/*
 * 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: PDFFilterList.java 1761026 2016-09-16 12:50:43Z ssteiner $ */

package org.apache.fop.pdf;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import java.util.List;
import java.util.Map;

This class represents a list of PDF filters to be applied when serializing the output of a PDF object.
/** * 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
/** Key for the default filter */
public static final String DEFAULT_FILTER = "default";
Key for the filter used for normal content
/** Key for the filter used for normal content*/
public static final String CONTENT_FILTER = "content";
Key for the filter used for precompressed content
/** Key for the filter used for precompressed content */
public static final String PRECOMPRESSED_FILTER = "precompressed";
Key for the filter used for images
/** Key for the filter used for images */
public static final String IMAGE_FILTER = "image";
Key for the filter used for JPEG images
/** Key for the filter used for JPEG images */
public static final String JPEG_FILTER = "jpeg";
Key for the filter used for TIFF images
/** Key for the filter used for TIFF images */
public static final String TIFF_FILTER = "tiff";
Key for the filter used for fonts
/** Key for the filter used for fonts */
public static final String FONT_FILTER = "font";
Key for the filter used for metadata
/** Key for the filter used for metadata */
public static final String METADATA_FILTER = "metadata"; private List<PDFFilter> filters = new java.util.ArrayList<PDFFilter>(); private boolean ignoreASCIIFilters; private boolean disableAllFilters;
Default constructor.

The flag for ignoring ASCII filters defaults to false.

/** * Default constructor. * <p> * 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.
Params:
  • ignoreASCIIFilters – true if ASCII filters should be ignored
/** * 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; }
Used to disable all filters.
Params:
  • value – true if all filters shall be disabled
/** * Used to disable all filters. * @param value true if all filters shall be disabled */
public void setDisableAllFilters(boolean value) { this.disableAllFilters = value; }
Returns true if all filters are disabled.
Returns:true if all filters are disabled
/** * Returns true if all filters are disabled. * @return true if all filters are disabled */
public boolean isDisableAllFilters() { return this.disableAllFilters; }
Indicates whether the filter list is already initialized.
Returns:true if more there are filters present
/** * 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.
Params:
  • filter – filter to add
/** * 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.
Params:
  • filterType – name of the filter to add
/** * 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("null")) { addFilter(new NullFilter()); } 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 filter and adds it in the correct place if necessary.
Params:
  • pdfFilter – the filter to check / add
/** * Checks the filter list for the filter and adds it in the correct * place if necessary. * @param pdfFilter the filter to check / add */
public void ensureFilterInPlace(PDFFilter pdfFilter) { if (this.filters.size() == 0) { addFilter(pdfFilter); } else { if (!(this.filters.get(0).equals(pdfFilter))) { this.filters.add(0, pdfFilter); } } }
Adds the default filters to this stream.
Params:
  • filters – Map of filters
  • type – which filter list to modify
/** * 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) { if (METADATA_FILTER.equals(type)) { //XMP metadata should not be embedded in clear-text addFilter(new NullFilter()); return; } 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) { if (JPEG_FILTER.equals(type)) { //JPEG is already well compressed addFilter(new NullFilter()); } else if (TIFF_FILTER.equals(type)) { //CCITT-encoded images are already well compressed addFilter(new NullFilter()); } else if (PRECOMPRESSED_FILTER.equals(type)) { //precompressed content doesn't need further compression addFilter(new NullFilter()); } else { // built-in default to flate addFilter(new FlateFilter()); } } else { for (Object aFilterset : filterset) { String v = (String) aFilterset; addFilter(v); } } } List<PDFFilter> getFilters() { return Collections.unmodifiableList(filters); }
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.
Returns:a String representing the filter list
/** * 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.size() > 0) { List names = new java.util.ArrayList(); List parms = new java.util.ArrayList(); int nonNullParams = populateNamesAndParms(names, parms); // now build up the filter entries for the dictionary return buildFilterEntries(names) + (nonNullParams > 0 ? buildDecodeParms(parms) : ""); } return ""; }
Apply the filters to the data in the order given and add the /Filter and /DecodeParms entries to the stream dictionary. If the filters have already been applied to the data (either externally, or internally) then the dictionary entries added.
Params:
  • dict – the PDFDictionary to set the entries on
/** * Apply the filters to the data * in the order given and add the /Filter and /DecodeParms * entries to the stream dictionary. If the filters have already * been applied to the data (either externally, or internally) * then the dictionary entries added. * @param dict the PDFDictionary to set the entries on */
protected void putFilterDictEntries(PDFDictionary dict) { if (filters.size() > 0) { List names = new java.util.ArrayList(); List parms = new java.util.ArrayList(); populateNamesAndParms(names, parms); // now build up the filter entries for the dictionary putFilterEntries(dict, names); putDecodeParams(dict, parms); } } private int populateNamesAndParms(List names, List parms) { // run the filters int nonNullParams = 0; for (PDFFilter filter : filters) { // place the names in our local vector in reverse order if (filter.getName().length() > 0) { names.add(0, filter.getName()); PDFObject param = filter.getDecodeParms(); if (param != null) { parms.add(0, param); nonNullParams++; } else { parms.add(0, null); } } } return nonNullParams; } private String buildFilterEntries(List names) { int filterCount = 0; StringBuffer sb = new StringBuffer(64); for (Object name1 : names) { final String name = (String) name1; if (name.length() > 0) { filterCount++; sb.append(name); sb.append(" "); } } if (filterCount > 0) { if (filterCount > 1) { return "/Filter [ " + sb + "]"; } else { return "/Filter " + sb; } } else { return ""; } } private void putFilterEntries(PDFDictionary dict, List names) { PDFArray array = new PDFArray(dict); for (Object name1 : names) { final String name = (String) name1; if (name.length() > 0) { array.add(new PDFName(name)); } } if (array.length() > 0) { if (array.length() > 1) { dict.put("Filter", array); } else { dict.put("Filter", array.get(0)); } } } private String buildDecodeParms(List parms) { StringBuffer sb = new StringBuffer(); boolean needParmsEntry = false; sb.append("\n/DecodeParms "); if (parms.size() > 1) { sb.append("[ "); } for (Object parm : parms) { String s = (String) parm; 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 ""; } } private void putDecodeParams(PDFDictionary dict, List parms) { boolean needParmsEntry = false; PDFArray array = new PDFArray(dict); for (Object obj : parms) { if (obj != null) { array.add(obj); needParmsEntry = true; } else { array.add(null); } } if (array.length() > 0 & needParmsEntry) { if (array.length() > 1) { dict.put("DecodeParms", array); } else { dict.put("DecodeParms", array.get(0)); } } }
Applies all registered filters as necessary. The method returns an OutputStream which will receive the filtered contents.
Params:
  • stream – raw data output stream
Throws:
Returns:OutputStream filtered output stream
/** * 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 (!isDisableAllFilters()) { for (int count = filters.size() - 1; count >= 0; count--) { PDFFilter filter = filters.get(count); out = filter.applyFilter(out); } } return out; } }