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