Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / gnu / java / awt / BitwiseXORComposite.java
blob6a05ee6c51b95c9cb4bf4bee6198d7175a63f943
1 /* BitwiseXORComposite.java -- Composite for emulating old-style XOR.
2 Copyright (C) 2003, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
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.
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. */
39 package gnu.java.awt;
41 import java.awt.Color;
42 import java.awt.Composite;
43 import java.awt.CompositeContext;
44 import java.awt.Rectangle;
45 import java.awt.RenderingHints;
46 import java.awt.image.ColorModel;
47 import java.awt.image.DataBuffer;
48 import java.awt.image.Raster;
49 import java.awt.image.WritableRaster;
52 /**
53 * A composite for emulating traditional bitwise XOR of pixel values.
54 * Please note that this composite does <i>not</i> implement the Porter-Duff
55 * XOR operator, but an exclusive or of overlapping subpixel regions.
57 * <p><img src="doc-files/BitwiseXORComposite-1.png" width="545"
58 * height="138" alt="A screen shot of BitwiseXORComposite in action"
59 * />
61 * <p>The above screen shot shows the result of applying six different
62 * BitwiseXORComposites. They were constructed with the colors colors
63 * white, blue, black, orange, green, and brown, respectively. Each
64 * composite was used to paint a fully white rectangle on top of the
65 * blue bar in the background.
67 * <p>The purpose of this composite is to support the {@link
68 * Graphics#setXORMode(Color)} method in composite-aware graphics
69 * implementations. Applications typically would use
70 * <code>setXORMode</code> for drawing &#x201c;highlights&#x201d; such
71 * as text selections or cursors by inverting colors temporarily and
72 * then inverting them back.
74 * <p>A concrete <code>Graphics</code> implementation may contain
75 * the following code:
77 * <p><pre> public void setXORMode(Color xorColor)
78 * {
79 * setComposite(new gnu.java.awt.BitwiseXORComposite(xorColor));
80 * }
82 * public void setPaintMode()
83 * {
84 * setComposite(java.awt.AlphaComposite.SrcOver);
85 * }</pre>
87 * @author Graydon Hoare (graydon@redhat.com)
88 * @author Sascha Brawer (brawer@dandelis.ch)
90 public class BitwiseXORComposite
91 implements Composite
93 /**
94 * The color whose RGB value is xor-ed with the values of each
95 * pixel.
97 protected Color xorColor;
101 * Constructs a new composite for xor-ing the pixel value.
103 * @param xorColor the color whose pixel value will be bitwise
104 * xor-ed with the source and destination pixels.
106 public BitwiseXORComposite(Color xorColor)
108 this.xorColor = xorColor;
113 * Creates a context object for performing the compositing
114 * operation. Several contexts may co-exist for one composite; each
115 * context may simultaneously be called from concurrent threads.
117 * @param srcColorModel the color model of the source.
118 * @param dstColorModel the color model of the destination.
119 * @param hints hints for choosing between rendering alternatives.
121 public CompositeContext createContext(ColorModel srcColorModel,
122 ColorModel dstColorModel,
123 RenderingHints hints)
125 if (IntContext.isSupported(srcColorModel, dstColorModel, hints))
126 return new IntContext(srcColorModel, xorColor);
128 return new GeneralContext(srcColorModel, dstColorModel, xorColor);
133 * A fallback CompositeContext that performs bitwise XOR of pixel
134 * values with the pixel value of the specified <code>xorColor</code>.
136 * <p>Applying this CompositeContext on a 1024x1024 BufferedImage of
137 * <code>TYPE_INT_RGB</code> took 611 ms on a lightly loaded 2.4 GHz
138 * Intel Pentium 4 CPU running Sun J2SE 1.4.1_01 on GNU/Linux
139 * 2.4.20. The timing is the average of ten runs on the same
140 * BufferedImage. Since the measurements were taken with {@link
141 * System#currentTimeMillis()}, they are rather inaccurate.
143 * @author Graydon Hoare (graydon@redhat.com)
145 private static class GeneralContext
146 implements CompositeContext
148 ColorModel srcColorModel;
149 ColorModel dstColorModel;
150 Color xorColor;
152 public GeneralContext(ColorModel srcColorModel,
153 ColorModel dstColorModel,
154 Color xorColor)
156 this.srcColorModel = srcColorModel;
157 this.dstColorModel = dstColorModel;
158 this.xorColor = xorColor;
162 public void compose(Raster src, Raster dstIn, WritableRaster dstOut)
164 Rectangle srcRect = src.getBounds();
165 Rectangle dstInRect = dstIn.getBounds();
166 Rectangle dstOutRect = dstOut.getBounds();
168 int xp = xorColor.getRGB();
169 int w = Math.min(Math.min(srcRect.width, dstOutRect.width),
170 dstInRect.width);
171 int h = Math.min(Math.min(srcRect.height, dstOutRect.height),
172 dstInRect.height);
174 Object srcPix = null, dstPix = null, rpPix = null;
176 // Re-using the rpPix object saved 1-2% of execution time in
177 // the 1024x1024 pixel benchmark.
179 for (int y = 0; y < h; y++)
181 for (int x = 0; x < w; x++)
183 srcPix = src.getDataElements(x + srcRect.x, y + srcRect.y, srcPix);
184 dstPix = dstIn.getDataElements(x + dstInRect.x, y + dstInRect.y,
185 dstPix);
186 int sp = srcColorModel.getRGB(srcPix);
187 int dp = dstColorModel.getRGB(dstPix);
188 int rp = sp ^ xp ^ dp;
189 dstOut.setDataElements(x + dstOutRect.x, y + dstOutRect.y,
190 dstColorModel.getDataElements(rp, rpPix));
197 * Disposes any cached resources. The default implementation does
198 * nothing because no resources are cached.
200 public void dispose()
207 * An optimized CompositeContext that performs bitwise XOR of
208 * <code>int</code> pixel values with the pixel value of a specified
209 * <code>xorColor</code>. This CompositeContext working only for
210 * rasters whose transfer format is {@link DataBuffer#TYPE_INT}.
212 * <p>Applying this CompositeContext on a 1024x1024 BufferedImage of
213 * <code>TYPE_INT_RGB</code> took 69 ms on a lightly loaded 2.4 GHz
214 * Intel Pentium 4 CPU running Sun J2SE 1.4.1_01 on GNU/Linux
215 * 2.4.20. The timing is the average of ten runs on the same
216 * BufferedImage. Since the measurements were taken with {@link
217 * System#currentTimeMillis()}, they are rather inaccurate.
219 * @author Sascha Brawer (brawer@dandelis.ch)
221 private static class IntContext
222 extends GeneralContext
224 public IntContext(ColorModel colorModel, Color xorColor)
226 super(colorModel, colorModel, xorColor);
230 public void compose(Raster src, Raster dstIn,
231 WritableRaster dstOut)
233 int aX, bX, dstX, aY, bY, dstY, width, height;
234 int xorPixel;
235 int[] srcLine, dstLine;
237 aX = src.getMinX();
238 aY = src.getMinY();
239 bX = dstIn.getMinX();
240 bY = dstIn.getMinY();
241 dstX = dstOut.getMinX();
242 dstY = dstOut.getMinY();
243 width = Math.min(Math.min(src.getWidth(), dstIn.getWidth()),
244 dstOut.getWidth());
245 height = Math.min(Math.min(src.getHeight(), dstIn.getHeight()),
246 dstOut.getHeight());
247 if ((width < 1) || (height < 1))
248 return;
250 srcLine = new int[width];
251 dstLine = new int[width];
253 /* We need an int[] array with at least one element here;
254 * srcLine is as good as any other.
256 srcColorModel.getDataElements(this.xorColor.getRGB(), srcLine);
257 xorPixel = srcLine[0];
259 for (int y = 0; y < height; y++)
261 src.getDataElements(aX, y + aY, width, 1, srcLine);
262 dstIn.getDataElements(bX, y + bY, width, 1, dstLine);
264 for (int x = 0; x < width; x++)
265 dstLine[x] ^= srcLine[x] ^ xorPixel;
267 dstOut.setDataElements(dstX, y + dstY, width, 1, dstLine);
273 * Determines whether an instance of this CompositeContext would
274 * be able to process the specified color models.
276 public static boolean isSupported(ColorModel srcColorModel,
277 ColorModel dstColorModel,
278 RenderingHints hints)
280 // FIXME: It would be good if someone could review these checks.
281 // They probably need to be more restrictive.
283 int transferType;
285 transferType = srcColorModel.getTransferType();
286 if (transferType != dstColorModel.getTransferType())
287 return false;
289 if (transferType != DataBuffer.TYPE_INT)
290 return false;
292 return true;