--- old/src/share/classes/sun/java2d/pisces/Stroker.java 2010-06-16 16:16:51.507550899 +0100 +++ new/src/share/classes/sun/java2d/pisces/Stroker.java 2010-06-16 16:16:51.342489094 +0100 @@ -113,6 +113,10 @@ double m10_2_m11_2; double m00_m10_m01_m11; + // An upper bound on the width the the transformed line and the + // untransformed line. + int wub; + /** * Empty constructor. setOutput and * setParameters must be called prior to calling any @@ -227,6 +231,9 @@ pen_dy[i] = (int)(r*(dm10*cos + dm11*sin)); } + wub = (int)((lineWidth * PiscesMath.hypot((long)m01+m00, (long)m10+m11)) >> 16); + wub = (wub > lineWidth) ? wub : lineWidth; + prev = CLOSE; rindex = 0; started = false; @@ -276,11 +283,12 @@ private boolean isCCW(int x0, int y0, int x1, int y1, int x2, int y2) { - int dx0 = x1 - x0; - int dy0 = y1 - y0; - int dx1 = x2 - x1; - int dy1 = y2 - y1; - return (long)dx0*dy1 < (long)dy0*dx1; + // These need to be longs to avoid overflows. + long dx0 = (long)x1 - x0; + long dy0 = (long)y1 - y0; + long dx1 = (long)x2 - x1; + long dy1 = (long)y2 - y1; + return dx0*dy1 < dy0*dx1; } private boolean side(int x, int y, int x0, int y0, int x1, int y1) { @@ -472,10 +480,35 @@ } } + private static void makeOverflowSafe(int[] coords, int wub) { + int x = coords[0]; + int y = coords[1]; + if ((long)x + wub != x + wub) { + x -= wub; + } + if ((long)y + wub != y + wub) { + y -= wub; + } + if ((long)x - wub != x - wub) { + x += wub; + } + if ((long)y - wub != y - wub) { + y += wub; + } + coords[0] = x; + coords[1] = y; + } public void moveTo(int x0, int y0) { // System.out.println("Stroker.moveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")"); + // We can't move too close to the borders set by Integer.MAX_VALUE or + // MIN_VALUE, because when we try to draw an endcap, or even just adding + // offsets to (x0,y0), overflows might happen. + int[] coords = {x0, y0}; + makeOverflowSafe(coords, wub); + x0 = coords[0]; y0 = coords[1]; + if (lineToOrigin) { // not closing the path, do the previous lineTo lineToImpl(sx0, sy0, joinToOrigin); @@ -531,6 +564,16 @@ int mx = offset[0]; int my = offset[1]; + // Now we want to make sure that none of the operations involving line + // drawing will overflow. These include adding pen points to (x1,y1), + // drawing a square end cap, and adding/subtracting mx and my to x1 + // and y1 (in the calls to emitLineTo). However, it does not protect + // against possible overflows when drawing miters. + // TODO: protect against possible overflows when drawing miters. + int[] coords = {x1, y1}; + makeOverflowSafe(coords, wub); + x1 = coords[0]; y1 = coords[1]; + if (!started) { emitMoveTo(x0 + mx, y0 + my); this.sx1 = x1;