unit DEngFreeType;

//
//  Some FreeType specific utilities.
//

{$MODE FPC}
{$MODESWITCH DEFAULTPARAMETERS}
{$MODESWITCH OUT}
{$MODESWITCH RESULT}

interface

uses
  dstrnum,
  DEng,
  freetype;

function DEngFT_Check(Location: PAnsiChar;
                       Error: FT_Error): Boolean;
      // If Error<>0, prints error message and returns False.
      // Returns True otherwise.

function DEngFT_Init(out Lib: FT_Library): Boolean; inline;

function DEngFT_Done(Lib: FT_Library): Boolean; inline;

// TODO support loading from TStream and assets
function DEngFT_LoadFace(Lib: FT_Library;
                         const FileName: AnsiString;
                         out Face: FT_Face;
                         FaceIndex: LongInt = 0): Boolean;

function DEngFT_FreeFace(Face: FT_Face): Boolean; inline;

function DEngFT_LoadChar(Face: FT_FACE; U: PtrUInt): Boolean;

implementation

function DEngFT_Check(Location: PAnsiChar;
                       Error: FT_Error): Boolean;
begin
  if Error <> 0 then begin
    LogTagged('DE', 'FAILED ' + Location + ': error=' + IntToStr(Error));
    Exit(False);
  end;
  Exit(True);
end;

function DEngFT_Init(out Lib: FT_Library): Boolean;
begin
  if DEngFT_Check('FT_Init_FreeType', FT_Init_FreeType(@Lib)) then
    Exit(True);
  Lib := nil;
  Exit(False);
end;

function DEngFT_Done(Lib: FT_Library): Boolean;
begin
  Exit(DEngFT_Check('FT_Done_FreeType', FT_Done_FreeType(Lib)));
end;

function DEngFT_LoadFace(Lib: FT_Library;
                         const FileName: AnsiString;
                         out Face: FT_Face;
                         FaceIndex: LongInt = 0): Boolean;
var
  Error: FT_Error;
begin
  Error := FT_New_Face(Lib, @FileName[1], FaceIndex, @Face);
  case Error of
    0: ;
    FT_Err_Unknown_File_Format: begin
        LogTagged('DE', 'FAILED ' + FileName + ': unknown file format');
        Exit(False);
      end;
  else
    LogTagged('DE', 'FAILED ' + FileName + ': FT_New_Face returned error ' + IntToStr(Error));
    Exit(False);
  end;
  // Uncomments this if you want to force unicode:
  // Exit(DEngFT_Check('FT_Select_Charmap', FT_Select_Charmap(Face, FT_ENCODING_UNICODE)));
  Exit(True);
end;

function DEngFT_FreeFace(Face: FT_Face): Boolean;
begin
  Exit(DEngFT_Check('FT_Done_Face', FT_Done_Face(Face)));
end;

function DEngFT_LoadChar(Face: FT_FACE; U: PtrUInt): Boolean;
begin
  if FT_Load_Char(Face, U, FT_LOAD_RENDER) <> 0 then
    Exit(False);
  if Face^.glyph^.format <> FT_GLYPH_FORMAT_BITMAP then begin
    if FT_Render_Glyph(Face^.glyph, FT_RENDER_MODE_NORMAL) <> 0 then
      Exit(False);
  end;
  Exit(True);
end;

end.
