Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/font/FontConfigManager.java
32287 views
1
/*
2
* Copyright (c) 2008, 2013, 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.util.Locale;
29
30
import sun.awt.SunHints;
31
import sun.awt.SunToolkit;
32
import sun.util.logging.PlatformLogger;
33
34
/**
35
* Small utility class to manage FontConfig.
36
*/
37
public class FontConfigManager {
38
39
static boolean fontConfigFailed = false;
40
41
/* This is populated by native */
42
private static final FontConfigInfo fcInfo = new FontConfigInfo();
43
44
/* Begin support for GTK Look and Feel - query libfontconfig and
45
* return a composite Font to Swing that uses the desktop font(s).
46
*/
47
48
/* These next three classes are just data structures.
49
*/
50
public static class FontConfigFont {
51
public String familyName; // eg Bitstream Vera Sans
52
public String styleStr; // eg Bold
53
public String fullName; // eg Bitstream Vera Sans Bold
54
public String fontFile; // eg /usr/X11/lib/fonts/foo.ttf
55
}
56
57
public static class FcCompFont {
58
public String fcName; // eg sans
59
public String fcFamily; // eg sans
60
public String jdkName; // eg sansserif
61
public int style; // eg 0=PLAIN
62
public FontConfigFont firstFont;
63
public FontConfigFont[] allFonts;
64
//boolean preferBitmaps; // if embedded bitmaps preferred over AA
65
public CompositeFont compFont; // null if not yet created/known.
66
}
67
68
public static class FontConfigInfo {
69
public int fcVersion;
70
public String[] cacheDirs = new String[4];
71
}
72
73
/* fontconfig recognises slants roman, italic, as well as oblique,
74
* and a slew of weights, where the ones that matter here are
75
* regular and bold.
76
* To fully qualify what we want, we can for example ask for (eg)
77
* Font.PLAIN : "serif:regular:roman"
78
* Font.BOLD : "serif:bold:roman"
79
* Font.ITALIC : "serif:regular:italic"
80
* Font.BOLD|Font.ITALIC : "serif:bold:italic"
81
*/
82
private static String[] fontConfigNames = {
83
"sans:regular:roman",
84
"sans:bold:roman",
85
"sans:regular:italic",
86
"sans:bold:italic",
87
88
"serif:regular:roman",
89
"serif:bold:roman",
90
"serif:regular:italic",
91
"serif:bold:italic",
92
93
"monospace:regular:roman",
94
"monospace:bold:roman",
95
"monospace:regular:italic",
96
"monospace:bold:italic",
97
};
98
99
/* This array has the array elements created in Java code and is
100
* passed down to native to be filled in.
101
*/
102
private FcCompFont[] fontConfigFonts;
103
104
/**
105
* Instantiates a new FontConfigManager getting the default instance
106
* of FontManager from the FontManagerFactory.
107
*/
108
public FontConfigManager() {
109
}
110
111
/* Called from code that needs to know what are the AA settings
112
* that apps using FC would pick up for the default desktop font.
113
* Note apps can change the default desktop font. etc, so this
114
* isn't certain to be right but its going to correct for most cases.
115
* Native return values map to the text aa values in sun.awt.SunHints.
116
* which is used to look up the renderinghint value object.
117
*/
118
public static Object getFontConfigAAHint() {
119
return getFontConfigAAHint("sans");
120
}
121
122
/* This is public solely so that for debugging purposes it can be called
123
* with other names, which might (eg) include a size, eg "sans-24"
124
* The return value is a text aa rendering hint value.
125
* Normally we should call the no-args version.
126
*/
127
public static Object getFontConfigAAHint(String fcFamily) {
128
if (FontUtilities.isWindows) {
129
return null;
130
} else {
131
int hint = getFontConfigAASettings(getFCLocaleStr(), fcFamily);
132
if (hint < 0) {
133
return null;
134
} else {
135
return SunHints.Value.get(SunHints.INTKEY_TEXT_ANTIALIASING,
136
hint);
137
}
138
}
139
}
140
141
142
private static String getFCLocaleStr() {
143
Locale l = SunToolkit.getStartupLocale();
144
String localeStr = l.getLanguage();
145
String country = l.getCountry();
146
if (!country.equals("")) {
147
localeStr = localeStr + "-" + country;
148
}
149
return localeStr;
150
}
151
152
/* This does cause the native libfontconfig to be loaded and unloaded,
153
* but it does not incur the overhead of initialisation of its
154
* data structures, so shouldn't have a measurable impact.
155
*/
156
public static native int getFontConfigVersion();
157
158
/* This can be made public if it's needed to force a re-read
159
* rather than using the cached values. The re-read would be needed
160
* only if some event signalled that the fontconfig has changed.
161
* In that event this method would need to return directly the array
162
* to be used by the caller in case it subsequently changed.
163
*/
164
public synchronized void initFontConfigFonts(boolean includeFallbacks) {
165
166
if (fontConfigFonts != null) {
167
if (!includeFallbacks || (fontConfigFonts[0].allFonts != null)) {
168
return;
169
}
170
}
171
172
if (FontUtilities.isWindows || fontConfigFailed) {
173
return;
174
}
175
176
long t0 = 0;
177
if (FontUtilities.isLogging()) {
178
t0 = System.nanoTime();
179
}
180
181
FcCompFont[] fontArr = new FcCompFont[fontConfigNames.length];
182
183
for (int i = 0; i< fontArr.length; i++) {
184
fontArr[i] = new FcCompFont();
185
fontArr[i].fcName = fontConfigNames[i];
186
int colonPos = fontArr[i].fcName.indexOf(':');
187
fontArr[i].fcFamily = fontArr[i].fcName.substring(0, colonPos);
188
fontArr[i].jdkName = FontUtilities.mapFcName(fontArr[i].fcFamily);
189
fontArr[i].style = i % 4; // depends on array order.
190
}
191
getFontConfig(getFCLocaleStr(), fcInfo, fontArr, includeFallbacks);
192
FontConfigFont anyFont = null;
193
/* If don't find anything (eg no libfontconfig), then just return */
194
for (int i = 0; i< fontArr.length; i++) {
195
FcCompFont fci = fontArr[i];
196
if (fci.firstFont == null) {
197
if (FontUtilities.isLogging()) {
198
PlatformLogger logger = FontUtilities.getLogger();
199
logger.info("Fontconfig returned no font for " +
200
fontArr[i].fcName);
201
}
202
fontConfigFailed = true;
203
} else if (anyFont == null) {
204
anyFont = fci.firstFont;
205
}
206
}
207
208
if (anyFont == null) {
209
if (FontUtilities.isLogging()) {
210
PlatformLogger logger = FontUtilities.getLogger();
211
logger.info("Fontconfig returned no fonts at all.");
212
}
213
fontConfigFailed = true;
214
return;
215
} else if (fontConfigFailed) {
216
for (int i = 0; i< fontArr.length; i++) {
217
if (fontArr[i].firstFont == null) {
218
fontArr[i].firstFont = anyFont;
219
}
220
}
221
}
222
223
fontConfigFonts = fontArr;
224
225
if (FontUtilities.isLogging()) {
226
227
PlatformLogger logger = FontUtilities.getLogger();
228
229
long t1 = System.nanoTime();
230
logger.info("Time spent accessing fontconfig="
231
+ ((t1 - t0) / 1000000) + "ms.");
232
233
for (int i = 0; i< fontConfigFonts.length; i++) {
234
FcCompFont fci = fontConfigFonts[i];
235
logger.info("FC font " + fci.fcName+" maps to family " +
236
fci.firstFont.familyName +
237
" in file " + fci.firstFont.fontFile);
238
if (fci.allFonts != null) {
239
for (int f=0;f<fci.allFonts.length;f++) {
240
FontConfigFont fcf = fci.allFonts[f];
241
logger.info("Family=" + fcf.familyName +
242
" Style="+ fcf.styleStr +
243
" Fullname="+fcf.fullName +
244
" File="+fcf.fontFile);
245
}
246
}
247
}
248
}
249
}
250
251
public PhysicalFont registerFromFcInfo(FcCompFont fcInfo) {
252
253
SunFontManager fm = SunFontManager.getInstance();
254
255
/* If it's a TTC file we need to know that as we will need to
256
* make sure we return the right font */
257
String fontFile = fcInfo.firstFont.fontFile;
258
int offset = fontFile.length()-4;
259
if (offset <= 0) {
260
return null;
261
}
262
String ext = fontFile.substring(offset).toLowerCase();
263
boolean isTTC = ext.equals(".ttc");
264
265
/* If this file is already registered, can just return its font.
266
* However we do need to check in case it's a TTC as we need
267
* a specific font, so rather than directly returning it, let
268
* findFont2D resolve that.
269
*/
270
PhysicalFont physFont = fm.getRegisteredFontFile(fontFile);
271
if (physFont != null) {
272
if (isTTC) {
273
Font2D f2d = fm.findFont2D(fcInfo.firstFont.familyName,
274
fcInfo.style,
275
FontManager.NO_FALLBACK);
276
if (f2d instanceof PhysicalFont) { /* paranoia */
277
return (PhysicalFont)f2d;
278
} else {
279
return null;
280
}
281
} else {
282
return physFont;
283
}
284
}
285
286
/* If the font may hide a JRE font (eg fontconfig says it is
287
* Lucida Sans), we want to use the JRE version, so make it
288
* point to the JRE font.
289
*/
290
physFont = fm.findJREDeferredFont(fcInfo.firstFont.familyName,
291
fcInfo.style);
292
293
/* It is also possible the font file is on the "deferred" list,
294
* in which case we can just initialise it now.
295
*/
296
if (physFont == null &&
297
fm.isDeferredFont(fontFile) == true) {
298
physFont = fm.initialiseDeferredFont(fcInfo.firstFont.fontFile);
299
/* use findFont2D to get the right font from TTC's */
300
if (physFont != null) {
301
if (isTTC) {
302
Font2D f2d = fm.findFont2D(fcInfo.firstFont.familyName,
303
fcInfo.style,
304
FontManager.NO_FALLBACK);
305
if (f2d instanceof PhysicalFont) { /* paranoia */
306
return (PhysicalFont)f2d;
307
} else {
308
return null;
309
}
310
} else {
311
return physFont;
312
}
313
}
314
}
315
316
/* In the majority of cases we reach here, and need to determine
317
* the type and rank to register the font.
318
*/
319
if (physFont == null) {
320
int fontFormat = SunFontManager.FONTFORMAT_NONE;
321
int fontRank = Font2D.UNKNOWN_RANK;
322
323
if (ext.equals(".ttf") || isTTC) {
324
fontFormat = SunFontManager.FONTFORMAT_TRUETYPE;
325
fontRank = Font2D.TTF_RANK;
326
} else if (ext.equals(".pfa") || ext.equals(".pfb")) {
327
fontFormat = SunFontManager.FONTFORMAT_TYPE1;
328
fontRank = Font2D.TYPE1_RANK;
329
}
330
physFont = fm.registerFontFile(fcInfo.firstFont.fontFile, null,
331
fontFormat, true, fontRank);
332
}
333
return physFont;
334
}
335
336
/*
337
* We need to return a Composite font which has as the font in
338
* its first slot one obtained from fontconfig.
339
*/
340
public CompositeFont getFontConfigFont(String name, int style) {
341
342
name = name.toLowerCase();
343
344
initFontConfigFonts(false);
345
if (fontConfigFonts == null) {
346
// This avoids an immediate NPE if fontconfig look up failed
347
// but doesn't guarantee this is a recoverable situation.
348
return null;
349
}
350
351
FcCompFont fcInfo = null;
352
for (int i=0; i<fontConfigFonts.length; i++) {
353
if (name.equals(fontConfigFonts[i].fcFamily) &&
354
style == fontConfigFonts[i].style) {
355
fcInfo = fontConfigFonts[i];
356
break;
357
}
358
}
359
if (fcInfo == null) {
360
fcInfo = fontConfigFonts[0];
361
}
362
363
if (FontUtilities.isLogging()) {
364
FontUtilities.getLogger()
365
.info("FC name=" + name + " style=" + style +
366
" uses " + fcInfo.firstFont.familyName +
367
" in file: " + fcInfo.firstFont.fontFile);
368
}
369
370
if (fcInfo.compFont != null) {
371
return fcInfo.compFont;
372
}
373
374
/* jdkFont is going to be used for slots 1..N and as a fallback.
375
* Slot 0 will be the physical font from fontconfig.
376
*/
377
FontManager fm = FontManagerFactory.getInstance();
378
CompositeFont jdkFont = (CompositeFont)
379
fm.findFont2D(fcInfo.jdkName, style, FontManager.LOGICAL_FALLBACK);
380
381
if (fcInfo.firstFont.familyName == null ||
382
fcInfo.firstFont.fontFile == null) {
383
return (fcInfo.compFont = jdkFont);
384
}
385
386
/* First, see if the family and exact style is already registered.
387
* If it is, use it. If it's not, then try to register it.
388
* If that registration fails (signalled by null) just return the
389
* regular JDK composite.
390
* Algorithmically styled fonts won't match on exact style, so
391
* will fall through this code, but the regisration code will
392
* find that file already registered and return its font.
393
*/
394
FontFamily family = FontFamily.getFamily(fcInfo.firstFont.familyName);
395
PhysicalFont physFont = null;
396
if (family != null) {
397
Font2D f2D = family.getFontWithExactStyleMatch(fcInfo.style);
398
if (f2D instanceof PhysicalFont) {
399
physFont = (PhysicalFont)f2D;
400
}
401
}
402
403
if (physFont == null ||
404
!fcInfo.firstFont.fontFile.equals(physFont.platName)) {
405
physFont = registerFromFcInfo(fcInfo);
406
if (physFont == null) {
407
return (fcInfo.compFont = jdkFont);
408
}
409
family = FontFamily.getFamily(physFont.getFamilyName(null));
410
}
411
412
/* Now register the fonts in the family (the other styles) after
413
* checking that they aren't already registered and are actually in
414
* a different file. They may be the same file in CJK cases.
415
* For cases where they are different font files - eg as is common for
416
* Latin fonts, then we rely on fontconfig to report these correctly.
417
* Assume that all styles of this font are found by fontconfig,
418
* so we can find all the family members which must be registered
419
* together to prevent synthetic styling.
420
*/
421
for (int i=0; i<fontConfigFonts.length; i++) {
422
FcCompFont fc = fontConfigFonts[i];
423
if (fc != fcInfo &&
424
physFont.getFamilyName(null).equals(fc.firstFont.familyName) &&
425
!fc.firstFont.fontFile.equals(physFont.platName) &&
426
family.getFontWithExactStyleMatch(fc.style) == null) {
427
428
registerFromFcInfo(fontConfigFonts[i]);
429
}
430
}
431
432
/* Now we have a physical font. We will back this up with the JDK
433
* logical font (sansserif, serif, or monospaced) that corresponds
434
* to the Pango/GTK/FC logical font name.
435
*/
436
return (fcInfo.compFont = new CompositeFont(physFont, jdkFont));
437
}
438
439
/**
440
*
441
* @param locale
442
* @param fcFamily
443
* @return
444
*/
445
public FcCompFont[] getFontConfigFonts() {
446
return fontConfigFonts;
447
}
448
449
/* Return an array of FcCompFont structs describing the primary
450
* font located for each of fontconfig/GTK/Pango's logical font names.
451
*/
452
private static native void getFontConfig(String locale,
453
FontConfigInfo fcInfo,
454
FcCompFont[] fonts,
455
boolean includeFallbacks);
456
457
void populateFontConfig(FcCompFont[] fcInfo) {
458
fontConfigFonts = fcInfo;
459
}
460
461
FcCompFont[] loadFontConfig() {
462
initFontConfigFonts(true);
463
return fontConfigFonts;
464
}
465
466
FontConfigInfo getFontConfigInfo() {
467
initFontConfigFonts(true);
468
return fcInfo;
469
}
470
471
private static native int
472
getFontConfigAASettings(String locale, String fcFamily);
473
}
474
475