7043054: REGRESSION: JDK 7 b126 : Wrong userBounds in Paint.createContext()
Reviewed-by: prr
--- a/jdk/src/share/classes/sun/java2d/opengl/OGLRenderer.java Tue May 10 15:59:01 2011 -0700
+++ b/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)
--- a/jdk/src/share/classes/sun/java2d/pipe/AAShapePipe.java Tue May 10 15:59:01 2011 -0700
+++ b/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;
--- a/jdk/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java Tue May 10 15:59:01 2011 -0700
+++ b/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,
--- a/jdk/src/share/classes/sun/java2d/pipe/BufferedRenderPipe.java Tue May 10 15:59:01 2011 -0700
+++ b/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,
--- a/jdk/src/share/classes/sun/java2d/pipe/LoopPipe.java Tue May 10 15:59:01 2011 -0700
+++ b/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,
--- a/jdk/src/share/classes/sun/java2d/pipe/ParallelogramPipe.java Tue May 10 15:59:01 2011 -0700
+++ b/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,
--- a/jdk/src/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java Tue May 10 15:59:01 2011 -0700
+++ b/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);
}
}
--- a/jdk/src/windows/classes/sun/java2d/d3d/D3DRenderer.java Tue May 10 15:59:01 2011 -0700
+++ b/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)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/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);
+ }
+ }
+}