[cp-patches] FYI: JComponent painting fix

2006-04-18 Thread Roman Kennke
This fixes two issues with the Swing painting:
1. As reported in http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27185, an
optimization in JComponent.paintChildrenOptimized() didn't work quite
right. Looking at it, it seems that this optimization doesn't gain much
anyway, possibly the overhead of calculating away things eats up all the
optimization. I removed this bit as it seemed to cause problems.
2. In JComponent.paintChildrenWithOverlap() we need to propagate the
dirty rectangles to the next child component, when the component was not
opaque, so that the next child gets painted correctly.

2006-04-18  Roman Kennke  [EMAIL PROTECTED]

PR 27185
* javax/swing/JComponent.java
(paintChildrenWithOverlap): When one child is not opaque,
propagate
the dirty rectangles to the next child.
(paintChildrenOptimized): Removed unnecessary 'optimization'.
This actually didn't work right and probably gained nothing.

/Roman

-- 
“Improvement makes straight roads, but the crooked roads, without
Improvement, are roads of Genius.” - William Blake
Index: javax/swing/JComponent.java
===
RCS file: /cvsroot/classpath/classpath/javax/swing/JComponent.java,v
retrieving revision 1.114
diff -u -1 -0 -r1.114 JComponent.java
--- javax/swing/JComponent.java	6 Apr 2006 10:15:34 -	1.114
+++ javax/swing/JComponent.java	18 Apr 2006 09:10:48 -
@@ -1929,20 +1929,26 @@
 x = compBounds.x + compBounds.width;
 y = r.y;
 w = r.width - (compBounds.x - r.x) - compBounds.width;
 h = r.height;
 rect.setBounds(x, y, w, h);
 if (! rect.isEmpty())
   {
 newPaintRects.add(rect);
   }
   }
+else
+  {
+// Not opaque, need to reuse the current paint rectangles
+// for the next component.
+newPaintRects.add(r);
+  }
 
   }
 else
   {
 newPaintRects.add(r);
   }
   }
 
 // Replace the paintRectangles with the new split up
 // paintRectangles.
@@ -2017,48 +2023,24 @@
*
* @param g the graphics context to use
*/
   private void paintChildrenOptimized(Graphics g)
   {
 Shape originalClip = g.getClip();
 Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache);
 g.clipRect(inner.x, inner.y, inner.width, inner.height);
 Component[] children = getComponents();
 
-// Find the bottommost component that needs to be painted. This is the
-// component that - together with the rectangles of the components that
-// are painted above it - covers the whole clip area.
-Rectangle rect = new Rectangle();
-int startIndex = children.length - 1;
-for (int i = 0; i  children.length; i++)
-  {
-Rectangle b = children[i].getBounds();
-if (children[i].isOpaque()  children[i].isVisible()
- g.hitClip(b.x, b.y, b.width, b.height))
-  {
-if (rect.isEmpty())
-  rect.setBounds(b);
-else
-  SwingUtilities.computeUnion(b.x, b.y, b.width, b.height, rect);
-
-if (SwingUtilities.isRectangleContainingRectangle(rect, inner))
-  {
-startIndex = i;
-break;
-  }
-  }
-  }
-
 // paintingTile becomes true just before we start painting the component's
 // children.
 paintingTile = true;
-for (int i = startIndex; i = 0; i--) //children.length; i++)
+for (int i = children.length - 1; i = 0; i--) //children.length; i++)
   {
 // paintingTile must be set to false before we begin to start painting
 // the last tile.
 if (i == children.length - 1)
   paintingTile = false;
 
 if (!children[i].isVisible())
   continue;
 
 Rectangle bounds = children[i].getBounds(rectCache);


signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil


[cp-patches] FYI: JComponent painting fix

2005-09-24 Thread Roman Kennke
Hi,

I fixed the Swing painting a little more. This finally removes the
flickers that have been visible from time to time (to be more precise:
when the AWT triggers repainting, which is entirely different from when
Swing triggers repainting).

Effectively, this adds a check in the paint() method if we are already
double-buffering (when we are called from AWT then we're not, that's
what caused the flickering) and if not, activate it by calling
paintDoubleBuffered. This looks a bit weird since paintDoubleBuffered
calls back into paint(), but that should actually work because the
isPaintingDoubleBuffered flag decides which branch in the if-else in
paint we go. When unwinding the call stack after painting, we go back
into paintDoubleBuffered and actually draw the buffer to screen. Maybe
meditate a little over this to understand...

You might ask why not do it like it has been done previously. The
double-buffering was always activated directly in paint() when double
buffering was enabled on the JComponent (and it was by default only
enabled on the JRootPane). This was not quite right for the following
reasons:

- in Sun's JDK, _all_ Swing components are doublebuffered-enabled by
default
- what if we want to have arbitrary Swing components displayed in an AWT
tree? With the old approach this was only possible with JRootPanes

So this hack improves the compatibility between AWT and Swing and also
removes some ugly screen flickering in one patch :-)

