1 /* 2 * Copyright (c) 2019, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package quality.util; 27 28 import javax.imageio.ImageIO; 29 import javax.swing.*; 30 import java.awt.*; 31 import java.awt.image.BufferedImage; 32 import java.awt.image.Raster; 33 import java.io.File; 34 import java.util.function.Consumer; 35 36 import static org.junit.Assert.assertNotNull; 37 import static org.junit.Assert.assertTrue; 38 39 public class RenderUtil { 40 final static int TOLERANCE = 40; 41 42 public static BufferedImage capture(int width, int height, Consumer<Graphics2D> painter) 43 throws Exception 44 { 45 JFrame[] f = new JFrame[1]; 46 Point[] p = new Point[1]; 47 double[] scale = new double[2]; 48 SwingUtilities.invokeAndWait(() -> { 49 f[0] = new JFrame(); 50 51 JComponent c = new MyComponent(painter); 52 53 f[0].add(c); 54 c.setSize(width + 10, height + 10); 55 f[0].setSize(width + 100, height + 100); // giving some space 56 // for frame border effects, 57 // e.g. rounded frame 58 c.setLocation(50, 50); 59 f[0].setVisible(true); 60 p[0]= c.getLocationOnScreen(); 61 scale[0] = f[0].getGraphicsConfiguration().getDefaultTransform().getScaleX(); 62 scale[1] = f[0].getGraphicsConfiguration().getDefaultTransform().getScaleY(); 63 }); 64 65 Rectangle screenRect; 66 Robot r = new Robot(); 67 while (!Color.black.equals(r.getPixelColor(p[0].x+1, p[0].y))) { 68 Thread.sleep(100); 69 } 70 screenRect = new Rectangle( 71 p[0].x + 5, 72 p[0].y + 5, 73 (int)((width - 20) * scale[0]), (int)((height - 30) * scale[1])); 74 75 BufferedImage result = r.createScreenCapture(screenRect); 76 SwingUtilities.invokeAndWait(f[0]::dispose); 77 return result; 78 } 79 80 private static class MyComponent extends JComponent { 81 private final Consumer<Graphics2D> painter; 82 83 private MyComponent(Consumer<Graphics2D> painter) { 84 this.painter = painter; 85 } 86 87 88 @Override 89 protected void paintComponent(Graphics g) { 90 Shape savedClip = g.getClip(); 91 g.translate(5, 5); 92 painter.accept((Graphics2D)g); 93 g.translate(-5, -5); 94 g.setClip(savedClip); 95 g.setColor(Color.black); 96 g.fillRect(0, 0, getWidth() + 10, 5); 97 g.fillRect(0, getHeight()-5, getWidth() + 10, 5); 98 g.fillRect(getWidth() - 10, -10, getWidth() + 5, getHeight() + 5); 99 g.fillRect(-5, -10, 10, getHeight() + 5); 100 } 101 } 102 103 @SuppressWarnings("SameParameterValue") 104 public static void checkImage(BufferedImage image, String path, String gfName) throws Exception { 105 106 String[] testDataVariant = { 107 "osx_hardware_rendering", "osx_software_rendering", 108 "osx_sierra_rendering", "osx_lowres_rendering", 109 "linux_rendering", "windows_rendering"}; 110 111 String testDataStr = System.getProperty("testdata"); 112 assertNotNull("testdata property is not set", testDataStr); 113 114 File testData = new File(testDataStr, "quality" + File.separator + path); 115 assertTrue("Test data dir does not exist", testData.exists()); 116 117 if (System.getProperty("gentestdata") == null) { 118 boolean failed = true; 119 StringBuilder failureReason = new StringBuilder(); 120 for (String variant : testDataVariant) { 121 File goldenFile = new File(testData, variant + File.separator + 122 gfName); 123 if (!goldenFile.exists()) continue; 124 125 BufferedImage goldenImage = ImageIO.read(goldenFile); 126 failed = true; 127 if (image.getWidth() != goldenImage.getWidth() || 128 image.getHeight() != image.getHeight()) 129 { 130 failureReason.append(variant).append(" : Golden image and result have different sizes\n"); 131 continue; 132 } 133 134 Raster gRaster = goldenImage.getData(); 135 Raster rRaster = image.getData(); 136 int[] gArr = new int[3]; 137 int[] rArr = new int[3]; 138 failed = false; 139 scan: 140 for (int i = 0; i < gRaster.getWidth(); i++) { 141 for (int j = 0; j < gRaster.getHeight(); j++) { 142 gRaster.getPixel(i, j, gArr); 143 rRaster.getPixel(i, j, rArr); 144 assertTrue(gArr.length == rArr.length); 145 for (int k = 0; k < gArr.length; k++) { 146 int diff = Math.abs(gArr[k] - rArr[k]); 147 if (diff > TOLERANCE) { 148 failureReason.append(variant).append(" : Different pixels found ("). 149 append("c[").append(k).append("]=").append(diff). 150 append(") at (").append(i).append(",").append(j).append(")"); 151 failed = true; 152 break scan; 153 } 154 } 155 } 156 } 157 158 if (!failed) break; 159 } 160 161 if (failed) throw new RuntimeException(failureReason.toString()); 162 } 163 else { 164 ImageIO.write(image, "png", new File(testData, gfName)); 165 } 166 } 167 }