< prev index next >
src/java.desktop/share/classes/sun/font/TrueTypeGlyphMapper.java
Print this page
@@ -85,11 +85,36 @@
Integer.toHexString((int)glyphCode) +
" for char " + Integer.toHexString(charCode));
}
return (char)missingGlyph;
}
- } catch(Exception e) {
+ } catch (Exception e) {
+ handleBadCMAP();
+ return (char) missingGlyph;
+ }
+ }
+
+ private char getGlyphFromCMAPVS(int charCode, int variationSelector) {
+ if (variationSelector == 0) {
+ return getGlyphFromCMAP(charCode);
+ }
+ try {
+ char glyphCode = cmap.getGlyph(charCode, variationSelector, true);
+ if (glyphCode < numGlyphs ||
+ glyphCode >= FileFontStrike.INVISIBLE_GLYPHS) {
+ return glyphCode;
+ } else {
+ if (FontUtilities.isLogging()) {
+ FontUtilities.getLogger().warning
+ (font + " out of range glyph id=" +
+ Integer.toHexString((int)glyphCode) +
+ " for char " + Integer.toHexString(charCode) +
+ " for vs " + Integer.toHexString(variationSelector));
+ }
+ return (char)missingGlyph;
+ }
+ } catch (Exception e) {
handleBadCMAP();
return (char) missingGlyph;
}
}
@@ -135,11 +160,42 @@
}
return glyph;
}
public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) {
- for (int i=0;i<count;i++) {
+ for (int i = 0; i < count; i++) {
+ if (isVariationSelector(unicodes[i])) {
+ charsToGlyphsVS(count, unicodes, glyphs);
+ return;
+ }
+ if (needsJAremapping) {
+ glyphs[i] = getGlyphFromCMAP(remapJAIntChar(unicodes[i]));
+ } else {
+ glyphs[i] = getGlyphFromCMAP(unicodes[i]);
+ }
+ if (font.checkUseNatives() &&
+ glyphs[i] < font.glyphToCharMap.length) {
+ font.glyphToCharMap[glyphs[i]] = (char)unicodes[i];
+ }
+ }
+ }
+
+ private void charsToGlyphsVS(int count, int[] unicodes, int[] glyphs) {
+ for (int i = 0; i < count; i++) {
+ if (i < count - 1 &&
+ isVariationSelector(unicodes[i + 1]) &&
+ isVSBaseChar(unicodes[i])) {
+ if (needsJAremapping) {
+ glyphs[i] = getGlyphFromCMAPVS(remapJAIntChar(unicodes[i]),
+ unicodes[i + 1]);
+ } else {
+ glyphs[i] = getGlyphFromCMAPVS(unicodes[i],
+ unicodes[i + 1]);
+ }
+ i++;
+ glyphs[i] = INVISIBLE_GLYPH_ID;
+ } else {
if (needsJAremapping) {
glyphs[i] = getGlyphFromCMAP(remapJAIntChar(unicodes[i]));
} else {
glyphs[i] = getGlyphFromCMAP(unicodes[i]);
}
@@ -147,14 +203,15 @@
glyphs[i] < font.glyphToCharMap.length) {
font.glyphToCharMap[glyphs[i]] = (char)unicodes[i];
}
}
}
+ }
public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) {
- for (int i=0; i<count; i++) {
+ for (int i = 0; i < count; i++) {
int code;
if (needsJAremapping) {
code = remapJAChar(unicodes[i]);
} else {
code = unicodes[i]; // char is unsigned.
@@ -167,22 +224,87 @@
if (low >= LO_SURROGATE_START &&
low <= LO_SURROGATE_END) {
code = (code - HI_SURROGATE_START) *
0x400 + low - LO_SURROGATE_START + 0x10000;
+ if (isVariationSelector(code)) {
+ charsToGlyphsVS(count, unicodes, glyphs);
+ return;
+ }
glyphs[i] = getGlyphFromCMAP(code);
i += 1; // Empty glyph slot after surrogate
glyphs[i] = INVISIBLE_GLYPH_ID;
continue;
}
+ } else if (isVariationSelectorBMP(unicodes[i])) {
+ charsToGlyphsVS(count, unicodes, glyphs);
+ return;
+ }
+ glyphs[i] = getGlyphFromCMAP(code);
+
+ if (font.checkUseNatives() &&
+ glyphs[i] < font.glyphToCharMap.length) {
+ font.glyphToCharMap[glyphs[i]] = (char)code;
+ }
+
+ }
+ }
+
+ private void charsToGlyphsVS(int count, char[] unicodes, int[] glyphs) {
+ for (int i = 0; i < count; i++) {
+ int code;
+ int variationSelector = 0;
+ int step = 1;
+ if (needsJAremapping) {
+ code = remapJAChar(unicodes[i]);
+ } else {
+ code = unicodes[i]; // char is unsigned.
+ }
+
+ if (code >= HI_SURROGATE_START &&
+ code <= HI_SURROGATE_END && i < count - 1) {
+ char low = unicodes[i + 1];
+
+ if (low >= LO_SURROGATE_START &&
+ low <= LO_SURROGATE_END) {
+ code = (code - HI_SURROGATE_START) *
+ 0x400 + low - LO_SURROGATE_START + 0x10000;
+
+ glyphs[i + 1] = INVISIBLE_GLYPH_ID;
+ step = 2;
+ }
+ }
+ if (i < count - step &&
+ isVariationSelectorBMP(unicodes[i + step]) &&
+ isVSBaseChar(code)) {
+ variationSelector = unicodes[i + step];
+ glyphs[i] = getGlyphFromCMAPVS(code, variationSelector);
+ glyphs[i+step] = INVISIBLE_GLYPH_ID;
+ i += 1;
+ } else if (i < count - step -1 &&
+ isVariationSelectorExt(unicodes[i + step],
+ unicodes[i + step + 1]) &&
+ isVSBaseChar(code)) {
+ variationSelector = (unicodes[i + step] - HI_SURROGATE_START)
+ * 0x400 + unicodes[i + step + 1]
+ - LO_SURROGATE_START + 0x10000;
+ glyphs[i] = getGlyphFromCMAPVS(code, variationSelector);
+ glyphs[i + step] = INVISIBLE_GLYPH_ID;
+ glyphs[i + step + 1] = INVISIBLE_GLYPH_ID;
+ i += 2;
}
+ if (variationSelector == 0) {
glyphs[i] = getGlyphFromCMAP(code);
if (font.checkUseNatives() &&
glyphs[i] < font.glyphToCharMap.length) {
font.glyphToCharMap[glyphs[i]] = (char)code;
}
+ }
+ if (code >= 0x10000) {
+ i++;
+ }
}
}
/* This variant checks if shaping is needed and immediately
@@ -190,12 +312,60 @@
* to check the return type because it needs to know how to handle
* the character data for display.
*/
public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) {
- for (int i=0; i<count; i++) {
+ for (int i = 0; i < count; i++) {
+ int code;
+ if (needsJAremapping) {
+ code = remapJAChar(unicodes[i]);
+ } else {
+ code = unicodes[i]; // char is unsigned.
+ }
+
+ if (code >= HI_SURROGATE_START &&
+ code <= HI_SURROGATE_END && i < count - 1) {
+ char low = unicodes[i + 1];
+
+ if (low >= LO_SURROGATE_START &&
+ low <= LO_SURROGATE_END) {
+ code = (code - HI_SURROGATE_START) *
+ 0x400 + low - LO_SURROGATE_START + 0x10000;
+ glyphs[i + 1] = INVISIBLE_GLYPH_ID;
+ }
+ }
+ if (isVariationSelector(code)) {
+ return charsToGlyphsNSVS(count, unicodes, glyphs);
+ }
+
+ glyphs[i] = getGlyphFromCMAP(code);
+ if (font.checkUseNatives() &&
+ glyphs[i] < font.glyphToCharMap.length) {
+ font.glyphToCharMap[glyphs[i]] = (char)code;
+ }
+
+ if (code < FontUtilities.MIN_LAYOUT_CHARCODE) {
+ continue;
+ }
+ else if (FontUtilities.isComplexCharCode(code)) {
+ return true;
+ }
+ else if (code >= 0x10000) {
+ i += 1; // Empty glyph slot after surrogate
+ continue;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean charsToGlyphsNSVS(int count, char[] unicodes,
+ int[] glyphs) {
+ for (int i = 0; i < count; i++) {
int code;
+ int step = 1;
+ int variationSelector = 0;
if (needsJAremapping) {
code = remapJAChar(unicodes[i]);
} else {
code = unicodes[i]; // char is unsigned.
}
@@ -207,18 +377,40 @@
if (low >= LO_SURROGATE_START &&
low <= LO_SURROGATE_END) {
code = (code - HI_SURROGATE_START) *
0x400 + low - LO_SURROGATE_START + 0x10000;
glyphs[i + 1] = INVISIBLE_GLYPH_ID;
+ step = 2;
}
}
+ if (i < count - step &&
+ isVariationSelectorBMP(unicodes[i + step]) &&
+ isVSBaseChar(code)) {
+ variationSelector = unicodes[i + step];
+ glyphs[i] = getGlyphFromCMAPVS(code, variationSelector);
+ glyphs[i+step] = INVISIBLE_GLYPH_ID;
+ i += 1;
+ } else if (i < count - step - 1 &&
+ isVariationSelectorExt(unicodes[i + step],
+ unicodes[i + step + 1]) &&
+ isVSBaseChar(code)) {
+ variationSelector = (unicodes[i + step] - HI_SURROGATE_START)
+ * 0x400 + unicodes[i + step + 1]
+ - LO_SURROGATE_START + 0x10000;
+ glyphs[i] = getGlyphFromCMAPVS(code, variationSelector);
+ glyphs[i + step] = INVISIBLE_GLYPH_ID;
+ glyphs[i + step + 1] = INVISIBLE_GLYPH_ID;
+ i += 2;
+ }
+ if (variationSelector == 0) {
glyphs[i] = getGlyphFromCMAP(code);
if (font.checkUseNatives() &&
glyphs[i] < font.glyphToCharMap.length) {
font.glyphToCharMap[glyphs[i]] = (char)code;
}
+ }
if (code < FontUtilities.MIN_LAYOUT_CHARCODE) {
continue;
}
else if (FontUtilities.isComplexCharCode(code)) {
@@ -240,6 +432,10 @@
return
cmap instanceof CMap.CMapFormat8 ||
cmap instanceof CMap.CMapFormat10 ||
cmap instanceof CMap.CMapFormat12;
}
+
+ int getGlyphOfVS(int charCode, int variationSelector) {
+ return cmap.getGlyph(charCode, variationSelector, false);
+ }
}
< prev index next >