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