2005-09-24  Roman Kennke  [EMAIL PROTECTED]

* javax/swing/JComponent.java
(paint): Activate double buffering if it is not already
activated.
(paintImmediately2): Prepare a component graphics object here
and
call paintDoubleBuffered with this.
(paintDoubleBuffered): Changed to work nicely with the new
paint()
and paintImmediately2() methods.

/Roman

Index: javax/swing/JComponent.java
===
RCS file: /cvsroot/classpath/classpath/javax/swing/JComponent.java,v
retrieving revision 1.59
diff -u -r1.59 JComponent.java
--- javax/swing/JComponent.java	22 Sep 2005 20:58:34 -	1.59
+++ javax/swing/JComponent.java	24 Sep 2005 20:36:46 -
@@ -341,6 +341,12 @@
   boolean autoscrolls = false;
 
   /**
+   * Indicates whether the current paint call is already double buffered or
+   * not. 
+   */
+  static boolean isPaintingDoubleBuffered = false;
+
+  /**
* Listeners for events other than [EMAIL PROTECTED] PropertyChangeEvent} are
* handled by this listener list. PropertyChangeEvents are handled in
* [EMAIL PROTECTED] #changeSupport}.
@@ -1449,9 +1455,24 @@
*/
   public void paint(Graphics g)
   {
-paintComponent(g);
-paintBorder(g);
-paintChildren(g);
+RepaintManager rm = RepaintManager.currentManager(this);
+// We do a little stunt act here to switch on double buffering if it's
+// not already on. If we are not already doublebuffered, then we jump
+// into the method paintDoubleBuffered, which turns on the double buffer
+// and then calls paint(g) again. In the second call we go into the else
+// branch of this if statement and actually paint things to the double
+// buffer. When this method completes, the call stack unwinds back to
+// paintDoubleBuffered, where the buffer contents is finally drawn to the
+// screen.
+if (!isPaintingDoubleBuffered  isDoubleBuffered()
+ rm.isDoubleBufferingEnabled())
+  paintDoubleBuffered(g);
+else
+  {
+paintComponent(g);
+paintBorder(g);
+paintChildren(g);
+  }
   }
 
   /**
@@ -1604,10 +1625,13 @@
   void paintImmediately2(Rectangle r)
   {
 RepaintManager rm = RepaintManager.currentManager(this);
+Graphics g = getGraphics();
+g.setClip(r.x, r.y, r.width, r.height);
 if (rm.isDoubleBufferingEnabled()  isDoubleBuffered())
-  paintDoubleBuffered(r);
+  paintDoubleBuffered(g);
 else
-  paintSimple(r);
+  paintSimple(g);
+g.dispose();
   }
 
   /**
@@ -1615,38 +1639,40 @@
*
* @param r the area to be repainted
*/
-  void paintDoubleBuffered(Rectangle r)
+  void paintDoubleBuffered(Graphics g)
   {
+
+Rectangle r = g.getClipBounds();
+if (r == null)
+  r = new Rectangle(0, 0, getWidth(), getHeight());
 RepaintManager rm = RepaintManager.currentManager(this);
 
 // Paint on the offscreen buffer.
-Image buffer = rm.getOffscreenBuffer(this, getWidth(), getHeight());
-Graphics g = buffer.getGraphics();
-Graphics g2 = getComponentGraphics(g);
-g2.setClip(r.x, r.y, r.width, r.height);
-paint(g2);
-g2.dispose();
-g.dispose();
+synchronized (paintLock)
+  {
+Image buffer = rm.getOffscreenBuffer(this, getWidth(), getHeight());
+Graphics g2 = buffer.getGraphics();
+g2 = getComponentGraphics(g2);
+g2.setClip(r.x, r.y, r.width, r.height);
+isPaintingDoubleBuffered = true;
+

Re: [cp-patches] FYI: JComponent painting fix

2005-09-24 Thread Andrew Pinski
 - in Sun's JDK, _all_ Swing components are doublebuffered-enabled by
 default

Not with Apple's JDK on Mac OS X where the window server handles the
double buffer.

-- Pinski


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