--- 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;