70
71 public int getNumGlyphs() {
72 return numGlyphs;
73 }
74
75 private char getGlyphFromCMAP(int charCode) {
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;
120 }
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 }
|
70
71 public int getNumGlyphs() {
72 return numGlyphs;
73 }
74
75 private char getGlyphFromCMAP(int charCode) {
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 getGlyphFromCMAPVS(int charCode, int variationSelector) {
97 if (variationSelector == 0) {
98 return getGlyphFromCMAP(charCode);
99 }
100 try {
101 char glyphCode = cmap.getGlyph(charCode, variationSelector, true);
102 if (glyphCode < numGlyphs ||
103 glyphCode >= FileFontStrike.INVISIBLE_GLYPHS) {
104 return glyphCode;
105 } else {
106 if (FontUtilities.isLogging()) {
107 FontUtilities.getLogger().warning
108 (font + " out of range glyph id=" +
109 Integer.toHexString((int)glyphCode) +
110 " for char " + Integer.toHexString(charCode) +
111 " for vs " + Integer.toHexString(variationSelector));
112 }
113 return (char)missingGlyph;
114 }
115 } catch (Exception e) {
116 handleBadCMAP();
117 return (char) missingGlyph;
118 }
119 }
120
121 private void handleBadCMAP() {
122 if (FontUtilities.isLogging()) {
123 FontUtilities.getLogger().severe("Null Cmap for " + font +
124 "substituting for this font");
125 }
126 SunFontManager.getInstance().deRegisterBadFont(font);
127 /* The next line is not really a solution, but might
128 * reduce the exceptions until references to this font2D
129 * are gone.
130 */
131 cmap = CMap.theNullCmap;
132 }
133
134 private char remapJAChar(char unicode) {
135 return (unicode == REVERSE_SOLIDUS) ? JA_YEN : unicode;
145 }
146 int glyph = getGlyphFromCMAP(unicode);
147 if (font.checkUseNatives() && glyph < font.glyphToCharMap.length) {
148 font.glyphToCharMap[glyph] = unicode;
149 }
150 return glyph;
151 }
152
153 public int charToGlyph(int unicode) {
154 if (needsJAremapping) {
155 unicode = remapJAIntChar(unicode);
156 }
157 int glyph = getGlyphFromCMAP(unicode);
158 if (font.checkUseNatives() && glyph < font.glyphToCharMap.length) {
159 font.glyphToCharMap[glyph] = (char)unicode;
160 }
161 return glyph;
162 }
163
164 public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) {
165 for (int i = 0; i < count; i++) {
166 if (isVariationSelector(unicodes[i])) {
167 charsToGlyphsVS(count, unicodes, glyphs);
168 return;
169 }
170 if (needsJAremapping) {
171 glyphs[i] = getGlyphFromCMAP(remapJAIntChar(unicodes[i]));
172 } else {
173 glyphs[i] = getGlyphFromCMAP(unicodes[i]);
174 }
175 if (font.checkUseNatives() &&
176 glyphs[i] < font.glyphToCharMap.length) {
177 font.glyphToCharMap[glyphs[i]] = (char)unicodes[i];
178 }
179 }
180 }
181
182 private void charsToGlyphsVS(int count, int[] unicodes, int[] glyphs) {
183 for (int i = 0; i < count; i++) {
184 if (i < count - 1 &&
185 isVariationSelector(unicodes[i + 1]) &&
186 isVSBaseChar(unicodes[i])) {
187 if (needsJAremapping) {
188 glyphs[i] = getGlyphFromCMAPVS(remapJAIntChar(unicodes[i]),
189 unicodes[i + 1]);
190 } else {
191 glyphs[i] = getGlyphFromCMAPVS(unicodes[i],
192 unicodes[i + 1]);
193 }
194 i++;
195 glyphs[i] = INVISIBLE_GLYPH_ID;
196 } else {
197 if (needsJAremapping) {
198 glyphs[i] = getGlyphFromCMAP(remapJAIntChar(unicodes[i]));
199 } else {
200 glyphs[i] = getGlyphFromCMAP(unicodes[i]);
201 }
202 if (font.checkUseNatives() &&
203 glyphs[i] < font.glyphToCharMap.length) {
204 font.glyphToCharMap[glyphs[i]] = (char)unicodes[i];
205 }
206 }
207 }
208 }
209
210 public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) {
211
212 for (int i = 0; i < count; i++) {
213 int code;
214 if (needsJAremapping) {
215 code = remapJAChar(unicodes[i]);
216 } else {
217 code = unicodes[i]; // char is unsigned.
218 }
219
220 if (code >= HI_SURROGATE_START &&
221 code <= HI_SURROGATE_END && i < count - 1) {
222 char low = unicodes[i + 1];
223
224 if (low >= LO_SURROGATE_START &&
225 low <= LO_SURROGATE_END) {
226 code = (code - HI_SURROGATE_START) *
227 0x400 + low - LO_SURROGATE_START + 0x10000;
228
229 if (isVariationSelector(code)) {
230 charsToGlyphsVS(count, unicodes, glyphs);
231 return;
232 }
233 glyphs[i] = getGlyphFromCMAP(code);
234 i += 1; // Empty glyph slot after surrogate
235 glyphs[i] = INVISIBLE_GLYPH_ID;
236 continue;
237 }
238 } else if (isVariationSelectorBMP(unicodes[i])) {
239 charsToGlyphsVS(count, unicodes, glyphs);
240 return;
241 }
242 glyphs[i] = getGlyphFromCMAP(code);
243
244 if (font.checkUseNatives() &&
245 glyphs[i] < font.glyphToCharMap.length) {
246 font.glyphToCharMap[glyphs[i]] = (char)code;
247 }
248
249 }
250 }
251
252 private void charsToGlyphsVS(int count, char[] unicodes, int[] glyphs) {
253 for (int i = 0; i < count; i++) {
254 int code;
255 int variationSelector = 0;
256 int step = 1;
257 if (needsJAremapping) {
258 code = remapJAChar(unicodes[i]);
259 } else {
260 code = unicodes[i]; // char is unsigned.
261 }
262
263 if (code >= HI_SURROGATE_START &&
264 code <= HI_SURROGATE_END && i < count - 1) {
265 char low = unicodes[i + 1];
266
267 if (low >= LO_SURROGATE_START &&
268 low <= LO_SURROGATE_END) {
269 code = (code - HI_SURROGATE_START) *
270 0x400 + low - LO_SURROGATE_START + 0x10000;
271
272 glyphs[i + 1] = INVISIBLE_GLYPH_ID;
273 step = 2;
274 }
275 }
276 if (i < count - step &&
277 isVariationSelectorBMP(unicodes[i + step]) &&
278 isVSBaseChar(code)) {
279 variationSelector = unicodes[i + step];
280 glyphs[i] = getGlyphFromCMAPVS(code, variationSelector);
281 glyphs[i+step] = INVISIBLE_GLYPH_ID;
282 i += 1;
283 } else if (i < count - step -1 &&
284 isVariationSelectorExt(unicodes[i + step],
285 unicodes[i + step + 1]) &&
286 isVSBaseChar(code)) {
287 variationSelector = (unicodes[i + step] - HI_SURROGATE_START)
288 * 0x400 + unicodes[i + step + 1]
289 - LO_SURROGATE_START + 0x10000;
290 glyphs[i] = getGlyphFromCMAPVS(code, variationSelector);
291 glyphs[i + step] = INVISIBLE_GLYPH_ID;
292 glyphs[i + step + 1] = INVISIBLE_GLYPH_ID;
293 i += 2;
294 }
295 if (variationSelector == 0) {
296 glyphs[i] = getGlyphFromCMAP(code);
297
298 if (font.checkUseNatives() &&
299 glyphs[i] < font.glyphToCharMap.length) {
300 font.glyphToCharMap[glyphs[i]] = (char)code;
301 }
302 }
303 if (code >= 0x10000) {
304 i++;
305 }
306
307 }
308 }
309
310 /* This variant checks if shaping is needed and immediately
311 * returns true if it does. A caller of this method should be expecting
312 * to check the return type because it needs to know how to handle
313 * the character data for display.
314 */
315 public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) {
316
317 for (int i = 0; i < count; i++) {
318 int code;
319 if (needsJAremapping) {
320 code = remapJAChar(unicodes[i]);
321 } else {
322 code = unicodes[i]; // char is unsigned.
323 }
324
325 if (code >= HI_SURROGATE_START &&
326 code <= HI_SURROGATE_END && i < count - 1) {
327 char low = unicodes[i + 1];
328
329 if (low >= LO_SURROGATE_START &&
330 low <= LO_SURROGATE_END) {
331 code = (code - HI_SURROGATE_START) *
332 0x400 + low - LO_SURROGATE_START + 0x10000;
333 glyphs[i + 1] = INVISIBLE_GLYPH_ID;
334 }
335 }
336 if (isVariationSelector(code)) {
337 return charsToGlyphsNSVS(count, unicodes, glyphs);
338 }
339
340 glyphs[i] = getGlyphFromCMAP(code);
341 if (font.checkUseNatives() &&
342 glyphs[i] < font.glyphToCharMap.length) {
343 font.glyphToCharMap[glyphs[i]] = (char)code;
344 }
345
346 if (code < FontUtilities.MIN_LAYOUT_CHARCODE) {
347 continue;
348 }
349 else if (FontUtilities.isComplexCharCode(code)) {
350 return true;
351 }
352 else if (code >= 0x10000) {
353 i += 1; // Empty glyph slot after surrogate
354 continue;
355 }
356 }
357
358 return false;
359 }
360
361 private boolean charsToGlyphsNSVS(int count, char[] unicodes,
362 int[] glyphs) {
363 for (int i = 0; i < count; i++) {
364 int code;
365 int step = 1;
366 int variationSelector = 0;
367 if (needsJAremapping) {
368 code = remapJAChar(unicodes[i]);
369 } else {
370 code = unicodes[i]; // char is unsigned.
371 }
372
373 if (code >= HI_SURROGATE_START &&
374 code <= HI_SURROGATE_END && i < count - 1) {
375 char low = unicodes[i + 1];
376
377 if (low >= LO_SURROGATE_START &&
378 low <= LO_SURROGATE_END) {
379 code = (code - HI_SURROGATE_START) *
380 0x400 + low - LO_SURROGATE_START + 0x10000;
381 glyphs[i + 1] = INVISIBLE_GLYPH_ID;
382 step = 2;
383 }
384 }
385
386 if (i < count - step &&
387 isVariationSelectorBMP(unicodes[i + step]) &&
388 isVSBaseChar(code)) {
389 variationSelector = unicodes[i + step];
390 glyphs[i] = getGlyphFromCMAPVS(code, variationSelector);
391 glyphs[i+step] = INVISIBLE_GLYPH_ID;
392 i += 1;
393 } else if (i < count - step - 1 &&
394 isVariationSelectorExt(unicodes[i + step],
395 unicodes[i + step + 1]) &&
396 isVSBaseChar(code)) {
397 variationSelector = (unicodes[i + step] - HI_SURROGATE_START)
398 * 0x400 + unicodes[i + step + 1]
399 - LO_SURROGATE_START + 0x10000;
400 glyphs[i] = getGlyphFromCMAPVS(code, variationSelector);
401 glyphs[i + step] = INVISIBLE_GLYPH_ID;
402 glyphs[i + step + 1] = INVISIBLE_GLYPH_ID;
403 i += 2;
404 }
405 if (variationSelector == 0) {
406 glyphs[i] = getGlyphFromCMAP(code);
407 if (font.checkUseNatives() &&
408 glyphs[i] < font.glyphToCharMap.length) {
409 font.glyphToCharMap[glyphs[i]] = (char)code;
410 }
411 }
412
413 if (code < FontUtilities.MIN_LAYOUT_CHARCODE) {
414 continue;
415 }
416 else if (FontUtilities.isComplexCharCode(code)) {
417 return true;
418 }
419 else if (code >= 0x10000) {
420 i += 1; // Empty glyph slot after surrogate
421 continue;
422 }
423 }
424
425 return false;
426 }
427
428 /* A pretty good heuristic is that the cmap we are using
429 * supports 32 bit character codes.
430 */
431 boolean hasSupplementaryChars() {
432 return
433 cmap instanceof CMap.CMapFormat8 ||
434 cmap instanceof CMap.CMapFormat10 ||
435 cmap instanceof CMap.CMapFormat12;
436 }
437
438 int getGlyphOfVS(int charCode, int variationSelector) {
439 return cmap.getGlyph(charCode, variationSelector, false);
440 }
441 }
|