Frames | No Frames |
1: /* TexturePaintContext.java -- PaintContext impl for TexturePaint 2: Copyright (C) 2006 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package gnu.java.awt.java2d; 40: 41: import java.awt.AWTError; 42: import java.awt.PaintContext; 43: import java.awt.Rectangle; 44: import java.awt.TexturePaint; 45: import java.awt.geom.AffineTransform; 46: import java.awt.geom.NoninvertibleTransformException; 47: import java.awt.geom.Rectangle2D; 48: import java.awt.image.BufferedImage; 49: import java.awt.image.ColorModel; 50: import java.awt.image.Raster; 51: import java.awt.image.WritableRaster; 52: 53: /** 54: * A {@link PaintContext} implementation for {@link TexturePaint}, done in 55: * pure Java. 56: * 57: * @author Roman Kennke (kennke@aicas.com) 58: */ 59: public class TexturePaintContext 60: implements PaintContext 61: { 62: 63: /** 64: * The TexturePaint object. 65: */ 66: private BufferedImage image; 67: 68: /** 69: * The Raster that holds the texture. 70: */ 71: private WritableRaster paintRaster; 72: 73: /** 74: * The transform from userspace into device space. 75: */ 76: private AffineTransform transform; 77: 78: /** 79: * Creates a new TexturePaintContext for the specified TexturePaint object. 80: * This initializes the Raster which is returned by 81: * {@link #getRaster(int, int, int, int)}. 82: * 83: * @param t the texture paint object 84: * @param db the bounds of the target raster in device space 85: * @param ub the bounds of the target raster in user space 86: * @param xform the transformation from user space to device space 87: */ 88: public TexturePaintContext(TexturePaint t, Rectangle db, 89: Rectangle2D ub, AffineTransform xform) 90: { 91: image = t.getImage(); 92: 93: try 94: { 95: // Prepare transform for mapping from device space into image space. 96: // In order to achieve this we take the transform for userspace-> 97: // devicespace, append the correct scale and translation according 98: // to the anchor (which gives us the image->userspace->devicespace 99: // transform), and invert that (which gives use the device->user->image 100: // transform). 101: Rectangle2D anchor = t.getAnchorRect(); 102: BufferedImage image = t.getImage(); 103: double scaleX = anchor.getWidth() / image.getWidth(); 104: double scaleY = anchor.getHeight() / image.getHeight(); 105: transform = (AffineTransform) xform.clone(); 106: transform.scale(scaleX, scaleY); 107: transform.translate(-anchor.getMinX(), -anchor.getMinY()); 108: transform = transform.createInverse(); 109: } 110: catch (NoninvertibleTransformException ex) 111: { 112: AWTError err = 113: new AWTError("Unexpected NoninvertibleTransformException"); 114: err.initCause(ex); 115: throw err; 116: } 117: } 118: 119: /** 120: * Disposes the PaintContext. Nothing is to do here, since we don't use 121: * any native resources in that implementation. 122: */ 123: public void dispose() 124: { 125: // Nothing to do here. 126: } 127: 128: /** 129: * Returns the color model of this PaintContext. This implementation returnes 130: * the color model used by the BufferedImage in the TexturePaint object, 131: * this avoids costly color model transformations (at least at this point). 132: * 133: * @return the color model of this PaintContext 134: */ 135: public ColorModel getColorModel() 136: { 137: return image.getColorModel(); 138: } 139: 140: /** 141: * Returns the Raster that is used for painting. 142: * 143: * @param x1 the x location of the raster inside the user bounds of this paint 144: * context 145: * @param y1 the y location of the raster inside the user bounds of this paint 146: * context 147: * @param w the width 148: * @param h the height 149: * 150: * @return the Raster that is used for painting 151: * 152: */ 153: public Raster getRaster(int x1, int y1, int w, int h) 154: { 155: ensureRasterSize(w, h); 156: int x2 = x1 + w; 157: int y2 = y1 + h; 158: float[] src = new float[2]; 159: float[] dest = new float[2]; 160: Raster source = image.getData(); 161: int minX = source.getMinX(); 162: int width = source.getWidth(); 163: int minY = source.getMinY(); 164: int height = source.getHeight(); 165: Object pixel = null; 166: for (int y = y1; y < y2; y++) 167: { 168: for (int x = x1; x < x2; x++) 169: { 170: // Transform the coordinates from device space into image space. 171: src[0] = x; 172: src[1] = y; 173: transform.transform(src, 0, dest, 0, 1); 174: int dx = (int) dest[0]; 175: int dy = (int) dest[1]; 176: 177: // The modulo operation gives us the replication effect. 178: dx = ((dx - minX) % width) + minX; 179: dy = ((dy - minY) % height) + minY; 180: 181: // Handle possible negative values (replicating above the top-left) 182: if (dx < 0) 183: dx += width; 184: if (dy < 0) 185: dy += height; 186: 187: // Copy the pixel. 188: pixel = source.getDataElements(dx, dy, pixel); 189: paintRaster.setDataElements(x - x1, y - y1, pixel); 190: } 191: } 192: return paintRaster; 193: } 194: 195: /** 196: * Ensures that the target raster exists and has at least the specified 197: * size. 198: * 199: * @param w the requested target width 200: * @param h the requested target height 201: */ 202: private void ensureRasterSize(int w, int h) 203: { 204: if (paintRaster == null || paintRaster.getWidth() < w 205: || paintRaster.getHeight() < h) 206: { 207: Raster s = image.getData(); 208: paintRaster = s.createCompatibleWritableRaster(w, h); 209: } 210: } 211: }