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