changeset 2512:3cf29ba320c1

Fix regression.
author Denis Lila <dlila@redhat.com>
date Thu, 12 May 2011 13:36:41 -0400
parents b142e8e007e6
children 711c59eac969
files ChangeLog Makefile.am NEWS patches/openjdk/pgram-pipe-regression.patch
diffstat 4 files changed, 564 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Apr 12 15:50:57 2011 +0200
+++ b/ChangeLog	Thu May 12 13:36:41 2011 -0400
@@ -1,3 +1,11 @@
+2011-05-12  Denis Lila <dlila@redhat.com>
+
+	* Makefile.am: Apply patch.
+	* NEWS: Update with backport.
+	* patches/openjdk/pgram-pipe-regression.patch: Fix regression a
+	where the wrong user space bounds would be passed to user supplied
+	paint object.
+
 2011-04-12  Xerxes RĂ„nby  <xerxes@zafena.se>
 
 	PR689: Shark fails to find LLVM 2.9 System headers during build
--- a/Makefile.am	Tue Apr 12 15:50:57 2011 +0200
+++ b/Makefile.am	Thu May 12 13:36:41 2011 -0400
@@ -330,7 +330,8 @@
 	patches/mark_sun_toolkit_privileged_code.patch \
 	patches/hotspot/$(HSBUILD)/7032388-work_without_cmov_instruction.patch \
 	patches/openjdk/7031385-gcc-register-allocation-fix.patch \
-	patches/shark-llvm-2.9.patch
+	patches/shark-llvm-2.9.patch \
+	patches/openjdk/pgram-pipe-regression.patch
 
 if WITH_ALT_HSBUILD
 ICEDTEA_PATCHES += \
--- a/NEWS	Tue Apr 12 15:50:57 2011 +0200
+++ b/NEWS	Thu May 12 13:36:41 2011 -0400
@@ -13,6 +13,8 @@
 
 * Shark
   - PR689: Shark fails to find LLVM 2.9 System headers during build.
