Skip to content

Commit

Permalink
Merge pull request #215 from rototor/fix_font_filehandle_leak
Browse files Browse the repository at this point in the history
Fix font filehandle leak for #209
  • Loading branch information
danfickle authored Apr 25, 2018
2 parents dc764cd + 7a4456e commit b03a9e8
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.awt.*;
import java.text.BreakIterator;
Expand Down Expand Up @@ -167,10 +166,6 @@ public FontResolver getFontResolver() {
return fontResolver;
}

public void flushFonts() {
fontResolver.flushCache();
}

/**
* The media for this context
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public class PdfBoxFontResolver implements FontResolver {
private Map<String, FontDescription> _fontCache = new HashMap<String, FontDescription>();
private final PDDocument _doc;
private final SharedContext _sharedContext;
private List<TrueTypeCollection> _collectionsToClose = new ArrayList<TrueTypeCollection>();

public PdfBoxFontResolver(SharedContext sharedContext, PDDocument doc) {
_sharedContext = sharedContext;
Expand All @@ -70,10 +71,42 @@ public FSFont resolveFont(SharedContext renderingContext, FontSpecification spec
return resolveFont(renderingContext, spec.families, spec.size, spec.fontWeight, spec.fontStyle, spec.variant);
}

/**
* Free all font resources (i.e. open files), the document should already be
* closed.
*/
public void close() {
for (FontDescription fontDescription : _fontCache.values()) {
/*
* If the font is not yet subset, we must subset it, otherwise we may leak a
* file handle because the PDType0Font may still have the font file open.
*/
if (fontDescription._font != null && fontDescription._font.willBeSubset()) {
try {
fontDescription._font.subset();
} catch (IOException e) {
e.printStackTrace();
}
}
}
_fontCache.clear();

// Close all still open TrueTypeCollections
for (TrueTypeCollection collection : _collectionsToClose) {
try {
collection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
_collectionsToClose.clear();
}

@Deprecated
@Override
public void flushCache() {
_fontFamilies = createInitialFontMap();
close();
_fontCache = new HashMap<String, FontDescription>();
}

Expand Down Expand Up @@ -160,10 +193,26 @@ private void addFont(TrueTypeFont trueTypeFont, String fontFamilyNameOverride,

PDFont font = PDType0Font.load(_doc, trueTypeFont, subset);

addFont(font, fontFamilyNameOverride, fontWeightOverride, fontStyleOverride, subset);
addFontLazy(new PDFontSupplier(font), fontFamilyNameOverride, fontWeightOverride, fontStyleOverride, subset);
}

private static class PDFontSupplier implements FSSupplier<PDFont> {
private final PDFont _font;

PDFontSupplier(PDFont font) {
_font = font;
}

@Override
public PDFont supply() {
return _font;
}
}

private void addFont(PDFont font, String fontFamilyNameOverride, Integer fontWeightOverride, IdentValue fontStyleOverride, boolean subset) {
/**
* Add a font with a lazy loaded PDFont
*/
private void addFontLazy(FSSupplier<PDFont> font, String fontFamilyNameOverride, Integer fontWeightOverride, IdentValue fontStyleOverride, boolean subset) {
FontFamily<FontDescription> fontFamily = getFontFamily(fontFamilyNameOverride);
FontDescription descr = new FontDescription(
_doc,
Expand Down Expand Up @@ -191,6 +240,7 @@ public void process(TrueTypeFont ttf) throws IOException {
addFont(ttf, fontFamilyNameOverride, fontWeightOverride, fontStyleOverride, subset);
}
});
_collectionsToClose.add(collection);
}

/**
Expand Down Expand Up @@ -235,7 +285,29 @@ public void addFont(File fontFile, final String fontFamilyNameOverride, final In
/*
* We load the font using the file.
*/
addFont(PDType0Font.load(_doc, fontFile), fontFamilyNameOverride, fontWeightOverride, fontStyleOverride, subset);
addFontLazy(new FilePDFontSupplier(fontFile, _doc), fontFamilyNameOverride, fontWeightOverride, fontStyleOverride, subset);
}

/**
* Loads a Type0 font on demand
*/
private static class FilePDFontSupplier implements FSSupplier<PDFont> {
private final File _fontFile;
private final PDDocument _doc;

FilePDFontSupplier(File fontFile, PDDocument doc) {
this._fontFile = fontFile;
this._doc = doc;
}

@Override
public PDFont supply() {
try {
return PDType0Font.load(_doc, _fontFile);
} catch (IOException e) {
return null;
}
}
}


Expand Down Expand Up @@ -517,6 +589,7 @@ public static class FontDescription implements MinimalFontDescription {
private final PDDocument _doc;

private FSSupplier<InputStream> _supplier;
private FSSupplier<PDFont> _fontSupplier;
private PDFont _font;

private float _underlinePosition;
Expand All @@ -531,10 +604,6 @@ private FontDescription(PDFont font, IdentValue style, int weight) {
this(null, font, style, weight);
}

public FontDescription(PDDocument doc, PDFont font) {
this(doc, font, IdentValue.NORMAL, 400);
}

private FontDescription(PDDocument doc, FSSupplier<InputStream> supplier, int weight, IdentValue style) {
this._supplier = supplier;
this._weight = weight;
Expand All @@ -550,8 +619,21 @@ private FontDescription(PDDocument doc, PDFont font, IdentValue style, int weigh
_doc = doc;
setMetricDefaults();
}


private FontDescription(PDDocument doc, FSSupplier<PDFont> fontSupplier, IdentValue style, int weight) {
_fontSupplier = fontSupplier;
_style = style;
_weight = weight;
_supplier = null;
_doc = doc;
}

private boolean realizeFont(boolean subset) {
if (_font == null && _fontSupplier != null) {
_font = _fontSupplier.supply();
setMetricDefaults();
_fontSupplier = null;
}
if (_font == null && _supplier != null) {
InputStream is = _supplier.supply();
_supplier = null; // We only try once.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,10 @@ public void cleanup() {
_outputDevice.close();
_sharedContext.removeFromThread();
ThreadCtx.cleanup();


// Close all still open font files
((PdfBoxFontResolver)getSharedContext().getFontResolver()).close();

if (_svgImpl != null) {
try {
_svgImpl.close();
Expand Down

0 comments on commit b03a9e8

Please sign in to comment.