/* CairoSurfaceGraphics.java
   Copyright (C) 2006 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.peer.gtk;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.RenderedImage;
import java.util.Hashtable;

/**
 * Implementation of Graphics2D on a Cairo surface.
 */
public class CairoSurfaceGraphics extends CairoGraphics2D
{
  protected CairoSurface surface;
  private BufferedImage buffer;
  private long cairo_t;

  /**
   * Create a graphics context from a cairo surface
   */
  public CairoSurfaceGraphics(CairoSurface surface)
  {
    this.surface = surface;
    cairo_t = surface.newCairoContext();
    setup( cairo_t );
    setClip(0, 0, surface.width, surface.height);
  }

  /**
   * Creates another context from a surface.
   * Used by create().
   */
  private CairoSurfaceGraphics(CairoSurfaceGraphics copyFrom)
  {
    surface = copyFrom.surface;
    cairo_t = surface.newCairoContext();
    copy( copyFrom, cairo_t );
  }

  public Graphics create()
  {
    return new CairoSurfaceGraphics(this);
  }

  public GraphicsConfiguration getDeviceConfiguration()
  {
    return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
  }

  protected Rectangle2D getRealBounds()
  {
    return new Rectangle2D.Double(0.0, 0.0, surface.width, surface.height);
  }

  public void copyAreaImpl(int x, int y, int width, int height, int dx, int dy)
  {
    surface.copyAreaNative(x, y, width, height, dx, dy, surface.width);
  }

  /**
   * Overloaded methods that do actual drawing need to account for custom
   * composites
   */
  public void draw(Shape s)
  {
    if (!surface.sharedBuffer)
      surface.syncJavaToNative(surface.surfacePointer, surface.getData());

    // Find total bounds of shape
    Rectangle r = findStrokedBounds(s);
    if (shiftDrawCalls)
      {
        r.width++;
        r.height++;
      }

    // Do the drawing
    if (comp == null || comp instanceof AlphaComposite)
      super.draw(s);

    else
      {
        createBuffer();

        Graphics2D g2d = (Graphics2D)buffer.getGraphics();
        g2d.setStroke(this.getStroke());
        g2d.setColor(this.getColor());
        g2d.setTransform(transform);
        g2d.draw(s);

        drawComposite(r.getBounds2D(), null);
      }

    if (!surface.sharedBuffer)
      surface.syncNativeToJava(surface.surfacePointer, surface.getData());
  }

  public void fill(Shape s)
  {
    if (!surface.sharedBuffer)
      surface.syncJavaToNative(surface.surfacePointer, surface.getData());

    if (comp == null || comp instanceof AlphaComposite)
      super.fill(s);

    else
      {
        createBuffer();

        Graphics2D g2d = (Graphics2D)buffer.getGraphics();
        g2d.setPaint(this.getPaint());
        g2d.setColor(this.getColor());
        g2d.setTransform(transform);
        g2d.fill(s);

        drawComposite(s.getBounds2D(), null);
      }

    if (!surface.sharedBuffer)
      surface.syncNativeToJava(surface.surfacePointer, surface.getData());
  }

  public void drawRenderedImage(RenderedImage image, AffineTransform xform)
  {
    if (!surface.sharedBuffer)
      surface.syncJavaToNative(surface.surfacePointer, surface.getData());

    if (comp == null || comp instanceof AlphaComposite)
      super.drawRenderedImage(image, xform);

    else
      {
        createBuffer();

        Graphics2D g2d = (Graphics2D)buffer.getGraphics();
        g2d.setRenderingHints(this.getRenderingHints());
        g2d.setTransform(transform);
        g2d.drawRenderedImage(image, xform);

        drawComposite(buffer.getRaster().getBounds(), null);
      }

    if (!surface.sharedBuffer)
      surface.syncNativeToJava(surface.surfacePointer, surface.getData());
  }

