Hi Francis,

I'm seeing this exception now when trying to run StatCVS:

[EMAIL PROTECTED]:~/mauve-cvs$ jamvm -Xmx300m -jar ~/statcvs-0.2.3/statcvs.jar logfile.log mauve
StatCVS - CVS statistics generation

Revision of install-sh does not match expected revision
Revision of mkinstalldirs does not match expected revision
java.lang.reflect.InvocationTargetException
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:372)
  at jamvm.java.lang.JarLauncher.main(JarLauncher.java:49)
Caused by: java.lang.ArrayIndexOutOfBoundsException: 307200
  at java.awt.image.DataBufferInt.getElem(DataBufferInt.java:200)
  at gnu.java.awt.Buffers.getData(Buffers.java:184)
at java.awt.image.SinglePixelPackedSampleModel.getDataElements(SinglePixelPackedSampleModel.java:258)
  at java.awt.image.Raster.getDataElements(Raster.java:651)
at gnu.java.awt.java2d.AlphaCompositeContext.compose(AlphaCompositeContext.java:217) at gnu.java.awt.java2d.AbstractGraphics2D.fillScanlineAA(AbstractGraphics2D.java:2109) at gnu.java.awt.java2d.AbstractGraphics2D.fillShapeAntialias(AbstractGraphics2D.java:2049) at gnu.java.awt.java2d.AbstractGraphics2D.fillShape(AbstractGraphics2D.java:1570) at gnu.java.awt.java2d.AbstractGraphics2D.fill(AbstractGraphics2D.java:545)
  at org.jfree.chart.JFreeChart.draw(JFreeChart.java:974)
  at org.jfree.chart.JFreeChart.createBufferedImage(JFreeChart.java:1213)
  at org.jfree.chart.JFreeChart.createBufferedImage(JFreeChart.java:1193)
at org.jfree.chart.ChartUtilities.writeChartAsPNG(ChartUtilities.java:174)
  at org.jfree.chart.ChartUtilities.saveChartAsPNG(ChartUtilities.java:329)
  at org.jfree.chart.ChartUtilities.saveChartAsPNG(ChartUtilities.java:300)
  at net.sf.statcvs.renderer.Chart.saveChart(Chart.java:93)
  at net.sf.statcvs.renderer.LOCChart.<init>(LOCChart.java:78)
  at net.sf.statcvs.output.HTMLOutput.createLOCChart(HTMLOutput.java:298)
  at net.sf.statcvs.output.HTMLOutput.createHTMLSuite(HTMLOutput.java:180)
  at net.sf.statcvs.Main.generateDefaultHTMLSuite(Main.java:193)
  at net.sf.statcvs.Main.main(Main.java:75)
  at java.lang.reflect.Method.invokeNative(Native Method)
  ...2 more

I haven't tried to reduce this to a simple test case yet...but I will if you need me to.

Regards,

Dave


Francis Kung wrote:
Hi,

The attached patch, committed, includes a number of fixes to our
handling of custom paint contexts.

This significantly improves our compliance to the Batik test-suite.

I've also included some drastic performance enhancements when doing
java2d operations with a custom paint context; our performance on some
Batik tests is now comparable to Sun's.

Cheers,
Francis


2006-11-21  Francis Kung  <[EMAIL PROTECTED]>

        * 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.

------------------------------------------------------------------------

Index: gnu/java/awt/peer/gtk/BufferedImageGraphics.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/BufferedImageGraphics.java,v
retrieving revision 1.15
diff -u -r1.15 BufferedImageGraphics.java
--- gnu/java/awt/peer/gtk/BufferedImageGraphics.java    19 Oct 2006 20:50:52 
-0000      1.15
+++ gnu/java/awt/peer/gtk/BufferedImageGraphics.java    21 Nov 2006 16:21:15 
-0000
@@ -54,7 +54,6 @@
 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 @@
    */
   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 @@
     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 @@
     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 @@
     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 )
Index: gnu/java/awt/peer/gtk/CairoSurface.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/CairoSurface.java,v
retrieving revision 1.21
diff -u -r1.21 CairoSurface.java
--- gnu/java/awt/peer/gtk/CairoSurface.java     18 Oct 2006 19:00:31 -0000      
1.21
+++ gnu/java/awt/peer/gtk/CairoSurface.java     21 Nov 2006 16:21:16 -0000
@@ -88,6 +88,11 @@
                                                        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
Index: gnu/java/awt/peer/gtk/CairoGraphics2D.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java,v
retrieving revision 1.50
diff -u -r1.50 CairoGraphics2D.java
--- gnu/java/awt/peer/gtk/CairoGraphics2D.java  21 Nov 2006 14:14:26 -0000      
1.50
+++ gnu/java/awt/peer/gtk/CairoGraphics2D.java  21 Nov 2006 16:21:16 -0000
@@ -134,6 +134,7 @@
    * The current paint
    */
   Paint paint;
+  boolean customPaint;
/**
    * The current stroke
@@ -255,6 +256,8 @@
           bg = new Color(g.bg.getRGB());
       }
+ firstClip = g.firstClip;
+    originalClip = g.originalClip;
     clip = g.getClip();
if (g.transform == null)
@@ -311,6 +314,11 @@
                                       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 @@
                                   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 @@
     if (paint instanceof Color)
       {
         setColor((Color) paint);
+        customPaint = false;
       }
     else if (paint instanceof TexturePaint)
       {
@@ -708,7 +718,8 @@
        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 @@
                     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 @@
                                                
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 @@
         return;
       }
+ if (customPaint)
+      setCustomPaint(s.getBounds());
+ createPath(s, true);
     cairoStroke(nativePointer);
   }
@@ -1031,6 +1099,9 @@
   {
     createPath(s, false);
+ if (customPaint)
+      setCustomPaint(s.getBounds());
+ double alpha = 1.0;
     if (comp instanceof AlphaComposite)
       alpha = ((AlphaComposite) comp).getAlpha();
@@ -1132,6 +1203,9 @@
     // 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 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 @@
     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 @@
return rect;
   }
-}
+}
\ No newline at end of file
Index: include/gnu_java_awt_peer_gtk_CairoGraphics2D.h
===================================================================
RCS file: 
/cvsroot/classpath/classpath/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h,v
retrieving revision 1.13
diff -u -r1.13 gnu_java_awt_peer_gtk_CairoGraphics2D.h
--- include/gnu_java_awt_peer_gtk_CairoGraphics2D.h     25 Oct 2006 21:07:59 
-0000      1.13
+++ include/gnu_java_awt_peer_gtk_CairoGraphics2D.h     21 Nov 2006 16:21:16 
-0000
@@ -14,7 +14,7 @@
 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);
Index: gnu/java/awt/java2d/TexturePaintContext.java
===================================================================
RCS file: 
/cvsroot/classpath/classpath/gnu/java/awt/java2d/TexturePaintContext.java,v
retrieving revision 1.2
diff -u -r1.2 TexturePaintContext.java
--- gnu/java/awt/java2d/TexturePaintContext.java        12 Sep 2006 19:05:38 
-0000      1.2
+++ gnu/java/awt/java2d/TexturePaintContext.java        21 Nov 2006 16:21:15 
-0000
@@ -177,6 +177,12 @@
             // 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);
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c
===================================================================
RCS file: 
/cvsroot/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c,v
retrieving revision 1.18
diff -u -r1.18 gnu_java_awt_peer_gtk_CairoGraphics2D.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c 23 Oct 2006 
19:55:38 -0000      1.18
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c 21 Nov 2006 
16:21:16 -0000
@@ -148,7 +148,8 @@
 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 @@
   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


Reply via email to