1 /*
   2  * Copyright (c) 2014, 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.AlphaComposite;
  25 import java.awt.Color;
  26 import java.awt.Graphics2D;
  27 import java.awt.GraphicsConfiguration;
  28 import java.awt.GraphicsEnvironment;
  29 import java.awt.Image;
  30 import java.awt.Rectangle;
  31 import java.awt.Shape;
  32 import java.awt.geom.AffineTransform;
  33 import java.awt.geom.Ellipse2D;
  34 import java.awt.image.BufferedImage;
  35 import java.awt.image.VolatileImage;
  36 import java.io.File;
  37 import java.io.IOException;
  38 
  39 import javax.imageio.ImageIO;
  40 
  41 import static java.awt.geom.Rectangle2D.Double;
  42 
  43 /**
  44  * @test
  45  * @bug 8041644
  46  * @summary Tests drawing volatile image to BI using different clip.
  47  *          Results of the blit compatibleImage to BI used for comparison.
  48  * @author Sergey Bylokhov
  49  */
  50 public final class IncorrectClipSurface2SW {
  51 
  52     private static int[] SCALES = {1, 2, 4};
  53     private static int[] SIZES = {127, 3, 2, 1};
  54     private static final Shape[] SHAPES = {new Rectangle(0, 0, 0, 0),
  55                                            new Rectangle(0, 0, 1, 1),
  56                                            new Rectangle(0, 1, 1, 1),
  57                                            new Rectangle(1, 0, 1, 1),
  58                                            new Rectangle(1, 1, 1, 1),
  59 
  60                                            new Ellipse2D.Double(0, 0, 1, 1),
  61                                            new Ellipse2D.Double(0, 1, 1, 1),
  62                                            new Ellipse2D.Double(1, 0, 1, 1),
  63                                            new Ellipse2D.Double(1, 1, 1, 1),
  64                                            new Ellipse2D.Double(.25, .25, .5,
  65                                                                 .5),
  66 
  67                                            new Double(0, 0, 0.5, 0.5),
  68                                            new Double(0, 0.5, 0.5, 0.5),
  69                                            new Double(0.5, 0, 0.5, 0.5),
  70                                            new Double(0.5, 0.5, 0.5, 0.5),
  71                                            new Double(0.25, 0.25, 0.5, 0.5),
  72                                            new Double(0, 0.25, 1, 0.5),
  73                                            new Double(0.25, 0, 0.5, 1),
  74 
  75                                            new Double(.10, .10, .20, .20),
  76                                            new Double(.75, .75, .20, .20),
  77                                            new Double(.75, .10, .20, .20),
  78                                            new Double(.10, .75, .20, .20),};
  79 
  80     public static void main(final String[] args) throws IOException {
  81         GraphicsEnvironment ge = GraphicsEnvironment
  82                 .getLocalGraphicsEnvironment();
  83         GraphicsConfiguration gc = ge.getDefaultScreenDevice()
  84                                      .getDefaultConfiguration();
  85         AffineTransform at;
  86         for (final int size : SIZES) {
  87             for (final int scale : SCALES) {
  88                 final int sw = size * scale;
  89                 at = AffineTransform.getScaleInstance(sw, sw);
  90                 for (Shape clip : SHAPES) {
  91                     clip = at.createTransformedShape(clip);
  92                     for (Shape to : SHAPES) {
  93                         to = at.createTransformedShape(to);
  94                         // Prepare test images
  95                         VolatileImage vi = getVolatileImage(gc, size);
  96                         BufferedImage bi = getBufferedImage(sw);
  97                         // Prepare gold images
  98                         BufferedImage goldvi = getCompatibleImage(gc, size);
  99                         BufferedImage goldbi = getBufferedImage(sw);
 100                         draw(clip, to, vi, bi, scale);
 101                         draw(clip, to, goldvi, goldbi, scale);
 102                         validate(bi, goldbi);
 103                     }
 104                 }
 105             }
 106         }
 107     }
 108 
 109     private static void draw(Shape clip, Shape to, Image vi, BufferedImage bi,
 110                              int scale) {
 111         Graphics2D big = bi.createGraphics();
 112         big.setComposite(AlphaComposite.Src);
 113         big.setClip(clip);
 114         Rectangle toBounds = to.getBounds();
 115         int x1 = toBounds.x;
 116 
 117         int y1 = toBounds.y;
 118         int x2 = x1 + toBounds.width;
 119         int y2 = y1 + toBounds.height;
 120         big.drawImage(vi, x1, y1, x2, y2, 0, 0, toBounds.width / scale,
 121                       toBounds.height / scale, null);
 122         big.dispose();
 123         vi.flush();
 124     }
 125 
 126     private static BufferedImage getBufferedImage(int sw) {
 127         BufferedImage bi = new BufferedImage(sw, sw,
 128                                              BufferedImage.TYPE_INT_ARGB);
 129         Graphics2D g2d = bi.createGraphics();
 130         g2d.setColor(Color.RED);
 131         g2d.fillRect(0, 0, sw, sw);
 132         return bi;
 133     }
 134 
 135     private static VolatileImage getVolatileImage(GraphicsConfiguration gc,
 136                                                   int size) {
 137         VolatileImage vi = gc.createCompatibleVolatileImage(size, size);
 138         Graphics2D g2d = vi.createGraphics();
 139         g2d.setColor(Color.GREEN);
 140         g2d.fillRect(0, 0, size, size);
 141         return vi;
 142     }
 143 
 144     private static BufferedImage getCompatibleImage(GraphicsConfiguration gc,
 145                                                     int size) {
 146         BufferedImage image = gc.createCompatibleImage(size, size);
 147         Graphics2D g2d = image.createGraphics();
 148         g2d.setColor(Color.GREEN);
 149         g2d.fillRect(0, 0, size, size);
 150         return image;
 151     }
 152 
 153     private static void validate(BufferedImage bi, BufferedImage goldbi)
 154             throws IOException {
 155         for (int x = 0; x < bi.getWidth(); ++x) {
 156             for (int y = 0; y < bi.getHeight(); ++y) {
 157                 if (goldbi.getRGB(x, y) != bi.getRGB(x, y)) {
 158                     ImageIO.write(bi, "png", new File("actual.png"));
 159                     ImageIO.write(goldbi, "png", new File("expected.png"));
 160                     throw new RuntimeException("Test failed.");
 161                 }
 162             }
 163         }
 164     }
 165 }