Hi,

This code extends the CairoSurface optimization I submitted a few days ago, adding fallback code for VMs that copy JNI arrays rather than pinning them.

Also included is some cleanup, removing various un-used CairoSurface methods.

Cheers,
Francis

2007-02-21  Francis Kung  <[EMAIL PROTECTED]>

        * gnu/java/awt/peer/gtk/BufferedImageGraphcs.java
        (constructor): Add pre-multiplied colour model to types available for
        optimization.
        (updateBufferedImage): Change surface.getPixels() call to 
surface.getData().
        * gnu/java/awt/peer/gtk/CairoGraphics2D.java
        (drawImage): Add checks before using CairoSurface optimization.
        * gnu/java/awt/peer/gtk/CairoSurface.java
        (bufferPointer): Removed field.
        (sharedBuffer): New field.
        (CairoSurface(GtkImage)): Copy array rather than using setPixels() call.
        (CairoSurface(int,int,int)): Use getData() convenience method.
        (CairoSurface(SampleModel,CairoSurface,Rectangle,Point)): Remove 
reference
        to deleted bufferPointer field.
        (copyAreaNative): Update documentation, remove reference to 
bufferPointer.
        (copyAreaNative2): Remove reference to deleted bufferPointer field.
        (destroy): Remove reference to deleted bufferPointer field.
        (dispose): Updated to reflect new method signature for destroy().
        (drawSurface): Added documentation.
        (getData): New convience method.
        (getFlippedBuffer): Removed method parameters.
        (getGtkImage): Updated to reflect new method signature.
        (getPixels): Removed method.
        (nativeGetElem): Removed method.
        (netiveGetPixels): Removed method.
        (nativeSetElem): Removed method.
        (nativeSetPixels): Removed method.
        (setPixels): Removed method.
        (syncJavaToNative): New method.
        (syncNativeToJava): New method.
        * gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
        (draw): Sync buffers if necessary.
        (drawGlyphVector): Likewise.
        (drawImage): Likewise.
        (drawRenderedImage): Likewise,
        (fill): Likewise.
        * 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_copyAreaNative2): Use pointer 
to
        surface rather than pointer to buffer.
        (Java_gnu_java_awt_peer_gtk_CairoSurface_create): Provide fall-back for
        copied arrays.
        (Java_gnu_java_awt_peer_gtk_CairoSurface_destroy): Handle copied arrays.
        (Java_gnu_java_awt_peer_gtk_CairoSurface_getFlippedBuffer): Retrieve
        information on size using JNI calls.
        (Java_gnu_java_awt_peer_gtk_CairoSurface_getElem): Removed.
        (Java_gnu_java_awt_peer_gtk_CairoSurface_getPixels): Removed.
        (Java_gnu_java_awt_peer_gtk_CairoSurface_setElem): Removed.
        (Java_gnu_java_awt_peer_gtk_CairoSurface_setPixels): Removed.
        (Java_gnu_java_awt_peer_gtk_CairoSurface_syncJavaToNative): New 
function.
        (Java_gnu_java_awt_peer_gtk_CairoSurface_syncNativeToJava): New 
function.
        (BUFFER): Removed constant.
        (SHARED): New constant.
Index: gnu/java/awt/peer/gtk/CairoSurface.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/CairoSurface.java,v
retrieving revision 1.24
diff -u -r1.24 CairoSurface.java
--- gnu/java/awt/peer/gtk/CairoSurface.java	16 Feb 2007 20:28:45 -0000	1.24
+++ gnu/java/awt/peer/gtk/CairoSurface.java	21 Feb 2007 21:26:54 -0000
@@ -1,5 +1,5 @@
 /* CairoSurface.java
-   Copyright (C) 2006 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -73,9 +73,9 @@
   long surfacePointer;
 
   /**
-   * The native pointer to the image's data buffer
+   * Whether the data buffer is shared between java and cairo.
    */
-  long bufferPointer;
+  boolean sharedBuffer;
 
   // FIXME: use only the cairoCM_pre colormodel
   // since that's what Cairo really uses (is there a way to do this cheaply?
@@ -108,17 +108,7 @@
   /**
    * Destroys the cairo surface and frees the buffer.
    */
