Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/sun/awt/PlatformFont.java
41152 views
1
/*
2
* Copyright (c) 1996, 2018, 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.awt;
27
28
import java.awt.peer.FontPeer;
29
import java.util.Locale;
30
import java.util.Vector;
31
import sun.font.SunFontManager;
32
import sun.java2d.FontSupport;
33
import java.nio.CharBuffer;
34
import java.nio.ByteBuffer;
35
36
public abstract class PlatformFont implements FontPeer {
37
38
static {
39
NativeLibLoader.loadLibraries();
40
initIDs();
41
}
42
43
protected FontDescriptor[] componentFonts;
44
protected char defaultChar;
45
protected FontConfiguration fontConfig;
46
47
protected FontDescriptor defaultFont;
48
49
protected String familyName;
50
51
private Object[] fontCache;
52
53
// Maybe this should be a property that is set based
54
// on the locale?
55
protected static int FONTCACHESIZE = 256;
56
protected static int FONTCACHEMASK = PlatformFont.FONTCACHESIZE - 1;
57
protected static String osVersion;
58
59
public PlatformFont(String name, int style){
60
SunFontManager sfm = SunFontManager.getInstance();
61
if (sfm instanceof FontSupport) {
62
fontConfig = ((FontSupport)sfm).getFontConfiguration();
63
}
64
if (fontConfig == null) {
65
return;
66
}
67
68
// map given font name to a valid logical font family name
69
familyName = name.toLowerCase(Locale.ENGLISH);
70
if (!FontConfiguration.isLogicalFontFamilyName(familyName)) {
71
familyName = fontConfig.getFallbackFamilyName(familyName, "sansserif");
72
}
73
74
componentFonts = fontConfig.getFontDescriptors(familyName, style);
75
76
// search default character
77
//
78
char missingGlyphCharacter = getMissingGlyphCharacter();
79
80
defaultChar = '?';
81
if (componentFonts.length > 0)
82
defaultFont = componentFonts[0];
83
84
for (int i = 0; i < componentFonts.length; i++){
85
if (componentFonts[i].isExcluded(missingGlyphCharacter)) {
86
continue;
87
}
88
89
if (componentFonts[i].encoder.canEncode(missingGlyphCharacter)) {
90
defaultFont = componentFonts[i];
91
defaultChar = missingGlyphCharacter;
92
break;
93
}
94
}
95
}
96
97
/**
98
* Returns the character that should be rendered when a glyph
99
* is missing.
100
*/
101
protected abstract char getMissingGlyphCharacter();
102
103
/**
104
* make a array of CharsetString with given String.
105
*/
106
public CharsetString[] makeMultiCharsetString(String str){
107
return makeMultiCharsetString(str.toCharArray(), 0, str.length(), true);
108
}
109
110
/**
111
* make a array of CharsetString with given String.
112
*/
113
public CharsetString[] makeMultiCharsetString(String str, boolean allowdefault){
114
return makeMultiCharsetString(str.toCharArray(), 0, str.length(), allowdefault);
115
}
116
117
/**
118
* make a array of CharsetString with given char array.
119
* @param str The char array to convert.
120
* @param offset offset of first character of interest
121
* @param len number of characters to convert
122
*/
123
public CharsetString[] makeMultiCharsetString(char[] str, int offset, int len) {
124
return makeMultiCharsetString(str, offset, len, true);
125
}
126
127
/**
128
* make a array of CharsetString with given char array.
129
* @param str The char array to convert.
130
* @param offset offset of first character of interest
131
* @param len number of characters to convert
132
* @param allowDefault whether to allow the default char.
133
* Setting this to true overloads the meaning of this method to
134
* return non-null only if all chars can be converted.
135
* @return array of CharsetString or if allowDefault is false and any
136
* of the returned chars would have been converted to a default char,
137
* then return null.
138
* This is used to choose alternative means of displaying the text.
139
*/
140
public CharsetString[] makeMultiCharsetString(char[] str, int offset, int len,
141
boolean allowDefault) {
142
143
if (len < 1) {
144
return new CharsetString[0];
145
}
146
Vector<CharsetString> mcs = null;
147
char[] tmpStr = new char[len];
148
char tmpChar = defaultChar;
149
boolean encoded = false;
150
151
FontDescriptor currentFont = defaultFont;
152
153
154
for (int i = 0; i < componentFonts.length; i++) {
155
if (componentFonts[i].isExcluded(str[offset])){
156
continue;
157
}
158
159
/* Need "encoded" variable to distinguish the case when
160
* the default char is the same as the encoded char.
161
* The defaultChar on Linux is '?' so it is needed there.
162
*/
163
if (componentFonts[i].encoder.canEncode(str[offset])){
164
currentFont = componentFonts[i];
165
tmpChar = str[offset];
166
encoded = true;
167
break;
168
}
169
}
170
if (!allowDefault && !encoded) {
171
return null;
172
} else {
173
tmpStr[0] = tmpChar;
174
}
175
176
int lastIndex = 0;
177
for (int i = 1; i < len; i++){
178
char ch = str[offset + i];
179
FontDescriptor fd = defaultFont;
180
tmpChar = defaultChar;
181
encoded = false;
182
for (int j = 0; j < componentFonts.length; j++){
183
if (componentFonts[j].isExcluded(ch)){
184
continue;
185
}
186
187
if (componentFonts[j].encoder.canEncode(ch)){
188
fd = componentFonts[j];
189
tmpChar = ch;
190
encoded = true;
191
break;
192
}
193
}
194
if (!allowDefault && !encoded) {
195
return null;
196
} else {
197
tmpStr[i] = tmpChar;
198
}
199
if (currentFont != fd){
200
if (mcs == null) {
201
mcs = new Vector<>(3);
202
}
203
mcs.addElement(new CharsetString(tmpStr, lastIndex,
204
i-lastIndex, currentFont));
205
currentFont = fd;
206
fd = defaultFont;
207
lastIndex = i;
208
}
209
}
210
CharsetString[] result;
211
CharsetString cs = new CharsetString(tmpStr, lastIndex,
212
len-lastIndex, currentFont);
213
if (mcs == null) {
214
result = new CharsetString[1];
215
result[0] = cs;
216
} else {
217
mcs.addElement(cs);
218
result = mcs.toArray(new CharsetString[mcs.size()]);
219
}
220
return result;
221
}
222
223
/**
224
* Is it possible that this font's metrics require the multi-font calls?
225
* This might be true, for example, if the font supports kerning.
226
**/
227
public boolean mightHaveMultiFontMetrics() {
228
return fontConfig != null;
229
}
230
231
/**
232
* Specialized fast path string conversion for AWT.
233
*/
234
public Object[] makeConvertedMultiFontString(String str)
235
{
236
return makeConvertedMultiFontChars(str.toCharArray(),0,str.length());
237
}
238
239
public Object[] makeConvertedMultiFontChars(char[] data,
240
int start, int len)
241
{
242
Object[] result = new Object[2];
243
Object[] workingCache;
244
byte[] convertedData = null;
245
int stringIndex = start;
246
int convertedDataIndex = 0;
247
int resultIndex = 0;
248
int cacheIndex;
249
FontDescriptor currentFontDescriptor = null;
250
FontDescriptor lastFontDescriptor = null;
251
char currentDefaultChar;
252
PlatformFontCache theChar;
253
254
// Simple bounds check
255
int end = start + len;
256
if (start < 0 || end > data.length) {
257
throw new ArrayIndexOutOfBoundsException();
258
}
259
260
if(stringIndex >= end) {
261
return null;
262
}
263
264
// coversion loop
265
while(stringIndex < end)
266
{
267
currentDefaultChar = data[stringIndex];
268
269
// Note that cache sizes must be a power of two!
270
cacheIndex = (currentDefaultChar & PlatformFont.FONTCACHEMASK);
271
272
theChar = (PlatformFontCache)getFontCache()[cacheIndex];
273
274
// Is the unicode char we want cached?
275
if(theChar == null || theChar.uniChar != currentDefaultChar)
276
{
277
/* find a converter that can convert the current character */
278
currentFontDescriptor = defaultFont;
279
currentDefaultChar = defaultChar;
280
char ch = data[stringIndex];
281
int componentCount = componentFonts.length;
282
283
for (int j = 0; j < componentCount; j++) {
284
FontDescriptor fontDescriptor = componentFonts[j];
285
286
fontDescriptor.encoder.reset();
287
//fontDescriptor.encoder.onUnmappleCharacterAction(...);
288
289
if (fontDescriptor.isExcluded(ch)) {
290
continue;
291
}
292
if (fontDescriptor.encoder.canEncode(ch)) {
293
currentFontDescriptor = fontDescriptor;
294
currentDefaultChar = ch;
295
break;
296
}
297
}
298
try {
299
char[] input = new char[1];
300
input[0] = currentDefaultChar;
301
302
theChar = new PlatformFontCache();
303
if (currentFontDescriptor.useUnicode()) {
304
/*
305
currentFontDescriptor.unicodeEncoder.encode(CharBuffer.wrap(input),
306
theChar.bb,
307
true);
308
*/
309
if (FontDescriptor.isLE) {
310
theChar.bb.put((byte)(input[0] & 0xff));
311
theChar.bb.put((byte)(input[0] >>8));
312
} else {
313
theChar.bb.put((byte)(input[0] >> 8));
314
theChar.bb.put((byte)(input[0] & 0xff));
315
}
316
}
317
else {
318
currentFontDescriptor.encoder.encode(CharBuffer.wrap(input),
319
theChar.bb,
320
true);
321
}
322
theChar.fontDescriptor = currentFontDescriptor;
323
theChar.uniChar = data[stringIndex];
324
getFontCache()[cacheIndex] = theChar;
325
} catch(Exception e){
326
// Should never happen!
327
System.err.println(e);
328
e.printStackTrace();
329
return null;
330
}
331
}
332
333
// Check to see if we've changed fonts.
334
if(lastFontDescriptor != theChar.fontDescriptor) {
335
if(lastFontDescriptor != null) {
336
result[resultIndex++] = lastFontDescriptor;
337
result[resultIndex++] = convertedData;
338
// Add the size to the converted data field.
339
if(convertedData != null) {
340
convertedDataIndex -= 4;
341
convertedData[0] = (byte)(convertedDataIndex >> 24);
342
convertedData[1] = (byte)(convertedDataIndex >> 16);
343
convertedData[2] = (byte)(convertedDataIndex >> 8);
344
convertedData[3] = (byte)convertedDataIndex;
345
}
346
347
if(resultIndex >= result.length) {
348
Object[] newResult = new Object[result.length * 2];
349
350
System.arraycopy(result, 0, newResult, 0,
351
result.length);
352
result = newResult;
353
}
354
}
355
356
if (theChar.fontDescriptor.useUnicode()) {
357
convertedData = new byte[(end - stringIndex + 1) *
358
(int)theChar.fontDescriptor.unicodeEncoder.maxBytesPerChar()
359
+ 4];
360
}
361
else {
362
convertedData = new byte[(end - stringIndex + 1) *
363
(int)theChar.fontDescriptor.encoder.maxBytesPerChar()
364
+ 4];
365
}
366
367
convertedDataIndex = 4;
368
369
lastFontDescriptor = theChar.fontDescriptor;
370
}
371
372
byte[] ba = theChar.bb.array();
373
int size = theChar.bb.position();
374
if(size == 1) {
375
convertedData[convertedDataIndex++] = ba[0];
376
}
377
else if(size == 2) {
378
convertedData[convertedDataIndex++] = ba[0];
379
convertedData[convertedDataIndex++] = ba[1];
380
} else if(size == 3) {
381
convertedData[convertedDataIndex++] = ba[0];
382
convertedData[convertedDataIndex++] = ba[1];
383
convertedData[convertedDataIndex++] = ba[2];
384
} else if(size == 4) {
385
convertedData[convertedDataIndex++] = ba[0];
386
convertedData[convertedDataIndex++] = ba[1];
387
convertedData[convertedDataIndex++] = ba[2];
388
convertedData[convertedDataIndex++] = ba[3];
389
}
390
stringIndex++;
391
}
392
393
result[resultIndex++] = lastFontDescriptor;
394
result[resultIndex] = convertedData;
395
396
// Add the size to the converted data field.
397
if(convertedData != null) {
398
convertedDataIndex -= 4;
399
convertedData[0] = (byte)(convertedDataIndex >> 24);
400
convertedData[1] = (byte)(convertedDataIndex >> 16);
401
convertedData[2] = (byte)(convertedDataIndex >> 8);
402
convertedData[3] = (byte)convertedDataIndex;
403
}
404
return result;
405
}
406
407
/*
408
* Create fontCache on demand instead of during construction to
409
* reduce overall memory consumption.
410
*
411
* This method is declared final so that its code can be inlined
412
* by the compiler.
413
*/
414
protected final Object[] getFontCache() {
415
// This method is not MT-safe by design. Since this is just a
416
// cache anyways, it's okay if we occasionally allocate the array
417
// twice or return an array which will be dereferenced and gced
418
// right away.
419
if (fontCache == null) {
420
fontCache = new Object[PlatformFont.FONTCACHESIZE];
421
}
422
423
return fontCache;
424
}
425
426
/**
427
* Initialize JNI field and method IDs
428
*/
429
private static native void initIDs();
430
431
class PlatformFontCache
432
{
433
char uniChar;
434
FontDescriptor fontDescriptor;
435
ByteBuffer bb = ByteBuffer.allocate(4);
436
}
437
}
438
439