diff options
author | Francis Kung <fkung@redhat.com> | 2006-11-21 16:34:03 +0000 |
---|---|---|
committer | Francis Kung <fkung@redhat.com> | 2006-11-21 16:34:03 +0000 |
commit | 488fa0077a655f3152140e74355b11b897352b1e (patch) | |
tree | 3e9eda675efa4542c6df0f4920e263946f8699a7 | |
parent | 03970a6b3aac93b82ebf1fa6f3467e35cf721aeb (diff) | |
download | classpath-488fa0077a655f3152140e74355b11b897352b1e.tar.gz |
2006-11-21 Francis Kung <fkung@redhat.com>
* gnu/java/awt/java2d/TexturePaintContext.java
(getRaster): Handle negative coordinate values.
* gnu/java/awt/peer/gtk/CairoGraphics2D.java
(setPaint): Moved custom paint processing to a new method.
(setPaintPixels): Added x, y parameters.
(getRealBounds): Added documentation.
(copy): Copy clipping information.
(drawLine): Process custom paints.
(setCustomPaint): New method.
(fill): Process custom paints.
(drawGlyphVector): Process custom paints.
(drawRect): Process custom paints.
(draw): Process custom paints.
* gnu/java/awt/peer/gtk/CairoSurface.java
(cairoCM_opaque): New constant.
* gnu/java/awt/peer/gtk/BufferedImageGraphics.java
(argb32): Removed constant.
(rgb32): Removed constant.
(BufferedImageGraphics(BufferedImage)): Updated constant names.
(BufferedImageGraphics(BufferedImageGraphics)): Copy color model flags.
(updateBufferedImage): Transform to device-space before updating.
* include/gnu_java_awt_peer_gtk_CairoGraphics2D.h
(Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setPaintPixels): Added x, y
parameters.
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c
(Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setPaintPixels): Set pattern
source at designated x, y origin.
-rw-r--r-- | ChangeLog | 30 | ||||
-rw-r--r-- | gnu/java/awt/java2d/TexturePaintContext.java | 6 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/BufferedImageGraphics.java | 23 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/CairoGraphics2D.java | 150 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/CairoSurface.java | 5 | ||||
-rw-r--r-- | include/gnu_java_awt_peer_gtk_CairoGraphics2D.h | 2 | ||||
-rw-r--r-- | native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c | 11 |
7 files changed, 176 insertions, 51 deletions
@@ -1,3 +1,33 @@ +2006-11-21 Francis Kung <fkung@redhat.com> + + * gnu/java/awt/java2d/TexturePaintContext.java + (getRaster): Handle negative coordinate values. + * gnu/java/awt/peer/gtk/CairoGraphics2D.java + (setPaint): Moved custom paint processing to a new method. + (setPaintPixels): Added x, y parameters. + (getRealBounds): Added documentation. + (copy): Copy clipping information. + (drawLine): Process custom paints. + (setCustomPaint): New method. + (fill): Process custom paints. + (drawGlyphVector): Process custom paints. + (drawRect): Process custom paints. + (draw): Process custom paints. + * gnu/java/awt/peer/gtk/CairoSurface.java + (cairoCM_opaque): New constant. + * gnu/java/awt/peer/gtk/BufferedImageGraphics.java + (argb32): Removed constant. + (rgb32): Removed constant. + (BufferedImageGraphics(BufferedImage)): Updated constant names. + (BufferedImageGraphics(BufferedImageGraphics)): Copy color model flags. + (updateBufferedImage): Transform to device-space before updating. + * include/gnu_java_awt_peer_gtk_CairoGraphics2D.h + (Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setPaintPixels): Added x, y + parameters. + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c + (Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setPaintPixels): Set pattern + source at designated x, y origin. + 2006-11-21 Roman Kennke <kennke@aicas.com> * java/awt/text/TextLayout.java diff --git a/gnu/java/awt/java2d/TexturePaintContext.java b/gnu/java/awt/java2d/TexturePaintContext.java index 840b61456..db0a2e658 100644 --- a/gnu/java/awt/java2d/TexturePaintContext.java +++ b/gnu/java/awt/java2d/TexturePaintContext.java @@ -177,6 +177,12 @@ public class TexturePaintContext // The modulo operation gives us the replication effect. dx = ((dx - minX) % width) + minX; dy = ((dy - minY) % height) + minY; + + // Handle possible negative values (replicating above the top-left) + if (dx < 0) + dx += width; + if (dy < 0) + dy += height; // Copy the pixel. pixel = source.getDataElements(dx, dy, pixel); diff --git a/gnu/java/awt/peer/gtk/BufferedImageGraphics.java b/gnu/java/awt/peer/gtk/BufferedImageGraphics.java index 341fa2a4e..f83be870d 100644 --- a/gnu/java/awt/peer/gtk/BufferedImageGraphics.java +++ b/gnu/java/awt/peer/gtk/BufferedImageGraphics.java @@ -54,7 +54,6 @@ import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DataBufferInt; -import java.awt.image.DirectColorModel; import java.awt.image.ImageObserver; import java.awt.image.ImageProducer; import java.awt.image.Raster; @@ -100,12 +99,6 @@ public class BufferedImageGraphics extends CairoGraphics2D */ private long cairo_t; - /** - * Colormodels we recognize for fast copying. - */ - static ColorModel rgb32 = new DirectColorModel(24, 0xFF0000, 0xFF00, 0xFF); - static ColorModel argb32 = new DirectColorModel(32, 0xFF0000, 0xFF00, 0xFF, - 0xFF000000); private boolean hasFastCM; private boolean hasAlpha; @@ -117,12 +110,12 @@ public class BufferedImageGraphics extends CairoGraphics2D imageHeight = bi.getHeight(); locked = false; - if(bi.getColorModel().equals(rgb32)) + if(bi.getColorModel().equals(CairoSurface.cairoCM_opaque)) { hasFastCM = true; hasAlpha = false; } - else if(bi.getColorModel().equals(argb32)) + else if(bi.getColorModel().equals(CairoSurface.cairoColorModel)) { hasFastCM = true; hasAlpha = true; @@ -176,8 +169,11 @@ public class BufferedImageGraphics extends CairoGraphics2D imageWidth = copyFrom.imageWidth; imageHeight = copyFrom.imageHeight; locked = false; + + hasFastCM = copyFrom.hasFastCM; + hasAlpha = copyFrom.hasAlpha; + copy( copyFrom, cairo_t ); - setClip(0, 0, surface.width, surface.height); } /** @@ -188,6 +184,13 @@ public class BufferedImageGraphics extends CairoGraphics2D if (locked) return; + double[] points = new double[]{x, y, width+x, height+y}; + transform.transform(points, 0, points, 0, 2); + x = (int)points[0]; + y = (int)points[1]; + width = (int)(points[2] - x); + height = (int)(points[3] - y); + int[] pixels = surface.getPixels(imageWidth * imageHeight); if( x > imageWidth || y > imageHeight ) diff --git a/gnu/java/awt/peer/gtk/CairoGraphics2D.java b/gnu/java/awt/peer/gtk/CairoGraphics2D.java index 68ada66fb..bb4debbf9 100644 --- a/gnu/java/awt/peer/gtk/CairoGraphics2D.java +++ b/gnu/java/awt/peer/gtk/CairoGraphics2D.java @@ -134,6 +134,7 @@ public abstract class CairoGraphics2D extends Graphics2D * The current paint */ Paint paint; + boolean customPaint; /** * The current stroke @@ -255,6 +256,8 @@ public abstract class CairoGraphics2D extends Graphics2D bg = new Color(g.bg.getRGB()); } + firstClip = g.firstClip; + originalClip = g.originalClip; clip = g.getClip(); if (g.transform == null) @@ -311,6 +314,11 @@ public abstract class CairoGraphics2D extends Graphics2D int width, int height, int dx, int dy); + /** + * Find the bounds of this graphics context, in device space. + * + * @return the bounds in device-space + */ protected abstract Rectangle2D getRealBounds(); ////// Native Methods //////////////////////////////////////////////////// @@ -336,7 +344,8 @@ public abstract class CairoGraphics2D extends Graphics2D int g2, int b2, int a2, boolean cyclic); private native void setPaintPixels(long pointer, int[] pixels, int w, - int h, int stride, boolean repeat); + int h, int stride, boolean repeat, + int x, int y); /** * Set the current transform matrix @@ -691,6 +700,7 @@ public abstract class CairoGraphics2D extends Graphics2D if (paint instanceof Color) { setColor((Color) paint); + customPaint = false; } else if (paint instanceof TexturePaint) { @@ -708,7 +718,8 @@ public abstract class CairoGraphics2D extends Graphics2D AffineTransformOp op = new AffineTransformOp(at, getRenderingHints()); BufferedImage texture = op.filter(img, null); int[] pixels = texture.getRGB(0, 0, width, height, null, 0, width); - setPaintPixels(nativePointer, pixels, width, height, width, true); + setPaintPixels(nativePointer, pixels, width, height, width, true, 0, 0); + customPaint = false; } else if (paint instanceof GradientPaint) { @@ -721,36 +732,90 @@ public abstract class CairoGraphics2D extends Graphics2D c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha(), c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha(), gp.isCyclic()); + customPaint = false; } else { - // Get bounds in device space - int minX = 0; - int minY = 0; - int width = (int)getRealBounds().getWidth(); - int height = (int)getRealBounds().getHeight(); - - Point2D origin = transform.transform(new Point2D.Double(minX, minY), - null); - Point2D extreme = transform.transform(new Point2D.Double(width + minX, - height + minY), - null); - minX = (int)origin.getX(); - minY = (int)origin.getY(); - width = (int)extreme.getX() - minX; - height = (int)extreme.getY() - minY; - - // Get raster of the paint background - PaintContext pc = paint.createContext(ColorModel.getRGBdefault(), - new Rectangle(minX, minY, - width, height), - getRealBounds(), - transform, hints); + customPaint = true; + } + } + + /** + * Sets a custom paint + * + * @param bounds the bounding box, in user space + */ + protected void setCustomPaint(Rectangle bounds) + { + if (paint instanceof Color || paint instanceof TexturePaint + || paint instanceof GradientPaint) + return; + + int userX = bounds.x; + int userY = bounds.y; + int userWidth = bounds.width; + int userHeight = bounds.height; + + // Find bounds in device space + Point2D origin = transform.transform(new Point2D.Double(userX, userY), + null); + Point2D extreme = transform.transform(new Point2D.Double(userWidth + userX, + userHeight + userY), + null); + int deviceX = (int)origin.getX(); + int deviceY = (int)origin.getY(); + int deviceWidth = (int)extreme.getX() - deviceX; + int deviceHeight = (int)extreme.getY() - deviceY; + + // Get raster of the paint background + PaintContext pc = paint.createContext(CairoSurface.cairoColorModel, + new Rectangle(deviceX, deviceY, + deviceWidth, + deviceHeight), + bounds, + transform, hints); + + Raster raster = pc.getRaster(deviceX, deviceY, deviceWidth, + deviceHeight); + + // Clear the transform matrix in Cairo, since the raster returned by the + // PaintContext is already in device-space + AffineTransform oldTx = new AffineTransform(transform); + setTransformImpl(new AffineTransform()); + + // Set pixels in cairo, aligning the top-left of the background image + // to the top-left corner in device space + if (pc.getColorModel().equals(CairoSurface.cairoColorModel) + && raster.getSampleModel().getTransferType() == DataBuffer.TYPE_INT) + { + // Use a fast copy if the paint context can uses a Cairo-compatible + // color model + setPaintPixels(nativePointer, + (int[])raster.getDataElements(0, 0, deviceWidth, + deviceHeight, null), + deviceWidth, deviceHeight, deviceWidth, false, + deviceX, deviceY); + } + + else if (pc.getColorModel().equals(CairoSurface.cairoCM_opaque) + && raster.getSampleModel().getTransferType() == DataBuffer.TYPE_INT) + { + // We can also optimize if the context uses a similar color model + // but without an alpha channel; we just add the alpha + int[] pixels = (int[])raster.getDataElements(0, 0, deviceWidth, + deviceHeight, null); - Raster raster = pc.getRaster(minX, minY, width, height); + for (int i = 0; i < pixels.length; i++) + pixels[i] = 0xff000000 | (pixels[i] & 0x00ffffff); - // Work around colorspace issues, and force use of the - // BufferedImage.getRGB method... this can be improved upon. + setPaintPixels(nativePointer, pixels, deviceWidth, deviceHeight, + deviceWidth, false, deviceX, deviceY); + } + + else + { + // Fall back on wrapping the raster in a BufferedImage, and + // use BufferedImage.getRGB() to do color-model conversion WritableRaster wr = Raster.createWritableRaster(raster.getSampleModel(), new Point(raster.getMinX(), raster.getMinY())); @@ -760,15 +825,15 @@ public abstract class CairoGraphics2D extends Graphics2D pc.getColorModel().isAlphaPremultiplied(), null); - // Set pixels in cairo setPaintPixels(nativePointer, - img2.getRGB(0, 0, width, height, null, 0, width), - width, height, width, false); - // setPaintPixels(nativePointer, - // raster.getPixels(0, 0, width, height, (int[])null), - // width, height, width, false); - // doesn't work... but would be much more efficient! + img2.getRGB(0, 0, deviceWidth, deviceHeight, null, 0, + deviceWidth), + deviceWidth, deviceHeight, deviceWidth, false, + deviceX, deviceY); } + + // Restore transform + setTransformImpl(oldTx); } public Stroke getStroke() @@ -1023,6 +1088,9 @@ public abstract class CairoGraphics2D extends Graphics2D return; } + if (customPaint) + setCustomPaint(s.getBounds()); + createPath(s, true); cairoStroke(nativePointer); } @@ -1031,6 +1099,9 @@ public abstract class CairoGraphics2D extends Graphics2D { createPath(s, false); + if (customPaint) + setCustomPaint(s.getBounds()); + double alpha = 1.0; if (comp instanceof AlphaComposite) alpha = ((AlphaComposite) comp).getAlpha(); @@ -1132,6 +1203,9 @@ public abstract class CairoGraphics2D extends Graphics2D // The coordinates being pairwise identical means one wants // to draw a single pixel. This is emulated by drawing // a one pixel sized rectangle. + if (customPaint) + setCustomPaint(new Rectangle(x1, y1, x2 - x1, y2 - y1)); + if (x1 == x2 && y1 == y2) cairoFillRect(nativePointer, x1, y1, 1, 1); else @@ -1140,6 +1214,9 @@ public abstract class CairoGraphics2D extends Graphics2D public void drawRect(int x, int y, int width, int height) { + if (customPaint) + setCustomPaint(new Rectangle(x, y, width, height)); + cairoDrawRect(nativePointer, shifted(x, shiftDrawCalls), shifted(y, shiftDrawCalls), width, height); } @@ -1550,6 +1627,9 @@ public abstract class CairoGraphics2D extends Graphics2D if( gv.getNumGlyphs() <= 0 ) return; + if (customPaint) + setCustomPaint(gv.getOutline().getBounds()); + if (comp instanceof AlphaComposite) alpha = ((AlphaComposite) comp).getAlpha(); if (gv instanceof FreetypeGlyphVector && alpha == 1.0) @@ -1908,4 +1988,4 @@ public abstract class CairoGraphics2D extends Graphics2D return rect; } -} +}
\ No newline at end of file diff --git a/gnu/java/awt/peer/gtk/CairoSurface.java b/gnu/java/awt/peer/gtk/CairoSurface.java index d3b3d4504..5b63e62e7 100644 --- a/gnu/java/awt/peer/gtk/CairoSurface.java +++ b/gnu/java/awt/peer/gtk/CairoSurface.java @@ -88,6 +88,11 @@ public class CairoSurface extends WritableRaster 0xFF000000, true, Buffers.smallestAppropriateTransferType(32)); + + // This CM corresponds to the CAIRO_FORMAT_RGB24 type in Cairo + static ColorModel cairoCM_opaque = new DirectColorModel(24, 0x00FF0000, + 0x0000FF00, + 0x000000FF); /** * Allocates and clears the buffer and creates the cairo surface. * @param width, height - the image size diff --git a/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h b/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h index f32b9381b..c4a7f1b02 100644 --- a/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h +++ b/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h @@ -14,7 +14,7 @@ JNIEXPORT jlong JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_init (JNIEnv JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_disposeNative (JNIEnv *env, jobject, jlong); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_drawPixels (JNIEnv *env, jobject, jlong, jintArray, jint, jint, jint, jdoubleArray, jdouble, jint); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setGradient (JNIEnv *env, jobject, jlong, jdouble, jdouble, jdouble, jdouble, jint, jint, jint, jint, jint, jint, jint, jint, jboolean); -JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setPaintPixels (JNIEnv *env, jobject, jlong, jintArray, jint, jint, jint, jboolean); +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setPaintPixels (JNIEnv *env, jobject, jlong, jintArray, jint, jint, jint, jboolean, jint, jint); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetMatrix (JNIEnv *env, jobject, jlong, jdoubleArray); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoScale (JNIEnv *env, jobject, jlong, jdouble, jdouble); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetOperator (JNIEnv *env, jobject, jlong, jint); diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c index 11b0426c6..bd63ac366 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c @@ -148,7 +148,8 @@ Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setGradient JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setPaintPixels (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), - jlong pointer, jintArray jarr, jint w, jint h, jint stride, jboolean repeat) + jlong pointer, jintArray jarr, jint w, jint h, jint stride, jboolean repeat, + jint x, jint y) { struct cairographics2d *gr = NULL; jint *jpixels = NULL; @@ -184,12 +185,12 @@ Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setPaintPixels gr->pattern = cairo_pattern_create_for_surface (gr->pattern_surface); g_assert (gr->pattern != NULL); + cairo_set_source_surface(gr->cr, gr->pattern_surface, x, y); + if (repeat) - cairo_pattern_set_extend (gr->pattern, CAIRO_EXTEND_REPEAT); + cairo_pattern_set_extend(cairo_get_source(gr->cr), CAIRO_EXTEND_REPEAT); else - cairo_pattern_set_extend (gr->pattern, CAIRO_EXTEND_NONE); - - cairo_set_source (gr->cr, gr->pattern); + cairo_pattern_set_extend(cairo_get_source(gr->cr), CAIRO_EXTEND_NONE); } JNIEXPORT void JNICALL |