-  private native void destroy(long surfacePointer, long bufferPointer, int[] buf);
-
-  /**
-   * Gets buffer elements
-   */
-  private native int nativeGetElem(long bufferPointer, int i);
-  
-  /**
-   * Sets buffer elements.
-   */
-  private native void nativeSetElem(long bufferPointer, int i, int val);
+  private native void destroy(long surfacePointer, int[] buf);
 
   /**
    * Draws this image to a given CairoGraphics context, 
@@ -128,6 +118,30 @@
                                        double[] i2u, double alpha,
                                        int interpolation);
 
+  /**
+   * Synchronizes the image's data buffers, copying any changes made in the
+   * Java array into the native array.
+   * 
+   * This method should only be called if (sharedBuffers == false).
+   */
+  native void syncNativeToJava(long surfacePointer, int[] buffer);
+  
+  /**
+   * Synchronizes the image's data buffers, copying any changes made in the
+   * native array into the Java array.
+   * 
+   * This method should only be called if (sharedBuffers == false).
+   */
+  native void syncJavaToNative(long surfacePointer, int[] buffer);
+  
+  /**
+   * Draw this CairoSurface image onto a given Cairo context.
+   * 
+   * @param contextPointer A pointer to the context to draw onto.
+   * @param i2u The transformation matrix (cannot be null).
+   * @param alpha The alpha value to paint with ( 0 <= alpha <= 1).
+   * @param interpolation The interpolation type, as defined in CairoGraphcs2D.
+   */
   public void drawSurface(long contextPointer, double[] i2u, double alpha,
                           int interpolation)
   {
@@ -135,26 +149,13 @@
   }
 
   /**
-   * getPixels -return the pixels as a java array.
-   */
-  native int[] nativeGetPixels(long bufferPointer, int size);
-
-  public int[] getPixels(int size)
-  {
-    return nativeGetPixels(bufferPointer, size);
-  }
-
-  /**
-   * getPixels -return the pixels as a java array.
+   * Return the buffer, with the sample values of each pixel reversed
+   * (ie, in ABGR instead of ARGB). 
+   * 
+   * @return A pointer to a flipped buffer.  The memory is allocated in native
+   *        code, and must be explicitly freed when it is no longer needed.
    */
-  native void nativeSetPixels(long bufferPointer, int[] pixels);
-
-  public void setPixels(int[] pixels)
-  {
-    nativeSetPixels(bufferPointer, pixels);
-  }
-
-  native long getFlippedBuffer(long bufferPointer, int size);
+  native long getFlippedBuffer();
 
   /**
    * Create a cairo_surface_t with specified width and height.
@@ -168,8 +169,7 @@
   
   public CairoSurface(int x, int y, int width, int height)
   {
-    super(createCairoSampleModel(width, height),
-	      null, new Point(x, y));
+    super(createCairoSampleModel(width, height), null, new Point(x, y));
 
     if(width <= 0 || height <= 0)
       throw new IllegalArgumentException("Image must be at least 1x1 pixels.");
@@ -177,11 +177,10 @@
     this.width = width;
     this.height = height;
     dataBuffer = new DataBufferInt(width * height);
-    create(width, height, width, ((DataBufferInt)dataBuffer).getData());
+    create(width, height, width, getData());
 
-    if(surfacePointer == 0 || bufferPointer == 0)
+    if(surfacePointer == 0)
       throw new Error("Could not allocate bitmap.");
-
   }
   
   /**
@@ -194,7 +193,6 @@
     
     this.width = parent.width;
     this.height = parent.height;
-    this.bufferPointer = parent.bufferPointer;
     this.surfacePointer = parent.surfacePointer;
     this.dataBuffer = parent.dataBuffer;
   }
@@ -245,7 +243,7 @@
           }
       }
 
-    setPixels( data );
+    System.arraycopy(data, 0, getData(), 0, data.length);
   }
 
   /**
@@ -254,8 +252,7 @@
   public void dispose()
   {
     if(surfacePointer != 0 && parent == null)
-      destroy(surfacePointer, bufferPointer,
-              ((DataBufferInt)dataBuffer).getData());
+      destroy(surfacePointer, getData());
   }
 
   /**
@@ -271,8 +268,17 @@
    */
   public GtkImage getGtkImage()
   {
-    return new GtkImage( width, height,
-                         getFlippedBuffer(bufferPointer, width * height ));
+    return new GtkImage(width, height, getFlippedBuffer());
+  }
+  
+  /**
+   * Convenience method to quickly grab the data array backing this Raster.
+   * 
+   * @return The array behind the databuffer.
+   */
+  public int[] getData()
+  {
+    return ((DataBufferInt)dataBuffer).getData();
   }
 
   /**
@@ -323,16 +329,24 @@
   }
 
   /**
-   * Copy an area of the surface. Expects parameters must be within bounds. 
-   * Count on a segfault otherwise.
+   * Copy a portion of this surface to another area on the surface.  The given
+   * parameters must be within bounds - count on a segfault otherwise.
+   * 
+   * @param x The x coordinate of the area to be copied from.
+   * @param y The y coordinate of the area to be copied from.
+   * @param width The width of the area to be copied.
+   * @param height The height of the area to be copied.
+   * @param dx The destination x coordinate.
+   * @param dy The destination y coordinate.
+   * @param stride The scanline stride.
    */
