diff --git a/src/share/classes/sun/java2d/opengl/OGLRenderer.java b/src/share/classes/sun/java2d/opengl/OGLRenderer.java index df9377e69e5628eb316ee24261ec127354590af7..935c68c170e3d556cdff994da7bc44545a4d2821 100644 --- a/src/share/classes/sun/java2d/opengl/OGLRenderer.java +++ b/src/share/classes/sun/java2d/opengl/OGLRenderer.java @@ -102,15 +102,20 @@ class OGLRenderer extends BufferedRenderPipe { 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 @@ class OGLRenderer extends BufferedRenderPipe { { GraphicsPrimitive.tracePrimitive("OGLDrawAAParallelogram"); realpipe.drawParallelogram(sg2d, + ux1, uy1, ux2, uy2, x, y, dx1, dy1, dx2, dy2, lw1, lw2); } @@ -166,21 +172,29 @@ class OGLRenderer extends BufferedRenderPipe { 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 --git a/src/share/classes/sun/java2d/pipe/AAShapePipe.java b/src/share/classes/sun/java2d/pipe/AAShapePipe.java index 6547f0e234e9b4a79916b1b4b30b5f45f75eb4d7..eaa821d90228ebf5e35437dc0007e9da339b09f0 100644 --- a/src/share/classes/sun/java2d/pipe/AAShapePipe.java +++ b/src/share/classes/sun/java2d/pipe/AAShapePipe.java @@ -68,21 +68,23 @@ public class AAShapePipe 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 @@ public class AAShapePipe 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 @@ public class AAShapePipe // 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 --git a/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java b/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java index d19a895cb16bcc0377f136a5bf80f534715a0b04..2b0ea08280e68b427eed0835ffc264ae185749f4 100644 --- a/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java +++ b/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java @@ -66,6 +66,8 @@ public class AlphaColorPipe implements CompositePipe, 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) @@ -75,6 +77,8 @@ public class AlphaColorPipe implements CompositePipe, ParallelogramPipe { } 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 --git a/src/share/classes/sun/java2d/pipe/BufferedRenderPipe.java b/src/share/classes/sun/java2d/pipe/BufferedRenderPipe.java index 675c8d71ff81b9c6fe20cbca083a32cf3acbd4e1..c5f30976958019cb7e27b7eff5b8578eaec0a96a 100644 --- a/src/share/classes/sun/java2d/pipe/BufferedRenderPipe.java +++ b/src/share/classes/sun/java2d/pipe/BufferedRenderPipe.java @@ -408,6 +408,8 @@ public abstract class BufferedRenderPipe } 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 abstract class BufferedRenderPipe } 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 @@ public abstract class BufferedRenderPipe 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 abstract class BufferedRenderPipe } 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 --git a/src/share/classes/sun/java2d/pipe/LoopPipe.java b/src/share/classes/sun/java2d/pipe/LoopPipe.java index 652239d784a93c7d2784ff3498b950627142665b..3df4adc893c6c1af3a91e73eb0325f6ae13db745 100644 --- a/src/share/classes/sun/java2d/pipe/LoopPipe.java +++ b/src/share/classes/sun/java2d/pipe/LoopPipe.java @@ -352,6 +352,8 @@ public class LoopPipe } 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 class LoopPipe } 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 --git a/src/share/classes/sun/java2d/pipe/ParallelogramPipe.java b/src/share/classes/sun/java2d/pipe/ParallelogramPipe.java index cefc09f10f2f4a4f4966be18d8e2b8f1615d2a67..57a9372ec13c02e39d299315ca7775e8905e374b 100644 --- a/src/share/classes/sun/java2d/pipe/ParallelogramPipe.java +++ b/src/share/classes/sun/java2d/pipe/ParallelogramPipe.java @@ -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 @@ import sun.java2d.SunGraphics2D; * => (x+dx2, y+dy2) * => origin * + * 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 @@ public interface ParallelogramPipe { * 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 --git a/src/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java b/src/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java index 3564fdf001ee8e8579baf96cd68bfe9760627794..86fcc5eaa17fb68ffd1b2da5e746d9655b687648 100644 --- a/src/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java +++ b/src/share/classes/sun/java2d/pipe/PixelToParallelogramConverter.java @@ -175,8 +175,8 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter } 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 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter 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 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter { 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 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter 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 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter 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 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter // 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 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter * 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 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter 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 --git a/src/windows/classes/sun/java2d/d3d/D3DRenderer.java b/src/windows/classes/sun/java2d/d3d/D3DRenderer.java index cd4e40df92a673718710f1fb4dfff5bf4c8fb7c5..1fc4f661535dfc352e31b04d8256549c9283d1ad 100644 --- a/src/windows/classes/sun/java2d/d3d/D3DRenderer.java +++ b/src/windows/classes/sun/java2d/d3d/D3DRenderer.java @@ -102,15 +102,20 @@ class D3DRenderer extends BufferedRenderPipe { 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 @@ class D3DRenderer extends BufferedRenderPipe { { GraphicsPrimitive.tracePrimitive("D3DDrawAAParallelogram"); realpipe.drawParallelogram(sg2d, + ux1, uy1, ux2, uy2, x, y, dx1, dy1, dx2, dy2, lw1, lw2); } @@ -167,21 +173,29 @@ class D3DRenderer extends BufferedRenderPipe { 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 --git a/test/java/awt/Paint/PgramUserBoundsTest.java b/test/java/awt/Paint/PgramUserBoundsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9c71f3482199a285a406b9d199ad98cbfbbd58f0 --- /dev/null +++ b/test/java/awt/Paint/PgramUserBoundsTest.java @@ -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); + } + } +}