I realised than immediate going to the highest possible root breaks
Roman's scrolling optimizations in JViewport. To fix this, I moved the
redundant repaint avoidance from addDirtyRegion to paintDirtyRegions,
where all regions to be painted are already known and it is possible to
pick the lowest possible root. The algorithm is now more complex.
My previous change, however, was not the only reason why the blitting is
broken. To restore blitting completely, the
JComponent.findOverlapFreeParents must stop iteration after reaching the
JViewport and not proceed upward. Otherwise JViewport becomes no longer
a painting root.
2006-05-15 Audrius Meskauskas <[EMAIL PROTECTED]>
* javax/swing/JComponent.java (findOverlapParent): Stop loop at
JViewport's.
* javax/swing/RepaintManager.java (addDirtyRegion): Always add the given
region. (paintDirtyRegions): Rewritten.
Index: javax/swing/JComponent.java
===================================================================
RCS file: /sources/classpath/classpath/javax/swing/JComponent.java,v
retrieving revision 1.119
diff -u -r1.119 JComponent.java
--- javax/swing/JComponent.java 4 May 2006 13:20:44 -0000 1.119
+++ javax/swing/JComponent.java 15 May 2006 16:56:47 -0000
@@ -3554,7 +3554,10 @@
Rectangle currentClip = clip;
Component found = this;
Container parent = this;
- while (parent != null && !(parent instanceof Window))
+ // Path up is stopped at viewports, allowing to use viewport
+ // painting optimizations.
+ while (parent != null && !(parent instanceof Window)
+ && !(parent instanceof JViewport))
{
Container newParent = parent.getParent();
if (newParent == null || newParent instanceof Window)
Index: javax/swing/RepaintManager.java
===================================================================
RCS file: /sources/classpath/classpath/javax/swing/RepaintManager.java,v
retrieving revision 1.32
diff -u -r1.32 RepaintManager.java
--- javax/swing/RepaintManager.java 15 May 2006 10:14:18 -0000 1.32
+++ javax/swing/RepaintManager.java 15 May 2006 16:56:48 -0000
@@ -50,6 +50,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -424,13 +425,6 @@
return;
Component parent = component.getParent();
- if (parent instanceof JComponent)
- {
- // If there is a delegateable parent, add the parent region instead.
- addDirtyRegion((JComponent) parent, x + component.getX(),
- y + component.getY(), w, h);
- return;
- }
component.computeVisibleRect(rectCache);
SwingUtilities.computeIntersection(x, y, w, h, rectCache);
@@ -564,8 +558,8 @@
}
/**
- * Repaint all regions of all components which have been marked dirty in
- * the [EMAIL PROTECTED] #dirtyComponents} table.
+ * Repaint all regions of all components which have been marked dirty in the
+ * [EMAIL PROTECTED] #dirtyComponents} table.
*/
public void paintDirtyRegions()
{
@@ -581,17 +575,57 @@
dirtyComponentsWork = swap;
}
- ArrayList repaintOrder = new ArrayList(dirtyComponentsWork.size());;
- // We sort the components by their size here. This way we have a good
- // chance that painting the bigger components also paints the smaller
- // components and we don't need to paint them twice.
- repaintOrder.addAll(dirtyComponentsWork.keySet());
-
- if (comparator == null)
- comparator = new ComponentComparator();
- Collections.sort(repaintOrder, comparator);
+ HashSet components = new HashSet(dirtyComponentsWork.keySet());
+ boolean someRemoved;
+ boolean cRemoved;
+
+ do
+ {
+ Iterator en = components.iterator();
+ someRemoved = false;
+ // Where possible, do not repaint the component, extending the
+ // parent repaint region instead.
+ en = components.iterator();
+ while (en.hasNext())
+ {
+ Component c = (Component) en.next();
+ cRemoved = false;
+ Component p = c.getParent();
+ int x = c.getX();
+ int y = c.getY();
+
+ while (p instanceof JComponent)
+ if (components.contains(p))
+ {
+ // The parent of this component is already marked for
+ // repainting.
+ // We will not repaint this component.
+ if (!cRemoved)
+ {
+ en.remove();
+ cRemoved = true;
+ }
+ en = components.iterator();
+ // We will repaint the parent instead.
+ Rectangle prect = (Rectangle) dirtyComponentsWork.get(p);
+ Rectangle crect = (Rectangle) dirtyComponentsWork.get(c);
+ crect.translate(x, y);
+ prect.add(crect);
+ someRemoved = true;
+ p = p.getParent();
+ }
+ else
+ {
+ x += p.getX();
+ y += p.getY();
+ p = p.getParent();
+ }
+ }
+ }
+ while (someRemoved);
+
repaintUnderway = true;
- for (Iterator i = repaintOrder.iterator(); i.hasNext();)
+ for (Iterator i = components.iterator(); i.hasNext();)
{
JComponent comp = (JComponent) i.next();
// If a component is marked completely clean in the meantime, then skip
@@ -601,6 +635,8 @@
continue;
comp.paintImmediately(damaged);
}
+
+ dirtyComponentsWork.clear();
repaintUnderway = false;
commitRemainingBuffers();
}