History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/font/TrueTypeGlyphMapper.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/font/TrueTypeGlyphMapper.java+269−0
@@ -0,0 +1,269 @@
1+/*
2+ * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
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+ static final char JA_FULLWIDTH_TILDE_CHAR = 0xff5e;
36+ static final char JA_WAVE_DASH_CHAR = 0x301c;
37+
38+ /* if running on Solaris and default Locale is ja_JP then
39+ * we map need to remap reverse solidus (backslash) to Yen as
40+ * apparently expected there.
41+ */
42+ static final boolean isJAlocale = Locale.JAPAN.equals(Locale.getDefault());
43+ private final boolean needsJAremapping;
44+ private boolean remapJAWaveDash;
45+
46+ TrueTypeFont font;
47+ CMap cmap;
48+ int numGlyphs;
49+
50+ public TrueTypeGlyphMapper(TrueTypeFont font) {
51+ this.font = font;
52+ try {
53+ cmap = CMap.initialize(font);
54+ } catch (Exception e) {
55+ cmap = null;
56+ }
57+ if (cmap == null) {
58+ handleBadCMAP();
59+ }
60+ missingGlyph = 0; /* standard for TrueType fonts */
61+ ByteBuffer buffer = font.getTableBuffer(TrueTypeFont.maxpTag);
62+ numGlyphs = buffer.getChar(4); // offset 4 bytes in MAXP table.
63+ if (FontUtilities.isSolaris && isJAlocale && font.supportsJA()) {
64+ needsJAremapping = true;
65+ if (FontUtilities.isSolaris8 &&
66+ getGlyphFromCMAP(JA_WAVE_DASH_CHAR) == missingGlyph) {
67+ remapJAWaveDash = true;
68+ }
69+ } else {
70+ needsJAremapping = false;
71+ }
72+ }
73+
74+ public int getNumGlyphs() {
75+ return numGlyphs;
76+ }
77+
78+ private char getGlyphFromCMAP(int charCode) {
79+ try {
80+ char glyphCode = cmap.getGlyph(charCode);
81+ if (glyphCode < numGlyphs ||
82+ glyphCode >= FileFontStrike.INVISIBLE_GLYPHS) {
83+ return glyphCode;
84+ } else {
85+ if (FontUtilities.isLogging()) {
86+ FontUtilities.getLogger().warning
87+ (font + " out of range glyph id=" +
88+ Integer.toHexString((int)glyphCode) +
89+ " for char " + Integer.toHexString(charCode));
90+ }
91+ return (char)missingGlyph;
92+ }
93+ } catch(Exception e) {
94+ handleBadCMAP();
95+ return (char) missingGlyph;
96+ }
97+ }
98+
99+ private void handleBadCMAP() {
100+ if (FontUtilities.isLogging()) {
101+ FontUtilities.getLogger().severe("Null Cmap for " + font +
102+ "substituting for this font");
103+ }
104+ SunFontManager.getInstance().deRegisterBadFont(font);
105+ /* The next line is not really a solution, but might
106+ * reduce the exceptions until references to this font2D
107+ * are gone.
108+ */
109+ cmap = CMap.theNullCmap;
110+ }
111+
112+ private final char remapJAChar(char unicode) {
113+ switch (unicode) {
114+ case REVERSE_SOLIDUS:
115+ return JA_YEN;
116+ /* This is a workaround for bug 4533422.
117+ * Japanese wave dash missing from Solaris JA TrueType fonts.
118+ */
119+ case JA_WAVE_DASH_CHAR:
120+ if (remapJAWaveDash) {
121+ return JA_FULLWIDTH_TILDE_CHAR;
122+ }
123+ default: return unicode;
124+ }
125+ }
126+ private final int remapJAIntChar(int unicode) {
127+ switch (unicode) {
128+ case REVERSE_SOLIDUS:
129+ return JA_YEN;
130+ /* This is a workaround for bug 4533422.
131+ * Japanese wave dash missing from Solaris JA TrueType fonts.
132+ */
133+ case JA_WAVE_DASH_CHAR:
134+ if (remapJAWaveDash) {
135+ return JA_FULLWIDTH_TILDE_CHAR;
136+ }
137+ default: return unicode;
138+ }
139+ }
140+
141+ public int charToGlyph(char unicode) {
142+ if (needsJAremapping) {
143+ unicode = remapJAChar(unicode);
144+ }
145+ int glyph = getGlyphFromCMAP(unicode);
146+ if (font.checkUseNatives() && glyph < font.glyphToCharMap.length) {
147+ font.glyphToCharMap[glyph] = unicode;
148+ }
149+ return glyph;
150+ }
151+
152+ public int charToGlyph(int unicode) {
153+ if (needsJAremapping) {
154+ unicode = remapJAIntChar(unicode);
155+ }
156+ int glyph = getGlyphFromCMAP(unicode);
157+ if (font.checkUseNatives() && glyph < font.glyphToCharMap.length) {
158+ font.glyphToCharMap[glyph] = (char)unicode;
159+ }
160+ return glyph;
161+ }
162+
163+ public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) {
164+ for (int i=0;i<count;i++) {
165+ if (needsJAremapping) {
166+ glyphs[i] = getGlyphFromCMAP(remapJAIntChar(unicodes[i]));
167+ } else {
168+ glyphs[i] = getGlyphFromCMAP(unicodes[i]);
169+ }
170+ if (font.checkUseNatives() &&
171+ glyphs[i] < font.glyphToCharMap.length) {
172+ font.glyphToCharMap[glyphs[i]] = (char)unicodes[i];
173+ }
174+ }
175+ }
176+
177+ public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) {
178+
179+ for (int i=0; i<count; i++) {
180+ int code;
181+ if (needsJAremapping) {
182+ code = remapJAChar(unicodes[i]);
183+ } else {
184+ code = unicodes[i]; // char is unsigned.
185+ }
186+
187+ if (code >= HI_SURROGATE_START &&
188+ code <= HI_SURROGATE_END && i < count - 1) {
189+ char low = unicodes[i + 1];
190+
191+ if (low >= LO_SURROGATE_START &&
192+ low <= LO_SURROGATE_END) {
193+ code = (code - HI_SURROGATE_START) *
194+ 0x400 + low - LO_SURROGATE_START + 0x10000;
195+
196+ glyphs[i] = getGlyphFromCMAP(code);
197+ i += 1; // Empty glyph slot after surrogate
198+ glyphs[i] = INVISIBLE_GLYPH_ID;
199+ continue;
200+ }
201+ }
202+ glyphs[i] = getGlyphFromCMAP(code);
203+
204+ if (font.checkUseNatives() &&
205+ glyphs[i] < font.glyphToCharMap.length) {
206+ font.glyphToCharMap[glyphs[i]] = (char)code;
207+ }
208+
209+ }
210+ }
211+
212+ /* This variant checks if shaping is needed and immediately
213+ * returns true if it does. A caller of this method should be expecting
214+ * to check the return type because it needs to know how to handle
215+ * the character data for display.
216+ */
217+ public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) {
218+
219+ for (int i=0; i<count; i++) {
220+ int code;
221+ if (needsJAremapping) {
222+ code = remapJAChar(unicodes[i]);
223+ } else {
224+ code = unicodes[i]; // char is unsigned.
225+ }
226+
227+ if (code >= HI_SURROGATE_START &&
228+ code <= HI_SURROGATE_END && i < count - 1) {
229+ char low = unicodes[i + 1];
230+
231+ if (low >= LO_SURROGATE_START &&
232+ low <= LO_SURROGATE_END) {
233+ code = (code - HI_SURROGATE_START) *
234+ 0x400 + low - LO_SURROGATE_START + 0x10000;
235+ glyphs[i + 1] = INVISIBLE_GLYPH_ID;
236+ }
237+ }
238+
239+ glyphs[i] = getGlyphFromCMAP(code);
240+ if (font.checkUseNatives() &&
241+ glyphs[i] < font.glyphToCharMap.length) {
242+ font.glyphToCharMap[glyphs[i]] = (char)code;
243+ }
244+
245+ if (code < FontUtilities.MIN_LAYOUT_CHARCODE) {
246+ continue;
247+ }
248+ else if (FontUtilities.isComplexCharCode(code)) {
249+ return true;
250+ }
251+ else if (code >= 0x10000) {
252+ i += 1; // Empty glyph slot after surrogate
253+ continue;
254+ }
255+ }
256+
257+ return false;
258+ }
259+
260+ /* A pretty good heuristic is that the cmap we are using
261+ * supports 32 bit character codes.
262+ */
263+ boolean hasSupplementaryChars() {
264+ return
265+ cmap instanceof CMap.CMapFormat8 ||
266+ cmap instanceof CMap.CMapFormat10 ||
267+ cmap instanceof CMap.CMapFormat12;
268+ }
269+}