Merged with mainline at revision 128810.
[official-gcc.git] / libjava / classpath / gnu / java / awt / peer / gtk / VolatileImageGraphics.java
blobad5cd5ecdf262e23e0866f5f5dbcc30a0c1bc19e
1 /* VolatileImageGraphics.java
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.java.awt.peer.gtk;
41 import java.awt.AlphaComposite;
42 import java.awt.Color;
43 import java.awt.Composite;
44 import java.awt.Graphics;
45 import java.awt.Graphics2D;
46 import java.awt.GraphicsConfiguration;
47 import java.awt.Image;
48 import java.awt.Point;
49 import java.awt.Shape;
50 import java.awt.Toolkit;
51 import java.awt.font.GlyphVector;
52 import java.awt.geom.AffineTransform;
53 import java.awt.geom.Point2D;
54 import java.awt.geom.Rectangle2D;
55 import java.awt.image.BufferedImage;
56 import java.awt.image.ColorModel;
57 import java.awt.image.ImageObserver;
58 import java.awt.image.ImageProducer;
59 import java.awt.image.Raster;
60 import java.awt.image.WritableRaster;
61 import java.util.Hashtable;
63 public class VolatileImageGraphics extends ComponentGraphics
65 private GtkVolatileImage owner;
66 private BufferedImage buffer;
68 public VolatileImageGraphics(GtkVolatileImage img)
70 this.owner = img;
71 cairo_t = initFromVolatile( owner.nativePointer, img.width, img.height );
72 setup( cairo_t );
75 private VolatileImageGraphics(VolatileImageGraphics copy)
77 this.owner = copy.owner;
78 cairo_t = initFromVolatile(owner.nativePointer, owner.width, owner.height);
79 copy( copy, cairo_t );
82 public void copyAreaImpl(int x, int y, int width, int height, int dx, int dy)
84 owner.copyArea(x, y, width, height, dx, dy);
87 public GraphicsConfiguration getDeviceConfiguration()
89 GraphicsConfiguration conf;
90 if (owner.component != null)
92 conf = owner.component.getGraphicsConfiguration();
94 else
96 return java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment()
97 .getDefaultScreenDevice().getDefaultConfiguration();
99 return conf;
102 public Graphics create()
104 return new VolatileImageGraphics( this );
107 public void draw(Shape s)
109 if (comp == null || comp instanceof AlphaComposite)
110 super.draw(s);
112 // Custom composite
113 else
115 // Draw operation to temporary buffer
116 createBuffer();
118 Graphics2D g2d = (Graphics2D)buffer.getGraphics();
119 g2d.setColor(this.getColor());
120 g2d.setStroke(this.getStroke());
121 g2d.draw(s);
123 drawComposite(s.getBounds2D(), null);
127 public void fill(Shape s)
129 if (comp == null || comp instanceof AlphaComposite)
130 super.fill(s);
132 // Custom composite
133 else
135 // Draw operation to temporary buffer
136 createBuffer();
138 Graphics2D g2d = (Graphics2D)buffer.getGraphics();
139 g2d.setPaint(this.getPaint());
140 g2d.setColor(this.getColor());
141 g2d.fill(s);
143 drawComposite(s.getBounds2D(), null);
147 public void drawGlyphVector(GlyphVector gv, float x, float y)
149 if (comp == null || comp instanceof AlphaComposite)
150 super.drawGlyphVector(gv, x, y);
152 // Custom composite
153 else
155 // Draw operation to temporary buffer
156 createBuffer();
158 Graphics2D g2d = (Graphics2D)buffer.getGraphics();
160 g2d.setPaint(this.getPaint());
161 g2d.setColor(this.getColor());
162 g2d.drawGlyphVector(gv, x, y);
164 Rectangle2D bounds = gv.getLogicalBounds();
165 bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(),
166 bounds.getWidth(), bounds.getHeight());
167 drawComposite(bounds, null);
171 protected boolean drawImage(Image img, AffineTransform xform,
172 Color bgcolor, ImageObserver obs)
174 if (comp == null || comp instanceof AlphaComposite)
175 return super.drawImage(img, xform, bgcolor, obs);
177 // Custom composite
178 else
180 // Get buffered image of source
181 if( !(img instanceof BufferedImage) )
183 ImageProducer source = img.getSource();
184 if (source == null)
185 return false;
186 img = Toolkit.getDefaultToolkit().createImage(source);
188 BufferedImage bImg = (BufferedImage) img;
190 // Find dimensions of translation
191 Point2D origin = new Point2D.Double(bImg.getMinX(), bImg.getMinY());
192 Point2D pt = new Point2D.Double(bImg.getWidth(), bImg.getHeight());
193 if (xform != null)
195 origin = xform.transform(origin, origin);
196 pt = xform.transform(pt, pt);
199 // Create buffer and draw image
200 createBuffer();
202 Graphics2D g2d = (Graphics2D)buffer.getGraphics();
203 g2d.setRenderingHints(this.getRenderingHints());
204 g2d.drawImage(img, xform, obs);
206 // Perform compositing from buffer to screen
207 return drawComposite(new Rectangle2D.Double((int)origin.getX(),
208 (int)origin.getY(),
209 (int)pt.getX(),
210 (int)pt.getY()),
211 obs);
215 public boolean drawImage(Image img, int x, int y, ImageObserver observer)
217 if (img instanceof GtkVolatileImage
218 && (comp == null || comp instanceof AlphaComposite))
220 owner.drawVolatile( ((GtkVolatileImage)img).nativePointer,
221 x, y,
222 ((GtkVolatileImage)img).width,
223 ((GtkVolatileImage)img).height );
224 return true;
226 return super.drawImage( img, x, y, observer );
229 public boolean drawImage(Image img, int x, int y, int width, int height,
230 ImageObserver observer)
232 if ((img instanceof GtkVolatileImage)
233 && (comp == null || comp instanceof AlphaComposite))
235 owner.drawVolatile( ((GtkVolatileImage)img).nativePointer,
236 x, y, width, height );
237 return true;
239 return super.drawImage( img, x, y, width, height, observer );
242 protected Rectangle2D getRealBounds()
244 return new Rectangle2D.Double(0, 0, owner.width, owner.height);
247 private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
249 // Clip source to visible areas that need updating
250 Rectangle2D clip = this.getClipBounds();
251 Rectangle2D.intersect(bounds, clip, bounds);
253 BufferedImage buffer2 = buffer;
254 if (!bounds.equals(buffer2.getRaster().getBounds()))
255 buffer2 = buffer2.getSubimage((int)bounds.getX(), (int)bounds.getY(),
256 (int)bounds.getWidth(),
257 (int)bounds.getHeight());
259 // Get current on-screen pixels (destination) and clip to bounds
260 BufferedImage current = owner.getSnapshot();
262 double[] points = new double[] {bounds.getX(), bounds.getY(),
263 bounds.getMaxX(), bounds.getMaxY()};
264 transform.transform(points, 0, points, 0, 2);
266 Rectangle2D deviceBounds = new Rectangle2D.Double(points[0], points[1],
267 points[2] - points[0],
268 points[3] - points[1]);
269 Rectangle2D.intersect(deviceBounds, this.getClipInDevSpace(), deviceBounds);
271 current = current.getSubimage((int)deviceBounds.getX(),
272 (int)deviceBounds.getY(),
273 (int)deviceBounds.getWidth(),
274 (int)deviceBounds.getHeight());
276 // Perform actual composite operation
277 compCtx.compose(buffer2.getRaster(), current.getRaster(),
278 buffer2.getRaster());
280 // This MUST call directly into the "action" method in CairoGraphics2D,
281 // not one of the wrappers, to ensure that the composite isn't processed
282 // more than once!
283 Composite oldComp = comp; // so that ComponentGraphics doesn't
284 comp = null; // process the composite again
285 boolean rv = super.drawImage(buffer2,
286 AffineTransform.getTranslateInstance(bounds.getX(),
287 bounds.getY()),
288 null, null);
289 comp = oldComp;
291 return rv;
294 private void createBuffer()
296 if (buffer == null)
298 WritableRaster rst;
299 rst = Raster.createWritableRaster(GtkVolatileImage.createGdkSampleModel(owner.width,
300 owner.height),
301 new Point(0,0));
303 buffer = new BufferedImage(GtkVolatileImage.gdkColorModel, rst,
304 GtkVolatileImage.gdkColorModel.isAlphaPremultiplied(),
305 new Hashtable());
307 else
309 Graphics2D g2d = ((Graphics2D)buffer.getGraphics());
311 g2d.setBackground(new Color(0,0,0,0));
312 g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
316 protected ColorModel getNativeCM()
318 // We should really return GtkVolatileImage.gdkColorModel ,
319 // but CairoGraphics2D doesn't handle alpha premultiplication properly (see
320 // the fixme in drawImage) so we use the naive Cairo model instead to trick
321 // the compositing context.
322 // Because getNativeCM() == getBufferCM() for this peer, it doesn't break.
323 return CairoSurface.cairoCM_pre;