Details
-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
1.2.2, 1.4.1, 1.4.2, 5.0
-
Fix Understood
-
generic, x86
-
generic, linux, windows_xp
Description
Name: wl91122 Date: 08/25/99
Java2D behaves incorrectly (and very unpredictably) when rendering objects with large coordinates.
Our mapping application typically has to render lines and polygons with very large coordinates. For
example, your window may be displaying a very small portion of California, but the application may
have to fill California's entire border. We need the rendering behavior to be very well-defined (with
efficient clipping) under JDK 1.2.
In JDK 1.1, the Graphics interface used ints to specify the coordinates to be rendered. However, the
actual rendering was performed by the underlying OS graphics system and was therefore constrained
by that system's coordinate limits. For instance, Windows GDI uses shorts for coordinates, so JDK 1.1
didn't have well-defined behavior for coordinates larger than shorts.
In JDK 1.2, the Graphics2D interface allows rendering of Shape objects, which can be specified with
float or double coordinates. Since the Graphics2D implementation provides some features that are
not available in Windows GDI (such as anti-aliasing), I assumed that this implementation performed
all of its own rendering without using GDI. If this is indeed the case, then the implementation should
have well-defined behavior when rendering all objects, with coordinates spanning the full range of
float and double values.
The following program illustrates how poorly defined the current rendering behavior is in JDK 1.2.2,
running under Windows NT 4.0 and Windows 98. You can choose one of four rendering cases by
specifying 1, 2, 3, or 4 as a parameter on the command line. Case 1 correctly draws a line with large
coordinates. Case 2 tries to draw the same line into an offscreen Image, but it appears to hang the
Java VM. Case 3 tries to fill a polygon with large coordinates, but it quickly draws nothing. Case 4
correctly fills the same polygon in an offscreen Image, but it takes several minutes to do so -- as if
the clipping is being performed on each scan line.
In this sample code, I've used Graphics.drawLine and Graphics.fillPolygon to illustrate the
behavior. I've gotten the same results using a GeneralPath with Graphics2D.draw and
Graphics2D.fill.
import java.awt.*;
import java.awt.event.*;
public class RenderBug extends Canvas {
int m_paintCase;
RenderBug(int num) {
m_paintCase = num;
}
public void paint(Graphics g) {
Image image;
switch (m_paintCase) {
case 1:
// This correctly and quickly draws the line.
drawBadLine(g);
break;
case 2:
// This hangs the VM.
image = createImage(640, 480);
drawBadLine(image.getGraphics());
g.drawImage(image, 0, 0, this);
break;
case 3:
// This incorrectly (but quickly) draws nothing.
fillBadPolygon(g);
break;
case 4:
// This correctly (but very slowly) fills the polygon.
image = createImage(640, 480);
fillBadPolygon(image.getGraphics());
g.drawImage(image, 0, 0, this);
break;
}
}
void drawBadLine(Graphics g) {
System.out.println("Drawing line...");
g.drawLine(0, 0, 55000, 20000);
System.out.println("Line is drawn.\n");
}
void fillBadPolygon(Graphics g) {
int[] x = { -90000000, 300, -40000000 };
int[] y = { -30000000, 300, -70000000 };
System.out.println("Filling polygon...");
g.setColor(Color.green);
g.fillPolygon(x, y, 3);
System.out.println("Polygon is filled.\n");
}
public static void main(String[] args) {
int num = 0;
if (args.length == 1) {
try {
num = Integer.parseInt(args[0]);
} catch (NumberFormatException ignore) {}
}
if (num < 1 || num > 4) {
System.out.println("Usage: java RenderBug { 1 | 2 | 3 | 4 }");
} else {
Frame frame = new Frame("DrawImage");
Canvas canvas = new RenderBug(num);
frame.setSize(640, 480);
frame.add("Center", canvas);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.show();
}
}
}
(Review ID: 94393)
======================================================================
Java2D behaves incorrectly (and very unpredictably) when rendering objects with large coordinates.
Our mapping application typically has to render lines and polygons with very large coordinates. For
example, your window may be displaying a very small portion of California, but the application may
have to fill California's entire border. We need the rendering behavior to be very well-defined (with
efficient clipping) under JDK 1.2.
In JDK 1.1, the Graphics interface used ints to specify the coordinates to be rendered. However, the
actual rendering was performed by the underlying OS graphics system and was therefore constrained
by that system's coordinate limits. For instance, Windows GDI uses shorts for coordinates, so JDK 1.1
didn't have well-defined behavior for coordinates larger than shorts.
In JDK 1.2, the Graphics2D interface allows rendering of Shape objects, which can be specified with
float or double coordinates. Since the Graphics2D implementation provides some features that are
not available in Windows GDI (such as anti-aliasing), I assumed that this implementation performed
all of its own rendering without using GDI. If this is indeed the case, then the implementation should
have well-defined behavior when rendering all objects, with coordinates spanning the full range of
float and double values.
The following program illustrates how poorly defined the current rendering behavior is in JDK 1.2.2,
running under Windows NT 4.0 and Windows 98. You can choose one of four rendering cases by
specifying 1, 2, 3, or 4 as a parameter on the command line. Case 1 correctly draws a line with large
coordinates. Case 2 tries to draw the same line into an offscreen Image, but it appears to hang the
Java VM. Case 3 tries to fill a polygon with large coordinates, but it quickly draws nothing. Case 4
correctly fills the same polygon in an offscreen Image, but it takes several minutes to do so -- as if
the clipping is being performed on each scan line.
In this sample code, I've used Graphics.drawLine and Graphics.fillPolygon to illustrate the
behavior. I've gotten the same results using a GeneralPath with Graphics2D.draw and
Graphics2D.fill.
import java.awt.*;
import java.awt.event.*;
public class RenderBug extends Canvas {
int m_paintCase;
RenderBug(int num) {
m_paintCase = num;
}
public void paint(Graphics g) {
Image image;
switch (m_paintCase) {
case 1:
// This correctly and quickly draws the line.
drawBadLine(g);
break;
case 2:
// This hangs the VM.
image = createImage(640, 480);
drawBadLine(image.getGraphics());
g.drawImage(image, 0, 0, this);
break;
case 3:
// This incorrectly (but quickly) draws nothing.
fillBadPolygon(g);
break;
case 4:
// This correctly (but very slowly) fills the polygon.
image = createImage(640, 480);
fillBadPolygon(image.getGraphics());
g.drawImage(image, 0, 0, this);
break;
}
}
void drawBadLine(Graphics g) {
System.out.println("Drawing line...");
g.drawLine(0, 0, 55000, 20000);
System.out.println("Line is drawn.\n");
}
void fillBadPolygon(Graphics g) {
int[] x = { -90000000, 300, -40000000 };
int[] y = { -30000000, 300, -70000000 };
System.out.println("Filling polygon...");
g.setColor(Color.green);
g.fillPolygon(x, y, 3);
System.out.println("Polygon is filled.\n");
}
public static void main(String[] args) {
int num = 0;
if (args.length == 1) {
try {
num = Integer.parseInt(args[0]);
} catch (NumberFormatException ignore) {}
}
if (num < 1 || num > 4) {
System.out.println("Usage: java RenderBug { 1 | 2 | 3 | 4 }");
} else {
Frame frame = new Frame("DrawImage");
Canvas canvas = new RenderBug(num);
frame.setSize(640, 480);
frame.add("Center", canvas);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.show();
}
}
}
(Review ID: 94393)
======================================================================
Attachments
Issue Links
- duplicates
-
JDK-4858912 JCK1.4a-runtime api/java_awt/interactive/GraphicsTests.html#GraphicsTests fails
- Closed
- relates to
-
JDK-4376103 Java hangs rendering a shape with max. coordinates much greater than 32K
- Resolved