1 /* 2 * Copyright (c) 2018, 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 7017058 8191130 8195836 27 @summary Test handling of ZWJ by layout. 28 */ 29 30 /* 31 * A forced mapping of ZWJ (u+200D) to a special invisible glyph ID 32 * was breaking many uses of ZWJ to form ligatures in fonts supporting 33 * Indic scripts (Malayalam, Bengali, Sinhala at least) and also Emoji. 34 * Without knowing the exact properties of a font under test, and also 35 * how a layout engine maps chars to glyphs, it is difficult to write 36 * a complete robust automated test. 37 * So whilst it tries to show rendering for any fonts that claims to 38 * support the target alphabet, it will fail only when specific known 39 * fonts fail. 40 * The test automatically passes or fails only if these fonts do 41 * not ligature away the ZWJ. 42 * Besides this the test renders the specific text from these fonts 43 * and any others that claim to fully support the text, so it can be 44 * manually examined if so desired. 45 */ 46 47 import java.awt.Font; 48 import java.awt.Graphics2D; 49 import java.awt.font.FontRenderContext; 50 import java.awt.font.GlyphVector; 51 import java.awt.geom.Point2D; 52 import java.awt.image.BufferedImage; 53 import java.util.Locale; 54 55 public class ZWJLigatureTest { 56 57 // These are fonts and scripts on Windows that should support 58 // the behaviours enough to make reliable tests"; 59 60 static final String malayalamName = "Malayalam"; 61 static final String malayalamFont = "Kartika"; 62 static final String malayalamText = "\u0D2C\u0D3E\u0D32\u0D28\u0D4D\u200D"; 63 64 static final String bengaliName = "Bengali"; 65 static final String bengaliFont = "Vrinda"; 66 static final String bengaliText = 67 "\u09CE \u09A4\u09CD\u200D " + 68 "\u09A4\u09BE\u09CE \u09A4\u09BE\u09A4\u09CD\u200D"; 69 70 static final String sinhalaName = "Sinhala"; 71 static final String sinhalaFont = "Iskoola Pota"; 72 static final String sinhalaText = 73 "\u0DC1\u0DCA\u200D\u0DBB\u0DD3" + 74 "\u0D9A\u0DCA\u200D\u0DBB\u0DD2" + 75 "\u0D9A\u0DCA\u200D\u0DBB\u0DD3" + 76 "\u0DA7\u0DCA\u200D\u0DBB\u0DDA" + 77 "\u0DB6\u0DCA\u200D\u0DBB\u0DD0" + 78 "\u0D9B\u0DCA\u200D\u0DBA\u0DCF"; 79 80 81 static String[] scripts = { malayalamName, bengaliName, sinhalaName }; 82 static String[] fontNames = { malayalamFont, bengaliFont, sinhalaFont }; 83 static String[] text = { malayalamText, bengaliText, sinhalaText }; 84 85 86 static void doTest() { 87 boolean testFailed = false; 88 89 BufferedImage bi = new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB); 90 Graphics2D g2d = (Graphics2D)bi.getGraphics(); 91 FontRenderContext frc = g2d.getFontRenderContext(); 92 for (int f=0; f < fontNames.length; f++) { 93 Font font = new Font(fontNames[f], Font.PLAIN, 30); 94 String family = font.getFamily(Locale.ENGLISH).toLowerCase(); 95 if (!fontNames[f].toLowerCase().equals(family)) { 96 System.out.println(fontNames[f] + " not found, skipping."); 97 continue; 98 } else { 99 System.out.println("Testing " + fontNames[f] + 100 " for " + scripts[f]); 101 } 102 char[] chs = text[f].toCharArray(); 103 GlyphVector gv = font.layoutGlyphVector(frc, chs, 0, chs.length, 0); 104 for (int g=0; g<gv.getNumGlyphs(); g++) { 105 int glyph = gv.getGlyphCode(g); 106 int charIdx = gv.getGlyphCharIndex(g); 107 int codePoint = text[f].codePointAt(charIdx); 108 Point2D pos = gv.getGlyphPosition(g); 109 110 if (codePoint == 0x200D) { 111 testFailed = true; 112 System.out.println("FAIL: GOT ZWJ\n"); 113 } 114 System.out.println("["+g+"]: gid="+Integer.toHexString(glyph) 115 +", charIdx="+Integer.toHexString(charIdx) 116 +", codePoint="+Integer.toHexString(codePoint) 117 +", pos=["+pos.getX()+","+pos.getY()+"]"); 118 } 119 } 120 if (testFailed) { 121 throw new RuntimeException("TEST FAILED"); 122 } 123 } 124 125 public static void main(String[] args) { 126 doTest(); 127 } 128 }