76 try { 77 char glyphCode = cmap.getGlyph(charCode); 78 if (glyphCode < numGlyphs || 79 glyphCode >= FileFontStrike.INVISIBLE_GLYPHS) { 80 return glyphCode; 81 } else { 82 if (FontUtilities.isLogging()) { 83 FontUtilities.getLogger().warning 84 (font + " out of range glyph id=" + 85 Integer.toHexString((int)glyphCode) + 86 " for char " + Integer.toHexString(charCode)); 87 } 88 return (char)missingGlyph; 89 } 90 } catch(Exception e) { 91 handleBadCMAP(); 92 return (char) missingGlyph; 93 } 94 } 95 96 private void handleBadCMAP() { 97 if (FontUtilities.isLogging()) { 98 FontUtilities.getLogger().severe("Null Cmap for " + font + 99 "substituting for this font"); 100 } 101 SunFontManager.getInstance().deRegisterBadFont(font); 102 /* The next line is not really a solution, but might 103 * reduce the exceptions until references to this font2D 104 * are gone. 105 */ 106 cmap = CMap.theNullCmap; 107 } 108 109 private char remapJAChar(char unicode) { 110 return (unicode == REVERSE_SOLIDUS) ? JA_YEN : unicode; 111 } 112 113 private int remapJAIntChar(int unicode) { 114 return (unicode == REVERSE_SOLIDUS) ? JA_YEN : unicode; 115 } 121 int glyph = getGlyphFromCMAP(unicode); 122 if (font.checkUseNatives() && glyph < font.glyphToCharMap.length) { 123 font.glyphToCharMap[glyph] = unicode; 124 } 125 return glyph; 126 } 127 128 public int charToGlyph(int unicode) { 129 if (needsJAremapping) { 130 unicode = remapJAIntChar(unicode); 131 } 132 int glyph = getGlyphFromCMAP(unicode); 133 if (font.checkUseNatives() && glyph < font.glyphToCharMap.length) { 134 font.glyphToCharMap[glyph] = (char)unicode; 135 } 136 return glyph; 137 } 138 139 public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) { 140 for (int i=0;i<count;i++) { 141 if (needsJAremapping) { 142 glyphs[i] = getGlyphFromCMAP(remapJAIntChar(unicodes[i])); 143 } else { 144 glyphs[i] = getGlyphFromCMAP(unicodes[i]); 145 } 146 if (font.checkUseNatives() && 147 glyphs[i] < font.glyphToCharMap.length) { 148 font.glyphToCharMap[glyphs[i]] = (char)unicodes[i]; 149 } 150 } 151 } 152 153 public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) { 154 155 for (int i=0; i<count; i++) { 156 int code; 157 if (needsJAremapping) { 158 code = remapJAChar(unicodes[i]); 159 } else { 160 code = unicodes[i]; // char is unsigned. 161 } 162 163 if (code >= HI_SURROGATE_START && 164 code <= HI_SURROGATE_END && i < count - 1) { 165 char low = unicodes[i + 1]; 166 167 if (low >= LO_SURROGATE_START && 168 low <= LO_SURROGATE_END) { 169 code = (code - HI_SURROGATE_START) * 170 0x400 + low - LO_SURROGATE_START + 0x10000; 171 172 glyphs[i] = getGlyphFromCMAP(code); 173 i += 1; // Empty glyph slot after surrogate 174 glyphs[i] = INVISIBLE_GLYPH_ID; 175 continue; 176 } 177 } 178 glyphs[i] = getGlyphFromCMAP(code); 179 180 if (font.checkUseNatives() && 181 glyphs[i] < font.glyphToCharMap.length) { 182 font.glyphToCharMap[glyphs[i]] = (char)code; 183 } 184 185 } 186 } 187 188 /* This variant checks if shaping is needed and immediately 189 * returns true if it does. A caller of this method should be expecting 190 * to check the return type because it needs to know how to handle 191 * the character data for display. 192 */ 193 public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) { 194 195 for (int i=0; i<count; i++) { 196 int code; 197 if (needsJAremapping) { 198 code = remapJAChar(unicodes[i]); 199 } else { 200 code = unicodes[i]; // char is unsigned. 201 } 202 203 if (code >= HI_SURROGATE_START && 204 code <= HI_SURROGATE_END && i < count - 1) { 205 char low = unicodes[i + 1]; 206 207 if (low >= LO_SURROGATE_START && 208 low <= LO_SURROGATE_END) { 209 code = (code - HI_SURROGATE_START) * 210 0x400 + low - LO_SURROGATE_START + 0x10000; 211 glyphs[i + 1] = INVISIBLE_GLYPH_ID; 212 } 213 } 214 215 glyphs[i] = getGlyphFromCMAP(code); 216 if (font.checkUseNatives() && 217 glyphs[i] < font.glyphToCharMap.length) { 218 font.glyphToCharMap[glyphs[i]] = (char)code; 219 } 220 221 if (code < FontUtilities.MIN_LAYOUT_CHARCODE) { 222 continue; 223 } 224 else if (FontUtilities.isComplexCharCode(code)) { 225 return true; 226 } 227 else if (code >= 0x10000) { 228 i += 1; // Empty glyph slot after surrogate 229 continue; 230 } 231 } 232 233 return false; 234 } 235 236 /* A pretty good heuristic is that the cmap we are using 237 * supports 32 bit character codes. 238 */ 239 boolean hasSupplementaryChars() { 240 return 241 cmap instanceof CMap.CMapFormat8 || 242 cmap instanceof CMap.CMapFormat10 || 243 cmap instanceof CMap.CMapFormat12; 244 } 245 } | 76 try { 77 char glyphCode = cmap.getGlyph(charCode); 78 if (glyphCode < numGlyphs || 79 glyphCode >= FileFontStrike.INVISIBLE_GLYPHS) { 80 return glyphCode; 81 } else { 82 if (FontUtilities.isLogging()) { 83 FontUtilities.getLogger().warning 84 (font + " out of range glyph id=" + 85 Integer.toHexString((int)glyphCode) + 86 " for char " + Integer.toHexString(charCode)); 87 } 88 return (char)missingGlyph; 89 } 90 } catch(Exception e) { 91 handleBadCMAP(); 92 return (char) missingGlyph; 93 } 94 } 95 96 private char getGlyphFromCMAP(int charCode, int variationSelector) { 97 if (variationSelector == 0) { 98 return getGlyphFromCMAP(charCode); 99 } 100 try { 101 char glyphCode = cmap.getGlyph(charCode, variationSelector); 102 if (glyphCode == 0) { // retry without variation selector 103 return getGlyphFromCMAP(charCode); 104 } 105 if (glyphCode < numGlyphs || 106 glyphCode >= FileFontStrike.INVISIBLE_GLYPHS) { 107 return glyphCode; 108 } else { 109 if (FontUtilities.isLogging()) { 110 FontUtilities.getLogger().warning 111 (font + " out of range glyph id=" + 112 Integer.toHexString((int)glyphCode) + 113 " for char " + Integer.toHexString(charCode) + 114 " for vs " + Integer.toHexString(variationSelector)); 115 } 116 return (char)missingGlyph; 117 } 118 } catch(Exception e) { 119 handleBadCMAP(); 120 return (char) missingGlyph; 121 } 122 } 123 124 private void handleBadCMAP() { 125 if (FontUtilities.isLogging()) { 126 FontUtilities.getLogger().severe("Null Cmap for " + font + 127 "substituting for this font"); 128 } 129 SunFontManager.getInstance().deRegisterBadFont(font); 130 /* The next line is not really a solution, but might 131 * reduce the exceptions until references to this font2D 132 * are gone. 133 */ 134 cmap = CMap.theNullCmap; 135 } 136 137 private char remapJAChar(char unicode) { 138 return (unicode == REVERSE_SOLIDUS) ? JA_YEN : unicode; 139 } 140 141 private int remapJAIntChar(int unicode) { 142 return (unicode == REVERSE_SOLIDUS) ? JA_YEN : unicode; 143 } 149 int glyph = getGlyphFromCMAP(unicode); 150 if (font.checkUseNatives() && glyph < font.glyphToCharMap.length) { 151 font.glyphToCharMap[glyph] = unicode; 152 } 153 return glyph; 154 } 155 156 public int charToGlyph(int unicode) { 157 if (needsJAremapping) { 158 unicode = remapJAIntChar(unicode); 159 } 160 int glyph = getGlyphFromCMAP(unicode); 161 if (font.checkUseNatives() && glyph < font.glyphToCharMap.length) { 162 font.glyphToCharMap[glyph] = (char)unicode; 163 } 164 return glyph; 165 } 166 167 public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) { 168 for (int i=0;i<count;i++) { 169 if (i < count - 1 && 170 isVariationSelector(unicodes[i + 1]) && 171 isBaseChar(unicodes[i])) { 172 if (needsJAremapping) { 173 glyphs[i] = getGlyphFromCMAP(remapJAIntChar(unicodes[i]), 174 unicodes[i + 1]); 175 } else { 176 glyphs[i] = getGlyphFromCMAP(unicodes[i], unicodes[i + 1]); 177 } 178 i++; 179 glyphs[i] = INVISIBLE_GLYPH_ID; 180 } else { 181 if (needsJAremapping) { 182 glyphs[i] = getGlyphFromCMAP(remapJAIntChar(unicodes[i])); 183 } else { 184 glyphs[i] = getGlyphFromCMAP(unicodes[i]); 185 } 186 if (font.checkUseNatives() && 187 glyphs[i] < font.glyphToCharMap.length) { 188 font.glyphToCharMap[glyphs[i]] = (char)unicodes[i]; 189 } 190 } 191 } 192 } 193 194 public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) { 195 196 for (int i=0; i<count; i++) { 197 int code; 198 int variationSelector = 0; 199 int step = 1; 200 if (needsJAremapping) { 201 code = remapJAChar(unicodes[i]); 202 } else { 203 code = unicodes[i]; // char is unsigned. 204 } 205 206 if (code >= HI_SURROGATE_START && 207 code <= HI_SURROGATE_END && i < count - 1) { 208 char low = unicodes[i + 1]; 209 210 if (low >= LO_SURROGATE_START && 211 low <= LO_SURROGATE_END) { 212 code = (code - HI_SURROGATE_START) * 213 0x400 + low - LO_SURROGATE_START + 0x10000; 214 215 glyphs[i + 1] = INVISIBLE_GLYPH_ID; 216 step = 2; 217 } 218 } 219 if (i < count - step && 220 isVariationSelector(unicodes[i + step]) && 221 isBaseChar(code)) { 222 variationSelector = unicodes[i + step]; 223 glyphs[i] = getGlyphFromCMAP(code, variationSelector); 224 glyphs[i+step] = INVISIBLE_GLYPH_ID; 225 i += 1; 226 } else if (i < count - step -1 && 227 isVariationSelector(unicodes[i + step], 228 unicodes[i + step + 1]) && 229 isBaseChar(code)) { 230 variationSelector = (unicodes[i + step] - HI_SURROGATE_START) 231 * 0x400 + unicodes[i + step + 1] 232 - LO_SURROGATE_START + 0x10000; 233 glyphs[i] = getGlyphFromCMAP(code, variationSelector); 234 glyphs[i + step] = INVISIBLE_GLYPH_ID; 235 glyphs[i + step + 1] = INVISIBLE_GLYPH_ID; 236 i += 2; 237 } 238 if (variationSelector == 0) { 239 glyphs[i] = getGlyphFromCMAP(code); 240 241 if (font.checkUseNatives() && 242 glyphs[i] < font.glyphToCharMap.length) { 243 font.glyphToCharMap[glyphs[i]] = (char)code; 244 } 245 } 246 if (code >= 0x10000) { 247 i++; 248 } 249 250 } 251 } 252 253 /* This variant checks if shaping is needed and immediately 254 * returns true if it does. A caller of this method should be expecting 255 * to check the return type because it needs to know how to handle 256 * the character data for display. 257 */ 258 public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) { 259 260 for (int i=0; i<count; i++) { 261 int code; 262 int step = 1; 263 int variationSelector = 0; 264 if (needsJAremapping) { 265 code = remapJAChar(unicodes[i]); 266 } else { 267 code = unicodes[i]; // char is unsigned. 268 } 269 270 if (code >= HI_SURROGATE_START && 271 code <= HI_SURROGATE_END && i < count - 1) { 272 char low = unicodes[i + 1]; 273 274 if (low >= LO_SURROGATE_START && 275 low <= LO_SURROGATE_END) { 276 code = (code - HI_SURROGATE_START) * 277 0x400 + low - LO_SURROGATE_START + 0x10000; 278 glyphs[i + 1] = INVISIBLE_GLYPH_ID; 279 step = 2; 280 } 281 } 282 283 if (i < count - step && 284 isVariationSelector(unicodes[i + step]) && 285 isBaseChar(code)) { 286 variationSelector = unicodes[i + step]; 287 glyphs[i] = getGlyphFromCMAP(code, variationSelector); 288 if (glyphs[i] == 0) { //Retry without variation selector 289 glyphs[i] = getGlyphFromCMAP(code); 290 } 291 glyphs[i+step] = INVISIBLE_GLYPH_ID; 292 i += 1; 293 } else if (i < count - step - 1 && 294 isVariationSelector(unicodes[i + step], 295 unicodes[i + step + 1]) && 296 isBaseChar(code)) { 297 variationSelector = (unicodes[i + step] - HI_SURROGATE_START) 298 * 0x400 + unicodes[i + step + 1] 299 - LO_SURROGATE_START + 0x10000; 300 glyphs[i] = getGlyphFromCMAP(code, variationSelector); 301 if (glyphs[i] == 0) { //Retry without variation selector 302 glyphs[i] = getGlyphFromCMAP(code); 303 } 304 glyphs[i + step] = INVISIBLE_GLYPH_ID; 305 glyphs[i + step + 1] = INVISIBLE_GLYPH_ID; 306 i += 2; 307 } 308 if (variationSelector == 0) { 309 glyphs[i] = getGlyphFromCMAP(code); 310 if (font.checkUseNatives() && 311 glyphs[i] < font.glyphToCharMap.length) { 312 font.glyphToCharMap[glyphs[i]] = (char)code; 313 } 314 } 315 316 if (code < FontUtilities.MIN_LAYOUT_CHARCODE) { 317 continue; 318 } 319 else if (FontUtilities.isComplexCharCode(code)) { 320 return true; 321 } 322 else if (code >= 0x10000) { 323 i += 1; // Empty glyph slot after surrogate 324 continue; 325 } 326 } 327 328 return false; 329 } 330 331 /* A pretty good heuristic is that the cmap we are using 332 * supports 32 bit character codes. 333 */ 334 boolean hasSupplementaryChars() { 335 return 336 cmap instanceof CMap.CMapFormat8 || 337 cmap instanceof CMap.CMapFormat10 || 338 cmap instanceof CMap.CMapFormat12; 339 } 340 341 @Override 342 protected boolean hasVariationSelectorGlyph(int charCode, 343 int variationSelector) { 344 return cmap.hasVariationSelectorGlyph(charCode, variationSelector); 345 } 346 } |