001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.gvt.filter;
020:
021: import java.awt.AlphaComposite;
022: import java.awt.Graphics2D;
023: import java.awt.Rectangle;
024: import java.awt.RenderingHints;
025: import java.awt.geom.AffineTransform;
026: import java.awt.geom.Rectangle2D;
027: import java.awt.image.BufferedImage;
028: import java.awt.image.ColorModel;
029: import java.awt.image.SampleModel;
030: import java.awt.image.WritableRaster;
031:
032: import org.apache.batik.ext.awt.image.GraphicsUtil;
033: import org.apache.batik.ext.awt.image.rendered.AbstractRed;
034: import org.apache.batik.ext.awt.image.rendered.AbstractTiledRed;
035: import org.apache.batik.ext.awt.image.rendered.CachableRed;
036: import org.apache.batik.gvt.GraphicsNode;
037:
038: /**
039: * This implementation of RenderableImage will render its input
040: * GraphicsNode on demand for tiles.
041: *
042: * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
043: * @version $Id: GraphicsNodeRed8Bit.java 475477 2006-11-15 22:44:28Z cam $
044: */
045: public class GraphicsNodeRed8Bit extends AbstractRed {
046:
047: /**
048: * GraphicsNode this image can render
049: */
050: private GraphicsNode node;
051:
052: private AffineTransform node2dev;
053:
054: private RenderingHints hints;
055:
056: private boolean usePrimitivePaint;
057:
058: public GraphicsNodeRed8Bit(GraphicsNode node,
059: AffineTransform node2dev, boolean usePrimitivePaint,
060: RenderingHints hints) {
061: super (); // We _must_ call init...
062:
063: this .node = node;
064: this .node2dev = node2dev;
065: this .hints = hints;
066: this .usePrimitivePaint = usePrimitivePaint;
067:
068: // Calculate my bounds by applying the affine transform to
069: // my input data..
070:
071: AffineTransform at = node2dev;
072: Rectangle2D bounds2D = node.getPrimitiveBounds();
073: if (bounds2D == null)
074: bounds2D = new Rectangle2D.Float(0, 0, 1, 1);
075: if (!usePrimitivePaint) {
076: // When not using Primitive paint we return our bounds in
077: // the nodes parent's user space. This makes sense since
078: // this is the space that we will draw our selves into
079: // (since paint unlike primitivePaint incorporates the
080: // transform from our user space to our parents user
081: // space).
082: AffineTransform nodeAt = node.getTransform();
083: if (nodeAt != null) {
084: at = (AffineTransform) at.clone();
085: at.concatenate(nodeAt);
086: }
087: }
088: Rectangle bounds = at.createTransformedShape(bounds2D)
089: .getBounds();
090: // System.out.println("Bounds: " + bounds);
091:
092: ColorModel cm = createColorModel();
093:
094: int defSz = AbstractTiledRed.getDefaultTileSize();
095:
096: // Make tile(0,0) fall on the closest intersection of defaultSz.
097: int tgX = defSz * (int) Math.floor(bounds.x / defSz);
098: int tgY = defSz * (int) Math.floor(bounds.y / defSz);
099:
100: int tw = (bounds.x + bounds.width) - tgX;
101: if (tw > defSz)
102: tw = defSz;
103: int th = (bounds.y + bounds.height) - tgY;
104: if (th > defSz)
105: th = defSz;
106: if ((tw <= 0) || (th <= 0)) {
107: tw = 1;
108: th = 1;
109: }
110:
111: // fix my sample model so it makes sense given my size.
112: SampleModel sm = cm.createCompatibleSampleModel(tw, th);
113:
114: // Finish initializing our base class...
115: init((CachableRed) null, bounds, cm, sm, tgX, tgY, null);
116: }
117:
118: public WritableRaster copyData(WritableRaster wr) {
119: genRect(wr);
120: return wr;
121: }
122:
123: public void genRect(WritableRaster wr) {
124: // System.out.println(" Rect: " + wr.getBounds());
125: BufferedImage offScreen = new BufferedImage(cm, wr
126: .createWritableTranslatedChild(0, 0), cm
127: .isAlphaPremultiplied(), null);
128:
129: Graphics2D g = GraphicsUtil.createGraphics(offScreen, hints);
130: g.setComposite(AlphaComposite.Clear);
131: g.fillRect(0, 0, wr.getWidth(), wr.getHeight());
132: g.setComposite(AlphaComposite.SrcOver);
133: g.translate(-wr.getMinX(), -wr.getMinY());
134:
135: // Set transform
136: g.transform(node2dev);
137:
138: // Invoke primitive paint.
139: if (usePrimitivePaint) {
140: node.primitivePaint(g);
141: } else {
142: node.paint(g);
143: }
144:
145: g.dispose();
146: }
147:
148: static final boolean onMacOSX;
149: static {
150: // This should be OK for applets.
151: onMacOSX = ("Mac OS X".equals(System.getProperty("os.name")));
152: }
153:
154: public ColorModel createColorModel() {
155: if (onMacOSX)
156: return GraphicsUtil.sRGB_Pre;
157: return GraphicsUtil.sRGB_Unpre;
158: }
159: }
|