/* BitwiseXORComposite.java -- Composite for emulating old-style XOR.
   Copyright (C) 2003, 2004  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.awt;

import java.awt.Color;
import java.awt.Composite;
import java.awt.CompositeContext;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;


/**
 * A composite for emulating traditional bitwise XOR of pixel values.
 * Please note that this composite does <i>not</i> implement the Porter-Duff
 * XOR operator, but an exclusive or of overlapping subpixel regions.
 *
 * <p><img src="doc-files/BitwiseXORComposite-1.png" width="545"
 * height="138" alt="A screen shot of BitwiseXORComposite in action"
 * />
 *
 * <p>The above screen shot shows the result of applying six different
 * BitwiseXORComposites. They were constructed with the colors
 * white, blue, black, orange, green, and brown, respectively. Each
 * composite was used to paint a fully white rectangle on top of the
 * blue bar in the background.
 *
 * <p>The purpose of this composite is to support the {@link
 * Graphics#setXORMode(Color)} method in composite-aware graphics
 * implementations. Applications typically would use
 * <code>setXORMode</code> for drawing &#x201c;highlights&#x201d; such
 * as text selections or cursors by inverting colors temporarily and
 * then inverting them back.
 *
 * <p>A concrete <code>Graphics</code> implementation may contain
 * the following code:
 *
 * <p><pre> public void setXORMode(Color xorColor)
 * {
 *   setComposite(new gnu.java.awt.BitwiseXORComposite(xorColor));
 * }
 *
 * public void setPaintMode()
 * {
 *   setComposite(java.awt.AlphaComposite.SrcOver);
 * }</pre>
 *
 * @author Graydon Hoare (graydon@redhat.com)
 * @author Sascha Brawer (brawer@dandelis.ch)
 */
