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