1 /* 2 * Copyright (c) 2015, 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 import java.awt.Color; 25 import java.awt.Graphics2D; 26 import java.awt.GraphicsConfiguration; 27 import java.awt.GraphicsEnvironment; 28 import java.awt.Image; 29 import java.awt.Rectangle; 30 import java.awt.Shape; 31 import java.awt.geom.AffineTransform; 32 import java.awt.image.BufferedImage; 33 import java.awt.image.VolatileImage; 34 import java.io.File; 35 import java.io.IOException; 36 37 import javax.imageio.ImageIO; 38 39 import static java.awt.geom.Rectangle2D.Double; 40 41 /** 42 * @test 43 * @bug 8061831 8130400 44 * @summary Tests drawing volatile image to volatile image using different 45 * clips + xor mode. Results of the blit compatibleImage to 46 * compatibleImage is used for comparison. 47 */ 48 public final class IncorrectClipXorModeSurface2Surface { 49 50 private static int[] SIZES = {2, 10, 100}; 51 private static final Shape[] SHAPES = { 52 new Rectangle(0, 0, 0, 0), 53 new Rectangle(0, 0, 1, 1), 54 new Rectangle(0, 1, 1, 1), 55 new Rectangle(1, 0, 1, 1), 56 new Rectangle(1, 1, 1, 1), 57 58 new Double(0, 0, 0.5, 0.5), 59 new Double(0, 0.5, 0.5, 0.5), 60 new Double(0.5, 0, 0.5, 0.5), 61 new Double(0.5, 0.5, 0.5, 0.5), 62 new Double(0.25, 0.25, 0.5, 0.5), 63 new Double(0, 0.25, 1, 0.5), 64 new Double(0.25, 0, 0.5, 1), 65 66 new Double(.10, .10, .20, .20), 67 new Double(.75, .75, .20, .20), 68 new Double(.75, .10, .20, .20), 69 new Double(.10, .75, .20, .20), 70 }; 71 72 public static void main(final String[] args) throws IOException { 73 GraphicsEnvironment ge = GraphicsEnvironment 74 .getLocalGraphicsEnvironment(); 75 GraphicsConfiguration gc = ge.getDefaultScreenDevice() 76 .getDefaultConfiguration(); 77 AffineTransform at; 78 for (int size : SIZES) { 79 at = AffineTransform.getScaleInstance(size, size); 80 for (Shape clip : SHAPES) { 81 clip = at.createTransformedShape(clip); 82 for (Shape to : SHAPES) { 83 to = at.createTransformedShape(to); 84 // Prepare test images 85 BufferedImage snapshot; 86 VolatileImage source = getVolatileImage(gc, size); 87 VolatileImage target = getVolatileImage(gc, size); 88 int attempt = 0; 89 while (true) { 90 if (++attempt > 10) { 91 throw new RuntimeException("Too many attempts: " + attempt); 92 } 93 // Prepare source images 94 source.validate(gc); 95 Graphics2D g2d = source.createGraphics(); 96 g2d.setColor(Color.RED); 97 g2d.fillRect(0, 0, size, size); 98 g2d.dispose(); 99 if (source.validate(gc) != VolatileImage.IMAGE_OK) { 100 continue; 101 } 102 // Prepare target images 103 target.validate(gc); 104 g2d = target.createGraphics(); 105 g2d.setColor(Color.GREEN); 106 g2d.fillRect(0, 0, size, size); 107 g2d.dispose(); 108 if (target.validate(gc) != VolatileImage.IMAGE_OK) { 109 continue; 110 } 111 112 draw(clip, to, source, target); 113 snapshot = target.getSnapshot(); 114 if (source.contentsLost() || target.contentsLost()) { 115 continue; 116 } 117 break; 118 } 119 // Prepare gold images 120 BufferedImage goldS = getSourceGold(gc, size); 121 BufferedImage goldT = getTargetGold(gc, size); 122 draw(clip, to, goldS, goldT); 123 validate(snapshot, goldT); 124 source.flush(); 125 target.flush(); 126 } 127 } 128 } 129 } 130 131 private static void draw(Shape clip, Shape shape, Image from, Image to) { 132 Graphics2D g2d = (Graphics2D) to.getGraphics(); 133 g2d.setXORMode(Color.BLACK); 134 g2d.setClip(clip); 135 Rectangle toBounds = shape.getBounds(); 136 g2d.drawImage(from, toBounds.x, toBounds.y, toBounds.width, 137 toBounds.height, null); 138 g2d.dispose(); 139 } 140 141 private static BufferedImage getSourceGold(GraphicsConfiguration gc, 142 int size) { 143 final BufferedImage bi = gc.createCompatibleImage(size, size); 144 Graphics2D g2d = bi.createGraphics(); 145 g2d.setColor(Color.RED); 146 g2d.fillRect(0, 0, size, size); 147 g2d.dispose(); 148 return bi; 149 } 150 151 private static BufferedImage getTargetGold(GraphicsConfiguration gc, 152 int size) { 153 BufferedImage image = gc.createCompatibleImage(size, size); 154 Graphics2D g2d = image.createGraphics(); 155 g2d.setColor(Color.GREEN); 156 g2d.fillRect(0, 0, size, size); 157 g2d.dispose(); 158 return image; 159 } 160 161 private static VolatileImage getVolatileImage(GraphicsConfiguration gc, 162 int size) { 163 return gc.createCompatibleVolatileImage(size, size); 164 } 165 166 private static void validate(BufferedImage bi, BufferedImage goldbi) 167 throws IOException { 168 for (int x = 0; x < bi.getWidth(); ++x) { 169 for (int y = 0; y < bi.getHeight(); ++y) { 170 if (goldbi.getRGB(x, y) != bi.getRGB(x, y)) { 171 ImageIO.write(bi, "png", new File("actual.png")); 172 ImageIO.write(goldbi, "png", new File("expected.png")); 173 throw new RuntimeException("Test failed."); 174 } 175 } 176 } 177 } 178 }