All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.intarsys.pdf.pd.DefaultAppearance Maven / Gradle / Ivy

Go to download

This is a fork of http://sourceforge.net/projects/jpodlib/ as development seems to be frozen. We're providing some bug fixes along with deployments to maven.

There is a newer version: 2.0
Show newest version
/*
 * Copyright (c) 2007, intarsys consulting GmbH
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * - 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.
 *
 * - Neither the name of intarsys nor the names of its contributors may be used
 *   to endorse or promote products derived from this software without specific
 *   prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, 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.
 */
package de.intarsys.pdf.pd;

import de.intarsys.pdf.content.CSContent;
import de.intarsys.pdf.content.CSDeviceBasedInterpreter;
import de.intarsys.pdf.content.CSOperation;
import de.intarsys.pdf.content.CSOperators;
import de.intarsys.pdf.content.CSVirtualDevice;
import de.intarsys.pdf.cos.COSDictionary;
import de.intarsys.pdf.cos.COSFixed;
import de.intarsys.pdf.cos.COSInteger;
import de.intarsys.pdf.cos.COSName;
import de.intarsys.pdf.cos.COSObject;
import de.intarsys.pdf.font.PDFont;
import de.intarsys.pdf.font.PDFontTools;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * A internal representation of the parsed {@link CSContent} for the default
 * appearance content stream fragment in a {@link PDAcroFormField}.
 */
public class DefaultAppearance {

    /**
     * An embedded "device" to gather information from the default appearance
     * string.
     */
    public class DefaultAppearanceDevice extends CSVirtualDevice {

        @Override
        protected void basicSetNonStrokeColorSpace(PDColorSpace colorSpace) {
            nonStrokeColorSpace = colorSpace;
        }

        @Override
        protected void basicSetNonStrokeColorValues(float[] values) {
            nonStrokeColorValues = values;
        }

        @Override
        protected void basicSetStrokeColorSpace(PDColorSpace colorSpace) {
            strokeColorSpace = colorSpace;
        }

        @Override
        protected void basicSetStrokeColorValues(float[] values) {
            strokeColorValues = values;
        }

        @Override
        public void textSetFont(COSName name, PDFont paramFont, float size) {
            fontName = name;
            fontSize = size;
        }
    }

    private PDAcroFormNode node;

    protected COSName fontName;

    protected float fontSize;

    protected float[] nonStrokeColorValues;

    protected PDColorSpace nonStrokeColorSpace;

    protected float[] strokeColorValues;

    protected PDColorSpace strokeColorSpace;

    public DefaultAppearance(PDAcroFormNode node) {
        super();
        this.node = node;
        CSDeviceBasedInterpreter interpreter;
        interpreter = new CSDeviceBasedInterpreter(null, new DefaultAppearanceDevice());
        interpreter.process(node.getDefaultAppearanceContent(), node.getAcroForm().getDefaultResources());
    }

    protected COSName addFontResource(PDAcroForm form, PDFont font) {
        PDResources resources = form.getDefaultResources();
        if (resources == null) {
            resources = (PDResources) PDResources.META.createNew();
            form.setDefaultResources(resources);
        }
        COSDictionary fontResources = resources.cosGetResources(PDResources.CN_RT_Font);
        if (fontResources == null) {
            fontResources = resources.cosInitResources(PDResources.CN_RT_Font);
        }
        for (Iterator i = fontResources.keySet().iterator(); i.hasNext(); ) {
            COSName fontKey = (COSName) i.next();
            COSObject fontValue = fontResources.get(fontKey);
            if (fontValue.equals(font.cosGetObject())) {
                return fontKey;
            }
        }
        return resources.createFontResource(font);
    }

    protected COSName addFontResource(PDFont font) {
        return addFontResource(node.getAcroForm(), font);
    }

    protected void cleanupFontResources(PDAcroForm form) {
        // collect used font keys
        Set referencedKeys = getReferencedFontKeys(form);

        // determine overhead
        Set overhead = new HashSet();
        COSDictionary fontDict = form.getDefaultResources().cosGetResources(PDResources.CN_RT_Font);
        if (fontDict != null) {
            for (Iterator i = fontDict.keySet().iterator(); i.hasNext(); ) {
                COSName key = (COSName) i.next();
                if (!referencedKeys.contains(key)) {
                    overhead.add(key);
                }
            }
            // remove overhead
            for (Iterator i = overhead.iterator(); i.hasNext(); ) {
                COSName key = (COSName) i.next();
                fontDict.remove(key);
            }
        }
    }

    protected void collectDefaultAppearanceFonts(PDAcroFormNode pNode, Set keys) {
        // check usage in default appearance
        COSName fontKey = pNode.getDefaultAppearanceFontName();
        if (fontKey != null) {
            keys.add(fontKey);
        }

        //
        if (pNode.getGenericChildren() == null) {
            return;
        }
        for (Iterator i = pNode.getGenericChildren().iterator(); i.hasNext(); ) {
            PDAcroFormNode child = (PDAcroFormNode) i.next();
            collectDefaultAppearanceFonts(child, keys);
        }
    }

