Path: blob/master/test/jdk/sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java
41152 views
/*1* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.awt.AWTException;24import java.awt.Canvas;25import java.awt.Color;26import java.awt.Component;27import java.awt.Dimension;28import java.awt.Frame;29import java.awt.Graphics;30import java.awt.Graphics2D;31import java.awt.GraphicsConfiguration;32import java.awt.GraphicsEnvironment;33import java.awt.HeadlessException;34import java.awt.Rectangle;35import java.awt.Robot;36import java.awt.Toolkit;37import java.awt.event.WindowAdapter;38import java.awt.event.WindowEvent;39import java.awt.image.BufferedImage;40import java.awt.image.VolatileImage;41import java.io.File;42import java.io.IOException;43import java.util.HashSet;44import javax.imageio.ImageIO;45import sun.awt.ConstrainableGraphics;4647/**48* @test49* @key headful50* @bug 6335200 6419610 819861351* @summary Tests that we don't render anything if specific empty clip is set52* @author [email protected]: area=Graphics53* @modules java.desktop/sun.awt54* @run main EmptyClipRenderingTest55* @run main/othervm -Dsun.java2d.noddraw=true EmptyClipRenderingTest56* @run main/othervm -Dsun.java2d.pmoffscreen=true EmptyClipRenderingTest57*/58public class EmptyClipRenderingTest {59static final int IMG_W = 400;60static final int IMG_H = 400;6162// generated rectangles63static HashSet<Rectangle> rects;6465volatile boolean isActivated = false;66volatile boolean isPainted;67private static boolean showErrors = false;6869public EmptyClipRenderingTest() {70// initialize clip/render region rectangles71initClips();7273HashSet<RuntimeException> errors = new HashSet<RuntimeException>();7475BufferedImage screenResult = testOnscreen();76try {77testResult(screenResult, "Screen");78} catch (RuntimeException e) {79errors.add(e);80}8182BufferedImage destBI =83new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_RGB);84runTest((Graphics2D)destBI.getGraphics());85try {86testResult(destBI, "BufferedImage");87} catch (RuntimeException e) {88errors.add(e);89}9091GraphicsConfiguration gc =92GraphicsEnvironment.getLocalGraphicsEnvironment().93getDefaultScreenDevice().getDefaultConfiguration();94VolatileImage destVI = gc.createCompatibleVolatileImage(IMG_W, IMG_H);95destVI.validate(gc);96runTest((Graphics2D)destVI.getGraphics());97try {98testResult(destVI.getSnapshot(), "VolatileImage");99} catch (RuntimeException e) {100errors.add(e);101}102103if (errors.isEmpty()) {104System.err.println("Test PASSED.");105} else {106for (RuntimeException re : errors) {107re.printStackTrace();108}109if (showErrors) {110System.err.println("Test FAILED: "+ errors.size() +111" subtest failures.");112} else {113throw new RuntimeException("Test FAILED: "+ errors.size() +114" subtest failures.");115}116}117}118119/**120* Recursively adds 4 new rectangles: two vertical and two horizontal121* based on the passed rectangle area. The area is then shrunk and the122* process repeated for smaller area.123*/124private static void add4Rects(HashSet<Rectangle> rects, Rectangle area) {125if (area.width < 10 || area.height < 10) {126rects.add(area);127return;128}129// two vertical rects130rects.add(new Rectangle(area.x, area.y, 5, area.height));131rects.add(new Rectangle(area.x + area.width - 5, area.y, 5, area.height));132// two horizontal rects133int width = area.width - 2*(5 + 1);134rects.add(new Rectangle(area.x+6, area.y, width, 5));135rects.add(new Rectangle(area.x+6, area.y + area.height - 5, width, 5));136// reduce the area and repeat137area.grow(-6, -6);138add4Rects(rects, area);139}140141/**142* Generate a bunch of non-intersecting rectangles143*/144private static void initClips() {145rects = new HashSet<Rectangle>();146add4Rects(rects, new Rectangle(0, 0, IMG_W, IMG_H));147System.err.println("Total number of test rects: " + rects.size());148}149150/**151* Render the pattern to the screen, capture the output with robot and152* return it.153*/154private BufferedImage testOnscreen() throws HeadlessException {155final Canvas destComponent;156final Object lock = new Object();157Frame f = new Frame("Test Frame");158f.setUndecorated(true);159f.add(destComponent = new Canvas() {160public void paint(Graphics g) {161isPainted = true;162}163public Dimension getPreferredSize() {164return new Dimension(IMG_W, IMG_H);165}166});167f.addWindowListener(new WindowAdapter() {168public void windowActivated(WindowEvent e) {169if (!isActivated) {170synchronized (lock) {171isActivated = true;172lock.notify();173}174}175}176});177f.pack();178f.setLocationRelativeTo(null);179f.setVisible(true);180synchronized(lock) {181while (!isActivated) {182try {183lock.wait(100);184} catch (InterruptedException ex) {185ex.printStackTrace();186}187}188}189Robot r;190try {191r = new Robot();192} catch (AWTException ex) {193throw new RuntimeException("Can't create Robot");194}195BufferedImage bi;196int attempt = 0;197do {198if (++attempt > 10) {199throw new RuntimeException("Too many attempts: " + attempt);200}201isPainted = false;202runTest((Graphics2D) destComponent.getGraphics());203r.waitForIdle();204Toolkit.getDefaultToolkit().sync();205bi = r.createScreenCapture(206new Rectangle(destComponent.getLocationOnScreen().x,207destComponent.getLocationOnScreen().y,208destComponent.getWidth(),209destComponent.getHeight()));210} while (isPainted);211f.setVisible(false);212f.dispose();213return bi;214}215216/**217* Run the test: cycle through all the rectangles, use one as clip and218* another as the area to render to.219* Set the clip in the same way Swing does it when repainting:220* first constrain the graphics to the damaged area, and repaint everything221*/222void runTest(Graphics2D destGraphics) {223destGraphics.setColor(Color.black);224destGraphics.fillRect(0, 0, IMG_W, IMG_H);225226destGraphics.setColor(Color.red);227for (Rectangle clip : rects) {228Graphics2D g2d = (Graphics2D)destGraphics.create();229g2d.setColor(Color.red);230// mimic what swing does in BufferStrategyPaintManager231if (g2d instanceof ConstrainableGraphics) {232((ConstrainableGraphics)g2d).constrain(clip.x, clip.y,233clip.width, clip.height);234}235g2d.setClip(clip);236237for (Rectangle renderRegion : rects) {238if (renderRegion != clip) {239// from CellRendererPane's paintComponent240Graphics2D rG = (Graphics2D)241g2d.create(renderRegion.x, renderRegion.y,242renderRegion.width, renderRegion.height);243rG.fillRect(0,0, renderRegion.width, renderRegion.height);244}245}246}247}248249void testResult(final BufferedImage bi, final String desc) {250for (int y = 0; y < bi.getHeight(); y++) {251for (int x = 0; x < bi.getWidth(); x++) {252if (bi.getRGB(x, y) != Color.black.getRGB()) {253if (showErrors) {254Frame f = new Frame("Error: " + desc);255f.add(new Component() {256public void paint(Graphics g) {257g.drawImage(bi, 0, 0, null);258}259public Dimension getPreferredSize() {260return new Dimension(bi.getWidth(),261bi.getHeight());262}263});264f.pack();265f.setVisible(true);266}267try {268String fileName =269"EmptyClipRenderingTest_"+desc+"_res.png";270System.out.println("Writing resulting image: "+fileName);271ImageIO.write(bi, "png", new File(fileName));272} catch (IOException ex) {273ex.printStackTrace();274}275throw new RuntimeException("Dest: "+desc+276" was rendered to at x="+277x + " y=" + y +278" pixel="+Integer.toHexString(bi.getRGB(x,y)));279}280}281}282}283284public static void main(String argv[]) {285for (String arg : argv) {286if (arg.equals("-show")) {287showErrors = true;288} else {289usage("Incorrect argument:" + arg);290}291}292new EmptyClipRenderingTest();293}294295private static void usage(String string) {296System.out.println(string);297System.out.println("Usage: EmptyClipRenderingTest [-show]");298}299}300301302