+* Backports
+  - S7043054: REGRESSION - wrong userBounds in Paint.createContext()
 
 New in release 1.10.1 (2011-04-04):
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/openjdk/pgram-pipe-regression.patch	Thu May 12 13:36:41 2011 -0400
@@ -0,0 +1,552 @@
+# HG changeset patch
+# User flar
+# Date 1305155521 25200
+# Node ID f290441b0cb7f5059caab84936b363b1f45e9e2f
+# Parent  85f53467c30ce903c3ea51cfea7759d9c7e39edc
+7043054: REGRESSION: JDK 7 b126 : Wrong userBounds in Paint.createContext()
+Reviewed-by: prr
+
+diff -r 85f53467c30c -r f290441b0cb7 src/share/classes/sun/java2d/opengl/OGLRenderer.java
+--- openjdk.orig/jdk/src/share/classes/sun/java2d/opengl/OGLRenderer.java	Tue May 10 15:59:01 2011 -0700
++++ openjdk/jdk/src/share/classes/sun/java2d/opengl/OGLRenderer.java	Wed May 11 16:12:01 2011 -0700
+@@ -102,15 +102,20 @@
+             final ParallelogramPipe realpipe = oglr.getAAParallelogramPipe();
+             return new ParallelogramPipe() {
+                 public void fillParallelogram(SunGraphics2D sg2d,
++                                              double ux1, double uy1,
++                                              double ux2, double uy2,
+                                               double x, double y,
+                                               double dx1, double dy1,
+                                               double dx2, double dy2)
+                 {
+                     GraphicsPrimitive.tracePrimitive("OGLFillAAParallelogram");
+                     realpipe.fillParallelogram(sg2d,
++                                               ux1, uy1, ux2, uy2,
+                                                x, y, dx1, dy1, dx2, dy2);
+                 }
+                 public void drawParallelogram(SunGraphics2D sg2d,
++                                              double ux1, double uy1,
++                                              double ux2, double uy2,
+                                               double x, double y,
+                                               double dx1, double dy1,
+                                               double dx2, double dy2,
+@@ -118,6 +123,7 @@
+                 {
+                     GraphicsPrimitive.tracePrimitive("OGLDrawAAParallelogram");
+                     realpipe.drawParallelogram(sg2d,
++                                               ux1, uy1, ux2, uy2,
+                                                x, y, dx1, dy1, dx2, dy2,
+                                                lw1, lw2);
+                 }
+@@ -166,21 +172,29 @@
+             oglr.fillSpans(sg2d, si, transx, transy);
+         }
+         public void fillParallelogram(SunGraphics2D sg2d,
++                                      double ux1, double uy1,
++                                      double ux2, double uy2,
+                                       double x, double y,
+                                       double dx1, double dy1,
+                                       double dx2, double dy2)
+         {
+             GraphicsPrimitive.tracePrimitive("OGLFillParallelogram");
+-            oglr.fillParallelogram(sg2d, x, y, dx1, dy1, dx2, dy2);
++            oglr.fillParallelogram(sg2d,
++                                   ux1, uy1, ux2, uy2,
++                                   x, y, dx1, dy1, dx2, dy2);
+         }
+         public void drawParallelogram(SunGraphics2D sg2d,
++                                      double ux1, double uy1,
++                                      double ux2, double uy2,
+                                       double x, double y,
+                                       double dx1, double dy1,
+                                       double dx2, double dy2,
+                                       double lw1, double lw2)
+         {
+             GraphicsPrimitive.tracePrimitive("OGLDrawParallelogram");
+-            oglr.drawParallelogram(sg2d, x, y, dx1, dy1, dx2, dy2, lw1, lw2);
++            oglr.drawParallelogram(sg2d,
++                                   ux1, uy1, ux2, uy2,
++                                   x, y, dx1, dy1, dx2, dy2, lw1, lw2);
+         }
+         public void copyArea(SunGraphics2D sg2d,
+                              int x, int y, int w, int h, int dx, int dy)
+diff -r 85f53467c30c -r f290441b0cb7 src/share/classes/sun/java2d/pipe/AAShapePipe.java
+--- openjdk.orig/jdk/src/share/classes/sun/java2d/pipe/AAShapePipe.java	Tue May 10 15:59:01 2011 -0700
++++ openjdk/jdk/src/share/classes/sun/java2d/pipe/AAShapePipe.java	Wed May 11 16:12:01 2011 -0700
+@@ -68,21 +68,23 @@
+         renderPath(sg, s, null);
+     }
+ 
+-    private static Rectangle2D computeBBox(double x, double y,
+-                                           double dx1, double dy1,
+-                                           double dx2, double dy2)
++    private static Rectangle2D computeBBox(double ux1, double uy1,
++                                           double ux2, double uy2)
+     {
+-        double lox, loy, hix, hiy;
+-        lox = hix = x;
+-        loy = hiy = y;
+-        if (dx1 < 0) { lox += dx1; } else { hix += dx1; }
+-        if (dy1 < 0) { loy += dy1; } else { hiy += dy1; }
+-        if (dx2 < 0) { lox += dx2; } else { hix += dx2; }
+-        if (dy2 < 0) { loy += dy2; } else { hiy += dy2; }
+-        return new Rectangle2D.Double(lox, loy, hix-lox, hiy-loy);
++        if ((ux2 -= ux1) < 0) {
++            ux1 += ux2;
++            ux2 = -ux2;
++        }
++        if ((uy2 -= uy1) < 0) {
++            uy1 += uy2;
++            uy2 = -uy2;
++        }
++        return new Rectangle2D.Double(ux1, uy1, ux2, uy2);
+     }
+ 
+     public void fillParallelogram(SunGraphics2D sg,
++                                  double ux1, double uy1,
++                                  double ux2, double uy2,
+                                   double x, double y,
+                                   double dx1, double dy1,
+                                   double dx2, double dy2)
+@@ -97,10 +99,12 @@
+             return;
+         }
+ 
+-        renderTiles(sg, computeBBox(x, y, dx1, dy1, dx2, dy2), aatg, abox);
++        renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox);
+     }
+ 
+     public void drawParallelogram(SunGraphics2D sg,
++                                  double ux1, double uy1,
++                                  double ux2, double uy2,
+                                   double x, double y,
+                                   double dx1, double dy1,
+                                   double dx2, double dy2,
+@@ -118,7 +122,7 @@
+ 
+         // Note that bbox is of the original shape, not the wide path.
+         // This is appropriate for handing to Paint methods...
+-        renderTiles(sg, computeBBox(x, y, dx1, dy1, dx2, dy2), aatg, abox);
++        renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox);
+     }
+ 
+     private static byte[] theTile;
+diff -r 85f53467c30c -r f290441b0cb7 src/share/classes/sun/java2d/pipe/AlphaColorPipe.java
+--- openjdk.orig/jdk/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java	Tue May 10 15:59:01 2011 -0700
++++ openjdk/jdk/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java	Wed May 11 16:12:01 2011 -0700
+@@ -66,6 +66,8 @@
+     }
+ 
+     public void fillParallelogram(SunGraphics2D sg,
++                                  double ux1, double uy1,
++                                  double ux2, double uy2,
+                                   double x, double y,
+                                   double dx1, double dy1,
+                                   double dx2, double dy2)
+@@ -75,6 +77,8 @@
+     }
+ 
+     public void drawParallelogram(SunGraphics2D sg,
++                                  double ux1, double uy1,
++                                  double ux2, double uy2,
+                                   double x, double y,
+                                   double dx1, double dy1,
+                                   double dx2, double dy2,
+diff -r 85f53467c30c -r f290441b0cb7 src/share/classes/sun/java2d/pipe/BufferedRenderPipe.java
+--- openjdk.orig/jdk/src/share/classes/sun/java2d/pipe/BufferedRenderPipe.java	Tue May 10 15:59:01 2011 -0700
++++ openjdk/jdk/src/share/classes/sun/java2d/pipe/BufferedRenderPipe.java	Wed May 11 16:12:01 2011 -0700
+@@ -408,6 +408,8 @@
+     }
+ 
+     public void fillParallelogram(SunGraphics2D sg2d,
++                                  double ux1, double uy1,
++                                  double ux2, double uy2,
+                                   double x, double y,
+                                   double dx1, double dy1,
+                                   double dx2, double dy2)
+@@ -429,6 +431,8 @@
+     }
+ 
+     public void drawParallelogram(SunGraphics2D sg2d,
++                                  double ux1, double uy1,
++                                  double ux2, double uy2,
+                                   double x, double y,
+                                   double dx1, double dy1,
+                                   double dx2, double dy2,
+@@ -454,6 +458,8 @@
+ 
+     private class AAParallelogramPipe implements ParallelogramPipe {
+         public void fillParallelogram(SunGraphics2D sg2d,
++                                      double ux1, double uy1,
++                                      double ux2, double uy2,
+                                       double x, double y,
+                                       double dx1, double dy1,
+                                       double dx2, double dy2)
+@@ -475,6 +481,8 @@
+         }
+ 
+         public void drawParallelogram(SunGraphics2D sg2d,
++                                      double ux1, double uy1,
++                                      double ux2, double uy2,
+                                       double x, double y,
+                                       double dx1, double dy1,
+                                       double dx2, double dy2,
+diff -r 85f53467c30c -r f290441b0cb7 src/share/classes/sun/java2d/pipe/LoopPipe.java
+--- openjdk.orig/jdk/src/share/classes/sun/java2d/pipe/LoopPipe.java	Tue May 10 15:59:01 2011 -0700
++++ openjdk/jdk/src/share/classes/sun/java2d/pipe/LoopPipe.java	Wed May 11 16:12:01 2011 -0700
+@@ -352,6 +352,8 @@
+     }
+ 
+     public void fillParallelogram(SunGraphics2D sg2d,
++                                  double ux1, double uy1,
++                                  double ux2, double uy2,
+                                   double x, double y,
+                                   double dx1, double dy1,
+                                   double dx2, double dy2)
+@@ -362,6 +364,8 @@
+     }
+ 
+     public void drawParallelogram(SunGraphics2D sg2d,
++                                  double ux1, double uy1,
++                                  double ux2, double uy2,
+                                   double x, double y,
+                                   double dx1, double dy1,
+                                   double dx2, double dy2,
+diff -r 85f53467c30c -r f290441b0cb7 src/share/classes/sun/java2d/pipe/ParallelogramPipe.java
+--- openjdk.orig/jdk/src/share/classes/sun/java2d/pipe/ParallelogramPipe.java	Tue May 10 15:59:01 2011 -0700
++++ openjdk/jdk/src/share/classes/sun/java2d/pipe/ParallelogramPipe.java	Wed May 11 16:12:01 2011 -0700
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2008, 2011 Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -40,9 +40,17 @@
+  *          => (x+dx2, y+dy2)
+  *          => origin
+  * </pre>
++ * The four u[xy][12] parameters are the unsorted extreme coordinates
++ * of the primitive in user space.  They may have been generated by a
++ * line or a rectangle so they could have u[xy]2 < u[xy]1 in some cases.
++ * They should be sorted before calculating the bounds of the original
++ * primitive (such as for calculating the user space bounds for the
++ * Paint.createContext() method).
+  */
+ public interface ParallelogramPipe {
+     public void fillParallelogram(SunGraphics2D sg,
++                                  double ux1, double uy1,
++                                  double ux2, double uy2,
+                                   double x, double y,
+                                   double dx1, double dy1,
+                                   double dx2, double dy2);
+@@ -59,6 +67,8 @@
+      * difference between the outer and inner parallelograms.
+      */
+     public void drawParallelogram(SunGraphics2D sg,
++                                  double ux1, double uy1,
++                                  double ux2, double uy2,
+                                   double x, double y,
+                                   double dx1, double dy1,
+                                   double dx2, double dy2,
+diff -r 85f53467c30c -r f290441b0cb7 src/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java
+--- openjdk.orig/jdk/src/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java	Tue May 10 15:59:01 2011 -0700
++++ openjdk/jdk/src/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java	Wed May 11 16:12:01 2011 -0700
+@@ -175,8 +175,8 @@
+     }
+ 
+     public boolean drawGeneralLine(SunGraphics2D sg2d,
+-                                   double x1, double y1,
+-                                   double x2, double y2)
++                                   double ux1, double uy1,
++                                   double ux2, double uy2)
+     {
+         if (sg2d.strokeState == SunGraphics2D.STROKE_CUSTOM ||
+             sg2d.strokeState == SunGraphics2D.STROKE_THINDASHED)
+@@ -194,13 +194,14 @@
+         double lw = bs.getLineWidth();
+         // Save the original dx, dy in case we need it to transform
+         // the linewidth as a perpendicular vector below
+-        double dx = x2 - x1;
+-        double dy = y2 - y1;
++        double dx = ux2 - ux1;
++        double dy = uy2 - uy1;
++        double x1, y1, x2, y2;
+         switch (sg2d.transformState) {
+         case SunGraphics2D.TRANSFORM_GENERIC:
+         case SunGraphics2D.TRANSFORM_TRANSLATESCALE:
+             {
+-                double coords[] = {x1, y1, x2, y2};
++                double coords[] = {ux1, uy1, ux2, uy2};
+                 sg2d.transform.transform(coords, 0, coords, 0, 2);
+                 x1 = coords[0];
+                 y1 = coords[1];
+@@ -213,13 +214,17 @@
+             {
+                 double tx = sg2d.transform.getTranslateX();
+                 double ty = sg2d.transform.getTranslateY();
+-                x1 += tx;
+-                y1 += ty;
+-                x2 += tx;
+-                y2 += ty;
++                x1 = ux1 + tx;
++                y1 = uy1 + ty;
++                x2 = ux2 + tx;
++                y2 = uy2 + ty;
+             }
+             break;
+         case SunGraphics2D.TRANSFORM_ISIDENT:
++            x1 = ux1;
++            y1 = uy1;
++            x2 = ux2;
++            y2 = uy2;
+             break;
+         default:
+             throw new InternalError("unknown TRANSFORM state...");
+@@ -279,7 +284,8 @@
+             dx += udx;
+             dy += udy;
+         }
+-        outrenderer.fillParallelogram(sg2d, px, py, -udy, udx, dx, dy);
++        outrenderer.fillParallelogram(sg2d, ux1, uy1, ux2, uy2,
++                                      px, py, -udy, udx, dx, dy);
+         return true;
+     }
+ 
+@@ -313,7 +319,8 @@
+             px = newx;
+             py = newy;
+         }
+-        outrenderer.fillParallelogram(sg2d, px, py, dx1, dy1, dx2, dy2);
++        outrenderer.fillParallelogram(sg2d, rx, ry, rx+rw, ry+rh,
++                                      px, py, dx1, dy1, dx2, dy2);
+     }
+ 
+     public void drawRectangle(SunGraphics2D sg2d,
+@@ -360,10 +367,12 @@
+             // entire hole in the middle of the parallelogram
+             // so we can just fill the outer parallelogram.
+             fillOuterParallelogram(sg2d,
++                                   rx, ry, rx+rw, ry+rh,
+                                    px, py, dx1, dy1, dx2, dy2,
+                                    len1, len2, lw1, lw2);
+         } else {
+             outrenderer.drawParallelogram(sg2d,
++                                          rx, ry, rx+rw, ry+rh,
+                                           px, py, dx1, dy1, dx2, dy2,
+                                           lw1 / len1, lw2 / len2);
+         }
+@@ -377,6 +386,8 @@
+      * and issues a single fillParallelogram request to fill it.
+      */
+     public void fillOuterParallelogram(SunGraphics2D sg2d,
++                                       double ux1, double uy1,
++                                       double ux2, double uy2,
+                                        double px, double py,
+                                        double dx1, double dy1,
+                                        double dx2, double dy2,
+@@ -412,6 +423,7 @@
+         dx2 += udx2;
+         dy2 += udy2;
+ 
+-        outrenderer.fillParallelogram(sg2d, px, py, dx1, dy1, dx2, dy2);
++        outrenderer.fillParallelogram(sg2d, ux1, uy1, ux2, uy2,
++                                      px, py, dx1, dy1, dx2, dy2);
+     }
+ }
+diff -r 85f53467c30c -r f290441b0cb7 src/windows/classes/sun/java2d/d3d/D3DRenderer.java
+--- openjdk.orig/jdk/src/windows/classes/sun/java2d/d3d/D3DRenderer.java	Tue May 10 15:59:01 2011 -0700
++++ openjdk/jdk/src/windows/classes/sun/java2d/d3d/D3DRenderer.java	Wed May 11 16:12:01 2011 -0700
+@@ -102,15 +102,20 @@
+             final ParallelogramPipe realpipe = d3dr.getAAParallelogramPipe();
+             return new ParallelogramPipe() {
+                 public void fillParallelogram(SunGraphics2D sg2d,
++                                              double ux1, double uy1,
++                                              double ux2, double uy2,
+                                               double x, double y,
+                                               double dx1, double dy1,
+                                               double dx2, double dy2)
+                 {
+                     GraphicsPrimitive.tracePrimitive("D3DFillAAParallelogram");
+                     realpipe.fillParallelogram(sg2d,
++                                               ux1, uy1, ux2, uy2,
+                                                x, y, dx1, dy1, dx2, dy2);
+                 }
+                 public void drawParallelogram(SunGraphics2D sg2d,
++                                              double ux1, double uy1,
++                                              double ux2, double uy2,
+                                               double x, double y,
+                                               double dx1, double dy1,
+                                               double dx2, double dy2,
+@@ -118,6 +123,7 @@
+                 {
+                     GraphicsPrimitive.tracePrimitive("D3DDrawAAParallelogram");
+                     realpipe.drawParallelogram(sg2d,
++                                               ux1, uy1, ux2, uy2,
+                                                x, y, dx1, dy1, dx2, dy2,
+                                                lw1, lw2);
+                 }
+@@ -167,21 +173,29 @@
+             d3dr.fillSpans(sg2d, si, transx, transy);
+         }
+         public void fillParallelogram(SunGraphics2D sg2d,
++                                      double ux1, double uy1,
++                                      double ux2, double uy2,
+                                       double x, double y,
+                                       double dx1, double dy1,
+                                       double dx2, double dy2)
+         {
+             GraphicsPrimitive.tracePrimitive("D3DFillParallelogram");
+-            d3dr.fillParallelogram(sg2d, x, y, dx1, dy1, dx2, dy2);
++            d3dr.fillParallelogram(sg2d,
++                                   ux1, uy1, ux2, uy2,
++                                   x, y, dx1, dy1, dx2, dy2);
+         }
+         public void drawParallelogram(SunGraphics2D sg2d,
++                                      double ux1, double uy1,
++                                      double ux2, double uy2,
+                                       double x, double y,
+                                       double dx1, double dy1,
+                                       double dx2, double dy2,
+                                       double lw1, double lw2)
+         {
+             GraphicsPrimitive.tracePrimitive("D3DDrawParallelogram");
+-            d3dr.drawParallelogram(sg2d, x, y, dx1, dy1, dx2, dy2, lw1, lw2);
++            d3dr.drawParallelogram(sg2d,
++                                   ux1, uy1, ux2, uy2,
++                                   x, y, dx1, dy1, dx2, dy2, lw1, lw2);
+         }
+         public void copyArea(SunGraphics2D sg2d,
+                              int x, int y, int w, int h, int dx, int dy)
+diff -r 85f53467c30c -r f290441b0cb7 test/java/awt/Paint/PgramUserBoundsTest.java
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ openjdk/jdk/test/java/awt/Paint/PgramUserBoundsTest.java	Wed May 11 16:12:01 2011 -0700
+@@ -0,0 +1,126 @@
++/*
++ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * This code is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 only, as
++ * published by the Free Software Foundation.
++ *
++ * This code is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * version 2 for more details (a copy is included in the LICENSE file that
++ * accompanied this code).
++ *
++ * You should have received a copy of the GNU General Public License version
++ * 2 along with this work; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
++ * or visit www.oracle.com if you need additional information or have any
++ * questions.
++ */
++
++/**
++ * @test
++ * @bug 7043054
++ * @summary Verifies that Paint objects receive the appropriate user space
++ *          bounds in their createContext() method
++ * @run main PgramUserBoundsTest
++ */
++
++import java.awt.Color;
++import java.awt.Graphics2D;
++import java.awt.Paint;
++import java.awt.PaintContext;
++import java.awt.RenderingHints;
++import java.awt.Rectangle;
++import java.awt.geom.AffineTransform;
++import java.awt.geom.Line2D;
++import java.awt.geom.Rectangle2D;
++import java.awt.image.BufferedImage;
++import java.awt.image.ColorModel;
++
++public class PgramUserBoundsTest {
++    static final int MinX = 10;
++    static final int MinY = 20;
++    static final int MaxX = 30;
++    static final int MaxY = 50;
++    static AffineTransform identity = new AffineTransform();
++
++    public static void main(String argv[]) {
++        BufferedImage bimg =
++            new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
++        Graphics2D g2d = bimg.createGraphics();
++        g2d.setPaint(new BoundsCheckerPaint(MinX, MinY, MaxX, MaxY));
++        testAll(g2d);
++        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
++                             RenderingHints.VALUE_ANTIALIAS_ON);
++        testAll(g2d);
++    }
++
++    static void testAll(Graphics2D g2d) {
++        g2d.setTransform(identity);
++        g2d.translate(100, 100);
++        testPrimitives(g2d);
++
++        g2d.setTransform(identity);
++        g2d.scale(10, 10);
++        testPrimitives(g2d);
++
++        g2d.setTransform(identity);
++        g2d.rotate(Math.PI/6);
++        testPrimitives(g2d);
++    }
++
++    static void testPrimitives(Graphics2D g2d) {
++        testLine(g2d);
++        testRect(g2d);
++    }
++
++    static void testLine(Graphics2D g2d) {
++        testLine(g2d, MinX, MinY, MaxX, MaxY);
++        testLine(g2d, MaxX, MinY, MinX, MaxY);
++        testLine(g2d, MinX, MaxY, MaxX, MinY);
++        testLine(g2d, MaxX, MaxY, MinX, MinY);
++    }
++
++    static void testRect(Graphics2D g2d) {
++        g2d.fillRect(MinX, MinY, MaxX - MinX, MaxY - MinY);
++        g2d.fill(new Rectangle(MinX, MinY, MaxX - MinX, MaxY - MinY));
++    }
++
++    static void testLine(Graphics2D g2d, int x1, int y1, int x2, int y2) {
++        g2d.drawLine(x1, y1, x2, y2);
++        g2d.draw(new Line2D.Double(x1, y1, x2, y2));
++    }
++
++    static class BoundsCheckerPaint implements Paint {
++        private Color c = Color.WHITE;
++        private Rectangle2D expectedBounds;
++
++        public BoundsCheckerPaint(double x1, double y1,
++                                  double x2, double y2)
++        {
++            expectedBounds = new Rectangle2D.Double();
++            expectedBounds.setFrameFromDiagonal(x1, y1, x2, y2);
++        }
++
++        public int getTransparency() {
++            return c.getTransparency();
++        }
++
++        public PaintContext createContext(ColorModel cm,
++                                          Rectangle deviceBounds,
++                                          Rectangle2D userBounds,
++                                          AffineTransform xform,
++                                          RenderingHints hints)
++        {
++            System.out.println("user bounds = "+userBounds);
++            if (!userBounds.equals(expectedBounds)) {
++                throw new RuntimeException("bounds fail to match");
++            }
++            return c.createContext(cm, deviceBounds, userBounds, xform, hints);
++        }
++    }
++}
+exporting patch:
+<fdopen>