/* Copyright (C) 2000, 2003  Free Software Foundation

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */

package gnu.awt.j2d;

import java.awt.Color;
import java.awt.Image;
import java.awt.Shape;
import java.awt.Rectangle;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.awt.image.ColorModel;

/**
 * IntegerGraphicsState is one of several graphics state
 * implementations.  This graphics state is used when the graphics
 * object has simple properties, (coordinate translation only, no
 * transform) and the backend supports integer coordinates (pixel
 * based). For primitive paint operations, this object translates the
 * coordinates and forwards the request to the backend. For requests
 * to draw arbitrary shapes and paths, this object translates the
 * requests to primitive drawing operations supported by the
 * backend. IntegerGraphicsState is meant to support the most common
 * state of an graphics object. The degree of functionality is roughly
 * equivalent with the old java.awt.Graphics API.
 */
public class IntegerGraphicsState extends AbstractGraphicsState
{
  int tx;
  int ty;
  
  DirectRasterGraphics directGfx;
  Shape clip;
  
  /** Interface for images which are coupled to a GraphicsConfiguration,
   * as is typically the case for an off-screen buffer used in
   * double-buffering.  Any image which implements this interface is
   * rendered directly by DirectRasterGraphics (i.e. by directGfx.drawImage)
   */
  public interface ScreenCoupledImage
  {
    /** Get the GraphicsConfiguration to which this image is coupled
     * @return the GraphicsConfiguration
     */
    GraphicsConfiguration getGraphicsConfiguration ();
  }
  
  public IntegerGraphicsState(DirectRasterGraphics directGfx)
  {
    this.directGfx = directGfx;
  }
  
  public Object clone()
  {
    IntegerGraphicsState clone = (IntegerGraphicsState) super.clone();
    clone.directGfx = (DirectRasterGraphics) directGfx.clone();
    
    return clone;
  }

  public void dispose()
  {
    DirectRasterGraphics lDeviceGfx = directGfx;
    
    directGfx = null;
    
    if (lDeviceGfx != null)
      lDeviceGfx.dispose();
    
    super.dispose();
  }
  
  // -------- Graphics methods:
  
  public void setColor(Color color)
  {
    directGfx.setColor(color);
  }
  
  public void setPaintMode()
  {
    directGfx.setPaintMode();
  }

  public void setXORMode(Color altColor)
  {
    directGfx.setXORMode(altColor);
  }
  
  public void setFont(Font font)
  {
    directGfx.setFont(font);
  }
  
  public FontMetrics getFontMetrics(Font font)
  {
    return directGfx.getFontMetrics(font);
  }

  public void setClip(Shape clip)
  {
    if (clip instanceof Rectangle)
      {
	Rectangle clipRect = (Rectangle) ((Rectangle) clip).clone();
	clipRect.x += tx;
	clipRect.y += ty;
	
	this.clip = clipRect;
	
	directGfx.setClip(clipRect);
	return;
      }
    
    String msg =
      "translating clip shape " + clip + " into device " +
      "coordinate space has not been implemented yet";
    
    throw new UnsupportedOperationException(msg);
  }

  public Shape getClip()
  {
    if (clip instanceof Rectangle)
      {
	Rectangle clipRect = (Rectangle) clip;
	clipRect.x -= tx;
	clipRect.y -= ty;
	return clipRect;
      }

    String msg =
      "translating clip shape " + clip + " into user " +
      "coordinate space has not been implemented yet";
    
    throw new UnsupportedOperationException(msg);
  }

  public Rectangle getClipBounds()
  {
    Rectangle clipRect = clip.getBounds();
    
    clipRect.x -= tx;
    clipRect.y -= ty;
    return clipRect;
  }

  public void copyArea(int x, int y, 
		       int width, int height,
		       int dx, int dy)
  {
    directGfx.copyArea(x+tx, y+ty, width, height, dx, dy);
  }

  public void drawLine(int x1, int y1,
		       int x2, int y2)
  {
    directGfx.drawLine(x1+tx, y1+ty, x2+tx, y2+ty);
  }
    
  public void fillRect(int x, int y,
		       int width, int height)
  {
    directGfx.fillRect(x+tx, y+ty, width, height);
  }
    
  public void clearRect(int x, int y,
			int width, int height)
  {
    directGfx.setColor(frontend.getBackground());
    directGfx.fillRect(x+tx, y+ty, width, height);
    directGfx.setColor(frontend.getColor());
  }

  public void drawRoundRect(int x, int y,
			    int width, int height,
			    int arcWidth, int arcHeight)
  {
    throw new UnsupportedOperationException("not implemented yet");
  }
  
  public void fillRoundRect(int x, int y,
			    int width, int height,
			    int arcWidth, int arcHeight)
  {
    throw new UnsupportedOperationException("not implemented yet");
  }

  public void drawOval(int x, int y,
		       int width, int height)
  {
    drawArc (x, y, width, height, 0, 360);
  }
  
  public void fillOval(int x, int y,
		       int width, int height)
  {
    fillArc (x, y, width, height, 0, 360);
  }

  public void drawArc(int x, int y,
		      int width, int height,
		      int startAngle, int arcAngle)
  {
    directGfx.drawArc(x+tx, y+ty, width, height, startAngle, arcAngle);
  }    

  public void fillArc(int x, int y,
		      int width, int height,
		      int startAngle, int arcAngle)
  {
    directGfx.fillArc(x+tx, y+ty, width, height, startAngle, arcAngle);
  }
  
