├── .asf.yaml ├── .github └── workflows │ ├── codeql.yml │ └── maven.yml ├── .gitignore ├── KEYS ├── LICENSE ├── NOTICE ├── README ├── build.properties ├── build.xml ├── checkstyle-5.5.xml ├── lib ├── README.txt ├── build │ ├── mockito-core-1.8.5.LICENCE.txt │ ├── mockito-core-1.8.5.NOTICE.txt │ ├── objenesis-1.0.0.LICENSE.txt │ └── qdox.LICENSE.txt ├── commons-io.LICENSE.txt ├── commons-io.NOTICE.txt ├── commons-logging.LICENSE.txt ├── commons-logging.NOTICE.txt ├── fontbox.LICENSE.txt ├── fontbox.NOTICE.txt ├── fop.LICENSE.txt ├── fop.NOTICE.txt ├── jacocoant.jar ├── pdfbox.LICENSE.txt ├── pdfbox.NOTICE.txt ├── xmlgraphics-commons.LICENSE.txt └── xmlgraphics-commons.NOTICE.txt ├── pom.xml ├── src ├── java │ ├── META-INF │ │ └── services │ │ │ ├── org.apache.fop.render.ImageHandler │ │ │ ├── org.apache.fop.render.pdf.PDFImageHandler │ │ │ ├── org.apache.xmlgraphics.image.loader.spi.ImageConverter │ │ │ ├── org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory │ │ │ └── org.apache.xmlgraphics.image.loader.spi.ImagePreloader │ └── org │ │ └── apache │ │ └── fop │ │ └── render │ │ └── pdf │ │ └── pdfbox │ │ ├── AbstractPDFBoxHandler.java │ │ ├── Cache.java │ │ ├── CloneAnnotations.java │ │ ├── DocumentRootModifier.java │ │ ├── FOPPDFFont.java │ │ ├── FOPPDFMultiByteFont.java │ │ ├── FOPPDFSingleByteFont.java │ │ ├── FontContainer.java │ │ ├── HandleAnnotations.java │ │ ├── ImageConverterPDF2AFP.java │ │ ├── ImageConverterPDF2G2D.java │ │ ├── ImageLoaderFactoryImageRawData.java │ │ ├── ImageLoaderFactoryPDF.java │ │ ├── ImageLoaderPDF.java │ │ ├── ImagePDF.java │ │ ├── Interceptors.java │ │ ├── LastResortPreloaderPDF.java │ │ ├── MaximumProfileTable.java │ │ ├── MergeAnnotations.java │ │ ├── MergeCFFFonts.java │ │ ├── MergeFonts.java │ │ ├── MergeFontsPDFWriter.java │ │ ├── MergeTTFonts.java │ │ ├── MergeType1Fonts.java │ │ ├── OTFSubSetFile.java │ │ ├── OnLoadInterceptor.java │ │ ├── PDFBoolean.java │ │ ├── PDFBoxAdapter.java │ │ ├── PDFBoxAdapterUtil.java │ │ ├── PDFBoxEventProducer.java │ │ ├── PDFBoxEventProducer.xml │ │ ├── PDFBoxImageHandler.java │ │ ├── PDFCloner.java │ │ ├── PDFString.java │ │ ├── PDFUtil.java │ │ ├── PDFWriter.java │ │ ├── PSPDFGraphics2D.java │ │ ├── PageParentTreeFinder.java │ │ ├── PatternUtil.java │ │ ├── PreloaderImageRawData.java │ │ ├── PreloaderPDF.java │ │ ├── StructureTreeMerger.java │ │ ├── StructureTreeMergerUtil.java │ │ ├── TaggedPDFConductor.java │ │ └── UniqueName.java └── tools │ └── resources │ └── findbugs │ └── exclusions.xml └── test ├── java └── org │ └── apache │ └── fop │ └── render │ └── pdf │ ├── StructureTreeMergerTestCase.java │ ├── TaggedPDFConductorTestCase.java │ └── pdfbox │ ├── DocumentRootModifierTestCase.java │ ├── FOPPDFSingleMultiByteFontTestCase.java │ ├── ImageConverterPDF2AFPTestCase.java │ ├── ImageConverterPDF2G2DTestCase.java │ ├── PDFBoxAdapterTestCase.java │ ├── PDFClonerTestCase.java │ ├── PDFRotateTestCase.java │ ├── PDFWriterTestCase.java │ ├── PSPDFGraphics2DTestCase.java │ ├── PageParentTreeFinderTestCase.java │ ├── PreloaderPDFTestCase.java │ └── StructureTreeMergerUtilTestCase.java └── resources └── org └── apache └── fop └── render └── pdf └── pdfbox ├── 2fonts.pdf ├── 2fonts2.pdf ├── NoParentTree.pdf ├── accessibleradiobuttons.pdf ├── annot.pdf ├── annot2.pdf ├── annot3.pdf ├── brokenLink.pdf ├── cffcid1.pdf ├── cffcid2.pdf ├── cffsubrs.pdf ├── cffsubrs2.pdf ├── cffsubrs3.pdf ├── cffsubrs4.pdf ├── classMap.pdf ├── emptyRowTable.pdf ├── error.pdf ├── fontsnotembedded.pdf ├── fontsnotembeddedcid.pdf ├── formrotated.pdf ├── gradientmask.pdf ├── hello2.pdf ├── helloWorld.pdf ├── image.pdf ├── libreoffice.pdf ├── link.pdf ├── linkTagged.pdf ├── loop.pdf ├── missingOBJR.pdf ├── otf.pdf ├── pattern.pdf ├── rotate.pdf ├── shading.pdf ├── simpleh.pdf ├── smask.pdf ├── softmask.pdf ├── t1subset.pdf ├── t1subset2.pdf ├── t1subset3.pdf ├── t1subset4.pdf ├── taggedWorld.pdf ├── ttcid1.pdf ├── ttcid2.pdf ├── ttsubset.pdf ├── ttsubset10.pdf ├── ttsubset11.pdf ├── ttsubset12.pdf ├── ttsubset13.pdf ├── ttsubset2.pdf ├── ttsubset3.pdf ├── ttsubset5.pdf ├── ttsubset6.pdf ├── ttsubset7.pdf ├── ttsubset8.pdf ├── ttsubset9.pdf ├── type0cff.pdf ├── type0tt.pdf └── xform.pdf /.asf.yaml: -------------------------------------------------------------------------------- 1 | github: 2 | description: "Apache XML Graphics FOP PDF Images" 3 | homepage: https://xmlgraphics.apache.org/fop/ 4 | labels: 5 | - fop 6 | - apache 7 | enabled_merge_buttons: 8 | merge: false # disable non-squashing merge 9 | squash: true 10 | rebase: true 11 | protected_branches: 12 | main: 13 | required_linear_history: true 14 | required_signatures: false 15 | dependabot_alerts: true 16 | dependabot_updates: false 17 | 18 | notifications: 19 | commits: commits@xmlgraphics.apache.org 20 | # issues: fop-dev@xmlgraphics.apache.org 21 | # pullrequests: fop-dev@xmlgraphics.apache.org 22 | # jobs: fop-dev@xmlgraphics.apache.org 23 | jira_options: link label 24 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "main" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "main" ] 20 | schedule: 21 | - cron: '21 3 * * 5' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'java' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Use only 'java' to analyze code written in Java, Kotlin or both 38 | # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both 39 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 40 | 41 | steps: 42 | - name: Checkout repository 43 | uses: actions/checkout@v3 44 | 45 | # Initializes the CodeQL tools for scanning. 46 | - name: Initialize CodeQL 47 | uses: github/codeql-action/init@v2 48 | with: 49 | languages: ${{ matrix.language }} 50 | # If you wish to specify custom queries, you can do so here or in a config file. 51 | # By default, queries listed here will override any specified in a config file. 52 | # Prefix the list here with "+" to use these queries and those in the config file. 53 | 54 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 55 | # queries: security-extended,security-and-quality 56 | 57 | 58 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). 59 | # If this step fails, then you should remove it and run the build manually (see below) 60 | - name: Autobuild 61 | uses: github/codeql-action/autobuild@v2 62 | 63 | # ℹ️ Command-line programs to run using the OS shell. 64 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 65 | 66 | # If the Autobuild fails above, remove it and uncomment the following three lines. 67 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 68 | 69 | # - run: | 70 | # echo "Run, Build Application using script" 71 | # ./location_of_script_within_repo/buildscript.sh 72 | 73 | - name: Perform CodeQL Analysis 74 | uses: github/codeql-action/analyze@v2 75 | with: 76 | category: "/language:${{matrix.language}}" 77 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Java CI with Maven 10 | 11 | on: 12 | push: 13 | branches: [ "main" ] 14 | pull_request: 15 | branches: [ "main" ] 16 | 17 | jobs: 18 | build: 19 | name: Test with Java ${{ matrix.jdk }} ${{ matrix.os }} 20 | runs-on: ${{ matrix.os }} 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | jdk: ['8', '11', '17', '21'] 25 | os: [ubuntu-latest, windows-latest] 26 | 27 | steps: 28 | - uses: actions/checkout@v4 29 | - name: Set up JDK ${{ matrix.jdk }} 30 | uses: actions/setup-java@v4 31 | with: 32 | java-version: ${{ matrix.jdk }} 33 | distribution: 'temurin' 34 | cache: maven 35 | - name: Build with Maven 36 | run: mvn -B package checkstyle:check spotbugs:check --file pom.xml 37 | 38 | # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive 39 | - name: Update dependency graph 40 | uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # maven artifacts 3 | target/ 4 | 5 | # test artifacts 6 | build/ 7 | 8 | # miscellaneous 9 | *~ 10 | *.bak 11 | 12 | # intellij artifacts 13 | .idea/ 14 | *.iml 15 | 16 | # temporary ignores 17 | .sdkmanrc 18 | -------------------------------------------------------------------------------- /KEYS: -------------------------------------------------------------------------------- 1 | This file contains the PGP keys of various developers. 2 | Please don't use them for email unless you have to. Their main 3 | purpose is code signing. 4 | 5 | Users: 6 | pgp < KEYS 7 | (gpg --import < KEYS) 8 | Developers: 9 | pgp -kxa and append it to this file. 10 | (pgpk -ll && pgpk -xa ) >> this file. 11 | (gpg --list-sigs 12 | && gpg --armor --export ) >> this file. 13 | 14 | pub 1024D/7C611584 2005-07-19 Jeremias M�rki 15 | sub 2048g/C0F1AD34 2005-07-19 16 | 17 | -----BEGIN PGP PUBLIC KEY BLOCK----- 18 | Version: GnuPG v1.4.2 (MingW32) 19 | 20 | mQGiBELdQqsRBACPvRuWTsO4Sv95wSFzaMJcSJs81b9lpAT4BKsi3K/1y7pcxTJW 21 | IKP5Khc6cOom3nnRDofEh1KcLnvx+X+A+WF5YF7c1qd4EG3tWgjzqnkT9NUsw6t/ 22 | 3yAHL9iHr5nB7aZuiDdXgsLL5F2wNjuiSrTEDVM1wSm+QLuqqJ2lSJOcCwCg97BA 23 | yyX59XauxdQNfF00pfYIW3UD/R2TzMD5YxHbCO2Ib3j5O2cJU+G56q1krLwFKSzq 24 | XsiKOh2+8Bvwj2bBlQ6uYMwZc08WOgtiG3uRMDsdPE3JIoDogIguuADzO1LFFoi5 25 | mAEizqCN+8OSZ6luVeznUKCObF+yJvqJyG9RoDgv+v8KdqVz5NZ2BdtcY7LxHGKI 26 | 6k/LA/9WH1p8N10GETyagzNtU1tDMZGk8zB5C1qE9hgMDr5iRKrFuGnwBzMseKOj 27 | nQ4tPW47hWYeXLaou6JPTRhGP0wITnOoYmcP5ymgOPZJZwARfC3qXznrdOAmL8D2 28 | x+W7DP7ZtKPCYDa0norSEq3VPSUWjAjAPvskgiN6u6Y5/0J487QlSmVyZW1pYXMg 29 | TcOkcmtpIDxqZXJlbWlhc0BtYWVya2kub3JnPoheBBMRAgAeBQJC3VVHAhsjBgsJ 30 | CAcDAgMVAgMDFgIBAh4BAheAAAoJEPcwlXB8YRWECjoAnA90rdo+Ob3k1BOMz5cK 31 | PaQZtuuiAKCHOPtp1foBDjGPBA0FR9MtSCmMLYhGBBIRAgAGBQJC31YgAAoJEKIR 32 | WuFfa4tyKSsAnj6YCONElnEDA5vaa1lJES4UcVAeAJ9JG4bXlEPUqyBPhOtvetVS 33 | OWtNGIhGBBMRAgAGBQJC7u6uAAoJEME58VMjy3oqElwAnijYebpmsWIw86ilU2Zf 34 | epTWKSt1AJ0cMQZmjm/WrGI68rCRcEL7X2wTOYhGBBMRAgAGBQJDK/iDAAoJEDf2 35 | j/UBWvyKp3YAniyZxx/ee9g7asY2AR87yAVWPRjQAJ0U4l3dC/8ugLmyE7RbkFqL 36 | iALoRLQpSmVyZW1pYXMgTcOkcmtpIDxpbmZvQGplcmVtaWFzLW1hZXJraS5jaD6I 37 | XgQTEQIAHgUCQt1VXQIbIwYLCQgHAwIDFQIDAxYCAQIeAQIXgAAKCRD3MJVwfGEV 38 | hNNHAKDkYf0faxpqpmnwtFNeFETmTqd7HACeK0jaTfp7b/VhTlFmF+cSkrO4lK2I 39 | RgQSEQIABgUCQt9WIAAKCRCiEVrhX2uLcpUWAKClQPvTzFXFlDk/nDBa0wxesi4n 40 | qwCfWiXArQAoIm/hG9zpK+h2zHwlYg6IRgQTEQIABgUCQu7urgAKCRDBOfFTI8t6 41 | KpDiAKCCPK5ixmDxrKvvIKnx7hofZ0LiAQCfV6vfRmuVmfWo2LMMaa9xw5WBtUKI 42 | RgQTEQIABgUCQyv4gwAKCRA39o/1AVr8iqV2AJ9sBMWQ6YjZHIfBp+aoo84EI/Kg 43 | 6wCfRDkrpQhjpeSM4DPaRiKgL1LQrVm0JUplcmVtaWFzIE3DpHJraSA8amVyZW1p 44 | YXNAYXBhY2hlLm9yZz6IXgQTEQIAHgUCQt1VgwIbIwYLCQgHAwIDFQIDAxYCAQIe 45 | AQIXgAAKCRD3MJVwfGEVhAjAAKDme5j7fzFk365pOZm1lJyEHMJuPACgspAO3iPV 46 | 7G659xb8l8IQQIZn18CIRgQSEQIABgUCQt9WGAAKCRCiEVrhX2uLcirOAKCwgb9x 47 | 2zr8Q3j7KnD9XSgqrwv33ACgzcUOgabzbXlJWEOiW4d2LIK4zjyIRgQTEQIABgUC 48 | Qu7uqQAKCRDBOfFTI8t6KuNXAJ40TlT/Goa/tV/5zL+ZH6OdWjTImACghZxdWnD+ 49 | CLZORMpBFYUlUKffSlWIRgQTEQIABgUCQyv4bAAKCRA39o/1AVr8iv1/AKCX8NY8 50 | nffFDHsck7SMPWdb8toSvwCfd0Yf8OOYq3/O8JidWNpnNTAZabqIYQQTEQIAIQIb 51 | IwYLCQgHAwIDFQIDAxYCAQIeAQIXgAUCQt1VmwIZAQAKCRD3MJVwfGEVhOZyAJ9G 52 | J6pU0t9yrsVkuHcAkhF1YG6RDgCdFOb6NohfGeBbOraUGdQvKwJ3J0W5Ag0EQt1C 53 | vhAIAIhBOvTiliy95oxWLplZzCiXq6Dm3lYUOhDxmioKavI6KH2FzdnrHHvz91ES 54 | f7tGUNizHQyv4+zSAv8B8JmKiQ7Tk6DL5yJjZ6otwyOuR0ZIviXZwYirT8lOO4wP 55 | m3oV1V6Uf1oIwZQ2Y1fTFO4+8UPlTT0IUNMxuIIbvkRSMup6FIFGDoJQ/IYtBB4G 56 | 4mo6DMilyNzDiaqJ5k+iSY/GcCIzdWUd7ryr7344DffnJHg0CDynR/gpISWWj0sf 57 | YCnjZJANrVGV7O5WnKsVKqzTIRfJKSGBoB1ekvQ8AtGq1X8DfGgKubjlzGjCNbeW 58 | YiKNEa/M4DOAwhFzvftGueuzujMAAwUH/1+A8nfA3YgoG8wGPifhXBrB5aUx5I12 59 | 1akJvK4KQaIFE3dDRRYtwQHp0EyKB85z3lTlmdOupE5oKHd3ZYeeaQSUnt5i+dtz 60 | Xxz3RLBB6NYlcYJJyqSb31rTAMoq1iultLYbH+ugK/kUPTIOslvUJ/q4J22NJ/wS 61 | aIEqBlz/RczCAniNooQ/2ie733MpJ6NfROGIiOrNsRlQw+7P9TOmB3FxKLtzIunD 62 | F/Oo/4vznSoaVSUtVFMCKM2tLLbVV2LWBm9ztakfOXwmV0aoveAZ6a0J5+9RbC82 63 | HJW5Sez4fLZxK7tENCQoscjkjM/xfsDz5mz/8JF4T0tLehUjKrLBlsaIRgQYEQIA 64 | BgUCQt1CvgAKCRD3MJVwfGEVhD0+AJwLiZ/2jUDCKVngO+lqNscX8TQ0LQCeM4DI 65 | UKHCLjnj2UtX8OfockTGIic= 66 | =1nMU 67 | -----END PGP PUBLIC KEY BLOCK----- 68 | pub 4096R/7CDB6DEA 2015-05-20 69 | uid Simon Steiner (CODE SIGNING KEY) 70 | sub 4096R/73382B77 2015-05-20 71 | 72 | -----BEGIN PGP PUBLIC KEY BLOCK----- 73 | Version: GnuPG v1 74 | 75 | mQINBFVcZesBEAC5Poew53ijRTE5kV2o2Tj+plJmoQMRtfiurMUpPQ4s/vTz8Bte 76 | WoHdNfJrzordHBZdy1S7V8p2kTtKWyaNFMyVoavBqo/BurmJ/3qUKH5otXkXuaAi 77 | zFaJPeEnR6y7pxTYkwFKyrn7TE4I84JKZEMLEbJIw1YF3t76nj055/OnzRtwc2Df 78 | cPyGqDALyoFXk6R04qIotVmlX3NwwF6A0M79+W+kWvPg4sD4R6SqwJb1UhcqHrqb 79 | kQOllg74cBjyAikRbqrCfoydHM10gc8f5w9+8v/fbDkSBtoh8Y31WSK6ocoWIg85 80 | I3odqHFxThwFTAYQC2tdw1M5kYcOiYVqw91JvBivpKH02vryH2BJu9zQDNFeyXud 81 | wyengMLlzUUmf9jBk3M8IUE4JTerw1AzWj0b3jdvG7FrgHrlszb6eCzE3BdY7zGS 82 | Qh6e+ROsF2LEKkbjxeAg58nl/h5iLythheY0S6sspeOTuDtgLgm8TZiGHA+j/qKH 83 | DY+aRReI0X2bzqNZROhTIXHSKsoX9+9g5a+1NYQeZmiICNo4vj+r4+i037QvIoy6 84 | 3K4NSVQgKnR9bbgyQCUprifrkywKF5a8eP3wtUGtH2FNqFQg1rUKBgLjLbRJ8PF2 85 | Ag8O0jmJBPxdOIdVP4vz37m+jyKE6L4JWjnaFldtD3NDJI1QQYX4MmXEaQARAQAB 86 | tDZTaW1vbiBTdGVpbmVyIChDT0RFIFNJR05JTkcgS0VZKSA8c3N0ZWluZXJAYXBh 87 | Y2hlLm9yZz6JAjgEEwECACIFAlVcZesCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4B 88 | AheAAAoJEFuT8d98223qTtoP/j5AH1w90HOiYioGGgxrxOciQdGNht0yOVPXHDyj 89 | 8oKNBKYhNYQ9tAxNxEZFVS2KxB3R5dy/Q/9XvOP/NYTP8p0VyXmxNMkicUhJQOJ/ 90 | 6mnxkTY/jk7y2XkYtdCby28SfMdExbM501arnG+vmXRtr3TpRRAxXCfS3FBI2n1H 91 | Y7aX8pVX3NNRQqGxjnSv4q/2NKrR1ZFt7aDuAO9VfLXd5NkJkaGJ7E7T4AQMJE6K 92 | KYUFkYKGeOc5dm1mHZMTVanyYRS0qWSpcnsamdU76HQgtC7koJmaeeI0MtntMkpB 93 | jObTY80iam97P81hfhEi9UsAPy0WPBmossNqQFYQ5kQzxq030C1ERJl1nXJCkIpl 94 | CpVv/aIV+kM+WQeA41IHgfLZsxHTkYRxtCZXh8HbFhpyKGwNRZhyvPn0oSbjQcke 95 | oAbfnxCj1YH6TQGJQH1R1rGPv3ph3omq9pRuJ/th4uFmq06xpO6VLjUICV9F1N1J 96 | kmiVpivC5iRDKw30YeRFe/J0BpflPizQh2gnTFCg0Q0ICUdehGovWKPDkJsG2+hb 97 | AJaxfYQg5cJQI1P0UOc3w6rLh2ye3qkSRxF1O9oyRHuAZtKtsabEg3v7bx6RnX1F 98 | BYGCB8ckud+qYlBjiGKLP7fJotuZv3hFWlFBoXb9F0WDpx+gUoEUH8H+9ygodEUq 99 | gjCRuQINBFVcZesBEADFcTVSAZoaax9xpw1zxwjVgfQrNfobqnJM33r2EBSB4b80 100 | NbPOtoHJ2OUvHq4w84PB+H4+JNAIA2KbPOvzB+u1Bn5IgJr9asH5lhrnrUSR+YCw 101 | UlnCw+2YJumdv/l6RKcFKbSRZHWSwTD3ZLBMuPUqX9uZkOuG1ftTkcVtfFHN3WAu 102 | ckHjVxTSkaHhZ7ALz8LIUH+8AL3/3eThM1KEgx+bcod8YttctzjTy9cAaT93DwKO 103 | qzqHXpk6Fpv9bvdiNye8Ye7f8487N0/3alMPpJqt2tHAqjxJRDb590/09cbt2N6l 104 | 6B+WlpM5hgkV//7ViL357Hids64sqbYSnmpQjZWUdafDvVvMKYbITmx26BEoWtIq 105 | wwpj7+DdQlxd/7bAtyk8XiHe6Ej9FF1PUEvBQw5NXOUiCSBo0hzcMMNy1uRb/Wpd 106 | oZX3TFKXTWulv95uzKGAo3zrUuKcfOGfDgqZ/H2dy8Yw9DaWJRnXyYwweUi1Ptnc 107 | Nk9ktycypCcVbsOQhGdQJNyGVUVgVV1CWz5GJ3eqtjHY09r7HEm6bGviJRu/sosk 108 | XmmjRUFpqwtDCRACYShDpnFjpmWTZegPcwpN+492qLP6cjh1XSN4Cg1YZ/0BMY4N 109 | V/yeadQf/hbM5hzPOhN6mr+VHOLulyXuV49EWisIRferqaXG67zIXbVQ4qfqfwAR 110 | AQABiQIfBBgBAgAJBQJVXGXrAhsMAAoJEFuT8d98223qGKoP/RtyjtE5zEkrd7oa 111 | vRK5FmNtdh8r63v8lwjxayCfmpQw14AQaPY7//ulfJQExpxqcCLFIEBqZ8o22RYA 112 | XnsV6RF3JAIjSktAh57GMqUljeNxBtlix2zv5MVi/XiYcmQrID812KNfp3/guJfK 113 | 3Us5BOxLyDwHylwyb88dLM3rP4W8VvaRAEXfd0/6rhEugdCdcHD1c+E1XliqBw/T 114 | UP3JjnnABfKR4NMZ67ENxc5jPDg2Jh3wychGGhvLddqk32KEIDTbV2SZYxtw3ylP 115 | cRUtEoVGvkCDj8KpcLvvTbE7QCOycQMj1aHt5tc0w+Ibqbj3X+DdJEAxuZhMDyR6 116 | hDkIr7YGkRjFacYeaunoY4tX4+x4tkf33eNsBa3DV6r6R18DWh8o6bWzHpPuEMZT 117 | ewbUuSHF9xm0Ti3uehDHNHIFsnEpGDanb2UMO1kd2Xr6kjabce4DIHn+PhOqwC1o 118 | bO9KBKaWO4uR7K1eWjOkqn70F7ykGz01AveouwRyOjh59VdpVe/Zpgtp/IvD6bP2 119 | FbW6pZZeHWWoj+zaDmyRDn5wRfGkNuLUIMblgCXQXttAm/nYdRwPQyAI+T5CP8f+ 120 | nmZfX1E6PwDD9rT+fU+0R1eAIkEZE+0UfWoBwbnei19Xqpwx6VH5x8mtfvUH9J5H 121 | PYDEgpBqDxD3E1CYq/cVFhKQRxpK 122 | =n+z/ 123 | -----END PGP PUBLIC KEY BLOCK----- 124 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | PDF image support for Apache FOP 2 | Copyright 2012-2025 The Apache Software Foundation 3 | Copyright 2007-2012 Jeremias Maerki and contributors. 4 | 5 | This product includes software developed at 6 | The Apache Software Foundation (http://www.apache.org/). 7 | 8 | -------------------------------------------------------------------------------- /build.properties: -------------------------------------------------------------------------------- 1 | version=2.11.0.SNAPSHOT 2 | vendor=The Apache Software Foundation (http://xmlgraphics.apache.org) 3 | year=2007-2025 4 | 5 | javac.debug=on 6 | javac.deprecation=on 7 | javac.fork=off 8 | javac.source=1.8 9 | javac.target=1.8 10 | 11 | junit.fork=on -------------------------------------------------------------------------------- /lib/README.txt: -------------------------------------------------------------------------------- 1 | 2 | Information on dependencies 3 | ============================ 4 | 5 | $Id$ 6 | 7 | The Apache License can also be found here: 8 | http://www.apache.org/licenses/ 9 | 10 | 11 | Normal Dependencies 12 | ---------------------- 13 | 14 | - Apache Jakarta Commons IO 15 | 16 | commons-io-*.jar 17 | http://jakarta.apache.org/commons/io/ 18 | (I/O routines) 19 | 20 | Apache License v2.0 21 | 22 | - Apache Jakarta Commons Logging 23 | 24 | commons-logging-*.jar 25 | http://jakarta.apache.org/commons/logging/ 26 | (Logging adapter for various logging backends like JDK 1.4 logging or Log4J) 27 | 28 | Apache License v2.0 29 | 30 | - Apache FOP 31 | 32 | fop*.jar 33 | http://xmlgraphics.apache.org/fop/ 34 | (Apache FOP, maintained by the Apache XML Graphics project) 35 | 36 | Apache License v2.0 37 | 38 | - Apache XML Graphics COmmons 39 | 40 | xmlgraphics-commons*.jar 41 | http://xmlgraphics.apache.org/commons/ 42 | (Apache XML Graphics Commons, maintained by the Apache XML Graphics project) 43 | 44 | Apache License v2.0 45 | 46 | - Apache PDFBox (Java PDF Library) 47 | 48 | pdfbox*.jar 49 | jempbox*.jar (XMP library used by Apache PDFBox) 50 | fontbox*.jar (font library used by Apache PDFBox) 51 | http://pdfbox.apache.org 52 | 53 | Apache License v2.0 54 | 55 | 56 | 57 | 58 | Additional development-time dependencies 59 | ------------------------------------------- 60 | 61 | - Apache Ant 62 | 63 | (not bundled, requires pre-installation) 64 | http://ant.apache.org 65 | (XML-based build system) 66 | 67 | Apache License V2.0 68 | -------------------------------------------------------------------------------- /lib/build/mockito-core-1.8.5.LICENCE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2007 Mockito contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /lib/build/mockito-core-1.8.5.NOTICE.txt: -------------------------------------------------------------------------------- 1 | Mockito license - MIT. 2 | 3 | Libraries used: 4 | 5 | Cglib - Apache License 2.0 6 | ASM - BSD license 7 | 8 | Mockito all distribution: 9 | 10 | Objenesis - MIT license 11 | Hamcrest - BSD license -------------------------------------------------------------------------------- /lib/build/objenesis-1.0.0.LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2003-2008, Objenesis Team and all contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /lib/commons-io.NOTICE.txt: -------------------------------------------------------------------------------- 1 | Apache Jakarta Commons IO 2 | Copyright 2001-2007 The Apache Software Foundation 3 | 4 | This product includes software developed by 5 | The Apache Software Foundation (http://www.apache.org/). 6 | 7 | -------------------------------------------------------------------------------- /lib/commons-logging.NOTICE.txt: -------------------------------------------------------------------------------- 1 | This product includes software developed by 2 | The Apache Software Foundation (http://www.apache.org/). 3 | 4 | -------------------------------------------------------------------------------- /lib/fontbox.NOTICE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache FontBox 3 | Copyright 2008-2010 The Apache Software Foundation 4 | 5 | This product includes software developed at 6 | The Apache Software Foundation (http://www.apache.org/). 7 | 8 | 9 | Based on source code contributed to the original FontBox project. 10 | Copyright (c) 2006-2007, www.fontbox.org 11 | -------------------------------------------------------------------------------- /lib/fop.NOTICE.txt: -------------------------------------------------------------------------------- 1 | Apache FOP 2 | Copyright 1999-2008 The Apache Software Foundation 3 | 4 | This product includes software developed at 5 | The Apache Software Foundation (http://www.apache.org/). 6 | 7 | This software consists of voluntary contributions made by many individuals 8 | on behalf of The Apache Software Foundation and was originally created by 9 | James Tauber . 10 | 11 | -------------------------------------------------------------------------------- /lib/jacocoant.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/lib/jacocoant.jar -------------------------------------------------------------------------------- /lib/pdfbox.NOTICE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache PDFBox 3 | Copyright 2002-2010 The Apache Software Foundation 4 | 5 | This product includes software developed at 6 | The Apache Software Foundation (http://www.apache.org/). 7 | 8 | 9 | Based on source code contributed to the original PDFBox project. 10 | Copyright (c) 2002-2007, www.pdfbox.org 11 | -------------------------------------------------------------------------------- /lib/xmlgraphics-commons.NOTICE.txt: -------------------------------------------------------------------------------- 1 | Apache XML Graphics Commons 2 | Copyright 2006-2007 The Apache Software Foundation 3 | 4 | This product includes software developed at 5 | The Apache Software Foundation (http://www.apache.org/). 6 | -------------------------------------------------------------------------------- /src/java/META-INF/services/org.apache.fop.render.ImageHandler: -------------------------------------------------------------------------------- 1 | org.apache.fop.render.pdf.pdfbox.PDFBoxImageHandler -------------------------------------------------------------------------------- /src/java/META-INF/services/org.apache.fop.render.pdf.PDFImageHandler: -------------------------------------------------------------------------------- 1 | org.apache.fop.render.pdf.pdfbox.PDFBoxPDFImageHandler -------------------------------------------------------------------------------- /src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageConverter: -------------------------------------------------------------------------------- 1 | org.apache.fop.render.pdf.pdfbox.ImageConverterPDF2AFP 2 | org.apache.fop.render.pdf.pdfbox.ImageConverterPDF2G2D 3 | -------------------------------------------------------------------------------- /src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory: -------------------------------------------------------------------------------- 1 | org.apache.fop.render.pdf.pdfbox.ImageLoaderFactoryPDF 2 | org.apache.fop.render.pdf.pdfbox.ImageLoaderFactoryImageRawData -------------------------------------------------------------------------------- /src/java/META-INF/services/org.apache.xmlgraphics.image.loader.spi.ImagePreloader: -------------------------------------------------------------------------------- 1 | org.apache.fop.render.pdf.pdfbox.PreloaderPDF 2 | org.apache.fop.render.pdf.pdfbox.PreloaderImageRawData 3 | org.apache.fop.render.pdf.pdfbox.LastResortPreloaderPDF -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/AbstractPDFBoxHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | 20 | package org.apache.fop.render.pdf.pdfbox; 21 | 22 | import java.awt.Rectangle; 23 | import java.awt.geom.AffineTransform; 24 | import java.io.IOException; 25 | import java.util.HashMap; 26 | import java.util.Map; 27 | 28 | import org.apache.pdfbox.pdmodel.PDDocument; 29 | import org.apache.pdfbox.pdmodel.PDPage; 30 | 31 | import org.apache.xmlgraphics.image.loader.util.ImageUtil; 32 | import org.apache.xmlgraphics.image.loader.util.SoftMapCache; 33 | 34 | import org.apache.fop.apps.FOUserAgent; 35 | import org.apache.fop.events.EventBroadcaster; 36 | import org.apache.fop.fonts.FontInfo; 37 | import org.apache.fop.pdf.PDFArray; 38 | import org.apache.fop.pdf.PDFDocument; 39 | import org.apache.fop.pdf.PDFPage; 40 | import org.apache.fop.pdf.PDFResources; 41 | import org.apache.fop.pdf.PDFStructElem; 42 | import org.apache.fop.pdf.Version; 43 | import org.apache.fop.render.pdf.PDFLogicalStructureHandler; 44 | 45 | /** 46 | * Abstract base class for implementation of FOP's image handler interfaces (old and new) 47 | * which can use PDFBox to parse an existing PDF file and write that to the 48 | * target PDF as a Form XObject. 49 | */ 50 | public abstract class AbstractPDFBoxHandler { 51 | 52 | protected Object createStreamForPDF(ImagePDF image, PDFPage targetPage, FOUserAgent userAgent, 53 | AffineTransform pageAdjust, FontInfo fontinfo, Rectangle destRect, 54 | Map usedFieldNames, Map pageNumbers, 55 | PDFLogicalStructureHandler handler, PDFStructElem curentSessionElem, 56 | AffineTransform generatorAT) throws IOException { 57 | 58 | EventBroadcaster eventBroadcaster = null; 59 | if (userAgent != null) { 60 | eventBroadcaster = userAgent.getEventBroadcaster(); 61 | } 62 | String originalImageUri = image.getInfo().getOriginalURI(); 63 | final int selectedPage = ImageUtil.needPageIndexFromURI(originalImageUri); 64 | 65 | PDDocument srcDoc = image.getPDDocument(); 66 | float pdfVersion = srcDoc.getDocument().getVersion(); 67 | Version inputDocVersion = Version.getValueOf(String.valueOf(pdfVersion)); 68 | PDFDocument pdfDoc = targetPage.getDocument(); 69 | 70 | if (pdfDoc.getPDFVersion().compareTo(inputDocVersion) < 0) { 71 | try { 72 | pdfDoc.setPDFVersion(inputDocVersion); 73 | } catch (IllegalStateException e) { 74 | getEventProducer(eventBroadcaster).pdfVersionMismatch(this, 75 | pdfDoc.getPDFVersionString(), String.valueOf(pdfVersion)); 76 | } 77 | } 78 | 79 | //Encryption test 80 | if (srcDoc.isEncrypted()) { 81 | getEventProducer(eventBroadcaster).encryptedPdf(this); 82 | return null; 83 | } 84 | 85 | //Warn about potential problems with PDF/A and PDF/X 86 | if (pdfDoc.getProfile().isPDFAActive()) { 87 | getEventProducer(eventBroadcaster).pdfAActive(this); 88 | } 89 | if (pdfDoc.getProfile().isPDFXActive()) { 90 | getEventProducer(eventBroadcaster).pdfXActive(this); 91 | } 92 | 93 | Map objectCachePerFile = getObjectCache(getImagePath(originalImageUri), userAgent); 94 | 95 | PDPage srcPage = srcDoc.getPage(selectedPage); 96 | 97 | if (targetPage.getPDFResources().getParentResources() == null) { 98 | PDFResources res = pdfDoc.getFactory().makeResources(); 99 | res.setParentResources(pdfDoc.getResources()); 100 | res.addContext(targetPage); 101 | targetPage.put("Resources", res); 102 | } 103 | 104 | Map objectCache = getObjectCache(getClass().getName(), userAgent); 105 | PDFBoxAdapter adapter = 106 | new PDFBoxAdapter(targetPage, objectCachePerFile, usedFieldNames, pageNumbers, objectCache); 107 | if (handler != null) { 108 | adapter.setCurrentMCID(handler.getPageParentTree().length()); 109 | } 110 | Object stream = adapter.createStreamFromPDFBoxPage( 111 | srcDoc, srcPage, originalImageUri, pageAdjust, fontinfo, destRect, generatorAT); 112 | if (userAgent.isAccessibilityEnabled() && curentSessionElem != null) { 113 | TaggedPDFConductor conductor = new TaggedPDFConductor(curentSessionElem, handler, srcPage, adapter); 114 | conductor.handleLogicalStructure(srcDoc); 115 | } 116 | return stream; 117 | } 118 | 119 | private Map getObjectCache(String path, FOUserAgent userAgent) { 120 | SoftMapCache objectCache = userAgent.getPDFObjectCache(); 121 | if (objectCache.get(path) == null) { 122 | objectCache.put(path, new HashMap()); 123 | } 124 | return (Map) objectCache.get(path); 125 | } 126 | 127 | private String getImagePath(String originalImageUri) { 128 | int hashIndex = originalImageUri.indexOf('#'); 129 | if (hashIndex > 0) { 130 | return originalImageUri.substring(0, hashIndex); 131 | } else { 132 | return originalImageUri; 133 | } 134 | } 135 | 136 | private PDFBoxEventProducer getEventProducer(EventBroadcaster eventBroadcaster) { 137 | return PDFBoxEventProducer.Provider.get(eventBroadcaster); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/Cache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.fop.render.pdf.pdfbox; 18 | 19 | import java.lang.ref.SoftReference; 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | import java.util.WeakHashMap; 23 | 24 | abstract class Cache { 25 | 26 | public enum Type { 27 | WEAK, SOFT, STRONG; 28 | } 29 | 30 | public abstract V getValue(K key, ValueMaker valueMaker) throws Exception; 31 | 32 | public static Cache createCache(Type cacheType) { 33 | switch (cacheType) { 34 | case WEAK: 35 | return new WeakDocumentCache(); 36 | case SOFT: 37 | return new SoftDocumentCache(); 38 | case STRONG: 39 | return new StrongDocumentCache(); 40 | default: 41 | return createDefaultCache(); 42 | } 43 | } 44 | 45 | private static Cache createDefaultCache() { 46 | return new WeakDocumentCache(); 47 | } 48 | 49 | private static class StrongDocumentCache extends Cache { 50 | 51 | private final Map cache = new HashMap(); 52 | 53 | @Override 54 | public V getValue(K key, ValueMaker valueMaker) throws Exception { 55 | V value = cache.get(key); 56 | if (value == null) { 57 | value = valueMaker.make(); 58 | cache.put(key, value); 59 | } 60 | return value; 61 | } 62 | } 63 | 64 | private static class SoftDocumentCache extends Cache { 65 | 66 | private final Map> softKeys = new HashMap>(); 67 | 68 | private final Map cache = new WeakHashMap(); 69 | 70 | @Override 71 | public V getValue(K key, ValueMaker valueMaker) throws Exception { 72 | SoftReference reference = softKeys.get(key); 73 | Object softKey; 74 | if (reference == null || reference.get() == null) { 75 | softKey = new Object(); 76 | reference = new SoftReference(softKey); 77 | softKeys.put(key, reference); 78 | } else { 79 | softKey = reference.get(); 80 | } 81 | V value = cache.get(softKey); 82 | if (value == null) { 83 | value = valueMaker.make(); 84 | cache.put(softKey, value); 85 | } 86 | return value; 87 | } 88 | } 89 | 90 | private static class WeakDocumentCache extends Cache { 91 | 92 | private V currentValue; 93 | 94 | private K currentKey; 95 | 96 | @Override 97 | public V getValue(K key, ValueMaker valueMaker) throws Exception { 98 | if (!key.equals(currentKey)) { 99 | currentKey = key; 100 | currentValue = valueMaker.make(); 101 | } 102 | return currentValue; 103 | } 104 | } 105 | 106 | public interface ValueMaker { 107 | V make() throws Exception; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/CloneAnnotations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | package org.apache.fop.render.pdf.pdfbox; 20 | 21 | import java.io.IOException; 22 | import java.io.Serializable; 23 | import java.util.Collection; 24 | import java.util.Comparator; 25 | import java.util.Set; 26 | import java.util.TreeSet; 27 | 28 | import org.apache.pdfbox.cos.COSArray; 29 | import org.apache.pdfbox.cos.COSBase; 30 | import org.apache.pdfbox.cos.COSDictionary; 31 | import org.apache.pdfbox.cos.COSName; 32 | import org.apache.pdfbox.cos.COSObject; 33 | import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; 34 | 35 | import org.apache.fop.pdf.PDFDictionary; 36 | 37 | public class CloneAnnotations implements HandleAnnotations { 38 | private PDFBoxAdapter pdfBoxAdapter; 39 | private Set fields = new TreeSet<>(new CompareFields()); 40 | 41 | public CloneAnnotations(PDFBoxAdapter pdfBoxAdapter) { 42 | this.pdfBoxAdapter = pdfBoxAdapter; 43 | } 44 | 45 | public Set getFields() { 46 | return fields; 47 | } 48 | 49 | public void load(COSObject annot, PDAcroForm srcAcroForm) { 50 | getField(annot, srcAcroForm); 51 | } 52 | 53 | private COSDictionary getField(COSObject fieldObject, PDAcroForm srcAcroForm) { 54 | COSDictionary field = (COSDictionary) fieldObject.getObject(); 55 | COSObject parent; 56 | while ((parent = getParent(field)) != null) { 57 | fieldObject = parent; 58 | field = (COSDictionary) fieldObject.getObject(); 59 | } 60 | if (srcAcroForm != null) { 61 | COSArray srcFields = (COSArray) srcAcroForm.getCOSObject().getDictionaryObject(COSName.FIELDS); 62 | if (srcFields != null && srcFields.toList().contains(fieldObject)) { 63 | fields.add(fieldObject); 64 | } 65 | } else { 66 | fields.add(fieldObject); 67 | } 68 | return field; 69 | } 70 | 71 | private COSObject getParent(COSDictionary field) { 72 | COSBase parent = field.getItem(COSName.PARENT); 73 | if (parent instanceof COSObject) { 74 | return (COSObject) parent; 75 | } 76 | return null; 77 | } 78 | 79 | public void cloneAnnotParent(COSBase annot, PDFDictionary clonedAnnot, Collection exclude) 80 | throws IOException { 81 | if (annot instanceof COSObject) { 82 | COSDictionary dictionary = (COSDictionary) ((COSObject) annot).getObject(); 83 | COSBase parent = dictionary.getItem(COSName.PARENT); 84 | if (parent != null) { 85 | clonedAnnot.put(COSName.PARENT.getName(), pdfBoxAdapter.cloneForNewDocument(parent, parent, exclude)); 86 | } 87 | } 88 | } 89 | 90 | static class CompareFields implements Comparator, Serializable { 91 | private static final long serialVersionUID = -6081505461660440801L; 92 | 93 | public int compare(COSObject o1, COSObject o2) { 94 | return (int) (o1.getObjectNumber() - o2.getObjectNumber()); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/DocumentRootModifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.fop.render.pdf.pdfbox; 18 | 19 | import java.io.IOException; 20 | 21 | import org.apache.pdfbox.cos.COSDictionary; 22 | import org.apache.pdfbox.cos.COSName; 23 | 24 | import org.apache.fop.pdf.PDFDictionary; 25 | import org.apache.fop.pdf.PDFDocument; 26 | import org.apache.fop.pdf.PDFStructTreeRoot; 27 | 28 | public class DocumentRootModifier { 29 | 30 | private PDFBoxAdapter adapter; 31 | private PDFDocument pdfDoc; 32 | 33 | public DocumentRootModifier(PDFBoxAdapter adapter, PDFDocument pdfDoc) { 34 | this.adapter = adapter; 35 | this.pdfDoc = pdfDoc; 36 | } 37 | 38 | public void structTreeRootEntriesToCopy(COSDictionary structRootDict) throws IOException { 39 | checkForMap(structRootDict, COSName.ROLE_MAP.getName()); 40 | checkForMap(structRootDict, "ClassMap"); 41 | } 42 | 43 | private void checkForMap(COSDictionary structRootDict, String mapName) throws IOException { 44 | if (structRootDict.containsKey(mapName)) { 45 | COSDictionary addedMapDict = (COSDictionary)structRootDict.getDictionaryObject(mapName); 46 | PDFDictionary temp = (PDFDictionary) adapter.cloneForNewDocument(addedMapDict); 47 | PDFStructTreeRoot structTreeRoot = pdfDoc.getRoot().getStructTreeRoot(); 48 | if (!structTreeRoot.containsKey(mapName)) { 49 | structTreeRoot.put(mapName, temp); 50 | } else { 51 | PDFDictionary rootMap = (PDFDictionary)structTreeRoot.get(mapName); 52 | addMapToStructTreeRoot(rootMap, temp, mapName); 53 | } 54 | } 55 | } 56 | 57 | private void mergeMapClass(PDFDictionary main, PDFDictionary addition) { 58 | for (String key : addition.keySet()) { 59 | main.put(key, addition.get(key)); 60 | } 61 | } 62 | 63 | private void mergeRoleMaps(PDFDictionary structRoot, PDFDictionary addition) { 64 | for (String key : addition.keySet()) { 65 | if (!structRoot.containsKey(key)) { 66 | structRoot.put(key, addition.get(key)); 67 | } 68 | } 69 | } 70 | 71 | private void addMapToStructTreeRoot(PDFDictionary rootMap, PDFDictionary map, String mapName) { 72 | if (mapName.equals(COSName.ROLE_MAP.getName())) { 73 | mergeRoleMaps(rootMap, map); 74 | } else { 75 | mergeMapClass(rootMap, map); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFFont.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.fop.render.pdf.pdfbox; 18 | 19 | import java.io.IOException; 20 | import java.util.List; 21 | 22 | import org.apache.pdfbox.cos.COSDictionary; 23 | 24 | import org.apache.fop.pdf.PDFDictionary; 25 | import org.apache.fop.pdf.RefPDFFont; 26 | 27 | interface FOPPDFFont extends RefPDFFont { 28 | String getFontName(); 29 | void setRef(PDFDictionary d); 30 | String addFont(COSDictionary fontdata) throws IOException; 31 | int size(); 32 | String getMappedWord(List word, byte[] bytes, FontContainer oldFont); 33 | } 34 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/FontContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.fop.render.pdf.pdfbox; 18 | 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | 22 | import java.util.Collections; 23 | import java.util.List; 24 | 25 | import org.apache.commons.io.IOUtils; 26 | import org.apache.fontbox.cmap.CMap; 27 | import org.apache.fontbox.cmap.CMapParser; 28 | import org.apache.fontbox.util.BoundingBox; 29 | import org.apache.pdfbox.cos.COSArray; 30 | import org.apache.pdfbox.cos.COSBase; 31 | import org.apache.pdfbox.cos.COSDictionary; 32 | import org.apache.pdfbox.cos.COSName; 33 | import org.apache.pdfbox.cos.COSStream; 34 | import org.apache.pdfbox.io.RandomAccessReadBuffer; 35 | import org.apache.pdfbox.pdmodel.font.PDCIDFont; 36 | import org.apache.pdfbox.pdmodel.font.PDFont; 37 | import org.apache.pdfbox.pdmodel.font.PDFontFactory; 38 | import org.apache.pdfbox.pdmodel.font.PDSimpleFont; 39 | import org.apache.pdfbox.pdmodel.font.PDType0Font; 40 | import org.apache.pdfbox.pdmodel.font.encoding.BuiltInEncoding; 41 | import org.apache.pdfbox.pdmodel.font.encoding.DictionaryEncoding; 42 | import org.apache.pdfbox.pdmodel.font.encoding.Encoding; 43 | 44 | public class FontContainer { 45 | private COSDictionary dict; 46 | private List widths; 47 | PDFont font; 48 | 49 | FontContainer(COSDictionary fontData) throws IOException { 50 | dict = fontData; 51 | font = PDFontFactory.createFont(fontData); 52 | } 53 | 54 | int getFirstChar() { 55 | return dict.getInt(COSName.FIRST_CHAR); 56 | } 57 | 58 | int getLastChar() { 59 | return dict.getInt(COSName.LAST_CHAR); 60 | } 61 | 62 | CMap getToUnicodeCMap() throws IOException { 63 | COSBase base = dict.getDictionaryObject(COSName.TO_UNICODE); 64 | if (font instanceof PDType0Font && base == null) { 65 | PDCIDFont cidFont = ((PDType0Font) font).getDescendantFont(); 66 | base = cidFont.getCOSObject().getDictionaryObject(COSName.TO_UNICODE); 67 | } 68 | if (base instanceof COSName) { 69 | // predefined CMap 70 | String name = ((COSName)base).getName(); 71 | CMapParser parser = new CMapParser(); 72 | return parser.parsePredefined(name); 73 | } else if (base instanceof COSStream) { 74 | // embedded CMap 75 | InputStream input = null; 76 | try { 77 | input = ((COSStream)base).createInputStream(); 78 | CMapParser parser = new CMapParser(); 79 | return parser.parse(new RandomAccessReadBuffer(input)); 80 | } finally { 81 | IOUtils.closeQuietly(input); 82 | } 83 | } else { 84 | // throw new IOException("Expected Name or Stream"); 85 | } 86 | return null; 87 | } 88 | 89 | COSBase getToUnicode() { 90 | return dict.getDictionaryObject(COSName.TO_UNICODE); 91 | } 92 | 93 | List getWidths() { 94 | if (widths == null) { 95 | COSArray array = (COSArray) dict.getDictionaryObject(COSName.WIDTHS); 96 | if (array != null) { 97 | widths = array.toCOSNumberIntegerList(); 98 | } else { 99 | widths = Collections.emptyList(); 100 | } 101 | } 102 | return widths; 103 | } 104 | 105 | Encoding getEncoding() { 106 | if (font instanceof PDSimpleFont) { 107 | if (((PDSimpleFont) font).getEncoding() instanceof DictionaryEncoding) { 108 | return new DictionaryEncoding( 109 | (COSDictionary)((PDSimpleFont)font).getEncoding().getCOSObject(), true, null); 110 | } 111 | return ((PDSimpleFont) font).getEncoding(); 112 | } 113 | return null; 114 | } 115 | 116 | String getBaseEncodingName() { 117 | Encoding encoding = getEncoding(); 118 | if (encoding != null && !(encoding instanceof BuiltInEncoding)) { 119 | COSBase cosObject = encoding.getCOSObject(); 120 | if (cosObject != null) { 121 | if (cosObject instanceof COSDictionary) { 122 | COSBase item = ((COSDictionary) cosObject).getItem(COSName.BASE_ENCODING); 123 | if (item != null) { 124 | return ((COSName)item).getName(); 125 | } 126 | } else if (cosObject instanceof COSName) { 127 | return ((COSName) cosObject).getName(); 128 | } else { 129 | throw new RuntimeException(cosObject.toString() + " not supported"); 130 | } 131 | } 132 | } 133 | return null; 134 | } 135 | 136 | float[] getBoundingBox() throws IOException { 137 | BoundingBox bb = font.getBoundingBox(); 138 | return new float[] {bb.getLowerLeftX(), bb.getLowerLeftY(), bb.getUpperRightX(), bb.getUpperRightY()}; 139 | } 140 | 141 | public PDFont getFont() { 142 | return font; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/HandleAnnotations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | package org.apache.fop.render.pdf.pdfbox; 20 | 21 | import java.io.IOException; 22 | import java.util.Collection; 23 | import java.util.Set; 24 | 25 | import org.apache.pdfbox.cos.COSBase; 26 | import org.apache.pdfbox.cos.COSName; 27 | import org.apache.pdfbox.cos.COSObject; 28 | import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; 29 | 30 | import org.apache.fop.pdf.PDFDictionary; 31 | 32 | public interface HandleAnnotations { 33 | /* 34 | * @return Set of fields 35 | */ 36 | Set getFields(); 37 | 38 | /* 39 | * Load annotations and add to fields set 40 | */ 41 | void load(COSObject annot, PDAcroForm srcAcroForm); 42 | 43 | /* 44 | * Clone annotation and set parent 45 | */ 46 | void cloneAnnotParent(COSBase annot, PDFDictionary clonedAnnot, Collection exclude) throws IOException; 47 | } 48 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2AFP.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | package org.apache.fop.render.pdf.pdfbox; 20 | 21 | import java.io.ByteArrayInputStream; 22 | import java.io.ByteArrayOutputStream; 23 | import java.io.IOException; 24 | import java.util.Map; 25 | 26 | import org.apache.pdfbox.multipdf.Splitter; 27 | import org.apache.pdfbox.pdmodel.PDDocument; 28 | 29 | import org.apache.xmlgraphics.image.loader.Image; 30 | import org.apache.xmlgraphics.image.loader.ImageFlavor; 31 | import org.apache.xmlgraphics.image.loader.MimeEnabledImageFlavor; 32 | import org.apache.xmlgraphics.image.loader.impl.AbstractImageConverter; 33 | import org.apache.xmlgraphics.image.loader.impl.ImageRawStream; 34 | import org.apache.xmlgraphics.image.loader.util.ImageUtil; 35 | 36 | public class ImageConverterPDF2AFP extends AbstractImageConverter { 37 | public Image convert(Image src, Map hints) throws IOException { 38 | if (!(src instanceof ImagePDF)) { 39 | return null; 40 | } 41 | ImagePDF imgPDF = (ImagePDF)src; 42 | int selectedPage = ImageUtil.needPageIndexFromURI(src.getInfo().getOriginalURI()); 43 | PDDocument pdDocument = imgPDF.getPDDocument(); 44 | Splitter splitter = new Splitter(); 45 | splitter.setStartPage(selectedPage + 1); 46 | splitter.setEndPage(selectedPage + 1); 47 | pdDocument = splitter.split(pdDocument).get(0); 48 | ByteArrayOutputStream pdf = new ByteArrayOutputStream(); 49 | pdDocument.save(pdf); 50 | pdDocument.close(); 51 | MimeEnabledImageFlavor imageFlavor = new MimeEnabledImageFlavor(src.getFlavor(), ImagePDF.MIME_PDF); 52 | return new ImageRawStream(src.getInfo(), imageFlavor, new ByteArrayInputStream(pdf.toByteArray())); 53 | } 54 | 55 | public ImageFlavor getSourceFlavor() { 56 | return ImagePDF.PDFBOX_IMAGE; 57 | } 58 | 59 | public ImageFlavor getTargetFlavor() { 60 | return ImageFlavor.RAW_PDF; 61 | } 62 | 63 | public int getConversionPenalty() { 64 | return 100; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/ImageLoaderFactoryImageRawData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | package org.apache.fop.render.pdf.pdfbox; 20 | 21 | import java.io.IOException; 22 | import java.util.Map; 23 | 24 | import org.apache.xmlgraphics.image.loader.Image; 25 | import org.apache.xmlgraphics.image.loader.ImageException; 26 | import org.apache.xmlgraphics.image.loader.ImageFlavor; 27 | import org.apache.xmlgraphics.image.loader.ImageInfo; 28 | import org.apache.xmlgraphics.image.loader.ImageSessionContext; 29 | import org.apache.xmlgraphics.image.loader.impl.AbstractImageLoaderFactory; 30 | import org.apache.xmlgraphics.image.loader.spi.ImageLoader; 31 | 32 | public class ImageLoaderFactoryImageRawData extends AbstractImageLoaderFactory { 33 | public String[] getSupportedMIMETypes() { 34 | String[] mimes = {"image/DataBufferInt"}; 35 | return mimes; 36 | } 37 | 38 | public ImageFlavor[] getSupportedFlavors(String s) { 39 | ImageFlavor[] imageFlavors = {ImageFlavor.BUFFERED_IMAGE}; 40 | return imageFlavors; 41 | } 42 | 43 | public ImageLoader newImageLoader(ImageFlavor imageFlavor) { 44 | return new RawImageLoader(); 45 | } 46 | 47 | static class RawImageLoader implements ImageLoader { 48 | 49 | public Image loadImage(ImageInfo imageInfo, Map map, ImageSessionContext imageSessionContext) 50 | throws ImageException, IOException { 51 | return imageInfo.getOriginalImage(); 52 | } 53 | 54 | public Image loadImage(ImageInfo imageInfo, ImageSessionContext imageSessionContext) 55 | throws ImageException, IOException { 56 | return null; 57 | } 58 | 59 | public ImageFlavor getTargetFlavor() { 60 | return ImageFlavor.BUFFERED_IMAGE; 61 | } 62 | 63 | public int getUsagePenalty() { 64 | return 0; 65 | } 66 | } 67 | 68 | public boolean isAvailable() { 69 | return true; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/ImageLoaderFactoryPDF.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | 20 | package org.apache.fop.render.pdf.pdfbox; 21 | 22 | import org.apache.xmlgraphics.image.loader.ImageFlavor; 23 | import org.apache.xmlgraphics.image.loader.impl.AbstractImageLoaderFactory; 24 | import org.apache.xmlgraphics.image.loader.spi.ImageLoader; 25 | 26 | /** 27 | * Factory class for the ImageLoader for PDF. 28 | */ 29 | public class ImageLoaderFactoryPDF extends AbstractImageLoaderFactory { 30 | 31 | private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { 32 | ImagePDF.PDFBOX_IMAGE}; 33 | 34 | private static final String[] MIMES = new String[] { 35 | ImagePDF.MIME_PDF}; 36 | 37 | /** {@inheritDoc} */ 38 | public String[] getSupportedMIMETypes() { 39 | return MIMES.clone(); 40 | } 41 | 42 | /** {@inheritDoc} */ 43 | public ImageFlavor[] getSupportedFlavors(String mime) { 44 | return FLAVORS.clone(); 45 | } 46 | 47 | /** {@inheritDoc} */ 48 | public ImageLoader newImageLoader(ImageFlavor targetFlavor) { 49 | return new ImageLoaderPDF(targetFlavor); 50 | } 51 | 52 | /** {@inheritDoc} */ 53 | @Override 54 | public int getUsagePenalty(String mime, ImageFlavor flavor) { 55 | return 10; 56 | } 57 | 58 | /** {@inheritDoc} */ 59 | public boolean isAvailable() { 60 | try { 61 | Class.forName("org.apache.pdfbox.pdmodel.PDDocument"); 62 | return true; 63 | } catch (Throwable t) { 64 | return false; 65 | } 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/ImageLoaderPDF.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | 20 | package org.apache.fop.render.pdf.pdfbox; 21 | 22 | import java.io.IOException; 23 | import java.util.Map; 24 | 25 | import org.apache.xmlgraphics.image.loader.Image; 26 | import org.apache.xmlgraphics.image.loader.ImageException; 27 | import org.apache.xmlgraphics.image.loader.ImageFlavor; 28 | import org.apache.xmlgraphics.image.loader.ImageInfo; 29 | import org.apache.xmlgraphics.image.loader.ImageSessionContext; 30 | import org.apache.xmlgraphics.image.loader.impl.AbstractImageLoader; 31 | 32 | /** 33 | * ImageLoader for PDF. Depends on the PDF preloader based on PDFBox. 34 | */ 35 | public class ImageLoaderPDF extends AbstractImageLoader { 36 | 37 | private ImageFlavor targetFlavor; 38 | 39 | /** 40 | * Main constructor. 41 | * @param targetFlavor the target flavor 42 | */ 43 | public ImageLoaderPDF(ImageFlavor targetFlavor) { 44 | if (!(ImagePDF.PDFBOX_IMAGE.equals(targetFlavor))) { 45 | throw new IllegalArgumentException("Unsupported target ImageFlavor: " + targetFlavor); 46 | } 47 | this.targetFlavor = targetFlavor; 48 | } 49 | 50 | /** {@inheritDoc} */ 51 | public ImageFlavor getTargetFlavor() { 52 | return this.targetFlavor; 53 | } 54 | 55 | /** {@inheritDoc} */ 56 | public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) 57 | throws ImageException, IOException { 58 | if (!ImagePDF.MIME_PDF.equals(info.getMimeType())) { 59 | throw new IllegalArgumentException("ImageInfo must be from a PDF document"); 60 | } 61 | Image img = info.getOriginalImage(); 62 | if (!(img instanceof ImagePDF)) { 63 | throw new IllegalArgumentException( 64 | "ImageInfo was expected to contain the PDF document"); 65 | } 66 | ImagePDF pdfImage = (ImagePDF)img; 67 | return pdfImage; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/ImagePDF.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | 20 | package org.apache.fop.render.pdf.pdfbox; 21 | 22 | import java.io.IOException; 23 | 24 | import org.apache.pdfbox.pdmodel.PDDocument; 25 | 26 | import org.apache.xmlgraphics.image.loader.ImageFlavor; 27 | import org.apache.xmlgraphics.image.loader.ImageInfo; 28 | import org.apache.xmlgraphics.image.loader.impl.AbstractImage; 29 | 30 | /** 31 | * Represents a PDF document as an image. 32 | */ 33 | public class ImagePDF extends AbstractImage { 34 | 35 | /** MIME type for PDF */ 36 | public static final String MIME_PDF = "application/pdf"; 37 | 38 | /** ImageFlavor for PDF */ 39 | public static final ImageFlavor PDFBOX_IMAGE = new ImageFlavor("PDFBox"); 40 | 41 | private final PDDocument pddoc; 42 | 43 | /** 44 | * Create an PDF image with the image information. 45 | * 46 | * @param info the information containing the data and bounding box 47 | * @param doc the PDF document 48 | */ 49 | public ImagePDF(ImageInfo info, PDDocument doc) { 50 | super(info); 51 | this.pddoc = doc; 52 | } 53 | 54 | /** 55 | * Returns the root PDDocument instance representing the PDF image. 56 | * @return the root PDDocument 57 | */ 58 | public PDDocument getPDDocument() { 59 | return this.pddoc; 60 | } 61 | 62 | /** {@inheritDoc} */ 63 | public ImageFlavor getFlavor() { 64 | return PDFBOX_IMAGE; 65 | } 66 | 67 | /** {@inheritDoc} */ 68 | public boolean isCacheable() { 69 | return false; 70 | } 71 | 72 | public void close() { 73 | try { 74 | pddoc.close(); 75 | } catch (IOException e) { 76 | throw new RuntimeException(e); 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/Interceptors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | 20 | package org.apache.fop.render.pdf.pdfbox; 21 | 22 | import java.io.IOException; 23 | import java.net.URI; 24 | 25 | import org.apache.pdfbox.pdmodel.PDDocument; 26 | 27 | /** 28 | * Handles interceptors (hooks) that can operate on PDF documents. 29 | */ 30 | public class Interceptors { 31 | 32 | private static Interceptors instance; 33 | 34 | private OnLoadInterceptor onLoad = null; 35 | 36 | public static synchronized Interceptors getInstance() { 37 | if (instance == null) { 38 | instance = new Interceptors(); 39 | } 40 | return instance; 41 | } 42 | 43 | /** 44 | * Intercepts the given PDF document on load. 45 | * @param doc the PDF document 46 | * @param uri the URI it has been loaded from (may be null) 47 | * @return the given document or potentially an alternative PDF 48 | * @throws IOException if an I/O occurs 49 | * @see OnLoadInterceptor#intercept(PDDocument, URI) 50 | */ 51 | public PDDocument interceptOnLoad(PDDocument doc, URI uri) throws IOException { 52 | PDDocument result = null; 53 | if (onLoad != null) { 54 | result = onLoad.intercept(doc, uri); 55 | } 56 | if (result == null) { 57 | result = doc; 58 | } 59 | return result; 60 | } 61 | 62 | /** 63 | * Set the on-load interceptor. 64 | * @param interceptor the interceptor instance 65 | */ 66 | public void setOnLoad(OnLoadInterceptor interceptor) { 67 | this.onLoad = interceptor; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/LastResortPreloaderPDF.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | package org.apache.fop.render.pdf.pdfbox; 20 | 21 | import java.io.IOException; 22 | 23 | import javax.imageio.stream.ImageInputStream; 24 | 25 | /** 26 | * Last resort PDF preloader for PDFs with data before the header 27 | */ 28 | public class LastResortPreloaderPDF extends PreloaderPDF { 29 | protected byte[] getHeader(ImageInputStream in, int size) throws IOException { 30 | byte[] header = new byte[1024]; 31 | long startPos = in.getStreamPosition(); 32 | int len = in.read(header); 33 | in.seek(startPos); 34 | String s = new String(header, "US-ASCII"); 35 | if (len > 0 && s.contains(PDF_HEADER)) { 36 | return PDF_HEADER.getBytes("US-ASCII"); 37 | } 38 | return new byte[0]; 39 | } 40 | 41 | public int getPriority() { 42 | return DEFAULT_PRIORITY * 3; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/MaximumProfileTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.fop.render.pdf.pdfbox; 18 | 19 | /** 20 | * A table in a true type font. 21 | */ 22 | public class MaximumProfileTable { 23 | /** 24 | * A tag that identifies this table type. 25 | */ 26 | public static final String TAG = "maxp"; 27 | 28 | private float version; 29 | private int numGlyphs; 30 | private int maxPoints; 31 | private int maxContours; 32 | private int maxCompositePoints; 33 | private int maxCompositeContours; 34 | private int maxZones; 35 | private int maxTwilightPoints; 36 | private int maxStorage; 37 | private int maxFunctionDefs; 38 | private int maxInstructionDefs; 39 | private int maxStackElements; 40 | private int maxSizeOfInstructions; 41 | private int maxComponentElements; 42 | private int maxComponentDepth; 43 | 44 | /** 45 | * @return Returns the maxComponentDepth. 46 | */ 47 | public int getMaxComponentDepth() { 48 | return maxComponentDepth; 49 | } 50 | /** 51 | * @param maxComponentDepthValue The maxComponentDepth to set. 52 | */ 53 | public void setMaxComponentDepth(int maxComponentDepthValue) { 54 | this.maxComponentDepth = maxComponentDepthValue; 55 | } 56 | /** 57 | * @return Returns the maxComponentElements. 58 | */ 59 | public int getMaxComponentElements() { 60 | return maxComponentElements; 61 | } 62 | /** 63 | * @param maxComponentElementsValue The maxComponentElements to set. 64 | */ 65 | public void setMaxComponentElements(int maxComponentElementsValue) { 66 | this.maxComponentElements = maxComponentElementsValue; 67 | } 68 | /** 69 | * @return Returns the maxCompositeContours. 70 | */ 71 | public int getMaxCompositeContours() { 72 | return maxCompositeContours; 73 | } 74 | /** 75 | * @param maxCompositeContoursValue The maxCompositeContours to set. 76 | */ 77 | public void setMaxCompositeContours(int maxCompositeContoursValue) { 78 | this.maxCompositeContours = maxCompositeContoursValue; 79 | } 80 | /** 81 | * @return Returns the maxCompositePoints. 82 | */ 83 | public int getMaxCompositePoints() { 84 | return maxCompositePoints; 85 | } 86 | /** 87 | * @param maxCompositePointsValue The maxCompositePoints to set. 88 | */ 89 | public void setMaxCompositePoints(int maxCompositePointsValue) { 90 | this.maxCompositePoints = maxCompositePointsValue; 91 | } 92 | /** 93 | * @return Returns the maxContours. 94 | */ 95 | public int getMaxContours() { 96 | return maxContours; 97 | } 98 | /** 99 | * @param maxContoursValue The maxContours to set. 100 | */ 101 | public void setMaxContours(int maxContoursValue) { 102 | this.maxContours = maxContoursValue; 103 | } 104 | /** 105 | * @return Returns the maxFunctionDefs. 106 | */ 107 | public int getMaxFunctionDefs() { 108 | return maxFunctionDefs; 109 | } 110 | /** 111 | * @param maxFunctionDefsValue The maxFunctionDefs to set. 112 | */ 113 | public void setMaxFunctionDefs(int maxFunctionDefsValue) { 114 | this.maxFunctionDefs = maxFunctionDefsValue; 115 | } 116 | /** 117 | * @return Returns the maxInstructionDefs. 118 | */ 119 | public int getMaxInstructionDefs() { 120 | return maxInstructionDefs; 121 | } 122 | /** 123 | * @param maxInstructionDefsValue The maxInstructionDefs to set. 124 | */ 125 | public void setMaxInstructionDefs(int maxInstructionDefsValue) { 126 | this.maxInstructionDefs = maxInstructionDefsValue; 127 | } 128 | /** 129 | * @return Returns the maxPoints. 130 | */ 131 | public int getMaxPoints() { 132 | return maxPoints; 133 | } 134 | /** 135 | * @param maxPointsValue The maxPoints to set. 136 | */ 137 | public void setMaxPoints(int maxPointsValue) { 138 | this.maxPoints = maxPointsValue; 139 | } 140 | /** 141 | * @return Returns the maxSizeOfInstructions. 142 | */ 143 | public int getMaxSizeOfInstructions() { 144 | return maxSizeOfInstructions; 145 | } 146 | /** 147 | * @param maxSizeOfInstructionsValue The maxSizeOfInstructions to set. 148 | */ 149 | public void setMaxSizeOfInstructions(int maxSizeOfInstructionsValue) { 150 | this.maxSizeOfInstructions = maxSizeOfInstructionsValue; 151 | } 152 | /** 153 | * @return Returns the maxStackElements. 154 | */ 155 | public int getMaxStackElements() { 156 | return maxStackElements; 157 | } 158 | /** 159 | * @param maxStackElementsValue The maxStackElements to set. 160 | */ 161 | public void setMaxStackElements(int maxStackElementsValue) { 162 | this.maxStackElements = maxStackElementsValue; 163 | } 164 | /** 165 | * @return Returns the maxStorage. 166 | */ 167 | public int getMaxStorage() { 168 | return maxStorage; 169 | } 170 | /** 171 | * @param maxStorageValue The maxStorage to set. 172 | */ 173 | public void setMaxStorage(int maxStorageValue) { 174 | this.maxStorage = maxStorageValue; 175 | } 176 | /** 177 | * @return Returns the maxTwilightPoints. 178 | */ 179 | public int getMaxTwilightPoints() { 180 | return maxTwilightPoints; 181 | } 182 | /** 183 | * @param maxTwilightPointsValue The maxTwilightPoints to set. 184 | */ 185 | public void setMaxTwilightPoints(int maxTwilightPointsValue) { 186 | this.maxTwilightPoints = maxTwilightPointsValue; 187 | } 188 | /** 189 | * @return Returns the maxZones. 190 | */ 191 | public int getMaxZones() { 192 | return maxZones; 193 | } 194 | /** 195 | * @param maxZonesValue The maxZones to set. 196 | */ 197 | public void setMaxZones(int maxZonesValue) { 198 | this.maxZones = maxZonesValue; 199 | } 200 | /** 201 | * @return Returns the numGlyphs. 202 | */ 203 | public int getNumGlyphs() { 204 | return numGlyphs; 205 | } 206 | /** 207 | * @param numGlyphsValue The numGlyphs to set. 208 | */ 209 | public void setNumGlyphs(int numGlyphsValue) { 210 | this.numGlyphs = numGlyphsValue; 211 | } 212 | /** 213 | * @return Returns the version. 214 | */ 215 | public float getVersion() { 216 | return version; 217 | } 218 | /** 219 | * @param versionValue The version to set. 220 | */ 221 | public void setVersion(float versionValue) { 222 | this.version = versionValue; 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/MergeAnnotations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | package org.apache.fop.render.pdf.pdfbox; 20 | 21 | import java.io.IOException; 22 | import java.util.ArrayList; 23 | import java.util.Arrays; 24 | import java.util.Collection; 25 | import java.util.HashSet; 26 | import java.util.List; 27 | import java.util.Map; 28 | import java.util.Set; 29 | 30 | import org.apache.pdfbox.cos.COSBase; 31 | import org.apache.pdfbox.cos.COSName; 32 | import org.apache.pdfbox.cos.COSObject; 33 | import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; 34 | 35 | import org.apache.fop.pdf.PDFArray; 36 | import org.apache.fop.pdf.PDFDictionary; 37 | import org.apache.fop.pdf.PDFDocument; 38 | 39 | public class MergeAnnotations implements HandleAnnotations { 40 | private PDFBoxAdapter pdfBoxAdapter; 41 | private Map fields; 42 | 43 | public MergeAnnotations(PDFBoxAdapter pdfBoxAdapter, Map fields) { 44 | this.pdfBoxAdapter = pdfBoxAdapter; 45 | this.fields = fields; 46 | } 47 | 48 | public Set getFields() { 49 | return new HashSet<>(fields.values()); 50 | } 51 | 52 | public void load(COSObject annot, PDAcroForm srcAcroForm) { 53 | //not used 54 | } 55 | 56 | public void cloneAnnotParent(COSBase annot, PDFDictionary clonedAnnot, Collection exclude) 57 | throws IOException { 58 | if (clonedAnnot.containsKey("T")) { 59 | List nameList = new ArrayList<>(); 60 | addToTree(clonedAnnot, nameList); 61 | PDFDictionary node = (PDFDictionary) fields.get(nameList.remove(0)); 62 | while (!nameList.isEmpty()) { 63 | String name = nameList.remove(0); 64 | PDFDictionary nextNode = findKid(name, node); 65 | if (nextNode == null) { 66 | if (nameList.isEmpty()) { 67 | nextNode = node; 68 | } else { 69 | nextNode = new PDFDictionary(); 70 | pdfBoxAdapter.pdfDoc.registerTrailerObject(nextNode); 71 | nextNode.put("Kids", new PDFArray()); 72 | nextNode.put("T", name); 73 | nextNode.put(COSName.PARENT.getName(), node); 74 | PDFArray kids = (PDFArray) node.get("Kids"); 75 | kids.add(nextNode); 76 | } 77 | } 78 | node = nextNode; 79 | } 80 | if (node != clonedAnnot) { 81 | insert(node, clonedAnnot); 82 | } 83 | } 84 | } 85 | 86 | private void insert(PDFDictionary parent, PDFDictionary clonedAnnot) throws IOException { 87 | if (parent.containsKey("Kids")) { 88 | PDFArray kids = (PDFArray) parent.get("Kids"); 89 | kids.add(clonedAnnot); 90 | } else { 91 | PDFDictionary grandParent = (PDFDictionary) parent.get(COSName.PARENT.getName()); 92 | PDFDictionary child = parent; 93 | parent = new PDFDictionary(); 94 | if (grandParent != null) { 95 | PDFArray kids = (PDFArray) grandParent.get("Kids"); 96 | kids.add(parent); 97 | } 98 | pdfBoxAdapter.pdfDoc.registerTrailerObject(parent); 99 | List excludeCopy = Arrays.asList("Subtype", "Type", "Rect", "MK", "F"); 100 | for (String key : child.keySet()) { 101 | if (!excludeCopy.contains(key)) { 102 | parent.put(key, child.get(key)); 103 | } 104 | } 105 | child.remove("T"); 106 | child.put(COSName.PARENT.getName(), parent); 107 | parent.put("Kids", new PDFArray(clonedAnnot, child)); 108 | 109 | } 110 | if (getT(clonedAnnot).equals(getT(parent))) { 111 | clonedAnnot.remove("T"); 112 | } 113 | clonedAnnot.put(COSName.PARENT.getName(), parent); 114 | } 115 | 116 | private PDFDictionary findKid(String name, PDFDictionary node) throws IOException { 117 | PDFArray kids = (PDFArray) node.get("Kids"); 118 | for (int i = 0; i < kids.length(); i++) { 119 | PDFDictionary kid = (PDFDictionary) kids.get(i); 120 | if (name.equals(getT(kid))) { 121 | return kid; 122 | } 123 | } 124 | return null; 125 | } 126 | 127 | private void addToTree(PDFDictionary clonedAnnot, List nameList) throws IOException { 128 | String tStr = getT(clonedAnnot); 129 | nameList.add(0, tStr); 130 | Object parent = clonedAnnot.get(COSName.PARENT.getName()); 131 | if (parent instanceof PDFDictionary) { 132 | addToTree((PDFDictionary) parent, nameList); 133 | } else if (!fields.containsKey(tStr)) { 134 | fields.put(tStr, clonedAnnot); 135 | } 136 | } 137 | 138 | private String getT(PDFDictionary clonedAnnot) throws IOException { 139 | Object tStr = clonedAnnot.get("T"); 140 | if (tStr instanceof byte[]) { 141 | tStr = new String((byte[]) tStr, PDFDocument.ENCODING); 142 | } 143 | return (String) tStr; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/MergeFonts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.fop.render.pdf.pdfbox; 18 | 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | import java.util.Map; 22 | 23 | public interface MergeFonts { 24 | void readFont(InputStream is, String name, FontContainer fontContainer, 25 | Map subsetGlyphs, boolean cid) throws IOException; 26 | byte[] getMergedFontSubset() throws IOException; 27 | } 28 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/OnLoadInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | 20 | package org.apache.fop.render.pdf.pdfbox; 21 | 22 | import java.io.IOException; 23 | import java.net.URI; 24 | 25 | import org.apache.pdfbox.pdmodel.PDDocument; 26 | 27 | /** 28 | * Interceptor interface for performing on newly loaded PDF files. This can be used, for example, 29 | * to decrypt an encrypted PDF. 30 | */ 31 | public interface OnLoadInterceptor { 32 | 33 | /** 34 | * Called when a new PDF document has been loaded. 35 | * @param doc the PDF document 36 | * @param uri the URI it has been loaded from (may be null) 37 | * @return the given document or potentially an alternative PDF 38 | * @throws IOException if an I/O occurs 39 | */ 40 | PDDocument intercept(PDDocument doc, URI uri) throws IOException; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/PDFBoolean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | 20 | package org.apache.fop.render.pdf.pdfbox; 21 | 22 | import java.io.IOException; 23 | import java.io.OutputStream; 24 | 25 | import org.apache.commons.io.output.CountingOutputStream; 26 | 27 | import org.apache.fop.pdf.PDFDocument; 28 | import org.apache.fop.pdf.PDFObject; 29 | 30 | /** 31 | * Represents a boolean object. 32 | */ 33 | public class PDFBoolean extends PDFObject { 34 | 35 | private boolean value; 36 | 37 | /** 38 | * Main constructor. 39 | * @param value the boolean value 40 | */ 41 | public PDFBoolean(boolean value) { 42 | this.value = value; 43 | } 44 | 45 | /** 46 | * Returns the boolean value 47 | * @return the boolean value 48 | */ 49 | public boolean getValue() { 50 | return this.value; 51 | } 52 | 53 | @Override 54 | public int output(OutputStream stream) throws IOException { 55 | CountingOutputStream cout = new CountingOutputStream(stream); 56 | PDFDocument.flushTextBuffer(new StringBuilder(Boolean.toString(getValue())), cout); 57 | return cout.getCount(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxEventProducer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.fop.render.pdf.pdfbox; 18 | 19 | import org.apache.fop.events.EventBroadcaster; 20 | import org.apache.fop.events.EventProducer; 21 | 22 | interface PDFBoxEventProducer extends EventProducer { 23 | 24 | /** Provider class for the event producer. */ 25 | final class Provider { 26 | 27 | private Provider() { } 28 | 29 | /** 30 | * Returns an event producer. 31 | * 32 | * @param broadcaster the event broadcaster to use 33 | * @return the event producer 34 | */ 35 | public static PDFBoxEventProducer get(EventBroadcaster broadcaster) { 36 | return broadcaster.getEventProducerFor(PDFBoxEventProducer.class); 37 | } 38 | } 39 | 40 | /** 41 | * The PDF version of the document being created is less than that of the PDF being inserted. 42 | * 43 | * @param source the event source 44 | * @param outDocVersion PDF version of the document being created 45 | * @param inputDocVersion PDF version of the included document 46 | * @event.severity WARN 47 | */ 48 | void pdfVersionMismatch(Object source, String outDocVersion, String inputDocVersion); 49 | 50 | 51 | /** 52 | * The document to be included is encrypted. 53 | * 54 | * @param source the event source 55 | * @event.severity ERROR 56 | */ 57 | void encryptedPdf(Object source); 58 | 59 | /** 60 | * PDF/A mode is active. 61 | * 62 | * @param source the event source 63 | * @event.severity WARN 64 | */ 65 | void pdfAActive(Object source); 66 | 67 | /** 68 | * PDF/X mode is active. 69 | * 70 | * @param source the event source 71 | * @event.severity WARN 72 | */ 73 | void pdfXActive(Object source); 74 | } 75 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxEventProducer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | The version of the loaded PDF is {inputDocVersion}. This doesn't match the document version {outDocVersion} and could lead to errors. 4 | PDF to be embedded must not be encrypted! 5 | PDF/A mode is active. Embedding a PDF file may result in a non-compliant file! 6 | PDF/X mode is active. Embedding a PDF file may result in a non-compliant file! 7 | 8 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxImageHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | 20 | package org.apache.fop.render.pdf.pdfbox; 21 | 22 | import java.awt.Rectangle; 23 | import java.awt.geom.AffineTransform; 24 | import java.io.IOException; 25 | 26 | import org.apache.commons.logging.Log; 27 | import org.apache.commons.logging.LogFactory; 28 | 29 | import org.apache.xmlgraphics.image.loader.Image; 30 | import org.apache.xmlgraphics.image.loader.ImageFlavor; 31 | 32 | import org.apache.fop.fonts.FontInfo; 33 | import org.apache.fop.pdf.PDFPage; 34 | import org.apache.fop.pdf.PDFXObject; 35 | import org.apache.fop.render.ImageHandler; 36 | import org.apache.fop.render.RenderingContext; 37 | import org.apache.fop.render.pdf.PDFContentGenerator; 38 | import org.apache.fop.render.pdf.PDFRenderingContext; 39 | 40 | /** 41 | * Implementation of the {@link ImageHandler} interfaces 42 | * which can use PDFBox to parse an existing PDF file and write that to the 43 | * target PDF as a Form XObject. 44 | */ 45 | public class PDFBoxImageHandler extends AbstractPDFBoxHandler implements ImageHandler { 46 | 47 | /** logging instance */ 48 | protected static final Log log = LogFactory.getLog(PDFBoxImageHandler.class); 49 | 50 | private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { 51 | ImagePDF.PDFBOX_IMAGE 52 | }; 53 | 54 | public void handleImage(RenderingContext context, Image image, Rectangle destRect) throws IOException { 55 | assert context instanceof PDFRenderingContext; 56 | PDFRenderingContext pdfContext = (PDFRenderingContext)context; 57 | PDFContentGenerator generator = pdfContext.getGenerator(); 58 | PDFPage targetPage = pdfContext.getPage(); 59 | 60 | assert image instanceof ImagePDF; 61 | ImagePDF pdfImage = (ImagePDF)image; 62 | try { 63 | // destRect in points. Because destRect size is in millipoints. 64 | float x = (float)destRect.getX() / 1000f; // Offset from left of page (IPD origin). 65 | float y = (float)destRect.getY() / 1000f; // Offset from top of page (BPD origin). 66 | float w = (float)destRect.getWidth() / 1000f; // Width of image. 67 | float h = (float)destRect.getHeight() / 1000f; // Height of image. 68 | 69 | AffineTransform pageAdjust = new AffineTransform(); 70 | AffineTransform generatorAT = generator.getAffineTransform(); 71 | if (generatorAT != null) { 72 | pageAdjust.setToTranslation( 73 | (float)(generator.getState().getTransform().getTranslateX()), 74 | (float)(generator.getState().getTransform().getTranslateY() - h - y)); 75 | } 76 | FontInfo fontinfo = (FontInfo)context.getHint("fontinfo"); 77 | Object stream = createStreamForPDF(pdfImage, targetPage, pdfContext.getUserAgent(), 78 | pageAdjust, fontinfo, destRect, pdfContext.getUsedFieldNames(), pdfContext.getPageNumbers(), 79 | pdfContext.getPdfLogicalStructureHandler(), pdfContext.getCurrentSessionStructElem(), generatorAT); 80 | 81 | if (stream == null) { 82 | return; 83 | } 84 | if (stream instanceof String) { 85 | if (pageAdjust.getScaleX() != 0) { 86 | pageAdjust.translate(x * (1 / pageAdjust.getScaleX()), -y * (1 / -pageAdjust.getScaleY())); 87 | } 88 | generator.placeImage(pageAdjust, (String) stream); 89 | } else { 90 | generator.placeImage(x, y, w, h, (PDFXObject) stream); 91 | } 92 | pdfImage.close(); 93 | } catch (Throwable t) { 94 | throw new RuntimeException( 95 | "Error on PDF page: " + pdfImage.getInfo().getOriginalURI() + " " + t.getMessage(), t); 96 | } 97 | } 98 | 99 | /** {@inheritDoc} */ 100 | public boolean isCompatible(RenderingContext targetContext, Image image) { 101 | return (image == null || image instanceof ImagePDF) 102 | && targetContext instanceof PDFRenderingContext; 103 | } 104 | 105 | /** {@inheritDoc} */ 106 | public int getPriority() { 107 | //Before built-in handlers in case someone implements a PDF -> Graphics2D converter 108 | return 50; 109 | } 110 | 111 | /** {@inheritDoc} */ 112 | public Class getSupportedImageClass() { 113 | return ImagePDF.class; 114 | } 115 | 116 | /** {@inheritDoc} */ 117 | public ImageFlavor[] getSupportedImageFlavors() { 118 | return FLAVORS.clone(); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/PDFString.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | 20 | package org.apache.fop.render.pdf.pdfbox; 21 | 22 | import java.io.IOException; 23 | import java.io.OutputStream; 24 | import java.io.UnsupportedEncodingException; 25 | 26 | import org.apache.commons.io.output.CountingOutputStream; 27 | 28 | import org.apache.fop.pdf.PDFDocument; 29 | import org.apache.fop.pdf.PDFObject; 30 | import org.apache.fop.pdf.PDFText; 31 | 32 | /** 33 | * Special PDF object for strings that goes beyond FOP's {@link PDFText} class. 34 | */ 35 | public class PDFString extends PDFObject { 36 | 37 | private String text; 38 | private byte[] binary; 39 | 40 | /** 41 | * Creates a new String. 42 | * @param text the text 43 | */ 44 | public PDFString(String text) { 45 | this.text = text; 46 | } 47 | 48 | /** 49 | * Creates a new String. 50 | * @param data the text data as byte array 51 | */ 52 | public PDFString(byte[] data) { 53 | this.binary = data.clone(); 54 | } 55 | 56 | /** 57 | * Returns the string as a Unicode string. 58 | * @return the string 59 | */ 60 | public String getString() { 61 | if (this.text == null) { 62 | String encoding = PDFDocument.ENCODING; 63 | int start = 0; 64 | if (this.binary.length > 2) { 65 | if (this.binary[0] == (byte)0xFF && this.binary[1] == (byte)0xFE) { 66 | encoding = "UTF-16LE"; 67 | start = 2; 68 | } else if (this.binary[0] == (byte)0xFE && this.binary[1] == (byte)0xFF) { 69 | encoding = "UTF-16BE"; 70 | start = 2; 71 | } 72 | } 73 | try { 74 | this.text = new String(this.binary, start, this.binary.length - start, encoding); 75 | } catch (UnsupportedEncodingException e) { 76 | throw new RuntimeException("Incompatible JVM: " + e.getMessage()); 77 | } 78 | } 79 | return this.text; 80 | } 81 | 82 | /** 83 | * Returns the string as binary data. 84 | * @return the binary representation 85 | */ 86 | public byte[] getBinary() { 87 | if (this.binary == null) { 88 | boolean unicode16 = false; 89 | char[] chars = this.text.toCharArray(); 90 | int length = chars.length; 91 | for (int i = 0; i < length; i++) { 92 | if (chars[i] > 255) { 93 | unicode16 = true; 94 | break; 95 | } 96 | } 97 | try { 98 | byte[] binary; 99 | if (unicode16) { 100 | byte[] data = this.text.getBytes("UTF-16BE"); 101 | binary = new byte[data.length + 2]; 102 | binary[0] = (byte)0xFE; 103 | binary[1] = (byte)0xFF; 104 | System.arraycopy(data, 0, binary, 2, data.length); 105 | } else { 106 | byte[] data = this.text.getBytes(PDFDocument.ENCODING); 107 | binary = new byte[data.length]; 108 | System.arraycopy(data, 0, binary, 0, data.length); 109 | } 110 | } catch (UnsupportedEncodingException e) { 111 | throw new RuntimeException("Incompatible JVM: " + e.getMessage()); 112 | } 113 | } 114 | if (binary == null) { 115 | return new byte[0]; 116 | } 117 | return this.binary.clone(); 118 | } 119 | 120 | @Override 121 | public int output(OutputStream stream) throws IOException { 122 | CountingOutputStream cout = new CountingOutputStream(stream); 123 | PDFDocument.flushTextBuffer(new StringBuilder(PDFText.escapeText(getString())), cout); 124 | return cout.getCount(); 125 | } 126 | 127 | /** 128 | * Indicates whether the given binary data contains only US-ASCII characters. 129 | * @param data the binary data 130 | * @return true if only US-ASCII data is found 131 | */ 132 | public static boolean isUSASCII(byte[] data) { 133 | for (int i = 0, c = data.length; i < c; i++) { 134 | if ((data[i] & 0xFF) >= 128) { 135 | return false; 136 | } 137 | } 138 | return true; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/PDFUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | 20 | package org.apache.fop.render.pdf.pdfbox; 21 | 22 | import org.apache.pdfbox.pdmodel.PDPage; 23 | 24 | /** 25 | * Common utility functions for PDF access. 26 | */ 27 | public final class PDFUtil { 28 | 29 | private PDFUtil() { } 30 | 31 | /** 32 | * Determines the rotation of a given page and normalizes the returned value to the values 33 | * 0, 90, 180 and 270. If not a multiple of 90 is encountered, 0 is returned. 34 | * @param page the page 35 | * @return the page rotation (0, 90, 180 or 270) 36 | */ 37 | public static int getNormalizedRotation(PDPage page) { 38 | //Handle the /Rotation entry on the page dict 39 | int rotation = page.getRotation(); 40 | rotation %= 360; 41 | if (rotation < 0) { 42 | rotation += 360; 43 | } 44 | switch (rotation) { 45 | case 90: 46 | case 180: 47 | case 270: 48 | return rotation; 49 | default: 50 | return 0; 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/PDFWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.fop.render.pdf.pdfbox; 18 | 19 | import java.io.IOException; 20 | import java.text.DecimalFormat; 21 | import java.text.DecimalFormatSymbols; 22 | import java.util.ArrayList; 23 | import java.util.Collection; 24 | import java.util.HashMap; 25 | import java.util.List; 26 | import java.util.Locale; 27 | import java.util.Map; 28 | 29 | import org.apache.pdfbox.contentstream.operator.Operator; 30 | import org.apache.pdfbox.cos.COSArray; 31 | import org.apache.pdfbox.cos.COSBase; 32 | import org.apache.pdfbox.cos.COSBoolean; 33 | import org.apache.pdfbox.cos.COSDictionary; 34 | import org.apache.pdfbox.cos.COSFloat; 35 | import org.apache.pdfbox.cos.COSInteger; 36 | import org.apache.pdfbox.cos.COSName; 37 | import org.apache.pdfbox.cos.COSNull; 38 | import org.apache.pdfbox.cos.COSString; 39 | import org.apache.pdfbox.pdfparser.PDFStreamParser; 40 | import org.apache.pdfbox.pdmodel.common.PDStream; 41 | 42 | import org.apache.fop.pdf.PDFDocument; 43 | 44 | public class PDFWriter { 45 | private DecimalFormat df = new DecimalFormat("#.####", new DecimalFormatSymbols(Locale.US)); 46 | private Map floatCache = new HashMap(); 47 | protected StringBuilder s = new StringBuilder(); 48 | protected UniqueName key; 49 | private int currentMCID; 50 | protected boolean keyUsed; 51 | 52 | public PDFWriter(UniqueName key, int currentMCID) { 53 | this.key = key; 54 | this.currentMCID = currentMCID; 55 | } 56 | 57 | public String writeText(PDStream pdStream) throws IOException { 58 | PDFStreamParser pdfStreamParser = new PDFStreamParser(pdStream.toByteArray()); 59 | List it = pdfStreamParser.parse(); 60 | List arguments = new ArrayList(); 61 | for (Object o : it) { 62 | if (o instanceof Operator) { 63 | Operator op = (Operator)o; 64 | readPDFArguments(op, arguments); 65 | s.append(op.getName() + "\n"); 66 | arguments.clear(); 67 | if (op.getImageParameters() != null) { 68 | for (Map.Entry cn : op.getImageParameters().entrySet()) { 69 | arguments.add(cn.getKey()); 70 | arguments.add(cn.getValue()); 71 | } 72 | readPDFArguments(op, arguments); 73 | s.append("ID " + new String(op.getImageData(), PDFDocument.ENCODING)); 74 | arguments.clear(); 75 | s.append("EI\n"); 76 | } 77 | } else { 78 | arguments.add((COSBase)o); 79 | } 80 | } 81 | return s.toString(); 82 | } 83 | 84 | protected void readPDFArguments(Operator op, Collection arguments) throws IOException { 85 | for (COSBase c : arguments) { 86 | processArg(op, c); 87 | } 88 | } 89 | 90 | protected void processArg(Operator op, COSBase c) throws IOException { 91 | if (c instanceof COSInteger) { 92 | s.append(((COSInteger) c).intValue()); 93 | s.append(" "); 94 | } else if (c instanceof COSFloat) { 95 | float f = ((COSFloat) c).floatValue(); 96 | if (!floatCache.containsKey(f)) { 97 | addCache(f); 98 | } 99 | s.append(floatCache.get(f)); 100 | s.append(" "); 101 | if (floatCache.size() > 1024) { 102 | floatCache.clear(); 103 | } 104 | } else if (c instanceof COSName) { 105 | COSName cn = (COSName)c; 106 | key.writeName(s, cn); 107 | s.append(" "); 108 | String name = key.getName(cn); 109 | if (!name.equals(cn.getName())) { 110 | keyUsed = true; 111 | } 112 | } else if (c instanceof COSString) { 113 | s.append("<" + ((COSString) c).toHexString() + ">"); 114 | } else if (c instanceof COSArray) { 115 | s.append("["); 116 | readPDFArguments(op, (Collection) ((COSArray) c).toList()); 117 | s.append("] "); 118 | } else if (c instanceof COSDictionary) { 119 | Collection dictArgs = new ArrayList(); 120 | if (currentMCID != 0 && op.getName().equals("BDC")) { 121 | for (Map.Entry cn : ((COSDictionary)c).entrySet()) { 122 | if (cn.getKey().getName().equals("MCID")) { 123 | updateMCID(cn, dictArgs); 124 | } else { 125 | dictArgs.add(cn.getKey()); 126 | dictArgs.add(cn.getValue()); 127 | } 128 | } 129 | } else { 130 | for (Map.Entry cn : ((COSDictionary)c).entrySet()) { 131 | dictArgs.add(cn.getKey()); 132 | dictArgs.add(cn.getValue()); 133 | } 134 | } 135 | s.append("<<"); 136 | readPDFArguments(op, dictArgs); 137 | s.append(">>"); 138 | } else if (c instanceof COSBoolean) { 139 | s.append(((COSBoolean) c).getValue()).append(" "); 140 | } else if (c instanceof COSNull) { 141 | s.append("null "); 142 | } else { 143 | throw new IOException(c + " not supported"); 144 | } 145 | } 146 | 147 | protected void addCache(float f) { 148 | String formatted = df.format(f); 149 | floatCache.put(f, formatted); 150 | } 151 | 152 | private void updateMCID(Map.Entry cn, Collection dictArgs) { 153 | COSBase cosMCID = cn.getValue(); 154 | assert cosMCID instanceof COSInteger; 155 | COSInteger mcid = (COSInteger) cosMCID; 156 | COSInteger updatedID = COSInteger.get(mcid.intValue() + currentMCID); 157 | dictArgs.add(cn.getKey()); 158 | dictArgs.add(updatedID); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/PageParentTreeFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.fop.render.pdf.pdfbox; 19 | 20 | import java.io.IOException; 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | import org.apache.pdfbox.cos.COSArray; 25 | import org.apache.pdfbox.cos.COSBase; 26 | import org.apache.pdfbox.cos.COSDictionary; 27 | import org.apache.pdfbox.cos.COSInteger; 28 | import org.apache.pdfbox.cos.COSName; 29 | import org.apache.pdfbox.cos.COSObject; 30 | 31 | import org.apache.pdfbox.pdmodel.PDDocument; 32 | import org.apache.pdfbox.pdmodel.PDPage; 33 | import org.apache.pdfbox.pdmodel.common.PDNumberTreeNode; 34 | import org.apache.pdfbox.pdmodel.graphics.PDXObject; 35 | 36 | public class PageParentTreeFinder { 37 | 38 | private PDPage srcPage; 39 | public PageParentTreeFinder(PDPage srcPage) { 40 | this.srcPage = srcPage; 41 | } 42 | 43 | public COSArray getPageParentTreeArray(PDDocument srcDoc) throws IOException { 44 | int position = srcPage.getCOSObject().getInt(COSName.STRUCT_PARENTS); 45 | if (position == -1) { 46 | position = findXObjectStructParent(); 47 | } 48 | if (position != -1) { 49 | PDNumberTreeNode srcNumberTreeNode = srcDoc.getDocumentCatalog().getStructureTreeRoot().getParentTree(); 50 | return traverseParentTree(srcNumberTreeNode.getCOSObject(), position); 51 | } 52 | return new COSArray(); 53 | } 54 | //TODO handle structural hierarchy in xboject stream 55 | private int findXObjectStructParent() throws IOException { 56 | int position = -1; 57 | Iterable mapXObject = srcPage.getResources().getXObjectNames(); 58 | for (COSName n : mapXObject) { 59 | PDXObject t = srcPage.getResources().getXObject(n); 60 | COSDictionary xObjectDict = t.getCOSObject(); 61 | position = xObjectDict.getInt(COSName.STRUCT_PARENTS); 62 | if (position != -1) { 63 | return position; 64 | } 65 | } 66 | return position; 67 | } 68 | 69 | private COSArray traverseParentTree(COSDictionary numberTreeNodeDict, int position) { 70 | COSArray numberTree; 71 | COSArray parentTree; 72 | List nums = new ArrayList(); 73 | if (numberTreeNodeDict.containsKey(COSName.NUMS)) { 74 | numberTree = (COSArray)numberTreeNodeDict.getItem(COSName.NUMS); 75 | return extractMarkedContentParents(numberTree, position); 76 | } else { 77 | parentTree = (COSArray) numberTreeNodeDict.getDictionaryObject(COSName.KIDS); 78 | traverseKids(parentTree, position, nums); 79 | } 80 | if (nums.isEmpty()) { 81 | return new COSArray(); 82 | } 83 | return nums.get(0); 84 | } 85 | 86 | private void traverseKids(COSBase kids, int position, List numList) { 87 | if (!numList.isEmpty()) { 88 | return; 89 | } 90 | if (kids instanceof COSArray) { 91 | COSArray kidsArray = (COSArray)kids; 92 | for (COSBase kid : kidsArray) { 93 | COSObject kidCOSObj = (COSObject) kid; 94 | traverseKids(kidCOSObj, position, numList); 95 | } 96 | } else if (kids instanceof COSObject) { 97 | COSObject kidCOSObj = (COSObject) kids; 98 | COSDictionary kid = (COSDictionary) kidCOSObj.getObject(); 99 | if (kid.getDictionaryObject(COSName.NUMS) == null) { 100 | traverseKids(kid.getDictionaryObject(COSName.KIDS), position, numList); 101 | } else { 102 | if (kid.getDictionaryObject(COSName.LIMITS) != null) { 103 | COSArray kidCOSArray = (COSArray) kid.getDictionaryObject(COSName.LIMITS); 104 | int lowerLimit = ((COSInteger) kidCOSArray.get(0)).intValue(); 105 | int upperLimit = ((COSInteger) kidCOSArray.get(1)).intValue(); 106 | if (lowerLimit <= position && position <= upperLimit) { 107 | COSArray nums = (COSArray) kid.getDictionaryObject(COSName.NUMS); 108 | numList.add(extractMarkedContentParents(nums, position)); 109 | } 110 | } else { 111 | COSArray nums = (COSArray) kid.getDictionaryObject(COSName.NUMS); 112 | numList.add(extractMarkedContentParents(nums, position)); 113 | } 114 | } 115 | } 116 | } 117 | 118 | private COSArray extractMarkedContentParents(COSArray numberTree, int position) { 119 | COSBase tempObject; 120 | boolean keyFlag = false; 121 | for (COSBase kid : numberTree) { 122 | if (keyFlag) { 123 | if (kid instanceof COSObject) { 124 | tempObject = ((COSObject)kid).getObject(); 125 | if (tempObject instanceof COSArray) { 126 | return (COSArray) tempObject; 127 | } 128 | } else if (kid instanceof COSArray) { 129 | return (COSArray)kid; 130 | } 131 | } 132 | if (kid instanceof COSInteger) { 133 | int temp = ((COSInteger)kid).intValue(); 134 | if (temp == position) { 135 | keyFlag = true; 136 | } 137 | } 138 | } 139 | return new COSArray(); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/PatternUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | package org.apache.fop.render.pdf.pdfbox; 20 | 21 | import java.awt.Rectangle; 22 | import java.awt.geom.AffineTransform; 23 | import java.io.IOException; 24 | import java.util.ArrayList; 25 | import java.util.Collections; 26 | import java.util.List; 27 | 28 | import org.apache.pdfbox.cos.COSName; 29 | import org.apache.pdfbox.pdmodel.PDPage; 30 | import org.apache.pdfbox.pdmodel.PDResources; 31 | import org.apache.pdfbox.pdmodel.common.PDRectangle; 32 | import org.apache.pdfbox.pdmodel.graphics.pattern.PDAbstractPattern; 33 | import org.apache.pdfbox.util.Matrix; 34 | 35 | import org.apache.fop.pdf.PDFArray; 36 | import org.apache.fop.pdf.PDFDictionary; 37 | import org.apache.fop.pdf.PDFObject; 38 | import org.apache.fop.pdf.PDFPage; 39 | 40 | public class PatternUtil { 41 | private List patternNames = new ArrayList<>(); 42 | private PDFPage targetPage; 43 | private Rectangle pos; 44 | private PDPage sourcePage; 45 | private AffineTransform generatorAT; 46 | 47 | public PatternUtil(PDFPage targetPage, Rectangle pos, PDPage sourcePage, boolean disabled, 48 | AffineTransform generatorAT) throws IOException { 49 | if (!disabled) { 50 | this.targetPage = targetPage; 51 | this.pos = pos; 52 | this.sourcePage = sourcePage; 53 | this.generatorAT = generatorAT; 54 | PDResources srcPgResources = sourcePage.getResources(); 55 | if (srcPgResources != null) { 56 | for (COSName name : srcPgResources.getPatternNames()) { 57 | patternNames.add(name); 58 | } 59 | transformPatterns(); 60 | } 61 | } 62 | } 63 | 64 | private void transformPatterns() throws IOException { 65 | // The pattern found in the source document. 66 | AffineTransform shadingAdjust = getShadingAffineTransform(); 67 | PDResources srcPgResources = sourcePage.getResources(); 68 | for (COSName srcPgPatternName : patternNames) { 69 | // Get the original pattern. 70 | PDAbstractPattern srcPattern = srcPgResources.getPattern(srcPgPatternName); 71 | Matrix originalMatrix = srcPattern.getMatrix(); 72 | if (originalMatrix == null) { 73 | originalMatrix = new Matrix(); 74 | } 75 | Matrix shadingMatrix = new Matrix(shadingAdjust); 76 | // Create the required new matrix and apply it to the pattern. 77 | Matrix newMatrix = originalMatrix.multiply(shadingMatrix); 78 | srcPattern.setMatrix(newMatrix.createAffineTransform()); 79 | // Add the pattern to the page resources for now. 80 | srcPgResources.put(srcPgPatternName, srcPattern); 81 | } 82 | } 83 | 84 | public List getPatternNames() { 85 | return patternNames; 86 | } 87 | 88 | private AffineTransform getShadingAffineTransform() { 89 | PDRectangle srcMediaBox = sourcePage.getMediaBox(); 90 | PDFArray targetPageMediaBox = (PDFArray)targetPage.get("MediaBox"); 91 | double targetMediaBoxHeight = (double) targetPageMediaBox.get(3); 92 | // Convert destRect to use bottom/left frame as origin. 93 | Rectangle cDestRect = new Rectangle(pos); 94 | cDestRect.y = (int) ((targetMediaBoxHeight * 1000 - (pos.getY() + pos.getHeight()))); 95 | double xScaleFactor = cDestRect.getWidth() / 1000f / srcMediaBox.getWidth(); 96 | double yScaleFactor = cDestRect.getHeight() / 1000f / srcMediaBox.getHeight(); 97 | // x translation: media box offset + scaled cDestRect x-offset 98 | double xTranslation = cDestRect.getX() / 1000f - srcMediaBox.getLowerLeftX() * xScaleFactor; 99 | // y translation: media box offset + scaled cDestRect 100 | double yTranslation = cDestRect.getY() / 1000f - srcMediaBox.getLowerLeftY() * yScaleFactor; 101 | if (generatorAT != null) { 102 | xTranslation -= generatorAT.getTranslateX(); 103 | yTranslation -= generatorAT.getTranslateY(); 104 | } 105 | return new AffineTransform(xScaleFactor, 0, 0, yScaleFactor, xTranslation, yTranslation); 106 | } 107 | 108 | public void promotePatterns() { 109 | if (targetPage != null) { 110 | PDFDictionary patternsDict = (PDFDictionary) targetPage.getPDFResources().get(COSName.PATTERN.getName()); 111 | if (patternsDict != null) { 112 | for (String key : patternsDict.keySet()) { 113 | PDFObject pattern = (PDFObject) patternsDict.get(key); 114 | pattern.setObjectNumber(targetPage.getDocument()); 115 | targetPage.getDocument().addObject(pattern); 116 | } 117 | } 118 | } 119 | } 120 | 121 | public String getKey(String key) { 122 | if (patternNames.isEmpty()) { 123 | return key; 124 | } 125 | return key + pos.getX() + pos.getY() + pos.getWidth() + pos.getHeight(); 126 | } 127 | 128 | public List getExclude() { 129 | if (targetPage == null) { 130 | return Collections.emptyList(); 131 | } 132 | return Collections.singletonList(COSName.PATTERN); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/PreloaderImageRawData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | package org.apache.fop.render.pdf.pdfbox; 20 | 21 | import java.awt.image.BufferedImage; 22 | import java.awt.image.DataBufferInt; 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.nio.ByteBuffer; 26 | import java.nio.ByteOrder; 27 | import java.nio.IntBuffer; 28 | 29 | import javax.xml.transform.Source; 30 | 31 | import org.apache.pdfbox.io.IOUtils; 32 | 33 | import org.apache.xmlgraphics.image.loader.ImageContext; 34 | import org.apache.xmlgraphics.image.loader.ImageException; 35 | import org.apache.xmlgraphics.image.loader.ImageInfo; 36 | import org.apache.xmlgraphics.image.loader.ImageSize; 37 | import org.apache.xmlgraphics.image.loader.ImageSource; 38 | import org.apache.xmlgraphics.image.loader.impl.AbstractImagePreloader; 39 | import org.apache.xmlgraphics.image.loader.impl.ImageRendered; 40 | 41 | public class PreloaderImageRawData extends AbstractImagePreloader { 42 | public ImageInfo preloadImage(String s, Source source, ImageContext imageContext) 43 | throws ImageException, IOException { 44 | if (source instanceof ImageSource && s.contains(DataBufferInt.class.getName())) { 45 | InputStream is = ((ImageSource)source).getInputStream(); 46 | byte[] input = IOUtils.toByteArray(is); 47 | is.reset(); 48 | IntBuffer intBuf = ByteBuffer.wrap(input).order(ByteOrder.BIG_ENDIAN).asIntBuffer(); 49 | int[] array = new int[intBuf.remaining()]; 50 | intBuf.get(array); 51 | int width = array[0]; 52 | int height = array[1]; 53 | ImageInfo info = new ImageInfo(s, "image/DataBufferInt"); 54 | ImageSize size = new ImageSize(width, height, imageContext.getSourceResolution()); 55 | size.calcSizeFromPixels(); 56 | info.setSize(size); 57 | BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 58 | DataBufferInt db = (DataBufferInt) img.getRaster().getDataBuffer(); 59 | System.arraycopy(array, 2, db.getData(), 0, db.getData().length); 60 | info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, new ImageRendered(info, img, null)); 61 | return info; 62 | } 63 | return null; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/PreloaderPDF.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | 20 | package org.apache.fop.render.pdf.pdfbox; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | import java.net.URI; 25 | import java.net.URISyntaxException; 26 | 27 | import javax.imageio.stream.ImageInputStream; 28 | import javax.xml.transform.Source; 29 | 30 | import org.apache.pdfbox.Loader; 31 | import org.apache.pdfbox.io.RandomAccessReadBuffer; 32 | import org.apache.pdfbox.pdmodel.PDDocument; 33 | import org.apache.pdfbox.pdmodel.PDPage; 34 | import org.apache.pdfbox.pdmodel.common.PDRectangle; 35 | 36 | import org.apache.xmlgraphics.image.loader.ImageContext; 37 | import org.apache.xmlgraphics.image.loader.ImageException; 38 | import org.apache.xmlgraphics.image.loader.ImageInfo; 39 | import org.apache.xmlgraphics.image.loader.ImageSize; 40 | import org.apache.xmlgraphics.image.loader.impl.AbstractImagePreloader; 41 | import org.apache.xmlgraphics.image.loader.util.ImageUtil; 42 | import org.apache.xmlgraphics.io.XmlSourceUtil; 43 | 44 | import org.apache.fop.datatypes.URISpecification; 45 | import org.apache.fop.render.pdf.pdfbox.Cache.ValueMaker; 46 | 47 | /** 48 | * Image preloader for PDF images. 49 | */ 50 | public class PreloaderPDF extends AbstractImagePreloader { 51 | 52 | /** PDF header text */ 53 | protected static final String PDF_HEADER = "%PDF-"; 54 | 55 | /** {@inheritDoc} */ 56 | public ImageInfo preloadImage(String uri, Source src, ImageContext context) 57 | throws IOException, ImageException { 58 | if (!ImageUtil.hasImageInputStream(src)) { 59 | return null; 60 | } 61 | ImageInfo info = null; 62 | ImageInputStream in = ImageUtil.needImageInputStream(src); 63 | in.mark(); 64 | try { 65 | byte[] header = getHeader(in, PDF_HEADER.length()); 66 | String s = new String(header, "US-ASCII"); 67 | 68 | boolean supported = PDF_HEADER.equals(s); 69 | if (supported) { 70 | info = loadPDF(uri, src, context); 71 | } 72 | return info; 73 | } finally { 74 | if (info == null) { 75 | in.reset(); //Error detected or not a PDF file 76 | } 77 | } 78 | } 79 | 80 | private static URI deriveDocumentURI(String uri) throws ImageException { 81 | try { 82 | URI originalURI = new URI(URISpecification.escapeURI(uri)); 83 | URI tempURI = new URI(originalURI.getScheme(), 84 | originalURI.getSchemeSpecificPart(), null); 85 | return tempURI; 86 | } catch (URISyntaxException e) { 87 | throw new ImageException("Problem processing URI", e); 88 | } 89 | } 90 | 91 | private ImageInfo loadPDF(String uri, Source src, ImageContext context) throws IOException, 92 | ImageException { 93 | int selectedPage = ImageUtil.needPageIndexFromURI(uri); 94 | 95 | URI docURI = deriveDocumentURI(src.getSystemId()); 96 | 97 | PDDocument pddoc = getDocument(context, docURI, src); 98 | pddoc = Interceptors.getInstance().interceptOnLoad(pddoc, docURI); 99 | 100 | //Disable the warning about a missing close since we rely on the GC to decide when 101 | //the cached PDF shall be disposed off. 102 | // pddoc.getDocument().setWarnMissingClose(false); 103 | 104 | int pageCount = pddoc.getNumberOfPages(); 105 | if (selectedPage < 0 || selectedPage >= pageCount) { 106 | throw new ImageException("Selected page (index: " + selectedPage 107 | + ") does not exist in the PDF file. The document has " 108 | + pddoc.getNumberOfPages() + " pages."); 109 | } 110 | PDPage page = pddoc.getPage(selectedPage); 111 | PDRectangle mediaBox = page.getMediaBox(); 112 | PDRectangle cropBox = page.getCropBox(); 113 | PDRectangle viewBox = cropBox != null ? cropBox : mediaBox; 114 | int w = Math.round(viewBox.getWidth() * 1000); 115 | int h = Math.round(viewBox.getHeight() * 1000); 116 | 117 | //Handle the /Rotation entry on the page dict 118 | int rotation = PDFUtil.getNormalizedRotation(page); 119 | if (rotation == 90 || rotation == 270) { 120 | //Swap width and height 121 | int exch = w; 122 | w = h; 123 | h = exch; 124 | } 125 | 126 | ImageSize size = new ImageSize(); 127 | size.setSizeInMillipoints(w, h); 128 | size.setResolution(context.getSourceResolution()); 129 | size.calcPixelsFromSize(); 130 | 131 | ImageInfo info = new ImageInfo(uri, ImagePDF.MIME_PDF); 132 | info.setSize(size); 133 | info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, new ImagePDF(info, pddoc)); 134 | 135 | int lastPageIndex = pddoc.getNumberOfPages() - 1; 136 | if (selectedPage < lastPageIndex) { 137 | info.getCustomObjects().put(ImageInfo.HAS_MORE_IMAGES, Boolean.TRUE); 138 | } 139 | 140 | return info; 141 | } 142 | 143 | // private void notifyCouldNotDecrypt(Exception e) 144 | // throws ImageException { 145 | // throw new ImageException("Error decrypting PDF: " 146 | // + e.getMessage() 147 | // + "\nPlease use an OnLoadInterceptor to provide " 148 | // + "suitable decryption material (ex. a password).", e); 149 | // } 150 | 151 | private PDDocument getDocument(Object context, URI uri, Source src) 152 | throws IOException { 153 | try { 154 | return createDocumentMaker(src, uri).make(); 155 | } catch (IOException ioe) { 156 | throw ioe; 157 | } catch (Exception e) { 158 | // We cannot recover from this 159 | throw new RuntimeException(e); 160 | } 161 | } 162 | 163 | private ValueMaker createDocumentMaker(final Source src, final URI docURI) { 164 | return new DocumentMaker(src, docURI); 165 | } 166 | 167 | static class DocumentMaker implements ValueMaker { 168 | private Source src; 169 | private URI docURI; 170 | 171 | public DocumentMaker(Source src, URI docURI) { 172 | this.src = src; 173 | this.docURI = docURI; 174 | } 175 | 176 | public PDDocument make() throws Exception { 177 | final InputStream in = XmlSourceUtil.needInputStream(src); 178 | try { 179 | PDDocument pddoc = Loader.loadPDF(new RandomAccessReadBuffer(in)); 180 | return Interceptors.getInstance().interceptOnLoad(pddoc, docURI); 181 | } finally { 182 | XmlSourceUtil.closeQuietly(src); 183 | } 184 | } 185 | }; 186 | } 187 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMergerUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.fop.render.pdf.pdfbox; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.Map.Entry; 22 | 23 | import org.apache.pdfbox.cos.COSArray; 24 | import org.apache.pdfbox.cos.COSBase; 25 | import org.apache.pdfbox.cos.COSDictionary; 26 | import org.apache.pdfbox.cos.COSName; 27 | import org.apache.pdfbox.cos.COSObject; 28 | 29 | public final class StructureTreeMergerUtil { 30 | 31 | private StructureTreeMergerUtil() { } 32 | 33 | public static int findObjectPositionInKidsArray(COSObject kidObj) { 34 | COSDictionary kid = (COSDictionary) kidObj.getObject(); 35 | COSObject parentObj = (COSObject) kid.getItem(COSName.P); 36 | COSDictionary parent = (COSDictionary) parentObj.getObject(); 37 | COSBase kids = parent.getItem(COSName.K); 38 | if (kids instanceof COSArray) { 39 | COSArray kidsArray = (COSArray)kids; 40 | return kidsArray.indexOfObject(kid); 41 | } else { 42 | return 0; 43 | } 44 | } 45 | 46 | public static List findRoleMapKeyByValue(String type, COSDictionary roleMap) { 47 | List keys = new ArrayList(); 48 | if (roleMap != null) { 49 | for (Entry entry : roleMap.entrySet()) { 50 | if (entry.getValue() instanceof COSName) { 51 | String value = ((COSName) entry.getValue()).getName(); 52 | String key = entry.getKey().getName(); 53 | if (type.equals(value)) { 54 | keys.add(key); 55 | } 56 | } 57 | } 58 | } 59 | return keys; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/TaggedPDFConductor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.fop.render.pdf.pdfbox; 19 | 20 | import java.io.IOException; 21 | 22 | import org.apache.pdfbox.cos.COSArray; 23 | import org.apache.pdfbox.cos.COSDictionary; 24 | import org.apache.pdfbox.cos.COSName; 25 | 26 | import org.apache.pdfbox.pdmodel.PDDocument; 27 | import org.apache.pdfbox.pdmodel.PDPage; 28 | import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDMarkInfo; 29 | 30 | import org.apache.fop.pdf.PDFDocument; 31 | import org.apache.fop.pdf.PDFName; 32 | import org.apache.fop.pdf.PDFPage; 33 | import org.apache.fop.pdf.PDFStructElem; 34 | import org.apache.fop.render.pdf.PDFLogicalStructureHandler; 35 | 36 | public class TaggedPDFConductor { 37 | 38 | private PDPage srcPage; 39 | private PDFPage targetPage; 40 | private DocumentRootModifier rootMod; 41 | private StructureTreeMerger merger; 42 | 43 | public TaggedPDFConductor(PDFStructElem currentSessionElem, 44 | PDFLogicalStructureHandler logicalStructHandler, PDPage srcPage, 45 | PDFBoxAdapter adapter) { 46 | this.srcPage = srcPage; 47 | this.targetPage = adapter.getTargetPage(); 48 | PDFDocument pdfDoc = targetPage.getDocument(); 49 | this.rootMod = new DocumentRootModifier(adapter, pdfDoc); 50 | merger = new StructureTreeMerger(currentSessionElem, logicalStructHandler, adapter, srcPage); 51 | } 52 | 53 | public void handleLogicalStructure(PDDocument srcDoc) throws IOException { 54 | if (isInputPDFTagged(srcDoc) && isStructureTreeRootNull(srcDoc)) { 55 | merger.setCurrentSessionElem(); 56 | COSDictionary strucRootDict = srcDoc.getDocumentCatalog().getStructureTreeRoot() 57 | .getCOSObject(); 58 | rootMod.structTreeRootEntriesToCopy(strucRootDict); 59 | if (!isParentTreeIsPresent(strucRootDict)) { 60 | merger.createDirectDescendants(strucRootDict, merger.getCurrentSessionElem()); 61 | } else { 62 | PageParentTreeFinder markedContentsParentFinder = new PageParentTreeFinder(srcPage); 63 | COSArray markedContentsParents = markedContentsParentFinder.getPageParentTreeArray(srcDoc); 64 | COSDictionary roleMap = (COSDictionary)strucRootDict.getDictionaryObject(COSName.ROLE_MAP); 65 | if (roleMap != null) { 66 | merger.setRoleMap(roleMap); 67 | } 68 | merger.copyStructure(markedContentsParents); 69 | } 70 | } 71 | configureCurrentSessionElem(srcDoc); 72 | } 73 | 74 | private void configureCurrentSessionElem(PDDocument srcDoc) { 75 | if (!(isInputPDFTagged(srcDoc) && isStructureTreeRootNull(srcDoc))) { 76 | merger.setCurrentSessionElemKid(); 77 | merger.getCurrentSessionElem().put(COSName.PG.getName(), targetPage.makeReference()); 78 | } else { 79 | merger.getCurrentSessionElem().put("S", new PDFName("Div")); 80 | merger.getCurrentSessionElem().remove("Alt"); 81 | } 82 | } 83 | private boolean isInputPDFTagged(PDDocument srcDoc) { 84 | PDMarkInfo mark = srcDoc.getDocumentCatalog().getMarkInfo(); 85 | return mark != null && mark.isMarked(); 86 | } 87 | 88 | private boolean isStructureTreeRootNull(PDDocument srcDoc) { 89 | return srcDoc.getDocumentCatalog().getStructureTreeRoot() != null; 90 | } 91 | 92 | private boolean isParentTreeIsPresent(COSDictionary strucRootDict) { 93 | return strucRootDict.keySet().contains(COSName.PARENT_TREE); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/java/org/apache/fop/render/pdf/pdfbox/UniqueName.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | package org.apache.fop.render.pdf.pdfbox; 20 | 21 | import java.awt.Rectangle; 22 | import java.io.ByteArrayOutputStream; 23 | import java.io.IOException; 24 | import java.util.ArrayList; 25 | import java.util.Collections; 26 | import java.util.List; 27 | 28 | import org.apache.pdfbox.cos.COSBase; 29 | import org.apache.pdfbox.cos.COSDictionary; 30 | import org.apache.pdfbox.cos.COSName; 31 | import org.apache.pdfbox.cos.COSObject; 32 | 33 | import org.apache.fop.pdf.PDFDocument; 34 | 35 | /** 36 | * This class provides collision-avoidance for names within a collection. 37 | * That is, if a submitted name collides with a name in the collection, an alternative is provided. 38 | * The alternative may or may not be in the collection. 39 | */ 40 | public class UniqueName { 41 | private String key; 42 | private String patternKey; 43 | private List resourceNames = Collections.emptyList(); 44 | private List patternNames = Collections.emptyList(); 45 | 46 | public UniqueName(String key, COSDictionary sourcePageResources, List patternNames, boolean disable, 47 | Rectangle destRect) { 48 | if (!disable) { 49 | key = key.split("#")[0]; 50 | this.key = Integer.toString(key.hashCode()); 51 | if (!patternNames.isEmpty()) { 52 | // Make pattern key unique to the destination rectangle. 53 | patternKey = Integer.toString((key 54 | + destRect.getX() + destRect.getY() + destRect.getWidth() + destRect.getHeight()).hashCode()); 55 | this.patternNames = patternNames; 56 | } 57 | resourceNames = getResourceNames(sourcePageResources); 58 | } 59 | } 60 | 61 | /** 62 | * Provides a de-collisioned name. 63 | * @param cn Submitted name. 64 | * @return The submitted name if it is not already in this object's collection or an alternative it is. 65 | * It is possible that the alternative is also in the collection. 66 | */ 67 | protected String getName(COSName cn) { 68 | if (patternNames.contains(cn)) { 69 | return cn.getName() + patternKey; 70 | } 71 | if (resourceNames.contains(cn)) { 72 | return cn.getName() + key; 73 | } 74 | return cn.getName(); 75 | } 76 | 77 | /** 78 | * Writes a name into a StringBuilder, appending a suffix if the name exists in this object's collection. 79 | * @param sb The StringBuilder. 80 | * @param cn The COSName. 81 | * @throws IOException On IO exception. 82 | */ 83 | protected void writeName(StringBuilder sb, COSName cn) throws IOException { 84 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 85 | cn.writePDF(bos); 86 | String name = bos.toString(PDFDocument.ENCODING); 87 | sb.append(name); 88 | if (patternNames.contains(cn)) { 89 | sb.append(patternKey); 90 | } 91 | if (resourceNames.contains(cn)) { 92 | sb.append(key); 93 | } 94 | } 95 | 96 | private List getResourceNames(COSDictionary sourcePageResources) { 97 | List resourceNames = new ArrayList<>(); 98 | for (COSBase e : sourcePageResources.getValues()) { 99 | if (e instanceof COSObject) { 100 | e = ((COSObject) e).getObject(); 101 | } 102 | if (e instanceof COSDictionary) { 103 | COSDictionary d = (COSDictionary) e; 104 | for (COSName cosName : d.keySet()) { 105 | if (!patternNames.contains(cosName)) { 106 | resourceNames.add(cosName); 107 | } 108 | } 109 | } 110 | } 111 | resourceNames.remove(COSName.S); 112 | return resourceNames; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/tools/resources/findbugs/exclusions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/java/org/apache/fop/render/pdf/TaggedPDFConductorTestCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.fop.render.pdf; 19 | 20 | import java.awt.geom.Rectangle2D; 21 | import java.io.IOException; 22 | import java.util.HashMap; 23 | import java.util.List; 24 | 25 | import org.junit.Assert; 26 | import org.junit.Test; 27 | 28 | import org.apache.pdfbox.pdmodel.PDDocument; 29 | import org.apache.pdfbox.pdmodel.PDPage; 30 | 31 | import org.apache.fop.pdf.PDFArray; 32 | import org.apache.fop.pdf.PDFDictionary; 33 | import org.apache.fop.pdf.PDFDocument; 34 | import org.apache.fop.pdf.PDFName; 35 | import org.apache.fop.pdf.PDFNumber; 36 | import org.apache.fop.pdf.PDFObject; 37 | import org.apache.fop.pdf.PDFPage; 38 | import org.apache.fop.pdf.PDFResources; 39 | import org.apache.fop.pdf.PDFStructElem; 40 | import org.apache.fop.render.pdf.pdfbox.PDFBoxAdapter; 41 | import org.apache.fop.render.pdf.pdfbox.PDFBoxAdapterTestCase; 42 | import org.apache.fop.render.pdf.pdfbox.TaggedPDFConductor; 43 | 44 | public class TaggedPDFConductorTestCase { 45 | private static final String LINK = "linkTagged.pdf"; 46 | private static final String HELLO = "helloWorld.pdf"; 47 | private static final String TABLE = "emptyRowTable.pdf"; 48 | private static final String OTF = "otf.pdf"; 49 | private static final String IMAGE = "hello2.pdf"; 50 | private static final String NOPARENTTREE = "NoParentTree.pdf"; 51 | private PDFPage pdfPage; 52 | private PDFDocument pdfDoc; 53 | 54 | @Test 55 | public void testHandleLogicalStructure() throws IOException { 56 | PDFStructElem elem = new PDFStructElem(); 57 | runConductor(LINK, elem); 58 | checkStructure(elem, 0); 59 | 60 | elem = new PDFStructElem(); 61 | runConductor(HELLO, elem); 62 | PDFNumber mcid = (PDFNumber)elem.getKids().get(0); 63 | int test = mcid.getNumber().intValue(); 64 | Assert.assertEquals(test, 0); 65 | 66 | elem = new PDFStructElem(); 67 | runConductor(TABLE, elem); 68 | Assert.assertEquals(print(elem), "/Div/Sect/Table/TBody/TR/TD/P/TD/P/TR/TD/TD"); 69 | 70 | elem = new PDFStructElem(); 71 | elem.put("Alt", "alt-text"); 72 | runConductor(OTF, elem); 73 | Assert.assertEquals(print(elem), "/Div/Art/P/Span"); 74 | Assert.assertNull(elem.get("Alt")); 75 | } 76 | 77 | private String print(PDFStructElem x) { 78 | StringBuilder sb = new StringBuilder(x.get("S").toString()); 79 | if (x.getKids() != null) { 80 | for (PDFObject k : x.getKids()) { 81 | if (k instanceof PDFStructElem) { 82 | sb.append(print((PDFStructElem) k)); 83 | } 84 | } 85 | return sb.toString(); 86 | } 87 | return ""; 88 | } 89 | 90 | private void runConductor(String pdf, PDFStructElem elem) throws IOException { 91 | setUp(); 92 | PDDocument doc = PDFBoxAdapterTestCase.load(pdf); 93 | PDPage srcPage = doc.getPage(0); 94 | elem.setObjectNumber(2); 95 | PDFBoxAdapter adapter = new PDFBoxAdapter( 96 | pdfPage, new HashMap<>(), new HashMap()); 97 | PDFLogicalStructureHandler handler = setUpPDFLogicalStructureHandler(); 98 | new TaggedPDFConductor(elem, handler, srcPage, adapter).handleLogicalStructure(doc); 99 | doc.close(); 100 | } 101 | 102 | private void setUp() { 103 | Rectangle2D r = new Rectangle2D.Double(); 104 | pdfPage = new PDFPage(new PDFResources(pdfDoc), 0, r, r, r, r); 105 | pdfDoc = new PDFDocument(" "); 106 | pdfDoc.makeStructTreeRoot(null); 107 | pdfPage.setObjectNumber(1); 108 | pdfPage.setDocument(pdfDoc); 109 | } 110 | 111 | private PDFLogicalStructureHandler setUpPDFLogicalStructureHandler() { 112 | PDFLogicalStructureHandler handler = new PDFLogicalStructureHandler(pdfDoc); 113 | handler.getParentTree().setDocument(pdfDoc); 114 | handler.startPage(pdfPage); 115 | return handler; 116 | } 117 | 118 | private void checkStructure(PDFStructElem elem, int index) { 119 | String [] types = {"Sect", "P"}; 120 | List list = elem.getKids(); 121 | if (index != types.length) { 122 | PDFStructElem kid = (PDFStructElem)list.get(0); 123 | String test = ((PDFName)kid.get("S")).getName(); 124 | String expected = types[index]; 125 | Assert.assertEquals(test, expected); 126 | index++; 127 | checkStructure(kid, index); 128 | } else { 129 | PDFDictionary firstKid = (PDFDictionary) list.get(0); 130 | int test = ((PDFNumber)firstKid.get("MCID")).getNumber().intValue(); 131 | int expected = 0; 132 | Assert.assertEquals(test, expected); 133 | PDFDictionary firstKidSibling = (PDFDictionary) list.get(2); 134 | test = ((PDFNumber)firstKidSibling.get("MCID")).getNumber().intValue(); 135 | expected = 2; 136 | Assert.assertEquals(test, expected); 137 | PDFStructElem second = (PDFStructElem)list.get(1); 138 | List secondKids = second.getKids(); 139 | PDFStructElem secKid = (PDFStructElem) secondKids.get(0); 140 | List secondKidKids = secKid.getKids(); 141 | PDFDictionary leafElem = (PDFDictionary)secondKidKids.get(0); 142 | test = ((PDFNumber)leafElem.get("MCID")).getNumber().intValue(); 143 | expected = 1; 144 | Assert.assertEquals(test, expected); 145 | } 146 | } 147 | 148 | @Test 149 | public void testTaggedImagePDF() throws IOException { 150 | PDFStructElem elem = new PDFStructElem(); 151 | runConductor(IMAGE, elem); 152 | Assert.assertEquals("/Div/Sect/P/Image", print(elem)); 153 | } 154 | 155 | @Test 156 | public void testCreateDirectDescendants() throws IOException { 157 | PDFStructElem elem = new PDFStructElem(); 158 | runConductor(NOPARENTTREE, elem); 159 | Assert.assertEquals(print(elem), "/Div/Document"); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /test/java/org/apache/fop/render/pdf/pdfbox/DocumentRootModifierTestCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.fop.render.pdf.pdfbox; 18 | 19 | import java.awt.geom.Rectangle2D; 20 | import java.io.IOException; 21 | import java.util.HashMap; 22 | 23 | import org.junit.Assert; 24 | import org.junit.Test; 25 | 26 | import org.apache.pdfbox.cos.COSDictionary; 27 | import org.apache.pdfbox.cos.COSName; 28 | import org.apache.pdfbox.pdmodel.PDDocument; 29 | 30 | import org.apache.fop.pdf.PDFArray; 31 | import org.apache.fop.pdf.PDFDictionary; 32 | import org.apache.fop.pdf.PDFDocument; 33 | import org.apache.fop.pdf.PDFName; 34 | import org.apache.fop.pdf.PDFPage; 35 | import org.apache.fop.pdf.PDFResources; 36 | import org.apache.fop.pdf.PDFStructTreeRoot; 37 | 38 | public class DocumentRootModifierTestCase { 39 | private static final String CLASSMAP = "classMap.pdf"; 40 | 41 | @Test 42 | public void testStructTreeRootEntriesToCopy() throws IOException { 43 | Rectangle2D r = new Rectangle2D.Double(); 44 | PDFDocument pdfDoc = new PDFDocument(""); 45 | PDFPage page = new PDFPage(new PDFResources(pdfDoc), 0, r, r, r, r); 46 | page.setObjectNumber(1); 47 | page.setDocument(pdfDoc); 48 | pdfDoc.makeStructTreeRoot(null); 49 | PDFStructTreeRoot structTreeRoot = pdfDoc.getRoot().getStructTreeRoot(); 50 | PDFDictionary rootBaseRoleMap = new PDFDictionary(); 51 | PDFBoxAdapter adapter = new PDFBoxAdapter(page, new HashMap<>(), new HashMap()); 52 | DocumentRootModifier modifier = new DocumentRootModifier(adapter, pdfDoc); 53 | COSDictionary root = new COSDictionary(); 54 | COSDictionary mapRole = new COSDictionary(); 55 | mapRole.setName("Icon", "Figure"); 56 | root.setItem(COSName.ROLE_MAP, mapRole); 57 | modifier.structTreeRootEntriesToCopy(root); 58 | structTreeRoot = pdfDoc.getRoot().getStructTreeRoot(); 59 | PDFDictionary baseRoot = (PDFDictionary) structTreeRoot.get(COSName.ROLE_MAP.getName()); 60 | String test = baseRoot.get("Icon").toString(); 61 | String expected = "/Figure"; 62 | Assert.assertEquals(test, expected); 63 | 64 | PDFName para = new PDFName("P"); 65 | rootBaseRoleMap.put("MyPara", para); 66 | structTreeRoot.put("RoleMap", rootBaseRoleMap); 67 | modifier.structTreeRootEntriesToCopy(root); 68 | structTreeRoot = pdfDoc.getRoot().getStructTreeRoot(); 69 | PDFDictionary baseRoot2 = (PDFDictionary) structTreeRoot.get(COSName.ROLE_MAP.getName()); 70 | PDFName nameIcon = (PDFName) baseRoot2.get("Icon"); 71 | PDFName myPara = (PDFName)baseRoot2.get("MyPara"); 72 | test = nameIcon.getName(); 73 | expected = "Figure"; 74 | Assert.assertEquals(test, expected); 75 | test = myPara.getName(); 76 | expected = "P"; 77 | Assert.assertEquals(test, expected); 78 | 79 | 80 | PDDocument doc = PDFBoxAdapterTestCase.load(CLASSMAP); 81 | COSDictionary temp = doc.getDocumentCatalog().getStructureTreeRoot().getCOSObject(); 82 | PDFDictionary classMap = new PDFDictionary(); 83 | PDFDictionary inner = new PDFDictionary(); 84 | inner.put("StartIndent", 0); 85 | classMap.put("Normal2", inner); 86 | structTreeRoot.put("ClassMap", classMap); 87 | modifier.structTreeRootEntriesToCopy(temp); 88 | structTreeRoot = pdfDoc.getRoot().getStructTreeRoot(); 89 | PDFDictionary testDict = (PDFDictionary)structTreeRoot.get("ClassMap"); 90 | Assert.assertNotNull(testDict.get("Normal2")); 91 | doc.close(); 92 | } 93 | 94 | } 95 | 96 | -------------------------------------------------------------------------------- /test/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2AFPTestCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.fop.render.pdf.pdfbox; 18 | 19 | import org.junit.Assert; 20 | import org.junit.Test; 21 | 22 | import org.apache.commons.io.IOUtils; 23 | 24 | import org.apache.pdfbox.Loader; 25 | import org.apache.pdfbox.io.RandomAccessReadBuffer; 26 | import org.apache.pdfbox.pdmodel.PDDocument; 27 | import org.apache.pdfbox.pdmodel.PDPage; 28 | 29 | import org.apache.xmlgraphics.image.loader.ImageInfo; 30 | import org.apache.xmlgraphics.image.loader.impl.ImageRawStream; 31 | 32 | public class ImageConverterPDF2AFPTestCase { 33 | @Test 34 | public void testConverter() throws Exception { 35 | PDDocument orgdoc = PDFBoxAdapterTestCase.load(PDFBoxAdapterTestCase.ANNOT); 36 | String orgPage = IOUtils.toString(orgdoc.getPage(1).getContents(), "utf8"); 37 | Assert.assertEquals(orgdoc.getNumberOfPages(), 2); 38 | ImageInfo info = new ImageInfo("x.pdf#page=2", ImagePDF.MIME_PDF); 39 | ImagePDF imagePDF = new ImagePDF(info, orgdoc); 40 | ImageConverterPDF2AFP converter = new ImageConverterPDF2AFP(); 41 | ImageRawStream stream = (ImageRawStream) converter.convert(imagePDF, null); 42 | PDDocument doc = Loader.loadPDF(new RandomAccessReadBuffer(stream.createInputStream())); 43 | PDPage page = doc.getPage(0); 44 | Assert.assertEquals(orgPage, IOUtils.toString(page.getContents(), "utf8")); 45 | Assert.assertEquals(doc.getNumberOfPages(), 1); 46 | Assert.assertEquals(stream.getMimeType(), ImagePDF.MIME_PDF); 47 | orgdoc.close(); 48 | doc.close(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /test/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2G2DTestCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id: ImageConverterPDF2G2D.java 1808727 2017-09-18 15:02:56Z ssteiner $ */ 19 | package org.apache.fop.render.pdf.pdfbox; 20 | 21 | import java.awt.Graphics2D; 22 | import java.awt.Rectangle; 23 | import java.awt.geom.Rectangle2D; 24 | import java.awt.image.BufferedImage; 25 | import java.io.ByteArrayOutputStream; 26 | import java.io.File; 27 | import java.io.IOException; 28 | import java.io.OutputStream; 29 | import java.net.URI; 30 | import java.nio.charset.StandardCharsets; 31 | import java.util.HashMap; 32 | import java.util.Map; 33 | 34 | import org.junit.Assert; 35 | import org.junit.Test; 36 | 37 | import org.apache.pdfbox.cos.COSName; 38 | import org.apache.pdfbox.cos.COSStream; 39 | import org.apache.pdfbox.pdmodel.PDDocument; 40 | import org.apache.pdfbox.pdmodel.common.PDStream; 41 | import org.apache.pdfbox.pdmodel.graphics.PDXObject; 42 | 43 | import org.apache.xmlgraphics.image.loader.ImageException; 44 | import org.apache.xmlgraphics.image.loader.ImageInfo; 45 | import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; 46 | import org.apache.xmlgraphics.java2d.GeneralGraphics2DImagePainter; 47 | import org.apache.xmlgraphics.java2d.GraphicContext; 48 | 49 | import org.apache.fop.apps.io.InternalResourceResolver; 50 | import org.apache.fop.apps.io.ResourceResolverFactory; 51 | import org.apache.fop.fonts.EmbedFontInfo; 52 | import org.apache.fop.fonts.EmbeddingMode; 53 | import org.apache.fop.fonts.FontUris; 54 | import org.apache.fop.fonts.LazyFont; 55 | import org.apache.fop.fonts.MultiByteFont; 56 | import org.apache.fop.fonts.Typeface; 57 | 58 | public class ImageConverterPDF2G2DTestCase { 59 | private static final String FONTSNOTEMBEDDED = "fontsnotembedded.pdf"; 60 | private static final String FONTSNOTEMBEDDEDCID = "fontsnotembeddedcid.pdf"; 61 | 62 | @Test 63 | public void testFontsNotEmbedded() throws IOException, ImageException { 64 | Assert.assertFalse(pdfToPS(FONTSNOTEMBEDDED, "xyz")); 65 | Assert.assertFalse(pdfToPS(FONTSNOTEMBEDDEDCID, "xyz")); 66 | } 67 | 68 | private boolean pdfToPS(String pdf, String font) throws IOException, ImageException { 69 | PDDocument doc = PDFBoxAdapterTestCase.load(pdf); 70 | MyLazyFont lazyFont = new MyLazyFont(); 71 | pdfToPS(doc, pdf, font, lazyFont); 72 | return lazyFont.font.fontUsed; 73 | } 74 | 75 | private void pdfToPS(String pdf, LazyFont lazyFont) throws IOException, ImageException { 76 | PDDocument doc = PDFBoxAdapterTestCase.load(pdf); 77 | pdfToPS(doc, pdf, "NewsMinIWA-Th", lazyFont); 78 | } 79 | 80 | private String pdfToPS(PDDocument doc, String pdf, String font, LazyFont lazyFont) 81 | throws IOException, ImageException { 82 | try { 83 | ImageConverterPDF2G2D i = new ImageConverterPDF2G2D(); 84 | ImageInfo imgi = new ImageInfo(pdf, "b"); 85 | org.apache.xmlgraphics.image.loader.Image img = new ImagePDF(imgi, doc); 86 | ImageGraphics2D ig = (ImageGraphics2D) i.convert(img, null); 87 | GeneralGraphics2DImagePainter g = (GeneralGraphics2DImagePainter) ig.getGraphics2DImagePainter(); 88 | g.addFallbackFont(font, lazyFont); 89 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); 90 | PSPDFGraphics2D g2d = (PSPDFGraphics2D) 91 | g.getGraphics(true, new PDFBoxAdapterTestCase.FOPPSGeneratorImpl(stream)); 92 | Rectangle2D rect = new Rectangle2D.Float(0, 0, 100, 100); 93 | GraphicContext gc = new GraphicContext(); 94 | g2d.setGraphicContext(gc); 95 | g.paint(g2d, rect); 96 | return stream.toString(StandardCharsets.UTF_8.name()); 97 | } finally { 98 | doc.close(); 99 | } 100 | } 101 | 102 | static class MyLazyFont extends LazyFont { 103 | Font font = new Font(); 104 | MyLazyFont() { 105 | super(new EmbedFontInfo(new FontUris(null, null), false, false, null, ""), null, false); 106 | } 107 | public Typeface getRealFont() { 108 | return font; 109 | } 110 | } 111 | 112 | static class Font extends MultiByteFont { 113 | boolean fontUsed; 114 | public Font() { 115 | super(null, EmbeddingMode.AUTO); 116 | } 117 | public boolean isOTFFile() { 118 | fontUsed = true; 119 | return true; 120 | } 121 | } 122 | 123 | @Test 124 | public void testPDFToImage() throws IOException, ImageException { 125 | PDDocument doc = PDFBoxAdapterTestCase.load(FONTSNOTEMBEDDED); 126 | ImageInfo imgi = new ImageInfo(FONTSNOTEMBEDDED, "b"); 127 | org.apache.xmlgraphics.image.loader.Image img = new ImagePDF(imgi, doc); 128 | ImageConverterPDF2G2D imageConverterPDF2G2D = new ImageConverterPDF2G2D(); 129 | ImageGraphics2D fopGraphics2D = (ImageGraphics2D) imageConverterPDF2G2D.convert(img, null); 130 | BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB); 131 | Graphics2D graphics2D = image.createGraphics(); 132 | fopGraphics2D.getGraphics2DImagePainter().paint(graphics2D, new Rectangle(0, 0, 1000, 1000)); 133 | doc.close(); 134 | Assert.assertEquals(graphics2D.getTransform().getScaleX(), 1.63, 0); 135 | } 136 | 137 | @Test 138 | public void testCheckImageMask() throws IOException, ImageException { 139 | String pdf = PDFBoxAdapterTestCase.CFFCID1; 140 | PDDocument doc = PDFBoxAdapterTestCase.load(pdf); 141 | COSStream cosStream = new COSStream(); 142 | OutputStream outputStream = cosStream.createOutputStream(); 143 | outputStream.write("/Fm0 Do\n".getBytes(StandardCharsets.UTF_8)); 144 | outputStream.close(); 145 | PDStream pdStream = new PDStream(cosStream); 146 | doc.getPage(0).setContents(pdStream); 147 | 148 | PDXObject form = doc.getPage(0).getResources().getXObject(COSName.getPDFName("Fm0")); 149 | OutputStream formStream = form.getCOSObject().createOutputStream(); 150 | formStream.write("1 g".getBytes(StandardCharsets.UTF_8)); 151 | formStream.close(); 152 | 153 | String ps = pdfToPS(doc, pdf, null, null); 154 | Assert.assertTrue(ps.contains("/ImageType 1")); 155 | } 156 | 157 | @Test 158 | public void testPDFToPSFontError() throws Exception { 159 | InternalResourceResolver rr = ResourceResolverFactory.createDefaultInternalResourceResolver(new URI(".")); 160 | EmbedFontInfo embedFontInfo = new EmbedFontInfo(new FontUris( 161 | new File("pom.xml").toURI(), null), false, false, null, ""); 162 | RuntimeException ex = Assert.assertThrows(RuntimeException.class, () -> 163 | pdfToPS(FONTSNOTEMBEDDEDCID, new LazyFont(embedFontInfo, rr, false))); 164 | Assert.assertTrue(ex.getMessage().contains("Reached EOF")); 165 | } 166 | 167 | @Test 168 | public void testSoftMaskHighDPI() throws Exception { 169 | Map hints = new HashMap<>(); 170 | hints.put("SOURCE_RESOLUTION", 96f); 171 | ByteArrayOutputStream bos = PDFBoxAdapterTestCase.pdfToPS(PDFBoxAdapterTestCase.SOFTMASK, hints); 172 | String output = bos.toString(StandardCharsets.UTF_8.name()); 173 | Assert.assertEquals(output.split("BeginBitmap").length, 3); 174 | Assert.assertTrue(output.contains("/ImageMatrix [196 0 0 104 0 0]")); 175 | Assert.assertTrue(output.contains("/ImageMatrix [192 0 0 192 0 0]")); 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /test/java/org/apache/fop/render/pdf/pdfbox/PDFClonerTestCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | package org.apache.fop.render.pdf.pdfbox; 20 | 21 | import java.awt.Rectangle; 22 | import java.awt.geom.Rectangle2D; 23 | import java.io.ByteArrayOutputStream; 24 | import java.io.IOException; 25 | import java.io.OutputStream; 26 | import java.util.ArrayList; 27 | import java.util.HashMap; 28 | import java.util.List; 29 | import java.util.Map; 30 | 31 | import org.junit.Assert; 32 | import org.junit.Test; 33 | 34 | import org.apache.pdfbox.cos.COSArray; 35 | import org.apache.pdfbox.cos.COSDictionary; 36 | import org.apache.pdfbox.cos.COSInteger; 37 | import org.apache.pdfbox.cos.COSName; 38 | import org.apache.pdfbox.cos.COSObject; 39 | import org.apache.pdfbox.cos.COSStream; 40 | import org.apache.pdfbox.cos.COSString; 41 | 42 | import org.apache.fop.pdf.PDFArray; 43 | import org.apache.fop.pdf.PDFDocument; 44 | import org.apache.fop.pdf.PDFPage; 45 | import org.apache.fop.pdf.PDFResources; 46 | import org.apache.fop.pdf.PDFStream; 47 | 48 | public class PDFClonerTestCase { 49 | @Test 50 | public void testCompareTree() throws IOException { 51 | Assert.assertEquals(PDFBoxAdapterUtil.getBaseKey(makeTree(2)), 52 | PDFBoxAdapterUtil.getBaseKey(makeTree(1))); 53 | } 54 | 55 | @Test 56 | public void testCompareDict() throws IOException { 57 | COSDictionary a = new COSDictionary(); 58 | a.setItem(COSName.C, COSInteger.ONE); 59 | a.setItem(COSName.D, COSInteger.ONE); 60 | COSDictionary b = new COSDictionary(); 61 | b.setItem(COSName.D, COSInteger.ONE); 62 | b.setItem(COSName.C, COSInteger.ONE); 63 | Assert.assertEquals(PDFBoxAdapterUtil.getBaseKey(a), PDFBoxAdapterUtil.getBaseKey(b)); 64 | } 65 | 66 | private COSDictionary makeTree(long objNumber) throws IOException { 67 | COSStream stream = new COSStream(); 68 | COSObject obj = new COSObject(stream); 69 | // obj.setObjectNumber(objNumber); 70 | COSArray array = new COSArray(); 71 | array.add(obj); 72 | COSDictionary root = new COSDictionary(); 73 | root.setItem(COSName.C, array); 74 | return root; 75 | } 76 | 77 | @Test 78 | public void testString() throws IOException { 79 | COSString string = new COSString(new byte[]{(byte) 127, (byte) 127}); 80 | PDFDocument doc = new PDFDocument(""); 81 | Rectangle2D r = new Rectangle2D.Double(); 82 | PDFPage page = new PDFPage(new PDFResources(doc), 0, r, r, r, r); 83 | page.setDocument(doc); 84 | PDFBoxAdapter adapter = new PDFBoxAdapter(page, new HashMap<>(), new HashMap()); 85 | String cloned = (String) new PDFCloner(adapter, false).cloneForNewDocument(string); 86 | Assert.assertArrayEquals(cloned.getBytes(PDFDocument.ENCODING), string.getBytes()); 87 | } 88 | 89 | @Test 90 | public void testStream() throws IOException { 91 | PDFDocument doc = new PDFDocument(""); 92 | Rectangle2D rectangle = new Rectangle2D.Double(); 93 | PDFPage page = new PDFPage(new PDFResources(doc), 0, rectangle, rectangle, rectangle, rectangle); 94 | page.setDocument(doc); 95 | PDFBoxAdapter adapter = new PDFBoxAdapter(page, new HashMap<>(), new HashMap()); 96 | COSDictionary res = new COSDictionary(); 97 | COSDictionary child = new COSDictionary(); 98 | child.setBoolean("a", true); 99 | res.setItem("a", child); 100 | Rectangle rect = new Rectangle(0, 0, 100, 100); 101 | List patternNames = new ArrayList<>(); 102 | adapter.uniqueName = new UniqueName("a", res, patternNames, false, rect); 103 | PDFStream cloneda = (PDFStream) new PDFCloner(adapter, false).cloneForNewDocument(getStream()); 104 | adapter.uniqueName = new UniqueName("b", res, patternNames, false, rect); 105 | PDFStream clonedb = (PDFStream) new PDFCloner(adapter, false).cloneForNewDocument(getStream()); 106 | Assert.assertNotSame(cloneda, clonedb); 107 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 108 | cloneda.setDocument(doc); 109 | clonedb.setDocument(doc); 110 | setFilterMap(doc); 111 | cloneda.output(bos); 112 | clonedb.output(bos); 113 | Assert.assertEquals(bos.toString(PDFDocument.ENCODING), "<< /Length 1 0 R /Subtype /Form >>\n" 114 | + "stream\n" 115 | + "/a97 tf\n\n" 116 | + "endstream" 117 | + "<< /Length 2 0 R /Subtype /Form >>\n" 118 | + "stream\n" 119 | + "/a98 tf\n\n" 120 | + "endstream"); 121 | } 122 | 123 | private void setFilterMap(PDFDocument doc) { 124 | Map> filterMap = new HashMap<>(); 125 | List filterList = new ArrayList<>(); 126 | filterList.add("null"); 127 | filterMap.put("default", filterList); 128 | doc.setFilterMap(filterMap); 129 | } 130 | 131 | private COSStream getStream() throws IOException { 132 | COSStream stream = new COSStream(); 133 | stream.setItem(COSName.SUBTYPE, COSName.FORM); 134 | try (OutputStream os = stream.createOutputStream()) { 135 | os.write("/a tf".getBytes(PDFDocument.ENCODING)); 136 | } 137 | return stream; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /test/java/org/apache/fop/render/pdf/pdfbox/PDFRotateTestCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | 20 | package org.apache.fop.render.pdf.pdfbox; 21 | 22 | import java.awt.Rectangle; 23 | import java.awt.geom.AffineTransform; 24 | import java.awt.geom.Rectangle2D; 25 | import java.io.IOException; 26 | 27 | import org.junit.Assert; 28 | import org.junit.Test; 29 | 30 | import org.apache.pdfbox.pdmodel.PDDocument; 31 | import org.apache.pdfbox.pdmodel.PDPage; 32 | 33 | import org.apache.xmlgraphics.image.loader.Image; 34 | import org.apache.xmlgraphics.image.loader.ImageInfo; 35 | import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; 36 | import org.apache.xmlgraphics.java2d.GraphicContext; 37 | import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; 38 | 39 | public class PDFRotateTestCase { 40 | 41 | @Test 42 | public void test() throws Exception { 43 | ImageConverterPDF2G2D i = new ImageConverterPDF2G2D(); 44 | ImageInfo imgi = new ImageInfo("a", "b"); 45 | PDDocument doc = new PDDocument(); 46 | PDPage page = new PDPage(); 47 | page.setRotation(90); 48 | doc.addPage(page); 49 | Image img = new ImagePDF(imgi, doc); 50 | ImageGraphics2D ig = (ImageGraphics2D)i.convert(img, null); 51 | Rectangle2D rect = new Rectangle2D.Float(0, 0, 100, 100); 52 | 53 | PSGraphics2D g2d = new PSPDFGraphics2D(true); 54 | GraphicContext gc = new GraphicContext(); 55 | g2d.setGraphicContext(gc); 56 | ig.getGraphics2DImagePainter().paint(g2d, rect); 57 | Assert.assertEquals(g2d.getTransform().getShearX(), 0.16339869281045752, 0); 58 | } 59 | 60 | @Test 61 | public void testAngle() throws IOException { 62 | Assert.assertEquals(getTransform(90), new AffineTransform(0, 1, 1, 0, 0, 0)); 63 | Assert.assertEquals(getTransform(270), new AffineTransform(0, -1, -1, 0, 842, 595)); 64 | AffineTransform at = getTransform(180); 65 | Assert.assertEquals((int)at.getTranslateX(), 842); 66 | Assert.assertEquals(at.getTranslateY(), 0.0, 0); 67 | } 68 | 69 | private AffineTransform getTransform(int angle) throws IOException { 70 | PDFBoxAdapter adapter = PDFBoxAdapterTestCase.getPDFBoxAdapter(false, false); 71 | PDDocument doc = PDFBoxAdapterTestCase.load(PDFBoxAdapterTestCase.ROTATE); 72 | PDPage page = doc.getPage(0); 73 | page.setRotation(angle); 74 | AffineTransform pageAdjust = new AffineTransform(); 75 | Rectangle r = new Rectangle(0, 1650, 842000, 595000); 76 | String stream = (String) adapter.createStreamFromPDFBoxPage(doc, page, "key", pageAdjust, null, r, pageAdjust); 77 | Assert.assertTrue(stream.contains("/GS0106079 gs")); 78 | Assert.assertTrue(stream.contains("/TT0106079 1 Tf")); 79 | doc.close(); 80 | return pageAdjust; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /test/java/org/apache/fop/render/pdf/pdfbox/PDFWriterTestCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.fop.render.pdf.pdfbox; 18 | 19 | import java.awt.Rectangle; 20 | import java.io.ByteArrayInputStream; 21 | import java.io.IOException; 22 | import java.nio.charset.StandardCharsets; 23 | import java.util.Locale; 24 | 25 | import org.junit.Assert; 26 | import org.junit.Test; 27 | 28 | import org.apache.pdfbox.pdmodel.PDDocument; 29 | import org.apache.pdfbox.pdmodel.common.PDStream; 30 | 31 | public class PDFWriterTestCase { 32 | @Test 33 | public void testFloat() throws IOException { 34 | Locale l = Locale.getDefault(); 35 | Locale.setDefault(Locale.FRENCH); 36 | PDFWriter pdfWriter = new PDFWriter(null, 0); 37 | String text = "[1.1 ] a"; 38 | PDStream pdStream = new PDStream(new PDDocument(), 39 | new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8))); 40 | Assert.assertEquals(pdfWriter.writeText(pdStream), text + "\n"); 41 | Locale.setDefault(l); 42 | } 43 | 44 | @Test 45 | public void testFloatCache() throws IOException { 46 | String text = "[1.1 1.1] a"; 47 | PDDocument doc = new PDDocument(); 48 | PDStream pdStream = new PDStream(doc, new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8))); 49 | MyPDFWriter pdfWriter = new MyPDFWriter(); 50 | pdfWriter.writeText(pdStream); 51 | doc.close(); 52 | Assert.assertEquals(1, pdfWriter.i); 53 | } 54 | 55 | private static class MyPDFWriter extends PDFWriter { 56 | int i; 57 | 58 | public MyPDFWriter() { 59 | super(new UniqueName("", null, null, true, new Rectangle(0, 0, 100, 100)), 0); 60 | } 61 | 62 | protected void addCache(float f) { 63 | super.addCache(f); 64 | i++; 65 | } 66 | } 67 | 68 | @Test 69 | public void testBoolean() throws IOException { 70 | String text = "[true true ] a\n"; 71 | PDStream pdStream = new PDStream(new PDDocument(), 72 | new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8))); 73 | Rectangle rect = new Rectangle(0, 0, 100, 100); 74 | PDFWriter pdfWriter = new PDFWriter(new UniqueName("", null, null, true, rect), 0); 75 | String out = pdfWriter.writeText(pdStream); 76 | Assert.assertEquals(out, text); 77 | } 78 | 79 | @Test 80 | public void testNull() throws IOException { 81 | String text = "[null ] a\n"; 82 | PDStream pdStream = new PDStream(new PDDocument(), 83 | new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8))); 84 | Rectangle rect = new Rectangle(0, 0, 100, 100); 85 | PDFWriter pdfWriter = new PDFWriter(new UniqueName("", null, null, true, rect), 0); 86 | String out = pdfWriter.writeText(pdStream); 87 | Assert.assertEquals(out, text); 88 | } 89 | 90 | @Test 91 | public void testSpaceInName() throws IOException { 92 | String text = "/a#20a a\n"; 93 | PDStream pdStream = new PDStream(new PDDocument(), 94 | new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8))); 95 | Rectangle rect = new Rectangle(0, 0, 100, 100); 96 | PDFWriter pdfWriter = new PDFWriter(new UniqueName("", null, null, true, rect), 0); 97 | String out = pdfWriter.writeText(pdStream); 98 | Assert.assertEquals(out, text); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /test/java/org/apache/fop/render/pdf/pdfbox/PSPDFGraphics2DTestCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* $Id$ */ 19 | package org.apache.fop.render.pdf.pdfbox; 20 | 21 | import java.io.ByteArrayOutputStream; 22 | import java.io.IOException; 23 | import java.io.OutputStream; 24 | import java.nio.charset.StandardCharsets; 25 | 26 | import org.junit.Assert; 27 | import org.junit.Test; 28 | 29 | import org.apache.pdfbox.cos.COSArray; 30 | import org.apache.pdfbox.cos.COSInteger; 31 | import org.apache.pdfbox.cos.COSName; 32 | import org.apache.pdfbox.cos.COSStream; 33 | import org.apache.pdfbox.pdmodel.common.function.PDFunction; 34 | import org.apache.pdfbox.pdmodel.common.function.PDFunctionType0; 35 | 36 | import org.apache.fop.render.gradient.Function; 37 | 38 | public class PSPDFGraphics2DTestCase { 39 | 40 | @Test 41 | public void testShading() throws IOException { 42 | COSStream stream = new COSStream(); 43 | OutputStream streamData = stream.createOutputStream(); 44 | streamData.write("test".getBytes(StandardCharsets.UTF_8)); 45 | streamData.close(); 46 | stream.setItem(COSName.BITS_PER_SAMPLE, COSInteger.get(8)); 47 | stream.setItem(COSName.FUNCTION_TYPE, COSInteger.ZERO); 48 | COSArray range = new COSArray(); 49 | range.add(COSInteger.ZERO); 50 | range.add(COSInteger.ONE); 51 | range.add(COSInteger.ZERO); 52 | range.add(COSInteger.ONE); 53 | range.add(COSInteger.ZERO); 54 | range.add(COSInteger.ONE); 55 | stream.setItem(COSName.RANGE, range); 56 | stream.setItem(COSName.DOMAIN, range); 57 | COSArray size = new COSArray(); 58 | size.add(COSInteger.ONE); 59 | stream.setItem(COSName.SIZE, size); 60 | 61 | Function f = new MyPSPDFGraphics2D().getAFunction(new PDFunctionType0(stream)); 62 | Assert.assertEquals(f.getBitsPerSample(), 8); 63 | } 64 | 65 | static class MyPSPDFGraphics2D extends PSPDFGraphics2D { 66 | MyPSPDFGraphics2D() { 67 | super(false); 68 | } 69 | 70 | Function getAFunction(PDFunction function) throws IOException { 71 | return getFunction(function); 72 | } 73 | } 74 | 75 | @Test 76 | public void testGradientWithMask() throws Exception { 77 | ByteArrayOutputStream bos = PDFBoxAdapterTestCase.pdfToPS("gradientmask.pdf"); 78 | Assert.assertTrue(bos.toString().contains("/Encode [ 0 1 0 1 1 0 ]")); 79 | Assert.assertTrue(bos.toString().contains("/MaskColor [ 0 0 0 ]")); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /test/java/org/apache/fop/render/pdf/pdfbox/PageParentTreeFinderTestCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.fop.render.pdf.pdfbox; 19 | 20 | import java.io.IOException; 21 | 22 | import org.junit.Assert; 23 | import org.junit.Test; 24 | 25 | import org.apache.pdfbox.cos.COSArray; 26 | import org.apache.pdfbox.cos.COSDictionary; 27 | import org.apache.pdfbox.cos.COSInteger; 28 | import org.apache.pdfbox.cos.COSName; 29 | import org.apache.pdfbox.cos.COSNull; 30 | import org.apache.pdfbox.cos.COSObject; 31 | 32 | import org.apache.pdfbox.pdmodel.PDDocument; 33 | import org.apache.pdfbox.pdmodel.PDPage; 34 | import org.apache.pdfbox.pdmodel.PDResources; 35 | import org.apache.pdfbox.pdmodel.common.PDNumberTreeNode; 36 | 37 | public class PageParentTreeFinderTestCase { 38 | private static final String LINK = "linkTagged.pdf"; 39 | 40 | @Test 41 | public void testGetPageParentTreeArray() throws IOException { 42 | PDDocument doc = PDFBoxAdapterTestCase.load(LINK); 43 | PDPage srcPage = doc.getPage(0); 44 | PageParentTreeFinder finder = new PageParentTreeFinder(srcPage); 45 | COSArray markedContentParents = finder.getPageParentTreeArray(doc); 46 | Assert.assertEquals(markedContentParents.size(), 3); 47 | COSObject firstObj = (COSObject)markedContentParents.get(0); 48 | COSObject secObj = (COSObject)markedContentParents.get(1); 49 | COSDictionary firstObjDict = (COSDictionary) firstObj.getObject(); 50 | COSArray firstKids = (COSArray)firstObjDict.getDictionaryObject(COSName.K); 51 | COSDictionary firstKid = (COSDictionary) firstKids.get(0); 52 | int test = firstKid.getInt("MCID"); 53 | int expected = 0; 54 | Assert.assertEquals(test, expected); 55 | COSDictionary firstKidBrother = (COSDictionary)firstKids.get(2); 56 | test = firstKidBrother.getInt("MCID"); 57 | expected = 2; 58 | Assert.assertEquals(test, expected); 59 | COSDictionary secObjDict = (COSDictionary) secObj.getObject(); 60 | COSArray secKidsArray = (COSArray)secObjDict.getDictionaryObject(COSName.K); 61 | COSDictionary secondKid = (COSDictionary)secKidsArray.get(0); 62 | test = secondKid.getInt("MCID"); 63 | expected = 1; 64 | Assert.assertEquals(test, expected); 65 | doc.close(); 66 | } 67 | 68 | @Test 69 | public void testNoparentTreePresent() throws IOException { 70 | PDPage srcPage = new PDPage(); 71 | srcPage.getCOSObject().setItem(COSName.STRUCT_PARENTS, COSInteger.get(-1)); 72 | PDResources res = new PDResources(); 73 | srcPage.setResources(res); 74 | PageParentTreeFinder finder = new PageParentTreeFinder(srcPage); 75 | COSArray parentTree = finder.getPageParentTreeArray(null); 76 | int test = parentTree.size(); 77 | Assert.assertEquals(test, 0); 78 | } 79 | 80 | @Test 81 | public void testTraverseKids() throws IOException { 82 | PDDocument doc = PDFBoxAdapterTestCase.load(LINK); 83 | PDNumberTreeNode srcNumberTreeNode = doc.getDocumentCatalog().getStructureTreeRoot().getParentTree(); 84 | COSArray parentTree = (COSArray) srcNumberTreeNode.getCOSObject().getDictionaryObject(COSName.KIDS); 85 | COSObject kidCOSObj = (COSObject) parentTree.get(0); 86 | COSDictionary dict = (COSDictionary) kidCOSObj.getObject(); 87 | COSArray nums = (COSArray) dict.getDictionaryObject(COSName.NUMS); 88 | nums.add(0, COSInteger.get(9)); 89 | nums.add(1, new COSDictionary()); 90 | COSArray numList = new PageParentTreeFinder(doc.getPage(0)).getPageParentTreeArray(doc); 91 | Assert.assertEquals(numList.size(), 3); 92 | doc.close(); 93 | } 94 | 95 | @Test 96 | public void testCOSNull() throws IOException { 97 | PDDocument doc = PDFBoxAdapterTestCase.load(LINK); 98 | PDNumberTreeNode srcNumberTreeNode = doc.getDocumentCatalog().getStructureTreeRoot().getParentTree(); 99 | COSArray parentTree = (COSArray) srcNumberTreeNode.getCOSObject().getDictionaryObject(COSName.KIDS); 100 | COSObject kidCOSObj = (COSObject) parentTree.get(0); 101 | COSDictionary dict = (COSDictionary) kidCOSObj.getObject(); 102 | COSArray nums = (COSArray) dict.getDictionaryObject(COSName.NUMS); 103 | nums.add(0, COSInteger.ZERO); 104 | nums.add(1, new COSObject(COSNull.NULL)); 105 | COSArray numList = new PageParentTreeFinder(doc.getPage(0)).getPageParentTreeArray(doc); 106 | Assert.assertEquals(numList.size(), 3); 107 | doc.close(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /test/java/org/apache/fop/render/pdf/pdfbox/PreloaderPDFTestCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.fop.render.pdf.pdfbox; 18 | 19 | import java.awt.image.DataBufferInt; 20 | import java.io.ByteArrayInputStream; 21 | import java.io.ByteArrayOutputStream; 22 | import java.io.DataOutputStream; 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.nio.charset.StandardCharsets; 26 | 27 | import javax.imageio.ImageIO; 28 | import javax.imageio.stream.ImageInputStream; 29 | import javax.imageio.stream.MemoryCacheImageInputStream; 30 | 31 | import org.junit.Assert; 32 | import org.junit.Test; 33 | 34 | import org.apache.commons.io.IOUtils; 35 | import org.apache.pdfbox.pdmodel.PDDocument; 36 | 37 | import org.apache.xmlgraphics.image.loader.ImageException; 38 | import org.apache.xmlgraphics.image.loader.ImageInfo; 39 | import org.apache.xmlgraphics.image.loader.ImageSource; 40 | import org.apache.xmlgraphics.image.loader.impl.DefaultImageContext; 41 | import org.apache.xmlgraphics.image.loader.impl.ImageRendered; 42 | 43 | public class PreloaderPDFTestCase { 44 | 45 | @Test 46 | public void testPreloaderImageRawData() throws IOException, ImageException { 47 | PreloaderImageRawData p = new PreloaderImageRawData(); 48 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 49 | DataOutputStream dos = new DataOutputStream(bos); 50 | dos.writeInt(1); 51 | dos.writeInt(1); 52 | dos.writeInt(1); 53 | InputStream is = new ByteArrayInputStream(bos.toByteArray()); 54 | ImageSource src = new ImageSource(new MemoryCacheImageInputStream(is), "", true); 55 | ImageInfo img = p.preloadImage(DataBufferInt.class.getName(), src, new DefaultImageContext()); 56 | Assert.assertTrue(img.getOriginalImage() instanceof ImageRendered); 57 | } 58 | 59 | @Test 60 | public void testPreloaderPDF() throws Exception { 61 | try (InputStream is = PreloaderPDFTestCase.class.getResourceAsStream(PDFBoxAdapterTestCase.ROTATE)) { 62 | ImageSource imageSource = new ImageSource( 63 | ImageIO.createImageInputStream(is), "", true); 64 | ImageInfo imageInfo = new PreloaderPDF().preloadImage("", imageSource, new DefaultImageContext()); 65 | Assert.assertEquals(imageInfo.getMimeType(), "application/pdf"); 66 | } 67 | } 68 | 69 | @Test 70 | public void testPreloaderPDFCache() throws IOException, ImageException { 71 | DefaultImageContext context = new DefaultImageContext(); 72 | readPDF(context); 73 | readPDF(context); 74 | } 75 | 76 | private void readPDF(DefaultImageContext context) throws IOException, ImageException { 77 | try (InputStream is = PreloaderPDFTestCase.class.getResourceAsStream(PDFBoxAdapterTestCase.ROTATE)) { 78 | ImageSource imageSource = new ImageSource(ImageIO.createImageInputStream(is), "", true); 79 | ImageInfo imageInfo = new PreloaderPDF().preloadImage("", imageSource, context); 80 | ImagePDF img = (ImagePDF) imageInfo.getOriginalImage(); 81 | PDDocument doc = img.getPDDocument(); 82 | doc.save(new ByteArrayOutputStream()); 83 | img.close(); 84 | } 85 | } 86 | 87 | @Test 88 | public void testLastResortPreloaderPDF() throws Exception { 89 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 90 | bos.write("xx".getBytes(StandardCharsets.UTF_8)); 91 | IOUtils.copy(PreloaderPDFTestCase.class.getResourceAsStream(PDFBoxAdapterTestCase.ROTATE), bos); 92 | InputStream pdf = new ByteArrayInputStream(bos.toByteArray()); 93 | ImageInputStream inputStream = ImageIO.createImageInputStream(pdf); 94 | ImageSource imageSource = new ImageSource(inputStream, "", true); 95 | ImageInfo imageInfo = new LastResortPreloaderPDF().preloadImage("", imageSource, new DefaultImageContext()); 96 | Assert.assertEquals(imageInfo.getMimeType(), "application/pdf"); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /test/java/org/apache/fop/render/pdf/pdfbox/StructureTreeMergerUtilTestCase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.fop.render.pdf.pdfbox; 19 | 20 | import java.util.List; 21 | 22 | import org.junit.Assert; 23 | import org.junit.Test; 24 | 25 | import org.apache.pdfbox.cos.COSDictionary; 26 | import org.apache.pdfbox.cos.COSName; 27 | import org.apache.pdfbox.cos.COSNull; 28 | 29 | public class StructureTreeMergerUtilTestCase { 30 | 31 | @Test 32 | public void testFindRoleMapKeyByValue() { 33 | 34 | COSDictionary rolemap = new COSDictionary(); 35 | COSName key1 = COSName.getPDFName("Para"); 36 | COSName value1 = COSName.P; 37 | COSName key2 = COSName.getPDFName("Icon"); 38 | COSName value2 = COSName.IMAGE; 39 | rolemap.setItem(key1, value1); 40 | rolemap.setItem(key2, value2); 41 | String type = "Image"; 42 | List result = StructureTreeMergerUtil.findRoleMapKeyByValue(type, rolemap); 43 | String test = result.get(0); 44 | String expected = "Icon"; 45 | Assert.assertEquals(test, expected); 46 | } 47 | 48 | @Test 49 | public void testCOSNull() { 50 | COSDictionary rolemap = new COSDictionary(); 51 | rolemap.setItem(COSName.A, COSNull.NULL); 52 | List result = StructureTreeMergerUtil.findRoleMapKeyByValue(null, rolemap); 53 | Assert.assertTrue(result.isEmpty()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/2fonts.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/2fonts.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/2fonts2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/2fonts2.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/NoParentTree.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/NoParentTree.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/accessibleradiobuttons.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/accessibleradiobuttons.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/annot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/annot.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/annot2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/annot2.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/annot3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/annot3.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/brokenLink.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/brokenLink.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/cffcid1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/cffcid1.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/cffcid2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/cffcid2.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/cffsubrs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/cffsubrs.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/cffsubrs2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/cffsubrs2.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/cffsubrs3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/cffsubrs3.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/cffsubrs4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/cffsubrs4.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/classMap.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/classMap.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/emptyRowTable.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/emptyRowTable.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/error.pdf: -------------------------------------------------------------------------------- 1 | %PDF-1.4 2 | %���� 3 | 1 0 obj 4 | << 5 | /Creator (Smart Communications) 6 | /Producer (Smart Communications) 7 | /CreationDate (D:20170227104302Z) 8 | >> 9 | endobj 10 | 2 0 obj 11 | << 12 | /N 3 13 | /Length 3 0 R 14 | /Filter /FlateDecode 15 | >> 16 | stream 17 | x���wXS���sN�`$!l{��@��� ٢� $ �@T����R)�X�Z�ԉ(��� 18 | R�Z����D����������|�������y��L�0V@(��#��q� ��`�=nn�WXX0�+З�ȕ;�ѫ�R��1{��O��l�(Lγx�\���䜙/�V�'�LK�P0�R�X~@9k(8u��?�̰��yBOΑr�� y 19 | ��<)_Έ"��<?_���l�) 20 | ��F+�s�9�H 21 | ���M����I������#�~��_��_ Q$���. R�$ s���Ņ���g�%f�����,a6GT�LΟEQԖ!/����������B��ſ)Eog�E��A��?l��kJ^�-ؒ��\���?l�{P��������&�d��������\EA��t���{6��~/Ç�‘fJ��q�2��bFn6��g0�<��8��a�O��"yD�|��Ty�E<�D�%bD����0�O��k���-��\���~����[��޷`|4Pܼ�љ��,��w���\A��8vD$�+�ͬ)�%@P4� �0L�����`� ,\��@ ��2��R��ՠ4�f� 22 | �Np ���%p��� ���`��a!2D�4!}��� 4򅂡(J�R!$��Ak�R����f�[�(t� 23 | Bw�!h�z#0 ����)l �`/8����p�.�7Õp|�O×�� ~ 24 | O!!"t�a",���"�H 25 | "FV %HҀ�"�Hr 26 | �!�[EE1PL�*��rP+P�Pը�T/�j5��&�u�VhWt :���G�+�M�v�Y� 27 | ����c�0ΘL&�� � ӆ9�� c��X�&� 28 | � 29 | �r�l1� 30 | {{{;�}�#��q8?\�������n�e�~��J0#�" �ՄJB+�,�>��H4$�É�*b%�����O�π/�7ʷ�����_�_�ߤ���R�S耠���u��́���-��D 35 | ZT�(�2X��� �r��|���P�-�A�YXN���������"�P$.8��U�wdY�(�(iTO�rtBts�����Y�m���KqZq���xl|t|S��B߅;�$8&'�\d��`х�Z�3OTN�$IB'�$Hz� �4p���k�'�l�N�S�'o;o���/珦��������nKO�H�H��Ղ���u�3B3�e|ʌ�l�I£"�(Cԛ��U�5�m�]�-�q�ّ3)7�B��r�$4��T��\�N:�77�&�M~t���QA�e����%~K�^�Z�]ڳ�`��eC˽�ׯ�V$��Yi��h��*�U�WVg��a�ݚ�5/�Ƭ�.�-ZU4��]K�R����z��uP6��X��c ��b�]iE��M�M�����O�S6�9��ނ�"�rs������Kʇ��l����^����*fW��$��UWvUWm�z_�V}�ƻ��V�vc��]�]Ww{�n�ӭ+�{�G��v�}G�iC�^�޼����f}�ܤ�T��a�h�l���f���:�Z�i�����W����Z�Fo+=I=�6�ۛ���ai����vj{I�Q�1ٙ�)��<:�hO�[w��6��;fp�����E'>�\rr�T���ө��{{=s�7�w�l�����Ν���;y��� ��^d]��t��߱�����:.;_��r�{p����WO_�v�z��K7���u����[�ۼ�cw2�<��ww�ު���%TT<�y��ŏm2'��!���G ��?�)���#E�ɏ+F�G��Ǝ��_y��������?��\����w�x��?;9�\��ӯ�^h���r�˞��������_���|��-�m߻�w�����+?X|�����'�O����� 36 | endstream 37 | endobj 38 | 3 0 obj 39 | 2592 40 | endobj 41 | 4 0 obj 42 | [/ICCBased 2 0 R] 43 | endobj 44 | 5 0 obj 45 | << 46 | /Type /Metadata 47 | /Subtype /XML 48 | /Length 6 0 R 49 | >> 50 | stream 51 | 52 | 53 | 54 | 55 | 56 | x-unknown 57 | 2017-02-27T10:43:02Z 58 | 59 | 60 | Smart Communications 61 | 1.4 62 | 63 | 64 | Smart Communications 65 | 2017-02-27T10:43:02Z 66 | 2017-02-27T10:43:02Z 67 | 68 | 69 | 70 | 71 | 72 | 73 | endstream 74 | endobj 75 | 6 0 obj 76 | 811 77 | endobj 78 | 7 0 obj 79 | << /Length 8 0 R /Filter /FlateDecode >> 80 | stream 81 | x�3T0B]C ani�gaf����U��?G 82 | endstream 83 | endobj 84 | 8 0 obj 85 | 31 86 | endobj 87 | 9 0 obj 88 | << 89 | 90 | /Type /Page 91 | /MediaBox [0 0 612.283 790.866] 92 | /CropBox [0 0 612.283 790.866] 93 | /BleedBox [0 0 612.283 790.866] 94 | /TrimBox [0 0 612.283 790.866] 95 | /Parent 11 0 R 96 | /Contents 7 0 R 97 | >> 98 | 99 | endobj 100 | 10 0 obj 101 | << /ProcSet [/PDF /ImageB /ImageC /Text] >> 102 | 103 | endobj 104 | 11 0 obj 105 | << /Type /Pages 106 | /Count 1 107 | /Kids [9 0 R ] >> 108 | endobj 109 | 12 0 obj 110 | << 111 | /Type /Catalog 112 | /Pages 11 0 R 113 | /Lang (x-unknown) 114 | /Metadata 5 0 R 115 | /PageLabels 13 0 R 116 | >> 117 | 118 | endobj 119 | 14 0 obj 120 | << /ProcSet [/PDF /ImageB /ImageC /Text] /ColorSpace << /DefaultRGB 4 0 R >> 121 | >> 122 | 123 | endobj 124 | 13 0 obj 125 | << /Nums [0 << /S /D >> 126 | ] >> 127 | 128 | endobj 129 | xref 130 | 0 15 131 | 0000000000 65535 f 132 | 0000000015 00000 n 133 | 0000000135 00000 n 134 | 0000002812 00000 n 135 | 0000002832 00000 n 136 | 0000002865 00000 n 137 | 0000003765 00000 n 138 | 0000003784 00000 n 139 | 0000003889 00000 n 140 | 0000003907 00000 n 141 | 0000004132 00000 n 142 | 0000004193 00000 n 143 | 0000004252 00000 n 144 | 0000004465 00000 n 145 | 0000004367 00000 n 146 | trailer 147 | << 148 | /Root 12 0 R 149 | /Info 1 0 R 150 | /ID [ ] 151 | /Size 15 152 | >> 153 | startxref 154 | 4511 155 | %%EOF 156 | -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/fontsnotembedded.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/fontsnotembedded.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/fontsnotembeddedcid.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/fontsnotembeddedcid.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/formrotated.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/formrotated.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/gradientmask.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/gradientmask.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/hello2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/hello2.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/helloWorld.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/helloWorld.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/image.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/image.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/libreoffice.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/libreoffice.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/link.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/link.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/linkTagged.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/linkTagged.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/loop.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/loop.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/missingOBJR.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/missingOBJR.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/otf.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/otf.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/pattern.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/pattern.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/rotate.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/rotate.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/shading.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/shading.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/simpleh.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/simpleh.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/smask.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/smask.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/softmask.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/softmask.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/t1subset.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/t1subset.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/t1subset2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/t1subset2.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/t1subset3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/t1subset3.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/t1subset4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/t1subset4.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/taggedWorld.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/taggedWorld.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttcid1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttcid1.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttcid2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttcid2.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset10.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset11.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset11.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset12.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset12.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset13.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset13.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset2.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset3.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset5.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset6.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset7.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset8.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/ttsubset9.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/type0cff.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/type0cff.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/type0tt.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/type0tt.pdf -------------------------------------------------------------------------------- /test/resources/org/apache/fop/render/pdf/pdfbox/xform.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/xmlgraphics-fop-pdf-images/c5b01dcb781950de404eb9e8144bc01e8cf56ffc/test/resources/org/apache/fop/render/pdf/pdfbox/xform.pdf --------------------------------------------------------------------------------