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

drawPolygon/fillPolygon behaviour different in 1.4 compared to previous releases

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 1.4.0
    • 1.3.0, 1.4.0
    • client-libs
    • 2d
    • beta3
    • x86, sparc
    • linux, solaris_8, windows_2000



      Name: boT120536 Date: 06/03/2001


      java version "1.4.0-beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta-b65)
      Java HotSpot(TM) Client VM (build 1.4.0-beta-b65, mixed mode)

      When a polygon is filled and drawn using the same
      parameters in JDK 1.4.0 beta on Linux the outline and fill
      don't match. This behaviour is different from all previous
      releases.

      I want to use small circles as markers on a map. Since
      this is in an applet I want to support JDK 1.0 and 1.1.
      As previously reported (4151279), since JDK 1.2 there is
      a difference between the way ovals are drawn when drawing
      directly to a canvas and when drawing to an offscreen
      image. This bug has been open for nearly three years and
      still hasn't been fixed in JDK 1.4.0.

        To produce acceptable-looking circles in JDK 1.2 and above
      I've been forced to draw them by hand using polygons.
      This no longer works in JDK 1.4.0 beta, as the polygon
      outline and fill don't match.

      The program below illustrates the problem. It fills and
      draws a number of small circles. When the mouse is clicked
      in the canvas it cycles through three different ways of
      drawing: directly to the canvas; to an offscreen image
      using fillOval/drawOval; to an offscreen image with the
      circles drawn as polygons.

      In JDK 1.0 and 1.1 these three methods all produce the same
      result. In JDK 1.2 and 1.3 the second method results in
      horrible-looking circles, while drawing by hand gives the
      same result as drawing direct to the canvas. In JDK 1.4.0
      beta drawing by hand also produces unacceptable results
      because of the offset between the polygon fill and draw.


      import java.awt.* ;

      public class PolygonBug extends Canvas {
          private Image offscreen = null ;
          private Graphics g0 = null ;
          private int click = 0 ;

          // offsets used to draw circles as polygons
          static private final int xcircle[][] = {
              null,
              null,
              null,
              { 0,1,2,2,1,0,-1,-1,0 },
              { -1,1,2,2,1,-1,-2,-2,-1 },
              { 0,1,3,3,1,0,-2,-2,0 },
              { -1,1,3,3,1,-1,-3,-3,-1 },
              { -1,2,4,4,2,-1,-3,-3,-1 },
              { -1,1,2,3,3,4,4,3,3,2,1,-1,-2,-3,-3,-4,-4,-3,-3,-2,-1},
          } ;

          static private final int ycircle[][] = {
              null,
              null,
              null,
              { -1,-1,0,1,2,2,1,0,-1 },
              { -2,-2,-1,1,2,2,1,-1,-2 },
              { -2,-2,0,1,3,3,1,0,-2 },
              { -3,-3,-1,1,3,3,1,-1,-3 },
              { -3,-3,-1,2,4,4,2,-1,-3 },
              { -4,-4,-3,-3,-2,-1,1,2,3,3,4,4,3,3,2,1,-1,-2,-3,-3,-4},
          } ;

          static String[] message = { "direct", "offscreen", "by hand" } ;

          public void addNotify() {
              super.addNotify() ;

              // create an offscreen image to draw into
              Rectangle r = bounds() ;
              offscreen = createImage(r.width, r.height) ;
              g0 = offscreen.getGraphics() ;
          }

          public void paint(Graphics g) {
              g.clearRect(0, 0, 100, 100) ;

              // draw crosshairs
              g.setColor(Color.black) ;
              g.drawLine(60, 70, 80, 70) ;
              g.drawLine(70, 60, 70, 80) ;

              boolean byHand = (click%3 == 2) ;

              // fill some circles
              g.setColor(Color.white) ;
              fillCircle(g, 10, 10, 4, byHand) ;
              fillCircle(g, 20, 20, 5, byHand) ;
              fillCircle(g, 35, 35, 6, byHand) ;
              fillCircle(g, 50, 50, 7, byHand) ;
              fillCircle(g, 70, 70, 8, byHand) ;

              // draw some circles
              g.setColor(Color.black) ;
              drawCircle(g, 10, 10, 4, byHand) ;
              drawCircle(g, 20, 20, 5, byHand) ;
              drawCircle(g, 35, 35, 6, byHand) ;
              drawCircle(g, 50, 50, 7, byHand) ;
              drawCircle(g, 70, 70, 8, byHand) ;

              // indicate how we drew the circles
              g.drawString(message[click%3], 5, 90) ;
          }

          public boolean mouseDown(Event ev, int x, int y ) {
              ++click ;

              if ( click%3 == 0 ) {
                  // draw directly to canvas
                  repaint() ;
              }
              else {
                  // draw to offscreen image
                  if ( offscreen != null ) {
                      paint(g0) ;

                      Graphics g = getGraphics() ;
                      g.drawImage(offscreen, 0, 0, this) ;
                      g.dispose() ;
                  }
              }

              return true ;
          }



          void drawCircle(Graphics g, int x, int y, int d, boolean byHand) {
              if ( byHand ) {
                  circleByHand(g, x, y, d, true) ;
              }
              else {
                  int d2 = d/2 ;

                  g.drawOval(x-d2, y-d2, d, d) ;
              }
          }

          void fillCircle(Graphics g, int x, int y, int d, boolean byHand) {
              if ( byHand ) {
                  circleByHand(g, x, y, d, false) ;
              }
              else {
                  int d2 = d/2 ;

                  g.fillOval(x-d2, y-d2, d, d) ;
              }
          }

          // draw or fill a circle using a polygon
          void circleByHand(Graphics g, int x, int y, int d, boolean draw) {
              int xc[] = xcircle[d] ;
              int yc[] = ycircle[d] ;
              int len = xc.length ;
              int px[] = new int[len] ;
              int py[] = new int[len] ;

              for ( int j=0; j<len; ++j ) {
                  px[j] = x + xc[j] ;
                  py[j] = y + yc[j] ;
              }

              if ( draw ) {
                  g.drawPolygon(px, py, len) ;
              }
              else {
                  g.fillPolygon(px, py, len) ;
              }
          }

          public static void main(String argv[]) {
              Frame f = new Frame("PolygonBug") ;
              Canvas c = new PolygonBug() ;
              c.resize(100,100) ;

              f.add("Center", c) ;
              f.pack() ;
              f.show() ;
          }
      }
      (Review ID: 125186)
      ======================================================================

            flar Jim Graham
            bonealsunw Bret O'neal (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: