--- old/src/java.desktop/share/classes/sun/font/CompositeGlyphMapper.java 2018-05-31 15:12:53.000000000 -0700 +++ new/src/java.desktop/share/classes/sun/font/CompositeGlyphMapper.java 2018-05-31 15:12:52.000000000 -0700 @@ -133,6 +133,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); + int glyphCode = missingGlyph; + if (mapper.hasVariationSelectorGlyph(unicode, + variationSelector)) { + int glyphCodes[] = { 0, 0}; + int codes[] = {unicode, variationSelector}; + mapper.charsToGlyphs(2, codes, glyphCodes); + glyphCode = glyphCodes[0]; + 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 @@ -193,6 +217,8 @@ for (int i=0; i= HI_SURROGATE_START && code <= HI_SURROGATE_END && i < count - 1) { @@ -203,12 +229,35 @@ code = (code - HI_SURROGATE_START) * 0x400 + low - LO_SURROGATE_START + 0x10000; glyphs[i + 1] = INVISIBLE_GLYPH_ID; + step = 2; } } - int gc = glyphs[i] = getCachedGlyphCode(code); - if (gc == UNINITIALIZED_GLYPH) { - glyphs[i] = convertToGlyph(code); + if (i < count - step && + isVariationSelector(unicodes[i+step]) && + isBaseChar(code)) { + variationSelector = unicodes[i+step]; + glyphs[i] = convertToGlyph(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] = 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) { @@ -232,6 +281,8 @@ public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) { for (int i=0; i= HI_SURROGATE_START && code <= HI_SURROGATE_END && i < count - 1) { @@ -242,19 +293,39 @@ code = (code - HI_SURROGATE_START) * 0x400 + low - LO_SURROGATE_START + 0x10000; - 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; + glyphs[i+1] = INVISIBLE_GLYPH_ID; + step = 2; } } - int gc = glyphs[i] = getCachedGlyphCode(code); - if (gc == UNINITIALIZED_GLYPH) { - glyphs[i] = convertToGlyph(code); + if (i < count - step && + isVariationSelector(unicodes[i+step]) && + isBaseChar(code)) { + variationSelector = unicodes[i+step]; + glyphs[i] = convertToGlyph(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] = 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++; } } } @@ -263,9 +334,17 @@ for (int i=0; i