7017058: Malayalam glyph substitution is failing for Malayalam with Windows Kartika font
8191130: Sinhala text rendering problem with C+VIRAMA+ZWJ+RA/YA+V 8195836: opentype:Bengali: "Khanda Ta" shaping issue with U+09A4 TA, U+09CD virama, U+200D ZWJ Reviewed-by: serb, psadhukhan
This commit is contained in:
parent
0bed87dccd
commit
b1b0ceb210
@ -566,6 +566,7 @@ abstract class CMap {
|
||||
|
||||
char getGlyph(int charCode) {
|
||||
|
||||
final int origCharCode = charCode;
|
||||
int index = 0;
|
||||
char glyphCode = 0;
|
||||
|
||||
@ -637,8 +638,8 @@ abstract class CMap {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (glyphCode != 0) {
|
||||
//System.err.println("cc="+Integer.toHexString((int)charCode) + " gc="+(int)glyphCode);
|
||||
if (glyphCode == 0) {
|
||||
glyphCode = getFormatCharGlyph(origCharCode);
|
||||
}
|
||||
return glyphCode;
|
||||
}
|
||||
@ -804,6 +805,7 @@ abstract class CMap {
|
||||
}
|
||||
|
||||
char getGlyph(int charCode) {
|
||||
final int origCharCode = charCode;
|
||||
int controlGlyph = getControlCodeGlyph(charCode, true);
|
||||
if (controlGlyph >= 0) {
|
||||
return (char)controlGlyph;
|
||||
@ -859,7 +861,7 @@ abstract class CMap {
|
||||
return glyphCode;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return getFormatCharGlyph(origCharCode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -883,6 +885,7 @@ abstract class CMap {
|
||||
}
|
||||
|
||||
char getGlyph(int charCode) {
|
||||
final int origCharCode = charCode;
|
||||
int controlGlyph = getControlCodeGlyph(charCode, true);
|
||||
if (controlGlyph >= 0) {
|
||||
return (char)controlGlyph;
|
||||
@ -894,7 +897,7 @@ abstract class CMap {
|
||||
|
||||
charCode -= firstCode;
|
||||
if (charCode < 0 || charCode >= entryCount) {
|
||||
return 0;
|
||||
return getFormatCharGlyph(origCharCode);
|
||||
} else {
|
||||
return glyphIdArray[charCode];
|
||||
}
|
||||
@ -1032,6 +1035,7 @@ abstract class CMap {
|
||||
}
|
||||
|
||||
char getGlyph(int charCode) {
|
||||
final int origCharCode = charCode;
|
||||
int controlGlyph = getControlCodeGlyph(charCode, false);
|
||||
if (controlGlyph >= 0) {
|
||||
return (char)controlGlyph;
|
||||
@ -1057,7 +1061,7 @@ abstract class CMap {
|
||||
(startGlyphID[range] + (charCode - startCharCode[range]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return getFormatCharGlyph(origCharCode);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1079,16 +1083,21 @@ abstract class CMap {
|
||||
case 0x000a:
|
||||
case 0x000d: return CharToGlyphMapper.INVISIBLE_GLYPH_ID;
|
||||
}
|
||||
} else if (charCode >= 0x200c) {
|
||||
} else if (noSurrogates && charCode >= 0xFFFF) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
final char getFormatCharGlyph(int charCode) {
|
||||
if (charCode >= 0x200c) {
|
||||
if ((charCode <= 0x200f) ||
|
||||
(charCode >= 0x2028 && charCode <= 0x202e) ||
|
||||
(charCode >= 0x206a && charCode <= 0x206f)) {
|
||||
return CharToGlyphMapper.INVISIBLE_GLYPH_ID;
|
||||
} else if (noSurrogates && charCode >= 0xFFFF) {
|
||||
return 0;
|
||||
return (char)CharToGlyphMapper.INVISIBLE_GLYPH_ID;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static class UVS {
|
||||
|
128
test/jdk/java/awt/font/GlyphVector/ZWJLigatureTest.java
Normal file
128
test/jdk/java/awt/font/GlyphVector/ZWJLigatureTest.java
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user