Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/unix/classes/sun/font/FontConfigManager.java
41153 views
1
/*
2
* Copyright (c) 2008, 2020, 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.isEmpty()) {
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
FontUtilities.logInfo("Fontconfig returned no font for " + fontArr[i].fcName);
199
}
200
fontConfigFailed = true;
201
} else if (anyFont == null) {
202
anyFont = fci.firstFont;
203
}
204
}
205
206
if (anyFont == null) {
207
if (FontUtilities.isLogging()) {
208
FontUtilities.logInfo("Fontconfig returned no fonts at all.");
209
}
210
fontConfigFailed = true;
211
return;
212
} else if (fontConfigFailed) {
213
for (int i = 0; i< fontArr.length; i++) {
214
if (fontArr[i].firstFont == null) {
215
fontArr[i].firstFont = anyFont;
216
}
217
}
218
}
219
220
fontConfigFonts = fontArr;
221
222
if (FontUtilities.isLogging()) {
223
long t1 = System.nanoTime();
224
FontUtilities.logInfo("Time spent accessing fontconfig="
225
+ ((t1 - t0) / 1000000) + "ms.");
226
227
for (int i = 0; i< fontConfigFonts.length; i++) {
228
FcCompFont fci = fontConfigFonts[i];
229
FontUtilities.logInfo("FC font " + fci.fcName+" maps to family " +
230
fci.firstFont.familyName +
231
" in file " + fci.firstFont.fontFile);
232
if (fci.allFonts != null) {
233
for (int f=0;f<fci.allFonts.length;f++) {
234
FontConfigFont fcf = fci.allFonts[f];
235
FontUtilities.logInfo("Family=" + fcf.familyName +
236
" Style="+ fcf.styleStr +
237
" Fullname="+fcf.fullName +
238
" File="+fcf.fontFile);
239
}
240
}
241
}
242
}
243
}
244
245
public PhysicalFont registerFromFcInfo(FcCompFont fcInfo) {
246
247
SunFontManager fm = SunFontManager.getInstance();
248
249
/* If it's a TTC file we need to know that as we will need to
250
* make sure we return the right font */
251
String fontFile = fcInfo.firstFont.fontFile;
252
int offset = fontFile.length()-4;
253
if (offset <= 0) {
254
return null;
255
}
256
String ext = fontFile.substring(offset).toLowerCase();
257
boolean isTTC = ext.equals(".ttc");
258
259
/* If this file is already registered, can just return its font.
260
* However we do need to check in case it's a TTC as we need
261
* a specific font, so rather than directly returning it, let
262
* findFont2D resolve that.
263
*/
264
PhysicalFont physFont = fm.getRegisteredFontFile(fontFile);
265
if (physFont != null) {
266
if (isTTC) {
267
Font2D f2d = fm.findFont2D(fcInfo.firstFont.familyName,
268
fcInfo.style,
269
FontManager.NO_FALLBACK);
270
if (f2d instanceof PhysicalFont) { /* paranoia */
271
return (PhysicalFont)f2d;
272
} else {
273
return null;
274
}
275
} else {
276
return physFont;
277
}
278
}
279
280
/* If the font may hide a JRE font, we want to use the JRE version,
281
* so make it point to the JRE font.
282
*/
283
physFont = fm.findJREDeferredFont(fcInfo.firstFont.familyName,
284
fcInfo.style);
285
286
/* It is also possible the font file is on the "deferred" list,
287
* in which case we can just initialise it now.
288
*/
289
if (physFont == null &&
290
fm.isDeferredFont(fontFile) == true) {
291
physFont = fm.initialiseDeferredFont(fcInfo.firstFont.fontFile);
292
/* use findFont2D to get the right font from TTC's */
293
if (physFont != null) {
294
if (isTTC) {
295
Font2D f2d = fm.findFont2D(fcInfo.firstFont.familyName,
296
fcInfo.style,
297
FontManager.NO_FALLBACK);
298
if (f2d instanceof PhysicalFont) { /* paranoia */
299
return (PhysicalFont)f2d;
300
} else {
301
return null;
302
}
303
} else {
304
return physFont;
305
}
306
}
307
}
308
309
/* In the majority of cases we reach here, and need to determine
310
* the type and rank to register the font.
311
*/
312
if (physFont == null) {
313
int fontFormat = SunFontManager.FONTFORMAT_NONE;
314
int fontRank = Font2D.UNKNOWN_RANK;
315
316
if (ext.equals(".ttf") || isTTC) {
317
fontFormat = SunFontManager.FONTFORMAT_TRUETYPE;
318
fontRank = Font2D.TTF_RANK;
319
} else if (ext.equals(".pfa") || ext.equals(".pfb")) {
320
fontFormat = SunFontManager.FONTFORMAT_TYPE1;
321
fontRank = Font2D.TYPE1_RANK;
322
}
323
physFont = fm.registerFontFile(fcInfo.firstFont.fontFile, null,
324
fontFormat, true, fontRank);
325
}
326
return physFont;
327
}
328
329
/*
330
* We need to return a Composite font which has as the font in
331
* its first slot one obtained from fontconfig.
332
*/
333
public CompositeFont getFontConfigFont(String name, int style) {
334
335
name = name.toLowerCase();
336
337
initFontConfigFonts(false);
338
if (fontConfigFonts == null) {
339
// This avoids an immediate NPE if fontconfig look up failed
340
// but doesn't guarantee this is a recoverable situation.
341
return null;
342
}
343
344
FcCompFont fcInfo = null;
345
for (int i=0; i<fontConfigFonts.length; i++) {
346
if (name.equals(fontConfigFonts[i].fcFamily) &&
347
style == fontConfigFonts[i].style) {
348
fcInfo = fontConfigFonts[i];
349
break;
350
}
351
}
352
if (fcInfo == null) {
353
fcInfo = fontConfigFonts[0];
354
}
355
356
if (FontUtilities.isLogging()) {
357
FontUtilities.logInfo("FC name=" + name + " style=" + style +
358
" uses " + fcInfo.firstFont.familyName +
359
" in file: " + fcInfo.firstFont.fontFile);
360
}
361
362
if (fcInfo.compFont != null) {
363
return fcInfo.compFont;
364
}
365
366
/* jdkFont is going to be used for slots 1..N and as a fallback.
367
* Slot 0 will be the physical font from fontconfig.
368
*/
369
FontManager fm = FontManagerFactory.getInstance();
370
CompositeFont jdkFont = (CompositeFont)
371
fm.findFont2D(fcInfo.jdkName, style, FontManager.LOGICAL_FALLBACK);
372
373
if (fcInfo.firstFont.familyName == null ||
374
fcInfo.firstFont.fontFile == null) {
375
return (fcInfo.compFont = jdkFont);
376
}
377
378
/* First, see if the family and exact style is already registered.
379
* If it is, use it. If it's not, then try to register it.
380
* If that registration fails (signalled by null) just return the
381
* regular JDK composite.
382
* Algorithmically styled fonts won't match on exact style, so
383
* will fall through this code, but the regisration code will
384
* find that file already registered and return its font.
385
*/
386
FontFamily family = FontFamily.getFamily(fcInfo.firstFont.familyName);
387
PhysicalFont physFont = null;
388
if (family != null) {
389
Font2D f2D = family.getFontWithExactStyleMatch(fcInfo.style);
390
if (f2D instanceof PhysicalFont) {
391
physFont = (PhysicalFont)f2D;
392
}
393
}
394
395
if (physFont == null ||
396
!fcInfo.firstFont.fontFile.equals(physFont.platName)) {
397
physFont = registerFromFcInfo(fcInfo);
398
if (physFont == null) {
399
return (fcInfo.compFont = jdkFont);
400
}
401
family = FontFamily.getFamily(physFont.getFamilyName(null));
402
}
403
404
/* Now register the fonts in the family (the other styles) after
405
* checking that they aren't already registered and are actually in
406
* a different file. They may be the same file in CJK cases.
407
* For cases where they are different font files - eg as is common for
408
* Latin fonts, then we rely on fontconfig to report these correctly.
409
* Assume that all styles of this font are found by fontconfig,
410
* so we can find all the family members which must be registered
411
* together to prevent synthetic styling.
412
*/
413
for (int i=0; i<fontConfigFonts.length; i++) {
414
FcCompFont fc = fontConfigFonts[i];
415
if (fc != fcInfo &&
416
physFont.getFamilyName(null).equals(fc.firstFont.familyName) &&
417
!fc.firstFont.fontFile.equals(physFont.platName) &&
418
family.getFontWithExactStyleMatch(fc.style) == null) {
419
420
registerFromFcInfo(fontConfigFonts[i]);
421
}
422
}
423
424
/* Now we have a physical font. We will back this up with the JDK
425
* logical font (sansserif, serif, or monospaced) that corresponds
426
* to the Pango/GTK/FC logical font name.
427
*/
428
return (fcInfo.compFont = new CompositeFont(physFont, jdkFont));
429
}
430
431
public FcCompFont[] getFontConfigFonts() {
432
return fontConfigFonts;
433
}
434
435
/* Return an array of FcCompFont structs describing the primary
436
* font located for each of fontconfig/GTK/Pango's logical font names.
437
*/
438
private static native void getFontConfig(String locale,
439
FontConfigInfo fcInfo,
440
FcCompFont[] fonts,
441
boolean includeFallbacks);
442
443
void populateFontConfig(FcCompFont[] fcInfo) {
444
fontConfigFonts = fcInfo;
445
}
446
447
FcCompFont[] loadFontConfig() {
448
initFontConfigFonts(true);
449
return fontConfigFonts;
450
}
451
452
FontConfigInfo getFontConfigInfo() {
453
initFontConfigFonts(true);
454
return fcInfo;
455
}
456
457
private static native int
458
getFontConfigAASettings(String locale, String fcFamily);
459
}
460
461