1 /* @test 2 @bug 4328745 5090704 3 @summary exercise getLayoutFlags, getGlyphCharIndex, getGlyphCharIndices 4 */ 5 6 import java.awt.*; 7 import java.awt.event.*; 8 import java.awt.font.*; 9 import java.awt.geom.*; 10 11 public class TestLayoutFlags { 12 13 static public void main(String[] args) { 14 new TestLayoutFlags().runTest(); 15 } 16 17 void runTest() { 18 19 Font font = new Font("Lucida Sans", Font.PLAIN, 24); 20 21 String latin1 = "This is a latin1 string"; // none 22 String hebrew = "\u05d0\u05d1\u05d2\u05d3"; // rtl 23 String arabic = "\u0646\u0644\u0622\u0646"; // rtl + mc/g 24 String hindi = "\u0939\u093f\u0923\u094d\u0921\u0940"; // ltr + reorder 25 // String tamil = "\u0b9c\u0bcb"; // ltr + mg/c + split 26 27 FontRenderContext frc = new FontRenderContext(null, true, true); 28 29 // get glyph char indices needs to initializes layoutFlags before use (5090704) 30 { 31 GlyphVector gv = font.createGlyphVector(frc, "abcde"); 32 int ix = gv.getGlyphCharIndex(0); 33 if (ix != 0) { 34 throw new Error("glyph 0 incorrectly mapped to char " + ix); 35 } 36 int[] ixs = gv.getGlyphCharIndices(0, gv.getNumGlyphs(), null); 37 for (int i = 0; i < ixs.length; ++i) { 38 if (ixs[i] != i) { 39 throw new Error("glyph " + i + " incorrectly mapped to char " + ixs[i]); 40 } 41 } 42 } 43 44 GlyphVector latinGV = makeGlyphVector("Lucida Sans", frc, latin1, false, 1 /* ScriptRun.LATIN */); 45 GlyphVector hebrewGV = makeGlyphVector("Lucida Sans", frc, hebrew, true, 5 /* ScriptRun.HEBREW */); 46 GlyphVector arabicGV = makeGlyphVector("Lucida Sans", frc, arabic, true, 6 /* ScriptRun.ARABIC */); 47 GlyphVector hindiGV = makeGlyphVector("Lucida Sans", frc, hindi, false, 7 /* ScriptRun.DEVANAGARI */); 48 // GlyphVector tamilGV = makeGlyphVector("Devanagari MT for IBM", frc, tamil, false, 12 /* ScriptRun.TAMIL */); 49 50 GlyphVector latinPos = font.createGlyphVector(frc, latin1); 51 Point2D pt = latinPos.getGlyphPosition(0); 52 pt.setLocation(pt.getX(), pt.getY() + 1.0); 53 latinPos.setGlyphPosition(0, pt); 54 55 GlyphVector latinTrans = font.createGlyphVector(frc, latin1); 56 latinTrans.setGlyphTransform(0, AffineTransform.getRotateInstance(.15)); 57 58 test("latin", latinGV, GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS); 59 test("hebrew", hebrewGV, GlyphVector.FLAG_RUN_RTL | 60 GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS); 61 test("arabic", arabicGV, GlyphVector.FLAG_RUN_RTL | 62 GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS); 63 test("hindi", hindiGV, GlyphVector.FLAG_COMPLEX_GLYPHS | 64 GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS); 65 // test("tamil", tamilGV, GlyphVector.FLAG_COMPLEX_GLYPHS); 66 test("pos", latinPos, GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS); 67 test("trans", latinTrans, GlyphVector.FLAG_HAS_TRANSFORMS); 68 } 69 70 GlyphVector makeGlyphVector(String fontname, FontRenderContext frc, String text, boolean rtl, int script) { 71 Font font = new Font(fontname, Font.PLAIN, 14); 72 System.out.println("asking for " + fontname + " and got " + font.getFontName()); 73 int flags = rtl ? 1 : 0; 74 return font.layoutGlyphVector(frc, text.toCharArray(), 0, text.length(), flags); 75 } 76 77 void test(String name, GlyphVector gv, int expectedFlags) { 78 expectedFlags &= gv.FLAG_MASK; 79 int computedFlags = computeFlags(gv) & gv.FLAG_MASK; 80 int actualFlags = gv.getLayoutFlags() & gv.FLAG_MASK; 81 82 System.out.println("\n*** " + name + " ***"); 83 System.out.println(" test flags"); 84 System.out.print("expected "); 85 printFlags(expectedFlags); 86 System.out.print("computed "); 87 printFlags(computedFlags); 88 System.out.print(" actual "); 89 printFlags(actualFlags); 90 91 if (expectedFlags != actualFlags) { 92 throw new Error("layout flags in test: " + name + 93 " expected: " + Integer.toHexString(expectedFlags) + 94 " but got: " + Integer.toHexString(actualFlags)); 95 } 96 } 97 98 static public void printFlags(int flags) { 99 System.out.print("flags:"); 100 if ((flags & GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS) != 0) { 101 System.out.print(" pos"); 102 } 103 if ((flags & GlyphVector.FLAG_HAS_TRANSFORMS) != 0) { 104 System.out.print(" trans"); 105 } 106 if ((flags & GlyphVector.FLAG_RUN_RTL) != 0) { 107 System.out.print(" rtl"); 108 } 109 if ((flags & GlyphVector.FLAG_COMPLEX_GLYPHS) != 0) { 110 System.out.print(" complex"); 111 } 112 if ((flags & GlyphVector.FLAG_MASK) == 0) { 113 System.out.print(" none"); 114 } 115 System.out.println(); 116 } 117 118 int computeFlags(GlyphVector gv) { 119 validateCharIndexMethods(gv); 120 121 int result = 0; 122 if (glyphsAreRTL(gv)) { 123 result |= GlyphVector.FLAG_RUN_RTL; 124 } 125 if (hasComplexGlyphs(gv)) { 126 result |= GlyphVector.FLAG_COMPLEX_GLYPHS; 127 } 128 129 return result; 130 } 131 132 /** 133 * throw an exception if getGlyphCharIndices returns a different result than 134 * you get from iterating through getGlyphCharIndex one at a time. 135 */ 136 void validateCharIndexMethods(GlyphVector gv) { 137 int[] indices = gv.getGlyphCharIndices(0, gv.getNumGlyphs(), null); 138 for (int i = 0; i < gv.getNumGlyphs(); ++i) { 139 if (gv.getGlyphCharIndex(i) != indices[i]) { 140 throw new Error("glyph index mismatch at " + i); 141 } 142 } 143 } 144 145 /** 146 * Return true if the glyph indices are pure ltr 147 */ 148 boolean glyphsAreLTR(GlyphVector gv) { 149 int[] indices = gv.getGlyphCharIndices(0, gv.getNumGlyphs(), null); 150 for (int i = 0; i < indices.length; ++i) { 151 if (indices[i] != i) { 152 return false; 153 } 154 } 155 return true; 156 } 157 158 /** 159 * Return true if the glyph indices are pure rtl 160 */ 161 boolean glyphsAreRTL(GlyphVector gv) { 162 int[] indices = gv.getGlyphCharIndices(0, gv.getNumGlyphs(), null); 163 for (int i = 0; i < indices.length; ++i) { 164 if (indices[i] != indices.length - i - 1) { 165 return false; 166 } 167 } 168 return true; 169 } 170 171 /** 172 * Return true if there is a local reordering (the run is not ltr or rtl). 173 * !!! We can't have mixed bidi runs in the glyphs. 174 */ 175 boolean hasComplexGlyphs(GlyphVector gv) { 176 return !glyphsAreLTR(gv) && !glyphsAreRTL(gv); 177 } 178 } 179 180 /* 181 rect getPixelBounds(frc, x, y) 182 rect getGlyphPixelBounds(frc, int, x, y) 183 getGlyphOutline(int index, x, y) 184 getGlyphInfo() 185 */