-  native void copyAreaNative2(long bufferPointer, int x, int y, int width,
-                             int height, int dx, int dy, int stride);
   public void copyAreaNative(int x, int y, int width,
                              int height, int dx, int dy, int stride)
   {
-    copyAreaNative2(bufferPointer, x, y, width, height, dx, dy, stride);
+    copyAreaNative2(x, y, width, height, dx, dy, stride);
   }
+  native void copyAreaNative2(int x, int y, int width, int height,
+                              int dx, int dy, int stride);
   
   /**
    * Creates a SampleModel that matches Cairo's native format
Index: gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java,v
retrieving revision 1.9
diff -u -r1.9 CairoSurfaceGraphics.java
--- gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java	16 Feb 2007 20:28:45 -0000	1.9
+++ gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java	21 Feb 2007 21:26:54 -0000
@@ -116,6 +116,9 @@
    */
   public void draw(Shape s)
   {
+    if (!surface.sharedBuffer)
+      surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+    
     // Find total bounds of shape
     Rectangle r = findStrokedBounds(s);
     if (shiftDrawCalls)
@@ -140,10 +143,16 @@
         
         drawComposite(r.getBounds2D(), null);
       }
+    
+    if (!surface.sharedBuffer)
+      surface.syncNativeToJava(surface.surfacePointer, surface.getData());
   }
 
   public void fill(Shape s)
   {
+    if (!surface.sharedBuffer)
+      surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+    
     if (comp == null || comp instanceof AlphaComposite)
       super.fill(s);
     
@@ -159,10 +168,16 @@
         
         drawComposite(s.getBounds2D(), null);
       }
+    
+    if (!surface.sharedBuffer)
+      surface.syncNativeToJava(surface.surfacePointer, surface.getData());
   }
 
   public void drawRenderedImage(RenderedImage image, AffineTransform xform)
   {
+    if (!surface.sharedBuffer)
+      surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+    
     if (comp == null || comp instanceof AlphaComposite)
       super.drawRenderedImage(image, xform);
     
@@ -177,14 +192,20 @@
         
         drawComposite(buffer.getRaster().getBounds(), null);
       }
-
+    
+    if (!surface.sharedBuffer)
+      surface.syncNativeToJava(surface.surfacePointer, surface.getData());
   }
 
   protected boolean drawImage(Image img, AffineTransform xform,
                               Color bgcolor, ImageObserver obs)
   {
+    if (!surface.sharedBuffer)
+      surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+
+    boolean ret;
     if (comp == null || comp instanceof AlphaComposite)
-      return super.drawImage(img, xform, bgcolor, obs);
+      ret = super.drawImage(img, xform, bgcolor, obs);
     
     else
       {
@@ -212,12 +233,20 @@
         g2d.drawImage(img, xform, obs);
 
         // Perform compositing
-        return drawComposite(bounds, obs);
+        ret = drawComposite(bounds, obs);
       }
+    
+    if (!surface.sharedBuffer)
+      surface.syncNativeToJava(surface.surfacePointer, surface.getData());
+    
+    return ret;
   }
 
   public void drawGlyphVector(GlyphVector gv, float x, float y)
   {
+    if (!surface.sharedBuffer)
+      surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+    
     if (comp == null || comp instanceof AlphaComposite)
       super.drawGlyphVector(gv, x, y);
     
@@ -235,6 +264,9 @@
                                         bounds.getWidth(), bounds.getHeight());
         drawComposite(bounds, null);
       }
