6345095: regression test EmptyClipRenderingTest fails
authorserb
Wed, 03 Dec 2014 15:43:25 +0300
changeset 28083 91a04df877cc
parent 28082 25a509d90496
child 28084 441853c190f4
6345095: regression test EmptyClipRenderingTest fails Reviewed-by: azvegint, alexsch
jdk/test/sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java	Wed Dec 03 15:43:25 2014 +0300
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.AWTException;
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.Toolkit;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.image.BufferedImage;
+import java.awt.image.VolatileImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import javax.imageio.ImageIO;
+import sun.awt.ConstrainableGraphics;
+
+/**
+ * @test
+ * @bug 6335200 6419610
+ * @summary Tests that we don't render anything if specific empty clip is set
+ * @author Dmitri.Trembovetski@Sun.COM: area=Graphics
+ * @run main EmptyClipRenderingTest
+ * @run main/othervm -Dsun.java2d.noddraw=true EmptyClipRenderingTest
+ * @run main/othervm -Dsun.java2d.pmoffscreen=true EmptyClipRenderingTest
+ * @run main/othervm -Dsun.java2d.opengl=true EmptyClipRenderingTest
+ */
+public class EmptyClipRenderingTest {
+    static final int IMG_W = 400;
+    static final int IMG_H = 400;
+
+    // generated rectangles
+    static HashSet<Rectangle> rects;
+
+    volatile boolean isActivated = false;
+    volatile boolean isPainted;
+    private static boolean showErrors = false;
+
+    public EmptyClipRenderingTest() {
+        // initialize clip/render region rectangles
+        initClips();
+
+        HashSet<RuntimeException> errors = new HashSet<RuntimeException>();
+
+        BufferedImage screenResult = testOnscreen();
+        try {
+            testResult(screenResult, "Screen");
+        } catch (RuntimeException e) {
+            errors.add(e);
+        }
+
+        BufferedImage destBI =
+            new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_RGB);
+        runTest((Graphics2D)destBI.getGraphics());
+        try {
+            testResult(destBI, "BufferedImage");
+        } catch (RuntimeException e) {
+            errors.add(e);
+        }
+
+        GraphicsConfiguration gc =
+                GraphicsEnvironment.getLocalGraphicsEnvironment().
+                getDefaultScreenDevice().getDefaultConfiguration();
+        VolatileImage destVI = gc.createCompatibleVolatileImage(IMG_W, IMG_H);
+        destVI.validate(gc);
+        runTest((Graphics2D)destVI.getGraphics());
+        try {
+            testResult(destVI.getSnapshot(), "VolatileImage");
+        } catch (RuntimeException e) {
+            errors.add(e);
+        }
+
+        if (errors.isEmpty()) {
+            System.err.println("Test PASSED.");
+        } else {
+            for (RuntimeException re : errors) {
+                re.printStackTrace();
+            }
+            if (showErrors) {
+                System.err.println("Test FAILED: "+ errors.size() +
+                                   " subtest failures.");
+            } else {
+                throw new RuntimeException("Test FAILED: "+ errors.size() +
+                                           " subtest failures.");
+            }
+        }
+    }
+
+    /**
+     * Recursively adds 4 new rectangles: two vertical and two horizontal
+     * based on the passed rectangle area. The area is then shrunk and the
+     * process repeated for smaller area.
+     */
+    private static void add4Rects(HashSet<Rectangle> rects, Rectangle area) {
+        if (area.width < 10 || area.height < 10) {
+            rects.add(area);
+            return;
+        }
+        // two vertical rects
+        rects.add(new Rectangle(area.x, area.y, 5, area.height));
+        rects.add(new Rectangle(area.x + area.width - 5, area.y, 5, area.height));
+        // two horizontal rects
+        int width = area.width - 2*(5 + 1);
+        rects.add(new Rectangle(area.x+6, area.y, width, 5));
+        rects.add(new Rectangle(area.x+6, area.y + area.height - 5, width, 5));
+        // reduce the area and repeat
+        area.grow(-6, -6);
+        add4Rects(rects, area);
+    }
+
+    /**
+     * Generate a bunch of non-intersecting rectangles
+     */
+    private static void initClips() {
+        rects = new HashSet<Rectangle>();
+        add4Rects(rects, new Rectangle(0, 0, IMG_W, IMG_H));
+        System.err.println("Total number of test rects: " + rects.size());
+    }
+
+    /**
+     * Render the pattern to the screen, capture the output with robot and
+     * return it.
+     */
+    private BufferedImage testOnscreen() throws HeadlessException {
+        final Canvas destComponent;
+        final Object lock = new Object();
+        Frame f = new Frame("Test Frame");
+        f.setUndecorated(true);
+        f.add(destComponent = new Canvas() {
+            public void paint(Graphics g) {
+                isPainted = true;
+            }
+            public Dimension getPreferredSize() {
+                return new Dimension(IMG_W, IMG_H);
+            }
+        });
+        f.addWindowListener(new WindowAdapter() {
+            public void windowActivated(WindowEvent e) {
+                if (!isActivated) {
+                    synchronized (lock) {
+                        isActivated = true;
+                        lock.notify();
+                    }
+                }
+            }
+        });
+        f.pack();
+        f.setLocationRelativeTo(null);
+        f.setVisible(true);
+        synchronized(lock) {
+            while (!isActivated) {
+                try {
+                    lock.wait(100);
+                } catch (InterruptedException ex) {
+                    ex.printStackTrace();
+                }
+            }
+        }
+        Robot r;
+        try {
+            r = new Robot();
+        } catch (AWTException ex) {
+            throw new RuntimeException("Can't create Robot");
+        }
+        BufferedImage bi;
+        int attempt = 0;
+        do {
+            if (++attempt > 10) {
+                throw new RuntimeException("Too many attempts: " + attempt);
+            }
+            isPainted = false;
+            runTest((Graphics2D) destComponent.getGraphics());
+            r.waitForIdle();
+            Toolkit.getDefaultToolkit().sync();
+            bi = r.createScreenCapture(
+                    new Rectangle(destComponent.getLocationOnScreen().x,
+                            destComponent.getLocationOnScreen().y,
+                            destComponent.getWidth(),
+                            destComponent.getHeight()));
+        } while (isPainted);
+        f.setVisible(false);
+        f.dispose();
+        return bi;
+    }
+
+    /**
+     * Run the test: cycle through all the rectangles, use one as clip and
+     * another as the area to render to.
+     * Set the clip in the same way Swing does it when repainting:
+     * first constrain the graphics to the damaged area, and repaint everything
+     */
+    void runTest(Graphics2D destGraphics) {
+        destGraphics.setColor(Color.black);
+        destGraphics.fillRect(0, 0, IMG_W, IMG_H);
+
+        destGraphics.setColor(Color.red);
+        for (Rectangle clip : rects) {
+            Graphics2D g2d = (Graphics2D)destGraphics.create();
+            g2d.setColor(Color.red);
+            // mimic what swing does in BufferStrategyPaintManager
+            if (g2d instanceof ConstrainableGraphics) {
+                ((ConstrainableGraphics)g2d).constrain(clip.x, clip.y,
+                                                       clip.width, clip.height);
+            }
+            g2d.setClip(clip);
+
+            for (Rectangle renderRegion : rects) {
+                if (renderRegion != clip) {
+                    // from CellRendererPane's paintComponent
+                    Graphics2D rG = (Graphics2D)
+                        g2d.create(renderRegion.x, renderRegion.y,
+                                   renderRegion.width, renderRegion.height);
+                    rG.fillRect(0,0, renderRegion.width, renderRegion.height);
+                }
+            }
+        }
+    }
+
+    void testResult(final BufferedImage bi, final String desc) {
+        for (int y = 0; y < bi.getHeight(); y++) {
+            for (int x = 0; x < bi.getWidth(); x++) {
+                if (bi.getRGB(x, y) != Color.black.getRGB()) {
+                    if (showErrors) {
+                        Frame f = new Frame("Error: " + desc);
+                        f.add(new Component() {
+                            public void paint(Graphics g) {
+                                g.drawImage(bi, 0, 0, null);
+                            }
+                            public Dimension getPreferredSize() {
+                                return new Dimension(bi.getWidth(),
+                                                     bi.getHeight());
+                            }
+                        });
+                        f.pack();
+                        f.setVisible(true);
+                    }
+                    try {
+                        String fileName =
+                            "EmptyClipRenderingTest_"+desc+"_res.png";
+                        System.out.println("Writing resulting image: "+fileName);
+                        ImageIO.write(bi, "png", new File(fileName));
+                    } catch (IOException ex) {
+                        ex.printStackTrace();
+                    }
+                    throw new RuntimeException("Dest: "+desc+
+                        " was rendered to at x="+
+                        x + " y=" + y +
+                        " pixel="+Integer.toHexString(bi.getRGB(x,y)));
+                }
+            }
+        }
+    }
+
+    public static void main(String argv[]) {
+        for (String arg : argv) {
+            if (arg.equals("-show")) {
+                showErrors = true;
+            } else {
+                usage("Incorrect argument:" + arg);
+            }
+        }
+        new EmptyClipRenderingTest();
+    }
+
+    private static void usage(String string) {
+        System.out.println(string);
+        System.out.println("Usage: EmptyClipRenderingTest [-show]");
+    }
+}