123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- /*
- * 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.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.
- */
- 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 precompressed content */
- public static final String PRECOMPRESSED_FILTER = "precompressed";
- /** 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 TIFF images */
- public static final String TIFF_FILTER = "tiff";
- /** Key for the filter used for fonts */
- public static final String FONT_FILTER = "font";
- /** 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.
- * <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.
- * @param ignoreASCIIFilters true if ASCII filters should be ignored
- */
- public PDFFilterList(boolean ignoreASCIIFilters) {
- this.ignoreASCIIFilters = ignoreASCIIFilters;
- }
-
- /**
- * 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.
- * @return true if all filters are disabled
- */
- public boolean isDisableAllFilters() {
- return this.disableAllFilters;
- }
-
- /**
- * 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("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.
- * @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.
- * @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.
- * @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.
- * @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.
- * @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;
- }
- }
|