+    
+    if (!surface.sharedBuffer)
+      surface.syncNativeToJava(surface.surfacePointer, surface.getData());
   }
   
   private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
Index: gnu/java/awt/peer/gtk/CairoGraphics2D.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java,v
retrieving revision 1.63
diff -u -r1.63 CairoGraphics2D.java
--- gnu/java/awt/peer/gtk/CairoGraphics2D.java	12 Feb 2007 21:39:20 -0000	1.63
+++ gnu/java/awt/peer/gtk/CairoGraphics2D.java	21 Feb 2007 21:26:53 -0000
@@ -1520,7 +1520,9 @@
     if (comp instanceof AlphaComposite)
       alpha = ((AlphaComposite) comp).getAlpha();
 
-    if(raster instanceof CairoSurface)
+    if(raster instanceof CairoSurface
+        && ((CairoSurface)raster).getParent() == null
+        && ((CairoSurface)raster).sharedBuffer == true)
       {
         ((CairoSurface)raster).drawSurface(nativePointer, i2u, alpha,
                                            getInterpolation());
Index: gnu/java/awt/peer/gtk/BufferedImageGraphics.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/BufferedImageGraphics.java,v
retrieving revision 1.24
diff -u -r1.24 BufferedImageGraphics.java
--- gnu/java/awt/peer/gtk/BufferedImageGraphics.java	12 Feb 2007 21:39:20 -0000	1.24
+++ gnu/java/awt/peer/gtk/BufferedImageGraphics.java	21 Feb 2007 21:26:52 -0000
@@ -112,7 +112,8 @@
         hasFastCM = true;
         hasAlpha = false;
       }
-    else if(bi.getColorModel().equals(CairoSurface.cairoColorModel))
+    else if(bi.getColorModel().equals(CairoSurface.cairoColorModel)
+        || bi.getColorModel().equals(CairoSurface.cairoCM_pre))
       {
         hasFastCM = true;
         hasAlpha = true;
@@ -142,10 +143,7 @@
         int minY = image.getRaster().getSampleModelTranslateY();
 
         // Pull pixels directly out of data buffer
-        if(raster instanceof CairoSurface)
-          pixels = ((CairoSurface)raster).getPixels(raster.getWidth() * raster.getHeight());
-        else
-          pixels = ((DataBufferInt)raster.getDataBuffer()).getData();
+        pixels = ((DataBufferInt)raster.getDataBuffer()).getData();
 
         // Discard pixels that fall outside of the image's bounds
         // (ie, this image is actually a subimage of a different image)
@@ -170,10 +168,11 @@
       {
         pixels = CairoGraphics2D.findSimpleIntegerArray(image.getColorModel(),
                                                         image.getData());
+        if (pixels != null)
+          System.arraycopy(pixels, 0, surface.getData(),
+                           0, pixels.length);
       }
     
-    surface.setPixels( pixels );
-
     setup( cairo_t );
     setClip(0, 0, imageWidth, imageHeight);
   }
@@ -204,7 +203,7 @@
     width = bounds.width;
     height = bounds.height;
 
-    int[] pixels = surface.getPixels(imageWidth * imageHeight);
+    int[] pixels = surface.getData();
 
     if( x > imageWidth || y > imageHeight )
       return;
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoSurface.c
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoSurface.c,v
retrieving revision 1.22
diff -u -r1.22 gnu_java_awt_peer_gtk_CairoSurface.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoSurface.c	16 Feb 2007 20:28:46 -0000	1.22
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoSurface.c	21 Feb 2007 21:26:54 -0000
@@ -47,7 +47,7 @@
  * Field names in CairoSurface.java
  */
 #define SURFACE "surfacePointer"
-#define BUFFER "bufferPointer"
+#define SHARED "sharedBuffer"
 
 /* prototypes */
 static void setNativeObject( JNIEnv *env, jobject obj, void *ptr, const char *pointer );
