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