Hi,

This patch optimizes the drawing of a CairoSurface onto another cairo context, and adds support for drawing subimages/subraster in this way.

Cheers,
Francis


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

        * gnu/java/awt/peer/gtk/CairoGraphics2D.java
        (drawCairoSurface): New method.
        (drawImage(Image,AffineTransform,Color,ImageObserver)): Use new
        drawCairoSurface() method.
        * gnu/java/awt/peer/gtk/CairoSurface.java
        (CairoSurface(SampleModel,CairoSurface,Rectangle,Point)): Copy correct
        width/height values, and copy sharedBuffer value.
        (createWritableChild): Remove debug line.
        (drawSurface): Removed method.
        * gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
        (drawComposite): Translate image when drawing.
Index: gnu/java/awt/peer/gtk/CairoSurface.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/CairoSurface.java,v
retrieving revision 1.26
diff -u -r1.26 CairoSurface.java
--- gnu/java/awt/peer/gtk/CairoSurface.java	22 Feb 2007 21:18:43 -0000	1.26
+++ gnu/java/awt/peer/gtk/CairoSurface.java	23 Feb 2007 22:15:41 -0000
@@ -43,7 +43,9 @@
 import java.awt.Graphics2D;
 import java.awt.Point;
 import java.awt.Rectangle;
+import java.awt.Shape;
 import java.awt.color.ColorSpace;
+import java.awt.geom.AffineTransform;
 import java.awt.image.BufferedImage;
 import java.awt.image.ColorModel;
 import java.awt.image.DataBuffer;
@@ -135,20 +137,6 @@
   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)
-  {
-    nativeDrawSurface(surfacePointer, contextPointer, i2u, alpha, interpolation);
-  }
-
-  /**
    * Return the buffer, with the sample values of each pixel reversed
    * (ie, in ABGR instead of ARGB). 
    * 
@@ -191,9 +179,10 @@
   {
     super(sm, parent.dataBuffer, bounds, origin, parent);
     
-    this.width = parent.width;
-    this.height = parent.height;
+    this.width = super.width;
+    this.height = super.height;
     this.surfacePointer = parent.surfacePointer;
+    this.sharedBuffer = parent.sharedBuffer;
     this.dataBuffer = parent.dataBuffer;
   }
 
@@ -414,8 +403,6 @@
                                             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");
Index: gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java,v
retrieving revision 1.10
diff -u -r1.10 CairoSurfaceGraphics.java
--- gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java	21 Feb 2007 21:47:36 -0000	1.10
+++ gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java	23 Feb 2007 22:15:41 -0000
@@ -317,9 +317,8 @@
     // 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()),
-                               AffineTransform.getTranslateInstance(0,0),
+                                 AffineTransform.getTranslateInstance(bounds.getX(),
+                                                                      bounds.getY()),
                                  null, null);
     setComposite(oldcomp);
     updateColor();
Index: gnu/java/awt/peer/gtk/CairoGraphics2D.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java,v
retrieving revision 1.64
diff -u -r1.64 CairoGraphics2D.java
--- gnu/java/awt/peer/gtk/CairoGraphics2D.java	21 Feb 2007 21:47:37 -0000	1.64
+++ gnu/java/awt/peer/gtk/CairoGraphics2D.java	23 Feb 2007 22:15:41 -0000
@@ -1521,11 +1521,9 @@
       alpha = ((AlphaComposite) comp).getAlpha();
 
     if(raster instanceof CairoSurface
-        && ((CairoSurface)raster).getParent() == null
         && ((CairoSurface)raster).sharedBuffer == true)
       {
-        ((CairoSurface)raster).drawSurface(nativePointer, i2u, alpha,
-                                           getInterpolation());
+        drawCairoSurface((CairoSurface)raster, xform, alpha, getInterpolation());
         updateColor();
         return true;
       }
@@ -1671,6 +1669,67 @@
   {
     return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, observer);
   }
+  
+  /**
+   * Optimized method for drawing a CairoSurface onto this graphics context.
+   * 
+   * @param surface The surface to draw.
+   * @param tx The transformation matrix (cannot be null).
+   * @param alpha The alpha value to paint with ( 0 <= alpha <= 1).
+   * @param interpolation The interpolation type.
+   */
+  private void drawCairoSurface(CairoSurface surface, AffineTransform tx,
+                                double alpha, int interpolation)
+  {
+    // Find offset required if this surface is a sub-raster, and append offset
+    // to transformation.
+    if (surface.getSampleModelTranslateX() != 0
+        || surface.getSampleModelTranslateY() != 0)
+      {
+        Point2D origin = new Point2D.Double(0, 0);
+        Point2D offset = new Point2D.Double(surface.getSampleModelTranslateX(),
+                                            surface.getSampleModelTranslateY());
+        
+        tx.transform(origin, origin);
+        tx.transform(offset, offset);
+        
+        tx.translate(offset.getX() - origin.getX(),
+                     offset.getY() - origin.getY());
+      }
+    
+    // Find dimensions of this surface relative to the root parent surface
+    Rectangle bounds = new Rectangle(-surface.getSampleModelTranslateX(),
+                                     -surface.getSampleModelTranslateY(),
+                                     surface.width, surface.height);
+    
+    // Clip to the translated image
+    //   We use direct cairo methods to avoid the overhead of maintaining a
+    //   java copy of the clip, since we will be reverting it immediately
+    //   after drawing
+    Shape newBounds = tx.createTransformedShape(bounds);
+    cairoSave(nativePointer);
+    cairoResetClip(nativePointer);
+    walkPath(newBounds.getPathIterator(null), false);
+    cairoClip(nativePointer);
+    
+    // Draw the surface
+    try
+    {
+      double[] i2u = new double[6];
+      tx.createInverse().getMatrix(i2u);
+      surface.nativeDrawSurface(surface.surfacePointer, nativePointer, i2u,
+                                alpha, interpolation);
+    }
+    catch (NoninvertibleTransformException ex)
+    {
+      // This should never happen(?), so we don't need to do anything here.
+      ;
+    }
+    
+    // Restore clip
+    cairoRestore(nativePointer);
+  }
+
 
   ///////////////////////// TEXT METHODS ////////////////////////////////////
 

Reply via email to