mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			326 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			326 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* 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 );
 | |
|     setup( cairo_t );
 | |
|   }
 | |
| 
 | |
|   private VolatileImageGraphics(VolatileImageGraphics copy)
 | |
|   {
 | |
|     this.owner = copy.owner;
 | |
|     cairo_t = initFromVolatile(owner.nativePointer);
 | |
|     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;
 | |
|   }
 | |
| }
 |