diff options
| author | Francis Kung <fkung@redhat.com> | 2007-02-16 20:28:45 +0000 |
|---|---|---|
| committer | Francis Kung <fkung@redhat.com> | 2007-02-16 20:28:45 +0000 |
| commit | a3d9c80d192ae0969f2cd4525b7a36d384f54fd4 (patch) | |
| tree | 2f3d9b117da481bee1e814d87d492460e1176912 /gnu/java | |
| parent | 7ada8d8b605c4ddcc8504140b185a89ced246cc7 (diff) | |
| download | classpath-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.java | 67 | ||||
| -rw-r--r-- | gnu/java/awt/peer/gtk/CairoSurface.java | 149 | ||||
| -rw-r--r-- | gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java | 92 | ||||
| -rw-r--r-- | gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java | 16 |
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; + } } |
