< prev index next >
src/java.desktop/share/classes/sun/font/TrueTypeGlyphMapper.java
Print this page
@@ -91,10 +91,38 @@
handleBadCMAP();
return (char) missingGlyph;
}
}
+ private char getGlyphFromCMAP(int charCode, int variationSelector) {
+ if (variationSelector == 0) {
+ return getGlyphFromCMAP(charCode);
+ }
+ try {
+ char glyphCode = cmap.getGlyph(charCode, variationSelector);
+ if (glyphCode == 0) { // retry without variation selector
+ return getGlyphFromCMAP(charCode);
+ }
+ 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;
+ }
+ }
+
private void handleBadCMAP() {
if (FontUtilities.isLogging()) {
FontUtilities.getLogger().severe("Null Cmap for " + font +
"substituting for this font");
}
@@ -136,10 +164,22 @@
return glyph;
}
public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) {
for (int i=0;i<count;i++) {
+ if (i < count - 1 &&
+ isVariationSelector(unicodes[i + 1]) &&
+ isBaseChar(unicodes[i])) {
+ if (needsJAremapping) {
+ glyphs[i] = getGlyphFromCMAP(remapJAIntChar(unicodes[i]),
+ unicodes[i + 1]);
+ } else {
+ glyphs[i] = getGlyphFromCMAP(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,15 +187,18 @@
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++) {
int code;
+ int variationSelector = 0;
+ int step = 1;
if (needsJAremapping) {
code = remapJAChar(unicodes[i]);
} else {
code = unicodes[i]; // char is unsigned.
}
@@ -167,22 +210,44 @@
if (low >= LO_SURROGATE_START &&
low <= LO_SURROGATE_END) {
code = (code - HI_SURROGATE_START) *
0x400 + low - LO_SURROGATE_START + 0x10000;
- glyphs[i] = getGlyphFromCMAP(code);
- i += 1; // Empty glyph slot after surrogate
- glyphs[i] = INVISIBLE_GLYPH_ID;
- continue;
+ glyphs[i + 1] = INVISIBLE_GLYPH_ID;
+ step = 2;
}
}
+ if (i < count - step &&
+ isVariationSelector(unicodes[i + step]) &&
+ isBaseChar(code)) {
+ variationSelector = unicodes[i + step];
+ glyphs[i] = getGlyphFromCMAP(code, variationSelector);
+ glyphs[i+step] = INVISIBLE_GLYPH_ID;
+ i += 1;
+ } else if (i < count - step -1 &&
+ isVariationSelector(unicodes[i + step],
+ unicodes[i + step + 1]) &&
+ isBaseChar(code)) {
+ variationSelector = (unicodes[i + step] - HI_SURROGATE_START)
+ * 0x400 + unicodes[i + step + 1]
+ - LO_SURROGATE_START + 0x10000;
+ glyphs[i] = getGlyphFromCMAP(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
@@ -192,10 +257,12 @@
*/
public boolean charsToGlyphsNS(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 +274,46 @@
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 &&
+ isVariationSelector(unicodes[i + step]) &&
+ isBaseChar(code)) {
+ variationSelector = unicodes[i + step];
+ glyphs[i] = getGlyphFromCMAP(code, variationSelector);
+ if (glyphs[i] == 0) { //Retry without variation selector
+ glyphs[i] = getGlyphFromCMAP(code);
+ }
+ glyphs[i+step] = INVISIBLE_GLYPH_ID;
+ i += 1;
+ } else if (i < count - step - 1 &&
+ isVariationSelector(unicodes[i + step],
+ unicodes[i + step + 1]) &&
+ isBaseChar(code)) {
+ variationSelector = (unicodes[i + step] - HI_SURROGATE_START)
+ * 0x400 + unicodes[i + step + 1]
+ - LO_SURROGATE_START + 0x10000;
+ glyphs[i] = getGlyphFromCMAP(code, variationSelector);
+ if (glyphs[i] == 0) { //Retry without variation selector
+ glyphs[i] = getGlyphFromCMAP(code);
+ }
+ 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 +335,12 @@
return
cmap instanceof CMap.CMapFormat8 ||
cmap instanceof CMap.CMapFormat10 ||
cmap instanceof CMap.CMapFormat12;
}
+
+ @Override
+ protected boolean hasVariationSelectorGlyph(int charCode,
+ int variationSelector) {
+ return cmap.hasVariationSelectorGlyph(charCode, variationSelector);
+ }
}
< prev index next >