I happened to create similar patch without knowing the report below.
https://bugs.openjdk.java.net/browse/JDK-8187100

======================================================
Difference with following SWING patch and my JavaFX patch.
http://cr.openjdk.java.net/~srl/8187100/webrev.00/

1.  For Acceleration and Memory saving, load only partial glyphs table.
javafx.graphics/src/main/java/com/sun/javafx/font/CMap.java

+ if (numMappings[i] > 0 && (uniStart[i] == null || glyphID[i] == null)) {
+                    try {
+                        initNonDef(i);


2.  Mongolian support
javafx.graphics/src/main/java/com/sun/javafx/text/ScriptMapper.java

+        else if (code <= 0x18af) { // 1800 - 18AF Mongolian (including FVS)
+            return true;
+        }


3.  Fix 2 bugs on Windows (See below bugs)


======================================================
This JavaFX patch fixes following 4 bugs.

1. To make display IVS/SVS
Sample is kami.java and kami2.java

javafx.graphics/src/main/java/com/sun/javafx/font/CMap.java
javafx.graphics/src/main/java/com/sun/javafx/font/CharToGlyphMapper.java
javafx.graphics/src/main/java/com/sun/javafx/font/CompositeGlyphMapper.java
javafx.graphics/src/main/java/com/sun/javafx/font/OpenTypeGlyphMapper.java



2. To make dislpay Mongolian and FVS
Sample is mongol.java

javafx.graphics/src/main/java/com/sun/javafx/text/ScriptMapper.java



3. Fix bug to handle minus value glyph_id on Windows
   (You run NG.java, then Java aborted)
Sample is NG.java

javafx.graphics/src/main/java/com/sun/javafx/font/directwrite/DWGlyph.java
javafx.graphics/src/main/java/com/sun/javafx/font/directwrite/DWGlyphLayout.java



4. Fix bug to display INVISIBLE_GLYPH on Windows (Now display square box. No need to display.)

javafx.graphics/src/main/java/com/sun/prism/sw/SWGraphics.java


======================================================
I checked this patch on CentOS 7.5 and Windows7 x64.


====================
PATCH
====================
diff -r 284d06bb1364 modules/javafx.graphics/src/main/java/com/sun/javafx/font/CMap.java --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/font/CMap.java Tue Jun 12 14:40:17 2018 +0530 +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/font/CMap.java Wed Jun 13 14:52:07 2018 +0900
@@ -42,12 +42,13 @@
 abstract class CMap {

     static final char noSuchChar = (char)0xfffd;
+    static final int BYTEMASK  = 0x000000ff;
     static final int SHORTMASK = 0x0000ffff;
     static final int INTMASK   = 0xffffffff;

     private static final int MAX_CODE_POINTS = 0x10ffff;

-    static CMap initialize(PrismFontFile font) {
+ static CMap initialize(PrismFontFile font, int[] offset_format, int create_cmap) {

         CMap cmap = null;

@@ -59,6 +60,11 @@
         Buffer cmapBuffer = font.readTable(FontConstants.cmapTag);
         short numberSubTables = cmapBuffer.getShort(2);

+        /* create CMap14 */
+        if (create_cmap == 14 && offset_format[0] != 0) {
+            return createCMap(cmapBuffer, offset_format[0]);
+        }
+
/* Locate the offsets of supported 3,* Microsoft platform encodings,
          * and any 0,* Unicode platform encoding. The latter is used by
          * all current OS X fonts that don't have a Microsoft cmap.
@@ -76,6 +82,9 @@
                 zeroStar = true;
                 encodingID = cmapBuffer.getShort();
                 zeroStarOffset = cmapBuffer.getInt();
+                if (encodingID == 5) {
+                    offset_format[0] = zeroStarOffset;
+                }
             }
             else if (platformID == 3) {
                 threeStar = true;
@@ -133,6 +142,7 @@
         case 8:  return new CMapFormat8(buffer, offset);
         case 10: return new CMapFormat10(buffer, offset);
         case 12: return new CMapFormat12(buffer, offset);
+        case 14: return new CMapFormat14(buffer, offset);
default: throw new RuntimeException("Cmap format unimplemented: " +
                                             (int)buffer.getChar(offset));
         }
@@ -140,6 +150,13 @@

     abstract char getGlyph(int charCode);

+    char getGlyph(int charCode, int vs) {
+        return getGlyph(charCode);
+    }
+
+    void setDefCMap(CMap defCmap) {
+    }
+
     /* Format 4 Header is
      * ushort format (off=0)
      * ushort length (off=2)
@@ -207,6 +224,7 @@
                 char ctmp = buffer.getChar();
                 idRangeOffset[i] = (char)((ctmp>>1)&0xffff);
             }
+
             /* Can calculate the number of glyph IDs by subtracting
              * "pos" from the length of the cmap
              */
@@ -591,6 +609,191 @@

     }

+    // Format 14: Table for Variation Selector (SVS and IVS)
+    static class CMapFormat14 extends CMap {
+
+        Buffer buffer;
+        int offset;
+
+        int numSelector;
+        int[] varSelector;
+
+        /* default glyphs */
+        int[] defaultOff, numRanges;
+        int[][] defUniStart;
+        short[][] additionalCnt;
+
+        /* non default glyphs */
+        int[] nonDefOff, numMappings;
+        int[][] uniStart, glyphID;
+        /* e.g.
+         *  uniStart[numSelector-1] = U+e0100
+         *  uniStart[numSelector-1][numMappings-1] = U+795e
+         *  glyphID[numSelector-1][numMappings-1] = 12345
+         */
+
+        CMap defCmap;
+        void setDefCMap(CMap cmap) {
+            this.defCmap = cmap;
+        }
+
+        CMapFormat14(Buffer buffer, int offset) {
+            this.buffer = buffer;
+            this.offset = offset;
+
+            buffer.position(offset+6);
+            /* get count of Variation Selector */
+            numSelector = buffer.getInt();
+
+ varSelector = new int[numSelector]; // e.g. {0xfe00, 0xe0100, 0xe0101}
+            defaultOff = new int[numSelector];
+            nonDefOff = new int[numSelector];
+
+            /* get Variation Selector and Table offset */
+            for (int i=0; i<numSelector; i++) {
+ varSelector[i] = ((buffer.getShort() & SHORTMASK)<<8) | (buffer.get() & BYTEMASK);
+                defaultOff[i] = buffer.getInt();
+                nonDefOff[i] = buffer.getInt();
+            }
+
+            numMappings = new int[numSelector];
+            uniStart = new int[numSelector][];
+            glyphID = new int[numSelector][];
+
+            /* nonDefault glyphs table, get Unicode and glyphID */
+            for (int i=0; i<numSelector; i++) {
+                if (nonDefOff[i] == 0) {
+                    numMappings[i] = 0;
+                    continue;
+                }
+                buffer.position(offset+nonDefOff[i]);
+                numMappings[i] = buffer.getInt();
+            }
+
+            numRanges = new int[numSelector];
+            defUniStart = new int[numSelector][];
+            additionalCnt = new short[numSelector][];
+
+            /* Default glyphs table, get Unicode and count */
+            for (int i=0; i<numSelector; i++) {
+                if (defaultOff[i] == 0) {
+                    numRanges[i] = 0;
+                    continue;
+                }
+                buffer.position(offset+defaultOff[i]);
+                numRanges[i] = buffer.getInt();
+            }
+        }
+
+ /* init Non Default Glyphs Table of pointed VS(e.g. fe00, e0100.) */
+        void initNonDef(int i) {
+        /* nonDefault glyphs table, get Unicode and glyphID */
+ buffer.position(offset+nonDefOff[i]+4); // +4 = skip numMappings
+            uniStart[i] = new int[numMappings[i]];
+            glyphID[i] = new int[numMappings[i]];
+
+            for (int j=0; j<numMappings[i]; j++) {
+ uniStart[i][j] = ((buffer.getShort() & SHORTMASK)<<8) | (buffer.get() & BYTEMASK);
+                glyphID[i][j] = buffer.getShort() & SHORTMASK;
+            }
+        }
+
+        void initDef(int i) {
+            buffer.position(offset+defaultOff[i]+4); // +4 = skip numRanges
+            defUniStart[i] = new int[numRanges[i]];
+            additionalCnt[i] = new short[numRanges[i]];
+
+            for (int j=0; j<numRanges[i]; j++) {
+ defUniStart[i][j] = ((buffer.getShort() & SHORTMASK)<<8) | (buffer.get() & BYTEMASK);
+                additionalCnt[i][j] = (short)(buffer.get() & BYTEMASK);
+            }
+        }
+
+        final int findMapNumber_NonDef(int charCode, int i) {
+            if (numMappings[i] > 0) {
+                int min = 0, max, mid;
+                max = numMappings[i];
+                while (min < max) {
+                    mid = (min+max) >> 1;
+                    if (charCode < uniStart[i][mid]) {
+                        max = mid;
+                    } else if (charCode > uniStart[i][mid]) {
+                        min = mid + 1;
+                    } else {
+                        return mid;
+                    }
+                }
+            }
+            return -1;
+        }
+
+        final int findRangeNumber_Def(int charCode, int i) {
+            if (numRanges[i] > 0) {
+                int min = 0, max, mid;
+                max = numRanges[i];
+                while (min < max) {
+                    mid = (min+max) >> 1;
+                    if (charCode < defUniStart[i][mid]) {
+                        max = mid;
+ } else if (charCode > defUniStart[i][mid] + additionalCnt[i][mid]) {
+                        min = mid + 1;
+                    } else {
+                        return mid;
+                    }
+                }
+            }
+            return -1;
+        }
+
+        char getGlyph(int charCode) {
+            return getGlyph(charCode, 0);
+        }
+
+        char getGlyph(int charCode, int vs) {
+            if (vs == 0) return 0;
+
+            int j;
+            for (int i=0; i<numSelector; i++) {
+                if (varSelector[i] > vs) break;
+                if (varSelector[i] != vs) continue;
+
+                /* non default glyphs table */
+ if (numMappings[i] > 0 && (uniStart[i] == null || glyphID[i] == null)) {
+                    try {
+                        initNonDef(i);
+                    } catch (Exception e) {
+                        return 0;
+                    }
+                }
+
+                /* search non default glyphs table */
+                j = findMapNumber_NonDef(charCode, i);
+                if (j != -1) {
+                    return (char)glyphID[i][j];
+                }
+
+                /* default glyphs table */
+ if (defCmap == null) break; // can't get glyphID by default glyphs table + if (numRanges[i] > 0 && (defUniStart[i] == null || additionalCnt[i] == null)) {
+                    try {
+                        initDef(i);
+                    } catch (Exception e) {
+                        return 0;
+                    }
+                }
+
+                /* search default glyphs table */
+                if (defCmap == null) break;
+                j = findRangeNumber_Def(charCode, i);
+                if (j != -1) {
+                    return defCmap.getGlyph(charCode);
+                }
+            }
+
+            return 0;
+        }
+    }
+
     /* Used to substitute for bad Cmaps. */
     static class NullCMapClass extends CMap {

diff -r 284d06bb1364 modules/javafx.graphics/src/main/java/com/sun/javafx/font/CharToGlyphMapper.java --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/font/CharToGlyphMapper.java Tue Jun 12 14:40:17 2018 +0530 +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/font/CharToGlyphMapper.java Wed Jun 13 14:52:07 2018 +0900
@@ -42,8 +42,66 @@
     public static final int MISSING_GLYPH = 0;
     public static final int INVISIBLE_GLYPH_ID = 0xffff;

+    public static final int SVS_START = 0xFE00;  // VS1
+    public static final int SVS_END = 0xFE0F;    // VS16
+    public static final int IVS_START = 0xE0100; // VS17
+    public static final int IVS_END = 0xE01EF;   // VS256
+    public static final int FVS_START = 0x180B;  // FVS1
+    public static final int FVS_END = 0x180D;    // FVS3
+
     protected int missingGlyph = MISSING_GLYPH;

+    /* http://www.unicode.org/versions/Unicode10.0.0/ch18.pdf */
+    public static boolean isCJK(int code) {
+        if (code >= 0x4E00 && code <= 0x9FFF) // Unified Ideographs
+            return true;
+        if (code >= 0x3400 && code <= 0x4DBF) // Extension A
+            return true;
+        if (code >= 0x20000 && code <= 0x2A6DF) // Extension B
+            return true;
+        if (code >= 0x2A700 && code <= 0x2B73F) // Extension C
+            return true;
+        if (code >= 0x2B740 && code <= 0x2B81F) // Extension D
+            return true;
+        if (code >= 0x2B820 && code <= 0x2CEAF) // Extension E
+            return true;
+        if (code >= 0x2CEB0 && code <= 0x2EBE0) // Extension F
+            return true;
+        if (code >= 0xF900 && code <= 0xFAFF) // Compatibility Ideographs
+            return true;
+ if (code >= 0x2F800 && code <= 0x2FA1F) // Compatibility Ideographs Supplement
+            return true;
+        return false;
+    }
+
+    public static boolean isVS(int code) {
+        if (isIVS(code))
+            return true;
+        if (isSVS(code))
+            return true;
+//        if (isFVS(code))
+//            return true;
+        return false;
+    }
+
+    public static boolean isSVS(int code) {
+        if (code >= SVS_START && code <= SVS_END)
+            return true;
+        return false;
+    }
+
+    public static boolean isIVS(int code) {
+        if (code >= IVS_START && code <= IVS_END)
+            return true;
+        return false;
+    }
+
+//    public static boolean isFVS(int code) {
+//        if (code >= FVS_START && code <= FVS_END)
+//            return true;
+//        return false;
+//    }
+
     public boolean canDisplay(char cp) {
         int glyph = charToGlyph(cp);
         return glyph != missingGlyph;
@@ -53,18 +111,28 @@
         return missingGlyph;
     }

-    public abstract int getGlyphCode(int charCode);
+    public abstract int getGlyphCode(int charCode, int vs);

     public int charToGlyph(char unicode) {
-        return getGlyphCode(unicode);
+        return getGlyphCode(unicode, (char)0);
+    }
+
+    public int charToGlyph(char unicode, char vs) {
+        return getGlyphCode(unicode, vs);
     }

     public int charToGlyph(int unicode) {
-        return getGlyphCode(unicode);
+        return getGlyphCode(unicode, 0);
+    }
+
+    public int charToGlyph(int unicode, int vs) {
+        return getGlyphCode(unicode, vs);
     }

     public void charsToGlyphs(int start, int count, char[] unicodes,
                               int[] glyphs, int glyphStart) {
+
+ int codeWasSurrogate = 0; // store surrogate pair to handle surrogate pair+VS
         for (int i=0; i<count; i++) {
             int code = unicodes[start + i]; // char is unsigned.
             if (code >= HI_SURROGATE_START &&
@@ -75,13 +143,67 @@
                     low <= LO_SURROGATE_END) {
code = ((code - HI_SURROGATE_START) << HI_SURROGATE_SHIFT) +
                         low - LO_SURROGATE_START + SURROGATES_START;
-                    glyphs[glyphStart + i] = getGlyphCode(code);
+
+                    if (isIVS(code) && i > 0 &&
+ ((codeWasSurrogate == 0 && isCJK((int)unicodes[start + i -1])) ||
+                          codeWasSurrogate != 0)) {
+                        int glyph;
+                        if (codeWasSurrogate == 0) {
+ glyph = getGlyphCode((int)unicodes[start + i -1], code); // IVS
+                        } else {
+ glyph = getGlyphCode(codeWasSurrogate, code); // surrogate pair+IVS
+                        }
+                        if (glyph == missingGlyph) {
+                            glyphs[glyphStart + i] = missingGlyph;
+                        } else {
+                            if (codeWasSurrogate == 0) {
+                                glyphs[glyphStart + i - 1] = glyph;
+ glyphs[glyphStart + i] = INVISIBLE_GLYPH_ID;
+                            } else {
+                                glyphs[glyphStart + i - 2] = glyph;
+ glyphs[glyphStart + i - 1] = INVISIBLE_GLYPH_ID; + glyphs[glyphStart + i] = INVISIBLE_GLYPH_ID;
+                            }
+                        }
+                        codeWasSurrogate = 0;
+                    } else { // surrogate pair
+                        glyphs[glyphStart + i] = getGlyphCode(code, 0);
+                        if (isIVS(code) == false) {
+ codeWasSurrogate = code; // store surrogate pair
+                        }
+                    }
+
                     i += 1; // Empty glyph slot after surrogate
                     glyphs[glyphStart + i] = INVISIBLE_GLYPH_ID;
                     continue;
                 }
+            } else if (isSVS(code) && i > 0 &&
+ ((codeWasSurrogate == 0 && isCJK((int)unicodes[start + i -1])) ||
+                         codeWasSurrogate != 0)) {
+                int glyph;
+                if (codeWasSurrogate == 0) {
+ glyph = getGlyphCode((int)unicodes[start + i -1], code); // SVS
+                } else {
+ glyph = getGlyphCode(codeWasSurrogate, code); // surrogate pair+SVS
+                }
+                if (glyph == missingGlyph) {
+                    glyphs[glyphStart + i] = missingGlyph;
+                } else {
+                    if (codeWasSurrogate == 0) {
+                        glyphs[glyphStart + i - 1] = glyph;
+                        glyphs[glyphStart + i] = INVISIBLE_GLYPH_ID;
+                    } else {
+                        glyphs[glyphStart + i - 2] = glyph;
+                        glyphs[glyphStart + i - 1] = INVISIBLE_GLYPH_ID;
+                        glyphs[glyphStart + i] = INVISIBLE_GLYPH_ID;
+                    }
+                }
+                codeWasSurrogate = 0;
+                continue;
             }
-            glyphs[glyphStart + i] = getGlyphCode(code);
+
+            glyphs[glyphStart + i] = getGlyphCode(code, 0);
+            codeWasSurrogate = 0;
         }
     }

diff -r 284d06bb1364 modules/javafx.graphics/src/main/java/com/sun/javafx/font/CompositeGlyphMapper.java --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/font/CompositeGlyphMapper.java Tue Jun 12 14:40:17 2018 +0530 +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/font/CompositeGlyphMapper.java Wed Jun 13 14:52:07 2018 +0900
@@ -31,6 +31,7 @@

     public static final int SLOTMASK =  0xff000000;
     public static final int GLYPHMASK = 0x00ffffff;
+    public static final long LONGMASK = 0x00000000ffffffffL;

     public static final int NBLOCKS = 216;
     public static final int BLOCKSZ = 256;
@@ -54,11 +55,17 @@
      * the caching ? So a variety of strategies are possible.
      */
     HashMap<Integer, Integer> glyphMap;
+    HashMap<Long, Integer> glyphMapVS; // HashMap for Variation Selector
+
+    public static long shiftVS_for_HashMap(int code) {
+        return (long)code << 32;
+    }

     public CompositeGlyphMapper(CompositeFontResource compFont) {
         font = compFont;
         missingGlyph = 0; // TrueType font standard, avoids lookup.
         glyphMap = new HashMap<Integer, Integer>();
+        glyphMapVS = new HashMap<Long, Integer>();
         slotMappers = new CharToGlyphMapper[compFont.getNumSlots()];
         asciiCacheOK = true;
     }
@@ -90,17 +97,35 @@
         return ((slot) << 24 | (glyphCode & GLYPHMASK));
     }

-    private final int convertToGlyph(int unicode) {
+    public static final int compGlyphToSlot(int compGlyphCode) {
+        return (compGlyphCode >> 24);
+    }
+
+    public static final int compGlyphToGlyph(int compGlyphCode) {
+        return (compGlyphCode & GLYPHMASK);
+    }
+
+    private final int convertToGlyph(int unicode, int vs) {
         for (int slot = 0; slot < font.getNumSlots(); slot++) {
             CharToGlyphMapper mapper = getSlotMapper(slot);
-            int glyphCode = mapper.charToGlyph(unicode);
+            int glyphCode = mapper.charToGlyph(unicode, vs);
+
             if (glyphCode != mapper.getMissingGlyphCode()) {
                 glyphCode = compositeGlyphCode(slot, glyphCode);
-                glyphMap.put(unicode, glyphCode);
+                if (vs == 0 || CharToGlyphMapper.isVS(vs) == false) {
+                    glyphMap.put(unicode, glyphCode);
+                } else {
+ glyphMapVS.put(shiftVS_for_HashMap(vs) | (unicode & LONGMASK), glyphCode);
+                }
                 return glyphCode;
             }
         }
-        glyphMap.put(unicode, missingGlyph);
+        if (vs == 0 || CharToGlyphMapper.isVS(vs) == false) {
+            glyphMap.put(unicode, missingGlyph);
+        } else {
+ glyphMapVS.put(shiftVS_for_HashMap(vs) | (unicode & LONGMASK), missingGlyph);
+        }
+
         return missingGlyph;
     }

@@ -137,18 +162,22 @@
         return charToGlyph[index];
     }

-    public int getGlyphCode(int charCode) {
+    public int getGlyphCode(int charCode, int vs) {
         // If ASCII then array lookup, else use glyphMap
         int retVal = getAsciiGlyphCode(charCode);
         if (retVal >= 0) {
             return retVal;
         }
-
-        Integer codeInt = glyphMap.get(charCode);
+        Integer codeInt;
+        if (vs == 0 || CharToGlyphMapper.isVS(vs) == false) {
+            codeInt = glyphMap.get(charCode);
+        } else {
+ codeInt = glyphMapVS.get(shiftVS_for_HashMap(vs) | (charCode & LONGMASK));
+        }
         if (codeInt != null) {
             return codeInt.intValue();
         } else {
-            return convertToGlyph(charCode);
+            return convertToGlyph(charCode, vs);
         }
     }
 }
diff -r 284d06bb1364 modules/javafx.graphics/src/main/java/com/sun/javafx/font/OpenTypeGlyphMapper.java --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/font/OpenTypeGlyphMapper.java Tue Jun 12 14:40:17 2018 +0530 +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/font/OpenTypeGlyphMapper.java Wed Jun 13 14:52:07 2018 +0900
@@ -29,11 +29,14 @@

     PrismFontFile font;
     CMap cmap;
+    int offset_format[] = {0}; // offset of format14
+    CMap cmap14;

     public OpenTypeGlyphMapper(PrismFontFile font) {
         this.font = font;
+        offset_format[0] = 0;
         try {
-            cmap = CMap.initialize(font);
+            cmap = CMap.initialize(font, offset_format, -1);
         } catch (Exception e) {
             cmap = null;
         }
@@ -43,13 +46,38 @@
         missingGlyph = 0; /* standard for TrueType fonts */
     }

-    public int getGlyphCode(int charCode) {
-        try {
-            return cmap.getGlyph(charCode);
-        } catch(Exception e) {
-            handleBadCMAP();
-            return missingGlyph;
+    public CMap createCMap14() {
+        if (cmap14 == null && offset_format[0] != 0) {
+            try {
+                cmap14 = CMap.initialize(font, offset_format, 14);
+            } catch (Exception e) {
+                cmap14 = null;
+            }
+            if (cmap14 != null) {
+                cmap14.setDefCMap(this.cmap);
+            }
+            offset_format[0] = 0;
         }
+        return cmap14;
+    }
+
+    public int getGlyphCode(int charCode, int vs) {
+        if (vs == 0) {
+            try {
+                return cmap.getGlyph(charCode);
+            } catch(Exception e) {
+                handleBadCMAP();
+                return missingGlyph;
+            }
+        } else if (createCMap14() != null) {
+            try {
+                return cmap14.getGlyph(charCode, vs);
+            } catch(Exception e) {
+                handleBadCMAP14();
+                return missingGlyph;
+            }
+        }
+        return missingGlyph;
     }

     private void handleBadCMAP() {
@@ -57,6 +85,10 @@
         cmap = CMap.theNullCmap;
     }

+    private void handleBadCMAP14() {
+        cmap14 = CMap.theNullCmap;
+    }
+
     /* A pretty good heuristic is that the cmap we are using
      * supports 32 bit character codes.
      */
diff -r 284d06bb1364 modules/javafx.graphics/src/main/java/com/sun/javafx/font/directwrite/DWGlyph.java --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/font/directwrite/DWGlyph.java Tue Jun 12 14:40:17 2018 +0530 +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/font/directwrite/DWGlyph.java Wed Jun 13 14:52:07 2018 +0900
@@ -52,6 +52,7 @@
     private static D2D1_COLOR_F WHITE = new D2D1_COLOR_F(1f, 1f, 1f, 1f);
private static D2D1_MATRIX_3X2_F D2D2_MATRIX_IDENTITY = new D2D1_MATRIX_3X2_F(1,0, 0,1, 0,0);

+    static final int intMask = 0x0000ffff;

     DWGlyph(DWFontStrike strike, int glyphCode, boolean drawShapes) {
         this.strike = strike;
@@ -303,12 +304,12 @@

     @Override
     public int getGlyphCode() {
-        return run.glyphIndices;
+        return ((int)run.glyphIndices & intMask);
     }

     @Override
     public RectBounds getBBox() {
-        return strike.getBBox(run.glyphIndices);
+        return strike.getBBox((int)run.glyphIndices & intMask);
     }

     @Override
@@ -321,7 +322,7 @@

     @Override
     public Shape getShape() {
-        return strike.createGlyphOutline(run.glyphIndices);
+        return strike.createGlyphOutline((int)run.glyphIndices & intMask);
     }

     @Override
diff -r 284d06bb1364 modules/javafx.graphics/src/main/java/com/sun/javafx/font/directwrite/DWGlyphLayout.java --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/font/directwrite/DWGlyphLayout.java Tue Jun 12 14:40:17 2018 +0530 +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/font/directwrite/DWGlyphLayout.java Wed Jun 13 14:52:07 2018 +0900
@@ -138,6 +138,7 @@
         int i, j;
         int[] iglyphs = new int[glyphCount];
         int slotMask = slot << 24;
+        final int intMask = 0x0000ffff;
         boolean missingGlyph = false;
         i = 0; j = rtl ? glyphCount - 1 : 0;
         while (i < glyphCount) {
@@ -145,7 +146,7 @@
                 missingGlyph = true;
                 if (composite) break;
             }
-            iglyphs[i] = glyphs[j] | slotMask;
+            iglyphs[i] = ((int)glyphs[j] & intMask) | slotMask;
             i++;
             j+=step;
         }
diff -r 284d06bb1364 modules/javafx.graphics/src/main/java/com/sun/javafx/text/ScriptMapper.java --- a/modules/javafx.graphics/src/main/java/com/sun/javafx/text/ScriptMapper.java Tue Jun 12 14:40:17 2018 +0530 +++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/text/ScriptMapper.java Wed Jun 13 14:52:07 2018 +0900
@@ -154,6 +154,9 @@
         else if (code <= 0x17ff) { // 1780 - 17FF Khmer
             return true;
         }
+        else if (code <= 0x18af) { // 1800 - 18AF Mongolian (including FVS)
+            return true;
+        }
         else if (code < 0x200c) {
             return false;
         }
diff -r 284d06bb1364 modules/javafx.graphics/src/main/java/com/sun/prism/sw/SWGraphics.java --- a/modules/javafx.graphics/src/main/java/com/sun/prism/sw/SWGraphics.java Tue Jun 12 14:40:17 2018 +0530 +++ b/modules/javafx.graphics/src/main/java/com/sun/prism/sw/SWGraphics.java Wed Jun 13 14:52:07 2018 +0900
@@ -62,6 +62,8 @@
 import com.sun.prism.paint.ImagePattern;
 import com.sun.prism.paint.Paint;

+import com.sun.javafx.font.CharToGlyphMapper;
+
 final class SWGraphics implements ReadbackGraphics {

     private static final BasicStroke DEFAULT_STROKE =
@@ -630,6 +632,9 @@

         final Glyph g = strike.getGlyph(gl.getGlyphCode(idx));
         if (drawAsMasks) {
+            if (g.getGlyphCode() == CharToGlyphMapper.INVISIBLE_GLYPH_ID) {
+                return;
+            }
final Point2D pt = new Point2D((float)(x + tx.getMxt() + gl.getPosX(idx)), (float)(y + tx.getMyt() + gl.getPosY(idx)));
             int subPixel = strike.getQuantizedPosition(pt);






====================
Sample (kami.java)
====================
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;

public class kami extends Application {

  @Override
  public void start(Stage stage) throws Exception {

    // You need to install ipamjm font
    String family = "IPAmjMincho"; // for Linux
//    String family = "IPAmj明朝"; // for Windows

    Text text[] = new Text[3];
    text[0] = new Text("\u795E+VS1 --> \u795E\uFE00\n"); // FVS
    text[1] = new Text("\u795E+VS20 --> \u795E\uDB40\uDD03\n"); // IVS
text[2] = new Text("\uD87A\uDF79+VS17 --> \uD87A\uDF79\uDB40\uDD01\n"); // Surrogate Pair+IVS

    for (int i=0; i<3; i++) {
      text[i].setFill(Color.BLACK);
      text[i].setFont(Font.font(family, 48));
    }
    TextFlow textFlow = new TextFlow(text[0], text[1], text[2]);
    textFlow.setLayoutX(60);
    textFlow.setLayoutY(60);

    Group group = new Group(textFlow);
    Scene scene = new Scene(group, 450, 250, Color.WHITE);
    stage.setScene(scene);
    stage.show();
  }
}





====================
Sample (kami2.java)
====================
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.scene.text.Text;
import javafx.scene.text.Font;

public class kami2 extends Application {
  public static void main(String[] args) {
    launch(args);
  }
  @Override
  public void start(Stage stage) {
    // You need to install ipamjm font
    String family = "IPAmjMincho"; // for Linux
//    String family = "IPAmj明朝"; // for Windows

    Scene scene = new Scene(new Group(), 650, 300);

    String str[] = new String[3];
    str[0] = new String("\u795E+VS1 --> \u795E\uFE00\n"); // FVS
    str[1] = new String("\u795E+VS20 --> \u795E\uDB40\uDD03\n"); // IVS
str[2] = new String("\uD87A\uDF79+VS17 --> \uD87A\uDF79\uDB40\uDD01\n"); // Surrogate Pair+IVS

    String str_for_area = new String("");
    for (int i=0; i<3; i++) {
      str_for_area += str[i].toString();
    }

    TextArea area = new TextArea(str_for_area);
    area.setFont(Font.font(family, 48));
    area.setPrefWidth(600);
    area.setPrefHeight(250);
    area.setPrefColumnCount(3);

    GridPane grid = new GridPane();
    grid.setVgap(4);
    grid.setHgap(10);
    grid.setPadding(new Insets(5, 5, 5, 5));
    grid.add(area, 1, 0);

    Group root = (Group) scene.getRoot();
    root.getChildren().add(grid);
    stage.setScene(scene);
    stage.show();
  }
}



====================
Sample (mongol.java)
====================
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;

public class mongol extends Application {

  @Override
  public void start(Stage stage) throws Exception {

    // http://www.mongolfont.com/en/font/mnglartotf.html
    String family = "Mongolian Art";
    double size = 48;

    // Correct mongolian form
    // http://www.unicode.org/versions/Unicode10.0.0/ch13.pdf#G27803
    Text text[] = new Text[9];
    text[0] = new Text("ᠤ ᠷ ᠲ ᠤ   --> ᠤᠷᠲᠤ (urtu)\n");
    text[1] = new Text("ᠣ ᠷ ᠳ ᠤ   --> ᠣᠷᠳᠤ (ordu)\n");
    text[2] = new Text("ᠡ ᠨ ᠳ ᠡ   --> ᠡᠨᠳᠡ (ende)\n");
    text[3] = new Text("ᠠ ᠳ ᠠ     --> ᠠᠳᠠ  (ada)\n");
    text[4] = new Text("ᠠ ᠪ ᠤ   --> ᠠᠪᠤ (abu)\n");
    text[5] = new Text("ᠣ ᠳ ᠣ   --> ᠣᠳᠣ (odo)\n");
    text[6] = new Text("ᠡ ᠨ ᠡ   --> ᠡᠨᠡ (ene)\n");
    text[7] = new Text("ᠭ ᠠ  --> ᠭᠠ (gal)\n");
    text[8] = new Text("ᠭ᠋ ᠠ  --> ᠭ᠋ᠠ (gal+U+180B)\n");

    for (int i=0; i<9; i++) {
      text[i].setFill(Color.BLACK);
      text[i].setFont(Font.font(family, size));
    }
TextFlow textFlow = new TextFlow(text[0], text[1], text[2], text[3], text[4], text[5], text[6], text[7], text[8]);
    textFlow.setLayoutX(60);
    textFlow.setLayoutY(60);

    Group group = new Group(textFlow);
    Scene scene = new Scene(group, 600, 650, Color.WHITE);
    stage.setScene(scene);
    stage.show();
  }
}




====================
Sample (NG.java)
====================
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;

// Run on Windows, then Java abort because of bug.
public class NG extends Application {
  @Override
  public void start(Stage stage) throws Exception {

    String family = "Arial Unicode MS";
    double size = 36;

    TextFlow textFlow = new TextFlow();
    textFlow.setLayoutX(60);
    textFlow.setLayoutY(60);

                                  // Unicode(GlyphID)
    Text text = new Text("힣฿");  // U+2F9D4(49496) + U+0E3F(1262)
    /* Inside JavaFX, 49496(Uint16) is handled as -16040(short).
     * By ScriptMapper.isComplexCharCode(), U+0E3F is handled as complex.
     * When in condition with minus glyphID value and complex
     * , JavaFX is forcibly terminated.
     *     (java.lang.ArrayIndexOutOfBoundsException)
     */

    text.setFill(Color.GREEN);
    text.setFont(Font.font(family, size));
    textFlow.getChildren().addAll(text);

    Group group = new Group(textFlow);
    Scene scene = new Scene(group, 1200, 300, Color.WHITE);
    stage.setScene(scene);
    stage.show();
  }
}




--------------------------------------
Name: Akira Nakajima
E-Mail: nakajima.ak...@nttcom.co.jp
--------------------------------------

Reply via email to