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