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: PDFFunction.java 1785982 2017-03-08 15:15:06Z ssteiner $ */
19 
20 package org.apache.fop.pdf;
21 
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.List;
25 
26 import org.apache.fop.render.gradient.Function;
27 import org.apache.fop.render.gradient.Function.SubFunctionRenderer;
28 import org.apache.fop.render.gradient.GradientMaker;
29 import org.apache.fop.render.gradient.GradientMaker.DoubleFormatter;
30 
31 /**
32  * class representing a PDF Function.
33  *
34  * PDF Functions represent parameterized mathematical formulas and
35  * sampled representations with
36  * arbitrary resolution. Functions are used in two areas: device-dependent
37  * rasterization information for halftoning and transfer
38  * functions, and color specification for smooth shading (a PDF 1.3 feature).
39  *
40  * All PDF Functions have a FunctionType (0,2,3, or 4), a Domain, and a Range.
41  */
42 public class PDFFunction extends PDFObject {
43 
44     private final Function function;
45 
46     private final List<PDFFunction> pdfFunctions;
47 
48     /**
49      * create an complete Function object of Type 2, an Exponential Interpolation function.
50      *
51      * Use null for an optional object parameter if you choose not to use it.
52      * For optional int parameters, pass the default.
53      *
54      * @param domain List objects of Double objects.
55      * This is the domain of the function.
56      * See page 264 of the PDF 1.3 Spec.
57      * @param range List of Doubles that is the Range of the function.
58      * See page 264 of the PDF 1.3 Spec.
59      * @param cZero This is a vector of Double objects which defines the function result
60      * when x=0.
61      *
62      * This attribute is optional.
63      * It's described on page 268 of the PDF 1.3 spec.
64      * @param cOne This is a vector of Double objects which defines the function result
65      * when x=1.
66      *
67      * This attribute is optional.
68      * It's described on page 268 of the PDF 1.3 spec.
69      * @param interpolationExponentN This is the inerpolation exponent.
70      *
71      * This attribute is required.
72      * PDF Spec page 268
73      */
PDFFunction(List<Double> domain, List<Double> range, float[] cZero, float[] cOne, double interpolationExponentN)74     public PDFFunction(List<Double> domain, List<Double> range, float[] cZero, float[] cOne,
75             double interpolationExponentN) {
76         this(new Function(domain, range, cZero, cOne, interpolationExponentN));
77 
78     }
79 
80     @SuppressWarnings("unchecked")
PDFFunction(Function function)81     public PDFFunction(Function function) {
82         this(function, Collections.EMPTY_LIST);
83     }
84 
PDFFunction(Function function, List<PDFFunction> pdfFunctions)85     public PDFFunction(Function function, List<PDFFunction> pdfFunctions) {
86         this.function = function;
87         this.pdfFunctions = pdfFunctions;
88     }
89 
getFunction()90     public Function getFunction() {
91         return function;
92     }
93 
94     /**
95      * represent as PDF. Whatever the FunctionType is, the correct
96      * representation spits out. The sets of required and optional
97      * attributes are different for each type, but if a required
98      * attribute's object was constructed as null, then no error
99      * is raised. Instead, the malformed PDF that was requested
100      * by the construction is dutifully output.
101      * This policy should be reviewed.
102      *
103      * @return the PDF string.
104      */
toPDF()105     public byte[] toPDF() {
106         return toByteString();
107     }
108 
109 
toByteString()110     public byte[] toByteString() {
111         SubFunctionRenderer subFunctionRenderer = new SubFunctionRenderer() {
112 
113             public void outputFunction(StringBuilder out, int functionIndex) {
114                 out.append(pdfFunctions.get(functionIndex).referencePDF());
115             }
116         };
117         StringBuilder out = new StringBuilder();
118         GradientMaker.DoubleFormatter doubleFormatter = new DoubleFormatter() {
119 
120             public String formatDouble(double d) {
121                 return PDFNumber.doubleOut(d);
122             }
123         };
124         function.output(out, doubleFormatter, subFunctionRenderer);
125         return encode(out.toString());
126     }
127 
128     /** {@inheritDoc} */
contentEquals(PDFObject obj)129     protected boolean contentEquals(PDFObject obj) {
130         if (obj == null) {
131             return false;
132         }
133         if (obj == this) {
134             return true;
135         }
136         if (!(obj instanceof PDFFunction)) {
137             return false;
138         }
139         Function func = ((PDFFunction) obj).function;
140         if (function.getFunctionType() != func.getFunctionType()) {
141             return false;
142         }
143         if (function.getBitsPerSample() != func.getBitsPerSample()) {
144             return false;
145         }
146         if (function.getOrder() != func.getOrder()) {
147             return false;
148         }
149         if (function.getInterpolationExponentN() != func.getInterpolationExponentN()) {
150             return false;
151         }
152         if (function.getDomain() != null) {
153             if (!function.getDomain().equals(func.getDomain())) {
154                 return false;
155             }
156         } else if (func.getDomain() != null) {
157             return false;
158         }
159         if (function.getRange() != null) {
160             if (!function.getRange().equals(func.getRange())) {
161                 return false;
162             }
163         } else if (func.getRange() != null) {
164             return false;
165         }
166         if (function.getEncode() != null) {
167             if (!function.getEncode().equals(func.getEncode())) {
168                 return false;
169             }
170         } else if (func.getEncode() != null) {
171             return false;
172         }
173         if (!Arrays.equals(function.getCZero(), func.getCZero())) {
174             return false;
175         }
176         if (!Arrays.equals(function.getCOne(), func.getCOne())) {
177             return false;
178         }
179         if (!pdfFunctions.equals(((PDFFunction) obj).pdfFunctions)) {
180             return false;
181         }
182         if (function.getBounds() != null) {
183             if (!function.getBounds().equals(func.getBounds())) {
184                 return false;
185             }
186         } else if (func.getBounds() != null) {
187             return false;
188         }
189         return true;
190     }
191 
192 }
193