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