From ce7029487740792782e03b232f3b20ebe242b671 Mon Sep 17 00:00:00 2001 From: Matthias Reischenbacher Date: Wed, 10 Oct 2018 19:21:55 +0000 Subject: FOP-2818: add test case and fix additional bug with missing shadings and patterns git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1843494 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/fop/pdf/PDFResources.java | 20 ++- .../org/apache/fop/pdf/PDFLibraryTestSuite.java | 1 + .../org/apache/fop/pdf/PDFResourcesTestCase.java | 192 +++++++++++++++++++++ 3 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 fop-core/src/test/java/org/apache/fop/pdf/PDFResourcesTestCase.java diff --git a/fop-core/src/main/java/org/apache/fop/pdf/PDFResources.java b/fop-core/src/main/java/org/apache/fop/pdf/PDFResources.java index af2c27d9f..f98263fcb 100644 --- a/fop-core/src/main/java/org/apache/fop/pdf/PDFResources.java +++ b/fop-core/src/main/java/org/apache/fop/pdf/PDFResources.java @@ -254,10 +254,18 @@ public class PDFResources extends PDFDictionary { } if (parent != null) { xObjects.addAll(parent.xObjects); + for (PDFResourceContext c : parent.contexts) { + patterns.addAll(c.getPatterns()); + shadings.addAll(c.getShadings()); + gstates.addAll(c.getGStates()); + } } if (!shadings.isEmpty()) { - PDFDictionary dict = new PDFDictionary(this); + PDFDictionary dict = (PDFDictionary) get("Shading"); + if (dict == null) { + dict = new PDFDictionary(this); + } for (PDFShading shading : shadings) { dict.put(shading.getName(), shading); } @@ -265,7 +273,10 @@ public class PDFResources extends PDFDictionary { } if (!patterns.isEmpty()) { - PDFDictionary dict = new PDFDictionary(this); + PDFDictionary dict = (PDFDictionary) get("Pattern"); + if (dict == null) { + dict = new PDFDictionary(this); + } for (PDFPattern pattern : patterns) { dict.put(pattern.getName(), pattern); } @@ -291,7 +302,10 @@ public class PDFResources extends PDFDictionary { } if (!gstates.isEmpty()) { - PDFDictionary dict = new PDFDictionary(this); + PDFDictionary dict = (PDFDictionary) get("ExtGState"); + if (dict == null) { + dict = new PDFDictionary(this); + } for (PDFGState gstate : gstates) { dict.put(gstate.getName(), gstate); } diff --git a/fop-core/src/test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java b/fop-core/src/test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java index 7f408ae2c..2f5abd4d9 100644 --- a/fop-core/src/test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java +++ b/fop-core/src/test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java @@ -40,6 +40,7 @@ import org.junit.runners.Suite.SuiteClasses; PDFNumsArrayTestCase.class, PDFRectangleTestCase.class, PDFReferenceTestCase.class, + PDFResourcesTestCase.class, VersionTestCase.class, VersionControllerTestCase.class }) diff --git a/fop-core/src/test/java/org/apache/fop/pdf/PDFResourcesTestCase.java b/fop-core/src/test/java/org/apache/fop/pdf/PDFResourcesTestCase.java new file mode 100644 index 000000000..19953d781 --- /dev/null +++ b/fop-core/src/test/java/org/apache/fop/pdf/PDFResourcesTestCase.java @@ -0,0 +1,192 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id: PDFReferenceTestCase.java 1551536 2013-12-17 13:15:06Z vhennebert $ */ + +package org.apache.fop.pdf; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Test case for {@link PDFResources}. + */ +public class PDFResourcesTestCase { + + private AtomicInteger patternCount = new AtomicInteger(0); + private AtomicInteger objectNummerCount = new AtomicInteger(0); + + /** + * Test PDF resources output with color space, pattern and shading. + * @throws IOException + */ + @Test + public void testOutput() throws IOException { + PDFDocument pdfDoc = new PDFDocument(null); + PDFResources res = new PDFResources(pdfDoc); + res.addColorSpace(this.createColorSpace()); + PDFResourceContext context = new PDFResourceContext(res); + + context.addPattern(this.createPDFPattern(res, pdfDoc)); + context.addShading(this.createPDFShading(res, pdfDoc)); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + res.output(baos); + + String expectedShading = "/Shading << /Sh2 4 0 R >>"; + String expectedPattern = "/Pattern << /Pa1 2 0 R >>\n"; + String expectedColorspace = "/ColorSpace << /cs1 [/Separation /cs1 /DeviceRGB 1 0 R] >>\n"; + + String outputString = baos.toString(); + + assertTrue(outputString.contains(expectedShading)); + assertTrue(outputString.contains(expectedPattern)); + assertTrue(outputString.contains(expectedColorspace)); + } + + /** + * Test PDF resources output with color space, pattern and shading, + * if the PDF resource object has a parent resource object. + * @throws IOException + */ + @Test + public void testOutputWithParent() throws IOException { + PDFDocument pdfDoc = new PDFDocument(null); + PDFResources res = new PDFResources(pdfDoc); + PDFResources resParent = new PDFResources(pdfDoc); + res.setParentResources(resParent); + resParent.addColorSpace(this.createColorSpace()); + PDFResourceContext context = new PDFResourceContext(resParent); + + context.addPattern(this.createPDFPattern(resParent, pdfDoc)); + context.addShading(this.createPDFShading(resParent, pdfDoc)); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + res.output(baos); + + String expectedShading = "/Shading << /Sh2 4 0 R >>"; + String expectedPattern = "/Pattern << /Pa1 2 0 R >>\n"; + String expectedColorspace = "/ColorSpace << /cs1 [/Separation /cs1 /DeviceRGB 1 0 R] >>\n"; + + String outputString = baos.toString(); + + assertTrue(outputString.contains(expectedShading)); + assertTrue(outputString.contains(expectedPattern)); + assertTrue(outputString.contains(expectedColorspace)); + } + + /** + * Test PDF resources output with color space, pattern and shading, + * if the PDF resource object has a parent resource object, that also has + * color spaces, patterns and shadings. + * @throws IOException + */ + @Test + public void testOutputWithParent2() throws IOException { + PDFDocument pdfDoc = new PDFDocument(null); + PDFResources res = new PDFResources(pdfDoc); + PDFDictionary shadingDict = new PDFDictionary(); + shadingDict.put("Sh1-1718006973", new PDFReference("9 0")); + res.put("Shading", shadingDict); + PDFDictionary patternDict = new PDFDictionary(); + patternDict.put("Pa1-1718006973", new PDFReference("10 0")); + res.put("Pattern", patternDict); + PDFDictionary colorSpaceDict = new PDFDictionary(); + colorSpaceDict.put("DefaultRGB", new PDFReference("11 0")); + res.put("ColorSpace", colorSpaceDict); + PDFResources resParent = new PDFResources(pdfDoc); + res.setParentResources(resParent); + resParent.addColorSpace(this.createColorSpace()); + PDFResourceContext context = new PDFResourceContext(resParent); + + context.addPattern(this.createPDFPattern(resParent, pdfDoc)); + context.addShading(this.createPDFShading(resParent, pdfDoc)); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + res.output(baos); + + String outputString = baos.toString(); + + String expectedShading = "/Shading << /Sh1-1718006973 9 0 R /Sh2 4 0 R >>"; + String expectedPattern = "/Shading << /Sh1-1718006973 9 0 R /Sh2 4 0 R >>"; + String expectedColorspace = "/ColorSpace << /DefaultRGB 11 0 R" + + " /cs1 [/Separation /cs1 /DeviceRGB 1 0 R] >>"; + + assertTrue(outputString.contains(expectedShading)); + assertTrue(outputString.contains(expectedPattern)); + assertTrue(outputString.contains(expectedColorspace)); + } + + private PDFShading createPDFShading(PDFResources res, PDFDocument pdfDoc) { + List coords = new ArrayList(4); + coords.add(1d); + coords.add(1d); + coords.add(1d); + coords.add(1d); + PDFFunction pdfFunction = createPDFFunction(); + PDFDeviceColorSpace deviceColorspace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB); + PDFShading shading = new PDFShading(2, deviceColorspace, coords, pdfFunction); + shading.setObjectNumber(objectNummerCount.incrementAndGet()); + shading.setDocument(pdfDoc); + shading.setName("Sh" + patternCount.incrementAndGet()); + return shading; + } + + private PDFColorSpace createColorSpace() { + PDFFunction tintFunction = createPDFFunction(); + return new PDFSeparationColorSpace("cs1", tintFunction); + } + + private PDFFunction createPDFFunction() { + final Double zero = 0d; + final Double one = 1d; + List domain = Arrays.asList(new Double[] {zero, one}); + List range = Arrays.asList(new Double[] {zero, one, zero, one, zero, one}); + float[] cZero = new float[] {1f, 1f, 1f}; + float[] cOne = {0f, 0f, 0f}; + PDFFunction tintFunction = new PDFFunction(domain, range, cZero, cOne, 1.0d); + tintFunction.setObjectNumber(objectNummerCount.incrementAndGet()); + return tintFunction; + } + + private PDFPattern createPDFPattern(PDFResources res, PDFDocument pdfDoc) { + List bbox = new ArrayList(); + bbox.add(1d); + bbox.add(1d); + bbox.add(1d); + bbox.add(1d); + List theMatrix = new ArrayList(); + for (int i = 0; i < 6; i++) { + theMatrix.add(1d); + } + + PDFPattern pattern = new PDFPattern(res, 1, 1, 1, bbox, 1, 1, theMatrix, null, + new StringBuffer()); + pattern.setObjectNumber(objectNummerCount.incrementAndGet()); + pattern.setDocument(pdfDoc); + pattern.setName("Pa" + patternCount.incrementAndGet()); + return pattern; + } +} -- cgit v1.2.3