Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4265778

Java2D incorrectly renders objects with large coordinates

    XMLWordPrintable

Details

    • 2d
    • 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)
      ======================================================================

      Attachments

        Issue Links

          Activity

            People

              avu Alexey Ushakov
              wleesunw William Lee (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Imported:
                Indexed: