--- /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]");
+ }
+}