aboutsummaryrefslogtreecommitdiffstats
path: root/src/base/UFont.pas
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/UFont.pas')
-rw-r--r--src/base/UFont.pas102
1 files changed, 98 insertions, 4 deletions
diff --git a/src/base/UFont.pas b/src/base/UFont.pas
index 79873272..49a19a1a 100644
--- a/src/base/UFont.pas
+++ b/src/base/UFont.pas
@@ -41,6 +41,9 @@ interface
{$DEFINE BITMAP_FONT}
{$ENDIF}
+// Enables the Freetype font cache
+{$DEFINE ENABLE_FT_FACE_CACHE}
+
uses
FreeType,
gl,
@@ -455,6 +458,7 @@ type
fFilename: IPath; //**< filename of the font-file
fFace: FT_Face; //**< Holds the height of the font
fFontUnitScale: TPositionDbl; //**< FT font-units to pixel ratio
+ fSize: integer;
public
{**
@@ -467,6 +471,25 @@ type
property Filename: IPath read fFilename;
property Data: FT_Face read fFace;
property FontUnitScale: TPositionDbl read fFontUnitScale;
+ property Size: integer read fSize;
+ end;
+
+ {**
+ * Loading font faces with freetype is a slow process.
+ * Especially loading a font (e.g. fallback fonts) more than once is a waste
+ * of time. Just cache already loaded faces here.
+ *}
+ TFTFontFaceCache = class
+ private
+ fFaces: array of TFTFontFace;
+ fFacesRefCnt: array of integer;
+ public
+ {**
+ * @raises EFontError if the font could not be initialized
+ *}
+ function LoadFace(const Filename: IPath; Size: integer): TFTFontFace;
+
+ procedure UnloadFace(Face: TFTFontFace);
end;
{**
@@ -543,6 +566,7 @@ type
TFTFont = class(TCachedFont)
private
procedure ResetIntern();
+ class function GetFaceCache(): TFTFontFaceCache;
protected
fFace: TFTFontFace; //**< Default font face
@@ -1479,6 +1503,10 @@ begin
end;
{*
+ * TFTFontFaceCache
+ *}
+
+{*
* TFTFontFace
*}
@@ -1487,6 +1515,7 @@ begin
inherited Create();
fFilename := Filename;
+ fSize := Size;
// load font information
if (FT_New_Face(TFreeType.GetLibrary(), PChar(Filename.ToNative), 0, fFace) <> 0) then
@@ -1513,6 +1542,61 @@ end;
{*
+ * TFTFontFaceCache
+ *}
+
+function TFTFontFaceCache.LoadFace(const Filename: IPath; Size: integer): TFTFontFace;
+var
+ I: Integer;
+ Face: TFTFontFace;
+begin
+ {$IFDEF ENABLE_FT_FACE_CACHE}
+ for I := 0 to High(fFaces) do
+ begin
+ Face := fFaces[I];
+ // check if we have this file in our cache
+ if ((Face.Filename.Equals(Filename)) and (Face.Size = Size)) then
+ begin
+ // true -> return cached face and increment ref-count
+ Inc(fFacesRefCnt[I]);
+ Result := Face;
+ Exit;
+ end;
+ end;
+ {$ENDIF}
+
+ // face not in cache -> load it
+ Face := TFTFontFace.Create(Filename, Size);
+
+ // add face to cache
+ SetLength(fFaces, Length(fFaces)+1);
+ SetLength(fFacesRefCnt, Length(fFaces)+1);
+ fFaces[High(fFaces)] := Face;
+ fFacesRefCnt[High(fFaces)] := 1;
+
+ Result := Face;
+end;
+
+procedure TFTFontFaceCache.UnloadFace(Face: TFTFontFace);
+var
+ I: Integer;
+begin
+ for I := 0 to High(fFaces) do
+ begin
+ // search face in cache
+ if (fFaces[I] = Face) then
+ begin
+ // decrement ref-count and free face if ref-count is 0
+ Dec(fFacesRefCnt[I]);
+ if (fFacesRefCnt[I] <= 0) then
+ fFaces[I].Free;
+ Exit;
+ end;
+ end;
+end;
+
+
+{*
* TFTFont
*}
@@ -1531,7 +1615,7 @@ begin
fUseDisplayLists := true;
fPart := fpNone;
- fFace := TFTFontFace.Create(Filename, Size);
+ fFace := GetFaceCache.LoadFace(Filename, Size);
ResetIntern();
@@ -1545,13 +1629,23 @@ var
I: integer;
begin
// free faces
- fFace.Free;
+ GetFaceCache.UnloadFace(fFace);
for I := 0 to High(fFallbackFaces) do
- fFallbackFaces[I].Free;
+ GetFaceCache.UnloadFace(fFallbackFaces[I]);
inherited;
end;
+var
+ FontFaceCache: TFTFontFaceCache = nil;
+
+class function TFTFont.GetFaceCache(): TFTFontFaceCache;
+begin
+ if (FontFaceCache = nil) then
+ FontFaceCache := TFTFontFaceCache.Create;
+ Result := FontFaceCache;
+end;
+
procedure TFTFont.ResetIntern();
begin
// Note: outset and non outset fonts use same spacing
@@ -1569,7 +1663,7 @@ procedure TFTFont.AddFallback(const Filename: IPath);
var
FontFace: TFTFontFace;
begin
- FontFace := TFTFontFace.Create(Filename, Size);
+ FontFace := GetFaceCache.LoadFace(Filename, Size);
SetLength(fFallbackFaces, Length(fFallbackFaces) + 1);
fFallbackFaces[High(fFallbackFaces)] := FontFace;
end;