Hello.

I think I have a fix for this bug:
http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=506

Basically, the problem is that if there is a magnifying affine transformation 
set on the graphics object and one tries to draw a line with small thickness 
and round end caps, the end caps appear jagged. This is because the computation 
of the length of the array that contains the points on the "pen" with which the 
decoration is drawn does not take into account the size of the pen after the 
magnification of the affine transformation. So, for example, if the line length 
was set to 1, and the transformation was a scaling by 10, the resulting pen 
would have a diameter of 10, but only 3 pen points would be computed 
(pi*untransformedLineWidth), so the end cap looks like a triangle.

My fix computes an approximation of the circumference of the transformed pen 
(which is an ellipse) and uses that as the number of points on the pen. The 
approximation is crude, but it is simple, faster than alternatives 
(http://en.wikipedia.org/wiki/Ellipse#Circumference), and I can say from 
observations that it works fairly well.

There is also icing on the cake, in the form of slight improvements in 
performance when the scaling is a zooming out. Example: if the original line 
width was 100, but g2d.scale(0.1,0.1) was set, then the resulting line would 
have a width of 10, so only ~31 points are necessary for the decoration to look 
like a circle, but without this patch, about 314 points are computed (and a 
line is emitted to each one of them).

I appreciate any feedback.

Regards,
Denis Lila.
exporting patch:
# HG changeset patch
# User Denis Lila <dl...@redhat.com>
# Date 1276110761 14400
# Node ID 5cc40c7f2678d320519013b58af6808a0516cd68
# Parent  4d55419ce99e749da5037fa4d8247117f1a5cc2e
Fixed bug http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=506

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
@@ -209,7 +209,34 @@
             this.miterLimitSq = (long)(limitSq*65536.0*65536.0);
         }
 
-        this.numPenSegments = (int)(3.14159f*lineWidth/65536.0f);
+        // The pen is a circle mapped through the linear transformation
+        // this.transform; therefore, we must calculate the circumference
+        // of the mapped pen, not the pen. If we calculate the
+        // circumference of the pen without taking into account this.transform
+        // the round end caps will look jagged. However, the way I calculate
+        // the circumference of the mapped pen is just a crude approximation, so
+        // if anyone reading this knows how to better compute the circumference 
+        // of ellipses, please fix it.
+
+        // So, we map the points (1,0), (0,1), (-1,0), and (0,-1) through
+        // the transformation. The results are (m00,m10), (m01,m11), 
+        // (-m00,-m01), and (-m01,-m11). We simply calculate the lengths of
+        // the mapped horizontal and vertical diameters, scale them by the
+        // actual radius of the circle (i.e. lineWidth / 2), calculate the 
+        // circumference of a circle whose diameter is the greater of those
+        // two, and pretend this calculation is a good enough approximation
+        // to the circumference of the mapped circle.
+        double dx1 = 2*dm00;
+        double dy1 = 2*dm10;
+        double dx2 = 2*dm01;
+        double dy2 = 2*dm11;
+        double radius = lineWidth / (2 * 65536.0);
+        // The diameters:
+        double mappedD1 = radius * java.lang.Math.sqrt(dx1*dx1 + dy1*dy1);
+        double mappedD2 = radius * java.lang.Math.sqrt(dx2*dx2 + dy2*dy2);
+        double mappedD = (mappedD1 < mappedD2) ? mappedD2 : mappedD1;
+        
+        this.numPenSegments = (int) (3.14159 * mappedD);
         if (pen_dx == null || pen_dx.length < numPenSegments) {
             this.pen_dx = new int[numPenSegments];
             this.pen_dy = new int[numPenSegments];

Reply via email to