1 /* 2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @summary Filling Java GeneralPath shapes using the even-odd winding rule doesn't work correctly when a GradientPaint or TexturePaint is used. 27 * @summary com.apple.junit.java.graphics.color 28 * @library ../regtesthelpers 29 * @build VisibilityValidator 30 * @run main R5214320TestEvenOddGradientFill 31 */ 32 33 import test.java.awt.regtesthelpers.VisibilityValidator; 34 import junit.framework.*; 35 import javax.swing.*; 36 import java.awt.*; 37 import java.awt.geom.AffineTransform; 38 import java.awt.geom.GeneralPath; 39 import java.awt.geom.Path2D; 40 import java.awt.image.BufferedImage; 41 42 /* 43 * Filling Java GeneralPath shapes using the even-odd winding rule doesn't work correctly when a GradientPaint or TexturePaint is used. 44 * 45 * Steps to Reproduce 46 * 47 * The following code generates a Java GeneralPath consisting of a outer rectangle (clockwise) and an inner rectangle (also clockwise), using the even-odd winding rule. 48 * 49 * GeneralPath gp = new GeneralPath(GeneralPath.WIND_EVEN_ODD); 50 * gp.append(new Rectangle(0, 0, 200, 200), false); 51 * gp.closePath(); 52 * gp.append(new Rectangle(50, 50, 100, 100), false); 53 * gp.closePath(); 54 * 55 * g2d.setPaint(new GradientPaint(0f, 0f, Color.BLUE, 200f, 200f, Color.YELLOW)); 56 * g2d.fill(gp); 57 * 58 * gp.transform(AffineTransform.getTranslateInstance(200, 0)); 59 * g2d.setPaint(Color.ORANGE); 60 * g2d.fill(gp); 61 * 62 * Expected Result 63 * 64 * The filled shapes should look like square donuts - i.e., a square shape with a square hole in the center. 65 * 66 * Actual Result 67 * 68 * When filled using a solid color, the outer loop is filled and the inner loop is empty (as it should be). When filled using a GradientPaint or TexturePaint, the inner rectangle is also filled (which is incorrect). 69 * 70 * Regression 71 * 72 * This code works correctly under Windows. 73 */ 74 public class R5214320TestEvenOddGradientFill extends TestCase { 75 private final static int INNER_LENGTH = 100; 76 private final static int OUTER_LENGTH = 200; 77 private final static int INNER_X = (OUTER_LENGTH - INNER_LENGTH)/2; 78 private final static int INNER_Y = INNER_X; 79 private final static Color FRAME_BACKGROUND = Color.white; 80 81 private JFrame frame = null; 82 private Robot robot; 83 84 protected void setUp() throws Exception { 85 if (robot == null) { 86 robot = new Robot(); 87 } 88 89 frame = new JFrame("TestEventOdd"); 90 frame.setBackground(FRAME_BACKGROUND); 91 frame.getContentPane().add(new EvenOddFill()); 92 frame.setSize(3*OUTER_LENGTH, OUTER_LENGTH+20); 93 } 94 95 private static class EvenOddFill extends Panel { 96 97 public void paint(Graphics g) { 98 Graphics2D g2d = (Graphics2D)g; 99 100 GeneralPath gp = new GeneralPath(Path2D.WIND_EVEN_ODD); 101 gp.append(new Rectangle(0, 0, OUTER_LENGTH, OUTER_LENGTH), false); 102 gp.closePath(); 103 gp.append(new Rectangle(INNER_X, INNER_Y, INNER_LENGTH, INNER_LENGTH), false); 104 gp.closePath(); 105 106 g2d.setPaint(new GradientPaint(0f, 0f, Color.BLUE, 200f, 200f, Color.YELLOW)); 107 g2d.fill(gp); 108 109 gp.transform(AffineTransform.getTranslateInstance(OUTER_LENGTH, 0)); 110 BufferedImage bi = new BufferedImage(2,2,BufferedImage.TYPE_INT_RGB); 111 bi.setRGB(0, 0, 0xffffffff); bi.setRGB(1, 0, 0xffffffff); 112 bi.setRGB(0, 1, 0xffffffff); bi.setRGB(1, 1, 0xff0000ff); 113 TexturePaint bluedots = new TexturePaint(bi,new Rectangle(0,0,2,2)); 114 g2d.setPaint(bluedots); 115 g2d.fill(gp); 116 117 gp.transform(AffineTransform.getTranslateInstance(OUTER_LENGTH, 0)); 118 g2d.setPaint(Color.ORANGE); 119 g2d.fill(gp); 120 } 121 } 122 123 public void testEvenOddFill() throws Exception { 124 VisibilityValidator.setVisibleAndConfirm(frame); 125 Thread.sleep(125); // Let humans see it too... 126 Point loc = frame.getLocationOnScreen(); 127 loc.x = loc.x + OUTER_LENGTH/2; 128 loc.y = loc.y + OUTER_LENGTH/2; 129 robot.mouseMove(loc.x, loc.y); 130 //System.out.println("robot.getPixelColor("+loc.x+", "+loc.y+"): "+robot.getPixelColor(loc.x, loc.y)); 131 assertTrue("Timed out without seeing a square donut for the first even-odd fill", VisibilityValidator.waitForColor(frame, loc.x, loc.y, FRAME_BACKGROUND)); 132 } 133 134 protected void tearDown() { 135 frame.dispose(); 136 } 137 138 139 public static Test suite() { 140 return new TestSuite(R5214320TestEvenOddGradientFill.class); 141 } 142 143 public static void main (String[] args) throws RuntimeException { 144 TestResult tr = junit.textui.TestRunner.run(suite()); 145 if ((tr.errorCount() != 0) || (tr.failureCount() != 0)) { 146 throw new RuntimeException("### FAILED: unexpected JUnit errors or failures."); 147 } 148 } 149 }