|
| 1 | +/* |
| 2 | + * Copyright (c) 1999, 2024, 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 4198081 |
| 27 | + * @key headful |
| 28 | + * @summary Arabic characters should appear instead of boxes and be correctly shaped. |
| 29 | + * Hebrew characters should appear instead of boxes. |
| 30 | + * Test is made headful so there's no excuse for test systems not having the fonts. |
| 31 | + */ |
| 32 | + |
| 33 | +import java.awt.BorderLayout; |
| 34 | +import java.awt.Color; |
| 35 | +import java.awt.Dimension; |
| 36 | +import java.awt.EventQueue; |
| 37 | +import java.awt.Graphics; |
| 38 | +import java.awt.Graphics2D; |
| 39 | +import java.awt.GridLayout; |
| 40 | +import java.awt.Font; |
| 41 | +import java.awt.Frame; |
| 42 | +import java.awt.Panel; |
| 43 | +import java.awt.font.FontRenderContext; |
| 44 | +import java.awt.font.GlyphVector; |
| 45 | +import java.awt.geom.Rectangle2D; |
| 46 | + |
| 47 | +public class TestArabicHebrew extends Panel { |
| 48 | + |
| 49 | + static volatile Frame frame; |
| 50 | + static volatile Font font = new Font(Font.DIALOG, Font.PLAIN, 36); |
| 51 | + |
| 52 | + static void createUI() { |
| 53 | + frame = new Frame("Test Arabic/Hebrew"); |
| 54 | + frame.setLayout(new BorderLayout()); |
| 55 | + TestArabicHebrew panel = new TestArabicHebrew(); |
| 56 | + frame.add(panel, BorderLayout.CENTER); |
| 57 | + frame.pack(); |
| 58 | + frame.setVisible(true); |
| 59 | + } |
| 60 | + |
| 61 | + public static void main(String args[]) throws Exception { |
| 62 | + EventQueue.invokeAndWait(TestArabicHebrew::createUI); |
| 63 | + try { |
| 64 | + checkStrings(); |
| 65 | + } finally { |
| 66 | + if (frame != null && args.length == 0) { |
| 67 | + EventQueue.invokeAndWait(frame::dispose); |
| 68 | + } |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + static void checkString(String script, String str) { |
| 73 | + int index = font.canDisplayUpTo(str); |
| 74 | + if (index != -1) { |
| 75 | + throw new RuntimeException("Cannot display char " + index + " for " + script); |
| 76 | + } |
| 77 | + } |
| 78 | + |
| 79 | + static void checkStrings() { |
| 80 | + checkString("Arabic", arabic); |
| 81 | + checkString("Hebrew", hebrew); |
| 82 | + checkString("Latin-1 Supplement", latin1sup); |
| 83 | + } |
| 84 | + |
| 85 | + // Table of arabic unicode characters - minimal support level |
| 86 | + // Includes arabic chars from basic block up to 0652 and |
| 87 | + // corresponding shaped characters from the arabic |
| 88 | + // extended-B block from fe80 to fefc (does include lam-alef |
| 89 | + // ligatures). |
| 90 | + // Does not include arabic-indic digits nor "arabic extended" |
| 91 | + // range. |
| 92 | + |
| 93 | + static final String arabic = |
| 94 | + "\u060c\u061b\u061f\u0621\u0622\u0623\u0624\u0625\u0626\u0627" |
| 95 | + + "\u0628\u0629\u062a\u062b\u062c\u062d\u062e\u062f\u0630\u0631" |
| 96 | + + "\u0632\u0633\u0634\u0635\u0636\u0637\u0638\u0639\u063a\u0640" |
| 97 | + + "\u0641\u0642\u0643\u0644\u0645\u0646\u0647\u0648\u0649\u064a" |
| 98 | + + "\u064b\u064c\u064d\u064e\u064f\u0650\u0651\u0652\ufe80\ufe81" |
| 99 | + + "\ufe82\ufe83\ufe84\ufe85\ufe86\ufe87\ufe88\ufe89\ufe8a\ufe8b" |
| 100 | + + "\ufe8c\ufe8d\ufe8e\ufe8f\ufe90\ufe91\ufe92\ufe93\ufe94\ufe95" |
| 101 | + + "\ufe96\ufe97\ufe98\ufe99\ufe9a\ufe9b\ufe9c\ufe9d\ufe9e\ufe9f" |
| 102 | + + "\ufea0\ufea1\ufea2\ufea3\ufea4\ufea5\ufea6\ufea7\ufea8\ufea9" |
| 103 | + + "\ufeaa\ufeab\ufeac\ufead\ufeae\ufeaf\ufeb0\ufeb1\ufeb2\ufeb3" |
| 104 | + + "\ufeb4\ufeb5\ufeb6\ufeb7\ufeb8\ufeb9\ufeba\ufebb\ufebc\ufebd" |
| 105 | + + "\ufebe\ufebf\ufec0\ufec1\ufec2\ufec3\ufec4\ufec5\ufec6\ufec7" |
| 106 | + + "\ufec8\ufec9\ufeca\ufecb\ufecc\ufecd\ufece\ufecf\ufed0\ufed1" |
| 107 | + + "\ufed2\ufed3\ufed4\ufed5\ufed6\ufed7\ufed8\ufed9\ufeda\ufedb" |
| 108 | + + "\ufedc\ufedd\ufede\ufedf\ufee0\ufee1\ufee2\ufee3\ufee4\ufee5" |
| 109 | + + "\ufee6\ufee7\ufee8\ufee9\ufeea\ufeeb\ufeec\ufeed\ufeee\ufeef" |
| 110 | + + "\ufef0\ufef1\ufef2\ufef3\ufef4\ufef5\ufef6\ufef7\ufef8\ufef9" |
| 111 | + + "\ufefa\ufefb\ufefc"; |
| 112 | + |
| 113 | + // hebrew table includes all characters in hebrew block |
| 114 | + |
| 115 | + static final String hebrew = |
| 116 | + "\u0591\u0592\u0593\u0594\u0595\u0596\u0597\u0598\u0599\u059a" |
| 117 | + + "\u059b\u059c\u059d\u059e\u059f\u05a0\u05a1\u05a3\u05a4\u05a5" |
| 118 | + + "\u05a6\u05a7\u05a8\u05a9\u05aa\u05ab\u05ac\u05ad\u05ae\u05af" |
| 119 | + + "\u05b0\u05b1\u05b2\u05b3\u05b4\u05b5\u05b6\u05b7\u05b8\u05b9" |
| 120 | + + "\u05bb\u05bc\u05bd\u05be\u05bf\u05c0\u05c1\u05c2\u05c3\u05c4" |
| 121 | + + "\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9" |
| 122 | + + "\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\u05e3" |
| 123 | + + "\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea\u05f0\u05f1\u05f2" |
| 124 | + + "\u05f3\u05f4"; |
| 125 | + |
| 126 | + // latin 1 supplement table includes all non-control characters |
| 127 | + // in this range. Included because of comment in code that claims |
| 128 | + // some problems displaying this range with some SJIS fonts. |
| 129 | + |
| 130 | + static final String latin1sup = |
| 131 | + "\u00a0\u00a1\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7" |
| 132 | + + "\u00a8\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1" |
| 133 | + + "\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00ba\u00bb" |
| 134 | + + "\u00bc\u00bd\u00be\u00bf\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5" |
| 135 | + + "\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf" |
| 136 | + + "\u00d0\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u00d7\u00d8\u00d9" |
| 137 | + + "\u00da\u00db\u00dc\u00dd\u00de\u00df\u00e0\u00e1\u00e2\u00e3" |
| 138 | + + "\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed" |
| 139 | + + "\u00ee\u00ef\u00f0\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u00f7" |
| 140 | + + "\u00f8\u00f9\u00fa\u00fb\u00fc\u00fd\u00fe\u00ff"; |
| 141 | + |
| 142 | + public TestArabicHebrew() { |
| 143 | + setLayout(new GridLayout(3, 1)); |
| 144 | + |
| 145 | + FontRenderContext frc = new FontRenderContext(null, false, false); |
| 146 | + add(new SubGlyphPanel("Arabic", arabic, font, frc)); |
| 147 | + add(new SubGlyphPanel("Hebrew", hebrew, font, frc)); |
| 148 | + add(new SubGlyphPanel("Latin-1 Supplement", latin1sup, font, frc)); |
| 149 | + } |
| 150 | + |
| 151 | + static class SubGlyphPanel extends Panel { |
| 152 | + String title; |
| 153 | + Dimension extent; |
| 154 | + GlyphVector[] vectors; |
| 155 | + |
| 156 | + static final int kGlyphsPerLine = 20; |
| 157 | + |
| 158 | + SubGlyphPanel(String title, String chars, Font font, FontRenderContext frc) { |
| 159 | + |
| 160 | + this.title = title; |
| 161 | + setBackground(Color.white); |
| 162 | + |
| 163 | + double width = 0; |
| 164 | + double height = 0; |
| 165 | + |
| 166 | + int max = chars.length(); |
| 167 | + vectors = new GlyphVector[(max + kGlyphsPerLine - 1) / kGlyphsPerLine]; |
| 168 | + for (int i = 0; i < vectors.length; i++) { |
| 169 | + int start = i * 20; |
| 170 | + int limit = Math.min(max, (i + 1) * kGlyphsPerLine); |
| 171 | + String substr = ""; |
| 172 | + for (int j = start; j < limit; ++j) { |
| 173 | + substr = substr.concat(chars.charAt(j) + " "); |
| 174 | + } |
| 175 | + GlyphVector gv = font.createGlyphVector(frc, substr); |
| 176 | + vectors[i] = gv; |
| 177 | + Rectangle2D bounds = gv.getLogicalBounds(); |
| 178 | + |
| 179 | + width = Math.max(width, bounds.getWidth()); |
| 180 | + height += bounds.getHeight(); |
| 181 | + } |
| 182 | + |
| 183 | + extent = new Dimension((int)(width + 1), (int)(height + 1 + 30)); // room for title |
| 184 | + |
| 185 | + setSize(getPreferredSize()); |
| 186 | + } |
| 187 | + |
| 188 | + public Dimension getPreferredSize() { |
| 189 | + return new Dimension(extent); |
| 190 | + } |
| 191 | + |
| 192 | + public Dimension getMinimumSize() { |
| 193 | + return getPreferredSize(); |
| 194 | + } |
| 195 | + |
| 196 | + public Dimension getMaximumSize() { |
| 197 | + return getPreferredSize(); |
| 198 | + } |
| 199 | + |
| 200 | + public void paint(Graphics g) { |
| 201 | + Graphics2D g2d = (Graphics2D)g; |
| 202 | + |
| 203 | + g.drawString(title, 10, 20); |
| 204 | + |
| 205 | + float x = 10; |
| 206 | + float y = 30; |
| 207 | + for (int i = 0; i < vectors.length; ++i) { |
| 208 | + GlyphVector gv = vectors[i]; |
| 209 | + Rectangle2D bounds = gv.getLogicalBounds(); |
| 210 | + g2d.drawGlyphVector(gv, x, (float)(y - bounds.getY())); |
| 211 | + y += bounds.getHeight(); |
| 212 | + } |
| 213 | + } |
| 214 | + } |
| 215 | +} |
0 commit comments