Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/awt/PlatformFont.java
38827 views
1
/*
2
* Copyright (c) 1996, 2010, 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 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 = new CharsetString[mcs.size()];
219
for (int i = 0; i < mcs.size(); i++){
220
result[i] = (CharsetString)mcs.elementAt(i);
221
}
222
}
223
return result;
224
}
225
226
/**
227
* Is it possible that this font's metrics require the multi-font calls?
228
* This might be true, for example, if the font supports kerning.
229
**/
230
public boolean mightHaveMultiFontMetrics() {
231
return fontConfig != null;
232
}
233
234
/**
235
* Specialized fast path string conversion for AWT.
236
*/
237
public Object[] makeConvertedMultiFontString(String str)
238
{
239
return makeConvertedMultiFontChars(str.toCharArray(),0,str.length());
240
}
241
242
public Object[] makeConvertedMultiFontChars(char[] data,
243
int start, int len)
244
{
245
Object[] result = new Object[2];
246
Object[] workingCache;
247
byte[] convertedData = null;
248
int stringIndex = start;
249
int convertedDataIndex = 0;
250
int resultIndex = 0;
251
int cacheIndex;
252
FontDescriptor currentFontDescriptor = null;
253
FontDescriptor lastFontDescriptor = null;
254
char currentDefaultChar;
255
PlatformFontCache theChar;
256
257
// Simple bounds check
258
int end = start + len;
259
if (start < 0 || end > data.length) {
260
throw new ArrayIndexOutOfBoundsException();
261
}
262
263
if(stringIndex >= end) {
264
return null;
265
}
266
267
// coversion loop
268
while(stringIndex < end)
269
{
270
currentDefaultChar = data[stringIndex];
271
272
// Note that cache sizes must be a power of two!
273
cacheIndex = (int)(currentDefaultChar & this.FONTCACHEMASK);
274
275
theChar = (PlatformFontCache)getFontCache()[cacheIndex];
276
277
// Is the unicode char we want cached?
278
if(theChar == null || theChar.uniChar != currentDefaultChar)
279
{
280
/* find a converter that can convert the current character */
281
currentFontDescriptor = defaultFont;
282
currentDefaultChar = defaultChar;
283
char ch = (char)data[stringIndex];
284
int componentCount = componentFonts.length;
285
286
for (int j = 0; j < componentCount; j++) {
287
FontDescriptor fontDescriptor = componentFonts[j];
288
289
fontDescriptor.encoder.reset();
290
//fontDescriptor.encoder.onUnmappleCharacterAction(...);
291
292
if (fontDescriptor.isExcluded(ch)) {
293
continue;
294
}
295
if (fontDescriptor.encoder.canEncode(ch)) {
296
currentFontDescriptor = fontDescriptor;
297
currentDefaultChar = ch;
298
break;
299
}
300
}
301
try {
302
char[] input = new char[1];
303
input[0] = currentDefaultChar;
304
305
theChar = new PlatformFontCache();
306
if (currentFontDescriptor.useUnicode()) {
307
/*
308
currentFontDescriptor.unicodeEncoder.encode(CharBuffer.wrap(input),
309
theChar.bb,
310
true);
311
*/
312
if (currentFontDescriptor.isLE) {
313
theChar.bb.put((byte)(input[0] & 0xff));
314
theChar.bb.put((byte)(input[0] >>8));
315
} else {
316
theChar.bb.put((byte)(input[0] >> 8));
317
theChar.bb.put((byte)(input[0] & 0xff));
318
}
319
}
320
else {
321
currentFontDescriptor.encoder.encode(CharBuffer.wrap(input),
322
theChar.bb,
323
true);
324
}
325
theChar.fontDescriptor = currentFontDescriptor;
326
theChar.uniChar = data[stringIndex];
327
getFontCache()[cacheIndex] = theChar;
328
} catch(Exception e){
329
// Should never happen!
330
System.err.println(e);
331
e.printStackTrace();
332
return null;
333
}
334
}
335
336
// Check to see if we've changed fonts.
337
if(lastFontDescriptor != theChar.fontDescriptor) {
338
if(lastFontDescriptor != null) {
339
result[resultIndex++] = lastFontDescriptor;
340
result[resultIndex++] = convertedData;
341
// Add the size to the converted data field.
342
if(convertedData != null) {
343
convertedDataIndex -= 4;
344
convertedData[0] = (byte)(convertedDataIndex >> 24);
345
convertedData[1] = (byte)(convertedDataIndex >> 16);
346
convertedData[2] = (byte)(convertedDataIndex >> 8);
347
convertedData[3] = (byte)convertedDataIndex;
348
}
349
350
if(resultIndex >= result.length) {
351
Object[] newResult = new Object[result.length * 2];
352
353
System.arraycopy(result, 0, newResult, 0,
354
result.length);
355
result = newResult;
356
}
357
}
358
359
if (theChar.fontDescriptor.useUnicode()) {
360
convertedData = new byte[(end - stringIndex + 1) *
361
(int)theChar.fontDescriptor.unicodeEncoder.maxBytesPerChar()
362
+ 4];
363
}
364
else {
365
convertedData = new byte[(end - stringIndex + 1) *
366
(int)theChar.fontDescriptor.encoder.maxBytesPerChar()
367
+ 4];
368
}
369
370
convertedDataIndex = 4;
371
372
lastFontDescriptor = theChar.fontDescriptor;
373
}
374
375
byte[] ba = theChar.bb.array();
376
int size = theChar.bb.position();
377
if(size == 1) {
378
convertedData[convertedDataIndex++] = ba[0];
379
}
380
else if(size == 2) {
381
convertedData[convertedDataIndex++] = ba[0];
382
convertedData[convertedDataIndex++] = ba[1];
383
} else if(size == 3) {
384
convertedData[convertedDataIndex++] = ba[0];
385
convertedData[convertedDataIndex++] = ba[1];
386
convertedData[convertedDataIndex++] = ba[2];
387
} else if(size == 4) {
388
convertedData[convertedDataIndex++] = ba[0];
389
convertedData[convertedDataIndex++] = ba[1];
390
convertedData[convertedDataIndex++] = ba[2];
391
convertedData[convertedDataIndex++] = ba[3];
392
}
393
stringIndex++;
394
}
395
396
result[resultIndex++] = lastFontDescriptor;
397
result[resultIndex] = convertedData;
398
399
// Add the size to the converted data field.
400
if(convertedData != null) {
401
convertedDataIndex -= 4;
402
convertedData[0] = (byte)(convertedDataIndex >> 24);
403
convertedData[1] = (byte)(convertedDataIndex >> 16);
404
convertedData[2] = (byte)(convertedDataIndex >> 8);
405
convertedData[3] = (byte)convertedDataIndex;
406
}
407
return result;
408
}
409
410
/*
411
* Create fontCache on demand instead of during construction to
412
* reduce overall memory consumption.
413
*
414
* This method is declared final so that its code can be inlined
415
* by the compiler.
416
*/
417
protected final Object[] getFontCache() {
418
// This method is not MT-safe by design. Since this is just a
419
// cache anyways, it's okay if we occasionally allocate the array
420
// twice or return an array which will be dereferenced and gced
421
// right away.
422
if (fontCache == null) {
423
fontCache = new Object[this.FONTCACHESIZE];
424
}
425
426
return fontCache;
427
}
428
429
/**
430
* Initialize JNI field and method IDs
431
*/
432
private static native void initIDs();
433
434
class PlatformFontCache
435
{
436
char uniChar;
437
FontDescriptor fontDescriptor;
438
ByteBuffer bb = ByteBuffer.allocate(4);
439
}
440
}
441
442