@@ -62,10 +62,29 @@
 {
   cairo_surface_t* surface;
   jboolean isCopy;
+
+  /* Retrieve java-created data array */
   void *data = (*env)->GetIntArrayElements (env, buf, &isCopy);
-/*  FIXME: provide fallback if (isCopy == true) */
-  setNativeObject(env, obj, data, BUFFER);
+  
+  /* Set sharedBuffer variable */
+  jclass cls = (*env)->GetObjectClass (env, obj);
+  jfieldID field = (*env)->GetFieldID (env, cls, SHARED, "Z");
+  g_assert (field != 0);
+  
+  isCopy = JNI_TRUE;
+  
+  if (isCopy == JNI_TRUE)
+    {
+      (*env)->SetBooleanField (env, obj, field, JNI_FALSE);
+      void* temp = g_malloc(stride * height * 4);
+      memcpy(temp, data, stride * height * 4);
+      (*env)->ReleaseIntArrayElements (env, buf, data, 0);
+      data = temp;
+    }
+  else
+    (*env)->SetBooleanField (env, obj, field, JNI_TRUE);
 
+  /* Create the cairo surface and set the java pointer */  	
   surface = cairo_image_surface_create_for_data
     (data, CAIRO_FORMAT_ARGB32, width, height, stride * 4);
 
@@ -78,109 +97,28 @@
 JNIEXPORT void JNICALL 
 Java_gnu_java_awt_peer_gtk_CairoSurface_destroy
 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
- jlong surfacePointer, jlong bufferPointer, jintArray buf)
+ jlong surfacePointer, jintArray buf)
 {
-  void *buffer;
   cairo_surface_t* surface = JLONG_TO_PTR(void, surfacePointer);
-  buffer = JLONG_TO_PTR(void, bufferPointer);
+  void *data = cairo_image_surface_get_data(surface);
   if( surface != NULL )
   {
-  	(*env)->ReleaseIntArrayElements (env, buf, buffer, 0);
+  	/* Release or free the data buffer as appropriate */
+    jclass cls = (*env)->GetObjectClass (env, obj);
+    jfieldID field = (*env)->GetFieldID (env, cls, SHARED, "Z");
+    g_assert (field != 0);
+    jboolean sharedBuffer = (*env)->GetBooleanField (env, obj, field);
+
+    if (sharedBuffer == JNI_TRUE)
+  	  (*env)->ReleaseIntArrayElements (env, buf, data, 0);
+  	else
+  	  g_free(data);
+  	  
+  	/* Destroy the cairo surface itself */
     cairo_surface_destroy(surface);
   }
 }
 
-/**
- * Gets a pixel
- */
-JNIEXPORT jint JNICALL 
-Java_gnu_java_awt_peer_gtk_CairoSurface_nativeGetElem
-(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
- jlong bufferPointer, jint i)
-{
-  jint *pixeldata = JLONG_TO_PTR(void, bufferPointer);
-
-  if( pixeldata == NULL )
-    return 0;
-
-  return pixeldata[i];
-}
-
-/**
- * Sets a pixel
- */
-JNIEXPORT void JNICALL 
-Java_gnu_java_awt_peer_gtk_CairoSurface_nativeSetElem 
-(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
- jlong bufferPointer, jint i, jint val)
-{
-  jint *pixeldata = JLONG_TO_PTR(void, bufferPointer);
-
-  if( pixeldata == NULL )
-    return;
-
-  pixeldata[i] = val;
-}
-
-/**
- * Gets all pixels in an array
- */
-JNIEXPORT jintArray JNICALL 
-Java_gnu_java_awt_peer_gtk_CairoSurface_nativeGetPixels
-(JNIEnv *env __attribute((unused)), jobject obj __attribute((unused)),
- jlong bufferPointer, int size)
-{
-  jint *pixeldata, *jpixdata;
-  jintArray jpixels;
-
-  pixeldata = JLONG_TO_PTR(void, bufferPointer);
-  g_assert(pixeldata != NULL);
-
-  jpixels = (*env)->NewIntArray (env, size);
-  jpixdata = (*env)->GetIntArrayElements (env, jpixels, NULL);
-  memcpy (jpixdata, pixeldata, size * sizeof( jint ));
-
-  (*env)->ReleaseIntArrayElements (env, jpixels, jpixdata, 0);
-  return jpixels;
-}
-
-/**
- * Sets all pixels by an array.
- */
-JNIEXPORT void JNICALL 
-Java_gnu_java_awt_peer_gtk_CairoSurface_nativeSetPixels
-(JNIEnv *env, jobject obj, jlong bufferPointer, jintArray jpixels)
-{
-  jint *pixeldata, *jpixdata;
-  int size;
-  int width, height;
-  jclass cls;
-  jfieldID field;
-
-  if( jpixels == NULL )
-    return;
-
-  cls = (*env)->GetObjectClass (env, obj);
-  field = (*env)->GetFieldID (env, cls, "width", "I");
-  g_assert (field != 0);
-  width = (*env)->GetIntField (env, obj, field);
-
-  field = (*env)->GetFieldID (env, cls, "height", "I");
-  g_assert (field != 0);
-  height = (*env)->GetIntField (env, obj, field);
-
-  pixeldata = JLONG_TO_PTR(void, bufferPointer);
-  g_assert(pixeldata != NULL);
-  
-  jpixdata = (*env)->GetIntArrayElements (env, jpixels, NULL);
-  size = (*env)->GetArrayLength( env, jpixels );
-  if( size > width * height ) size = width * height; /* stop overflows. */
-  
-  memcpy (pixeldata, jpixdata, size * sizeof( jint ));
-
-  (*env)->ReleaseIntArrayElements (env, jpixels, jpixdata, 0);
-}
-
 JNIEXPORT void JNICALL
 Java_gnu_java_awt_peer_gtk_CairoSurface_nativeDrawSurface 
 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
