From: Jeremias Maerki Date: Thu, 27 Mar 2003 10:23:37 +0000 (+0000) Subject: This class represents a list of PDF filters to be applied when serializing the output... X-Git-Tag: Root_Temp_KnuthStylePageBreaking~1720 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=a532632413aa7fd9e9878b818d32b66d1f26ee08;p=xmlgraphics-fop.git This class represents a list of PDF filters to be applied when serializing the output of a PDF object. It also contains a method to build the filter lists from an Avalon Configuration object. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@196153 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/fop/pdf/PDFFilterList.java b/src/java/org/apache/fop/pdf/PDFFilterList.java new file mode 100644 index 000000000..54b97e16e --- /dev/null +++ b/src/java/org/apache/fop/pdf/PDFFilterList.java @@ -0,0 +1,318 @@ +/* + * $Id$ + * ============================================================================ + * The Apache Software License, Version 1.1 + * ============================================================================ + * + * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modifica- + * tion, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The end-user documentation included with the redistribution, if any, must + * include the following acknowledgment: "This product includes software + * developed by the Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, if + * and wherever such third-party acknowledgments normally appear. + * + * 4. The names "FOP" and "Apache Software Foundation" must not be used to + * endorse or promote products derived from this software without prior + * written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", nor may + * "Apache" appear in their name, without prior written permission of the + * Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ============================================================================ + * + * This software consists of voluntary contributions made by many individuals + * on behalf of the Apache Software Foundation and was originally created by + * James Tauber . For more information on the Apache + * Software Foundation, please see . + */ +package org.apache.fop.pdf; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; +import java.util.Map; + +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; + +/** + * This class represents a list of PDF filters to be applied when serializing + * the output of a PDF object. + */ +public class PDFFilterList { + + /** Key for the default filter */ + public static final String DEFAULT_FILTER = "default"; + /** Key for the filter used for normal content*/ + public static final String CONTENT_FILTER = "content"; + /** Key for the filter used for images */ + public static final String IMAGE_FILTER = "image"; + /** Key for the filter used for JPEG images */ + public static final String JPEG_FILTER = "jpeg"; + /** Key for the filter used for fonts */ + public static final String FONT_FILTER = "font"; + + private List filters = new java.util.ArrayList(); + + private boolean ignoreASCIIFilters = false; + + /** + * Default constructor. + *

+ * The flag for ignoring ASCII filters defaults to false. + */ + public PDFFilterList() { + //nop + } + + /** + * Use this descriptor if you want to have ASCII filters (such as ASCIIHex + * and ASCII85) ignored, for example, when encryption is active. + * @param ignoreASCIIFilters true if ASCII filters should be ignored + */ + public PDFFilterList(boolean ignoreASCIIFilters) { + this.ignoreASCIIFilters = ignoreASCIIFilters; + } + + /** + * Indicates whether the filter list is already initialized. + * @return true if more there are filters present + */ + public boolean isInitialized() { + return this.filters.size() > 0; + } + + /** + * Add a filter for compression of the stream. Filters are + * applied in the order they are added. This should always be a + * new instance of the particular filter of choice. The applied + * flag in the filter is marked true after it has been applied to the + * data. + * @param filter filter to add + */ + public void addFilter(PDFFilter filter) { + if (filter != null) { + if (this.ignoreASCIIFilters && filter.isASCIIFilter()) { + return; //ignore ASCII filter + } + filters.add(filter); + } + } + + /** + * Add a filter for compression of the stream by name. + * @param filterType name of the filter to add + */ + public void addFilter(String filterType) { + if (filterType == null) { + return; + } + if (filterType.equals("flate")) { + addFilter(new FlateFilter()); + } else if (filterType.equals("ascii-85")) { + if (this.ignoreASCIIFilters) { + return; //ignore ASCII filter + } + addFilter(new ASCII85Filter()); + } else if (filterType.equals("ascii-hex")) { + if (this.ignoreASCIIFilters) { + return; //ignore ASCII filter + } + addFilter(new ASCIIHexFilter()); + } else if (filterType.equals("")) { + return; + } else { + throw new IllegalArgumentException( + "Unsupported filter type in stream-filter-list: " + filterType); + } + } + + /** + * Checks the filter list for the DCT filter and adds it in the correct + * place if necessary. + */ + public void ensureDCTFilterInPlace() { + if (this.filters.size() == 0) { + addFilter(new DCTFilter()); + } else { + if (!(this.filters.get(0) instanceof DCTFilter)) { + this.filters.add(0, new DCTFilter()); + } + } + } + + /** + * Adds the default filters to this stream. + * @param filters Map of filters + * @param type which filter list to modify + */ + public void addDefaultFilters(Map filters, String type) { + List filterset = null; + if (filters != null) { + filterset = (List)filters.get(type); + if (filterset == null) { + filterset = (List)filters.get(DEFAULT_FILTER); + } + } + if (filterset == null || filterset.size() == 0) { + // built-in default to flate + //addFilter(new FlateFilter()); + } else { + for (int i = 0; i < filterset.size(); i++) { + String v = (String)filterset.get(i); + addFilter(v); + } + } + } + + /** + * Apply the filters to the data + * in the order given and return the /Filter and /DecodeParms + * entries for the stream dictionary. If the filters have already + * been applied to the data (either externally, or internally) + * then the dictionary entries are built and returned. + * @return a String representing the filter list + */ + protected String buildFilterDictEntries() { + if (filters != null && filters.size() > 0) { + List names = new java.util.ArrayList(); + List parms = new java.util.ArrayList(); + + // run the filters + for (int count = 0; count < filters.size(); count++) { + PDFFilter filter = (PDFFilter)filters.get(count); + // place the names in our local vector in reverse order + names.add(0, filter.getName()); + parms.add(0, filter.getDecodeParms()); + } + + // now build up the filter entries for the dictionary + return buildFilterEntries(names) + buildDecodeParms(parms); + } + return ""; + + } + + private String buildFilterEntries(List names) { + boolean needFilterEntry = false; + StringBuffer sb = new StringBuffer(64); + sb.append("/Filter [ "); + for (int i = 0; i < names.size(); i++) { + final String name = (String)names.get(i); + if (name.length() > 0) { + needFilterEntry = true; + sb.append(name); + sb.append(" "); + } + } + if (needFilterEntry) { + sb.append("]"); + return sb.toString(); + } else { + return ""; + } + } + + private String buildDecodeParms(List parms) { + StringBuffer sb = new StringBuffer(); + boolean needParmsEntry = false; + sb.append("/DecodeParms "); + + if (parms.size() > 1) { + sb.append("[ "); + } + for (int count = 0; count < parms.size(); count++) { + String s = (String)parms.get(count); + if (s != null) { + sb.append(s); + needParmsEntry = true; + } else { + sb.append("null"); + } + sb.append(" "); + } + if (parms.size() > 1) { + sb.append("]"); + } + if (needParmsEntry) { + return sb.toString(); + } else { + return ""; + } + } + + + /** + * Applies all registered filters as necessary. The method returns an + * OutputStream which will receive the filtered contents. + * @param stream raw data output stream + * @return OutputStream filtered output stream + * @throws IOException In case of an I/O problem + */ + public OutputStream applyFilters(OutputStream stream) throws IOException { + OutputStream out = stream; + if (filters != null) { + for (int count = filters.size() - 1; count >= 0; count--) { + PDFFilter filter = (PDFFilter)filters.get(count); + out = filter.applyFilter(out); + } + } + return out; + } + + /** + * Builds a filter map from an Avalon Configuration object. + * @param cfg the Configuration object + * @return Map the newly built filter map + * @throws ConfigurationException if a filter list is defined twice + */ + public static Map buildFilterMapFromConfiguration(Configuration cfg) + throws ConfigurationException { + Map filterMap = new java.util.HashMap(); + Configuration[] filterLists = cfg.getChildren("filterList"); + for (int i = 0; i < filterLists.length; i++) { + Configuration filters = filterLists[i]; + String type = filters.getAttribute("type", null); + Configuration[] filt = filters.getChildren("value"); + List filterList = new java.util.ArrayList(); + for (int j = 0; j < filt.length; j++) { + String name = filt[j].getValue(); + filterList.add(name); + } + + if (type == null) { + type = PDFFilterList.DEFAULT_FILTER; + } + if (filterMap.get(type) != null) { + throw new ConfigurationException("A filterList of type '" + + type + "' has already been defined"); + } + filterMap.put(type, filterList); + } + return filterMap; + } + +}