116 } 117 return mapper; 118 } 119 120 private int convertToGlyph(int unicode) { 121 122 for (int slot = 0; slot < font.numSlots; slot++) { 123 if (!hasExcludes || !font.isExcludedChar(slot, unicode)) { 124 CharToGlyphMapper mapper = getSlotMapper(slot); 125 int glyphCode = mapper.charToGlyph(unicode); 126 if (glyphCode != mapper.getMissingGlyphCode()) { 127 glyphCode = compositeGlyphCode(slot, glyphCode); 128 setCachedGlyphCode(unicode, glyphCode); 129 return glyphCode; 130 } 131 } 132 } 133 return missingGlyph; 134 } 135 136 public int getNumGlyphs() { 137 int numGlyphs = 0; 138 /* The number of glyphs in a composite is affected by 139 * exclusion ranges and duplicates (ie the same code point is 140 * mapped by two different fonts) and also whether or not to 141 * count fallback fonts. A nearly correct answer would be very 142 * expensive to generate. A rough ballpark answer would 143 * just count the glyphs in all the slots. However this would 144 * initialize mappers for all slots when they aren't necessarily 145 * needed. For now just use the first slot as JDK 1.4 did. 146 */ 147 for (int slot=0; slot<1 /*font.numSlots*/; slot++) { 148 CharToGlyphMapper mapper = slotMappers[slot]; 149 if (mapper == null) { 150 mapper = font.getSlotFont(slot).getMapper(); 151 slotMappers[slot] = mapper; 152 } 153 numGlyphs += mapper.getNumGlyphs(); 154 } 155 return numGlyphs; 188 * returns true if it does. A caller of this method should be expecting 189 * to check the return type because it needs to know how to handle 190 * the character data for display. 191 */ 192 public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) { 193 194 for (int i=0; i<count; i++) { 195 int code = unicodes[i]; // char is unsigned. 196 197 if (code >= HI_SURROGATE_START && 198 code <= HI_SURROGATE_END && i < count - 1) { 199 char low = unicodes[i + 1]; 200 201 if (low >= LO_SURROGATE_START && 202 low <= LO_SURROGATE_END) { 203 code = (code - HI_SURROGATE_START) * 204 0x400 + low - LO_SURROGATE_START + 0x10000; 205 glyphs[i + 1] = INVISIBLE_GLYPH_ID; 206 } 207 } 208 209 int gc = glyphs[i] = getCachedGlyphCode(code); 210 if (gc == UNINITIALIZED_GLYPH) { 211 glyphs[i] = convertToGlyph(code); 212 } 213 214 if (code < FontUtilities.MIN_LAYOUT_CHARCODE) { 215 continue; 216 } 217 else if (FontUtilities.isComplexCharCode(code)) { 218 return true; 219 } 220 else if (code >= 0x10000) { 221 i += 1; // Empty glyph slot after surrogate 222 continue; 223 } 224 } 225 226 return false; 227 } 228 229 /* The conversion is not very efficient - looping as it does, converting 230 * one char at a time. However the cache should fill very rapidly. 231 */ 232 public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) { 233 for (int i=0; i<count; i++) { 234 int code = unicodes[i]; // char is unsigned. 235 236 if (code >= HI_SURROGATE_START && 237 code <= HI_SURROGATE_END && i < count - 1) { 238 char low = unicodes[i + 1]; 239 240 if (low >= LO_SURROGATE_START && 241 low <= LO_SURROGATE_END) { 242 code = (code - HI_SURROGATE_START) * 243 0x400 + low - LO_SURROGATE_START + 0x10000; 244 245 int gc = glyphs[i] = getCachedGlyphCode(code); 246 if (gc == UNINITIALIZED_GLYPH) { 247 glyphs[i] = convertToGlyph(code); 248 } 249 i += 1; // Empty glyph slot after surrogate 250 glyphs[i] = INVISIBLE_GLYPH_ID; 251 continue; 252 } 253 } 254 255 int gc = glyphs[i] = getCachedGlyphCode(code); 256 if (gc == UNINITIALIZED_GLYPH) { 257 glyphs[i] = convertToGlyph(code); 258 } 259 } 260 } 261 262 public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) { 263 for (int i=0; i<count; i++) { 264 int code = unicodes[i]; 265 266 glyphs[i] = getCachedGlyphCode(code); 267 if (glyphs[i] == UNINITIALIZED_GLYPH) { 268 glyphs[i] = convertToGlyph(code); 269 } 270 } 271 } 272 273 } | 116 } 117 return mapper; 118 } 119 120 private int convertToGlyph(int unicode) { 121 122 for (int slot = 0; slot < font.numSlots; slot++) { 123 if (!hasExcludes || !font.isExcludedChar(slot, unicode)) { 124 CharToGlyphMapper mapper = getSlotMapper(slot); 125 int glyphCode = mapper.charToGlyph(unicode); 126 if (glyphCode != mapper.getMissingGlyphCode()) { 127 glyphCode = compositeGlyphCode(slot, glyphCode); 128 setCachedGlyphCode(unicode, glyphCode); 129 return glyphCode; 130 } 131 } 132 } 133 return missingGlyph; 134 } 135 136 private int convertToGlyph(int unicode, int variationSelector) { 137 if (variationSelector == 0) { 138 return convertToGlyph(unicode); 139 } 140 for (int slot = 0; slot < font.numSlots; slot++) { 141 if (!hasExcludes || !font.isExcludedChar(slot, unicode)) { 142 CharToGlyphMapper mapper = getSlotMapper(slot); 143 if (mapper instanceof TrueTypeGlyphMapper) { 144 int glyphCode = ((TrueTypeGlyphMapper)mapper). 145 getGlyphOfVS(unicode, variationSelector); 146 if (glyphCode != mapper.getMissingGlyphCode()) { 147 glyphCode = compositeGlyphCode(slot, glyphCode); 148 return glyphCode; 149 } 150 } 151 } 152 } 153 return convertToGlyph(unicode); //retry without Variation Selector 154 } 155 156 public int getNumGlyphs() { 157 int numGlyphs = 0; 158 /* The number of glyphs in a composite is affected by 159 * exclusion ranges and duplicates (ie the same code point is 160 * mapped by two different fonts) and also whether or not to 161 * count fallback fonts. A nearly correct answer would be very 162 * expensive to generate. A rough ballpark answer would 163 * just count the glyphs in all the slots. However this would 164 * initialize mappers for all slots when they aren't necessarily 165 * needed. For now just use the first slot as JDK 1.4 did. 166 */ 167 for (int slot=0; slot<1 /*font.numSlots*/; slot++) { 168 CharToGlyphMapper mapper = slotMappers[slot]; 169 if (mapper == null) { 170 mapper = font.getSlotFont(slot).getMapper(); 171 slotMappers[slot] = mapper; 172 } 173 numGlyphs += mapper.getNumGlyphs(); 174 } 175 return numGlyphs; 208 * returns true if it does. A caller of this method should be expecting 209 * to check the return type because it needs to know how to handle 210 * the character data for display. 211 */ 212 public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) { 213 214 for (int i=0; i<count; i++) { 215 int code = unicodes[i]; // char is unsigned. 216 217 if (code >= HI_SURROGATE_START && 218 code <= HI_SURROGATE_END && i < count - 1) { 219 char low = unicodes[i + 1]; 220 221 if (low >= LO_SURROGATE_START && 222 low <= LO_SURROGATE_END) { 223 code = (code - HI_SURROGATE_START) * 224 0x400 + low - LO_SURROGATE_START + 0x10000; 225 glyphs[i + 1] = INVISIBLE_GLYPH_ID; 226 } 227 } 228 if (isVariationSelector(code)) { 229 return charsToGlyphsNSVS(count, unicodes, glyphs); 230 } 231 232 int gc = glyphs[i] = getCachedGlyphCode(code); 233 if (gc == UNINITIALIZED_GLYPH) { 234 glyphs[i] = convertToGlyph(code); 235 } 236 237 if (code < FontUtilities.MIN_LAYOUT_CHARCODE) { 238 continue; 239 } 240 else if (FontUtilities.isComplexCharCode(code)) { 241 return true; 242 } 243 else if (code >= 0x10000) { 244 i += 1; // Empty glyph slot after surrogate 245 continue; 246 } 247 } 248 249 return false; 250 } 251 252 private boolean charsToGlyphsNSVS(int count, char[] unicodes, 253 int[] glyphs) { 254 255 for (int i = 0; i < count; i++) { 256 int code = unicodes[i]; // char is unsigned. 257 int step = 1; 258 int variationSelector = 0; 259 260 if (code >= HI_SURROGATE_START && 261 code <= HI_SURROGATE_END && i < count - 1) { 262 char low = unicodes[i + 1]; 263 264 if (low >= LO_SURROGATE_START && 265 low <= LO_SURROGATE_END) { 266 code = (code - HI_SURROGATE_START) * 267 0x400 + low - LO_SURROGATE_START + 0x10000; 268 glyphs[i + 1] = INVISIBLE_GLYPH_ID; 269 step = 2; 270 } 271 } 272 273 if (i < count - step && 274 isVariationSelectorBMP(unicodes[i+step]) && 275 isVSBaseChar(code)) { 276 variationSelector = unicodes[i+step]; 277 glyphs[i] = convertToGlyph(code, variationSelector); 278 glyphs[i+step] = INVISIBLE_GLYPH_ID; 279 i += 1; 280 } else if (i < count - step -1 && 281 isVariationSelectorExt(unicodes[i+step], 282 unicodes[i+step+1]) && 283 isVSBaseChar(code)) { 284 variationSelector = (unicodes[i+step] 285 - HI_SURROGATE_START) * 0x400 286 + unicodes[i+step+1] - LO_SURROGATE_START 287 + 0x10000; 288 glyphs[i] = convertToGlyph(code, variationSelector); 289 glyphs[i+step] = INVISIBLE_GLYPH_ID; 290 glyphs[i+step+1] = INVISIBLE_GLYPH_ID; 291 i += 2; 292 } 293 if (variationSelector == 0) { 294 int gc = glyphs[i] = getCachedGlyphCode(code); 295 if (gc == UNINITIALIZED_GLYPH) { 296 glyphs[i] = convertToGlyph(code); 297 } 298 } 299 300 if (code < FontUtilities.MIN_LAYOUT_CHARCODE) { 301 continue; 302 } 303 else if (FontUtilities.isComplexCharCode(code)) { 304 return true; 305 } 306 else if (code >= 0x10000) { 307 i += 1; // Empty glyph slot after surrogate 308 continue; 309 } 310 } 311 312 return false; 313 } 314 315 /* The conversion is not very efficient - looping as it does, converting 316 * one char at a time. However the cache should fill very rapidly. 317 */ 318 public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) { 319 for (int i=0; i<count; i++) { 320 int code = unicodes[i]; // char is unsigned. 321 322 if (code >= HI_SURROGATE_START && 323 code <= HI_SURROGATE_END && i < count - 1) { 324 char low = unicodes[i + 1]; 325 326 if (low >= LO_SURROGATE_START && 327 low <= LO_SURROGATE_END) { 328 code = (code - HI_SURROGATE_START) * 329 0x400 + low - LO_SURROGATE_START + 0x10000; 330 if (isVariationSelector(code)) { 331 charsToGlyphsVS(count, unicodes, glyphs); 332 return; 333 } 334 335 int gc = glyphs[i] = getCachedGlyphCode(code); 336 if (gc == UNINITIALIZED_GLYPH) { 337 glyphs[i] = convertToGlyph(code); 338 } 339 i += 1; // Empty glyph slot after surrogate 340 glyphs[i] = INVISIBLE_GLYPH_ID; 341 continue; 342 } 343 } else if (isVariationSelectorBMP(unicodes[i])) { 344 charsToGlyphsVS(count, unicodes, glyphs); 345 return; 346 } 347 348 int gc = glyphs[i] = getCachedGlyphCode(code); 349 if (gc == UNINITIALIZED_GLYPH) { 350 glyphs[i] = convertToGlyph(code); 351 } 352 } 353 } 354 355 private void charsToGlyphsVS(int count, char[] unicodes, int[] glyphs) { 356 for (int i = 0; i < count; i++) { 357 int code = unicodes[i]; // char is unsigned. 358 int variationSelector = 0; 359 int step = 1; 360 361 if (code >= HI_SURROGATE_START && 362 code <= HI_SURROGATE_END && i < count - 1) { 363 char low = unicodes[i + 1]; 364 365 if (low >= LO_SURROGATE_START && 366 low <= LO_SURROGATE_END) { 367 code = (code - HI_SURROGATE_START) * 368 0x400 + low - LO_SURROGATE_START + 0x10000; 369 370 glyphs[i+1] = INVISIBLE_GLYPH_ID; 371 step = 2; 372 } 373 } 374 375 if (i < count - step && 376 isVariationSelectorBMP(unicodes[i+step]) && 377 isVSBaseChar(code)) { 378 variationSelector = unicodes[i+step]; 379 glyphs[i] = convertToGlyph(code, variationSelector); 380 glyphs[i+step] = INVISIBLE_GLYPH_ID; 381 i += 1; 382 } else if (i < count - step -1 && 383 isVariationSelectorExt(unicodes[i+step], 384 unicodes[i+step+1]) && 385 isVSBaseChar(code)) { 386 variationSelector = (unicodes[i+step] 387 - HI_SURROGATE_START) * 0x400 388 + unicodes[i+step+1] - LO_SURROGATE_START 389 + 0x10000; 390 glyphs[i] = convertToGlyph(code, variationSelector); 391 glyphs[i+step] = INVISIBLE_GLYPH_ID; 392 glyphs[i+step+1] = INVISIBLE_GLYPH_ID; 393 i += 2; 394 } 395 if (variationSelector == 0) { 396 int gc = glyphs[i] = getCachedGlyphCode(code); 397 if (gc == UNINITIALIZED_GLYPH) { 398 glyphs[i] = convertToGlyph(code); 399 } 400 } 401 if (code >= 0x10000) { 402 i++; 403 } 404 } 405 } 406 407 public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) { 408 for (int i=0; i<count; i++) { 409 int code = unicodes[i]; 410 if (isVariationSelector(code)) { 411 charsToGlyphsVS(count, unicodes, glyphs); 412 return; 413 } 414 415 glyphs[i] = getCachedGlyphCode(code); 416 if (glyphs[i] == UNINITIALIZED_GLYPH) { 417 glyphs[i] = convertToGlyph(code); 418 } 419 } 420 } 421 422 private void charsToGlyphsVS(int count, int[] unicodes, int[] glyphs) { 423 for (int i = 0; i < count; i++) { 424 int code = unicodes[i]; 425 426 if (i < count-1 && 427 isVariationSelector(unicodes[i+1]) && 428 isVSBaseChar(code) ) { 429 glyphs[i] = convertToGlyph(code, unicodes[i+1]); 430 glyphs[i+1] = INVISIBLE_GLYPH_ID; 431 i++; 432 } else { 433 glyphs[i] = getCachedGlyphCode(code); 434 if (glyphs[i] == UNINITIALIZED_GLYPH) { 435 glyphs[i] = convertToGlyph(code); 436 } 437 } 438 } 439 } 440 441 } |