| /* |
| * 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$ */ |
| |
| package org.apache.fop.pdf; |
| |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.apache.fop.render.gradient.Function; |
| import org.apache.fop.render.gradient.Function.SubFunctionRenderer; |
| import org.apache.fop.render.gradient.GradientMaker; |
| import org.apache.fop.render.gradient.GradientMaker.DoubleFormatter; |
| |
| /** |
| * class representing a PDF Function. |
| * |
| * PDF Functions represent parameterized mathematical formulas and |
| * sampled representations with |
| * arbitrary resolution. Functions are used in two areas: device-dependent |
| * rasterization information for halftoning and transfer |
| * functions, and color specification for smooth shading (a PDF 1.3 feature). |
| * |
| * All PDF Functions have a FunctionType (0,2,3, or 4), a Domain, and a Range. |
| */ |
| public class PDFFunction extends PDFObject { |
| |
| private final Function function; |
| |
| private final List<PDFFunction> pdfFunctions; |
| |
| /** |
| * create an complete Function object of Type 2, an Exponential Interpolation function. |
| * |
| * Use null for an optional object parameter if you choose not to use it. |
| * For optional int parameters, pass the default. |
| * |
| * @param domain List objects of Double objects. |
| * This is the domain of the function. |
| * See page 264 of the PDF 1.3 Spec. |
| * @param range List of Doubles that is the Range of the function. |
| * See page 264 of the PDF 1.3 Spec. |
| * @param cZero This is a vector of Double objects which defines the function result |
| * when x=0. |
| * |
| * This attribute is optional. |
| * It's described on page 268 of the PDF 1.3 spec. |
| * @param cOne This is a vector of Double objects which defines the function result |
| * when x=1. |
| * |
| * This attribute is optional. |
| * It's described on page 268 of the PDF 1.3 spec. |
| * @param interpolationExponentN This is the inerpolation exponent. |
| * |
| * This attribute is required. |
| * PDF Spec page 268 |
| */ |
| public PDFFunction(List<Double> domain, List<Double> range, float[] cZero, float[] cOne, |
| double interpolationExponentN) { |
| this(new Function(domain, range, cZero, cOne, interpolationExponentN)); |
| |
| } |
| |
| @SuppressWarnings("unchecked") |
| public PDFFunction(Function function) { |
| this(function, Collections.EMPTY_LIST); |
| } |
| |
| public PDFFunction(Function function, List<PDFFunction> pdfFunctions) { |
| this.function = function; |
| this.pdfFunctions = pdfFunctions; |
| } |
| |
| public Function getFunction() { |
| return function; |
| } |
| |
| /** |
| * represent as PDF. Whatever the FunctionType is, the correct |
| * representation spits out. The sets of required and optional |
| * attributes are different for each type, but if a required |
| * attribute's object was constructed as null, then no error |
| * is raised. Instead, the malformed PDF that was requested |
| * by the construction is dutifully output. |
| * This policy should be reviewed. |
| * |
| * @return the PDF string. |
| */ |
| public byte[] toPDF() { |
| return toByteString(); |
| } |
| |
| |
| public byte[] toByteString() { |
| SubFunctionRenderer subFunctionRenderer = new SubFunctionRenderer() { |
| |
| public void outputFunction(StringBuilder out, int functionIndex) { |
| out.append(pdfFunctions.get(functionIndex).referencePDF()); |
| } |
| }; |
| StringBuilder out = new StringBuilder(); |
| GradientMaker.DoubleFormatter doubleFormatter = new DoubleFormatter() { |
| |
| public String formatDouble(double d) { |
| return PDFNumber.doubleOut(d); |
| } |
| }; |
| function.output(out, doubleFormatter, subFunctionRenderer); |
| return encode(out.toString()); |
| } |
| |
| /** {@inheritDoc} */ |
| protected boolean contentEquals(PDFObject obj) { |
| if (obj == null) { |
| return false; |
| } |
| if (obj == this) { |
| return true; |
| } |
| if (!(obj instanceof PDFFunction)) { |
| return false; |
| } |
| Function func = ((PDFFunction) obj).function; |
| if (function.getFunctionType() != func.getFunctionType()) { |
| return false; |
| } |
| if (function.getBitsPerSample() != func.getBitsPerSample()) { |
| return false; |
| } |
| if (function.getOrder() != func.getOrder()) { |
| return false; |
| } |
| if (function.getInterpolationExponentN() != func.getInterpolationExponentN()) { |
| return false; |
| } |
| if (function.getDomain() != null) { |
| if (!function.getDomain().equals(func.getDomain())) { |
| return false; |
| } |
| } else if (func.getDomain() != null) { |
| return false; |
| } |
| if (function.getRange() != null) { |
| if (!function.getRange().equals(func.getRange())) { |
| return false; |
| } |
| } else if (func.getRange() != null) { |
| return false; |
| } |
| if (function.getEncode() != null) { |
| if (!function.getEncode().equals(func.getEncode())) { |
| return false; |
| } |
| } else if (func.getEncode() != null) { |
| return false; |
| } |
| if (!Arrays.equals(function.getCZero(), func.getCZero())) { |
| return false; |
| } |
| if (!Arrays.equals(function.getCOne(), func.getCOne())) { |
| return false; |
| } |
| if (!pdfFunctions.equals(((PDFFunction) obj).pdfFunctions)) { |
| return false; |
| } |
| if (function.getBounds() != null) { |
| if (!function.getBounds().equals(func.getBounds())) { |
| return false; |
| } |
| } else if (func.getBounds() != null) { |
| return false; |
| } |
| return true; |
| } |
| |
| } |