141 * For safety we also invalidate all strike's scaler context.
142 * So, in case they cache pointer to native scaler
143 * it will not ever be used.
144 *
145 * It also appears desirable to remove all the entries from the
146 * cache so no other code will pick them up. But we can't just
147 * 'delete' them as code may be using them. And simply dropping
148 * the reference to the cache will make the reference objects
149 * unreachable and so they will not get disposed.
150 * Since a strike may hold (via java arrays) native pointers to many
151 * rasterised glyphs, this would be a memory leak.
152 * The solution is :
153 * - to move all the entries to another map where they
154 * are no longer locatable
155 * - update FontStrikeDisposer to be able to distinguish which
156 * map they are held in via a boolean flag
157 * Since this isn't expected to be anything other than an extremely
158 * rare maybe it is not worth doing this last part.
159 */
160 synchronized void deregisterFontAndClearStrikeCache() {
161 FontManager.deRegisterBadFont(this);
162
163 for (Reference strikeRef : strikeCache.values()) {
164 if (strikeRef != null) {
165 /* NB we know these are all FileFontStrike instances
166 * because the cache is on this FileFont
167 */
168 FileFontStrike strike = (FileFontStrike)strikeRef.get();
169 if (strike != null && strike.pScalerContext != 0L) {
170 scaler.invalidateScalerContext(strike.pScalerContext);
171 }
172 }
173 }
174 scaler.dispose();
175 scaler = FontManager.getNullScaler();
176 }
177
178 StrikeMetrics getFontMetrics(long pScalerContext) {
179 try {
180 return getScaler().getFontMetrics(pScalerContext);
181 } catch (FontScalerException fe) {
182 scaler = FontManager.getNullScaler();
183 return getFontMetrics(pScalerContext);
184 }
185 }
186
187 float getGlyphAdvance(long pScalerContext, int glyphCode) {
188 try {
189 return getScaler().getGlyphAdvance(pScalerContext, glyphCode);
190 } catch (FontScalerException fe) {
191 scaler = FontManager.getNullScaler();
192 return getGlyphAdvance(pScalerContext, glyphCode);
193 }
194 }
195
196 void getGlyphMetrics(long pScalerContext, int glyphCode, Point2D.Float metrics) {
197 try {
198 getScaler().getGlyphMetrics(pScalerContext, glyphCode, metrics);
199 } catch (FontScalerException fe) {
200 scaler = FontManager.getNullScaler();
201 getGlyphMetrics(pScalerContext, glyphCode, metrics);
202 }
203 }
204
205 long getGlyphImage(long pScalerContext, int glyphCode) {
206 try {
207 return getScaler().getGlyphImage(pScalerContext, glyphCode);
208 } catch (FontScalerException fe) {
209 scaler = FontManager.getNullScaler();
210 return getGlyphImage(pScalerContext, glyphCode);
211 }
212 }
213
214 Rectangle2D.Float getGlyphOutlineBounds(long pScalerContext, int glyphCode) {
215 try {
216 return getScaler().getGlyphOutlineBounds(pScalerContext, glyphCode);
217 } catch (FontScalerException fe) {
218 scaler = FontManager.getNullScaler();
219 return getGlyphOutlineBounds(pScalerContext, glyphCode);
220 }
221 }
222
223 GeneralPath getGlyphOutline(long pScalerContext, int glyphCode, float x, float y) {
224 try {
225 return getScaler().getGlyphOutline(pScalerContext, glyphCode, x, y);
226 } catch (FontScalerException fe) {
227 scaler = FontManager.getNullScaler();
228 return getGlyphOutline(pScalerContext, glyphCode, x, y);
229 }
230 }
231
232 GeneralPath getGlyphVectorOutline(long pScalerContext, int[] glyphs, int numGlyphs, float x, float y) {
233 try {
234 return getScaler().getGlyphVectorOutline(pScalerContext, glyphs, numGlyphs, x, y);
235 } catch (FontScalerException fe) {
236 scaler = FontManager.getNullScaler();
237 return getGlyphVectorOutline(pScalerContext, glyphs, numGlyphs, x, y);
238 }
239 }
240
241 /* T1 & TT implementation differ so this method is abstract.
242 NB: null should not be returned here! */
243 protected abstract FontScaler getScaler();
244
245 protected long getUnitsPerEm() {
246 return getScaler().getUnitsPerEm();
247 }
248
249 private static class CreatedFontFileDisposerRecord
250 implements DisposerRecord {
251
252 File fontFile = null;
253 CreatedFontTracker tracker;
254
255 private CreatedFontFileDisposerRecord(File file,
256 CreatedFontTracker tracker) {
258 this.tracker = tracker;
259 }
260
261 public void dispose() {
262 java.security.AccessController.doPrivileged(
263 new java.security.PrivilegedAction() {
264 public Object run() {
265 if (fontFile != null) {
266 try {
267 if (tracker != null) {
268 tracker.subBytes((int)fontFile.length());
269 }
270 /* REMIND: is it possible that the file is
271 * still open? It will be closed when the
272 * font2D is disposed but could this code
273 * execute first? If so the file would not
274 * be deleted on MS-windows.
275 */
276 fontFile.delete();
277 /* remove from delete on exit hook list : */
278 FontManager.tmpFontFiles.remove(fontFile);
279 } catch (Exception e) {
280 }
281 }
282 return null;
283 }
284 });
285 }
286 }
287 }
|
141 * For safety we also invalidate all strike's scaler context.
142 * So, in case they cache pointer to native scaler
143 * it will not ever be used.
144 *
145 * It also appears desirable to remove all the entries from the
146 * cache so no other code will pick them up. But we can't just
147 * 'delete' them as code may be using them. And simply dropping
148 * the reference to the cache will make the reference objects
149 * unreachable and so they will not get disposed.
150 * Since a strike may hold (via java arrays) native pointers to many
151 * rasterised glyphs, this would be a memory leak.
152 * The solution is :
153 * - to move all the entries to another map where they
154 * are no longer locatable
155 * - update FontStrikeDisposer to be able to distinguish which
156 * map they are held in via a boolean flag
157 * Since this isn't expected to be anything other than an extremely
158 * rare maybe it is not worth doing this last part.
159 */
160 synchronized void deregisterFontAndClearStrikeCache() {
161 SunFontManager fm = SunFontManager.getInstance();
162 fm.deRegisterBadFont(this);
163
164 for (Reference strikeRef : strikeCache.values()) {
165 if (strikeRef != null) {
166 /* NB we know these are all FileFontStrike instances
167 * because the cache is on this FileFont
168 */
169 FileFontStrike strike = (FileFontStrike)strikeRef.get();
170 if (strike != null && strike.pScalerContext != 0L) {
171 scaler.invalidateScalerContext(strike.pScalerContext);
172 }
173 }
174 }
175 scaler.dispose();
176 scaler = FontScaler.getNullScaler();
177 }
178
179 StrikeMetrics getFontMetrics(long pScalerContext) {
180 try {
181 return getScaler().getFontMetrics(pScalerContext);
182 } catch (FontScalerException fe) {
183 scaler = FontScaler.getNullScaler();
184 return getFontMetrics(pScalerContext);
185 }
186 }
187
188 float getGlyphAdvance(long pScalerContext, int glyphCode) {
189 try {
190 return getScaler().getGlyphAdvance(pScalerContext, glyphCode);
191 } catch (FontScalerException fe) {
192 scaler = FontScaler.getNullScaler();
193 return getGlyphAdvance(pScalerContext, glyphCode);
194 }
195 }
196
197 void getGlyphMetrics(long pScalerContext, int glyphCode, Point2D.Float metrics) {
198 try {
199 getScaler().getGlyphMetrics(pScalerContext, glyphCode, metrics);
200 } catch (FontScalerException fe) {
201 scaler = FontScaler.getNullScaler();
202 getGlyphMetrics(pScalerContext, glyphCode, metrics);
203 }
204 }
205
206 long getGlyphImage(long pScalerContext, int glyphCode) {
207 try {
208 return getScaler().getGlyphImage(pScalerContext, glyphCode);
209 } catch (FontScalerException fe) {
210 scaler = FontScaler.getNullScaler();
211 return getGlyphImage(pScalerContext, glyphCode);
212 }
213 }
214
215 Rectangle2D.Float getGlyphOutlineBounds(long pScalerContext, int glyphCode) {
216 try {
217 return getScaler().getGlyphOutlineBounds(pScalerContext, glyphCode);
218 } catch (FontScalerException fe) {
219 scaler = FontScaler.getNullScaler();
220 return getGlyphOutlineBounds(pScalerContext, glyphCode);
221 }
222 }
223
224 GeneralPath getGlyphOutline(long pScalerContext, int glyphCode, float x, float y) {
225 try {
226 return getScaler().getGlyphOutline(pScalerContext, glyphCode, x, y);
227 } catch (FontScalerException fe) {
228 scaler = FontScaler.getNullScaler();
229 return getGlyphOutline(pScalerContext, glyphCode, x, y);
230 }
231 }
232
233 GeneralPath getGlyphVectorOutline(long pScalerContext, int[] glyphs, int numGlyphs, float x, float y) {
234 try {
235 return getScaler().getGlyphVectorOutline(pScalerContext, glyphs, numGlyphs, x, y);
236 } catch (FontScalerException fe) {
237 scaler = FontScaler.getNullScaler();
238 return getGlyphVectorOutline(pScalerContext, glyphs, numGlyphs, x, y);
239 }
240 }
241
242 /* T1 & TT implementation differ so this method is abstract.
243 NB: null should not be returned here! */
244 protected abstract FontScaler getScaler();
245
246 protected long getUnitsPerEm() {
247 return getScaler().getUnitsPerEm();
248 }
249
250 private static class CreatedFontFileDisposerRecord
251 implements DisposerRecord {
252
253 File fontFile = null;
254 CreatedFontTracker tracker;
255
256 private CreatedFontFileDisposerRecord(File file,
257 CreatedFontTracker tracker) {
259 this.tracker = tracker;
260 }
261
262 public void dispose() {
263 java.security.AccessController.doPrivileged(
264 new java.security.PrivilegedAction() {
265 public Object run() {
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 }
|