Package org.apache.batik.gvt.filter

Source Code of org.apache.batik.gvt.filter.BackgroundRable8Bit

/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved.        *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in  *
* the LICENSE file.                                                         *
*****************************************************************************/

package org.apache.batik.gvt.filter;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
import java.awt.image.BufferedImage;
import java.awt.image.renderable.RenderContext;
import java.awt.image.renderable.RenderableImage;

import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.gvt.CompositeGraphicsNode;
import org.apache.batik.gvt.GraphicsNodeRenderContext;
import org.apache.batik.ext.awt.image.renderable.Filter;
import org.apache.batik.gvt.filter.GraphicsNodeRable;
import org.apache.batik.gvt.filter.GraphicsNodeRableFactory;
import org.apache.batik.ext.awt.image.CompositeRule;
import org.apache.batik.ext.awt.image.PadMode;
import org.apache.batik.ext.awt.image.renderable.AbstractRable;
import org.apache.batik.ext.awt.image.renderable.CompositeRable8Bit;
import org.apache.batik.ext.awt.image.renderable.AffineRable8Bit;

/**
* This implementation of RenderableImage will render its input
* GraphicsNode into a BufferedImage upon invokation of one of its
* createRendering methods.
*
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
* @version $Id: BackgroundRable8Bit.java,v 1.6 2001/03/26 21:27:36 deweese Exp $
*/
public class BackgroundRable8Bit
    extends    AbstractRable {

    /**
     * GraphicsNode this image can render
     */
    private GraphicsNode node;

    /**
     * GraphicsNodeRenderContext currently associated with above GraphicsNode.
     */
    private GraphicsNodeRenderContext gnrc;

    /**
     * Returns the <tt>GraphicsNode</tt> rendered by this image
     */
    public GraphicsNode getGraphicsNode(){
        return node;
    }

    /**
     * Sets the <tt>GraphicsNode</tt> this image should render
     */
    public void setGraphicsNode(GraphicsNode node){
        if(node == null){
            throw new IllegalArgumentException();
        }

        this.node = node;
    }

    /**
     * @param node The GraphicsNode this image should represent
     */
    public BackgroundRable8Bit(GraphicsNode node, GraphicsNodeRenderContext rc){
        if(node == null)
            throw new IllegalArgumentException();

        this.gnrc = rc;
        this.node = node;
    }


    // This is a utilitiy method that unions the bounds of
    // cgn upto child (if child is null it does all children).
    // It unions them with init if provided.
    static Rectangle2D addBounds(CompositeGraphicsNode cgn,
                                 GraphicsNode child,
                                 GraphicsNodeRenderContext rc,
                                 Rectangle2D  init) {
        // System.out.println("CGN: " + cgn);
        // System.out.println("Child: " + child);

        List children = cgn.getChildren();
        Iterator i = children.iterator();
        Rectangle2D r2d = null;
        while (i.hasNext()) {
            GraphicsNode gn = (GraphicsNode)i.next();
            if (gn == child)
                break;

            // System.out.println("GN: " + gn);
            Rectangle2D cr2d = gn.getBounds(rc);
            AffineTransform at = gn.getTransform();
            if (at != null)
                cr2d = at.createTransformedShape(cr2d).getBounds2D();

            if (r2d == null) r2d = (Rectangle2D)cr2d.clone();
            r2d.add(cr2d);
        }

        if (r2d == null) {
            if (init == null)
                return CompositeGraphicsNode.VIEWPORT;

            return init;
        }

        if (init == null)
            return r2d;

        init.add(r2d);

        return init;
    }


    static Rectangle2D getViewportBounds(GraphicsNode gn,
                                         GraphicsNode child,
                                         GraphicsNodeRenderContext rc) {
        // See if background is enabled.
        Rectangle2D r2d = null;
        if (gn instanceof CompositeGraphicsNode) {
            CompositeGraphicsNode cgn = (CompositeGraphicsNode)gn;
            r2d = cgn.getBackgroundEnable();
        }

        if (r2d == null)
            // No background enable so check our parent's value.
            r2d = getViewportBounds(gn.getParent(), gn, rc);

        // No background for any ancester (error) return null
        if (r2d == null)
            return null;

        // Background enabled is set, but it has no fixed bounds set.
        if (r2d == CompositeGraphicsNode.VIEWPORT) {
            // If we don't have a child then just use our bounds.
            if (child == null)
                return gn.getPrimitiveBounds(rc);

            // gn must be composite so add all it's children's bounds
            // up to child.
            CompositeGraphicsNode cgn = (CompositeGraphicsNode)gn;
            return addBounds(cgn, child, rc, null);
        }

        // We have a partial bound from parent, so map it to gn's
        // coordinate system...
        AffineTransform at = gn.getTransform();
        if (at != null) {
            try {
                at = at.createInverse();
                r2d = at.createTransformedShape(r2d).getBounds2D();
            } catch (NoninvertibleTransformException nte) {
                // Degenerate case return null;
                r2d = null;
            }
        }

        if (child != null) {
            // Add our childrens bounds to it...
            CompositeGraphicsNode cgn = (CompositeGraphicsNode)gn;
            r2d = addBounds(cgn, child, rc, r2d);
        } else
            r2d.add(gn.getPrimitiveBounds(rc));

        return r2d;
    }

    // This does the leg work for getBounds().
    // It traverses the tree figuring out the bounds of the
    // background image.
    static Rectangle2D getBoundsRecursive(GraphicsNode gn,
                                          GraphicsNode child) {

        Rectangle2D r2d = null;
        if (gn == null)
            return null;

        if (gn instanceof CompositeGraphicsNode) {
            CompositeGraphicsNode cgn = (CompositeGraphicsNode)gn;
            // See if background is enabled.
            r2d = cgn.getBackgroundEnable();
        }

        // background has definite bounds so return them.
        if (r2d != null)
            return  r2d;

        // No background enable so check our parent's value.
        r2d = getBoundsRecursive(gn.getParent(), gn);

        // No background for any ancester (error) return null
        if (r2d == null)
            return null;

        // Our parent has background but no bounds (and we must
        // have been the first child so build the new bounds...
        if (r2d == CompositeGraphicsNode.VIEWPORT)
            return r2d;

        AffineTransform at = gn.getTransform();
        if (at != null) {
            try {
                // background has a definite bound so map it to gn's
                // coordinate system...
                at = at.createInverse();
                r2d = at.createTransformedShape(r2d).getBounds2D();
            } catch (NoninvertibleTransformException nte) {
                // Degenerate case return null;
                r2d = null;
            }
        }

        return r2d;
    }

    /**
     * Returns the bounds of this Rable in the user coordinate system.
     */
    public Rectangle2D getBounds2D() {
        // System.out.println("GetBounds2D called");
        Rectangle2D r2d = getBoundsRecursive(node, null);

        if (r2d == CompositeGraphicsNode.VIEWPORT)
            r2d = getViewportBounds(node, null, getGraphicsNodeRenderContext());

        return r2d;
    }

    /**
     * Returns a filter that represents the background image
     * for <tt>child</tt>.
     */
    public Filter getBackground(GraphicsNode gn,
                                GraphicsNode child,
                                GraphicsNodeRenderContext rc,
                                Rectangle2D aoi) {
        if (gn == null) {
            throw new IllegalArgumentException
                ("BackgroundImage requested yet no parent has " +
                 "'enable-background:new'");
        }

        Rectangle2D r2d = null;
        if (gn instanceof CompositeGraphicsNode) {
            CompositeGraphicsNode cgn = (CompositeGraphicsNode)gn;
            r2d = cgn.getBackgroundEnable();
        }

        Vector srcs = new Vector();
        if (r2d == null) {
            Rectangle2D paoi = aoi;
            AffineTransform at = gn.getTransform();
            if (at != null)
                paoi = at.createTransformedShape(aoi).getBounds2D();
            Filter f = getBackground(gn.getParent(), gn, rc, paoi);
            if ((f != null) && f.getBounds2D().intersects(aoi)) {
                srcs.add(f);
            }
        }

        GraphicsNodeRableFactory gnrf;
         gnrf = rc.getGraphicsNodeRableFactory();

        if (child != null) {
            CompositeGraphicsNode cgn = (CompositeGraphicsNode)gn;
            List children = cgn.getChildren();
            Iterator i = children.iterator();
            while (i.hasNext()) {
                GraphicsNode childGN = (GraphicsNode)i.next();
                // System.out.println("Parent: "      + cgn +
                //                    "\n  Child: "   + child +
                //                    "\n  ChildGN: " + childGN);
                if (childGN == child)
                    break;

                Rectangle2D cbounds = childGN.getBounds(rc);
                // System.out.println("Child : " + childGN);
                // System.out.println("Bounds: " + cbounds);
                // System.out.println("      : " + aoi);

                AffineTransform at = childGN.getTransform();
                if (at != null)
                    cbounds = at.createTransformedShape(cbounds).getBounds2D();


                if (aoi.intersects(cbounds)) {
                    GraphicsNodeRable gnr;
                    gnr  = gnrf.createGraphicsNodeRable(childGN, rc);
                    gnr.setUsePrimitivePaint(false);
                    srcs.add(gnr);
                }
            }
        }

        if (srcs.size() == 0)
            return null;

        Filter ret = null;
        if (srcs.size() == 1)
            ret = (Filter)srcs.get(0);
        else
            ret = new CompositeRable8Bit(srcs, CompositeRule.OVER, false);

        if (child != null) {
            // We are returning the filter to child so make
            // sure to map the filter from the parents user space
            // to the childs user space...

            AffineTransform at = child.getTransform();
            if (at != null) {
                try {
                    at = at.createInverse();
                    ret = new AffineRable8Bit(ret, at);
                } catch (NoninvertibleTransformException nte) {
                    ret = null;
                }
            }
        }

        return ret;
    }

    /**
     * Returns true if successive renderings (that is, calls to
     * createRendering() or createScaledRendering()) with the same arguments
     * may produce different results.  This method may be used to
     * determine whether an existing rendering may be cached and
     * reused.  It is always safe to return true.
     */
    public boolean isDynamic(){
        return false;
    }

    /**
     * Creates a RenderedImage that represented a rendering of this image
     * using a given RenderContext.  This is the most general way to obtain a
     * rendering of a RenderableImage.
     *
     * <p> The created RenderedImage may have a property identified
     * by the String HINTS_OBSERVED to indicate which RenderingHints
     * (from the RenderContext) were used to create the image.
     * In addition any RenderedImages
     * that are obtained via the getSources() method on the created
     * RenderedImage may have such a property.
     *
     * @param renderContext the RenderContext to use to produce the rendering.
     * @return a RenderedImage containing the rendered data.
     */
    public RenderedImage createRendering(RenderContext renderContext){

        GraphicsNodeRenderContext gnrc;
        gnrc = GraphicsNodeRenderContext.
            getGraphicsNodeRenderContext(renderContext);

        Rectangle2D r2d = getBounds2D();

        // System.out.println("Rendering called");

        Shape aoi = renderContext.getAreaOfInterest();
        if (aoi != null) {
            Rectangle2D aoiR2d = aoi.getBounds2D();
            if (r2d.intersects(aoiR2d) == false)
                return null;

            // System.out.println("R2d: " + r2d);
            // System.out.println("AOI: " + aoiR2d);

            Rectangle2D.intersect(r2d, aoiR2d, r2d);
        }

        Filter f = getBackground(node, null, gnrc, r2d);

        if ( f == null)
            return null;

        RenderedImage ri = f.createRendering(renderContext);
        // org.ImageDisplay.showImage("BG: ", ri);
        return ri;
    }

    protected void setGraphicsNodeRenderContext(GraphicsNodeRenderContext rc) {
        this.gnrc = rc;
    }

    protected GraphicsNodeRenderContext getGraphicsNodeRenderContext() {
        return gnrc;
    }


}
TOP

Related Classes of org.apache.batik.gvt.filter.BackgroundRable8Bit

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.