  public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints)
  {
    if ((tx == 0) && (ty == 0))
      {
	directGfx.drawPolyline(xPoints, yPoints, nPoints);
	return;
      }
	    
    throw new UnsupportedOperationException("translate not implemented");
  }

  public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints)
  {
    if ((tx == 0) && (ty == 0))
      {
	directGfx.drawPolygon(xPoints, yPoints, nPoints);
	return;
      }

    throw new UnsupportedOperationException("translate not implemented");
  }
  
  public void fillPolygon (int[] xPoints, int[] yPoints, int nPoints)
  {
    // FIXME: remove tx & ty args once translation via AffineTransform
    // is implemented.
    directGfx.fillPolygon (xPoints, yPoints, nPoints, tx, ty);
  }

  public boolean drawImage(Image image, int x, int y,
			   ImageObserver observer)
  {
    x += tx;
    y += ty;
    
    if (image instanceof ScreenCoupledImage)
    {
      GraphicsConfiguration config
        = ((ScreenCoupledImage)image).getGraphicsConfiguration ();
      if (config == frontend.config)
        return directGfx.drawImage (image, x, y, observer);
    }
    if (image instanceof BufferedImage)
    {
      BufferedImage bImage = (BufferedImage) image;
      // FIXME: eliminate? ScreenCoupledImage is probably more efficient
      Object config = bImage.getProperty ("java.awt.GraphicsConfiguration");
      if (config == frontend.config)
        return directGfx.drawImage (image, x, y, observer);
      
      int width = image.getWidth (null);
      int height = image.getHeight (null);
      
      Rectangle bounds = new Rectangle (x, y, width, height);
      
      MappedRaster mr = directGfx.mapRaster (bounds);
      
      // manipulate raster here...
      ColorModel colorModel = mr.getColorModel ();
      WritableRaster raster = mr.getRaster ();
      
      int xEnd = x + width;
      int yEnd = y + height;
      
      // FIXME: Use the following code only as a fallback. It's SLOW!
      
      Object rgbElem = null;
      for (int yy=0; yy<height; yy++)
      {
        for (int xx=0; xx<width; xx++)
        {
          int srgb = bImage.getRGB (xx, yy);
          int sa = ((srgb >>> 24) & 0xff) + 1;
          int sr = ((srgb >>> 16) & 0xff) + 1;
          int sg = ((srgb >>> 8) & 0xff) + 1;
          int sb = (srgb & 0xff) + 1;
          
          rgbElem = raster.getDataElements (xx+x, yy+y, rgbElem);
          int drgb = colorModel.getRGB (rgbElem);
          int dr = ((drgb >>> 16) & 0xff) + 1;
          int dg = ((drgb >>> 8) & 0xff) + 1;
          int db = (drgb & 0xff) + 1;
          int da = 256 - sa;
          
          dr = ((sr*sa + dr*da) >>> 8) - 1;
          dg = ((sg*sa + dg*da) >>> 8) - 1;
          db = ((sb*sa + db*da) >>> 8) - 1;
          
          drgb = (dr<<16) | (dg<<8) | db;
          
          rgbElem = colorModel.getDataElements (drgb, rgbElem);
          
          raster.setDataElements (xx+x, yy+y, rgbElem);
        }
      }
      directGfx.unmapRaster (mr);
      return true;
      
    }
    throw new UnsupportedOperationException ("drawing image " + image +
    "not implemented");
  }
  

  // -------- Graphics2D methods:
  
  public void draw(Shape shape)
  {
    if (shape instanceof Rectangle)
      {
	Rectangle rect = (Rectangle) shape;
	directGfx.drawRect(rect.x+tx, rect.y+ty, rect.width, rect.height);
	return;
      } 
    
    throw new UnsupportedOperationException("shape not implemented");
  }

  public void fill(Shape shape)
  {
    if (shape instanceof Rectangle)
      {
	Rectangle rect = (Rectangle) shape;
	directGfx.fillRect(rect.x+tx, rect.y+ty, rect.width, rect.height);
	return;
      }
    
    throw new UnsupportedOperationException("not implemented");
  }
    
  public boolean hit(Rectangle rect, Shape text,
		     boolean onStroke)
  {
    throw new UnsupportedOperationException("not implemented");
  }

  public void drawString(String text, int x, int y)
  {
    directGfx.drawString(text, x+tx, y+ty);
  }

  public void drawString(String text, float x, float y)
  {
    drawString(text, (int) x, (int) y);
  }
  
  public void translate(int x, int y)
  {
    tx += x;
    ty += y;
  }
    
  public void translate(double tx, double ty)
  {
    if ((tx == 0) && (ty == 0))
      return;
    
    needAffineTransform();
  }

  public void rotate(double theta)
  {
    if (theta == 0)
      return;
    
    needAffineTransform();
  }

  public void rotate(double theta, double x, double y)
  {
    if (theta == 0)
      return;
    
    needAffineTransform();
  }

  public void scale(double scaleX, double scaleY)
  {
    if ((scaleX == 1) && (scaleY == 1))
      return;

    needAffineTransform();
  }
  
  public void shear(double shearX, double shearY)
  {
    if ((shearX == 0) && (shearY == 0))
      return;
    
    needAffineTransform();
  }   
  
  private void needAffineTransform()
  {
    throw new UnsupportedOperationException("state with affine " +
					    "transform not implemented");
  }
}
