< prev index next >
src/java.desktop/share/classes/sun/font/CompositeGlyphMapper.java
Print this page
@@ -131,10 +131,30 @@
}
}
return missingGlyph;
}
+ private int convertToGlyph(int unicode, int variationSelector) {
+ if (variationSelector == 0) {
+ return convertToGlyph(unicode);
+ }
+ for (int slot = 0; slot < font.numSlots; slot++) {
+ if (!hasExcludes || !font.isExcludedChar(slot, unicode)) {
+ CharToGlyphMapper mapper = getSlotMapper(slot);
+ if (mapper instanceof TrueTypeGlyphMapper) {
+ int glyphCode = ((TrueTypeGlyphMapper)mapper).
+ getGlyphOfVS(unicode, variationSelector);
+ if (glyphCode != mapper.getMissingGlyphCode()) {
+ glyphCode = compositeGlyphCode(slot, glyphCode);
+ return glyphCode;
+ }
+ }
+ }
+ }
+ return convertToGlyph(unicode); //retry without Variation Selector
+ }
+
public int getNumGlyphs() {
int numGlyphs = 0;
/* The number of glyphs in a composite is affected by
* exclusion ranges and duplicates (ie the same code point is
* mapped by two different fonts) and also whether or not to
@@ -203,15 +223,81 @@
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);
+ }
+
+ int gc = glyphs[i] = getCachedGlyphCode(code);
+ if (gc == UNINITIALIZED_GLYPH) {
+ glyphs[i] = convertToGlyph(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 = unicodes[i]; // char is unsigned.
+ int step = 1;
+ int variationSelector = 0;
+
+ 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] = convertToGlyph(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] = convertToGlyph(code, variationSelector);
+ glyphs[i+step] = INVISIBLE_GLYPH_ID;
+ glyphs[i+step+1] = INVISIBLE_GLYPH_ID;
+ i += 2;
+ }
+ if (variationSelector == 0) {
int gc = glyphs[i] = getCachedGlyphCode(code);
if (gc == UNINITIALIZED_GLYPH) {
glyphs[i] = convertToGlyph(code);
}
+ }
if (code < FontUtilities.MIN_LAYOUT_CHARCODE) {
continue;
}
else if (FontUtilities.isComplexCharCode(code)) {
@@ -239,35 +325,117 @@
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;
+ }
int gc = glyphs[i] = getCachedGlyphCode(code);
if (gc == UNINITIALIZED_GLYPH) {
glyphs[i] = convertToGlyph(code);
}
i += 1; // Empty glyph slot after surrogate
glyphs[i] = INVISIBLE_GLYPH_ID;
continue;
}
+ } else if (isVariationSelectorBMP(unicodes[i])) {
+ charsToGlyphsVS(count, unicodes, glyphs);
+ return;
}
int gc = glyphs[i] = getCachedGlyphCode(code);
if (gc == UNINITIALIZED_GLYPH) {
glyphs[i] = convertToGlyph(code);
}
}
}
+ private void charsToGlyphsVS(int count, char[] unicodes, int[] glyphs) {
+ for (int i = 0; i < count; i++) {
+ int code = unicodes[i]; // char is unsigned.
+ int variationSelector = 0;
+ int step = 1;
+
+ 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] = convertToGlyph(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] = convertToGlyph(code, variationSelector);
+ glyphs[i+step] = INVISIBLE_GLYPH_ID;
+ glyphs[i+step+1] = INVISIBLE_GLYPH_ID;
+ i += 2;
+ }
+ if (variationSelector == 0) {
+ int gc = glyphs[i] = getCachedGlyphCode(code);
+ if (gc == UNINITIALIZED_GLYPH) {
+ glyphs[i] = convertToGlyph(code);
+ }
+ }
+ if (code >= 0x10000) {
+ i++;
+ }
+ }
+ }
+
public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) {
for (int i=0; i<count; i++) {
int code = unicodes[i];
+ if (isVariationSelector(code)) {
+ charsToGlyphsVS(count, unicodes, glyphs);
+ return;
+ }
+
+ glyphs[i] = getCachedGlyphCode(code);
+ if (glyphs[i] == UNINITIALIZED_GLYPH) {
+ glyphs[i] = convertToGlyph(code);
+ }
+ }
+ }
+
+ private void charsToGlyphsVS(int count, int[] unicodes, int[] glyphs) {
+ for (int i = 0; i < count; i++) {
+ int code = unicodes[i];
+ if (i < count-1 &&
+ isVariationSelector(unicodes[i+1]) &&
+ isVSBaseChar(code) ) {
+ glyphs[i] = convertToGlyph(code, unicodes[i+1]);
+ glyphs[i+1] = INVISIBLE_GLYPH_ID;
+ i++;
+ } else {
glyphs[i] = getCachedGlyphCode(code);
if (glyphs[i] == UNINITIALIZED_GLYPH) {
glyphs[i] = convertToGlyph(code);
}
}
}
+ }
}
< prev index next >