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