public class BitwiseXORComposite
  implements Composite
{
  /**
   * The color whose RGB value is xor-ed with the values of each
   * pixel.
   */
  protected Color xorColor;


  /**
   * Constructs a new composite for xor-ing the pixel value.
   *
   * @param xorColor the color whose pixel value will be bitwise
   * xor-ed with the source and destination pixels.
   */
  public BitwiseXORComposite(Color xorColor)
  {
    this.xorColor = xorColor;
  }


  /**
   * Creates a context object for performing the compositing
   * operation. Several contexts may co-exist for one composite; each
   * context may simultaneously be called from concurrent threads.
   *
   * @param srcColorModel the color model of the source.
   * @param dstColorModel the color model of the destination.
   * @param hints hints for choosing between rendering alternatives.
   */
  public CompositeContext createContext(ColorModel srcColorModel,
                                        ColorModel dstColorModel,
                                        RenderingHints hints)
  {
    if (IntContext.isSupported(srcColorModel, dstColorModel, hints))
      return new IntContext(srcColorModel, xorColor);

    return new GeneralContext(srcColorModel, dstColorModel, xorColor);
  }


  /**
   * A fallback CompositeContext that performs bitwise XOR of pixel
   * values with the pixel value of the specified <code>xorColor</code>.
   *
   * <p>Applying this CompositeContext on a 1024x1024 BufferedImage of
   * <code>TYPE_INT_RGB</code> took 611 ms on a lightly loaded 2.4 GHz
   * Intel Pentium 4 CPU running Sun J2SE 1.4.1_01 on GNU/Linux
   * 2.4.20. The timing is the average of ten runs on the same
   * BufferedImage. Since the measurements were taken with {@link
   * System#currentTimeMillis()}, they are rather inaccurate.
   *
   * @author Graydon Hoare (graydon@redhat.com)
   */
  private static class GeneralContext
    implements CompositeContext
  {
    ColorModel srcColorModel;
    ColorModel dstColorModel;
    Color xorColor;

    public GeneralContext(ColorModel srcColorModel,
                          ColorModel dstColorModel,
                          Color xorColor)
    {
      this.srcColorModel = srcColorModel;
      this.dstColorModel = dstColorModel;
      this.xorColor = xorColor;
    }


    public void compose(Raster src, Raster dstIn, WritableRaster dstOut)
    {
      Rectangle srcRect = src.getBounds();
      Rectangle dstInRect = dstIn.getBounds();
      Rectangle dstOutRect = dstOut.getBounds();

      int xp = xorColor.getRGB();
      int w = Math.min(Math.min(srcRect.width, dstOutRect.width),
                       dstInRect.width);
      int h = Math.min(Math.min(srcRect.height, dstOutRect.height),
                       dstInRect.height);

      Object srcPix = null, dstPix = null, rpPix = null;

      // Re-using the rpPix object saved 1-2% of execution time in
      // the 1024x1024 pixel benchmark.

      for (int y = 0; y < h; y++)
      {
        for (int x = 0; x < w; x++)
        {
          srcPix = src.getDataElements(x + srcRect.x, y + srcRect.y, srcPix);
          dstPix = dstIn.getDataElements(x + dstInRect.x, y + dstInRect.y,
                                         dstPix);
          int sp = srcColorModel.getRGB(srcPix);
          int dp = dstColorModel.getRGB(dstPix);
          int rp = sp ^ xp ^ dp;
          dstOut.setDataElements(x + dstOutRect.x, y + dstOutRect.y,
                                 dstColorModel.getDataElements(rp, rpPix));
        }
      }
    }


    /**
     * Disposes any cached resources. The default implementation does
     * nothing because no resources are cached.
     */
    public void dispose()
    {
    }
  }


  /**
   * An optimized CompositeContext that performs bitwise XOR of
   * <code>int</code> pixel values with the pixel value of a specified
   * <code>xorColor</code>.  This CompositeContext working only for
   * rasters whose transfer format is {@link DataBuffer#TYPE_INT}.
   *
   * <p>Applying this CompositeContext on a 1024x1024 BufferedImage of
   * <code>TYPE_INT_RGB</code> took 69 ms on a lightly loaded 2.4 GHz
   * Intel Pentium 4 CPU running Sun J2SE 1.4.1_01 on GNU/Linux
   * 2.4.20. The timing is the average of ten runs on the same
   * BufferedImage. Since the measurements were taken with {@link
   * System#currentTimeMillis()}, they are rather inaccurate.
   *
   * @author Sascha Brawer (brawer@dandelis.ch)
   */
  private static class IntContext
    extends GeneralContext
  {
    public IntContext(ColorModel colorModel, Color xorColor)
    {
      super(colorModel, colorModel, xorColor);
    }


    public void compose(Raster src, Raster dstIn,
                        WritableRaster dstOut)
    {
      int aX, bX, dstX, aY, bY, dstY, width, height;
      int xorPixel;
      int[] srcLine, dstLine;

      aX = src.getMinX();
      aY = src.getMinY();
      bX = dstIn.getMinX();
      bY = dstIn.getMinY();
      dstX = dstOut.getMinX();
      dstY = dstOut.getMinY();
      width = Math.min(Math.min(src.getWidth(), dstIn.getWidth()),
                       dstOut.getWidth());
      height = Math.min(Math.min(src.getHeight(), dstIn.getHeight()),
                        dstOut.getHeight());
      if ((width < 1) || (height < 1))
        return;

      srcLine = new int[width];
      dstLine = new int[width];

      /* We need an int[] array with at least one element here;
       * srcLine is as good as any other.
       */
      srcColorModel.getDataElements(this.xorColor.getRGB(), srcLine);
      xorPixel = srcLine[0];

      for (int y = 0; y < height; y++)
      {
        src.getDataElements(aX, y + aY, width, 1, srcLine);
        dstIn.getDataElements(bX, y + bY, width, 1, dstLine);

        for (int x = 0; x < width; x++)
          dstLine[x] ^= srcLine[x] ^ xorPixel;

        dstOut.setDataElements(dstX, y + dstY, width, 1, dstLine);
      }
    }


    /**
     * Determines whether an instance of this CompositeContext would
     * be able to process the specified color models.
     */
    public static boolean isSupported(ColorModel srcColorModel,
                                      ColorModel dstColorModel,
                                      RenderingHints hints)
    {
      // FIXME: It would be good if someone could review these checks.
      // They probably need to be more restrictive.

      int transferType;

      transferType = srcColorModel.getTransferType();
      if (transferType != dstColorModel.getTransferType())
        return false;

      if (transferType != DataBuffer.TYPE_INT)
        return false;

      return true;
    }
  }
}
