summaryrefslogtreecommitdiff
path: root/gnu/java
diff options
context:
space:
mode:
authorFrancis Kung <fkung@redhat.com>2007-02-16 20:28:45 +0000
committerFrancis Kung <fkung@redhat.com>2007-02-16 20:28:45 +0000
commita3d9c80d192ae0969f2cd4525b7a36d384f54fd4 (patch)
tree2f3d9b117da481bee1e814d87d492460e1176912 /gnu/java
parent7ada8d8b605c4ddcc8504140b185a89ced246cc7 (diff)
downloadclasspath-a3d9c80d192ae0969f2cd4525b7a36d384f54fd4.tar.gz
2007-02-16 Francis Kung <fkung@redhat.com>
* gnu/java/awt/ClasspathGraphicsEnvironment.java: New file. * gnu/java/awt/peer/gtk/CairoSurface.java (CairoDataBuffer): Removed inner class. (CairoSurface(int,int,int,int)): New constructor. (CairoSurface(int,int)): Delegate to new constructor. (CairoSurface(SampleModel,CairoSurface,Rectangle,Point)): New constructor for creating child rasters. (create): Added int[] parameter. (createChild): New method. (createCompatibleWritableRaster): New methods. (createTranslatedChild): New method. (createWritableChild): New method. (createWritableTranslatedChild): New method. (destroy): Added int[] parameter. (dispose): Only free native resources if this Surface has no parents. (isCompatibleColorModel): New method. (isCompatibleSampleModel): New method. * gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java (draw): Set transform, smarter bounds generation. (drawComposite): Improved clipping. (drawImage): Fixed bounds translation. (drawRenderedImage): Set transform in buffer. (fill): Set transform in buffer. * gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java (createRaster): New method. * java/awt/image/BufferedImage.java (BufferedImage(int,int,int)): Use optimized raster if possible. * include/gnu_java_awt_peer_gtk_CairoSurface.h: Regenerated. * native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoSurface.c (Java_gnu_java_awt_peer_gtk_CairoSurface_create): Share data buffer between Cairo and Java. (Java_gnu_java_awt_peer_gtk_CairoSurface_destroy): Free data array.
Diffstat (limited to 'gnu/java')
-rw-r--r--gnu/java/awt/ClasspathGraphicsEnvironment.java67
-rw-r--r--gnu/java/awt/peer/gtk/CairoSurface.java149
-rw-r--r--gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java92
-rw-r--r--gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java16
4 files changed, 250 insertions, 74 deletions
diff --git a/gnu/java/awt/ClasspathGraphicsEnvironment.java b/gnu/java/awt/ClasspathGraphicsEnvironment.java
new file mode 100644
index 000000000..865da1d95
--- /dev/null
+++ b/gnu/java/awt/ClasspathGraphicsEnvironment.java
@@ -0,0 +1,67 @@
+/* ClasspathGraphicsEnvironment.java
+ Copyright (C) 2007 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;
+
+import java.awt.GraphicsEnvironment;
+import java.awt.image.ColorModel;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
+
+/**
+ * This class extends the GraphicsEnvironment API with some Classpath-specific
+ * methods, in order to provide optimized graphics handling.
+ *
+ * @author Francis Kung <fkung@redhat.com>
+ */
+public abstract class ClasspathGraphicsEnvironment
+ extends GraphicsEnvironment
+{
+ /**
+ * Returns an appropriate Raster that can efficiently back a
+ * BufferedImage with the given ColorModel and SampleModel.
+ *
+ * @param cm The color model.
+ * @param sm The samepl model.
+ * @return An appropriate WritableRaster, or null if acceleration/optimization
+ * is not available for the given colour model / sample model.
+ */
+ public WritableRaster createRaster(ColorModel cm, SampleModel sm)
+ {
+ return null;
+ }
+}
diff --git a/gnu/java/awt/peer/gtk/CairoSurface.java b/gnu/java/awt/peer/gtk/CairoSurface.java
index d217c796d..cef420733 100644
--- a/gnu/java/awt/peer/gtk/CairoSurface.java
+++ b/gnu/java/awt/peer/gtk/CairoSurface.java
@@ -42,15 +42,20 @@ import gnu.java.awt.Buffers;
import java.awt.Graphics2D;
import java.awt.Point;
+import java.awt.Rectangle;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
+import java.awt.image.Raster;
+import java.awt.image.RasterFormatException;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;
import java.nio.ByteOrder;
+import java.util.Arrays;
import java.util.Hashtable;
/**
@@ -98,12 +103,12 @@ public class CairoSurface extends WritableRaster
* @param width, height - the image size
* @param stride - the buffer row stride. (in ints)
*/
- private native void create(int width, int height, int stride);
+ private native void create(int width, int height, int stride, int[] buf);
/**
* Destroys the cairo surface and frees the buffer.
*/
- private native void destroy(long surfacePointer, long bufferPointer);
+ private native void destroy(long surfacePointer, long bufferPointer, int[] buf);
/**
* Gets buffer elements
@@ -158,20 +163,40 @@ public class CairoSurface extends WritableRaster
*/
public CairoSurface(int width, int height)
{
+ this(0, 0, width, height);
+ }
+
+ public CairoSurface(int x, int y, int width, int height)
+ {
super(createCairoSampleModel(width, height),
- null, new Point(0, 0));
+ null, new Point(x, y));
if(width <= 0 || height <= 0)
throw new IllegalArgumentException("Image must be at least 1x1 pixels.");
this.width = width;
this.height = height;
- create(width, height, width);
+ dataBuffer = new DataBufferInt(width * height);
+ create(width, height, width, ((DataBufferInt)dataBuffer).getData());
if(surfacePointer == 0 || bufferPointer == 0)
throw new Error("Could not allocate bitmap.");
- dataBuffer = new CairoDataBuffer();
+ }
+
+ /**
+ * Create a Cairo Surface that is a subimage of another Cairo Surface
+ */
+ public CairoSurface(SampleModel sm, CairoSurface parent, Rectangle bounds,
+ Point origin)
+ {
+ super(sm, parent.dataBuffer, bounds, origin, parent);
+
+ this.width = parent.width;
+ this.height = parent.height;
+ this.bufferPointer = parent.bufferPointer;
+ this.surfacePointer = parent.surfacePointer;
+ this.dataBuffer = parent.dataBuffer;
}
/**
@@ -228,8 +253,9 @@ public class CairoSurface extends WritableRaster
*/
public void dispose()
{
- if(surfacePointer != 0)
- destroy(surfacePointer, bufferPointer);
+ if(surfacePointer != 0 && parent == null)
+ destroy(surfacePointer, bufferPointer,
+ ((DataBufferInt)dataBuffer).getData());
}
/**
@@ -276,34 +302,6 @@ public class CairoSurface extends WritableRaster
new Hashtable());
}
- private class CairoDataBuffer extends DataBuffer
- {
- public CairoDataBuffer()
- {
- super(DataBuffer.TYPE_INT, width * height);
- }
-
- /**
- * DataBuffer.getElem implementation
- */
- public int getElem(int bank, int i)
- {
- if(bank != 0 || i < 0 || i >= width * height)
- throw new IndexOutOfBoundsException(i+" size: "+width * height);
- return nativeGetElem(bufferPointer, i);
- }
-
- /**
- * DataBuffer.setElem implementation
- */
- public void setElem(int bank, int i, int val)
- {
- if(bank != 0 || i < 0 || i >= width*height)
- throw new IndexOutOfBoundsException(i+" size: "+width * height);
- nativeSetElem(bufferPointer, i, val);
- }
- }
-
/**
* Return a Graphics2D drawing to the CairoSurface.
*/
@@ -345,4 +343,85 @@ public class CairoSurface extends WritableRaster
new int[]{0x00FF0000, 0x0000FF00,
0x000000FF, 0xFF000000});
}
+
+ /**
+ * Returns whether this ColorModel is compatible with Cairo's native types.
+ *
+ * @param cm The color model to check.
+ * @return Whether it is compatible.
+ */
+ public static boolean isCompatibleColorModel(ColorModel cm)
+ {
+ return (cm.equals(cairoCM_pre) || cm.equals(cairoCM_opaque) ||
+ cm.equals(cairoColorModel));
+ }
+
+ /**
+ * Returns whether this SampleModel is compatible with Cairo's native types.
+ *
+ * @param sm The sample model to check.
+ * @return Whether it is compatible.
+ */
+ public static boolean isCompatibleSampleModel(SampleModel sm)
+ {
+ return (sm instanceof SinglePixelPackedSampleModel
+ && sm.getDataType() == DataBuffer.TYPE_INT
+ && Arrays.equals(((SinglePixelPackedSampleModel)sm).getBitMasks(),
+ new int[]{0x00FF0000, 0x0000FF00,
+ 0x000000FF, 0xFF000000}));
+ }
+
+ ///// Methods interhited from Raster and WritableRaster /////
+ public Raster createChild(int parentX, int parentY, int width, int height,
+ int childMinX, int childMinY, int[] bandList)
+ {
+ return createWritableChild(parentX, parentY, width, height,
+ childMinX, childMinY, bandList);
+ }
+
+ public WritableRaster createCompatibleWritableRaster()
+ {
+ return new CairoSurface(width, height);
+ }
+
+ public WritableRaster createCompatibleWritableRaster (int x, int y,
+ int w, int h)
+ {
+ return new CairoSurface(x, y, w, h);
+ }
+
+ public Raster createTranslatedChild(int childMinX, int childMinY)
+ {
+ return createWritableTranslatedChild(childMinX, childMinY);
+ }
+
+ public WritableRaster createWritableChild(int parentX, int parentY,
+ int w, int h, int childMinX,
+ int childMinY, int[] bandList)
+ {
+ if (true)
+ return this;
+ if (parentX < minX || parentX + w > minX + width
+ || parentY < minY || parentY + h > minY + height)
+ throw new RasterFormatException("Child raster extends beyond parent");
+
+ SampleModel sm = (bandList == null) ?
+ sampleModel :
+ sampleModel.createSubsetSampleModel(bandList);
+
+ return new CairoSurface(sm, this,
+ new Rectangle(childMinX, childMinY, w, h),
+ new Point(sampleModelTranslateX + childMinX - parentX,
+ sampleModelTranslateY + childMinY - parentY));
+ }
+
+ public WritableRaster createWritableTranslatedChild(int x, int y)
+ {
+ int tcx = sampleModelTranslateX - minX + x;
+ int tcy = sampleModelTranslateY - minY + y;
+
+ return new CairoSurface(sampleModel, this,
+ new Rectangle(x, y, width, height),
+ new Point(tcx, tcy));
+ }
}
diff --git a/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java b/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
index 36743b9c2..547946e0f 100644
--- a/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
+++ b/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
@@ -40,6 +40,7 @@ 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;
@@ -50,7 +51,6 @@ 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;
@@ -116,6 +116,15 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
*/
public void draw(Shape s)
{
+ // 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);
@@ -126,9 +135,10 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
Graphics2D g2d = (Graphics2D)buffer.getGraphics();
g2d.setStroke(this.getStroke());
g2d.setColor(this.getColor());
+ g2d.setTransform(transform);
g2d.draw(s);
- drawComposite(s.getBounds2D(), null);
+ drawComposite(r.getBounds2D(), null);
}
}
@@ -144,6 +154,7 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
Graphics2D g2d = (Graphics2D)buffer.getGraphics();
g2d.setPaint(this.getPaint());
g2d.setColor(this.getColor());
+ g2d.setTransform(transform);
g2d.fill(s);
drawComposite(s.getBounds2D(), null);
@@ -161,6 +172,7 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
Graphics2D g2d = (Graphics2D)buffer.getGraphics();
g2d.setRenderingHints(this.getRenderingHints());
+ g2d.setTransform(transform);
g2d.drawRenderedImage(image, xform);
drawComposite(buffer.getRaster().getBounds(), null);
@@ -187,14 +199,10 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
BufferedImage bImg = (BufferedImage) img;
// Find translated bounds
- Point2D origin = new Point2D.Double(bImg.getMinX(), bImg.getMinY());
- Point2D pt = new Point2D.Double(bImg.getWidth() + bImg.getMinX(),
- bImg.getHeight() + bImg.getMinY());
+ Rectangle2D bounds = new Rectangle(bImg.getMinX(), bImg.getMinY(),
+ bImg.getWidth(), bImg.getHeight());
if (xform != null)
- {
- origin = xform.transform(origin, origin);
- pt = xform.transform(pt, pt);
- }
+ bounds = getTransformedBounds(bounds, xform);
// Create buffer and draw image
createBuffer();
@@ -204,10 +212,7 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
g2d.drawImage(img, xform, obs);
// Perform compositing
- return drawComposite(new Rectangle2D.Double(origin.getX(),
- origin.getY(),
- pt.getX(), pt.getY()),
- obs);
+ return drawComposite(bounds, obs);
}
}
@@ -234,47 +239,58 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
{
- // Clip source to visible areas that need updating
- Rectangle2D clip = this.getClipBounds();
- Rectangle2D.intersect(bounds, clip, bounds);
- clip = new Rectangle(buffer.getMinX(), buffer.getMinY(),
- buffer.getWidth(), buffer.getHeight());
- Rectangle2D.intersect(bounds, clip, bounds);
+ // 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());
-
- // Get destination clip to bounds
- 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);
-
+
+ // Find subimage of main image for updating
BufferedImage current = CairoSurface.getBufferedImage(surface);
- current = current.getSubimage((int)deviceBounds.getX(),
- (int)deviceBounds.getY(),
- (int)deviceBounds.getWidth(),
- (int)deviceBounds.getHeight());
+ 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()),
- new Color(0,0,0,0), null);
+// AffineTransform.getTranslateInstance(bounds.getX(),
+// bounds.getY()),
+ AffineTransform.getTranslateInstance(0,0),
+ null, null);
+ setComposite(oldcomp);
+ updateColor();
return rv;
}
diff --git a/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java b/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
index db725b697..bd6daa2d1 100644
--- a/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
+++ b/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
@@ -38,16 +38,21 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
+import gnu.java.awt.ClasspathGraphicsEnvironment;
+
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
import java.awt.image.Raster;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
import java.util.Locale;
-public class GdkGraphicsEnvironment extends GraphicsEnvironment
+public class GdkGraphicsEnvironment extends ClasspathGraphicsEnvironment
{
private final int native_state = GtkGenericPeer.getUniqueInteger ();
@@ -139,4 +144,13 @@ public class GdkGraphicsEnvironment extends GraphicsEnvironment
* Used by GtkMouseInfoPeer.
*/
native int[] getMouseCoordinates();
+
+ public WritableRaster createRaster(ColorModel cm, SampleModel sm)
+ {
+ if (CairoSurface.isCompatibleSampleModel(sm)
+ && CairoSurface.isCompatibleColorModel(cm))
+ return new CairoSurface(sm.getWidth(), sm.getHeight());
+ else
+ return null;
+ }
}