  protected boolean drawImage(Image img, AffineTransform xform,
                              Color bgcolor, ImageObserver obs)
  {
    if (!surface.sharedBuffer)
      surface.syncJavaToNative(surface.surfacePointer, surface.getData());

    boolean ret;
    if (comp == null || comp instanceof AlphaComposite)
      ret = super.drawImage(img, xform, bgcolor, obs);

    else
      {
        // Get buffered image of source
        if( !(img instanceof BufferedImage) )
          {
            ImageProducer source = img.getSource();
            if (source == null)
              return false;
            img = Toolkit.getDefaultToolkit().createImage(source);
          }
        BufferedImage bImg = (BufferedImage) img;

        // Find translated bounds
        Rectangle2D bounds = new Rectangle(bImg.getMinX(), bImg.getMinY(),
                                           bImg.getWidth(), bImg.getHeight());
        if (xform != null)
          bounds = getTransformedBounds(bounds, xform);

        // Create buffer and draw image
        createBuffer();

        Graphics2D g2d = (Graphics2D)buffer.getGraphics();
        g2d.setRenderingHints(this.getRenderingHints());
        g2d.drawImage(img, xform, obs);

        // Perform compositing
        ret = drawComposite(bounds, obs);
      }

    if (!surface.sharedBuffer)
      surface.syncNativeToJava(surface.surfacePointer, surface.getData());

    return ret;
  }

  public void drawGlyphVector(GlyphVector gv, float x, float y)
  {
    if (!surface.sharedBuffer)
      surface.syncJavaToNative(surface.surfacePointer, surface.getData());

    if (comp == null || comp instanceof AlphaComposite)
      super.drawGlyphVector(gv, x, y);

    else
      {
        createBuffer();

        Graphics2D g2d = (Graphics2D)buffer.getGraphics();
        g2d.setPaint(this.getPaint());
        g2d.setStroke(this.getStroke());
        g2d.drawGlyphVector(gv, x, y);

        Rectangle2D bounds = gv.getLogicalBounds();
        bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(),
                                        bounds.getWidth(), bounds.getHeight());
        drawComposite(bounds, null);
      }

    if (!surface.sharedBuffer)
      surface.syncNativeToJava(surface.surfacePointer, surface.getData());
  }

  private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
  {
    // Find bounds in device space
    bounds = getTransformedBounds(bounds, transform);

    // Clip bounds by the stored clip, and by the internal buffer
    Rectangle2D devClip = this.getClipInDevSpace();
    Rectangle2D.intersect(bounds, devClip, bounds);
    devClip = new Rectangle(buffer.getMinX(), buffer.getMinY(),
                            buffer.getWidth(), buffer.getHeight());
    Rectangle2D.intersect(bounds, devClip, bounds);

    // Round bounds as needed, but be careful in our rounding
    // (otherwise it may leave unpainted stripes)
    double x = bounds.getX();
    double y = bounds.getY();
    double maxX = x + bounds.getWidth();
    double maxY = y + bounds.getHeight();
    x = Math.round(x);
    y = Math.round(y);
    bounds.setRect(x, y, Math.round(maxX - x), Math.round(maxY - y));

    // Find subimage of internal buffer for updating
    BufferedImage buffer2 = buffer;
    if (!bounds.equals(buffer2.getRaster().getBounds()))
      buffer2 = buffer2.getSubimage((int)bounds.getX(), (int)bounds.getY(),
                                    (int)bounds.getWidth(),
                                    (int)bounds.getHeight());

    // Find subimage of main image for updating
    BufferedImage current = CairoSurface.getBufferedImage(surface);
    current = current.getSubimage((int)bounds.getX(), (int)bounds.getY(),
                                  (int)bounds.getWidth(),
                                  (int)bounds.getHeight());

    // Perform actual composite operation
    compCtx.compose(buffer2.getRaster(), current.getRaster(),
                    buffer2.getRaster());

    // Set cairo's composite to direct SRC, since we've already done our own
    // compositing
    Composite oldcomp = comp;
    setComposite(AlphaComposite.Src);

    // This MUST call directly into the "action" method in CairoGraphics2D,
    // not one of the wrappers, to ensure that the composite isn't processed
    // more than once!
    boolean rv = super.drawImage(buffer2,
                                 AffineTransform.getTranslateInstance(bounds.getX(),
                                                                      bounds.getY()),
                                 null, null);
    setComposite(oldcomp);
    updateColor();
    return rv;
  }

  private void createBuffer()
  {
    if (buffer == null)
      {
        buffer = new BufferedImage(getBufferCM(),
                                   surface.createCompatibleWritableRaster(),
                                   getBufferCM().isAlphaPremultiplied(),
                                   new Hashtable());
      }
    else
      {
        Graphics2D g2d = ((Graphics2D)buffer.getGraphics());

        g2d.setBackground(new Color(0,0,0,0));
        g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
      }
  }

  protected ColorModel getNativeCM()
  {
    return CairoSurface.cairoCM_pre;
  }

  protected ColorModel getBufferCM()
  {
    return CairoSurface.cairoColorModel;
  }
}