    protected void contentReplaceColor(float[] color) {
        CSContent appearance = node.getDefaultAppearanceContent();
        CSContent content = CSContent.createNew();
        CSOperation op = null;
        switch (color.length) {
            case 1: {
                op = new CSOperation(CSOperators.CSO_g);
                break;
            }
            case 3: {
                op = new CSOperation(CSOperators.CSO_rg);
                break;
            }
            case 4: {
                op = new CSOperation(CSOperators.CSO_k);
                break;
            }
        }
        for (int index = 0; index < color.length; index++) {
            op.addOperand(COSFixed.create(color[index]));
        }
        if (appearance == null) {
            content.addOperation(op);
        } else {
            // copy / modify stream
            int len = appearance.size();
            boolean replaced = false;
            for (int i = 0; i < len; i++) {
                CSOperation operation = appearance.getOperation(i);
                if (operation.matchesOperator(CSOperators.CSO_g)
                    || operation.matchesOperator(CSOperators.CSO_rg)
                    || operation.matchesOperator(CSOperators.CSO_k)) {
                    content.addOperation(op);
                    replaced = true;
                } else {
                    content.addOperation(operation);
                }
            }
            if (!replaced) {
                content.addOperation(op);
            }
        }
        node.setDefaultAppearanceContent(content);
    }

    protected void contentReplaceFont(COSName pFontName) {
        CSContent appearance = node.getDefaultAppearanceContent();
        CSContent content = CSContent.createNew();
        CSOperation op = new CSOperation(CSOperators.CSO_Tf);
        op.addOperand(pFontName);
        op.addOperand(COSInteger.create(0));
        if (appearance == null) {
            content.addOperation(op);
        } else {
            // copy / modify stream
            int len = appearance.size();
            boolean replaced = false;
            for (int i = 0; i < len; i++) {
                CSOperation operation = appearance.getOperation(i);
                if (operation.matchesOperator(CSOperators.CSO_Tf)) {
                    if (operation.operandSize() >= 2) {
                        op.setOperand(1, operation.getOperand(1));
                    }
                    content.addOperation(op);
                    replaced = true;
                } else {
                    content.addOperation(operation);
                }
            }
            if (!replaced) {
                content.addOperation(op);
            }
        }
        node.setDefaultAppearanceContent(content);
    }

    protected void contentReplaceSize(float pFontSize) {
        CSContent appearance = node.getDefaultAppearanceContent();
        CSContent content = CSContent.createNew();
        CSOperation op = new CSOperation(CSOperators.CSO_Tf);
        op.addOperand(COSName.create("Helv")); //$NON-NLS-1$
        op.addOperand(COSFixed.create(pFontSize));
        if (appearance == null) {
            content.addOperation(op);
        } else {
            // copy / modify stream
            int len = appearance.size();
            boolean replaced = false;
            for (int i = 0; i < len; i++) {
                CSOperation operation = appearance.getOperation(i);
                if (operation.matchesOperator(CSOperators.CSO_Tf)) {
                    if (operation.operandSize() >= 1) {
                        op.setOperand(0, operation.getOperand(0));
                    }
                    content.addOperation(op);
                    replaced = true;
                } else {
                    content.addOperation(operation);
                }
            }
            if (!replaced) {
                content.addOperation(op);
            }
        }
        node.setDefaultAppearanceContent(content);
    }

    public PDFont getFont() {
        PDResources resources = node.getAcroForm().getDefaultResources();
        if (resources == null) {
            return null;
        }
        return PDFontTools.getFont(resources, getFontName());
    }

    /**
     * parse the requested font color from the default appearance string
     *
     * @return the font color used in the default appearance
     * @throws IllegalStateException
     */
    public float[] getFontColorValues() {
        return nonStrokeColorValues;
    }

    public COSName getFontName() {
        return fontName;
    }

    public float getFontSize() {
        return fontSize;
    }

    public PDAcroFormNode getNode() {
        return node;
    }

    protected Set getReferencedFontKeys(PDAcroForm form) {
        Set referencedKeys = new HashSet();
        collectDefaultAppearanceFonts(form, referencedKeys);
        return referencedKeys;
    }

    public void setFont(PDFont font) {
        COSName cosFontName = addFontResource(font);
        setFontName(cosFontName);
        cleanupFontResources(node.getAcroForm());
    }

    public void setFontColorValues(float[] color) {
        contentReplaceColor(color);
        nonStrokeColorValues = color;
    }

    public void setFontName(COSName pFontName) {
        contentReplaceFont(pFontName);
        fontName = pFontName;
    }

    public void setFontSize(float pFontSize) {
        contentReplaceSize(pFontSize);
        fontSize = pFontSize;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy