Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/sun/font/FontFamily.java
41154 views
1
/*
2
* Copyright (c) 2003, 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.io.File;
29
import java.awt.Font;
30
import java.io.IOException;
31
import java.util.Collection;
32
import java.util.HashMap;
33
import java.util.concurrent.ConcurrentHashMap;
34
import java.util.Locale;
35
36
public class FontFamily {
37
38
private static ConcurrentHashMap<String, FontFamily>
39
familyNameMap = new ConcurrentHashMap<String, FontFamily>();
40
private static HashMap<String, FontFamily> allLocaleNames;
41
42
protected String familyName;
43
protected Font2D plain;
44
protected Font2D bold;
45
protected Font2D italic;
46
protected Font2D bolditalic;
47
protected boolean logicalFont = false;
48
protected int familyRank;
49
50
public static FontFamily getFamily(String name) {
51
return familyNameMap.get(name.toLowerCase(Locale.ENGLISH));
52
}
53
54
public static String[] getAllFamilyNames() {
55
return null;
56
}
57
58
/* Only for use by FontManager.deRegisterBadFont(..).
59
* If this was the only font in the family, the family is removed
60
* from the map
61
*/
62
static void remove(Font2D font2D) {
63
64
String name = font2D.getFamilyName(Locale.ENGLISH);
65
FontFamily family = getFamily(name);
66
if (family == null) {
67
return;
68
}
69
if (family.plain == font2D) {
70
family.plain = null;
71
}
72
if (family.bold == font2D) {
73
family.bold = null;
74
}
75
if (family.italic == font2D) {
76
family.italic = null;
77
}
78
if (family.bolditalic == font2D) {
79
family.bolditalic = null;
80
}
81
if (family.plain == null && family.bold == null &&
82
family.italic == null && family.bolditalic == null) {
83
familyNameMap.remove(name);
84
}
85
}
86
87
public FontFamily(String name, boolean isLogFont, int rank) {
88
logicalFont = isLogFont;
89
familyName = name;
90
familyRank = rank;
91
familyNameMap.put(name.toLowerCase(Locale.ENGLISH), this);
92
}
93
94
/* Create a family for created fonts which aren't listed in the
95
* main map.
96
*/
97
FontFamily(String name) {
98
logicalFont = false;
99
familyName = name;
100
familyRank = Font2D.DEFAULT_RANK;
101
}
102
103
public String getFamilyName() {
104
return familyName;
105
}
106
107
public int getRank() {
108
return familyRank;
109
}
110
111
private boolean isFromSameSource(Font2D font) {
112
if (!(font instanceof FileFont)) {
113
return false;
114
}
115
116
FileFont existingFont = null;
117
if (plain instanceof FileFont) {
118
existingFont = (FileFont)plain;
119
} else if (bold instanceof FileFont) {
120
existingFont = (FileFont)bold;
121
} else if (italic instanceof FileFont) {
122
existingFont = (FileFont)italic;
123
} else if (bolditalic instanceof FileFont) {
124
existingFont = (FileFont)bolditalic;
125
}
126
// A family isn't created until there's a font.
127
// So if we didn't find a file font it means this
128
// isn't a file-based family.
129
if (existingFont == null) {
130
return false;
131
}
132
File existDir = (new File(existingFont.platName)).getParentFile();
133
134
FileFont newFont = (FileFont)font;
135
File newDir = (new File(newFont.platName)).getParentFile();
136
if (existDir != null) {
137
try {
138
existDir = existDir.getCanonicalFile();
139
} catch (IOException ignored) {}
140
}
141
if (newDir != null) {
142
try {
143
newDir = newDir.getCanonicalFile();
144
} catch (IOException ignored) {}
145
}
146
return java.util.Objects.equals(newDir, existDir);
147
}
148
149
/*
150
* We want a family to be of the same width and prefer medium/normal width.
151
* Once we find a particular width we accept more of the same width
152
* until we find one closer to normal when we 'evict' all existing fonts.
153
* So once we see a 'normal' width font we evict all members that are not
154
* normal width and then accept only new ones that are normal width.
155
*
156
* Once a font passes the width test we subject it to the weight test.
157
* For Plain we target the weight the closest that is <= NORMAL (400)
158
* For Bold we target the weight that is closest to BOLD (700).
159
*
160
* In the future, rather than discarding these fonts, we should
161
* extend the family to include these so lookups on these properties
162
* can locate them, as presently they will only be located by full name
163
* based lookup.
164
*/
165
166
private int familyWidth = 0;
167
private boolean preferredWidth(Font2D font) {
168
169
int newWidth = font.getWidth();
170
171
if (familyWidth == 0) {
172
familyWidth = newWidth;
173
return true;
174
}
175
176
if (newWidth == familyWidth) {
177
return true;
178
}
179
180
if (Math.abs(Font2D.FWIDTH_NORMAL - newWidth) <
181
Math.abs(Font2D.FWIDTH_NORMAL - familyWidth))
182
{
183
if (FontUtilities.debugFonts()) {
184
FontUtilities.logInfo(
185
"Found more preferred width. New width = " + newWidth +
186
" Old width = " + familyWidth + " in font " + font +
187
" nulling out fonts plain: " + plain + " bold: " + bold +
188
" italic: " + italic + " bolditalic: " + bolditalic);
189
}
190
familyWidth = newWidth;
191
plain = bold = italic = bolditalic = null;
192
return true;
193
} else if (FontUtilities.debugFonts()) {
194
FontUtilities.logInfo(
195
"Family rejecting font " + font +
196
" of less preferred width " + newWidth);
197
}
198
return false;
199
}
200
201
private boolean closerWeight(Font2D currFont, Font2D font, int style) {
202
if (familyWidth != font.getWidth()) {
203
return false;
204
}
205
206
if (currFont == null) {
207
return true;
208
}
209
210
if (FontUtilities.debugFonts()) {
211
FontUtilities.logInfo(
212
"New weight for style " + style + ". Curr.font=" + currFont +
213
" New font="+font+" Curr.weight="+ + currFont.getWeight()+
214
" New weight="+font.getWeight());
215
}
216
217
int newWeight = font.getWeight();
218
switch (style) {
219
case Font.PLAIN:
220
case Font.ITALIC:
221
return (newWeight <= Font2D.FWEIGHT_NORMAL &&
222
newWeight > currFont.getWeight());
223
224
case Font.BOLD:
225
case Font.BOLD|Font.ITALIC:
226
return (Math.abs(newWeight - Font2D.FWEIGHT_BOLD) <
227
Math.abs(currFont.getWeight() - Font2D.FWEIGHT_BOLD));
228
229
default:
230
return false;
231
}
232
}
233
234
public void setFont(Font2D font, int style) {
235
236
if (FontUtilities.isLogging()) {
237
String msg;
238
if (font instanceof CompositeFont) {
239
msg = "Request to add " + font.getFamilyName(null) +
240
" with style " + style + " to family " + familyName;
241
} else {
242
msg = "Request to add " + font +
243
" with style " + style + " to family " + this;
244
}
245
FontUtilities.logInfo(msg);
246
}
247
/* Allow a lower-rank font only if its a file font
248
* from the exact same source as any previous font.
249
*/
250
if ((font.getRank() > familyRank) && !isFromSameSource(font)) {
251
if (FontUtilities.isLogging()) {
252
FontUtilities.logWarning("Rejecting adding " + font +
253
" of lower rank " + font.getRank() +
254
" to family " + this +
255
" of rank " + familyRank);
256
}
257
return;
258
}
259
260
switch (style) {
261
262
case Font.PLAIN:
263
if (preferredWidth(font) && closerWeight(plain, font, style)) {
264
plain = font;
265
}
266
break;
267
268
case Font.BOLD:
269
if (preferredWidth(font) && closerWeight(bold, font, style)) {
270
bold = font;
271
}
272
break;
273
274
case Font.ITALIC:
275
if (preferredWidth(font) && closerWeight(italic, font, style)) {
276
italic = font;
277
}
278
break;
279
280
case Font.BOLD|Font.ITALIC:
281
if (preferredWidth(font) && closerWeight(bolditalic, font, style)) {
282
bolditalic = font;
283
}
284
break;
285
286
default:
287
break;
288
}
289
}
290
291
public Font2D getFontWithExactStyleMatch(int style) {
292
293
switch (style) {
294
295
case Font.PLAIN:
296
return plain;
297
298
case Font.BOLD:
299
return bold;
300
301
case Font.ITALIC:
302
return italic;
303
304
case Font.BOLD|Font.ITALIC:
305
return bolditalic;
306
307
default:
308
return null;
309
}
310
}
311
312
/* REMIND: if the callers of this method are operating in an
313
* environment in which not all fonts are registered, the returned
314
* font may be a algorithmically styled one, where in fact if loadfonts
315
* were executed, a styled font may be located. Our present "solution"
316
* to this is to register all fonts in a directory and assume that this
317
* registered all the styles of a font, since they would all be in the
318
* same location.
319
*/
320
public Font2D getFont(int style) {
321
322
switch (style) {
323
324
case Font.PLAIN:
325
return plain;
326
327
case Font.BOLD:
328
if (bold != null) {
329
return bold;
330
} else if (plain != null && plain.canDoStyle(style)) {
331
return plain;
332
} else {
333
return null;
334
}
335
336
case Font.ITALIC:
337
if (italic != null) {
338
return italic;
339
} else if (plain != null && plain.canDoStyle(style)) {
340
return plain;
341
} else {
342
return null;
343
}
344
345
case Font.BOLD|Font.ITALIC:
346
if (bolditalic != null) {
347
return bolditalic;
348
} else if (bold != null && bold.canDoStyle(style)) {
349
return bold;
350
} else if (italic != null && italic.canDoStyle(style)) {
351
return italic;
352
} else if (plain != null && plain.canDoStyle(style)) {
353
return plain;
354
} else {
355
return null;
356
}
357
default:
358
return null;
359
}
360
}
361
362
/* Only to be called if getFont(style) returns null
363
* This method will only return null if the family is completely empty!
364
* Note that it assumes the font of the style you need isn't in the
365
* family. The logic here is that if we must substitute something
366
* it might as well be from the same family.
367
*/
368
Font2D getClosestStyle(int style) {
369
370
switch (style) {
371
/* if you ask for a plain font try to return a non-italic one,
372
* then a italic one, finally a bold italic one */
373
case Font.PLAIN:
374
if (bold != null) {
375
return bold;
376
} else if (italic != null) {
377
return italic;
378
} else {
379
return bolditalic;
380
}
381
382
/* if you ask for a bold font try to return a non-italic one,
383
* then a bold italic one, finally an italic one */
384
case Font.BOLD:
385
if (plain != null) {
386
return plain;
387
} else if (bolditalic != null) {
388
return bolditalic;
389
} else {
390
return italic;
391
}
392
393
/* if you ask for a italic font try to return a bold italic one,
394
* then a plain one, finally an bold one */
395
case Font.ITALIC:
396
if (bolditalic != null) {
397
return bolditalic;
398
} else if (plain != null) {
399
return plain;
400
} else {
401
return bold;
402
}
403
404
case Font.BOLD|Font.ITALIC:
405
if (italic != null) {
406
return italic;
407
} else if (bold != null) {
408
return bold;
409
} else {
410
return plain;
411
}
412
}
413
return null;
414
}
415
416
/* Font may have localized names. Store these in a separate map, so
417
* that only clients who use these names need be affected.
418
*/
419
static synchronized void addLocaleNames(FontFamily family, String[] names){
420
if (allLocaleNames == null) {
421
allLocaleNames = new HashMap<String, FontFamily>();
422
}
423
for (int i=0; i<names.length; i++) {
424
allLocaleNames.put(names[i].toLowerCase(), family);
425
}
426
}
427
428
public static synchronized FontFamily getLocaleFamily(String name) {
429
if (allLocaleNames == null) {
430
return null;
431
}
432
return allLocaleNames.get(name.toLowerCase());
433
}
434
435
public static FontFamily[] getAllFontFamilies() {
436
Collection<FontFamily> families = familyNameMap.values();
437
return families.toArray(new FontFamily[0]);
438
}
439
440
public String toString() {
441
return
442
"Font family: " + familyName +
443
" plain="+plain+
444
" bold=" + bold +
445
" italic=" + italic +
446
" bolditalic=" + bolditalic;
447
448
}
449
450
}
451
452