< 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 >