blob: 5c227687e7d0d178075d5da90c15523587769459 [file] [log] [blame]
/*
* 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();
}
}