src/share/classes/sun/java2d/pisces/Dasher.java
Print this page
@@ -179,37 +179,41 @@
this.x0 = x1;
this.y0 = y1;
}
public void lineTo(int x1, int y1) {
+ long MAX = java.lang.Integer.MAX_VALUE;
+ long MIN = java.lang.Integer.MIN_VALUE;
while (true) {
+ // We use longs in this method to avoid overflows.
+
int d = dash[idx] - phase;
- int lx = x1 - x0;
- int ly = y1 - y0;
+ long xLen = (long)x1 - x0;
+ long yLen = (long)y1 - y0;
// Compute segment length in the untransformed
// coordinate system
// IMPL NOTE - use fixed point
- int l;
+ long origLen;
if (symmetric) {
- l = (int)((PiscesMath.hypot(lx, ly)*65536L)/ldet);
+ origLen = (int)((PiscesMath.hypot(xLen, yLen)*65536L)/ldet);
} else{
- long la = ((long)ly*m00 - (long)lx*m10)/ldet;
- long lb = ((long)ly*m01 - (long)lx*m11)/ldet;
- l = (int)PiscesMath.hypot(la, lb);
+ long origXLen = (m11*xLen - m01*yLen)/ldet;
+ long origYLen = (m00*yLen - m10*xLen)/ldet;
+ origLen = PiscesMath.hypot(origXLen, origYLen);
}
- if (l < d) {
+ if (origLen < d) {
goTo(x1, y1);
// Advance phase within current dash segment
- phase += l;
+ phase += origLen;
return;
}
- long t;
- int xsplit, ysplit;
+ long t; // the ratio (olddash/oldlinelength) * 2^16
+ long xsplit, ysplit;
// // For zero length dashses, SE appears to move 1/8 unit
// // in device space
// if (d == 0) {
// double dlx = lx/65536.0;
// double dly = ly/65536.0;
@@ -218,15 +222,30 @@
// double dxsplit = (x0/65536.0) + dt*dlx;
// double dysplit = (y0/65536.0) + dt*dly;
// xsplit = (int)(dxsplit*65536.0);
// ysplit = (int)(dysplit*65536.0);
// } else {
- t = ((long)d << 16)/l;
- xsplit = x0 + (int)(t*(x1 - x0) >> 16);
- ysplit = y0 + (int)(t*(y1 - y0) >> 16);
+ t = ((long)d << 16)/origLen;
+ xsplit = x0 + (t * xLen >> 16);
+ ysplit = y0 + (t * yLen >> 16);
// }
- goTo(xsplit, ysplit);
+
+ // If java math had infinite precision, xsplit and ysplit would
+ // be guaranteed never to go outside of the range [MIN, MAX], but
+ // it isn't, and an overflow here would be hard to diagnose, so
+ // the efficiency trade off is worth it.
+ // Note: I have not proven mathematicaly there there is, indeed,
+ // some input that could would overflow here, so it might be
+ // nice to try to prove that overflow is impossible. If it is,
+ // the next 6 lines can be eliminated.
+ if (xsplit > MAX || xsplit < MIN) {
+ xsplit = (xsplit > MAX) ? MAX : MIN;
+ }
+ if (ysplit > MAX || ysplit < MIN) {
+ ysplit = (ysplit > MAX) ? MAX : MIN;
+ }
+ goTo((int)xsplit, (int)ysplit);
// Advance to next dash segment
idx = (idx + 1) % dash.length;
dashOn = !dashOn;
phase = 0;