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; 176 } 177 178 public int charToGlyph(char unicode) { 179 180 int glyphCode = getCachedGlyphCode(unicode); 181 if (glyphCode == UNINITIALIZED_GLYPH) { 182 glyphCode = convertToGlyph(unicode); 183 } 184 return glyphCode; 185 } 186 187 /* This variant checks if shaping is needed and immediately 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 int glyphCode = missingGlyph; 144 if (mapper.hasVariationSelectorGlyph(unicode, 145 variationSelector)) { 146 int glyphCodes[] = { 0, 0}; 147 int codes[] = {unicode, variationSelector}; 148 mapper.charsToGlyphs(2, codes, glyphCodes); 149 glyphCode = glyphCodes[0]; 150 if (glyphCode != mapper.getMissingGlyphCode()) { 151 glyphCode = compositeGlyphCode(slot, glyphCode); 152 return glyphCode; 153 } 154 } 155 } 156 } 157 return convertToGlyph(unicode); //retry without Variation Selector 158 } 159 160 public int getNumGlyphs() { 161 int numGlyphs = 0; 162 /* The number of glyphs in a composite is affected by 163 * exclusion ranges and duplicates (ie the same code point is 164 * mapped by two different fonts) and also whether or not to 165 * count fallback fonts. A nearly correct answer would be very 166 * expensive to generate. A rough ballpark answer would 167 * just count the glyphs in all the slots. However this would 168 * initialize mappers for all slots when they aren't necessarily 169 * needed. For now just use the first slot as JDK 1.4 did. 170 */ 171 for (int slot=0; slot<1 /*font.numSlots*/; slot++) { 172 CharToGlyphMapper mapper = slotMappers[slot]; 173 if (mapper == null) { 174 mapper = font.getSlotFont(slot).getMapper(); 175 slotMappers[slot] = mapper; 176 } 177 numGlyphs += mapper.getNumGlyphs(); 178 } 179 return numGlyphs; 200 } 201 202 public int charToGlyph(char unicode) { 203 204 int glyphCode = getCachedGlyphCode(unicode); 205 if (glyphCode == UNINITIALIZED_GLYPH) { 206 glyphCode = convertToGlyph(unicode); 207 } 208 return glyphCode; 209 } 210 211 /* This variant checks if shaping is needed and immediately 212 * returns true if it does. A caller of this method should be expecting 213 * to check the return type because it needs to know how to handle 214 * the character data for display. 215 */ 216 public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) { 217 218 for (int i=0; i<count; i++) { 219 int code = unicodes[i]; // char is unsigned. 220 int step = 1; 221 int variationSelector = 0; 222 223 if (code >= HI_SURROGATE_START && 224 code <= HI_SURROGATE_END && i < count - 1) { 225 char low = unicodes[i + 1]; 226 227 if (low >= LO_SURROGATE_START && 228 low <= LO_SURROGATE_END) { 229 code = (code - HI_SURROGATE_START) * 230 0x400 + low - LO_SURROGATE_START + 0x10000; 231 glyphs[i + 1] = INVISIBLE_GLYPH_ID; 232 step = 2; 233 } 234 } 235 236 if (i < count - step && 237 isVariationSelector(unicodes[i+step]) && 238 isBaseChar(code)) { 239 variationSelector = unicodes[i+step]; 240 glyphs[i] = convertToGlyph(code, variationSelector); 241 glyphs[i+step] = INVISIBLE_GLYPH_ID; 242 i += 1; 243 } else if (i < count - step -1 && 244 isVariationSelector(unicodes[i+step], 245 unicodes[i+step+1]) && 246 isBaseChar(code)) { 247 variationSelector = (unicodes[i+step] 248 - HI_SURROGATE_START) * 0x400 249 + unicodes[i+step+1] - LO_SURROGATE_START 250 + 0x10000; 251 glyphs[i] = convertToGlyph(code, variationSelector); 252 glyphs[i+step] = INVISIBLE_GLYPH_ID; 253 glyphs[i+step+1] = INVISIBLE_GLYPH_ID; 254 i += 2; 255 } 256 if (variationSelector == 0) { 257 int gc = glyphs[i] = getCachedGlyphCode(code); 258 if (gc == UNINITIALIZED_GLYPH) { 259 glyphs[i] = convertToGlyph(code); 260 } 261 } 262 263 if (code < FontUtilities.MIN_LAYOUT_CHARCODE) { 264 continue; 265 } 266 else if (FontUtilities.isComplexCharCode(code)) { 267 return true; 268 } 269 else if (code >= 0x10000) { 270 i += 1; // Empty glyph slot after surrogate 271 continue; 272 } 273 } 274 275 return false; 276 } 277 278 /* The conversion is not very efficient - looping as it does, converting 279 * one char at a time. However the cache should fill very rapidly. 280 */ 281 public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) { 282 for (int i=0; i<count; i++) { 283 int code = unicodes[i]; // char is unsigned. 284 int variationSelector = 0; 285 int step = 1; 286 287 if (code >= HI_SURROGATE_START && 288 code <= HI_SURROGATE_END && i < count - 1) { 289 char low = unicodes[i + 1]; 290 291 if (low >= LO_SURROGATE_START && 292 low <= LO_SURROGATE_END) { 293 code = (code - HI_SURROGATE_START) * 294 0x400 + low - LO_SURROGATE_START + 0x10000; 295 296 glyphs[i+1] = INVISIBLE_GLYPH_ID; 297 step = 2; 298 } 299 } 300 301 if (i < count - step && 302 isVariationSelector(unicodes[i+step]) && 303 isBaseChar(code)) { 304 variationSelector = unicodes[i+step]; 305 glyphs[i] = convertToGlyph(code, variationSelector); 306 glyphs[i+step] = INVISIBLE_GLYPH_ID; 307 i += 1; 308 } else if (i < count - step -1 && 309 isVariationSelector(unicodes[i+step], 310 unicodes[i+step+1]) && 311 isBaseChar(code)) { 312 variationSelector = (unicodes[i+step] 313 - HI_SURROGATE_START) * 0x400 314 + unicodes[i+step+1] - LO_SURROGATE_START 315 + 0x10000; 316 glyphs[i] = convertToGlyph(code, variationSelector); 317 glyphs[i+step] = INVISIBLE_GLYPH_ID; 318 glyphs[i+step+1] = INVISIBLE_GLYPH_ID; 319 i += 2; 320 } 321 if (variationSelector == 0) { 322 int gc = glyphs[i] = getCachedGlyphCode(code); 323 if (gc == UNINITIALIZED_GLYPH) { 324 glyphs[i] = convertToGlyph(code); 325 } 326 } 327 if (code >= 0x10000) { 328 i++; 329 } 330 } 331 } 332 333 public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) { 334 for (int i=0; i<count; i++) { 335 int code = unicodes[i]; 336 337 if (i < count-1 338 && isVariationSelector(unicodes[i+1]) 339 && isBaseChar(code) ) { 340 glyphs[i] = convertToGlyph(code, unicodes[i+1]); 341 glyphs[i+1] = INVISIBLE_GLYPH_ID; 342 i++; 343 } else { 344 glyphs[i] = getCachedGlyphCode(code); 345 if (glyphs[i] == UNINITIALIZED_GLYPH) { 346 glyphs[i] = convertToGlyph(code); 347 } 348 } 349 } 350 } 351 352 } |