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