/* VolatileImageGraphics.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.Image;
import java.awt.Point;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
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.Raster;
import java.awt.image.WritableRaster;
import java.util.Hashtable;

public class VolatileImageGraphics extends ComponentGraphics
{
  private GtkVolatileImage owner;
  private BufferedImage buffer;

  public VolatileImageGraphics(GtkVolatileImage img)
  {
    this.owner = img;
    cairo_t = initFromVolatile( owner.nativePointer, img.width, img.height );
    setup( cairo_t );
  }

  private VolatileImageGraphics(VolatileImageGraphics copy)
  {
    this.owner = copy.owner;
    cairo_t = initFromVolatile(owner.nativePointer, owner.width, owner.height);
    copy( copy, cairo_t );
  }

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

  public GraphicsConfiguration getDeviceConfiguration()
  {
    GraphicsConfiguration conf;
    if (owner.component != null)
      {
        conf = owner.component.getGraphicsConfiguration();
      }
    else
      {
        return java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment()
          .getDefaultScreenDevice().getDefaultConfiguration();
      }
    return conf;
  }

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

  public void draw(Shape s)
  {
    if (comp == null || comp instanceof AlphaComposite)
      super.draw(s);
    
    // Custom composite
    else
      {
        // Draw operation to temporary buffer
        createBuffer();

        Graphics2D g2d = (Graphics2D)buffer.getGraphics();
        g2d.setColor(this.getColor());
        g2d.setStroke(this.getStroke());
        g2d.draw(s);
        
        drawComposite(s.getBounds2D(), null);
      }
  }
  
  public void fill(Shape s)
  {
    if (comp == null || comp instanceof AlphaComposite)
      super.fill(s);

    // Custom composite
    else
      {
        // Draw operation to temporary buffer
        createBuffer();

        Graphics2D g2d = (Graphics2D)buffer.getGraphics();
        g2d.setPaint(this.getPaint());
        g2d.setColor(this.getColor());
        g2d.fill(s);
        
        drawComposite(s.getBounds2D(), null);
      }
  }
  
  public void drawGlyphVector(GlyphVector gv, float x, float y)
  {
    if (comp == null || comp instanceof AlphaComposite)
      super.drawGlyphVector(gv, x, y);
    
    // Custom composite
    else
      {
        // Draw operation to temporary buffer
        createBuffer();

        Graphics2D g2d = (Graphics2D)buffer.getGraphics();
        
        g2d.setPaint(this.getPaint());
        g2d.setColor(this.getColor());
        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);
      }
  }

  protected boolean drawImage(Image img, AffineTransform xform,
                              Color bgcolor, ImageObserver obs)
    {
      if (comp == null || comp instanceof AlphaComposite)
        return super.drawImage(img, xform, bgcolor, obs);
      
      // Custom composite
      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 dimensions of translation
          Point2D origin = new Point2D.Double(bImg.getMinX(), bImg.getMinY());
          Point2D pt = new Point2D.Double(bImg.getWidth(), bImg.getHeight());
          if (xform != null)
            {
              origin = xform.transform(origin, origin);
              pt = xform.transform(pt, pt);
            }
          
          // Create buffer and draw image
          createBuffer();
          
          Graphics2D g2d = (Graphics2D)buffer.getGraphics();
          g2d.setRenderingHints(this.getRenderingHints());
          g2d.drawImage(img, xform, obs);

          // Perform compositing from buffer to screen
          return drawComposite(new Rectangle2D.Double((int)origin.getX(),
                                                      (int)origin.getY(),
                                                      (int)pt.getX(),
                                                      (int)pt.getY()),
                               obs);
        }
    }
  
  public boolean drawImage(Image img, int x, int y, ImageObserver observer)
  {
    if (img instanceof GtkVolatileImage
        && (comp == null || comp instanceof AlphaComposite))
      {
        owner.drawVolatile( ((GtkVolatileImage)img).nativePointer, 
                            x, y,
                            ((GtkVolatileImage)img).width, 
                            ((GtkVolatileImage)img).height );
        return true;
      }      
    return super.drawImage( img, x, y, observer );
  }
  
  public boolean drawImage(Image img, int x, int y, int width, int height,
                           ImageObserver observer)
  {
    if ((img instanceof GtkVolatileImage)
        && (comp == null || comp instanceof AlphaComposite))
      {
        owner.drawVolatile( ((GtkVolatileImage)img).nativePointer, 
                            x, y, width, height );
        return true;
      }      
    return super.drawImage( img, x, y, width, height, observer );
  }

  protected Rectangle2D getRealBounds()
  {
    return new Rectangle2D.Double(0, 0, owner.width, owner.height);
  }
  
  private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
  {
    // Clip source to visible areas that need updating
    Rectangle2D clip = this.getClipBounds();
    Rectangle2D.intersect(bounds, clip, bounds);
    
    BufferedImage buffer2 = buffer;
    if (!bounds.equals(buffer2.getRaster().getBounds()))
      buffer2 = buffer2.getSubimage((int)bounds.getX(), (int)bounds.getY(),
                                    (int)bounds.getWidth(),
                                    (int)bounds.getHeight());
    
    // Get current on-screen pixels (destination) and clip to bounds
    BufferedImage current = owner.getSnapshot();

    double[] points = new double[] {bounds.getX(), bounds.getY(),
                                    bounds.getMaxX(), bounds.getMaxY()};
    transform.transform(points, 0, points, 0, 2);
    
    Rectangle2D deviceBounds = new Rectangle2D.Double(points[0], points[1],
                                                      points[2] - points[0],
                                                      points[3] - points[1]);
    Rectangle2D.intersect(deviceBounds, this.getClipInDevSpace(), deviceBounds);
    
    current = current.getSubimage((int)deviceBounds.getX(),
                                  (int)deviceBounds.getY(),
                                  (int)deviceBounds.getWidth(),
                                  (int)deviceBounds.getHeight());

    // Perform actual composite operation
    compCtx.compose(buffer2.getRaster(), current.getRaster(),
                    buffer2.getRaster());
    
    // 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!
    Composite oldComp = comp;           // so that ComponentGraphics doesn't
    comp = null;                        // process the composite again
    boolean rv = super.drawImage(buffer2,
                           AffineTransform.getTranslateInstance(bounds.getX(),
                                                                bounds.getY()),
                           null, null);
    comp = oldComp;

    return rv;
  }
  
  private void createBuffer()
  {
    if (buffer == null)
      {
        WritableRaster rst;
        rst = Raster.createWritableRaster(GtkVolatileImage.createGdkSampleModel(owner.width,
                                                                  owner.height),
                                          new Point(0,0));
        
        buffer = new BufferedImage(GtkVolatileImage.gdkColorModel, rst,
                                   GtkVolatileImage.gdkColorModel.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()
  {
    // We should really return GtkVolatileImage.gdkColorModel ,
    // but CairoGraphics2D doesn't handle alpha premultiplication properly (see
    // the fixme in drawImage) so we use the naive Cairo model instead to trick
    // the compositing context.
    // Because getNativeCM() == getBufferCM() for this peer, it doesn't break.
    return CairoSurface.cairoCM_pre;
  }
}

