Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/sun/font/FileFont.java
41155 views
1
/*
2
* Copyright (c) 2003, 2021, 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.lang.ref.Reference;
29
import java.awt.FontFormatException;
30
import java.awt.geom.GeneralPath;
31
import java.awt.geom.Point2D;
32
import java.awt.geom.Rectangle2D;
33
import java.io.File;
34
import java.nio.ByteBuffer;
35
import sun.java2d.Disposer;
36
import sun.java2d.DisposerRecord;
37
38
import java.io.IOException;
39
import java.util.List;
40
import java.security.AccessController;
41
import java.security.PrivilegedActionException;
42
import java.security.PrivilegedExceptionAction;
43
44
public abstract class FileFont extends PhysicalFont {
45
46
protected boolean useJavaRasterizer = true;
47
48
/* I/O and file operations are always synchronized on the font
49
* object. Two threads can be accessing the font and retrieving
50
* information, and synchronized only to the extent that filesystem
51
* operations require.
52
* A limited number of files can be open at a time, to limit the
53
* absorption of file descriptors. If a file needs to be opened
54
* when there are none free, then the synchronization of all I/O
55
* ensures that any in progress operation will complete before some
56
* other thread closes the descriptor in order to allocate another one.
57
*/
58
// NB consider using a RAF. FIS has finalize method so may take a
59
// little longer to be GC'd. We don't use this stream at all anyway.
60
// In fact why increase the size of a FileFont object if the stream
61
// isn't needed ..
62
//protected FileInputStream stream;
63
//protected FileChannel channel;
64
protected int fileSize;
65
66
protected FontScaler scaler;
67
68
/* The following variables are used, (and in the case of the arrays,
69
* only initialised) for select fonts where a native scaler may be
70
* used to get glyph images and metrics.
71
* glyphToCharMap is filled in on the fly and used to do a reverse
72
* lookup when a FileFont needs to get the charcode back from a glyph
73
* code so it can re-map via a NativeGlyphMapper to get a native glyph.
74
* This isn't a big hit in time, since a boolean test is sufficient
75
* to choose the usual default path, nor in memory for fonts which take
76
* the native path, since fonts have contiguous zero-based glyph indexes,
77
* and these obviously do all exist in the font.
78
*/
79
protected NativeFont[] nativeFonts;
80
protected char[] glyphToCharMap;
81
/*
82
* @throws FontFormatException if the font can't be opened
83
*/
84
FileFont(String platname, Object nativeNames)
85
throws FontFormatException {
86
87
super(platname, nativeNames);
88
}
89
90
FontStrike createStrike(FontStrikeDesc desc) {
91
return new FileFontStrike(this, desc);
92
}
93
94
/* This method needs to be accessible to FontManager if there is
95
* file pool management. It may be a no-op.
96
*/
97
protected abstract void close();
98
99
100
/*
101
* This is the public interface. The subclasses need to implement
102
* this. The returned block may be longer than the requested length.
103
*/
104
abstract ByteBuffer readBlock(int offset, int length);
105
106
public boolean canDoStyle(int style) {
107
return true;
108
}
109
110
static void setFileToRemove(List<Font2D> fonts,
111
File file, int cnt,
112
CreatedFontTracker tracker)
113
{
114
CreatedFontFileDisposerRecord dr =
115
new CreatedFontFileDisposerRecord(file, cnt, tracker);
116
117
for (Font2D f : fonts) {
118
Disposer.addObjectRecord(f, dr);
119
}
120
}
121
122
/* This is called when a font scaler is determined to
123
* be unusable (ie bad).
124
* We want to replace current scaler with NullFontScaler, so
125
* we never try to use same font scaler again.
126
* Scaler native resources could have already been disposed
127
* or they will be eventually by Java2D disposer.
128
* However, it should be safe to call dispose() explicitly here.
129
*
130
* For safety we also invalidate all strike's scaler context.
131
* So, in case they cache pointer to native scaler
132
* it will not ever be used.
133
*
134
* It also appears desirable to remove all the entries from the
135
* cache so no other code will pick them up. But we can't just
136
* 'delete' them as code may be using them. And simply dropping
137
* the reference to the cache will make the reference objects
138
* unreachable and so they will not get disposed.
139
* Since a strike may hold (via java arrays) native pointers to many
140
* rasterised glyphs, this would be a memory leak.
141
* The solution is :
142
* - to move all the entries to another map where they
143
* are no longer locatable
144
* - update FontStrikeDisposer to be able to distinguish which
145
* map they are held in via a boolean flag
146
* Since this isn't expected to be anything other than an extremely
147
* rare maybe it is not worth doing this last part.
148
*/
149
synchronized void deregisterFontAndClearStrikeCache() {
150
SunFontManager fm = SunFontManager.getInstance();
151
fm.deRegisterBadFont(this);
152
153
for (Reference<FontStrike> strikeRef : strikeCache.values()) {
154
if (strikeRef != null) {
155
/* NB we know these are all FileFontStrike instances
156
* because the cache is on this FileFont
157
*/
158
FileFontStrike strike = (FileFontStrike)strikeRef.get();
159
if (strike != null && strike.pScalerContext != 0L) {
160
scaler.invalidateScalerContext(strike.pScalerContext);
161
}
162
}
163
}
164
if (scaler != null) {
165
scaler.disposeScaler();
166
}
167
scaler = FontScaler.getNullScaler();
168
}
169
170
StrikeMetrics getFontMetrics(long pScalerContext) {
171
try {
172
return getScaler().getFontMetrics(pScalerContext);
173
} catch (FontScalerException fe) {
174
scaler = FontScaler.getNullScaler();
175
return getFontMetrics(pScalerContext);
176
}
177
}
178
179
float getGlyphAdvance(long pScalerContext, int glyphCode) {
180
try {
181
return getScaler().getGlyphAdvance(pScalerContext, glyphCode);
182
} catch (FontScalerException fe) {
183
scaler = FontScaler.getNullScaler();
184
return getGlyphAdvance(pScalerContext, glyphCode);
185
}
186
}
187
188
void getGlyphMetrics(long pScalerContext, int glyphCode, Point2D.Float metrics) {
189
try {
190
getScaler().getGlyphMetrics(pScalerContext, glyphCode, metrics);
191
} catch (FontScalerException fe) {
192
scaler = FontScaler.getNullScaler();
193
getGlyphMetrics(pScalerContext, glyphCode, metrics);
194
}
195
}
196
197
long getGlyphImage(long pScalerContext, int glyphCode) {
198
try {
199
return getScaler().getGlyphImage(pScalerContext, glyphCode);
200
} catch (FontScalerException fe) {
201
scaler = FontScaler.getNullScaler();
202
return getGlyphImage(pScalerContext, glyphCode);
203
}
204
}
205
206
Rectangle2D.Float getGlyphOutlineBounds(long pScalerContext, int glyphCode) {
207
try {
208
return getScaler().getGlyphOutlineBounds(pScalerContext, glyphCode);
209
} catch (FontScalerException fe) {
210
scaler = FontScaler.getNullScaler();
211
return getGlyphOutlineBounds(pScalerContext, glyphCode);
212
}
213
}
214
215
GeneralPath getGlyphOutline(long pScalerContext, int glyphCode, float x, float y) {
216
try {
217
return getScaler().getGlyphOutline(pScalerContext, glyphCode, x, y);
218
} catch (FontScalerException fe) {
219
scaler = FontScaler.getNullScaler();
220
return getGlyphOutline(pScalerContext, glyphCode, x, y);
221
}
222
}
223
224
GeneralPath getGlyphVectorOutline(long pScalerContext, int[] glyphs, int numGlyphs, float x, float y) {
225
try {
226
return getScaler().getGlyphVectorOutline(pScalerContext, glyphs, numGlyphs, x, y);
227
} catch (FontScalerException fe) {
228
scaler = FontScaler.getNullScaler();
229
return getGlyphVectorOutline(pScalerContext, glyphs, numGlyphs, x, y);
230
}
231
}
232
233
/* T1 & TT implementation differ so this method is abstract.
234
NB: null should not be returned here! */
235
protected abstract FontScaler getScaler();
236
237
protected long getUnitsPerEm() {
238
return getScaler().getUnitsPerEm();
239
}
240
241
private static class CreatedFontFileDisposerRecord
242
implements DisposerRecord {
243
244
File fontFile = null;
245
int count = 0; // number of fonts referencing this file object.
246
CreatedFontTracker tracker;
247
248
private CreatedFontFileDisposerRecord(File file, int cnt,
249
CreatedFontTracker tracker) {
250
fontFile = file;
251
count = (cnt > 0) ? cnt : 1;
252
this.tracker = tracker;
253
}
254
255
@SuppressWarnings("removal")
256
public void dispose() {
257
java.security.AccessController.doPrivileged(
258
new java.security.PrivilegedAction<Object>() {
259
public Object run() {
260
synchronized (fontFile) {
261
count--;
262
if (count > 0) {
263
return null;
264
}
265
}
266
if (fontFile != null) {
267
try {
268
if (tracker != null) {
269
tracker.subBytes((int)fontFile.length());
270
}
271
/* REMIND: is it possible that the file is
272
* still open? It will be closed when the
273
* font2D is disposed but could this code
274
* execute first? If so the file would not
275
* be deleted on MS-windows.
276
*/
277
fontFile.delete();
278
/* remove from delete on exit hook list : */
279
// FIXME: still need to be refactored
280
SunFontManager.getInstance().tmpFontFiles.remove(fontFile);
281
} catch (Exception e) {
282
}
283
}
284
return null;
285
}
286
});
287
}
288
}
289
290
@SuppressWarnings("removal")
291
protected String getPublicFileName() {
292
SecurityManager sm = System.getSecurityManager();
293
if (sm == null) {
294
return platName;
295
}
296
boolean canReadProperty = true;
297
298
try {
299
sm.checkPropertyAccess("java.io.tmpdir");
300
} catch (SecurityException e) {
301
canReadProperty = false;
302
}
303
304
if (canReadProperty) {
305
return platName;
306
}
307
308
final File f = new File(platName);
309
310
Boolean isTmpFile = Boolean.FALSE;
311
try {
312
isTmpFile = AccessController.doPrivileged(
313
new PrivilegedExceptionAction<Boolean>() {
314
public Boolean run() {
315
File tmp = new File(System.getProperty("java.io.tmpdir"));
316
try {
317
String tpath = tmp.getCanonicalPath();
318
String fpath = f.getCanonicalPath();
319
320
return (fpath == null) || fpath.startsWith(tpath);
321
} catch (IOException e) {
322
return Boolean.TRUE;
323
}
324
}
325
}
326
);
327
} catch (PrivilegedActionException e) {
328
// unable to verify whether value of java.io.tempdir will be
329
// exposed, so return only a name of the font file.
330
isTmpFile = Boolean.TRUE;
331
}
332
333
return isTmpFile ? "temp file" : platName;
334
}
335
}
336
337