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