| /* |
| |
| Copyright 2001,2003 The Apache Software Foundation |
| |
| Licensed 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. |
| |
| */ |
| package org.apache.batik.ext.awt.image.renderable; |
| |
| import java.awt.Color; |
| import java.awt.Graphics2D; |
| import java.awt.Rectangle; |
| import java.awt.RenderingHints; |
| import java.awt.Shape; |
| import java.awt.geom.AffineTransform; |
| import java.awt.geom.Rectangle2D; |
| import java.awt.image.BufferedImage; |
| import java.awt.image.RenderedImage; |
| import java.awt.image.renderable.RenderContext; |
| |
| import org.apache.batik.ext.awt.image.GraphicsUtil; |
| import org.apache.batik.ext.awt.image.PadMode; |
| import org.apache.batik.ext.awt.image.rendered.BufferedImageCachableRed; |
| import org.apache.batik.ext.awt.image.rendered.CachableRed; |
| import org.apache.batik.ext.awt.image.rendered.MultiplyAlphaRed; |
| import org.apache.batik.ext.awt.image.rendered.PadRed; |
| import org.apache.batik.ext.awt.image.rendered.RenderedImageCachableRed; |
| |
| /** |
| * ClipRable implementation |
| * |
| * @author <a href="mailto:Thomas.DeWeese@Kodak.com">Thomas DeWeese</a> |
| * @version $Id$ |
| */ |
| public class ClipRable8Bit |
| extends AbstractRable |
| implements ClipRable { |
| |
| protected boolean useAA; |
| |
| /** |
| * The node who's outline specifies our mask. |
| */ |
| protected Shape clipPath; |
| |
| public ClipRable8Bit(Filter src, Shape clipPath) { |
| super(src, null); |
| setClipPath(clipPath); |
| setUseAntialiasedClip(false); |
| } |
| |
| public ClipRable8Bit(Filter src, Shape clipPath, boolean useAA) { |
| super(src, null); |
| setClipPath(clipPath); |
| setUseAntialiasedClip(useAA); |
| } |
| |
| /** |
| * The source to be masked by the mask node. |
| * @param src The Image to be masked. |
| */ |
| public void setSource(Filter src) { |
| init(src, null); |
| } |
| |
| /** |
| * This returns the current image being masked by the mask node. |
| * @return The image to mask |
| */ |
| public Filter getSource() { |
| return (Filter)getSources().get(0); |
| } |
| |
| /** |
| * Set the default behaviour of anti-aliased clipping. |
| * for this clip object. |
| */ |
| public void setUseAntialiasedClip(boolean useAA) { |
| touch(); |
| this.useAA = useAA; |
| } |
| |
| /** |
| * Resturns true if the default behaviour should be to use |
| * anti-aliased clipping. |
| */ |
| public boolean getUseAntialiasedClip() { |
| return useAA; |
| } |
| |
| |
| /** |
| * Set the clip path to use. |
| * The path will be filled with opaque white. |
| * @param clipPath The clip path to use |
| */ |
| public void setClipPath(Shape clipPath) { |
| touch(); |
| this.clipPath = clipPath; |
| } |
| |
| /** |
| * Returns the Shape that the cliprable will use to |
| * define the clip path. |
| * @return The shape that defines the clip path. |
| */ |
| public Shape getClipPath() { |
| return clipPath; |
| } |
| |
| /** |
| * Pass-through: returns the source's bounds |
| */ |
| public Rectangle2D getBounds2D(){ |
| return getSource().getBounds2D(); |
| } |
| |
| public RenderedImage createRendering(RenderContext rc) { |
| |
| AffineTransform usr2dev = rc.getTransform(); |
| |
| // Just copy over the rendering hints. |
| RenderingHints rh = rc.getRenderingHints(); |
| if (rh == null) rh = new RenderingHints(null); |
| |
| Shape aoi = rc.getAreaOfInterest(); |
| if (aoi == null) aoi = getBounds2D(); |
| |
| Rectangle2D rect = getBounds2D(); |
| Rectangle2D clipRect = clipPath.getBounds2D(); |
| Rectangle2D aoiRect = aoi.getBounds2D(); |
| |
| if (rect.intersects(clipRect) == false) |
| return null; |
| Rectangle2D.intersect(rect, clipRect, rect); |
| |
| |
| if (rect.intersects(aoiRect) == false) |
| return null; |
| Rectangle2D.intersect(rect, aoi.getBounds2D(), rect); |
| |
| Rectangle devR = usr2dev.createTransformedShape(rect).getBounds(); |
| |
| if ((devR.width == 0) || (devR.height == 0)) |
| return null; |
| |
| BufferedImage bi = new BufferedImage(devR.width, devR.height, |
| BufferedImage.TYPE_BYTE_GRAY); |
| |
| Shape devShape = usr2dev.createTransformedShape(getClipPath()); |
| Rectangle devAOIR; |
| devAOIR = usr2dev.createTransformedShape(aoi).getBounds(); |
| |
| Graphics2D g2d = GraphicsUtil.createGraphics(bi, rh); |
| |
| if (false) { |
| java.util.Set s = rh.keySet(); |
| java.util.Iterator i = s.iterator(); |
| while (i.hasNext()) { |
| Object o = i.next(); |
| System.out.println("XXX: " + o + " -> " + rh.get(o)); |
| } |
| } |
| g2d.translate(-devR.x, -devR.y); |
| g2d.setPaint(Color.white); |
| g2d.fill(devShape); |
| g2d.dispose(); |
| |
| RenderedImage ri; |
| ri = getSource().createRendering(new RenderContext(usr2dev, rect, rh)); |
| |
| CachableRed cr, clipCr; |
| cr = RenderedImageCachableRed.wrap(ri); |
| clipCr = new BufferedImageCachableRed(bi, devR.x, devR.y); |
| CachableRed ret = new MultiplyAlphaRed(cr, clipCr); |
| |
| // Pad back out to the proper size... |
| ret = new PadRed(ret, devAOIR, PadMode.ZERO_PAD, rh); |
| |
| return ret; |
| } |
| } |