Hi,

I finally got my improved (I hope) Swing painting to work. The situation
before was, that we always went up to the root window and painted
everything and let the clipping sort out what is not repainted.

This new painting is more finegrained. It makes use of the opaque and
isOptimizedPainting properties in JComponent, to sensibly find a paint
root that is:
- opaque
- not overlapped by another component

Also I changed addDirtyRegion, so it collapses overlapping dirty regions
into bigger chunks to avoid painting the same stuff more than once
within one work request.

I would like you to test this stuff. My hope is that painting is faster
for most cases, but since I haven't benchmarked this yet, I cannot
guarantee that. Also I want to avoid introducing any bugs with that, so
I won't blindly commit it before it's tested. Also, if you feel that it
makes performance worse, I will have to look into it a little deeper.

2005-10-12  Roman Kennke  <[EMAIL PROTECTED]>

        * javax/swing/JComponent.java
        (paintImmediately): Find the paint root more cleverly, instead
of
        going up to the root.
        (findPaintRoot): New helper method.
        (findOverlapFreeParent): New helper method.
        (findOpaqueParent): New helper method.
        * javax/swing/RepaintManager.java
        (addDirtyRegion): Collapse overlapping dirty regions into single
        regions.
        (paintDirtyRegions): Simple iterator over dirty regions and
        paint them. The optimizations are done in JComponent and
        addDirtyRegion.

Kind regards,
Roman
Index: javax/swing/JComponent.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JComponent.java,v
retrieving revision 1.68
diff -u -r1.68 JComponent.java
--- javax/swing/JComponent.java	12 Oct 2005 12:41:27 -0000	1.68
+++ javax/swing/JComponent.java	12 Oct 2005 20:05:45 -0000
@@ -1616,6 +1616,7 @@
   public void paintImmediately(Rectangle r)
   {
     // Try to find a root pane for this component.
+    //Component root = findPaintRoot(r);
     Component root = SwingUtilities.getRootPane(this);
     // If no root pane can be found, then try to find the Window that contains
     // this component.
@@ -2935,5 +2936,76 @@
         JComponent jc = (JComponent) children[i];
         jc.fireAncestorEvent(ancestor, id);
       }
+  }
+
+  private Component findPaintRoot(Rectangle c)
+  {
+    Component p = findOverlapFreeParent(c);
+    Component root = findOpaqueParent(p);
+    return root;
+  }
+
+  private Component findOverlapFreeParent(Rectangle clip)
+  {
+    Rectangle currentClip = clip;
+    Component found = this;
+    Container parent = this; 
+    while (parent != null)
+      {
+        Container newParent = parent.getParent();
+        if (newParent == null)
+          break;
+        // If the parent is optimizedDrawingEnabled, then its children are
+        // tiled and cannot have an overlapping child. Go directly to next
+        // parent.
+        if (newParent instanceof JComponent
+            && ((JComponent) newParent).isOptimizedDrawingEnabled())
+          {
+            parent = newParent;
+            continue;
+          }
+
+        // Otherwise we must check if one of the children of this parent
+        // overlaps with the current component.
+        Rectangle currentRect = SwingUtilities.convertRectangle(found,
+                                                                currentClip,
+                                                                newParent);
+        Component[] children = newParent.getComponents();
+        for (int i = 0; i < children.length; i++)
+          {
+            if (children[i] == parent)
+              continue;
+            Component c = children[i]; 
+            if (currentRect.intersects(c.getX(), c.getY(), c.getWidth(),
+                                       c.getHeight()))
+              {
+                // We found a parent whose children overlap with our current
+                // component. Make this the current component.
+                found = newParent;
+                currentClip = currentRect;
+                break;
+              }
+          }
+        parent = newParent;
+      }
+    return found;
+  }
+
+  private Component findOpaqueParent(Component c)
+  {
+    Component found = c;
+    while (true)
+      {
+        if ((found instanceof JComponent) && ((JComponent) found).isOpaque())
+          break;
+        else if (!(found instanceof JComponent))
+          break;
+        Container p = found.getParent();
+        if (p == null)
+          break;
+        else
+          found = p;
+      }
+    return found;
   }
 }
Index: javax/swing/RepaintManager.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/RepaintManager.java,v
retrieving revision 1.14
diff -u -r1.14 RepaintManager.java
--- javax/swing/RepaintManager.java	13 Sep 2005 09:17:21 -0000	1.14
+++ javax/swing/RepaintManager.java	12 Oct 2005 20:05:47 -0000
@@ -321,6 +321,32 @@
     Rectangle r = new Rectangle(x, y, w, h);
     if (dirtyComponents.containsKey(component))
       r = r.union((Rectangle)dirtyComponents.get(component));
+    else
+      {
+        for (Iterator i = dirtyComponents.entrySet().iterator(); i.hasNext();)
+          {
+            Map.Entry entry = (Map.Entry) i.next();
+            JComponent c = (JComponent) entry.getKey();
+            Rectangle dirty = (Rectangle) entry.getValue();
+            if (SwingUtilities.isDescendingFrom(c, component))
+              {
+                Rectangle oldDirty = SwingUtilities.convertRectangle(component,
+                                                                     dirty, c);
+                r = oldDirty.union(new Rectangle(x, y, w, h));
+                i.remove();
+                break;
+              }
+            else if (SwingUtilities.isDescendingFrom(component, c))
+              {
+                Rectangle newR = new Rectangle(x, y, w, h);
+                Rectangle newDirty = SwingUtilities.convertRectangle(c, newR,
+                                                                    component);
+                r = dirty.union(newDirty);
+                component = c;
+                break;
+              }
+          }
+      }
     dirtyComponents.put(component, r);
     if (! repaintWorker.isLive())
       {
@@ -430,40 +456,13 @@
   {
     // step 1: pull out roots and calculate spanning damage
 
-    HashMap roots = new HashMap();
     for (Enumeration e = dirtyComponents.keys(); e.hasMoreElements(); )
       {
         JComponent comp = (JComponent) e.nextElement();
-        if (! (comp.isVisible() && comp.isShowing()))
-          continue;
         Rectangle damaged = getDirtyRegion(comp);
-        if (damaged.width == 0 || damaged.height == 0)
-          continue;
-        JRootPane root = comp.getRootPane();
-        // If the component has no root, no repainting will occur.
-        if (root == null)
-          continue;
-        Rectangle rootDamage = SwingUtilities.convertRectangle(comp, damaged, root);
-        if (! roots.containsKey(root))
-          {
-            roots.put(root, rootDamage);
-          }
-        else
-          {
-            roots.put(root, ((Rectangle)roots.get(root)).union(rootDamage));
-          }
+        comp.paintImmediately(damaged);
       }
     dirtyComponents.clear();
-
-    // step 2: paint those roots
-    Iterator i = roots.entrySet().iterator();
-    while(i.hasNext())
-      {
-        Map.Entry ent = (Map.Entry) i.next();
-        JRootPane root = (JRootPane) ent.getKey();
-        Rectangle rect = (Rectangle) ent.getValue();
-        root.paintImmediately(rect);                	
-      }
   }
 
   /**

Attachment: signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil

_______________________________________________
Classpath-patches mailing list
Classpath-patches@gnu.org
http://lists.gnu.org/mailman/listinfo/classpath-patches

Reply via email to