@@ -246,17 +184,35 @@
 JNIEXPORT jlong JNICALL 
 Java_gnu_java_awt_peer_gtk_CairoSurface_getFlippedBuffer 
 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
- jlong bufferPointer, jint size)
+ jlong surfacePointer)
 {
+  cairo_surface_t* surface;
+  jint *src;
   jint *dst;
-  jint *src = JLONG_TO_PTR(void, bufferPointer);
-  int i;
-  int t;
+  int i, t, width, height;
+  jclass cls;
+  jfieldID field;
 
+  /* Retrieve pointer to cairo data buffer */  
+  surface = JLONG_TO_PTR(void, surfacePointer);
+  src = (jint*)cairo_image_surface_get_data(surface);
+  
+  /* Retrieve dimensions of surface, from java fields */
+  cls = (*env)->GetObjectClass (env, obj);
+  field = (*env)->GetFieldID (env, cls, "width", "I");
+  g_assert (field != 0);
+  width = (*env)->GetIntField (env, obj, field);
+
+  field = (*env)->GetFieldID (env, cls, "height", "I");
+  g_assert (field != 0);
+  height = (*env)->GetIntField (env, obj, field);
+
+  /* Create destination array */
   g_assert( src != NULL );
-  dst = g_malloc( size * sizeof( jint ) );
+  dst = g_malloc( width * height * sizeof( jint ) );
 
-  for(i = 0; i < size; i++ )
+  /* Copy data into destination array, reversing sample order of each pixel */
+  for(i = 0; i < (height * width); i++ )
     {
       t = (src[i] & 0x0000FF) << 16;
       dst[i] = (src[i] & 0x00FF0000) >> 16;
@@ -290,24 +246,30 @@
 JNIEXPORT void JNICALL 
 Java_gnu_java_awt_peer_gtk_CairoSurface_copyAreaNative2
 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
- jlong bufferPointer,
+ jlong surfacePointer,
  jint x, jint y, jint w, jint h, jint dx, jint dy, jint stride)
 {
   int row;
   int srcOffset, dstOffset;
   jint *temp;
-  jint *pixeldata = JLONG_TO_PTR(jint, bufferPointer);
+  
+  /* Retrieve pointer to cairo data buffer */  
+  cairo_surface_t* surface = JLONG_TO_PTR(void, surfacePointer);
+  jint *pixeldata = (jint*)cairo_image_surface_get_data(surface);
   g_assert( pixeldata != NULL );
 
+  /* Create temporary buffer and calculate offsets */
   temp = g_malloc( h * w * 4 );
   g_assert( temp != NULL );
 
   srcOffset = x + (y * stride);
   dstOffset = (x + dx) + ((y + dy) * stride);
 
+  /* Copy desired region into temporary buffer */
   for( row = 0; row < h; row++ )
     memcpy( temp + (w * row), pixeldata + srcOffset + (stride * row), w * 4 );
 
+  /* Copy out of buffer and to destination */
   for( row = 0; row < h; row++ )
     memcpy( pixeldata + dstOffset + (stride * row), temp + (w * row), w * 4 );
 
@@ -315,6 +277,50 @@
 }
 
 /*
+ * Synchronizes the java and native data buffers, copying any changes made in
+ * the java array into the native array.
+ * This method should only be called if (sharedBuffer == false). 
+ */
+JNIEXPORT void JNICALL 
+Java_gnu_java_awt_peer_gtk_CairoSurface_syncJavaToNative
+(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
+ jlong surfacePointer, jintArray buffer)
+{
+  /* Get size of java array */
+  int size = (*env)->GetArrayLength(env, buffer);
+  
+  /* Get native data buffer */
+  cairo_surface_t* surface = JLONG_TO_PTR(void, surfacePointer);
+  g_assert(surface != NULL);
+  void* nativeBuffer = cairo_image_surface_get_data(surface);
+  
+  /* Sync buffers */
+  (*env)->GetIntArrayRegion(env, buffer, 0, size, nativeBuffer);
+}
+
+/*
+ * Synchronizes the java and native data buffers, copying any changes made in
+ * the native array into the java array.
+ * This method should only be called if (sharedBuffer == false). 
+ */
+JNIEXPORT void JNICALL 
+Java_gnu_java_awt_peer_gtk_CairoSurface_syncNativeToJava
+(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
+ jlong surfacePointer, jintArray buffer)
+{
+  /* Get size of java array */
+  int size = (*env)->GetArrayLength(env, buffer);
+  
+  /* Get native data buffer */
+  cairo_surface_t* surface = JLONG_TO_PTR(void, surfacePointer);
+  g_assert(surface != NULL);
+  void* nativeBuffer = cairo_image_surface_get_data(surface);
+  
+  /* Sync buffers */
+  (*env)->SetIntArrayRegion(env, buffer, 0, size, nativeBuffer);
+}
+
+/*
  * Sets the native object field.
  */
 static void 
Index: include/gnu_java_awt_peer_gtk_CairoSurface.h
===================================================================
RCS file: /cvsroot/classpath/classpath/include/gnu_java_awt_peer_gtk_CairoSurface.h,v
retrieving revision 1.8
diff -u -r1.8 gnu_java_awt_peer_gtk_CairoSurface.h
--- include/gnu_java_awt_peer_gtk_CairoSurface.h	16 Feb 2007 20:28:46 -0000	1.8
+++ include/gnu_java_awt_peer_gtk_CairoSurface.h	21 Feb 2007 21:26:54 -0000
@@ -11,15 +11,13 @@
 #endif
 
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_create (JNIEnv *env, jobject, jint, jint, jint, jintArray);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_destroy (JNIEnv *env, jobject, jlong, jlong, jintArray);
-JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_nativeGetElem (JNIEnv *env, jobject, jlong, jint);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_nativeSetElem (JNIEnv *env, jobject, jlong, jint, jint);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_destroy (JNIEnv *env, jobject, jlong, jintArray);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_nativeDrawSurface (JNIEnv *env, jobject, jlong, jlong, jdoubleArray, jdouble, jint);
-JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_nativeGetPixels (JNIEnv *env, jobject, jlong, jint);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_nativeSetPixels (JNIEnv *env, jobject, jlong, jintArray);
-JNIEXPORT jlong JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_getFlippedBuffer (JNIEnv *env, jobject, jlong, jint);
+JNIEXPORT jlong JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_getFlippedBuffer (JNIEnv *env, jobject, jlong);
 JNIEXPORT jlong JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_nativeNewCairoContext (JNIEnv *env, jobject, jlong);
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_copyAreaNative2 (JNIEnv *env, jobject, jlong, jint, jint, jint, jint, jint, jint, jint);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_syncJavaToNative (JNIEnv *env, jobject, jlong, jintArray);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoSurface_syncNativeToJava (JNIEnv *env, jobject, jlong, jintArray);
 
 #ifdef __cplusplus
 }

Reply via email to