This fixes some clipping problems with the XGraphics.
2006-07-19 Roman Kennke <[EMAIL PROTECTED]>
* gnu/java/awt/peer/x/XGraphics.java
(translate): Don't set the clip on the X server.
(clipRect): Use setXClip() to set the clip on the X server.
(hitClip): More efficient and correct implementation.
(setClip): Use setXClip() to set the clip on the X server.
(setClip(Shape)): Use setXClip() to set the clip on the X server.
(copyArea): Translate and clip the source rectangle correctly.
(dispose): Only flush when object is not yet disposed.
(clone): Use setXClip() to set the clip on the X server.
/Roman
Index: gnu/java/awt/peer/x/XGraphics.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/x/XGraphics.java,v
retrieving revision 1.5
diff -u -1 -2 -r1.5 XGraphics.java
--- gnu/java/awt/peer/x/XGraphics.java 19 Jul 2006 08:17:52 -0000 1.5
+++ gnu/java/awt/peer/x/XGraphics.java 19 Jul 2006 19:20:40 -0000
@@ -126,25 +126,24 @@
/**
* Translates the origin by (x, y).
*/
public void translate(int x, int y)
{
translateX += x;
translateY += y;
if (clip != null)
{
clip.x -= x;
clip.y -= y;
- setClip(clip);
}
}
/**
* Returns the current foreground color, possibly <code>null</code>.
*
* @return the current foreground color, possibly <code>null</code>
*/
public Color getColor()
{
return foreground;
}
@@ -247,104 +246,136 @@
*/
public void clipRect(int x, int y, int width, int height)
{
if (clip == null)
{
clip = new Rectangle(x, y, width, height);
}
else
{
computeIntersection(x, y, width, height, clip);
}
// Update the X clip setting.
- setClip(clip.x, clip.y, clip.width, clip.height);
+ setXClip(clip.x, clip.y, clip.width, clip.height);
}
/**
* Returns <code>true</code> when the specified rectangle intersects with
* the current clip, <code>false</code> otherwise. This is overridden to
* avoid unnecessary creation of Rectangles via getBounds().
*
* @param x the x coordinate of the rectangle
* @param y the y coordinate of the rectangle
* @param w the width of the rectangle
* @param h the height of the rectangle
*
* @return <code>true</code> when the specified rectangle intersects with
* the current clip, <code>false</code> otherwise
*/
public boolean hitClip(int x, int y, int w, int h)
{
boolean hit;
if (clip == null)
{
hit = true;
}
else
{
- hit = clip.intersects(x, y, w, h);
+ // It's easier to determine if the rectangle lies outside the clip,
+ // so we determine that and reverse the result (if it's not completely
+ // outside, it most likely hits the clip rectangle).
+ int x2 = x + w;
+ int y2 = y + h;
+ int clipX2 = clip.x + clip.width;
+ int clipY2 = clip.y + clip.height;
+ boolean outside = (x < clip.x && x2 < clip.x) // Left.
+ || (x > clipX2 && x2 > clipX2) // Right.
+ || (y < clip.y && y2 < clip.y) // Top.
+ || (y > clipY2 && y2 > clipY2); // Bottom.
+ hit = ! outside;
}
- //System.err.println("hitClip: " + hit);
return hit;
}
public void setClip(int x, int y, int width, int height)
{
if (clip != null)
clip.setBounds(x, y, width, height);
else
clip = new Rectangle(x, y, width, height);
+ setXClip(clip.x, clip.y, clip.width, clip.height);
+ }
+ /**
+ * Sets the clip on the X server GC. The coordinates are not yet translated,
+ * this will be performed by the X server.
+ *
+ * @param x the clip, X coordinate
+ * @param y the clip, Y coordinate
+ * @param w the clip, width
+ * @param h the clip, height
+ */
+ private void setXClip(int x, int y, int w, int h)
+ {
gnu.x11.Rectangle[] clipRects = new gnu.x11.Rectangle[] {
- new gnu.x11.Rectangle(x, y, width, height) };
- xgc.set_clip_rectangles(translateX, translateY, clipRects, GC.UN_SORTED);
+ new gnu.x11.Rectangle(x, y, w, h) };
+ xgc.set_clip_rectangles(translateX, translateY, clipRects, GC.YX_BANDED);
}
public Shape getClip()
{
// Return a copy here, so nobody can trash our clip.
return clip == null ? null : clip.getBounds();
}
/**
* Sets the current clip.
*
- * @param clip the clip to set
+ * @param c the clip to set
*/
- public void setClip(Shape clip)
+ public void setClip(Shape c)
{
- if (clip != null)
+ if (c != null)
{
Rectangle b;
- if (clip instanceof Rectangle)
+ if (c instanceof Rectangle)
{
- b = (Rectangle) clip;
+ b = (Rectangle) c;
}
else
{
- b = clip.getBounds();
+ b = c.getBounds();
}
- setClip(b.x, b.y, b.width, b.height);
+ clip.setBounds(b);
+ setXClip(b.x, b.y, b.width, b.height);
}
else
{
- setClip(0, 0, xdrawable.width, xdrawable.height);
+ clip.setBounds(0, 0, xdrawable.width, xdrawable.height);
+ setXClip(0, 0, xdrawable.width, xdrawable.height);
}
}
public void copyArea(int x, int y, int width, int height, int dx, int dy)
{
- int srcX = x + translateX;
- int srcY = y + translateY;
- xdrawable.copy_area(xdrawable, xgc, srcX, srcY, width, height,
+ // Clip and translate src rectangle.
+ int srcX = Math.min(Math.max(x, clip.x), clip.x + clip.width)
+ + translateX;
+ int srcY = Math.min(Math.max(y, clip.y), clip.y + clip.height)
+ + translateY;
+ int srcWidth = Math.min(Math.max(x + width, clip.x),
+ clip.x + clip.width) - x;
+ int srcHeight = Math.min(Math.max(y + height, clip.y),
+ clip.y + clip.height) - y;
+ xdrawable.copy_area(xdrawable, xgc, srcX, srcY, srcWidth, srcHeight,
srcX + dx, srcY + dy);
}
/**
* Draws a line from point (x1, y1) to point (x2, y2).
*/
public void drawLine(int x1, int y1, int x2, int y2)
{
//System.err.println("drawLine: " + (x1 + translateX) + ", " + ( y1 + translateY) + ", " + (x2 + translateX) + ", " + (y2 + translateY) + " on: " + xdrawable);
xdrawable.line(xgc, x1 + translateX, y1 + translateY,
x2 + translateX, y2 + translateY);
}
@@ -597,55 +628,55 @@
// Reset clip.
setClip(old);
return res;
}
/**
* Frees any resources associated with this object.
*/
public void dispose()
{
- xdrawable.display.flush();
if (! disposed)
{
xgc.free();
+ xdrawable.display.flush();
disposed = true;
}
}
// Additional helper methods.
/**
* Creates and returns an exact copy of this XGraphics.
*/
protected Object clone()
{
try
{
XGraphics copy = (XGraphics) super.clone();
copy.xgc = xgc.copy();
-
- // Save the original clip.
if (clip != null)
- copy.clip = new Rectangle(clip);
+ {
+ copy.clip = new Rectangle(clip);
+ copy.setXClip(clip.x, clip.y, clip.width, clip.height);
+ }
return copy;
}
catch (CloneNotSupportedException ex)
{
- AWTError err = new AWTError("Error while cloning XGraphics");
- err.initCause(ex);
- throw err;
+ assert false;
}
+ return null;
}
/**
* Computes the intersection between two rectangles and stores the result
* int the second rectangle.
*
* This method has been copied from [EMAIL PROTECTED] javax.swing.SwingUtilities}.
*
* @param x the x coordinate of the rectangle #1
* @param y the y coordinate of the rectangle #1
* @param w the width of the rectangle #1
* @param h the height of the rectangle #1