2
|
1 |
/*
|
|
2 |
* Copyright 2003-2005 Sun Microsystems, Inc. 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. Sun designates this
|
|
8 |
* particular file as subject to the "Classpath" exception as provided
|
|
9 |
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
22 |
* CA 95054 USA or visit www.sun.com if you need additional information or
|
|
23 |
* have any questions.
|
|
24 |
*/
|
|
25 |
|
|
26 |
package sun.font;
|
|
27 |
|
|
28 |
import java.awt.FontFormatException;
|
|
29 |
import java.awt.font.FontRenderContext;
|
|
30 |
import java.awt.geom.GeneralPath;
|
|
31 |
import java.awt.geom.Rectangle2D;
|
|
32 |
import java.util.HashMap;
|
|
33 |
import java.util.Locale;
|
|
34 |
import java.nio.charset.*;
|
|
35 |
import java.nio.CharBuffer;
|
|
36 |
import java.nio.ByteBuffer;
|
|
37 |
|
|
38 |
class XMap {
|
|
39 |
|
|
40 |
private static HashMap xMappers = new HashMap();
|
|
41 |
|
|
42 |
/* ConvertedGlyphs has unicode code points as indexes and values
|
|
43 |
* are platform-encoded multi-bytes chars packed into java chars.
|
|
44 |
* These platform-encoded characters are equated to glyph ids, although
|
|
45 |
* that's not strictly true, as X11 only supports using chars.
|
|
46 |
* The assumption carried over from the native implementation that
|
|
47 |
* a char is big enough to hold an X11 glyph id (ie platform char).
|
|
48 |
*/
|
|
49 |
char[] convertedGlyphs;
|
|
50 |
|
|
51 |
static synchronized XMap getXMapper(String encoding) {
|
|
52 |
XMap mapper = (XMap)xMappers.get(encoding);
|
|
53 |
if (mapper == null) {
|
|
54 |
mapper = getXMapperInternal(encoding);
|
|
55 |
xMappers.put(encoding, mapper);
|
|
56 |
}
|
|
57 |
return mapper;
|
|
58 |
}
|
|
59 |
|
|
60 |
static final int SINGLE_BYTE = 1;
|
|
61 |
static final int DOUBLE_BYTE = 2;
|
|
62 |
|
|
63 |
private static XMap getXMapperInternal(String encoding) {
|
|
64 |
|
|
65 |
String jclass = null;
|
|
66 |
int nBytes = SINGLE_BYTE;
|
|
67 |
int maxU = 0xffff;
|
|
68 |
int minU = 0;
|
|
69 |
boolean addAscii = false;
|
|
70 |
boolean lowPartOnly = false;
|
|
71 |
if (encoding.equals("dingbats")) {
|
|
72 |
jclass = "sun.awt.motif.X11Dingbats";
|
|
73 |
minU = 0x2701;
|
|
74 |
maxU = 0x27be;
|
|
75 |
} else if (encoding.equals("symbol")){
|
|
76 |
jclass = "sun.awt.Symbol";
|
|
77 |
minU = 0x0391;
|
|
78 |
maxU = 0x22ef;
|
|
79 |
} else if (encoding.equals("iso8859-1")) {
|
|
80 |
maxU = 0xff;
|
|
81 |
} else if (encoding.equals("iso8859-2")) {
|
|
82 |
jclass = "ISO8859_2";
|
|
83 |
} else if (encoding.equals("jisx0208.1983-0")) {
|
|
84 |
jclass = "sun.awt.motif.X11JIS0208";
|
|
85 |
nBytes = DOUBLE_BYTE;
|
|
86 |
} else if (encoding.equals("jisx0201.1976-0")) {
|
|
87 |
jclass = "sun.awt.motif.X11JIS0201";
|
|
88 |
// this is mapping the latin supplement range 128->255 which
|
|
89 |
// doesn't exist in JIS0201. This needs examination.
|
|
90 |
// it was also overwriting a couple of the mappings of
|
|
91 |
// 7E and A5 which in JIS201 are different chars than in
|
|
92 |
// Latin 1. I have revised AddAscii to not overwrite chars
|
|
93 |
// which are already converted.
|
|
94 |
addAscii = true;
|
|
95 |
lowPartOnly = true;
|
|
96 |
} else if (encoding.equals("jisx0212.1990-0")) {
|
|
97 |
jclass = "sun.awt.motif.X11JIS0212";
|
|
98 |
nBytes = DOUBLE_BYTE;
|
|
99 |
} else if (encoding.equals("iso8859-4")) {
|
|
100 |
jclass = "ISO8859_4";
|
|
101 |
} else if (encoding.equals("iso8859-5")) {
|
|
102 |
jclass = "ISO8859_5";
|
|
103 |
} else if (encoding.equals("koi8-r")) {
|
|
104 |
jclass = "KOI8_R";
|
|
105 |
} else if (encoding.equals("ansi-1251")) {
|
|
106 |
jclass = "windows-1251";
|
|
107 |
} else if (encoding.equals("iso8859-6")) {
|
|
108 |
jclass = "ISO8859_6";
|
|
109 |
} else if (encoding.equals("iso8859-7")) {
|
|
110 |
jclass = "ISO8859_7";
|
|
111 |
} else if (encoding.equals("iso8859-8")) {
|
|
112 |
jclass = "ISO8859_8";
|
|
113 |
} else if (encoding.equals("iso8859-9")) {
|
|
114 |
jclass = "ISO8859_9";
|
|
115 |
} else if (encoding.equals("iso8859-13")) {
|
|
116 |
jclass = "ISO8859_13";
|
|
117 |
} else if (encoding.equals("iso8859-15")) {
|
|
118 |
jclass = "ISO8859_15";
|
|
119 |
} else if (encoding.equals("ksc5601.1987-0")) {
|
|
120 |
jclass ="sun.awt.motif.X11KSC5601";
|
|
121 |
nBytes = DOUBLE_BYTE;
|
|
122 |
} else if (encoding.equals( "ksc5601.1992-3")) {
|
|
123 |
jclass ="sun.awt.motif.X11Johab";
|
|
124 |
nBytes = DOUBLE_BYTE;
|
|
125 |
} else if (encoding.equals( "ksc5601.1987-1")) {
|
|
126 |
jclass ="EUC_KR";
|
|
127 |
nBytes = DOUBLE_BYTE;
|
|
128 |
} else if (encoding.equals( "cns11643-1")) {
|
|
129 |
jclass = "sun.awt.motif.X11CNS11643P1";
|
|
130 |
nBytes = DOUBLE_BYTE;
|
|
131 |
} else if (encoding.equals("cns11643-2")) {
|
|
132 |
jclass = "sun.awt.motif.X11CNS11643P2";
|
|
133 |
nBytes = DOUBLE_BYTE;
|
|
134 |
} else if (encoding.equals("cns11643-3")) {
|
|
135 |
jclass = "sun.awt.motif.X11CNS11643P3";
|
|
136 |
nBytes = DOUBLE_BYTE;
|
|
137 |
} else if (encoding.equals("gb2312.1980-0")) {
|
|
138 |
jclass = "sun.awt.motif.X11GB2312";
|
|
139 |
nBytes = DOUBLE_BYTE;
|
|
140 |
} else if (encoding.indexOf("big5") >= 0) {
|
|
141 |
jclass = "Big5";
|
|
142 |
nBytes = DOUBLE_BYTE;
|
|
143 |
addAscii = true;
|
|
144 |
} else if (encoding.equals("tis620.2533-0")) {
|
|
145 |
jclass = "TIS620";
|
|
146 |
} else if (encoding.equals("gbk-0")) {
|
|
147 |
jclass = "sun.awt.motif.X11GBK";
|
|
148 |
nBytes = DOUBLE_BYTE;
|
|
149 |
} else if (encoding.indexOf("sun.unicode-0") >= 0) {
|
|
150 |
jclass = "sun.awt.motif.X11SunUnicode_0";
|
|
151 |
nBytes = DOUBLE_BYTE;
|
|
152 |
} else if (encoding.indexOf("gb18030.2000-1") >= 0) {
|
|
153 |
jclass = "sun.awt.motif.X11GB18030_1";
|
|
154 |
nBytes = DOUBLE_BYTE;
|
|
155 |
} else if (encoding.indexOf( "gb18030.2000-0") >= 0) {
|
|
156 |
jclass = "sun.awt.motif.X11GB18030_0";
|
|
157 |
nBytes = DOUBLE_BYTE;
|
|
158 |
} else if (encoding.indexOf("hkscs") >= 0) {
|
|
159 |
jclass = "sun.awt.HKSCS";
|
|
160 |
nBytes = DOUBLE_BYTE;
|
|
161 |
}
|
|
162 |
return new XMap(jclass, minU, maxU, nBytes, addAscii, lowPartOnly);
|
|
163 |
}
|
|
164 |
|
|
165 |
private static final char SURR_MIN = '\uD800';
|
|
166 |
private static final char SURR_MAX = '\uDFFF';
|
|
167 |
|
|
168 |
private XMap(String className, int minU, int maxU, int nBytes,
|
|
169 |
boolean addAscii, boolean lowPartOnly) {
|
|
170 |
|
|
171 |
CharsetEncoder enc = null;
|
|
172 |
if (className != null) {
|
|
173 |
try {
|
|
174 |
if (className.startsWith("sun.awt")) {
|
|
175 |
enc = ((Charset)Class.forName(className).newInstance()).newEncoder();
|
|
176 |
} else {
|
|
177 |
enc = Charset.forName(className).newEncoder();
|
|
178 |
}
|
|
179 |
} catch (Exception x) {x.printStackTrace();}
|
|
180 |
}
|
|
181 |
if (enc == null) {
|
|
182 |
convertedGlyphs = new char[256];
|
|
183 |
for (int i=0; i<256; i++) {
|
|
184 |
convertedGlyphs[i] = (char)i;
|
|
185 |
}
|
|
186 |
return;
|
|
187 |
} else {
|
|
188 |
/* chars is set to the unicode values to convert,
|
|
189 |
* bytes is where the X11 character codes will be output.
|
|
190 |
* Finally we pack the byte pairs into chars.
|
|
191 |
*/
|
|
192 |
int count = maxU - minU + 1;
|
|
193 |
byte[] bytes = new byte[count*nBytes];
|
|
194 |
char[] chars = new char[count];
|
|
195 |
for (int i=0; i<count; i++) {
|
|
196 |
chars[i] = (char)(minU+i);
|
|
197 |
}
|
|
198 |
int startCharIndex = 0;
|
|
199 |
/* For multi-byte encodings, single byte chars should be skipped */
|
|
200 |
if (nBytes > SINGLE_BYTE && minU < 256) {
|
|
201 |
startCharIndex = 256-minU;
|
|
202 |
}
|
|
203 |
byte[] rbytes = new byte[nBytes];
|
|
204 |
try {
|
|
205 |
int cbLen = 0;
|
|
206 |
int bbLen = 0;
|
|
207 |
// Since we dont support surrogates in any X11 encoding, skip
|
|
208 |
// the surrogate area, otherwise the sequence of "Oxdbff0xdc00"
|
|
209 |
// will accidently cause the surrogate-aware nio charset to treat
|
|
210 |
// them as a legal pair and then undesirablly skip 2 "chars"
|
|
211 |
// for one "unmappable character"
|
|
212 |
if (startCharIndex < SURR_MIN && startCharIndex + count >SURR_MAX) {
|
|
213 |
cbLen = SURR_MIN - startCharIndex;
|
|
214 |
bbLen = cbLen * nBytes;
|
|
215 |
enc.onMalformedInput(CodingErrorAction.REPLACE)
|
|
216 |
.onUnmappableCharacter(CodingErrorAction.REPLACE)
|
|
217 |
.replaceWith(rbytes)
|
|
218 |
.encode(CharBuffer.wrap(chars, startCharIndex, cbLen),
|
|
219 |
ByteBuffer.wrap(bytes, startCharIndex * nBytes, bbLen),
|
|
220 |
true);
|
|
221 |
startCharIndex = SURR_MAX + 1;
|
|
222 |
}
|
|
223 |
cbLen = count - startCharIndex;
|
|
224 |
bbLen = cbLen * nBytes;
|
|
225 |
enc.onMalformedInput(CodingErrorAction.REPLACE)
|
|
226 |
.onUnmappableCharacter(CodingErrorAction.REPLACE)
|
|
227 |
.replaceWith(rbytes)
|
|
228 |
.encode(CharBuffer.wrap(chars, startCharIndex, cbLen),
|
|
229 |
ByteBuffer.wrap(bytes, startCharIndex * nBytes, bbLen),
|
|
230 |
true);
|
|
231 |
} catch (Exception e) { e.printStackTrace();}
|
|
232 |
|
|
233 |
convertedGlyphs = new char[65536];
|
|
234 |
for (int i=0; i<count; i++) {
|
|
235 |
if (nBytes == 1) {
|
|
236 |
convertedGlyphs[i+minU] = (char)(bytes[i]&0xff);
|
|
237 |
} else {
|
|
238 |
convertedGlyphs[i+minU] =
|
|
239 |
(char)(((bytes[i*2]&0xff) << 8) + (bytes[i*2+1]&0xff));
|
|
240 |
}
|
|
241 |
}
|
|
242 |
}
|
|
243 |
|
|
244 |
int max = (lowPartOnly) ? 128 : 256;
|
|
245 |
if (addAscii && convertedGlyphs.length >= 256) {
|
|
246 |
for (int i=0;i<max;i++) {
|
|
247 |
if (convertedGlyphs[i] == 0) {
|
|
248 |
convertedGlyphs[i] = (char)i;
|
|
249 |
}
|
|
250 |
}
|
|
251 |
}
|
|
252 |
}
|
|
253 |
}
|