Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/font/FileFont.java
38829 views
/*1* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.font;2627import java.lang.ref.Reference;28import java.awt.FontFormatException;29import java.awt.geom.GeneralPath;30import java.awt.geom.Point2D;31import java.awt.geom.Rectangle2D;32import java.io.File;33import java.nio.ByteBuffer;34import sun.java2d.Disposer;35import sun.java2d.DisposerRecord;3637import java.io.IOException;38import java.security.AccessController;39import java.security.PrivilegedActionException;40import java.security.PrivilegedExceptionAction;4142public abstract class FileFont extends PhysicalFont {4344protected boolean useJavaRasterizer = true;4546/* I/O and file operations are always synchronized on the font47* object. Two threads can be accessing the font and retrieving48* information, and synchronized only to the extent that filesystem49* operations require.50* A limited number of files can be open at a time, to limit the51* absorption of file descriptors. If a file needs to be opened52* when there are none free, then the synchronization of all I/O53* ensures that any in progress operation will complete before some54* other thread closes the descriptor in order to allocate another one.55*/56// NB consider using a RAF. FIS has finalize method so may take a57// little longer to be GC'd. We don't use this stream at all anyway.58// In fact why increase the size of a FileFont object if the stream59// isn't needed ..60//protected FileInputStream stream;61//protected FileChannel channel;62protected int fileSize;6364protected FontScaler scaler;6566/* The following variables are used, (and in the case of the arrays,67* only initialised) for select fonts where a native scaler may be68* used to get glyph images and metrics.69* glyphToCharMap is filled in on the fly and used to do a reverse70* lookup when a FileFont needs to get the charcode back from a glyph71* code so it can re-map via a NativeGlyphMapper to get a native glyph.72* This isn't a big hit in time, since a boolean test is sufficient73* to choose the usual default path, nor in memory for fonts which take74* the native path, since fonts have contiguous zero-based glyph indexes,75* and these obviously do all exist in the font.76*/77protected boolean checkedNatives;78protected boolean useNatives;79protected NativeFont[] nativeFonts;80protected char[] glyphToCharMap;81/*82* @throws FontFormatException - if the font can't be opened83*/84FileFont(String platname, Object nativeNames)85throws FontFormatException {8687super(platname, nativeNames);88}8990FontStrike createStrike(FontStrikeDesc desc) {91if (!checkedNatives) {92checkUseNatives();93}94return new FileFontStrike(this, desc);95}9697protected boolean checkUseNatives() {98checkedNatives = true;99return useNatives;100}101102/* This method needs to be accessible to FontManager if there is103* file pool management. It may be a no-op.104*/105protected abstract void close();106107108/*109* This is the public interface. The subclasses need to implement110* this. The returned block may be longer than the requested length.111*/112abstract ByteBuffer readBlock(int offset, int length);113114public boolean canDoStyle(int style) {115return true;116}117118void setFileToRemove(File file, CreatedFontTracker tracker) {119Disposer.addObjectRecord(this,120new CreatedFontFileDisposerRecord(file, tracker));121}122123// MACOSX begin -- Make this static so that we can pass in CFont124static void setFileToRemove(Object font, File file, CreatedFontTracker tracker) {125Disposer.addObjectRecord(font,126new CreatedFontFileDisposerRecord(file, tracker));127}128// MACOSX - end129130/* This is called when a font scaler is determined to131* be unusable (ie bad).132* We want to replace current scaler with NullFontScaler, so133* we never try to use same font scaler again.134* Scaler native resources could have already been disposed135* or they will be eventually by Java2D disposer.136* However, it should be safe to call dispose() explicitly here.137*138* For safety we also invalidate all strike's scaler context.139* So, in case they cache pointer to native scaler140* it will not ever be used.141*142* It also appears desirable to remove all the entries from the143* cache so no other code will pick them up. But we can't just144* 'delete' them as code may be using them. And simply dropping145* the reference to the cache will make the reference objects146* unreachable and so they will not get disposed.147* Since a strike may hold (via java arrays) native pointers to many148* rasterised glyphs, this would be a memory leak.149* The solution is :150* - to move all the entries to another map where they151* are no longer locatable152* - update FontStrikeDisposer to be able to distinguish which153* map they are held in via a boolean flag154* Since this isn't expected to be anything other than an extremely155* rare maybe it is not worth doing this last part.156*/157synchronized void deregisterFontAndClearStrikeCache() {158SunFontManager fm = SunFontManager.getInstance();159fm.deRegisterBadFont(this);160161for (Reference strikeRef : strikeCache.values()) {162if (strikeRef != null) {163/* NB we know these are all FileFontStrike instances164* because the cache is on this FileFont165*/166FileFontStrike strike = (FileFontStrike)strikeRef.get();167if (strike != null && strike.pScalerContext != 0L) {168scaler.invalidateScalerContext(strike.pScalerContext);169}170}171}172if (scaler != null) {173scaler.disposeScaler();174}175scaler = FontScaler.getNullScaler();176}177178StrikeMetrics getFontMetrics(long pScalerContext) {179try {180return getScaler().getFontMetrics(pScalerContext);181} catch (FontScalerException fe) {182scaler = FontScaler.getNullScaler();183return getFontMetrics(pScalerContext);184}185}186187float getGlyphAdvance(long pScalerContext, int glyphCode) {188try {189return getScaler().getGlyphAdvance(pScalerContext, glyphCode);190} catch (FontScalerException fe) {191scaler = FontScaler.getNullScaler();192return getGlyphAdvance(pScalerContext, glyphCode);193}194}195196void getGlyphMetrics(long pScalerContext, int glyphCode, Point2D.Float metrics) {197try {198getScaler().getGlyphMetrics(pScalerContext, glyphCode, metrics);199} catch (FontScalerException fe) {200scaler = FontScaler.getNullScaler();201getGlyphMetrics(pScalerContext, glyphCode, metrics);202}203}204205long getGlyphImage(long pScalerContext, int glyphCode) {206try {207return getScaler().getGlyphImage(pScalerContext, glyphCode);208} catch (FontScalerException fe) {209scaler = FontScaler.getNullScaler();210return getGlyphImage(pScalerContext, glyphCode);211}212}213214Rectangle2D.Float getGlyphOutlineBounds(long pScalerContext, int glyphCode) {215try {216return getScaler().getGlyphOutlineBounds(pScalerContext, glyphCode);217} catch (FontScalerException fe) {218scaler = FontScaler.getNullScaler();219return getGlyphOutlineBounds(pScalerContext, glyphCode);220}221}222223GeneralPath getGlyphOutline(long pScalerContext, int glyphCode, float x, float y) {224try {225return getScaler().getGlyphOutline(pScalerContext, glyphCode, x, y);226} catch (FontScalerException fe) {227scaler = FontScaler.getNullScaler();228return getGlyphOutline(pScalerContext, glyphCode, x, y);229}230}231232GeneralPath getGlyphVectorOutline(long pScalerContext, int[] glyphs, int numGlyphs, float x, float y) {233try {234return getScaler().getGlyphVectorOutline(pScalerContext, glyphs, numGlyphs, x, y);235} catch (FontScalerException fe) {236scaler = FontScaler.getNullScaler();237return getGlyphVectorOutline(pScalerContext, glyphs, numGlyphs, x, y);238}239}240241/* T1 & TT implementation differ so this method is abstract.242NB: null should not be returned here! */243protected abstract FontScaler getScaler();244245protected long getUnitsPerEm() {246return getScaler().getUnitsPerEm();247}248249private static class CreatedFontFileDisposerRecord250implements DisposerRecord {251252File fontFile = null;253CreatedFontTracker tracker;254255private CreatedFontFileDisposerRecord(File file,256CreatedFontTracker tracker) {257fontFile = file;258this.tracker = tracker;259}260261public void dispose() {262java.security.AccessController.doPrivileged(263new java.security.PrivilegedAction() {264public Object run() {265if (fontFile != null) {266try {267if (tracker != null) {268tracker.subBytes((int)fontFile.length());269}270/* REMIND: is it possible that the file is271* still open? It will be closed when the272* font2D is disposed but could this code273* execute first? If so the file would not274* be deleted on MS-windows.275*/276fontFile.delete();277/* remove from delete on exit hook list : */278// FIXME: still need to be refactored279SunFontManager.getInstance().tmpFontFiles.remove(fontFile);280} catch (Exception e) {281}282}283return null;284}285});286}287}288289protected String getPublicFileName() {290SecurityManager sm = System.getSecurityManager();291if (sm == null) {292return platName;293}294boolean canReadProperty = true;295296try {297sm.checkPropertyAccess("java.io.tmpdir");298} catch (SecurityException e) {299canReadProperty = false;300}301302if (canReadProperty) {303return platName;304}305306final File f = new File(platName);307308Boolean isTmpFile = Boolean.FALSE;309try {310isTmpFile = AccessController.doPrivileged(311new PrivilegedExceptionAction<Boolean>() {312public Boolean run() {313File tmp = new File(System.getProperty("java.io.tmpdir"));314try {315String tpath = tmp.getCanonicalPath();316String fpath = f.getCanonicalPath();317318return (fpath == null) || fpath.startsWith(tpath);319} catch (IOException e) {320return Boolean.TRUE;321}322}323}324);325} catch (PrivilegedActionException e) {326// unable to verify whether value of java.io.tempdir will be327// exposed, so return only a name of the font file.328isTmpFile = Boolean.TRUE;329}330331return isTmpFile ? "temp file" : platName;332}333}334335336