OSDN Git Service

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