21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.font;
27
28 import java.nio.ByteBuffer;
29 import java.util.Locale;
30
31 public class TrueTypeGlyphMapper extends CharToGlyphMapper {
32
33 static final char REVERSE_SOLIDUS = 0x005c; // the backslash char.
34 static final char JA_YEN = 0x00a5;
35
36 /* if running on Solaris and default Locale is ja_JP then
37 * we map need to remap reverse solidus (backslash) to Yen as
38 * apparently expected there.
39 */
40 static final boolean isJAlocale = Locale.JAPAN.equals(Locale.getDefault());
41 private final boolean needsJAremapping;
42
43 TrueTypeFont font;
44 CMap cmap;
45 int numGlyphs;
46
47 public TrueTypeGlyphMapper(TrueTypeFont font) {
48 this.font = font;
49 try {
50 cmap = CMap.initialize(font);
51 } catch (Exception e) {
52 cmap = null;
53 }
54 if (cmap == null) {
55 handleBadCMAP();
56 }
57 missingGlyph = 0; /* standard for TrueType fonts */
58 ByteBuffer buffer = font.getTableBuffer(TrueTypeFont.maxpTag);
59 if (buffer != null && buffer.capacity() >= 6) {
60 numGlyphs = buffer.getChar(4); // offset 4 bytes in MAXP table.
61 } else {
62 handleBadCMAP();
63 }
64 if (FontUtilities.isSolaris && isJAlocale && font.supportsJA()) {
65 needsJAremapping = true;
66 } else {
67 needsJAremapping = false;
68 }
69 }
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;
124 FontUtilities.getLogger().severe("Null Cmap for " + font +
125 "substituting for this font");
126 }
127 SunFontManager.getInstance().deRegisterBadFont(font);
128 /* The next line is not really a solution, but might
129 * reduce the exceptions until references to this font2D
130 * are gone.
131 */
132 cmap = CMap.theNullCmap;
133 }
134
135 private char remapJAChar(char unicode) {
136 return (unicode == REVERSE_SOLIDUS) ? JA_YEN : unicode;
137 }
138
139 private int remapJAIntChar(int unicode) {
140 return (unicode == REVERSE_SOLIDUS) ? JA_YEN : unicode;
141 }
142
143 public int charToGlyph(char unicode) {
144 if (needsJAremapping) {
145 unicode = remapJAChar(unicode);
146 }
147 int glyph = getGlyphFromCMAP(unicode);
148 if (font.checkUseNatives() && glyph < font.glyphToCharMap.length) {
149 font.glyphToCharMap[glyph] = unicode;
150 }
151 return glyph;
152 }
153
154 public int charToGlyph(int unicode) {
155 if (needsJAremapping) {
156 unicode = remapJAIntChar(unicode);
157 }
158 int glyph = getGlyphFromCMAP(unicode);
159 if (font.checkUseNatives() && glyph < font.glyphToCharMap.length) {
160 font.glyphToCharMap[glyph] = (char)unicode;
161 }
162 return glyph;
163 }
164
165 @Override
166 public int charToVariationGlyph(int unicode, int variationSelector) {
167 if (needsJAremapping) {
168 unicode = remapJAIntChar(unicode);
169 }
170 int glyph = getGlyphFromCMAP(unicode, variationSelector);
171 if (font.checkUseNatives() && glyph < font.glyphToCharMap.length) {
172 font.glyphToCharMap[glyph] = (char)unicode;
173 }
174 return glyph;
175 }
176
177 public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) {
178 for (int i=0;i<count;i++) {
179 if (needsJAremapping) {
180 glyphs[i] = getGlyphFromCMAP(remapJAIntChar(unicodes[i]));
181 } else {
182 glyphs[i] = getGlyphFromCMAP(unicodes[i]);
183 }
184 if (font.checkUseNatives() &&
185 glyphs[i] < font.glyphToCharMap.length) {
186 font.glyphToCharMap[glyphs[i]] = (char)unicodes[i];
187 }
188 }
189 }
190
191 public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) {
192
193 for (int i=0; i<count; i++) {
194 int code;
195 if (needsJAremapping) {
196 code = remapJAChar(unicodes[i]);
197 } else {
198 code = unicodes[i]; // char is unsigned.
199 }
200
201 if (code >= HI_SURROGATE_START &&
202 code <= HI_SURROGATE_END && i < count - 1) {
203 char low = unicodes[i + 1];
204
205 if (low >= LO_SURROGATE_START &&
206 low <= LO_SURROGATE_END) {
207 code = (code - HI_SURROGATE_START) *
208 0x400 + low - LO_SURROGATE_START + 0x10000;
209
210 glyphs[i] = getGlyphFromCMAP(code);
211 i += 1; // Empty glyph slot after surrogate
212 glyphs[i] = INVISIBLE_GLYPH_ID;
213 continue;
214 }
215 }
216 glyphs[i] = getGlyphFromCMAP(code);
217
218 if (font.checkUseNatives() &&
219 glyphs[i] < font.glyphToCharMap.length) {
220 font.glyphToCharMap[glyphs[i]] = (char)code;
221 }
222
223 }
224 }
225
226 /* This variant checks if shaping is needed and immediately
227 * returns true if it does. A caller of this method should be expecting
228 * to check the return type because it needs to know how to handle
229 * the character data for display.
230 */
231 public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) {
232
233 for (int i=0; i<count; i++) {
234 int code;
235 if (needsJAremapping) {
236 code = remapJAChar(unicodes[i]);
237 } else {
238 code = unicodes[i]; // char is unsigned.
239 }
240
241 if (code >= HI_SURROGATE_START &&
242 code <= HI_SURROGATE_END && i < count - 1) {
243 char low = unicodes[i + 1];
244
245 if (low >= LO_SURROGATE_START &&
246 low <= LO_SURROGATE_END) {
247 code = (code - HI_SURROGATE_START) *
248 0x400 + low - LO_SURROGATE_START + 0x10000;
249 glyphs[i + 1] = INVISIBLE_GLYPH_ID;
250 }
251 }
252
253 glyphs[i] = getGlyphFromCMAP(code);
254 if (font.checkUseNatives() &&
255 glyphs[i] < font.glyphToCharMap.length) {
256 font.glyphToCharMap[glyphs[i]] = (char)code;
257 }
258
259 if (code < FontUtilities.MIN_LAYOUT_CHARCODE) {
260 continue;
261 }
262 else if (FontUtilities.isComplexCharCode(code) ||
263 CharToGlyphMapper.isVariationSelector(code)) {
264 return true;
265 }
266 else if (code >= 0x10000) {
267 i += 1; // Empty glyph slot after surrogate
268 continue;
269 }
270 }
271
272 return false;
273 }
274
275 /* A pretty good heuristic is that the cmap we are using
276 * supports 32 bit character codes.
277 */
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.font;
27
28 import java.nio.ByteBuffer;
29 import java.util.Locale;
30
31 public class TrueTypeGlyphMapper extends CharToGlyphMapper {
32
33 static final char REVERSE_SOLIDUS = 0x005c; // the backslash char.
34 static final char JA_YEN = 0x00a5;
35
36 /* if running on Solaris and default Locale is ja_JP then
37 * we map need to remap reverse solidus (backslash) to Yen as
38 * apparently expected there.
39 */
40 static final boolean isJAlocale = Locale.JAPAN.equals(Locale.getDefault());
41
42 TrueTypeFont font;
43 CMap cmap;
44 int numGlyphs;
45
46 public TrueTypeGlyphMapper(TrueTypeFont font) {
47 this.font = font;
48 try {
49 cmap = CMap.initialize(font);
50 } catch (Exception e) {
51 cmap = null;
52 }
53 if (cmap == null) {
54 handleBadCMAP();
55 }
56 missingGlyph = 0; /* standard for TrueType fonts */
57 ByteBuffer buffer = font.getTableBuffer(TrueTypeFont.maxpTag);
58 if (buffer != null && buffer.capacity() >= 6) {
59 numGlyphs = buffer.getChar(4); // offset 4 bytes in MAXP table.
60 } else {
61 handleBadCMAP();
62 }
63 }
64
65 public int getNumGlyphs() {
66 return numGlyphs;
67 }
68
69 private char getGlyphFromCMAP(int charCode) {
70 try {
71 char glyphCode = cmap.getGlyph(charCode);
72 if (glyphCode < numGlyphs ||
73 glyphCode >= FileFontStrike.INVISIBLE_GLYPHS) {
74 return glyphCode;
75 } else {
76 if (FontUtilities.isLogging()) {
77 FontUtilities.getLogger().warning
78 (font + " out of range glyph id=" +
79 Integer.toHexString((int)glyphCode) +
80 " for char " + Integer.toHexString(charCode));
81 }
82 return (char)missingGlyph;
118 FontUtilities.getLogger().severe("Null Cmap for " + font +
119 "substituting for this font");
120 }
121 SunFontManager.getInstance().deRegisterBadFont(font);
122 /* The next line is not really a solution, but might
123 * reduce the exceptions until references to this font2D
124 * are gone.
125 */
126 cmap = CMap.theNullCmap;
127 }
128
129 private char remapJAChar(char unicode) {
130 return (unicode == REVERSE_SOLIDUS) ? JA_YEN : unicode;
131 }
132
133 private int remapJAIntChar(int unicode) {
134 return (unicode == REVERSE_SOLIDUS) ? JA_YEN : unicode;
135 }
136
137 public int charToGlyph(char unicode) {
138 int glyph = getGlyphFromCMAP(unicode);
139 return glyph;
140 }
141
142 public int charToGlyph(int unicode) {
143 int glyph = getGlyphFromCMAP(unicode);
144 return glyph;
145 }
146
147 @Override
148 public int charToVariationGlyph(int unicode, int variationSelector) {
149 int glyph = getGlyphFromCMAP(unicode, variationSelector);
150 return glyph;
151 }
152
153 public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) {
154 for (int i=0;i<count;i++) {
155 glyphs[i] = getGlyphFromCMAP(unicodes[i]);
156 }
157 }
158
159 public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) {
160
161 for (int i=0; i<count; i++) {
162 int code = unicodes[i]; // char is unsigned.
163
164 if (code >= HI_SURROGATE_START &&
165 code <= HI_SURROGATE_END && i < count - 1) {
166 char low = unicodes[i + 1];
167
168 if (low >= LO_SURROGATE_START &&
169 low <= LO_SURROGATE_END) {
170 code = (code - HI_SURROGATE_START) *
171 0x400 + low - LO_SURROGATE_START + 0x10000;
172
173 glyphs[i] = getGlyphFromCMAP(code);
174 i += 1; // Empty glyph slot after surrogate
175 glyphs[i] = INVISIBLE_GLYPH_ID;
176 continue;
177 }
178 }
179 glyphs[i] = getGlyphFromCMAP(code);
180
181 }
182 }
183
184 /* This variant checks if shaping is needed and immediately
185 * returns true if it does. A caller of this method should be expecting
186 * to check the return type because it needs to know how to handle
187 * the character data for display.
188 */
189 public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) {
190
191 for (int i=0; i<count; i++) {
192 int code = unicodes[i]; // char is unsigned.
193
194 if (code >= HI_SURROGATE_START &&
195 code <= HI_SURROGATE_END && i < count - 1) {
196 char low = unicodes[i + 1];
197
198 if (low >= LO_SURROGATE_START &&
199 low <= LO_SURROGATE_END) {
200 code = (code - HI_SURROGATE_START) *
201 0x400 + low - LO_SURROGATE_START + 0x10000;
202 glyphs[i + 1] = INVISIBLE_GLYPH_ID;
203 }
204 }
205
206 glyphs[i] = getGlyphFromCMAP(code);
207
208 if (code < FontUtilities.MIN_LAYOUT_CHARCODE) {
209 continue;
210 }
211 else if (FontUtilities.isComplexCharCode(code) ||
212 CharToGlyphMapper.isVariationSelector(code)) {
213 return true;
214 }
215 else if (code >= 0x10000) {
216 i += 1; // Empty glyph slot after surrogate
217 continue;
218 }
219 }
220
221 return false;
222 }
223
224 /* A pretty good heuristic is that the cmap we are using
225 * supports 32 bit character codes.
226 */
|