1 /*
   2  * Copyright (c) 2005, 2010, 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   @key headful
  27   @bug 6244574
  28   @bug 6258142
  29   @bug 6395165
  30   @bug 6588884
  31   @summary Tests that source is clipped correctly when blitting
  32   different types of images to the screen
  33   @author Dmitri.Trembovetski: area=Graphics2D
  34   @run main SourceClippingBlitTest
  35 */
  36 
  37 import java.awt.AWTException;
  38 import java.awt.Canvas;
  39 import java.awt.Color;
  40 import java.awt.Dimension;
  41 import java.awt.Frame;
  42 import java.awt.Graphics;
  43 import java.awt.GraphicsConfiguration;
  44 import java.awt.Image;
  45 import java.awt.Point;
  46 import java.awt.Rectangle;
  47 import java.awt.Robot;
  48 import java.awt.Toolkit;
  49 import java.awt.Transparency;
  50 import java.awt.event.ComponentAdapter;
  51 import java.awt.event.ComponentEvent;
  52 import java.awt.event.WindowAdapter;
  53 import java.awt.event.WindowEvent;
  54 import java.awt.image.BufferedImage;
  55 import java.awt.image.VolatileImage;
  56 
  57 public class SourceClippingBlitTest extends Canvas {
  58     static final int TESTW = 300;
  59     static final int TESTH = 300;
  60     static final int IMAGEW = 50;
  61     static final int IMAGEH = 50;
  62 
  63     static final Rectangle IMAGE_BOUNDS = new Rectangle(0, 0, IMAGEW, IMAGEH);
  64     static Robot robot;
  65     static private boolean showErrors;
  66 
  67     private static final Object lock = new Object();
  68     private static volatile boolean done = false;
  69 
  70     BufferedImage grabbedBI;
  71 
  72     public static void main(String[] args) {
  73         // allow user to override the properties if needed
  74         if (System.getProperty("sun.java2d.pmoffscreen") == null) {
  75             System.setProperty("sun.java2d.pmoffscreen", "true");
  76         }
  77 
  78         if (args.length > 0 && args[0].equals("-showerrors")) {
  79             showErrors = true;
  80         }
  81 
  82         try {
  83             robot = new Robot();
  84         } catch (AWTException e) {
  85             throw new RuntimeException(e);
  86         }
  87 
  88         Frame f = new Frame(SourceClippingBlitTest.class.getName());
  89         final SourceClippingBlitTest test = new SourceClippingBlitTest();
  90         f.add(test);
  91         f.addWindowListener(new WindowAdapter() {
  92             public void windowActivated(WindowEvent e) {
  93                 if (!done) {
  94                     test.runTests();
  95                 }
  96             }
  97 
  98         });
  99         f.pack();
 100         f.setLocation(100, 100);
 101         f.setVisible(true);
 102         synchronized (lock) {
 103             while (!done) {
 104                 try {
 105                     lock.wait();
 106                 } catch (InterruptedException ex) {
 107                     ex.printStackTrace();
 108                 }
 109             }
 110         }
 111         if (!showErrors) {
 112             f.dispose();
 113         }
 114     }
 115 
 116     public Dimension getPreferredSize() {
 117         return new Dimension(TESTW, TESTH);
 118     }
 119 
 120     public void paint(Graphics g) {
 121         if (showErrors && done && grabbedBI != null) {
 122             g.drawImage(grabbedBI, 0, 0, null);
 123         }
 124     }
 125 
 126     public void runTests() {
 127         GraphicsConfiguration gc = getGraphicsConfiguration();
 128         for (Image srcIm :
 129             new Image[] {
 130                 getBufferedImage(gc, IMAGEW, IMAGEH,
 131                         BufferedImage.TYPE_INT_RGB, true),
 132                 getBufferedImage(gc, IMAGEW, IMAGEH,
 133                         BufferedImage.TYPE_INT_RGB, false),
 134                 // commented out due to 6593406
 135 //                getBMImage(gc, IMAGEW, IMAGEH),
 136 //                getBufferedImage(gc, IMAGEW, IMAGEH,
 137 //                        BufferedImage.TYPE_INT_ARGB, true),
 138 //                getBufferedImage(gc, IMAGEW, IMAGEH,
 139 //                        BufferedImage.TYPE_INT_ARGB, false),
 140                 getVImage(gc, IMAGEW, IMAGEH),
 141             })
 142         {
 143             System.out.println("Testing source: " + srcIm);
 144             // wiggle the source and dest rectangles
 145             try {
 146                 for (int locationVar = -10; locationVar < 20; locationVar += 10)
 147                 {
 148                     for (int sizeVar = -10; sizeVar < 20; sizeVar += 10) {
 149                         Rectangle srcRect = (Rectangle)IMAGE_BOUNDS.clone();
 150                         srcRect.translate(locationVar, locationVar);
 151                         srcRect.grow(sizeVar, sizeVar);
 152 
 153                         Rectangle dstRect =
 154                                 new Rectangle(sizeVar, sizeVar,
 155                                 srcRect.width, srcRect.height);
 156                         System.out.println("testing blit rect src: " + srcRect);
 157                         System.out.println("                  dst: " + dstRect);
 158                         render(getGraphics(), srcIm, srcRect, dstRect);
 159                         test(srcRect, dstRect);
 160                     }
 161                 }
 162                 System.out.println("Test passed.");
 163             } finally {
 164                 synchronized (lock) {
 165                     done = true;
 166                     lock.notifyAll();
 167                 }
 168             }
 169         }
 170     }
 171 
 172     public void render(Graphics g, Image image,
 173                        Rectangle srcRect, Rectangle dstRect)
 174     {
 175         int w = getWidth();
 176         int h = getHeight();
 177         g.setColor(Color.green);
 178         g.fillRect(0, 0, w, h);
 179 
 180         int bltWidth = srcRect.width;
 181         int bltHeight = srcRect.height;
 182         VolatileImage vi = null;
 183         if (image instanceof VolatileImage) {
 184             vi = (VolatileImage)image;
 185         }
 186         do {
 187             if (vi != null) {
 188                 GraphicsConfiguration gc = getGraphicsConfiguration();
 189                 if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
 190                     initImage(gc, vi);
 191                 }
 192             }
 193             g.drawImage(image,
 194                     dstRect.x, dstRect.y,
 195                     dstRect.x + bltWidth, dstRect.y + bltHeight,
 196                     srcRect.x, srcRect.y,
 197                     srcRect.x + bltWidth, srcRect.y + bltHeight,
 198                     Color.red,
 199                     null);
 200         } while (vi != null && vi.contentsLost());
 201     }
 202 
 203 
 204     public void test(Rectangle srcRect, Rectangle dstRect) {
 205         int w = getWidth();
 206         int h = getHeight();
 207         Toolkit.getDefaultToolkit().sync();
 208         try {
 209             Thread.sleep(2000);
 210         } catch (InterruptedException ex) {}
 211         Point p = getLocationOnScreen();
 212         grabbedBI = robot.createScreenCapture(new Rectangle(p.x, p.y, w, h));
 213 
 214         // calculate the destination rectangle
 215         Rectangle srcBounds = srcRect.intersection(IMAGE_BOUNDS);
 216         int trX = dstRect.x - srcRect.x;
 217         int trY = dstRect.y - srcRect.y;
 218         Rectangle newDstRect = (Rectangle)dstRect.clone();
 219         newDstRect.translate(-trX, -trY);
 220         Rectangle.intersect(newDstRect, srcBounds, newDstRect);
 221         newDstRect.translate(trX, trY);
 222         Rectangle.intersect(newDstRect, new Rectangle(0, 0, w, h), newDstRect);
 223 
 224         System.out.println("calculated dest rect:" + newDstRect);
 225 
 226         // we do implicit clipping of the destination surface
 227         // by only checking pixels within its bounds
 228         for (int y = 0; y < h; y++) {
 229             for (int x = 0; x < w; x++) {
 230                 int rgb = 0;
 231                 if (newDstRect.contains(x, y)) {
 232                     rgb = Color.red.getRGB();
 233                 } else {
 234                     rgb = Color.green.getRGB();
 235                 }
 236                 if (grabbedBI.getRGB(x, y) != rgb) {
 237                     String msg1 = "Test failed at x="+x+" y="+y;
 238                     System.out.println(msg1);
 239                     System.out.println(" expected: "+Integer.toHexString(rgb)+
 240                             " got:"+Integer.toHexString(grabbedBI.getRGB(x, y)));
 241                     throw new RuntimeException(msg1);
 242                 }
 243             }
 244         }
 245         System.out.println("subtest passed");
 246     }
 247 
 248     static VolatileImage dstImage;
 249     static void initImage(GraphicsConfiguration gc, Image image) {
 250         Graphics g = image.getGraphics();
 251         g.setColor(Color.RED);
 252         int w = image.getWidth(null);
 253         int h = image.getHeight(null);
 254         g.fillRect(0, 0, w, h);
 255         g.dispose();
 256 
 257         // need to 'accelerate' the image
 258         if (dstImage == null) {
 259             dstImage =
 260                 gc.createCompatibleVolatileImage(TESTW, TESTH,
 261                                                  Transparency.OPAQUE);
 262         }
 263         dstImage.validate(gc);
 264         g = dstImage.getGraphics();
 265         g.drawImage(image, 0, 0, null);
 266         g.drawImage(image, 0, 0, null);
 267         g.drawImage(image, 0, 0, null);
 268     }
 269 
 270     static VolatileImage getVImage(GraphicsConfiguration gc,
 271                                    int w, int h)
 272     {
 273         VolatileImage image =
 274             gc.createCompatibleVolatileImage(w, h, Transparency.OPAQUE);
 275         image.validate(gc);
 276         initImage(gc, image);
 277         return image;
 278     }
 279 
 280     static Image getBMImage(GraphicsConfiguration gc,
 281                             int w, int h)
 282     {
 283         Image image =
 284             gc.createCompatibleImage(w, h, Transparency.BITMASK);
 285         initImage(gc, image);
 286         return image;
 287     }
 288 
 289     static Image getBufferedImage(GraphicsConfiguration gc,
 290                                   int w, int h, int type, boolean acceleratable)
 291     {
 292         BufferedImage image = new BufferedImage(w, h, type);
 293         if (!acceleratable) {
 294             image.setAccelerationPriority(0.0f);
 295         }
 296         initImage(gc, image);
 297         return image;
 298     }
 299 }