< prev index next >

src/java.desktop/share/classes/sun/font/CMap.java

Print this page




 123 
 124     static final short ShiftJISEncoding = 2;
 125     static final short GBKEncoding      = 3;
 126     static final short Big5Encoding     = 4;
 127     static final short WansungEncoding  = 5;
 128     static final short JohabEncoding    = 6;
 129     static final short MSUnicodeSurrogateEncoding = 10;
 130 
 131     static final char noSuchChar = (char)0xfffd;
 132     static final int SHORTMASK = 0x0000ffff;
 133     static final int INTMASK   = 0xffffffff;
 134 
 135     static final char[][] converterMaps = new char[7][];
 136 
 137     /*
 138      * Unicode->other encoding translation array. A pre-computed look up
 139      * which can be shared across all fonts using that encoding.
 140      * Using this saves running character coverters repeatedly.
 141      */
 142     char[] xlat;

 143 
 144     static CMap initialize(TrueTypeFont font) {
 145 
 146         CMap cmap = null;
 147 
 148         int offset, platformID, encodingID=-1;
 149 
 150         int three0=0, three1=0, three2=0, three3=0, three4=0, three5=0,
 151             three6=0, three10=0;

 152         boolean threeStar = false;
 153 
 154         ByteBuffer cmapBuffer = font.getTableBuffer(TrueTypeFont.cmapTag);
 155         int cmapTableOffset = font.getTableSize(TrueTypeFont.cmapTag);
 156         short numberSubTables = cmapBuffer.getShort(2);
 157 
 158         /* locate the offsets of all 3,*  (ie Microsoft platform) encodings */
 159         for (int i=0; i<numberSubTables; i++) {
 160             cmapBuffer.position(i * 8 + 4);
 161             platformID = cmapBuffer.getShort();
 162             if (platformID == 3) {
 163                 threeStar = true;
 164                 encodingID = cmapBuffer.getShort();
 165                 offset     = cmapBuffer.getInt();
 166                 switch (encodingID) {
 167                 case 0:  three0  = offset; break; // MS Symbol encoding
 168                 case 1:  three1  = offset; break; // MS Unicode cmap
 169                 case 2:  three2  = offset; break; // ShiftJIS cmap.
 170                 case 3:  three3  = offset; break; // GBK cmap
 171                 case 4:  three4  = offset; break; // Big 5 cmap
 172                 case 5:  three5  = offset; break; // Wansung
 173                 case 6:  three6  = offset; break; // Johab
 174                 case 10: three10 = offset; break; // MS Unicode surrogates
 175                 }






 176             }
 177         }
 178 
 179         /* This defines the preference order for cmap subtables */
 180         if (threeStar) {
 181             if (three10 != 0) {
 182                 cmap = createCMap(cmapBuffer, three10, null);
 183             }
 184             else if  (three0 != 0) {
 185                 /* The special case treatment of these fonts leads to
 186                  * anomalies where a user can view "wingdings" and "wingdings2"
 187                  * and the latter shows all its code points in the unicode
 188                  * private use area at 0xF000->0XF0FF and the former shows
 189                  * a scattered subset of its glyphs that are known mappings to
 190                  * unicode code points.
 191                  * The primary purpose of these mappings was to facilitate
 192                  * display of symbol chars etc in composite fonts, however
 193                  * this is not needed as all these code points are covered
 194                  * by Lucida Sans Regular.
 195                  * Commenting this out reduces the role of these two files


 245                 else {
 246                     cmap = createCMap(cmapBuffer, three4,
 247                                       getConverterMap(Big5Encoding));
 248                 }
 249             }
 250             else if (three5 != 0) {
 251                 cmap = createCMap(cmapBuffer, three5,
 252                                   getConverterMap(WansungEncoding));
 253             }
 254             else if (three6 != 0) {
 255                 cmap = createCMap(cmapBuffer, three6,
 256                                   getConverterMap(JohabEncoding));
 257             }
 258         } else {
 259             /* No 3,* subtable was found. Just use whatever is the first
 260              * table listed. Not very useful but maybe better than
 261              * rejecting the font entirely?
 262              */
 263             cmap = createCMap(cmapBuffer, cmapBuffer.getInt(8), null);
 264         }




 265         return cmap;
 266     }
 267 
 268     /* speed up the converting by setting the range for double
 269      * byte characters;
 270      */
 271     static char[] getConverter(short encodingID) {
 272         int dBegin = 0x8000;
 273         int dEnd   = 0xffff;
 274         String encoding;
 275 
 276         switch (encodingID) {
 277         case ShiftJISEncoding:
 278             dBegin = 0x8140;
 279             dEnd   = 0xfcfc;
 280             encoding = "SJIS";
 281             break;
 282         case GBKEncoding:
 283             dBegin = 0x8140;
 284             dEnd   = 0xfea0;


 407             subtableLength = buffer.getInt(offset+4) & INTMASK;
 408         }
 409         if (offset+subtableLength > buffer.capacity()) {
 410             if (FontUtilities.isLogging()) {
 411                 FontUtilities.getLogger().warning("Cmap subtable overflows buffer.");
 412             }
 413         }
 414         switch (subtableFormat) {
 415         case 0:  return new CMapFormat0(buffer, offset);
 416         case 2:  return new CMapFormat2(buffer, offset, xlat);
 417         case 4:  return new CMapFormat4(buffer, offset, xlat);
 418         case 6:  return new CMapFormat6(buffer, offset, xlat);
 419         case 8:  return new CMapFormat8(buffer, offset, xlat);
 420         case 10: return new CMapFormat10(buffer, offset, xlat);
 421         case 12: return new CMapFormat12(buffer, offset, xlat);
 422         default: throw new RuntimeException("Cmap format unimplemented: " +
 423                                             (int)buffer.getChar(offset));
 424         }
 425     }
 426 



















 427 /*
 428     final char charVal(byte[] cmap, int index) {
 429         return (char)(((0xff & cmap[index]) << 8)+(0xff & cmap[index+1]));
 430     }
 431 
 432     final short shortVal(byte[] cmap, int index) {
 433         return (short)(((0xff & cmap[index]) << 8)+(0xff & cmap[index+1]));
 434     }
 435 */
 436     abstract char getGlyph(int charCode);
 437 
 438     /* Format 4 Header is
 439      * ushort format (off=0)
 440      * ushort length (off=2)
 441      * ushort language (off=4)
 442      * ushort segCountX2 (off=6)
 443      * ushort searchRange (off=8)
 444      * ushort entrySelector (off=10)
 445      * ushort rangeShift (off=12)
 446      * ushort endCount[segCount] (off=14)


1042     public static final NullCMapClass theNullCmap = new NullCMapClass();
1043 
1044     final int getControlCodeGlyph(int charCode, boolean noSurrogates) {
1045         if (charCode < 0x0010) {
1046             switch (charCode) {
1047             case 0x0009:
1048             case 0x000a:
1049             case 0x000d: return CharToGlyphMapper.INVISIBLE_GLYPH_ID;
1050             }
1051         } else if (charCode >= 0x200c) {
1052             if ((charCode <= 0x200f) ||
1053                 (charCode >= 0x2028 && charCode <= 0x202e) ||
1054                 (charCode >= 0x206a && charCode <= 0x206f)) {
1055                 return CharToGlyphMapper.INVISIBLE_GLYPH_ID;
1056             } else if (noSurrogates && charCode >= 0xFFFF) {
1057                 return 0;
1058             }
1059         }
1060         return -1;
1061     }



















































































1062 }


 123 
 124     static final short ShiftJISEncoding = 2;
 125     static final short GBKEncoding      = 3;
 126     static final short Big5Encoding     = 4;
 127     static final short WansungEncoding  = 5;
 128     static final short JohabEncoding    = 6;
 129     static final short MSUnicodeSurrogateEncoding = 10;
 130 
 131     static final char noSuchChar = (char)0xfffd;
 132     static final int SHORTMASK = 0x0000ffff;
 133     static final int INTMASK   = 0xffffffff;
 134 
 135     static final char[][] converterMaps = new char[7][];
 136 
 137     /*
 138      * Unicode->other encoding translation array. A pre-computed look up
 139      * which can be shared across all fonts using that encoding.
 140      * Using this saves running character coverters repeatedly.
 141      */
 142     char[] xlat;
 143     UVS uvs = null;
 144 
 145     static CMap initialize(TrueTypeFont font) {
 146 
 147         CMap cmap = null;
 148 
 149         int offset, platformID, encodingID=-1;
 150 
 151         int three0=0, three1=0, three2=0, three3=0, three4=0, three5=0,
 152             three6=0, three10=0;
 153         int zero5 = 0; // for Unicode Variation Sequences
 154         boolean threeStar = false;
 155 
 156         ByteBuffer cmapBuffer = font.getTableBuffer(TrueTypeFont.cmapTag);
 157         int cmapTableOffset = font.getTableSize(TrueTypeFont.cmapTag);
 158         short numberSubTables = cmapBuffer.getShort(2);
 159 
 160         /* locate the offsets of all 3,*  (ie Microsoft platform) encodings */
 161         for (int i=0; i<numberSubTables; i++) {
 162             cmapBuffer.position(i * 8 + 4);
 163             platformID = cmapBuffer.getShort();
 164             if (platformID == 3) {
 165                 threeStar = true;
 166                 encodingID = cmapBuffer.getShort();
 167                 offset     = cmapBuffer.getInt();
 168                 switch (encodingID) {
 169                 case 0:  three0  = offset; break; // MS Symbol encoding
 170                 case 1:  three1  = offset; break; // MS Unicode cmap
 171                 case 2:  three2  = offset; break; // ShiftJIS cmap.
 172                 case 3:  three3  = offset; break; // GBK cmap
 173                 case 4:  three4  = offset; break; // Big 5 cmap
 174                 case 5:  three5  = offset; break; // Wansung
 175                 case 6:  three6  = offset; break; // Johab
 176                 case 10: three10 = offset; break; // MS Unicode surrogates
 177                 }
 178             } else if (platformID == 0) {
 179                 encodingID = cmapBuffer.getShort();
 180                 offset     = cmapBuffer.getInt();
 181                 if (encodingID == 5) {
 182                     zero5 = offset;
 183                 } 
 184             }
 185         }
 186 
 187         /* This defines the preference order for cmap subtables */
 188         if (threeStar) {
 189             if (three10 != 0) {
 190                 cmap = createCMap(cmapBuffer, three10, null);
 191             }
 192             else if  (three0 != 0) {
 193                 /* The special case treatment of these fonts leads to
 194                  * anomalies where a user can view "wingdings" and "wingdings2"
 195                  * and the latter shows all its code points in the unicode
 196                  * private use area at 0xF000->0XF0FF and the former shows
 197                  * a scattered subset of its glyphs that are known mappings to
 198                  * unicode code points.
 199                  * The primary purpose of these mappings was to facilitate
 200                  * display of symbol chars etc in composite fonts, however
 201                  * this is not needed as all these code points are covered
 202                  * by Lucida Sans Regular.
 203                  * Commenting this out reduces the role of these two files


 253                 else {
 254                     cmap = createCMap(cmapBuffer, three4,
 255                                       getConverterMap(Big5Encoding));
 256                 }
 257             }
 258             else if (three5 != 0) {
 259                 cmap = createCMap(cmapBuffer, three5,
 260                                   getConverterMap(WansungEncoding));
 261             }
 262             else if (three6 != 0) {
 263                 cmap = createCMap(cmapBuffer, three6,
 264                                   getConverterMap(JohabEncoding));
 265             }
 266         } else {
 267             /* No 3,* subtable was found. Just use whatever is the first
 268              * table listed. Not very useful but maybe better than
 269              * rejecting the font entirely?
 270              */
 271             cmap = createCMap(cmapBuffer, cmapBuffer.getInt(8), null);
 272         }
 273         // For Unicode Variation Sequences
 274         if (cmap != null && zero5 != 0) {
 275             cmap.createUVS(cmapBuffer, zero5);
 276         }
 277         return cmap;
 278     }
 279 
 280     /* speed up the converting by setting the range for double
 281      * byte characters;
 282      */
 283     static char[] getConverter(short encodingID) {
 284         int dBegin = 0x8000;
 285         int dEnd   = 0xffff;
 286         String encoding;
 287 
 288         switch (encodingID) {
 289         case ShiftJISEncoding:
 290             dBegin = 0x8140;
 291             dEnd   = 0xfcfc;
 292             encoding = "SJIS";
 293             break;
 294         case GBKEncoding:
 295             dBegin = 0x8140;
 296             dEnd   = 0xfea0;


 419             subtableLength = buffer.getInt(offset+4) & INTMASK;
 420         }
 421         if (offset+subtableLength > buffer.capacity()) {
 422             if (FontUtilities.isLogging()) {
 423                 FontUtilities.getLogger().warning("Cmap subtable overflows buffer.");
 424             }
 425         }
 426         switch (subtableFormat) {
 427         case 0:  return new CMapFormat0(buffer, offset);
 428         case 2:  return new CMapFormat2(buffer, offset, xlat);
 429         case 4:  return new CMapFormat4(buffer, offset, xlat);
 430         case 6:  return new CMapFormat6(buffer, offset, xlat);
 431         case 8:  return new CMapFormat8(buffer, offset, xlat);
 432         case 10: return new CMapFormat10(buffer, offset, xlat);
 433         case 12: return new CMapFormat12(buffer, offset, xlat);
 434         default: throw new RuntimeException("Cmap format unimplemented: " +
 435                                             (int)buffer.getChar(offset));
 436         }
 437     }
 438 
 439     private void createUVS(ByteBuffer buffer, int offset) {
 440         int subtableFormat = buffer.getChar(offset);
 441         if (subtableFormat == 14) {
 442             long subtableLength = buffer.getInt(offset + 2) & INTMASK;
 443             if (offset + subtableLength > buffer.capacity()) {
 444                 if (FontUtilities.isLogging()) {
 445                     FontUtilities.getLogger()
 446                             .warning("Cmap UVS subtable overflows buffer.");
 447                 }
 448             }
 449             try {
 450                 this.uvs = new UVS(buffer, offset);
 451             } catch (Throwable t) {
 452                 t.printStackTrace();
 453             }
 454         }
 455         return;
 456     }
 457 
 458 /*
 459     final char charVal(byte[] cmap, int index) {
 460         return (char)(((0xff & cmap[index]) << 8)+(0xff & cmap[index+1]));
 461     }
 462 
 463     final short shortVal(byte[] cmap, int index) {
 464         return (short)(((0xff & cmap[index]) << 8)+(0xff & cmap[index+1]));
 465     }
 466 */
 467     abstract char getGlyph(int charCode);
 468 
 469     /* Format 4 Header is
 470      * ushort format (off=0)
 471      * ushort length (off=2)
 472      * ushort language (off=4)
 473      * ushort segCountX2 (off=6)
 474      * ushort searchRange (off=8)
 475      * ushort entrySelector (off=10)
 476      * ushort rangeShift (off=12)
 477      * ushort endCount[segCount] (off=14)


1073     public static final NullCMapClass theNullCmap = new NullCMapClass();
1074 
1075     final int getControlCodeGlyph(int charCode, boolean noSurrogates) {
1076         if (charCode < 0x0010) {
1077             switch (charCode) {
1078             case 0x0009:
1079             case 0x000a:
1080             case 0x000d: return CharToGlyphMapper.INVISIBLE_GLYPH_ID;
1081             }
1082         } else if (charCode >= 0x200c) {
1083             if ((charCode <= 0x200f) ||
1084                 (charCode >= 0x2028 && charCode <= 0x202e) ||
1085                 (charCode >= 0x206a && charCode <= 0x206f)) {
1086                 return CharToGlyphMapper.INVISIBLE_GLYPH_ID;
1087             } else if (noSurrogates && charCode >= 0xFFFF) {
1088                 return 0;
1089             }
1090         }
1091         return -1;
1092     }
1093 
1094     static class UVS {
1095         int numSelectors;
1096         int[] selector;
1097 
1098         //for Non-Default UVS Table
1099         int[] numUVSMapping;
1100         int[][] unicodeValue;
1101         char[][] glyphID;
1102 
1103         UVS(ByteBuffer buffer, int offset) {
1104             numSelectors = buffer.getInt(offset+6);
1105             selector = new int[numSelectors];
1106             numUVSMapping = new int[numSelectors];
1107             unicodeValue = new int[numSelectors][];
1108             glyphID = new char[numSelectors][];
1109 
1110             for (int i = 0; i < numSelectors; i++) {
1111                 buffer.position(offset + 10 + i * 11);
1112                 selector[i] = (buffer.get() & 0xff) << 16; //UINT24
1113                 selector[i] += (buffer.get() & 0xff) << 8;
1114                 selector[i] += buffer.get() & 0xff;
1115 
1116                 //skip Default UVS Table
1117 
1118                 //for Non-Default UVS Table
1119                 int tableOffset = buffer.getInt(offset + 10 + i * 11 + 7);
1120                 if (tableOffset == 0) {
1121                     numUVSMapping[i] = 0;
1122                 } else if (tableOffset > 0) {
1123                     buffer.position(offset+tableOffset);
1124                     numUVSMapping[i] = buffer.getInt() & INTMASK;
1125                     unicodeValue[i] = new int[numUVSMapping[i]];
1126                     glyphID[i] = new char[numUVSMapping[i]];
1127 
1128                     for (int j = 0; j < numUVSMapping[i]; j++) {
1129                         int temp = (buffer.get() & 0xff) << 16; //UINT24
1130                         temp += (buffer.get() & 0xff) << 8;
1131                         temp += buffer.get() & 0xff;
1132                         unicodeValue[i][j] = temp;
1133                         glyphID[i][j] = buffer.getChar();
1134                     }
1135                 }
1136             }
1137         }
1138 
1139         static final int VS_NOGLYPH = 0;
1140         private int getGlyph(int charCode, int variationSelector) {
1141             int targetSelector = -1;
1142             for (int i = 0; i < numSelectors; i++) {
1143                 if (selector[i] == variationSelector) {
1144                     targetSelector = i;
1145                     break;
1146                 }
1147             }
1148             if (targetSelector == -1) {
1149                 return VS_NOGLYPH;
1150             }
1151             if (numUVSMapping[targetSelector] > 0) {
1152                 int index = java.util.Arrays.binarySearch(
1153                                 unicodeValue[targetSelector], charCode);
1154                 if (index >= 0) {
1155                     return glyphID[targetSelector][index];
1156                 }
1157             }
1158             return VS_NOGLYPH;
1159         }
1160     }
1161 
1162     char getVariationGlyph(int charCode, int variationSelector) {
1163         char glyph = 0;
1164         if (uvs == null) {
1165             glyph = getGlyph(charCode);
1166         } else {
1167             int result = uvs.getGlyph(charCode, variationSelector);
1168             if (result > 0) {
1169                 glyph = (char)(result & 0xFFFF);
1170             } else {
1171                 glyph = getGlyph(charCode);
1172             }
1173         }
1174         return glyph;
1175     }
1176 }
< prev index next >