- /*
- * @(#)RenderableImageOp.java 1.11 00/02/02
- *
- * Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the proprietary information of Sun Microsystems, Inc.
- * Use is subject to license terms.
- *
- */
-
- /* ********************************************************************
- **********************************************************************
- **********************************************************************
- *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
- *** As an unpublished work pursuant to Title 17 of the United ***
- *** States Code. All rights reserved. ***
- **********************************************************************
- **********************************************************************
- **********************************************************************/
-
- package java.awt.image.renderable;
- import java.awt.geom.AffineTransform;
- import java.awt.geom.Rectangle2D;
- import java.awt.image.RenderedImage;
- import java.awt.RenderingHints;
- import java.util.Hashtable;
- import java.util.Vector;
-
- /**
- * This class handles the renderable aspects of an operation with help
- * from its associated instance of a ContextualRenderedImageFactory.
- */
- public class RenderableImageOp implements RenderableImage {
-
- /** A ParameterBlock containing source and parameters. */
- ParameterBlock paramBlock;
-
- /** The associated ContextualRenderedImageFactory. */
- ContextualRenderedImageFactory myCRIF;
-
- /** The bounding box of the results of this RenderableImageOp. */
- Rectangle2D boundingBox;
-
-
- /**
- * Constructs a RenderedImageOp given a
- * ContextualRenderedImageFactory object, and
- * a ParameterBlock containing RenderableImage sources and other
- * parameters. Any RenderedImage sources referenced by the
- * ParameterBlock will be ignored.
- *
- * @param CRIF a ContextualRenderedImageFactory object
- * @param paramBlock a ParameterBlock containing this operation's source
- * images and other parameters necessary for the operation
- * to run.
- */
- public RenderableImageOp(ContextualRenderedImageFactory CRIF,
- ParameterBlock paramBlock) {
- this.myCRIF = CRIF;
- this.paramBlock = (ParameterBlock) paramBlock.clone();
- }
-
- /**
- * Returns a vector of RenderableImages that are the sources of
- * image data for this RenderableImage. Note that this method may
- * return an empty vector, to indicate that the image has no sources,
- * or null, to indicate that no information is available.
- *
- * @return a (possibly empty) Vector of RenderableImages, or null.
- */
- public Vector getSources() {
- return getRenderableSources();
- }
-
- private Vector getRenderableSources() {
- Vector sources = null;
-
- if (paramBlock.getNumSources() > 0) {
- sources = new Vector();
- int i = 0;
- while (i < paramBlock.getNumSources()) {
- Object o = paramBlock.getSource(i);
- if (o instanceof RenderableImage) {
- sources.add((RenderableImage)o);
- i++;
- } else {
- break;
- }
- }
- }
- return sources;
- }
-
- /**
- * Gets a property from the property set of this image.
- * If the property name is not recognized, java.awt.Image.UndefinedProperty
- * will be returned.
- *
- * @param name the name of the property to get, as a String.
- * @return a reference to the property Object, or the value
- * java.awt.Image.UndefinedProperty.
- */
- public Object getProperty(String name) {
- return myCRIF.getProperty(paramBlock, name);
- }
-
- /**
- * Return a list of names recognized by getProperty.
- */
- public String[] getPropertyNames() {
- return myCRIF.getPropertyNames();
- }
-
- /**
- * 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. The CRIF's isDynamic method will be called.
- */
- public boolean isDynamic() {
- return myCRIF.isDynamic();
- }
-
- /**
- * Gets the width in user coordinate space. By convention, the
- * usual width of a RenderableImage is equal to the image's aspect
- * ratio (width divided by height).
- *
- * @return the width of the image in user coordinates.
- */
- public float getWidth() {
- if (boundingBox == null) {
- boundingBox = myCRIF.getBounds2D(paramBlock);
- }
- return (float)boundingBox.getWidth();
- }
-
- /**
- * Gets the height in user coordinate space. By convention, the
- * usual height of a RenderedImage is equal to 1.0F.
- *
- * @return the height of the image in user coordinates.
- */
- public float getHeight() {
- if (boundingBox == null) {
- boundingBox = myCRIF.getBounds2D(paramBlock);
- }
- return (float)boundingBox.getHeight();
- }
-
- /**
- * Gets the minimum X coordinate of the rendering-independent image data.
- */
- public float getMinX() {
- if (boundingBox == null) {
- boundingBox = myCRIF.getBounds2D(paramBlock);
- }
- return (float)boundingBox.getMinX();
- }
-
- /**
- * Gets the minimum Y coordinate of the rendering-independent image data.
- */
- public float getMinY() {
- if (boundingBox == null) {
- boundingBox = myCRIF.getBounds2D(paramBlock);
- }
- return (float)boundingBox.getMinY();
- }
-
- /**
- * Change the current ParameterBlock of the operation, allowing
- * editing of image rendering chains. The effects of such a
- * change will be visible when a new rendering is created from
- * this RenderableImageOp or any dependent RenderableImageOp.
- *
- * @param paramBlock the new ParameterBlock.
- * @return the old ParameterBlock.
- */
- public ParameterBlock setParameterBlock(ParameterBlock paramBlock) {
- ParameterBlock oldParamBlock = this.paramBlock;
- this.paramBlock = (ParameterBlock)paramBlock.clone();
- return oldParamBlock;
- }
-
- /** Returns a reference to the current parameter block. */
- public ParameterBlock getParameterBlock() {
- return paramBlock;
- }
-
- /**
- * Creates a RenderedImage instance of this image with width w, and
- * height h in pixels. The RenderContext is built automatically
- * with an appropriate usr2dev transform and an area of interest
- * of the full image. All the rendering hints come from hints
- * passed in.
- *
- * <p> If w == 0, it will be taken to equal
- * Math.round(h*(getWidth()/getHeight())).
- * Similarly, if h == 0, it will be taken to equal
- * Math.round(w*(getHeight()/getWidth())). One of
- * w or h must be non-zero or else an IllegalArgumentException
- * will be thrown.
- *
- * <p> The created RenderedImage may have a property identified
- * by the String HINTS_OBSERVED to indicate which RenderingHints
- * 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 w the width of rendered image in pixels, or 0.
- * @param h the height of rendered image in pixels, or 0.
- * @param hints a RenderingHints object containg hints.
- * @return a RenderedImage containing the rendered data.
- */
- public RenderedImage createScaledRendering(int w, int h,
- RenderingHints hints) {
- // DSR -- code to try to get a unit scale
- double sx = (double)wgetWidth();
- double sy = (double)hgetHeight();
- if (Math.abs(sxsy - 1.0) < 0.01) {
- sx = sy;
- }
- AffineTransform usr2dev = AffineTransform.getScaleInstance(sx, sy);
- RenderContext newRC = new RenderContext(usr2dev, hints);
- return createRendering(newRC);
- }
-
- /**
- * Gets a RenderedImage instance of this image with a default
- * width and height in pixels. The RenderContext is built
- * automatically with an appropriate usr2dev transform and an area
- * of interest of the full image. All the rendering hints come
- * from hints passed in. Implementors of this interface must be
- * sure that there is a defined default width and height.
- *
- * @return a RenderedImage containing the rendered data.
- */
- public RenderedImage createDefaultRendering() {
- AffineTransform usr2dev = new AffineTransform(); // Identity
- RenderContext newRC = new RenderContext(usr2dev);
- return createRendering(newRC);
- }
-
- /**
- * Creates a RenderedImage which represents this
- * RenderableImageOp (including its Renderable sources) rendered
- * according to the given RenderContext.
- *
- * <p> This method supports chaining of either Renderable or
- * RenderedImage operations. If sources in
- * the ParameterBlock used to construct the RenderableImageOp are
- * RenderableImages, then a three step process is followed:
- *
- * <ol>
- * <li> mapRenderContext() is called on the associated CRIF for
- * each RenderableImage source;
- * <li> createRendering() is called on each of the RenderableImage sources
- * using the backwards-mapped RenderContexts obtained in step 1,
- * resulting in a rendering of each source;
- * <li> ContextualRenderedImageFactory.create() is called
- * with a new ParameterBlock containing the parameters of
- * the RenderableImageOp and the RenderedImages that were created by the
- * createRendering() calls.
- * </ol>
- *
- * <p> If the elements of the source Vector of
- * the ParameterBlock used to construct the RenderableImageOp are
- * instances of RenderedImage, then the CRIF.create() method is
- * called immediately using the original ParameterBlock.
- * This provides a basis case for the recursion.
- *
- * <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 perform the rendering.
- * @return a RenderedImage containing the desired output image.
- */
- public RenderedImage createRendering(RenderContext renderContext) {
- RenderedImage image = null;
- RenderContext rcOut = null;
-
- // Clone the original ParameterBlock; if the ParameterBlock
- // contains RenderableImage sources, they will be replaced by
- // RenderedImages.
- ParameterBlock renderedParamBlock = (ParameterBlock)paramBlock.clone();
- Vector sources = getRenderableSources();
-
- try {
- // This assumes that if there is no renderable source, that there
- // is a rendered source in paramBlock
-
- if (sources != null) {
- Vector renderedSources = new Vector();
- for (int i = 0; i < sources.size(); i++) {
- rcOut = myCRIF.mapRenderContext(i, renderContext,
- paramBlock, this);
- RenderedImage rdrdImage =
- ((RenderableImage)sources.elementAt(i)).createRendering(rcOut);
- if (rdrdImage == null) {
- return null;
- }
-
- // Add this rendered image to the ParameterBlock's
- // list of RenderedImages.
- renderedSources.addElement(rdrdImage);
- }
-
- if (renderedSources.size() > 0) {
- renderedParamBlock.setSources(renderedSources);
- }
- }
-
- return myCRIF.create(renderContext, renderedParamBlock);
- } catch (ArrayIndexOutOfBoundsException e) {
- // This should never happen
- return null;
- }
- }
- }