JDK-6966747 : End caps are not drawn on zero length lines.
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 7
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2010-07-05
  • Updated: 2012-03-20
  • Resolved: 2011-03-07
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_18"
OpenJDK Runtime Environment (IcedTea6 1.8) (fedora-41.b18.fc13-x86_64)
OpenJDK 64-Bit Server VM (build 14.0-b16, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
2.6.33.5-124.fc13.x86_64 #1 SMP Fri Jun 11 09:38:12 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
If a a line of 0 length is drawn, it's end caps (if any) are not drawn.

The specification does not say whether they should be drawn, but it makes sense that they should, and they are drawn in closed source JDK, which is why I think this report is justified.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run provided program.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
A white circle of diameter 10 is drawn at (100,100), and 24 circles of diameter 10 should be drawn across the top of the image, in a horizontal line.
ACTUAL -
Only 3 circles at the top right are drawn.

3 are drawn as opposed to 0 because of a separate issue in Dasher.java, which I am reluctant to file a bug for, since I think its effects are visible if and only if this bug exists.

What is happening is that Dasher takes a big line and breaks it down into lines of length equal to the dash lengths, and feeds these smaller lines to Stroker.
Even though the x and y lengths of these smaller lines are constant, Dasher computes them in a loop as a division of a non-constant numerator and non-constant denominator. The numerator and denominator are supposed to change in a such a way as to keep the result constant (which is why dasher works most of the time), but because infinite precision arithmetic doesn't exist, the value of this quotient changes slightly from iteration to iteration. When the dash lengths are small enough, some of these line lengths underflow to 0, and because of this bug, Stroker doesn't draw end caps for them.
On other iterations, however, the line lengths are computed as slightly greater than 0, which is enough for Stroker to draw their end caps.
And this is why we see the 3 circles at the upper right.

NOTE: if end caps are not used, nothing would (and should) be drawn, since the dash lengths are so small as to not be able to cross pixel boundaries most of the time.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import javax.imageio.*;

public class TestDBZ extends Frame {

    public static void main(String[] args) {
        BufferedImage bImg = new BufferedImage(512, 512, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = (Graphics2D) bImg.getGraphics();

//        g2d.setStroke(new BasicStroke(10f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10.0f));
        g2d.setStroke(new BasicStroke(10f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10.0f, new float[] {0.001f, 20f}, 0));

        g2d.drawLine(10, 10, 500, 10);
        g2d.drawLine(100, 100, 100, 100);
        try { ImageIO.write(bImg, "png", new java.io.File("test.png")); } catch (Exception e) {}
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
None that I can think of.

Comments
EVALUATION It is believed this was fixed in this changeset http://hg.openjdk.java.net/jdk7/2d/jdk/rev/065e6c5a8027 which listed only 6967434: Round joins/caps of scaled up lines have poor quality. So I am closing this bug a dup. of that one, so we can at least track it as being fixed in that changeset.
07-03-2011