blob: 67a7b09bb02c4b10daa3142e8f44e57dff6f64c9 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2007 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
26package sun.awt.motif;
27
28import java.awt.Font;
29import java.io.BufferedReader;
30import java.io.File;
31import java.io.FileInputStream;
32import java.io.InputStreamReader;
33import java.util.HashMap;
34import java.util.HashSet;
35import java.util.Locale;
36import java.util.logging.Logger;
37import java.util.Properties;
38import java.util.Scanner;
39import sun.awt.FontConfiguration;
40import sun.awt.X11GraphicsEnvironment;
41import sun.java2d.SunGraphicsEnvironment;
42import java.nio.charset.Charset;
43
44public class MFontConfiguration extends FontConfiguration {
45
46 private static FontConfiguration fontConfig = null;
47 private static Logger logger;
48
49 public MFontConfiguration(SunGraphicsEnvironment environment) {
50 super(environment);
51 if (SunGraphicsEnvironment.debugFonts) {
52 logger = Logger.getLogger("sun.awt.FontConfiguration");
53 }
54 initTables();
55 }
56
57
58 public MFontConfiguration(SunGraphicsEnvironment environment,
59 boolean preferLocaleFonts,
60 boolean preferPropFonts) {
61 super(environment, preferLocaleFonts, preferPropFonts);
62 if (SunGraphicsEnvironment.debugFonts) {
63 logger = Logger.getLogger("sun.awt.FontConfiguration");
64 }
65 initTables();
66 }
67
68 /* Needs to be kept in sync with updates in the languages used in
69 * the fontconfig files.
70 */
71 protected void initReorderMap() {
72 reorderMap = new HashMap();
73 if (osName == null) { /* null means SunOS */
74 initReorderMapForSolaris();
75 } else {
76 initReorderMapForLinux();
77 }
78 }
79
80 private void initReorderMapForSolaris() {
81 /* Don't create a no-op entry, so we can optimize this case
82 * i.e. we don't need to do anything so can avoid slower paths in
83 * the code.
84 */
85// reorderMap.put("UTF-8", "latin-1");
86 reorderMap.put("UTF-8.hi", "devanagari"); // NB is in Lucida.
87 reorderMap.put("UTF-8.ja",
88 split("japanese-x0201,japanese-x0208,japanese-x0212"));
89 reorderMap.put("UTF-8.ko", "korean-johab");
90 reorderMap.put("UTF-8.th", "thai");
91 reorderMap.put("UTF-8.zh.TW", "chinese-big5");
92 reorderMap.put("UTF-8.zh.HK", split("chinese-big5,chinese-hkscs"));
93 if (sun.font.FontManager.isSolaris8) {
94 reorderMap.put("UTF-8.zh.CN", split("chinese-gb2312,chinese-big5"));
95 } else {
96 reorderMap.put("UTF-8.zh.CN",
97 split("chinese-gb18030-0,chinese-gb18030-1"));
98 }
99 reorderMap.put("UTF-8.zh",
100 split("chinese-big5,chinese-hkscs,chinese-gb18030-0,chinese-gb18030-1"));
101 reorderMap.put("Big5", "chinese-big5");
102 reorderMap.put("Big5-HKSCS", split("chinese-big5,chinese-hkscs"));
103 if (! sun.font.FontManager.isSolaris8 && ! sun.font.FontManager.isSolaris9) {
104 reorderMap.put("GB2312", split("chinese-gbk,chinese-gb2312"));
105 } else {
106 reorderMap.put("GB2312","chinese-gb2312");
107 }
108 reorderMap.put("x-EUC-TW",
109 split("chinese-cns11643-1,chinese-cns11643-2,chinese-cns11643-3"));
110 reorderMap.put("GBK", "chinese-gbk");
111 reorderMap.put("GB18030",split("chinese-gb18030-0,chinese-gb18030-1"));
112
113 reorderMap.put("TIS-620", "thai");
114 reorderMap.put("x-PCK",
115 split("japanese-x0201,japanese-x0208,japanese-x0212"));
116 reorderMap.put("x-eucJP-Open",
117 split("japanese-x0201,japanese-x0208,japanese-x0212"));
118 reorderMap.put("EUC-KR", "korean");
119 /* Don't create a no-op entry, so we can optimize this case */
120// reorderMap.put("ISO-8859-1", "latin-1");
121 reorderMap.put("ISO-8859-2", "latin-2");
122 reorderMap.put("ISO-8859-5", "cyrillic-iso8859-5");
123 reorderMap.put("windows-1251", "cyrillic-cp1251");
124 reorderMap.put("KOI8-R", "cyrillic-koi8-r");
125 reorderMap.put("ISO-8859-6", "arabic");
126 reorderMap.put("ISO-8859-7", "greek");
127 reorderMap.put("ISO-8859-8", "hebrew");
128 reorderMap.put("ISO-8859-9", "latin-5");
129 reorderMap.put("ISO-8859-13", "latin-7");
130 reorderMap.put("ISO-8859-15", "latin-9");
131 }
132
133 private void initReorderMapForLinux() {
134 reorderMap.put("UTF-8.ja.JP", "japanese-iso10646");
135 reorderMap.put("UTF-8.ko.KR", "korean-iso10646");
136 reorderMap.put("UTF-8.zh.TW", "chinese-tw-iso10646");
137 reorderMap.put("UTF-8.zh.HK", "chinese-tw-iso10646");
138 reorderMap.put("UTF-8.zh.CN", "chinese-cn-iso10646");
139 reorderMap.put("x-euc-jp-linux",
140 split("japanese-x0201,japanese-x0208"));
141 reorderMap.put("GB2312", "chinese-gb18030");
142 reorderMap.put("Big5", "chinese-big5");
143 reorderMap.put("EUC-KR", "korean");
144 if (osName.equals("Sun")){
145 reorderMap.put("GB18030", "chinese-cn-iso10646");
146 }
147 else {
148 reorderMap.put("GB18030", "chinese-gb18030");
149 }
150 }
151
152 /**
153 * Sets the OS name and version from environment information.
154 */
155 protected void setOsNameAndVersion(){
156 super.setOsNameAndVersion();
157
158 if (osName.equals("SunOS")) {
159 //don't care os name on Solaris
160 osName = null;
161 } else if (osName.equals("Linux")) {
162 try {
163 File f;
164 if ((f = new File("/etc/sun-release")).canRead()) {
165 osName = "Sun";
166 osVersion = getVersionString(f);
167 } else if ((f = new File("/etc/fedora-release")).canRead()) {
168 osName = "Fedora";
169 osVersion = getVersionString(f);
170 } else if ((f = new File("/etc/redhat-release")).canRead()) {
171 osName = "RedHat";
172 osVersion = getVersionString(f);
173 } else if ((f = new File("/etc/turbolinux-release")).canRead()) {
174 osName = "Turbo";
175 osVersion = getVersionString(f);
176 } else if ((f = new File("/etc/SuSE-release")).canRead()) {
177 osName = "SuSE";
178 osVersion = getVersionString(f);
179 } else if ((f = new File("/etc/lsb-release")).canRead()) {
180 /* Ubuntu and (perhaps others) use only lsb-release.
181 * Syntax and encoding is compatible with java properties.
182 * For Ubuntu the ID is "Ubuntu".
183 */
184 Properties props = new Properties();
185 props.load(new FileInputStream(f));
186 osName = props.getProperty("DISTRIB_ID");
187 osVersion = props.getProperty("DISTRIB_RELEASE");
188 }
189 } catch (Exception e) {
190 }
191 }
192 return;
193 }
194
195 /**
196 * Gets the OS version string from a Linux release-specific file.
197 */
198 private String getVersionString(File f){
199 try {
200 Scanner sc = new Scanner(f);
201 return sc.findInLine("(\\d)+((\\.)(\\d)+)*");
202 }
203 catch (Exception e){
204 }
205 return null;
206 }
207
208 private static final String fontsDirPrefix = "$JRE_LIB_FONTS";
209
210 protected String mapFileName(String fileName) {
211 if (fileName != null && fileName.startsWith(fontsDirPrefix)) {
212 return SunGraphicsEnvironment.jreFontDirName
213 + fileName.substring(fontsDirPrefix.length());
214 }
215 return fileName;
216 }
217
218 // overrides FontConfiguration.getFallbackFamilyName
219 public String getFallbackFamilyName(String fontName, String defaultFallback) {
220 // maintain compatibility with old font.properties files, which
221 // either had aliases for TimesRoman & Co. or defined mappings for them.
222 String compatibilityName = getCompatibilityFamilyName(fontName);
223 if (compatibilityName != null) {
224 return compatibilityName;
225 }
226 return defaultFallback;
227 }
228
229 protected String getEncoding(String awtFontName,
230 String characterSubsetName) {
231 // extract encoding field from XLFD
232 int beginIndex = 0;
233 int fieldNum = 13; // charset registry field
234 while (fieldNum-- > 0 && beginIndex >= 0) {
235 beginIndex = awtFontName.indexOf("-", beginIndex) + 1;
236 }
237 if (beginIndex == -1) {
238 return "default";
239 }
240 String xlfdEncoding = awtFontName.substring(beginIndex);
241 if (xlfdEncoding.indexOf("fontspecific") > 0) {
242 if (awtFontName.indexOf("dingbats") > 0) {
243 return "sun.awt.motif.X11Dingbats";
244 } else if (awtFontName.indexOf("symbol") > 0) {
245 return "sun.awt.Symbol";
246 }
247 }
248 String encoding = (String) encodingMap.get(xlfdEncoding);
249 if (encoding == null) {
250 encoding = "default";
251 }
252 return encoding;
253 }
254
255 protected Charset getDefaultFontCharset(String fontName) {
256 return Charset.forName("ISO8859_1");
257 }
258
259 /* methods for Motif support *********************************************/
260
261 private String[][] motifFontSets = new String[NUM_FONTS][NUM_STYLES];
262
263 public String getMotifFontSet(String fontName, int style) {
264 assert isLogicalFontFamilyName(fontName);
265 fontName = fontName.toLowerCase(Locale.ENGLISH);
266 int fontIndex = getFontIndex(fontName);
267 int styleIndex = getStyleIndex(style);
268 return getMotifFontSet(fontIndex, styleIndex);
269 }
270
271 private String getMotifFontSet(int fontIndex, int styleIndex) {
272 String fontSet = motifFontSets[fontIndex][styleIndex];
273 if (fontSet == null) {
274 fontSet = buildMotifFontSet(fontIndex, styleIndex);
275 motifFontSets[fontIndex][styleIndex] = fontSet;
276 }
277 return fontSet;
278 }
279
280 private String buildMotifFontSet(int fontIndex, int styleIndex) {
281 StringBuilder buffer = new StringBuilder();
282 short[] scripts = getCoreScripts(fontIndex);
283 for (int i = 0; i < scripts.length; i++) {
284 short nameID = getComponentFontIDMotif(scripts[i], fontIndex, styleIndex);
285 if (nameID == 0) {
286 nameID = getComponentFontID(scripts[i], fontIndex, styleIndex);
287 }
288 String name = getComponentFontName(nameID);
289 if (name == null || name.endsWith("fontspecific")) {
290 continue;
291 }
292 if (buffer.length() > 0) {
293 buffer.append(',');
294 }
295 buffer.append(name);
296 }
297 return buffer.toString();
298 }
299
300 protected String getFaceNameFromComponentFontName(String componentFontName) {
301 return null;
302 }
303
304 protected String getFileNameFromComponentFontName(String componentFontName) {
305 // for X11, component font name is XLFD
306 // if we have a file name already, just use it; otherwise let's see
307 // what the graphics environment can provide
308 String fileName = getFileNameFromPlatformName(componentFontName);
309 if (fileName != null && fileName.charAt(0) == '/' &&
310 !needToSearchForFile(fileName)) {
311 return fileName;
312 }
313 return ((X11GraphicsEnvironment) environment).getFileNameFromXLFD(componentFontName);
314 }
315
316 /**
317 * Get default font for Motif widgets to use, preventing them from
318 * wasting time accessing inappropriate X resources. This is called
319 * only from native code.
320 *
321 * This is part of a Motif specific performance enhancement. By
322 * default, when Motif widgets are created and initialized, Motif will
323 * set up default fonts for the widgets, which we ALWAYS override.
324 * This set up includes finding the default font in the widget's X
325 * resources and fairly expensive requests of the X server to identify
326 * the specific font or fontset. We avoid all of this overhead by
327 * providing a well known font to use at the creation of widgets, where
328 * possible.
329 *
330 * The X11 fonts are specified by XLFD strings which have %d as a
331 * marker to indicate where the fontsize should be substituted. [The
332 * libc function sprintf() is used to replace it.] The value 140
333 * specifies a font size of 14 points.
334 */
335 private static String getDefaultMotifFontSet() {
336 String font = ((MFontConfiguration) getFontConfiguration()).getMotifFontSet("sansserif", Font.PLAIN);
337 if (font != null) {
338 int i;
339 while ((i = font.indexOf("%d")) >= 0) {
340 font = font.substring(0, i) + "140" + font.substring(i+2);
341 }
342 }
343 return font;
344 }
345
346 public HashSet<String> getAWTFontPathSet() {
347 HashSet<String> fontDirs = new HashSet<String>();
348 short[] scripts = getCoreScripts(0);
349 for (int i = 0; i< scripts.length; i++) {
350 String path = getString(table_awtfontpaths[scripts[i]]);
351 if (path != null) {
352 int start = 0;
353 int colon = path.indexOf(':');
354 while (colon >= 0) {
355 fontDirs.add(path.substring(start, colon));
356 start = colon + 1;
357 colon = path.indexOf(':', start);
358 }
359 fontDirs.add((start == 0) ? path : path.substring(start));
360 }
361 }
362 return fontDirs;
363 }
364
365 /* methods for table setup ***********************************************/
366
367 private static HashMap encodingMap = new HashMap();
368
369 private void initTables() {
370 // encodingMap maps XLFD encoding component to
371 // name of corresponding java.nio charset
372 encodingMap.put("iso8859-1", "ISO-8859-1");
373 encodingMap.put("iso8859-2", "ISO-8859-2");
374 encodingMap.put("iso8859-4", "ISO-8859-4");
375 encodingMap.put("iso8859-5", "ISO-8859-5");
376 encodingMap.put("iso8859-6", "ISO-8859-6");
377 encodingMap.put("iso8859-7", "ISO-8859-7");
378 encodingMap.put("iso8859-8", "ISO-8859-8");
379 encodingMap.put("iso8859-9", "ISO-8859-9");
380 encodingMap.put("iso8859-13", "ISO-8859-13");
381 encodingMap.put("iso8859-15", "ISO-8859-15");
382 encodingMap.put("gb2312.1980-0", "sun.awt.motif.X11GB2312");
383 if (osName == null) {
384 // use standard converter on Solaris
385 encodingMap.put("gbk-0", "GBK");
386 } else {
387 encodingMap.put("gbk-0", "sun.awt.motif.X11GBK");
388 }
389 encodingMap.put("gb18030.2000-0", "sun.awt.motif.X11GB18030_0");
390 encodingMap.put("gb18030.2000-1", "sun.awt.motif.X11GB18030_1");
391 encodingMap.put("cns11643-1", "sun.awt.motif.X11CNS11643P1");
392 encodingMap.put("cns11643-2", "sun.awt.motif.X11CNS11643P2");
393 encodingMap.put("cns11643-3", "sun.awt.motif.X11CNS11643P3");
394 encodingMap.put("big5-1", "Big5");
395 encodingMap.put("big5-0", "Big5");
396 encodingMap.put("hkscs-1", "Big5-HKSCS");
397 encodingMap.put("ansi-1251", "windows-1251");
398 encodingMap.put("koi8-r", "KOI8-R");
399 encodingMap.put("jisx0201.1976-0", "sun.awt.motif.X11JIS0201");
400 encodingMap.put("jisx0208.1983-0", "sun.awt.motif.X11JIS0208");
401 encodingMap.put("jisx0212.1990-0", "sun.awt.motif.X11JIS0212");
402 encodingMap.put("ksc5601.1987-0", "sun.awt.motif.X11KSC5601");
403 encodingMap.put("ksc5601.1992-3", "sun.awt.motif.X11Johab");
404 encodingMap.put("tis620.2533-0", "TIS-620");
405 encodingMap.put("iso10646-1", "UTF-16BE");
406 }
407
408}