1 /* 2 * Copyright (c) 2009, 2017, 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 * @key headful 27 * @bug 4337267 28 * @summary test that numeric shaping works in Swing components 29 * @author Sergey Groznyh 30 * @run main bug4337267 31 */ 32 33 import java.awt.Component; 34 import java.awt.Dimension; 35 import java.awt.Graphics; 36 import java.awt.font.NumericShaper; 37 import java.awt.font.TextAttribute; 38 import java.awt.image.BufferedImage; 39 import javax.swing.BoxLayout; 40 import javax.swing.JComponent; 41 import javax.swing.JFrame; 42 import javax.swing.JLabel; 43 import javax.swing.JPanel; 44 import javax.swing.JTextArea; 45 import javax.swing.SwingUtilities; 46 47 public class bug4337267 { 48 TestJPanel p1, p2; 49 TestBufferedImage i1, i2; 50 JComponent[] printq; 51 JFrame window; 52 static boolean testFailed = false; 53 static boolean done = false; 54 55 String shaped = 56 "000 (E) 111 (A) \u0641\u0642\u0643 \u0662\u0662\u0662 (E) 333"; 57 String text = "000 (E) 111 (A) \u0641\u0642\u0643 222 (E) 333"; 58 59 void run() { 60 initUI(); 61 testTextComponent(); 62 testNonTextComponentHTML(); 63 testNonTextComponentPlain(); 64 65 doneTask(); 66 } 67 68 void initUI() { 69 window = new JFrame("bug4337267"); 70 window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 71 window.setSize(800, 600); 72 Component content = createContentPane(); 73 window.add(content); 74 window.setVisible(true); 75 } 76 77 Runnable printComponents = new Runnable() { 78 public void run() { 79 printComponent(printq[0], i1); 80 printComponent(printq[1], i2); 81 } 82 }; 83 84 Runnable compareRasters = new Runnable() { 85 public void run() { 86 assertEquals(p1.image, p2.image); 87 assertEquals(i1, i2); 88 } 89 }; 90 91 void doneTask() { 92 final Object monitor = this; 93 SwingUtilities.invokeLater(new Runnable() { 94 public void run() { 95 done = true; 96 synchronized(monitor) { 97 monitor.notify(); 98 } 99 } 100 }); 101 } 102 103 104 void fail(String message) { 105 testFailed = true; 106 throw new RuntimeException(message); 107 } 108 109 void assertEquals(Object o1, Object o2) { 110 if ((o1 == null) && (o2 != null)) { 111 fail("Expected null, got " + o2); 112 } else if ((o1 != null) && (o2 == null)) { 113 fail("Expected " + o1 + ", got null"); 114 } else if (!o1.equals(o2)) { 115 fail("Expected " + o1 + ", got " + o2); 116 } 117 } 118 119 void testTextComponent() { 120 System.out.println("testTextComponent:"); 121 JTextArea area1 = new JTextArea(); 122 injectComponent(p1, area1, false); 123 area1.setText(shaped); 124 JTextArea area2 = new JTextArea(); 125 injectComponent(p2, area2, true); 126 area2.setText(text); 127 window.repaint(); 128 printq = new JComponent[] { area1, area2 }; 129 SwingUtilities.invokeLater(printComponents); 130 SwingUtilities.invokeLater(compareRasters); 131 } 132 133 void testNonTextComponentHTML() { 134 System.out.println("testNonTextComponentHTML:"); 135 JLabel label1 = new JLabel(); 136 injectComponent(p1, label1, false); 137 label1.setText("<html>" + shaped); 138 JLabel label2 = new JLabel(); 139 injectComponent(p2, label2, true); 140 label2.setText("<html>" + text); 141 window.repaint(); 142 printq = new JComponent[] { label1, label2 }; 143 SwingUtilities.invokeLater(printComponents); 144 SwingUtilities.invokeLater(compareRasters); 145 } 146 147 void testNonTextComponentPlain() { 148 System.out.println("testNonTextComponentHTML:"); 149 JLabel label1 = new JLabel(); 150 injectComponent(p1, label1, false); 151 label1.setText(shaped); 152 JLabel label2 = new JLabel(); 153 injectComponent(p2, label2, true); 154 label2.setText(text); 155 window.repaint(); 156 printq = new JComponent[] { label1, label2 }; 157 SwingUtilities.invokeLater(printComponents); 158 SwingUtilities.invokeLater(compareRasters); 159 } 160 161 void setShaping(JComponent c) { 162 c.putClientProperty(TextAttribute.NUMERIC_SHAPING, 163 NumericShaper.getContextualShaper(NumericShaper.ARABIC)); 164 } 165 166 void injectComponent(JComponent p, JComponent c, boolean shape) { 167 if (shape) { 168 setShaping(c); 169 } 170 p.removeAll(); 171 p.add(c); 172 } 173 174 void printComponent(JComponent c, TestBufferedImage i) { 175 Graphics g = i.getGraphics(); 176 g.setColor(c.getBackground()); 177 g.fillRect(0, 0, i.getWidth(), i.getHeight()); 178 c.print(g); 179 } 180 181 Component createContentPane() { 182 Dimension size = new Dimension(500, 100); 183 i1 = new TestBufferedImage(size.width, size.height, 184 BufferedImage.TYPE_INT_ARGB); 185 i2 = new TestBufferedImage(size.width, size.height, 186 BufferedImage.TYPE_INT_ARGB); 187 p1 = new TestJPanel(); 188 p1.setPreferredSize(size); 189 p2 = new TestJPanel(); 190 p2.setPreferredSize(size); 191 JPanel panel = new JPanel(); 192 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 193 panel.add(p1); 194 panel.add(p2); 195 196 return panel; 197 } 198 199 static class TestBufferedImage extends BufferedImage { 200 int MAX_GLITCHES = 0; 201 202 TestBufferedImage(int width, int height, int imageType) { 203 super(width, height, imageType); 204 } 205 206 @Override 207 public boolean equals(Object other) { 208 if (! (other instanceof TestBufferedImage)) { 209 return false; 210 } 211 TestBufferedImage image2 = (TestBufferedImage) other; 212 int width = getWidth(); 213 int height = getHeight(); 214 if ((image2.getWidth() != width) || (image2.getHeight() != height)) { 215 return false; 216 } 217 int glitches = 0; 218 for (int x = 0; x < width; x++) { 219 for (int y = 0; y < height; y++) { 220 int rgb1 = getRGB(x, y); 221 int rgb2 = image2.getRGB(x, y); 222 if (rgb1 != rgb2) { 223 //System.out.println(x+" "+y+" "+rgb1+" "+rgb2); 224 glitches++; 225 } 226 } 227 } 228 return glitches <= MAX_GLITCHES; 229 } 230 } 231 232 static class TestJPanel extends JPanel { 233 TestBufferedImage image = createImage(new Dimension(1, 1)); 234 235 TestBufferedImage createImage(Dimension d) { 236 return new TestBufferedImage(d.width, d.height, 237 BufferedImage.TYPE_INT_ARGB); 238 } 239 240 public void setPreferredSize(Dimension size) { 241 super.setPreferredSize(size); 242 image = createImage(size); 243 } 244 245 public void paint(Graphics g) { 246 Graphics g0 = image.getGraphics(); 247 super.paint(g0); 248 g.drawImage(image, 0, 0, this); 249 } 250 } 251 252 253 254 public static void main(String[] args) throws Throwable { 255 final bug4337267 test = new bug4337267(); 256 SwingUtilities.invokeLater(new Runnable() { 257 public void run() { 258 test.run(); 259 } 260 }); 261 262 synchronized(test) { 263 while (!done) { 264 try { 265 test.wait(); 266 } catch (InterruptedException ex) { 267 // do nothing 268 } 269 } 270 } 271 272 if (testFailed) { 273 throw new RuntimeException("FAIL"); 274 } 275 276 System.out.println("OK"); 277 } 278 }