123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 2003 by the Free Pascal development team
- Basic canvas definitions.
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {$mode objfpc}{$h+}
- unit freetype;
- interface
- uses sysutils, classes, freetypeh, FPImgCmn;
- { TODO : take resolution in account to find the size }
- { TODO : speed optimization: search glyphs with a hash-function/tree/binary search/... }
- { TODO : memory optimization: TStringBitmaps keeps for each differnet character
- only 1 bitmap }
- { TODO : load other files depending on the extention }
- { possible TODO : different sizes/resolutions for x and y }
- { possible TODO : TFontmanager can fill a list of all the fonts he can find
- fontfiles and faces available in a fontfile }
- // determine if file comparison need to be case sensitive or not
- {$ifdef WIN32}
- {$undef CaseSense}
- {$else}
- {$define CaseSense}
- {$endif}
- type
- FreeTypeException = class (exception);
- TBitmapType = (btBlackWhite, bt256Gray);
- TFontBitmap = record
- height, width, pitch,
- x,y, advanceX, advanceY : integer;
- data : PByteArray;
- end;
- PFontBitmap = ^TFontBitmap;
- TStringBitMaps = class
- private
- FList : TList;
- FBounds : TRect;
- FText : string;
- FMode : TBitmapType;
- function GetCount : integer;
- function GetBitmap (index:integer) : PFontBitmap;
- procedure CalculateGlobals;
- public
- constructor Create (ACount : integer);
- destructor destroy; override;
- procedure GetBoundRect (var aRect : TRect);
- property Text : string read FText;
- property Mode : TBitmapType read FMode;
- property Count : integer read GetCount;
- property Bitmaps[index:integer] : PFontBitmap read GetBitmap;
- end;
- TFontManager = class;
- PMgrGlyph = ^TMgrGlyph;
- TMgrGlyph = record
- Character : char;
- GlyphIndex : FT_UInt;
- Glyph : PFT_Glyph;
- end;
- PMgrSize = ^TMgrSize;
- TMgrSize = record
- Resolution, Size : integer;
- Glyphs : TList;
- end;
- TMgrFont = class
- private
- Mgr : TFontManager;
- Font : PFT_Face;
- FSizes : TList;
- Filename : string;
- LastSize : PMgrSize;
- procedure FreeGlyphs;
- public
- constructor Create (aMgr:TFontManager; afilename:string; anindex:integer);
- destructor destroy; override;
- end;
- TFontManager = class
- private
- FTLib : PFT_Library;
- FList : TList;
- FPaths : TStringList;
- FExtention : string;
- FResolution : integer;
- CurFont : TMgrFont;
- CurSize : PMgrSize;
- CurRenderMode : FT_Render_Mode;
- CurTransform : FT_Matrix;
- UseKerning : boolean;
- function GetSearchPath : string;
- procedure SetSearchPath (AValue : string);
- procedure SetExtention (AValue : string);
- protected
- function GetFontId (afilename:string; anindex:integer) : integer;
- function CreateFont (afilename:string; anindex:integer) : integer;
- function SearchFont (afilename:string) : string;
- function GetFont (FontID:integer) : TMgrFont;
- procedure GetSize (aSize, aResolution : integer);
- function CreateSize (aSize, aResolution : integer) : PMgrSize;
- procedure SetPixelSize (aSize, aResolution : integer);
- function GetGlyph (c : char) : PMgrGlyph;
- function CreateGlyph (c : char) : PMgrGlyph;
- procedure MakeTransformation (angle:real; var Transformation:FT_Matrix);
- procedure InitMakeString (FontID, Size:integer);
- function MakeString (FontId:integer; Text:string; size:integer; angle:real) : TStringBitmaps;
- function MakeString (FontId:integer; Text:string; Size:integer) : TStringBitmaps;
- public
- constructor Create;
- destructor destroy; override;
- function RequestFont (afilename:string) : integer;
- function RequestFont (afilename:string; anindex:integer) : integer;
- function GetFreeTypeFont (aFontID:integer) : PFT_Face;
- function GetString (FontId:integer; Text:string; size:integer; angle:real) : TStringBitmaps;
- // Black and white
- function GetStringGray (FontId:integer; Text:string; size:integer; angle:real) : TStringBitmaps;
- // Anti Aliased gray scale
- function GetString (FontId:integer; Text:string; Size:integer) : TStringBitmaps;
- // Black and white, following the direction of the font (left to right, top to bottom, ...)
- function GetStringGray (FontId:integer; Text:string; Size:integer) : TStringBitmaps;
- // Anti Aliased gray scale, following the direction of the font (left to right, top to bottom, ...)
- property SearchPath : string read GetSearchPath write SetSearchPath;
- property DefaultExtention : string read FExtention write SetExtention;
- property Resolution : integer read Fresolution write FResolution;
- end;
- const
- sErrErrorsInCleanup : string = '%d errors detected while freeing a Font Manager object';
- sErrFontFileNotFound : string = 'Font file "%s" not found';
- sErrFreeType : string = 'Error %d while %s';
- sInitializing : string = 'initializing font engine';
- sDestroying : string = 'destroying font engine';
- sErrErrorInCleanup : string = 'freeing Font Manager object';
- sErrSetPixelSize : string = 'setting pixel size %d (resolution %d)';
- sErrSetCharSize : string = 'setting char size %d (resolution %d)';
- sErrLoadingGlyph : string = 'loading glyph';
- sErrKerning : string = 'determining kerning distance';
- sErrMakingString1 : string = 'making string bitmaps step 1';
- sErrMakingString2 : string = 'making string bitmaps step 2';
- sErrMakingString3 : string = 'making string bitmaps step 3';
- sErrMakingString4 : string = 'making string bitmaps step 4';
- sErrLoadFont : string = 'loading font %d from file %s';
- sErrInitializing : string = 'initializing FreeType';
- sErrDestroying : string = 'finalizing FreeType';
- DefaultFontExtention : string = '.ttf';
- DefaultSearchPath : string = '';
- {$IFDEF MAC}
- DefaultResolution : integer = 72;
- {$ELSE}
- DefaultResolution : integer = 97;
- {$ENDIF}
- implementation
- {$IFDEF win32}uses dos;{$ENDIF}
- procedure FTError (Event:string; Err:integer);
- begin
- raise FreeTypeException.CreateFmt (sErrFreeType, [Err,Event]);
- end;
- Function FTCheck (Res: Integer; Msg:string) : Integer;
- begin
- Result:=Res;
- If (Result<>0) then
- FTError(Msg,Result);
- end;
- { TMgrFont }
- constructor TMgrFont.Create (aMgr:TFontManager; afilename:string; anindex:integer);
- begin
- inherited create;
- Filename := afilename;
- Mgr := aMgr;
- FSizes := TList.create;
- LastSize := nil;
- Try
- FTCheck(FT_New_Face (aMgr.FTLib, pchar(afilename), anindex, font),format (sErrLoadFont,[anindex,afilename]));
- except
- Font:=Nil;
- Raise;
- end;
- end;
- destructor TMgrFont.destroy;
- begin
- try
- FreeGlyphs;
- finally
- FSizes.Free;
- inherited Destroy;
- end;
- end;
- procedure TMgrFont.FreeGlyphs;
- var r,t : integer;
- S : PMgrSize;
- G : PMgrGlyph;
- begin
- for r := FSizes.count-1 downto 0 do
- begin
- with PMgrSize(FSizes[r])^ do
- begin
- for t := Glyphs.count-1 downto 0 do
- begin
- with PMgrGlyph(Glyphs[t])^ do
- FT_Done_Glyph (Glyph);
- G := PMgrGlyph(Glyphs[t]);
- dispose (G);
- end;
- Glyphs.Free;
- end;
- S := PMgrSize(FSizes[r]);
- dispose (S);
- end;
- end;
- { TFontManager }
- constructor TFontManager.Create;
- var r : integer;
- begin
- inherited create;
- FList := Tlist.Create;
- FPaths := TStringList.Create;
- r := FT_Init_FreeType(FTLib);
- if r <> 0 then
- begin
- FTLib := nil;
- FTError (sErrInitializing, r);
- end;
- SearchPath := DefaultSearchPath;
- DefaultExtention := DefaultFontExtention;
- Resolution := DefaultResolution;
- end;
- destructor TFontManager.Destroy;
- procedure FreeFontObjects;
- var r : integer;
- begin
- for r := FList.Count-1 downto 0 do
- begin
- GetFont(r).Free;
- end;
- end;
- procedure FreeLibrary;
- var r : integer;
- begin
- r := FT_Done_FreeType (FTlib);
- if r <> 0 then
- FTError (sErrDestroying, r);
- end;
- begin
- FreeFontObjects;
- FList.Free;
- FPaths.Free;
- try
- if assigned(FTLib) then
- FreeLibrary;
- finally
- inherited Destroy;
- end;
- end;
- function TFontManager.GetSearchPath : string;
- var r : integer;
- begin
- if FPaths.count > 0 then
- begin
- result := FPaths[0];
- for r := 1 to FPaths.count-1 do
- result := result + ';' + FPaths[r];
- end
- else
- result := '';
- end;
- procedure TFontManager.SetSearchPath (AValue : string);
- procedure AddPath (apath : string);
- begin
- FPaths.Add (IncludeTrailingBackslash(Apath));
- end;
- var p : integer;
- begin
- while (AValue <> '') do
- begin
- p := pos (';', AValue);
- if p = 0 then
- begin
- AddPath (AValue);
- AValue := '';
- end
- else
- begin
- AddPath (copy(AValue,1,p-1));
- delete (AVAlue,1,p);
- end;
- end;
- end;
- procedure TFontManager.SetExtention (AValue : string);
- begin
- if AValue <> '' then
- if AValue[1] <> '.' then
- FExtention := '.' + AValue
- else
- FExtention := AValue
- else
- AValue := '';
- end;
- function TFontManager.SearchFont (afilename:string) : string;
- // returns full filename of font, taking SearchPath in account
- var p,fn : string;
- r : integer;
- begin
- if (pos('.', afilename)=0) and (DefaultFontExtention<>'') then
- fn := afilename + DefaultFontExtention
- else
- fn := aFilename;
- if FileExists(fn) then
- result := ExpandFilename(fn)
- else
- begin
- p := ExtractFilepath(fn);
- if p = '' then
- begin // no path given, look in SearchPaths
- r := FPaths.Count;
- repeat
- dec (r);
- until (r < 0) or FileExists(FPaths[r]+fn);
- if r < 0 then
- raise FreeTypeException.CreateFmt (sErrFontFileNotFound, [fn])
- else
- result := FPaths[r]+fn;
- end
- else
- raise FreeTypeException.CreateFmt (sErrFontFileNotFound, [afilename]);
- end;
- end;
- function TFontManager.GetFontId (afilename:string; anindex:integer) : integer;
- begin
- result := FList.count-1;
- while (result >= 0) and
- ( ({$ifdef CaseSense}CompareText{$else}CompareStr{$endif}
- (TMgrFont(FList[anIndex]).Filename, afilename) <> 0) or
- (anIndex <> TMgrFont(FList[anIndex]).font^.face_index)
- ) do
- dec (result);
- end;
- function TFontManager.CreateFont (afilename:string; anindex:integer) : integer;
- var f : TMgrFont;
- begin
- // writeln ('creating font ',afilename,' (',anindex,')');
- f := TMgrFont.Create (self, afilename, anindex);
- result := FList.Count;
- Flist.Add (f);
- end;
- function TFontManager.GetFont (FontID:integer) : TMgrFont;
- begin
- result := TMgrFont(FList[FontID]);
- if result <> CurFont then // set last used size of the font as current size
- begin
- CurSize := result.LastSize;
- end;
- end;
- procedure TFontManager.GetSize (aSize, aResolution : integer);
- var r : integer;
- begin
- if not ( assigned(CurSize) and
- (CurSize^.Size = aSize) and (CurSize^.resolution = aResolution)) then
- begin
- r := CurFont.FSizes.count;
- repeat
- dec (r)
- until (r < 0) or ( (PMgrSize(CurFont.FSizes[r])^.size = aSize) and
- (PMgrSize(CurFont.FSizes[r])^.resolution = FResolution) );
- if r < 0 then
- CurSize := CreateSize (aSize,aResolution)
- else
- CurSize := PMgrSize(CurFont.FSizes[r]);
- CurFont.LastSize := CurSize;
- end;
- end;
- function TFontManager.CreateSize (aSize, aResolution : integer) : PMgrSize;
- begin
- new (result);
- result^.Size := aSize;
- result^.Resolution := aResolution;
- result^.Glyphs := Tlist.Create;
- SetPixelSize (aSize,aResolution);
- CurFont.FSizes.Add (result);
- end;
- procedure TFontManager.SetPixelSize (aSize, aResolution : integer);
- procedure CheckSize;
- var r : integer;
- begin
- with Curfont.Font^ do
- begin
- r := Num_fixed_sizes;
- repeat
- dec (r);
- until (r < 0) or
- ( (available_sizes^[r].height=asize) and
- (available_sizes^[r].width=asize) );
- if r >= 0 then
- raise FreeTypeException.CreateFmt ('Size %d not available for %s %s',
- [aSize, style_name, family_name]);
- end;
- end;
- var s : longint;
- Err : integer;
- begin
- with Curfont, Font^ do
- if (face_flags and FT_Face_Flag_Fixed_Sizes) <> 0 then
- begin
- CheckSize;
- Err := FT_Set_pixel_sizes (Font, aSize, aSize);
- if Err <> 0 then
- FTError (format(sErrSetPixelSize,[aSize,aResolution]), Err);
- end
- else
- begin
- s := aSize shl 6;
- Err := FT_Set_char_size (Font, s, s, aResolution, aResolution);
- if Err <> 0 then
- FTError (format(sErrSetCharSize,[aSize,aResolution]), Err);
- end;
- end;
- procedure TFontManager.MakeTransformation (angle:real; var Transformation:FT_Matrix);
- begin
- with Transformation do
- begin
- xx := round( cos(angle)*$10000);
- xy := round(-sin(angle)*$10000);
- yx := round( sin(angle)*$10000);
- yy := round( cos(angle)*$10000);
- end;
- end;
- function TFontManager.CreateGlyph (c : char) : PMgrGlyph;
- var e : integer;
- begin
- new (result);
- result^.character := c;
- result^.GlyphIndex := FT_Get_Char_Index (CurFont.font, ord(c));
- e := FT_Load_Glyph (CurFont.font, result^.GlyphIndex, FT_Load_Default);
- if e <> 0 then
- begin
- FTError (sErrLoadingGlyph, e);
- end;
- e := FT_Get_Glyph (Curfont.font^.glyph, result^.glyph);
- if e <> 0 then
- begin
- FTError (sErrLoadingGlyph, e);
- end;
- CurSize^.Glyphs.Add (result);
- end;
- function TFontManager.GetGlyph (c : char) : PMgrGlyph;
- var r : integer;
- begin
- With CurSize^ do
- begin
- r := Glyphs.Count;
- repeat
- dec (r)
- until (r < 0) or (PMgrGlyph(Glyphs[r])^.character = c);
- if r < 0 then
- result := CreateGlyph (c)
- else
- result := PMgrGlyph(Glyphs[r]);
- end;
- end;
- procedure TFontManager.InitMakeString (FontID, Size:integer);
- begin
- GetSize (size,Resolution);
- UseKerning := ((Curfont.font^.face_flags and FT_FACE_FLAG_KERNING) <> 0);
- end;
- function TFontManager.MakeString (FontId:integer; Text:string; size:integer; angle:real) : TStringBitmaps;
- var g : PMgrGlyph;
- bm : PFT_BitmapGlyph;
- gl : PFT_Glyph;
- e, prevIndex, prevx, c, r, rx : integer;
- pre, adv, pos, kern : FT_Vector;
- buf : PByteArray;
- reverse : boolean;
- trans : FT_Matrix;
- begin
- CurFont := GetFont(FontID);
- if (Angle = 0) or // no angle asked, or can't work with angles (not scalable)
- ((CurFont.Font^.face_flags and FT_FACE_FLAG_SCALABLE)=0) then
- result := MakeString (FontID, Text, Size)
- else
- begin
- InitMakeString (FontID, Size);
- c := length(text);
- result := TStringBitmaps.Create(c);
- if (CurRenderMode = FT_RENDER_MODE_MONO) then
- result.FMode := btBlackWhite
- else
- result.FMode := bt256Gray;
- MakeTransformation (angle, trans);
- prevIndex := 0;
- prevx := 0;
- pos.x := 0;
- pos.y := 0;
- pre.x := 0;
- pre.y := 0;
- for r := 0 to c-1 do
- begin
- // retrieve loaded glyph
- g := GetGlyph (Text[r+1]);
- // check kerning
- if UseKerning and (g^.glyphindex <>0) and (PrevIndex <> 0) then
- begin
- prevx := pre.x;
- FTCheck(FT_Get_Kerning (Curfont.Font, prevIndex, g^.GlyphIndex, ft_kerning_default, kern),sErrKerning);
- pre.x := pre.x + kern.x;
- end;
- // render the glyph
- Gl:=Nil;
- FTCheck(FT_Glyph_Copy (g^.glyph, gl),sErrMakingString1);
- // placing the glyph
- FTCheck(FT_Glyph_Transform (gl, nil, @pre),sErrMakingString2);
- adv := gl^.advance;
- // rotating the glyph
- FTCheck(FT_Glyph_Transform (gl, @trans, nil),sErrMakingString3);
- // rendering the glyph
- FTCheck(FT_Glyph_To_Bitmap (gl, CurRenderMode, nil, true),sErrMakingString4);
- // Copy what is needed to record
- bm := PFT_BitmapGlyph(gl);
- with result.Bitmaps[r]^ do
- begin
- with gl^.advance do
- begin
- advanceX := x div 64;
- advanceY := y div 64;
- end;
- with bm^ do
- begin
- height := bitmap.rows;
- width := bitmap.width;
- x := {(pos.x div 64)} + left; // transformed bitmap has correct x,y
- y := {(pos.y div 64)} - top; // not transformed has only a relative correction
- buf := PByteArray(bitmap.buffer);
- reverse := (bitmap.pitch < 0);
- if reverse then
- begin
- pitch := -bitmap.pitch;
- getmem (data, pitch*height);
- for rx := height-1 downto 0 do
- move (buf^[rx*pitch], data^[(height-rx-1)*pitch], pitch);
- end
- else
- begin
- pitch := bitmap.pitch;
- rx := pitch*height;
- getmem (data, rx);
- move (buf^[0], data^[0], rx);
- end;
- end;
- end;
- // place position for next glyph
- with gl^.advance do
- begin
- pos.x := pos.x + (x div 1024);
- pos.y := pos.y + (y div 1024);
- end;
- with adv do
- pre.x := pre.x + (x div 1024);
- if prevx > pre.x then
- pre.x := prevx;
- // finish rendered glyph
- FT_Done_Glyph (gl);
- end;
- result.FText := Text;
- result.CalculateGlobals;
- end;
- end;
- function TFontManager.MakeString (FontId:integer; Text:string; Size:integer) : TStringBitmaps;
- var g : PMgrGlyph;
- bm : PFT_BitmapGlyph;
- gl : PFT_Glyph;
- e, prevIndex, prevx, c, r, rx : integer;
- pos, kern : FT_Vector;
- buf : PByteArray;
- reverse : boolean;
- begin
- CurFont := GetFont(FontID);
- InitMakeString (FontID, Size);
- c := length(text);
- result := TStringBitmaps.Create(c);
- if (CurRenderMode = FT_RENDER_MODE_MONO) then
- result.FMode := btBlackWhite
- else
- result.FMode := bt256Gray;
- prevIndex := 0;
- prevx := 0;
- pos.x := 0;
- pos.y := 0;
- for r := 0 to c-1 do
- begin
- // retrieve loaded glyph
- g := GetGlyph (Text[r+1]);
- // check kerning
- if UseKerning and (g^.glyphindex <>0) and (PrevIndex <> 0) then
- begin
- prevx := pos.x;
- e := FT_Get_Kerning (Curfont.Font, prevIndex, g^.GlyphIndex, ft_kerning_default, kern);
- if e <> 0 then
- FTError (sErrKerning, e);
- pos.x := pos.x + kern.x;
- end;
- // render the glyph
- FTCheck(FT_Glyph_Copy (g^.glyph, gl),sErrMakingString1);
- FTCheck(FT_Glyph_To_Bitmap (gl, CurRenderMode, @pos, true),sErrMakingString4);
- // Copy what is needed to record
- bm := PFT_BitmapGlyph(gl);
- with result.Bitmaps[r]^ do
- begin
- with gl^.advance do
- begin
- advanceX := x shr 6;
- advanceY := y shr 6;
- end;
- with bm^ do
- begin
- height := bitmap.rows;
- width := bitmap.width;
- x := (pos.x shr 6) + left; // transformed bitmap has correct x,y
- y := (pos.y shr 6) - top; // not transformed has only a relative correction
- buf := PByteArray(bitmap.buffer);
- reverse := (bitmap.pitch < 0);
- if reverse then
- begin
- pitch := -bitmap.pitch;
- getmem (data, pitch*height);
- for rx := height-1 downto 0 do
- move (buf^[rx*pitch], data^[(height-rx-1)*pitch], pitch);
- end
- else
- begin
- pitch := bitmap.pitch;
- rx := pitch*height;
- getmem (data, rx);
- move (buf^[0], data^[0], rx);
- end;
- end;
- end;
- // place position for next glyph
- pos.x := pos.x + (gl^.advance.x shr 10);
- // pos.y := pos.y + (gl^.advance.y shr 6); // for angled texts also
- if prevx > pos.x then
- pos.x := prevx;
- // finish rendered glyph
- FT_Done_Glyph (gl);
- end;
- result.FText := Text;
- result.CalculateGlobals;
- end;
- function TFontManager.GetString (FontId:integer; Text:string; size:integer; angle:real) : TStringBitmaps;
- // Black and white
- begin
- CurRenderMode := FT_RENDER_MODE_MONO;
- result := MakeString (FontID, text, Size, angle);
- end;
- function TFontManager.GetStringGray (FontId:integer; Text:string; size:integer; angle:real) : TStringBitmaps;
- // Anti Aliased gray scale
- begin
- CurRenderMode := FT_RENDER_MODE_NORMAL;
- result := MakeString (FontID, text, Size, angle);
- end;
- { Procedures without angle have own implementation to have better speed }
- function TFontManager.GetString (FontId:integer; Text:string; Size:integer) : TStringBitmaps;
- // Black and white, following the direction of the font (left to right, top to bottom, ...)
- begin
- CurRenderMode := FT_RENDER_MODE_MONO;
- result := MakeString (FontID, text, Size);
- end;
- function TFontManager.GetStringGray (FontId:integer; Text:string; Size:integer) : TStringBitmaps;
- // Anti Aliased gray scale, following the direction of the font (left to right, top to bottom, ...)
- begin
- CurRenderMode := FT_RENDER_MODE_NORMAL;
- result := MakeString (FontID, text, Size);
- end;
- function TFontManager.RequestFont (afilename:string) : integer;
- begin
- result := RequestFont (afilename,0);
- end;
- function TFontManager.RequestFont (afilename:string; anindex:integer) : integer;
- var s : string;
- begin
- if afilename = '' then
- result := -1
- else
- begin
- s := SearchFont (afilename);
- result := GetFontID (s,anindex);
- if result < 0 then
- result := CreateFont (s,anindex);
- end;
- end;
- function TFontManager.GetFreeTypeFont (aFontID:integer) : PFT_Face;
- begin
- result := GetFont(aFontID).font;
- end;
- { TStringBitmaps }
- function TStringBitmaps.GetCount : integer;
- begin
- result := FList.Count;
- end;
- function TStringBitmaps.GetBitmap (index:integer) : PFontBitmap;
- begin
- result := PFontBitmap(FList[index]);
- end;
- constructor TStringBitmaps.Create (ACount : integer);
- var r : integer;
- bm : PFontBitmap;
- begin
- inherited create;
- FList := Tlist.Create;
- FList.Capacity := ACount;
- for r := 0 to ACount-1 do
- begin
- new (bm);
- FList.Add (bm);
- end;
- end;
- destructor TStringBitmaps.destroy;
- var r : integer;
- bm : PFontBitmap;
- begin
- for r := 0 to Flist.count-1 do
- begin
- bm := PFontBitmap(FList[r]);
- freemem (bm^.data);
- dispose (bm);
- end;
- FList.Free;
- inherited;
- end;
- procedure TStringBitmaps.CalculateGlobals;
- var r : integer;
- begin
- if count = 0 then
- Exit;
- // check first 2 bitmaps for left side
- // check last 2 bitmaps for right side
- with BitMaps[0]^ do
- begin
- FBounds.left := x;
- FBounds.top := y + height;
- FBounds.bottom := y;
- end;
- with Bitmaps[count-1]^ do
- FBounds.right := x + width;
- if count > 1 then
- begin
- with Bitmaps[1]^ do
- r := x;
- if r < FBounds.left then
- FBounds.left := r;
- with Bitmaps[count-2]^ do
- r := x + width;
- if r > FBounds.right then
- FBounds.right := r;
- end;
- // check top/bottom of other bitmaps
- for r := 1 to count-1 do
- with Bitmaps[r]^ do
- begin
- if FBounds.top < y + height then
- FBounds.top := y + height;
- if FBounds.bottom > y then
- FBounds.bottom := y;
- end;
- end;
- procedure TStringBitmaps.GetBoundRect (var aRect : TRect);
- begin
- aRect := FBounds;
- end;
- {$ifdef win32}
- procedure SetWindowsFontPath;
- begin
- DefaultSearchPath := includetrailingbackslash(GetEnv('windir')) + 'fonts';
- end;
- {$endif}
- initialization
- {$ifdef win32}
- SetWindowsFontPath;
- {$endif}
- end.
|