| /* | |
| * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| /* @test | |
| @bug 7017058 8191130 8195836 | |
| @summary Test handling of ZWJ by layout. | |
| */ | |
| /* | |
| * A forced mapping of ZWJ (u+200D) to a special invisible glyph ID | |
| * was breaking many uses of ZWJ to form ligatures in fonts supporting | |
| * Indic scripts (Malayalam, Bengali, Sinhala at least) and also Emoji. | |
| * Without knowing the exact properties of a font under test, and also | |
| * how a layout engine maps chars to glyphs, it is difficult to write | |
| * a complete robust automated test. | |
| * So whilst it tries to show rendering for any fonts that claims to | |
| * support the target alphabet, it will fail only when specific known | |
| * fonts fail. | |
| * The test automatically passes or fails only if these fonts do | |
| * not ligature away the ZWJ. | |
| * Besides this the test renders the specific text from these fonts | |
| * and any others that claim to fully support the text, so it can be | |
| * manually examined if so desired. | |
| */ | |
| import java.awt.Font; | |
| import java.awt.Graphics2D; | |
| import java.awt.font.FontRenderContext; | |
| import java.awt.font.GlyphVector; | |
| import java.awt.geom.Point2D; | |
| import java.awt.image.BufferedImage; | |
| import java.util.Locale; | |
| public class ZWJLigatureTest { | |
| // These are fonts and scripts on Windows that should support | |
| // the behaviours enough to make reliable tests"; | |
| static final String malayalamName = "Malayalam"; | |
| static final String malayalamFont = "Kartika"; | |
| static final String malayalamText = "\u0D2C\u0D3E\u0D32\u0D28\u0D4D\u200D"; | |
| static final String bengaliName = "Bengali"; | |
| static final String bengaliFont = "Vrinda"; | |
| static final String bengaliText = | |
| "\u09CE \u09A4\u09CD\u200D " + | |
| "\u09A4\u09BE\u09CE \u09A4\u09BE\u09A4\u09CD\u200D"; | |
| static final String sinhalaName = "Sinhala"; | |
| static final String sinhalaFont = "Iskoola Pota"; | |
| static final String sinhalaText = | |
| "\u0DC1\u0DCA\u200D\u0DBB\u0DD3" + | |
| "\u0D9A\u0DCA\u200D\u0DBB\u0DD2" + | |
| "\u0D9A\u0DCA\u200D\u0DBB\u0DD3" + | |
| "\u0DA7\u0DCA\u200D\u0DBB\u0DDA" + | |
| "\u0DB6\u0DCA\u200D\u0DBB\u0DD0" + | |
| "\u0D9B\u0DCA\u200D\u0DBA\u0DCF"; | |
| static String[] scripts = { malayalamName, bengaliName, sinhalaName }; | |
| static String[] fontNames = { malayalamFont, bengaliFont, sinhalaFont }; | |
| static String[] text = { malayalamText, bengaliText, sinhalaText }; | |
| static void doTest() { | |
| boolean testFailed = false; | |
| BufferedImage bi = new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB); | |
| Graphics2D g2d = (Graphics2D)bi.getGraphics(); | |
| FontRenderContext frc = g2d.getFontRenderContext(); | |
| for (int f=0; f < fontNames.length; f++) { | |
| Font font = new Font(fontNames[f], Font.PLAIN, 30); | |
| String family = font.getFamily(Locale.ENGLISH).toLowerCase(); | |
| if (!fontNames[f].toLowerCase().equals(family)) { | |
| System.out.println(fontNames[f] + " not found, skipping."); | |
| continue; | |
| } else { | |
| System.out.println("Testing " + fontNames[f] + | |
| " for " + scripts[f]); | |
| } | |
| char[] chs = text[f].toCharArray(); | |
| GlyphVector gv = font.layoutGlyphVector(frc, chs, 0, chs.length, 0); | |
| for (int g=0; g<gv.getNumGlyphs(); g++) { | |
| int glyph = gv.getGlyphCode(g); | |
| int charIdx = gv.getGlyphCharIndex(g); | |
| int codePoint = text[f].codePointAt(charIdx); | |
| Point2D pos = gv.getGlyphPosition(g); | |
| if (codePoint == 0x200D) { | |
| testFailed = true; | |
| System.out.println("FAIL: GOT ZWJ\n"); | |
| } | |
| System.out.println("["+g+"]: gid="+Integer.toHexString(glyph) | |
| +", charIdx="+Integer.toHexString(charIdx) | |
| +", codePoint="+Integer.toHexString(codePoint) | |
| +", pos=["+pos.getX()+","+pos.getY()+"]"); | |
| } | |
| } | |
| if (testFailed) { | |
| throw new RuntimeException("TEST FAILED"); | |
| } | |
| } | |
| public static void main(String[] args) { | |
| doTest(); | |
| } | |
| } |