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 
main(String[] args)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 
getPreferredSize()116     public Dimension getPreferredSize() {
117         return new Dimension(TESTW, TESTH);
118     }
119 
paint(Graphics g)120     public void paint(Graphics g) {
121         if (showErrors && done && grabbedBI != null) {
122             g.drawImage(grabbedBI, 0, 0, null);
123         }
124     }
125 
runTests()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 
render(Graphics g, Image image, Rectangle srcRect, Rectangle dstRect)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 
test(Rectangle srcRect, Rectangle dstRect)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;
initImage(GraphicsConfiguration gc, Image image)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 
getVImage(GraphicsConfiguration gc, int w, int h)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 
getBMImage(GraphicsConfiguration gc, int w, int h)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 
getBufferedImage(GraphicsConfiguration gc, int w, int h, int type, boolean acceleratable)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 }
300