Sorry, wrong patch. Here it comes. /Roman
Am Dienstag, den 03.03.2009, 16:17 +0100 schrieb Roman Kennke: > Hi there, > > > 4. StrokeShapeTest: createStrokedShape() behaves differently. > > It turns out that there is an arithmetic overflow here. The pisces > stroker does a stupid thing here. First it initializes the > scaledLineWidth like this: > > this.scaledLineWidth2 = ((long)transform.m00*lineWidth2); > > which is infact wrong, because in fixed point arithmetics you need to > apply >> 16, because the decimal moves. > > However, in another place it uses this factor like this: > > dx = (int)( (ly*scaledLineWidth2)/ilen >> 16); > dy = (int)(-(lx*scaledLineWidth2)/ilen >> 16); > > which makes it ok in the end. The only problem is, that we start with an > incredibly large number, then multiply another incredibly large number > and _after_ that (when the overflow already occured) do the >> 16. The > patch moves the >> 16 to the initialization of scaledLineWidth, which > makes it clearer, more correct and even a tad faster, because we do the > second calculation at least 2x. > > Of course, the real fix here would be to turn the whole implementation > into floating point. This particular testcase is fixed by this patch, > and the 'range of correct behaviour' is much large now, but if you deal > with very large numbers in your shapes, then you will get trouble again. > > /Roman -- Dipl.-Inform. (FH) Roman Kennke, Software Engineer, http://kennke.org aicas Allerton Interworks Computer Automated Systems GmbH Haid-und-Neu-Straße 18 * D-76131 Karlsruhe * Germany http://www.aicas.com * Tel: +49-721-663 968-48 USt-Id: DE216375633, Handelsregister HRB 109481, AG Karlsruhe Geschäftsführer: Dr. James J. Hunt
diff --git a/src/share/classes/sun/java2d/pisces/Stroker.java b/src/share/classes/sun/java2d/pisces/Stroker.java --- a/src/share/classes/sun/java2d/pisces/Stroker.java +++ b/src/share/classes/sun/java2d/pisces/Stroker.java @@ -181,7 +181,7 @@ Transform4 transform) { this.lineWidth = lineWidth; this.lineWidth2 = lineWidth >> 1; - this.scaledLineWidth2 = (long)transform.m00*lineWidth2; + this.scaledLineWidth2 = ((long)transform.m00*lineWidth2) >> 16; this.capStyle = capStyle; this.joinStyle = joinStyle; this.miterLimit = miterLimit; @@ -243,8 +243,8 @@ if (ilen == 0) { dx = dy = 0; } else { - dx = (int)( (ly*scaledLineWidth2)/ilen >> 16); - dy = (int)(-(lx*scaledLineWidth2)/ilen >> 16); + dx = (int)( (ly*scaledLineWidth2)/ilen); + dy = (int)(-(lx*scaledLineWidth2)/ilen); } } else { double dlx = x1 - x0;