Hi,

We had another deadlock between ComponentGraphics and CairoGraphics if
the image wasn't a BufferedImage already. Then CairoGraphics would try
to convert the Image to an BuffereImage which in some cases would need
the gdk lock. So this patch makes sure that ComponentGraphics always
passes an BufferedImage to its super class. While debugging this I
noticed that ComponentGraphics would not directly draw a
GtkVolatileImage if the transform set on the Graphics2D instance was the
identity transform. That was easily solved and should make some
operations a little faster. (Not really that many. I only observed
JMenus using backbuffers that were drawn with the identity transform
set).

2006-06-13  Mark Wielaard  <[EMAIL PROTECTED]>

    * gnu/java/awt/peer/gtk/CairoGraphics2D.java (drawImage): Don't
    allocate unused AffineTransform. Add comment about conversion to
    BufferedImage.
    * gnu/java/awt/peer/gtk/ComponentGraphics.java (drawImage):
    Recognize identity transform as "easy". Always convert to
    BufferedImage before calling super.

Committed,

Mark
Index: gnu/java/awt/peer/gtk/CairoGraphics2D.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java,v
retrieving revision 1.21
diff -u -r1.21 CairoGraphics2D.java
--- gnu/java/awt/peer/gtk/CairoGraphics2D.java	12 Jun 2006 21:10:11 -0000	1.21
+++ gnu/java/awt/peer/gtk/CairoGraphics2D.java	13 Jun 2006 12:48:51 -0000
@@ -1144,7 +1144,7 @@
     // other way around. Therefore to get the "user -> pixel" transform 
     // that cairo wants from "image -> user" transform that we currently
     // have, we will need to invert the transformation matrix.
-    AffineTransform invertedXform = new AffineTransform();
+    AffineTransform invertedXform;
 
     try
       {
@@ -1157,6 +1157,9 @@
       }
 
     // Unrecognized image - convert to a BufferedImage
+    // Note - this can get us in trouble when the gdk lock is re-acquired.
+    // for example by VolatileImage. See ComponentGraphics for how we work
+    // around this.
     if( !(img instanceof BufferedImage) )
       {
 	ImageProducer source = img.getSource();
Index: gnu/java/awt/peer/gtk/ComponentGraphics.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java,v
retrieving revision 1.15
diff -u -r1.15 ComponentGraphics.java
--- gnu/java/awt/peer/gtk/ComponentGraphics.java	12 Jun 2006 21:10:11 -0000	1.15
+++ gnu/java/awt/peer/gtk/ComponentGraphics.java	13 Jun 2006 12:48:51 -0000
@@ -46,6 +46,7 @@
 import java.awt.Image;
 import java.awt.Rectangle;
 import java.awt.Shape;
+import java.awt.Toolkit;
 import java.awt.Point;
 import java.awt.font.FontRenderContext;
 import java.awt.font.GlyphVector;
@@ -53,6 +54,7 @@
 import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
 import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
 import java.awt.image.ImagingOpException;
 import java.awt.image.RenderedImage;
 
@@ -277,33 +279,84 @@
   
   public boolean drawImage(Image img, int x, int y, ImageObserver observer)
   {
-    if (img instanceof GtkVolatileImage
-        && transform.getType() == AffineTransform.TYPE_TRANSLATION)
+    // If it is a GtkVolatileImage with an "easy" transform then
+    // draw directly. Always pass a BufferedImage to super to avoid
+    // deadlock (see Note in CairoGraphics.drawImage()).
+    if (img instanceof GtkVolatileImage)
       {
-        x += transform.getTranslateX();
-        y += transform.getTranslateY();
         GtkVolatileImage vimg = (GtkVolatileImage) img;
-	drawVolatile( component, vimg.nativePointer,
-                      x, y, vimg.width, vimg.height );
-	return true;
-      }      
-    return super.drawImage( img, x, y, observer );
+	int type = transform.getType();
+	if (type == AffineTransform.TYPE_IDENTITY)
+	  {
+	    drawVolatile(component, vimg.nativePointer,
+			 x, y, vimg.width, vimg.height);
+	    return true;
+	  }
+	  else if (type == AffineTransform.TYPE_TRANSLATION)
+	  {
+	    x += transform.getTranslateX();
+	    y += transform.getTranslateY();
+	    drawVolatile(component, vimg.nativePointer,
+			 x, y, vimg.width, vimg.height);
+	    return true;
+	  }
+	else
+	  return super.drawImage(vimg.getSnapshot(), x, y, observer);
+      }
+
+    BufferedImage bimg;
+    if (img instanceof BufferedImage)
+      bimg = (BufferedImage) img;
+    else
+      {
+	ImageProducer source = img.getSource();
+        if (source == null)
+          return false;
+        bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source);
+      }
+    return super.drawImage(bimg, x, y, observer);
   }
   
   public boolean drawImage(Image img, int x, int y, int width, int height,
                            ImageObserver observer)
   {
-    if( img instanceof GtkVolatileImage
-        && transform.getType() == AffineTransform.TYPE_TRANSLATION)
+    // If it is a GtkVolatileImage with an "easy" transform then
+    // draw directly. Always pass a BufferedImage to super to avoid
+    // deadlock (see Note in CairoGraphics.drawImage()).
+    if (img instanceof GtkVolatileImage)
       {
-        x += transform.getTranslateX();
-        y += transform.getTranslateY();
         GtkVolatileImage vimg = (GtkVolatileImage) img;
-	drawVolatile( component, vimg.nativePointer, x, y, 
-		      width, height );
-	return true;
-      }      
-    return super.drawImage( img, x, y, width, height, observer );
+	int type = transform.getType();
+	if (type == AffineTransform.TYPE_IDENTITY)
+	  {
+	    drawVolatile(component, vimg.nativePointer,
+			 x, y, width, height);
+	    return true;
+	  }
+	  else if (type == AffineTransform.TYPE_TRANSLATION)
+	  {
+	    x += transform.getTranslateX();
+	    y += transform.getTranslateY();
+	    drawVolatile(component, vimg.nativePointer,
+			 x, y, width, height);
+	    return true;
+	  }
+	else
+	  return super.drawImage(vimg.getSnapshot(), x, y,
+				 width, height, observer);
+      }
+
+    BufferedImage bimg;
+    if (img instanceof BufferedImage)
+      bimg = (BufferedImage) img;
+    else
+      {
+	ImageProducer source = img.getSource();
+        if (source == null)
+          return false;
+        bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source);
+      }
+    return super.drawImage(bimg, x, y, width, height, observer);
   }
 
 }

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to