(*******************************************************************
 *
 *  FreeType.Pas
 *
 *    High-level interface specification.
 *
 *  Copyright 1996 David Turner, Robert Wilhelm and Werner Lemberg
 *
 *  This file is part of the FreeType project, and may only be used
 *  modified and distributed under the terms of the FreeType project
 *  license, LICENSE.TXT. By continuing to use, modify or distribute
 *  this file you indicate that you have read the license and
 *  understand and accept it fully.
 *
 *  Notes :
 *
 *    This is the only file that should be included by client
 *    application sources for the final release. All other types
 *    and functions defined in the "tt*.h" files are library
 *    internals, and should not be included ( except of course
 *    during development, as now )
 *
 ******************************************************************)
{
From: http://www.freetype.org/license.html

FreeType comes with two licenses from which you can choose the one which fits your needs best.

The FreeType License is the most commonly used one. Full text here: http://www.freetype.org/FTL.TXT
 It is a BSD-style license with a credit clause (and thus compatible with GPLv3 but not GPLv2).

The GNU General Public License (GPL), version 2.
 For all projects which use GPLv2 also or which need a license compatible to the GPLv2.
}
unit LazFreeType;

interface
{$mode objfpc}{$H+}
{$R-}
uses TTTypes, Classes;

  (***********************************************************************)
  (*                                                                     *)
  (*                  Base Library Functions                             *)
  (*                                                                     *)
  (***********************************************************************)

  (*****************************************************************)
  (*  Initialise the engine                                        *)
  (*                                                               *)
  function  TT_Init_FreeType : TT_Error;

  (*****************************************************************)
  (*  Finalise the engine - discards all objects                   *)
  (*                                                               *)
  procedure TT_Done_FreeType;

  (*****************************************************************)
  (*  Set the gray-level palette used for font-smoothing           *)
  (*                                                               *)
  (*  it is an array of 5 bytes following this convention :        *)
  (*                                                               *)
  (*    palette[0] := background (white)                           *)
  (*    palette[1] := light                                        *)
  (*    palette[2] := medium                                       *)
  (*    palette[3] := dark                                         *)
  (*    palette[4] := foreground (black)                           *)
  (*                                                               *)
  function TT_Set_Raster_Palette( palette : TT_Gray_Palette ) : TT_Error;

  (***********************************************************************)
  (*                                                                     *)
  (*                    Face Management functions                        *)
  (*                                                                     *)
  (***********************************************************************)

  (*****************************************************************)
  (*  Open a new font file and returns a handle for it in '_face'  *)
  (*                                                               *)
  (*  The file can be a TrueType collection, in which case the     *)
  (*  first embedded font will be loaded.                          *)
  (*                                                               *)
  function TT_Open_Face( fontname  : string;
                         var _face : TT_Face ) : TT_Error;

  function TT_Open_Face( AStream : TStream; AStreamOwner: boolean;
                         var _face : TT_Face ) : TT_Error;

  (*****************************************************************)
  (*  Open a font file embedded in a collection.                   *)
  (*                                                               *)
  function TT_Open_Collection( fontname  : string;
                               faceIndex : integer;
                               var _face : TT_Face ) : TT_Error;

  (*****************************************************************)
  (*  Return face properties in 'prop'                             *)
  (*                                                               *)
  function TT_Get_Face_Properties( _face    : TT_Face;
                                   out prop : TT_Face_Properties ) : TT_Error;

  (*****************************************************************)
  (*  Set face's generic pointer                                   *)
  (*                                                               *)
  function TT_Set_Face_Pointer( _face : TT_Face;
                                data  : Pointer ) : TT_Error;

  (*****************************************************************)
  (*  Get face's generic pointer                                   *)
  (*                                                               *)
  function TT_Get_Face_Pointer( _face : TT_Face ) : Pointer;

  (*****************************************************************)
  (*  close a given face object. This releases all child objects   *)
  (*  like instances and glyphs                                    *)
  (*                                                               *)
  function TT_Close_Face( _face : TT_Face ) : TT_Error;

  (***********************************************************************)
  (*                                                                     *)
  (*                  Instance management functions                      *)
  (*                                                                     *)
  (***********************************************************************)

  (*****************************************************************)
  (*  open a new face instance and return a handle in '_ins'       *)
  (*                                                               *)
  function TT_New_Instance( _face    : TT_Face;
                            var _ins : TT_Instance ) : TT_Error;

  (*****************************************************************)
  (*  set an instance's device resolutions, expressed in dpi       *)
  (*                                                               *)
  function TT_Set_Instance_Resolutions( _ins         : TT_Instance;
                                        x_resolution : Integer;
                                        y_resolution : Integer ) : TT_Error;

  (*****************************************************************)
  (*  set an instance's point size (assumes width==height)         *)
  (*                                                               *)
  function TT_Set_Instance_PointSize( _ins      : TT_Instance;
                                      pointsize : Integer ) : TT_Error;

  (*****************************************************************)
  (*  set an instance's point size (assumes width==height)         *)
  (*                                                               *)
  function TT_Set_Instance_CharSize( _ins     : TT_Instance;
                                     charsize : Integer ) : TT_Error;

  (*****************************************************************)
  (*  set an instance's point size (assumes width==height)         *)
  (*                                                               *)
  function TT_Set_Instance_CharSizes( _ins      : TT_Instance;
                                      charsizex : Integer;
                                      charsizey : Integer ) : TT_Error;

  (*****************************************************************)
  (*  set an instance's height and width, expressed in pixels      *)
  (*                                                               *)
  function TT_Set_Instance_PixelSizes( _ins      : TT_Instance;
                                       pixelX    : Integer;
                                       pixelY    : Integer;
                                       pointsize : Integer ) : TT_Error;

  (*****************************************************************)
  (*  set an instance's height and width, expressed in pixels      *)
  (*                                                               *)

  (*****************************************************************)
  (*  the core truetype engine doesn't provide _direct_ support    *)
  (*  for rotation or stretching. This means that the transforms   *)
  (*  must be applied on the glyph outline by a higher-level       *)
  (*  library or the client application. However, we use two flags *)
  (*  to notice the TrueType hinter that the glyphs will be        *)
  (*  transformed later.                                           *)
  (*                                                               *)
  (*    rotated   : set if the glyphs are to be rotated            *)
  (*    distorted : set if the glyphs are to be distorted          *)
  (*                                                               *)
  (*  an application is any transform that doesn't keep distances  *)
  (*  constants. skewing and stretching are examples of distorsion *)
  (*                                                               *)
  function TT_Set_Instance_Transforms( _ins      : TT_Instance;
                                       rotated   : Boolean;
                                       distorted : Boolean ) : TT_Error;

  (*****************************************************************)
  (*  Return instance metrics in 'm'                               *)
  (*                                                               *)
  function TT_Get_Instance_Metrics( _ins  : TT_Instance;
                                    out m : TT_Instance_Metrics ) : TT_Error;

  (*****************************************************************)
  (*  Set instance generic pointer                                 *)
  (*                                                               *)
  function TT_Set_Instance_Pointer( _ins : TT_Instance;
                                    data : Pointer ) : TT_Error;

  (*****************************************************************)
  (*  Get instance generic pointer                                 *)
  (*                                                               *)
  function TT_Get_Instance_Pointer( _ins : TT_Instance ) : Pointer;

  (*****************************************************************)
  (*  Close an instance                                            *)
  (*                                                               *)
  function TT_Done_Instance( _ins : TT_Instance ) : TT_Error;

  (***********************************************************************)
  (*                                                                     *)
  (*                  Glyph management functions                         *)
  (*                                                                     *)
  (***********************************************************************)

  (*****************************************************************)
  (*  Create a new glyph container, return a handle in '_glyph'    *)
  (*                                                               *)
  function TT_New_Glyph( _face      : TT_Face;
                         var _glyph : TT_Glyph ) : TT_Error;

  (*****************************************************************)
  (*  Releases a glyph container                                   *)
  (*                                                               *)
  function TT_Done_Glyph( _glyph : TT_Glyph ) : TT_Error;

  (*****************************************************************)
  (*  Load a glyph inside a container                              *)
  (*                                                               *)
  function  TT_Load_Glyph( _instance   : TT_Instance;
                           _glyph      : TT_Glyph;
                           glyph_index : Word;
                           load_flags  : Integer ) : TT_Error;

  (*****************************************************************)
  (*  Copy a glyph container into another one                      *)
  (*                                                               *)
  function TT_Copy_Glyph( var source : TT_Glyph;
                          var target : TT_Glyph ) : TT_Error;

const
  TT_Load_Scale_Glyph = 1;  (* ask the loader to scale the glyph  *)
                            (* to the current pointsize/transform *)

  TT_Load_Hint_Glyph  = 2;  (* when scaling is on, ask the loader *)
                            (* to hint the glyph too..            *)

  TT_Load_Debug       = 16;

  TT_Load_Default     = TT_Load_Scale_Glyph or
                        TT_Load_Hint_Glyph;


  (*****************************************************************)
  (*  Get a glyph's outline                                        *)
  (*                                                               *)
  function TT_Get_Glyph_Outline( _glyph      : TT_Glyph;
                                 var outline : TT_Outline ) : TT_Error;

  (*****************************************************************)
  (*  Get a glyph's metrics                                        *)
  (*                                                               *)
  function TT_Get_Glyph_Metrics( _glyph       : TT_Glyph;
                                 out gmetrics : TT_Glyph_Metrics ) : TT_Error;

  (*****************************************************************)
  (*  Get a glyph's big metrics                                    *)
  (*                                                               *)
  function TT_Get_Glyph_Big_Metrics( _glyph       : TT_Glyph;
                                     out gmetrics : TT_Big_Glyph_Metrics
                                   ) : TT_Error;

  (*****************************************************************)
  (*  Render a glyph's bitmap                                      *)
  (*                                                               *)
  function TT_Get_Glyph_Bitmap( _glyph   : TT_Glyph;
                                var map  : TT_Raster_Map;
                                x_offset : TT_F26Dot6;
                                y_offset : TT_F26Dot6; rasterizer: TFreeTypeCustomRasterizer = nil ) : TT_Error;

  (*****************************************************************)
  (*  Render a glyph's pixmap (i.e. smoothed glyph )               *)
  (*                                                               *)
  function TT_Get_Glyph_Pixmap( _glyph   : TT_Glyph;
                                var map  : TT_Raster_Map;
                                x_offset : TT_F26Dot6;
                                y_offset : TT_F26Dot6; rasterizer: TFreeTypeCustomRasterizer = nil  ) : TT_Error;

  function TT_Get_Glyph_Pixmap_HQ( _glyph   : TT_Glyph;
                                var map  : TT_Raster_Map;
                                x_offset : TT_F26Dot6;
                                y_offset : TT_F26Dot6; rasterizer: TFreeTypeCustomRasterizer = nil  ) : TT_Error;

  function TT_Render_Directly_Glyph_Gray( var _glyph   : TT_Glyph;
                              x_offset : TT_F26Dot6;
                              y_offset : TT_F26Dot6;
                              x,y,tx,ty: integer;
                              OnRender: TDirectRenderingFunction; rasterizer: TFreeTypeCustomRasterizer = nil ) : TT_Error;

  function TT_Render_Directly_Glyph_HQ( var _glyph   : TT_Glyph;
                              x_offset : TT_F26Dot6;
                              y_offset : TT_F26Dot6;
                              x,y,tx,ty: integer;
                              OnRender: TDirectRenderingFunction; rasterizer: TFreeTypeCustomRasterizer = nil ) : TT_Error;

  (***********************************************************************)
  (*                                                                     *)
  (*                      Outline functions                              *)
  (*                                                                     *)
  (***********************************************************************)

  (*****************************************************************)
  (*  Apply translation to an outline                              *)
  (*                                                               *)
  function TT_Translate_Outline( var out : TT_Outline;
                                 x, y    : TT_F26Dot6 ) : TT_Error;

  (*****************************************************************)
  (*  Apply a 2x2 transform to an outline                          *)
  (*                                                               *)
  function TT_Transform_Outline( var out : TT_Outline;
                                 var mat : TT_Matrix ) : TT_Error;

  (*****************************************************************)
  (*  Apply a 2x2 transform to a vector                            *)
  (*                                                               *)
  function TT_Transform_Vector( var x, y : TT_F26Dot6;
                                var mat  : TT_Matrix ) : TT_Error;

  (*****************************************************************)
  (*  Render an outline into a bitmap                              *)
  (*                                                               *)
  function TT_Get_Outline_Bitmap( var out : TT_Outline;
                                  var map : TT_raster_Map; rasterizer: TFreeTypeCustomRasterizer = nil  ) : TT_Error;

  (*****************************************************************)
  (*  Render an outline into a pixmap                              *)
  (*                                                               *)
  function TT_Get_Outline_Pixmap( var out : TT_Outline;
                                  var map : TT_raster_Map; rasterizer: TFreeTypeCustomRasterizer = nil  ) : TT_Error;

  function TT_Get_Outline_Pixmap_HQ( var out : TT_Outline;
                                  var map : TT_raster_Map; rasterizer: TFreeTypeCustomRasterizer = nil  ) : TT_Error;

  function TT_Render_Directly_Outline_Gray( var out : TT_Outline;
                                  x, y, tx, ty: integer;
                                  OnRender: TDirectRenderingFunction; rasterizer: TFreeTypeCustomRasterizer = nil ) : TT_Error;

  function TT_Render_Directly_Outline_HQ( var out : TT_Outline;
                                  x, y, tx, ty: integer;
                                  OnRender: TDirectRenderingFunction; rasterizer: TFreeTypeCustomRasterizer = nil ) : TT_Error;

  (*****************************************************************)
  (*  Get an outline's bounding box                                *)
  (*                                                               *)
  function TT_Get_Outline_BBox( var out  : TT_Outline;
                                var bbox : TT_Bbox;
                                nbPhantomPoints : integer = 0 ) : TT_Error;

  (*****************************************************************)
  (*  Get the kerning between two glyph                            *)
  (*                                                               *)
  function TT_Get_KerningInfo( _Face: TT_Face;
                           glyph_left, glyph_right: Word) : TT_KerningInfo;

  (*****************************************************************)
  (*  Create a new glyph outline                                   *)
  (*                                                               *)
  function TT_New_Outline( n_points   : integer;
                           n_contours : integer;
                           var out    : TT_Outline ) : TT_Error;

  (*****************************************************************)
  (*  Copy a glyph outline into another one                        *)
  (*                                                               *)
  function TT_Copy_Outline( var source : TT_Outline;
                            var target : TT_Outline ) : TT_Error;

  (*****************************************************************)
  (*  Clone a given outline. This will create the outline, then    *)
  (*  copy the source in it                                        *)
  (*                                                               *)
  function TT_Clone_Outline( var source : TT_Outline;
                             var target : TT_Outline ) : TT_Error;

  (*****************************************************************)
  (*  Discards a glyph outline                                     *)
  (*                                                               *)
  function TT_Done_Outline( var out : TT_Outline ) : TT_Error;

  (***********************************************************************)
  (*                                                                     *)
  (*                     Character Mapping support                       *)
  (*                                                                     *)
  (***********************************************************************)

  (*****************************************************************)
  (*  Get a face's number of character maps                        *)
  (*                                                               *)
  function  TT_Get_CharMap_Count( face : TT_Face ) : integer;

  (*****************************************************************)
  (*  Get a given char. map's ID in a face                         *)
  (*                                                               *)
  function  TT_Get_CharMap_ID( face         : TT_Face;
                               charmapIndex : integer;
                               var platform : integer;
                               var encoding : integer ) : TT_Error;

  (*****************************************************************)
  (*  Get a handle to a given char. map                            *)
  (*                                                               *)
  function  TT_Get_CharMap( face         : TT_Face;
                            charmapIndex : integer;
                            var charMap  : TT_CharMap ) : TT_Error;

  (*****************************************************************)
  (*  Translate from char. code to glyph index                     *)
  (*                                                               *)
  function  TT_Char_Index( charmap  : TT_CharMap;
                           charCode : Longint ) : Word;

  (***********************************************************************)
  (*                                                                     *)
  (*                        Names Table support                          *)
  (*                                                                     *)
  (***********************************************************************)

  (*****************************************************************)
  (*  Return number of name table entries                          *)
  (*                                                               *)
  function  TT_Get_Name_Count( face : TT_Face ) : integer;

  (*****************************************************************)
  (*  Return the ID of a given name table entry                    *)
  (*                                                               *)
  function  TT_Get_Name_ID( face         : TT_Face;
                            nameIndex    : integer;
                            out platform : integer;
                            out encoding : integer;
                            out language : integer;
                            out nameid   : integer ) : TT_Error;

  (*****************************************************************)
  (*  Return a given name table string                             *)
  (*                                                               *)
  function  TT_Get_Name_String( face      : TT_Face;
                                nameIndex : integer;
                                out str   : Pointer;
                                out len   : integer ) : TT_Error;

  function  TT_Get_Name_String( face      : TT_Face;
                                nameIndex : integer ) : string;

  (***********************************************************************)
  (*                                                                     *)
  (*                        Font Storage Access                          *)
  (*                                                                     *)
  (***********************************************************************)

  (*****************************************************************)
  (*  Access font data and copies it into user block               *)
  (*                                                               *)
  function  TT_Get_Font_Data( face       : TT_Face;
                              tableTag   : Longint;
                              offset     : Longint;
                              var buffer;
                              var length : longint ) : TT_Error;

implementation

uses
  TTError,
  TTCalc,
  TTMemory,
  TTTables,
  TTCache,
  TTFile,
  TTCMap,
  TTObjs,
  TTLoad,
  TTGLoad,
  TTKern,
  TTRaster;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Init_FreeType : TT_Error;
  begin
    if TTMemory_Init or
       TTCache_Init  or
       TTFile_Init   or
       TTObjs_Init   or
       TTRaster_Init then
    begin
      TT_Init_FreeType := error;
      exit;
    end;

    TT_Init_FreeType := TT_Err_Ok;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  procedure TT_Done_FreeType;
  begin
    TTRaster_Done;
    TTObjs_Done;
    TTFile_Done;
    TTCache_Done;
    TTMemory_Done;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Set_Raster_Palette( palette : TT_Gray_Palette ) : TT_Error;
  begin
    TTGetDefaultRasterizer.Set_Raster_Palette( palette );
    TT_Set_Raster_Palette := TT_Err_Ok;
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Open_Face( fontname  : string;
                         var _face : TT_Face ) : TT_Error;
  var
    input        : TFont_Input;
  begin
    input.fontIndex := 0;

    if TT_Open_Stream( fontname, input.stream ) then
    begin
      TT_Open_Face    := error;
      exit;
    end;

    Cache_New( face_cache, Pointer(_face), @input );

    TT_Open_Face := error;
  end;

  function TT_Open_Face(AStream: TStream; AStreamOwner: boolean;
    var _face: TT_Face): TT_Error;
  var
    input        : TFont_Input;
  begin
    input.fontIndex := 0;

    if TT_Open_Stream( AStream, AStreamOwner, input.stream ) then
    begin
      TT_Open_Face    := error;
      exit;
    end;

    Cache_New( face_cache, Pointer(_face), @input );

    TT_Open_Face := error;
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Open_Collection( fontname  : string;
                               faceIndex : integer;
                               var _face : TT_Face ) : TT_Error;
  var
    input : TFont_Input;
  begin
    input.fontIndex := faceIndex;

    if TT_Open_Stream( fontname, input.stream ) then
    begin
      TT_Open_Collection := error;
      exit;
    end;

    Cache_New( face_cache, Pointer(_face), @input );

    TT_Open_Collection := error;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Get_Face_Properties( _face    : TT_Face;
                                   out prop : TT_Face_Properties ) : TT_Error;
  var
    face : PFace;
  begin
    face := _face.z;
    if face <> nil then
    begin
      with prop do
      begin
        num_Glyphs   := face^.numGlyphs;
        max_Points   := face^.maxPoints;
        max_Contours := face^.maxContours;
        max_Faces    := face^.ttcHeader.dirCount;
        header       := @face^.fontHeader;
        horizontal   := @face^.horizontalHeader;

        if face^.verticalInfo then
          vertical := @face^.verticalHeader
        else
          vertical := nil;

        os2          := @face^.os2;
        postscript   := @face^.postscript;
      end;
      TT_Get_Face_Properties := TT_Err_Ok;
    end
    else
      TT_Get_Face_Properties := TT_Err_Invalid_Face_Handle;
  end;


  (*****************************************************************)
  (*  Set face's generic pointer                                   *)
  (*                                                               *)
  function TT_Set_Face_Pointer( _face : TT_Face;
                                data  : Pointer ) : TT_Error;
  var
    face :PFace;
  begin
    face := PFace(_face.z);
    if face <> nil then
      begin
        face^.genericP      := data;
        TT_Set_Face_Pointer := TT_Err_Ok;
      end
    else
      TT_Set_Face_Pointer := TT_Err_Invalid_Face_Handle;
  end;

  (*****************************************************************)
  (*  Get face's generic pointer                                   *)
  (*                                                               *)
  function TT_Get_Face_Pointer( _face : TT_Face ) : Pointer;
  var
    face : PFace;
  begin
    face := PFace(_face.z);
    if face <> nil then
      TT_Get_Face_Pointer := face^.genericP
    else
      TT_get_Face_Pointer := nil;
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Close_Face( _face : TT_Face ) : TT_Error;
  var
    face : PFace;
  begin
    face := _face.z;
    if face <> nil then
      begin
        error := TT_Err_Ok;
        (* Note : the stream is closed by the face destructor !! *)
        Cache_Done( face_cache, _face.z );
        TT_Close_Face := error;
      end
    else
      TT_Close_Face := TT_Err_Invalid_Face_Handle;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_New_Instance( _face    : TT_Face;
                            var _ins : TT_Instance ) : TT_Error;
  var
    face : PFace;
  begin
    face := _face.z;
    if face <> nil then
      begin
        error := TT_Err_Ok;
        if not Cache_New( face^.instances, _ins.z, face ) then
          Instance_Init( _ins.z );
        TT_New_Instance := error;
      end
    else
      TT_New_Instance := TT_Err_Invalid_Face_Handle;
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Set_Instance_Resolutions( _ins         : TT_Instance;
                                        x_resolution : Integer;
                                        y_resolution : Integer ) : TT_Error;
  var
    ins : PInstance;
  begin
    ins := _ins.z;
    if ins <> nil then
      begin
        ins^.metrics.x_resolution   := x_resolution;
        ins^.metrics.y_resolution   := y_resolution;
        ins^.valid                  := False;
        TT_Set_Instance_Resolutions := TT_Err_Ok;
      end
    else
        TT_Set_Instance_Resolutions := TT_Err_Invalid_Instance_Handle;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Set_Instance_CharSize( _ins     : TT_Instance;
                                     charsize : Integer ) : TT_Error;
  begin
    TT_Set_Instance_CharSize :=
      TT_Set_Instance_CharSizes( _ins, charsize, charsize );
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Set_Instance_CharSizes( _ins      : TT_Instance;
                                      charsizex : Integer;
                                      charsizey : Integer ) : TT_Error;
  var
    ins : PInstance;
  begin
    if (charsizex < 1*64) or (charsizey < 1*64) then
      begin
        TT_Set_Instance_CharSizes := TT_Err_Bad_Argument;
        exit;
      end;

    ins := _ins.z;
    if ins <> nil then
      begin
        with ins^.metrics do
        begin
          x_scale1 := ( Long(charsizex) * x_resolution ) div 72;
          x_scale2 := ins^.owner^.fontHeader.units_per_EM;

          y_scale1 := ( Long(charsizey) * y_resolution ) div 72;
          y_scale2 := x_scale2;

          if ins^.owner^.fontHeader.flags and 8 <> 0 then
          begin
            x_scale1 := (x_scale1 + 32) and -64;
            y_scale1 := (y_scale1 + 32) and -64;
          end;

          x_ppem   := x_scale1 div 64;
          y_ppem   := y_scale1 div 64;
        end;

        if charsizex > charsizey then
          ins^.metrics.pointsize  := charsizex
        else
          ins^.metrics.pointsize  := charsizey;

        ins^.valid                := False;
        TT_Set_Instance_CharSizes := TT_Err_Ok;
      end
    else
      TT_Set_Instance_CharSizes := TT_Err_Invalid_Instance_Handle;
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Set_Instance_PointSize( _ins      : TT_Instance;
                                      pointsize : integer ) : TT_Error;
  begin
    TT_Set_Instance_PointSize :=
      TT_Set_Instance_CharSize( _ins, pointsize*64 );
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Set_Instance_PixelSizes( _ins      : TT_Instance;
                                       pixelX    : Integer;
                                       pixelY    : Integer;
                                       pointsize : Integer ) : TT_Error;
  var
    ins : PInstance;
  begin
    ins := _ins.z;
    if ins <> nil then
      begin
        ins^.metrics.x_ppem    := pixelX;
        ins^.metrics.y_ppem    := pixelY;
        ins^.metrics.pointSize := pointsize;

        ins^.metrics.x_scale1  := ins^.metrics.x_ppem * 64;
        ins^.metrics.x_scale2  := ins^.owner^.fontHeader.units_per_EM;
        ins^.metrics.y_scale1  := ins^.metrics.y_ppem * 64;
        ins^.metrics.y_scale2  := ins^.metrics.x_scale2;

        ins^.valid             := false;

        TT_Set_Instance_PixelSizes := TT_Err_Ok;
      end
    else
      TT_Set_Instance_PixelSizes := TT_Err_Invalid_Instance_Handle;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Set_Instance_Transforms( _ins      : TT_Instance;
                                       rotated   : Boolean;
                                       distorted : Boolean ) : TT_Error;
  var
    ins : PInstance;
  begin
    ins := _ins.z;
    if ins <> nil then
      begin
        ins^.metrics.rotated   := rotated;
        ins^.metrics.stretched := distorted;
        TT_Set_Instance_Transforms := TT_Err_Ok;
      end
    else
      TT_Set_Instance_Transforms := TT_Err_Invalid_Instance_Handle;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Get_Instance_Metrics( _ins  : TT_Instance;
                                    out m : TT_Instance_Metrics ) : TT_Error;
  var
    ins : PInstance;
  begin
    {$push}
    {$hints off}
    fillchar(m, sizeof(m),0);
    {$pop}
    ins := _ins.z;
    if ins <> nil then
      begin
        if not ins^.valid then
          if Instance_Reset( ins, False ) then
          begin
            TT_Get_Instance_Metrics := error;
            exit;
          end;

        with m do
        begin
          pointSize    := ins^.metrics.pointSize;

          x_scale      := MulDiv_Round( $10000,
                                        ins^.metrics.x_scale1,
                                        ins^.metrics.x_scale2 );

          y_scale      := MulDiv_Round( $10000,
                                        ins^.metrics.y_scale1,
                                        ins^.metrics.y_scale2 );

          x_resolution := ins^.metrics.x_resolution;
          y_resolution := ins^.metrics.y_resolution;

          x_ppem       := ins^.metrics.x_ppem;
          y_ppem       := ins^.metrics.y_ppem;

          TT_Get_Instance_Metrics := TT_Err_Ok;
        end;
      end
    else
      TT_Get_Instance_Metrics := TT_Err_Invalid_Instance_Handle;
  end;


  (*****************************************************************)
  (*  Set instance generic pointer                                 *)
  (*                                                               *)
  function TT_Set_Instance_Pointer( _ins : TT_Instance;
                                    data : Pointer ) : TT_Error;
  var
    ins : PInstance;
  begin
    ins := PInstance(_ins.z);
    if ins <> nil then
      begin
        ins^.genericP := data;
        TT_Set_Instance_Pointer := TT_Err_Ok;
      end
    else
      TT_Set_Instance_Pointer := TT_Err_Invalid_Instance_Handle;
  end;

  (*****************************************************************)
  (*  Get instance generic pointer                                 *)
  (*                                                               *)
  function TT_Get_Instance_Pointer( _ins : TT_Instance ) : Pointer;
  var
    ins : PInstance;
  begin
    ins := PInstance(_ins.z);
    if ins <> nil then
      TT_Get_Instance_Pointer := ins^.genericP
    else
      TT_Get_Instance_Pointer := nil;
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Done_Instance( _ins : TT_Instance ) : TT_Error;
  var
    ins : PInstance;
  begin
    ins := PInstance(_ins.z);
    if ins <> nil then
      begin
        error := TT_Err_Ok;
        Cache_Done( ins^.owner^.instances, ins );
        TT_Done_Instance := error;
      end
    else
      TT_Done_Instance := TT_Err_Invalid_Instance_Handle;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_New_Glyph( _face      : TT_Face;
                         var _glyph : TT_Glyph ) : TT_Error;
  var
    face : PFace;
  begin
    face := PFace(_face.z);
    if face <> nil then
      begin
        error := TT_Err_Ok;
        Cache_New( face^.glyphs, _glyph.z, _face.z );
        TT_New_Glyph := error;
      end
    else
      TT_New_Glyph := TT_Err_Invalid_Face_Handle;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Done_Glyph( _glyph : TT_Glyph ) : TT_Error;
  var
    glyph : PGlyph;
  begin
    glyph := PGlyph(_glyph.z);
    if glyph <> nil then
      begin
        error := TT_Err_Ok;
        Cache_Done( glyph^.face^.glyphs, glyph );
        TT_Done_Glyph := error;
      end
    else
      TT_Done_Glyph := TT_Err_Invalid_Glyph_Handle;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function  TT_Load_Glyph( _instance   : TT_Instance;
                           _glyph      : TT_Glyph;
                           glyph_index : Word;
                           load_flags  : Integer ) : TT_Error;
  var
    ins   : PInstance;
    glyph : PGlyph;
  begin
    ins := PInstance(_instance.z);
    if ins = nil then
      begin
        TT_Load_Glyph := TT_Err_Invalid_Instance_Handle;
        exit;
      end;

    glyph := PGlyph(_glyph.z);
    if glyph = nil then
      begin
        TT_Load_Glyph := TT_Err_Invalid_Glyph_Handle;
        exit;
      end;

    if ins^.owner <> glyph^.face then
      begin
        TT_Load_Glyph := TT_Err_Invalid_Face_Handle;
        exit;
      end;

    if not ins^.valid then
      if Instance_Reset( ins, False ) then
      begin
        TT_Load_Glyph := error;
        exit;
      end;

    error := TT_Err_Ok;
    Load_TrueType_Glyph( ins, glyph, glyph_index, load_flags );
    TT_Load_Glyph := error;
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Copy_Glyph(var source: TT_Glyph; var target: TT_Glyph): TT_Error;
  var
    src, dst : PGlyph;
  begin

    src := PGlyph(source.z);
    dst := PGlyph(target.z);

    if (PGlyph(source.z)<>nil) then
      begin
        if dst=nil then
          begin
            error := TT_New_Glyph(TT_Face(src^.face), target);
            if error<>TT_Err_Ok then
              begin
                TT_Copy_Glyph := error;
                exit;
              end;
            dst := PGlyph(target.z);
          end;

        TT_Done_Outline(dst^.outline);

        dst^.metrics        := src^.metrics;
        dst^.computed_width := src^.computed_width;
        dst^.precalc_width  := src^.precalc_width;
        dst^.is_composite   := src^.is_composite;

        TT_New_Outline(src^.outline.n_points, src^.outline.n_contours, dst^.outline);

        dst^.outline.owner := src^.outline.owner;
        dst^.outline.high_precision := src^.outline.high_precision;
        dst^.outline.second_pass := src^.outline.second_pass;
        dst^.outline.dropout_mode := src^.outline.dropout_mode;

        TT_Copy_Glyph := TT_Copy_Outline( src^.outline, dst^.outline );
      end
    else
      TT_Copy_Glyph := TT_Err_Invalid_Glyph_Handle;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Get_Glyph_Outline( _glyph      : TT_Glyph;
                                 var outline : TT_Outline ) : TT_Error;
  var
    glyph : PGlyph;
  begin
    glyph := PGlyph(_glyph.z);
    if glyph <> nil then
      begin
        outline       := glyph^.outline;
        outline.owner := false;
        TT_Get_Glyph_Outline := TT_Err_Ok;
      end
    else
      TT_Get_Glyph_Outline := TT_Err_Invalid_Glyph_Handle;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Get_Glyph_Metrics( _glyph       : TT_Glyph;
                                 out gmetrics : TT_Glyph_Metrics ) : TT_Error;
  var
    glyph : PGlyph;
  begin
    glyph := PGlyph(_glyph.z);
    if glyph <> nil then
      begin
        gmetrics.bbox     := glyph^.metrics.bbox;
        gmetrics.bearingX := glyph^.metrics.horiBearingX;
        gmetrics.bearingY := glyph^.metrics.horiBearingY;
        gmetrics.advance  := glyph^.metrics.horiAdvance;
        TT_Get_Glyph_Metrics := TT_Err_Ok;
      end
    else
      begin
        fillchar(gmetrics, sizeof(gmetrics), 0);
        TT_Get_Glyph_Metrics := TT_Err_Invalid_Glyph_Handle;
      end;
  end;

  (*****************************************************************)
  (*  Get a glyph's big metrics                                    *)
  (*                                                               *)
  function TT_Get_Glyph_Big_Metrics( _glyph       : TT_Glyph;
                                     out gmetrics : TT_Big_Glyph_Metrics
                                   ) : TT_Error;
  var
    glyph : PGlyph;
  begin
    glyph := PGlyph(_glyph.z);
    if glyph <> nil then
      begin
        gmetrics := glyph^.metrics;
        TT_Get_Glyph_Big_Metrics := TT_Err_Ok;
      end
    else
      begin
        fillchar(gmetrics, sizeof(gmetrics), 0);
        TT_Get_Glyph_Big_Metrics := TT_Err_Invalid_Glyph_Handle;
      end;
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Get_Glyph_Bitmap( _glyph   : TT_Glyph;
                                var map  : TT_raster_Map;
                                x_offset : TT_F26Dot6;
                                y_offset : TT_F26Dot6;
                                rasterizer: TFreeTypeCustomRasterizer) : TT_Error;
  var
    glyph   : PGlyph;
    outline : TT_Outline;
  begin
    glyph := _glyph.z;
    if glyph <> nil then
      begin
        if rasterizer = nil then rasterizer := TTGetDefaultRasterizer;
        outline := glyph^.outline;
        (* XXX: for now, we only use dropout mode #2 *)
        outline.dropout_mode := 2;

        TT_Translate_Outline( outline, x_offset, y_offset );
        TT_Get_Glyph_Bitmap := TT_Get_Outline_Bitmap( outline, map, rasterizer );
        TT_Translate_Outline( outline, -x_offset, -y_offset );
      end
    else
      TT_Get_Glyph_Bitmap := TT_Err_Invalid_Glyph_Handle;
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Get_Glyph_Pixmap( _glyph   : TT_Glyph;
                                var map  : TT_raster_Map;
                                x_offset : TT_F26Dot6;
                                y_offset : TT_F26Dot6;
                                rasterizer: TFreeTypeCustomRasterizer ) : TT_Error;
  var
    glyph   : PGlyph;
    outline : TT_Outline;
  begin
    glyph := _glyph.z;
    if glyph <> nil then
      begin
        if rasterizer = nil then rasterizer := TTGetDefaultRasterizer;
        outline := glyph^.outline;
        (* XXX: for now, we only use dropout mode #2 *)
        outline.dropout_mode := 2;

        TT_translate_Outline( outline, x_offset, y_offset );
        TT_Get_Glyph_Pixmap := TT_Get_Outline_Pixmap( outline, map );
        TT_translate_Outline( outline, -x_offset, -y_offset );
      end
    else
      TT_Get_Glyph_Pixmap := TT_Err_Invalid_Glyph_Handle;
  end;

  function TT_Get_Glyph_Pixmap_HQ( _glyph   : TT_Glyph;
                                var map  : TT_raster_Map;
                                x_offset : TT_F26Dot6;
                                y_offset : TT_F26Dot6;
                                rasterizer: TFreeTypeCustomRasterizer ) : TT_Error;
  var
    glyph   : PGlyph;
    outline : TT_Outline;
  begin
    glyph := _glyph.z;
    if glyph <> nil then
      begin
        if rasterizer = nil then rasterizer := TTGetDefaultRasterizer;
        outline := glyph^.outline;
        (* XXX: for now, we only use dropout mode #2 *)
        outline.dropout_mode := 2;

        TT_translate_Outline( outline, x_offset, y_offset );
        TT_Get_Glyph_Pixmap_HQ := TT_Get_Outline_Pixmap_HQ( outline, map );
        TT_translate_Outline( outline, -x_offset, -y_offset );
      end
    else
      TT_Get_Glyph_Pixmap_HQ := TT_Err_Invalid_Glyph_Handle;
  end;

  function TT_Render_Directly_Glyph_Gray(var _glyph: TT_Glyph; x_offset: TT_F26Dot6;
    y_offset: TT_F26Dot6; x, y, tx, ty: integer;
    OnRender: TDirectRenderingFunction;
    rasterizer: TFreeTypeCustomRasterizer): TT_Error;
  var
    glyph   : PGlyph;
    outline : TT_Outline;
  begin
    glyph := _glyph.z;
    if glyph <> nil then
      begin
        if rasterizer = nil then rasterizer := TTGetDefaultRasterizer;
        outline := glyph^.outline;
        (* XXX: for now, we only use dropout mode #2 *)
        outline.dropout_mode := 2;

        TT_translate_Outline( outline, x_offset, y_offset );
        TT_Render_Directly_Glyph_Gray := TT_Render_Directly_Outline_Gray( outline, x,y,tx,ty,OnRender );
        TT_translate_Outline( outline, -x_offset, -y_offset );
      end
    else
      TT_Render_Directly_Glyph_Gray := TT_Err_Invalid_Glyph_Handle;
  end;

  function TT_Render_Directly_Glyph_HQ(var _glyph: TT_Glyph;
                              x_offset : TT_F26Dot6;
                              y_offset : TT_F26Dot6;
                              x, y, tx, ty: integer;
                      OnRender: TDirectRenderingFunction;
                      rasterizer: TFreeTypeCustomRasterizer): TT_Error;
  var
    glyph   : PGlyph;
    outline : TT_Outline;
  begin
    glyph := _glyph.z;
    if glyph <> nil then
      begin
        if rasterizer = nil then rasterizer := TTGetDefaultRasterizer;
        outline := glyph^.outline;
        (* XXX: for now, we only use dropout mode #2 *)
        outline.dropout_mode := 2;

        TT_translate_Outline( outline, x_offset, y_offset );
        TT_Render_Directly_Glyph_HQ := TT_Render_Directly_Outline_HQ( outline, x,y,tx,ty,OnRender );
        TT_translate_Outline( outline, -x_offset, -y_offset );
      end
    else
      TT_Render_Directly_Glyph_HQ := TT_Err_Invalid_Glyph_Handle;
  end;

  (*****************************************************************)
  (*  Create a new glyph outline                                   *)
  (*                                                               *)
  function TT_New_Outline( n_points   : integer;
                           n_contours : integer;
                           var out    : TT_Outline ) : TT_Error;
  label
    Fail;
  begin
    out.n_points   := n_points;
    out.n_contours := n_contours;
    out.points     := nil;
    out.flags      := nil;
    out.conEnds    := nil;
    out.owner      := true;

    if Alloc( Pointer(out.points), 2*n_points*sizeof(TT_Pos) ) or
       Alloc( Pointer(out.flags),    n_points*sizeof(Byte)   ) or
       Alloc( Pointer(out.conEnds),  n_contours*sizeof(Short) ) then
      goto Fail;

    TT_New_Outline := TT_Err_Ok;
    exit;

  Fail:
    TT_Done_Outline( out );
    TT_New_Outline := error;
  end;

  (*****************************************************************)
  (*  Copy a glyph outline into another one                        *)
  (*                                                               *)
  function TT_Copy_Outline( var source : TT_Outline;
                            var target : TT_Outline ) : TT_Error;
  begin
    Result := 0;
    if (source.n_points   = target.n_points) and
       (source.n_contours = target.n_contours) then
      begin
        move( source.points^, target.points^,  2*source.n_points*4 );
        move( source.flags^,  target.flags^,   source.n_points );
        move( source.conEnds^,target.conEnds^, source.n_contours*2 );
      end
    else
      TT_Copy_Outline := TT_Err_Invalid_Argument;
  end;

  (*****************************************************************)
  (*  Clone a given outline. This will create the outline, then    *)
  (*  copy the source in it                                        *)
  (*                                                               *)
  function TT_Clone_Outline( var source : TT_Outline;
                             var target : TT_Outline ) : TT_Error;
  begin
    error := TT_New_Outline( source.n_points, source.n_contours, target );
    if error = TT_Err_Ok then
      TT_Copy_Outline( source, target );

    TT_Clone_Outline := error;
  end;

  (*****************************************************************)
  (*  Discards a glyph outline                                     *)
  (*                                                               *)
  function TT_Done_Outline( var out : TT_Outline ) : TT_Error;
  begin
    if out.owner then
      begin
        Free( Pointer(out.conEnds) );
        Free( Pointer(out.flags) );
        Free( Pointer(out.points) );
        out.n_points   := 0;
        out.n_contours := 0;
        TT_Done_Outline := TT_Err_Ok;
      end
    else
      TT_Done_Outline := TT_Err_Invalid_Argument;
  end;

  (*****************************************************************)
  (*  Render an outline into a bitmap                              *)
  (*                                                               *)
  function TT_Get_Outline_Bitmap( var out : TT_Outline;
                                  var map : TT_raster_Map;
                                  rasterizer: TFreeTypeCustomRasterizer ) : TT_Error;
  begin
    if rasterizer = nil then rasterizer := TTGetDefaultRasterizer;
    if rasterizer.Render_Glyph( out, map ) then
      TT_Get_Outline_Bitmap := error
    else
      TT_Get_Outline_Bitmap := TT_Err_Ok;
  end;

  (*****************************************************************)
  (*  Render an outline into a pixmap                              *)
  (*                                                               *)
  function TT_Get_Outline_Pixmap( var out : TT_Outline;
                                  var map : TT_raster_Map;
                                  rasterizer: TFreeTypeCustomRasterizer ) : TT_Error;
  begin
    if rasterizer = nil then rasterizer := TTGetDefaultRasterizer;
    if rasterizer.Render_Gray_Glyph( out, map, nil ) then
      TT_Get_Outline_Pixmap := error
    else
      TT_Get_Outline_Pixmap := TT_Err_Ok;
  end;

  function TT_Get_Outline_Pixmap_HQ( var out : TT_Outline;
                                  var map : TT_raster_Map;
                                  rasterizer: TFreeTypeCustomRasterizer ) : TT_Error;
  begin
    if rasterizer = nil then rasterizer := TTGetDefaultRasterizer;
    if rasterizer.Render_Gray_Glyph_HQ( out, map ) then
      TT_Get_Outline_Pixmap_HQ := error
    else
      TT_Get_Outline_Pixmap_HQ := TT_Err_Ok;
  end;

  function TT_Render_Directly_Outline_Gray(var out: TT_Outline; x, y, tx,
    ty: integer; OnRender: TDirectRenderingFunction;
    rasterizer: TFreeTypeCustomRasterizer): TT_Error;
  begin
    if rasterizer = nil then rasterizer := TTGetDefaultRasterizer;
    if rasterizer.Render_Directly_Gray_Glyph( out, x,y,tx,ty, OnRender, nil ) then
      TT_Render_Directly_Outline_Gray := error
    else
      TT_Render_Directly_Outline_Gray := TT_Err_Ok;
  end;

  function TT_Render_Directly_Outline_HQ(var out: TT_Outline; x, y, tx,
    ty: integer; OnRender: TDirectRenderingFunction;
    rasterizer: TFreeTypeCustomRasterizer): TT_Error;
  begin
    if rasterizer = nil then rasterizer := TTGetDefaultRasterizer;
    if rasterizer.Render_Directly_Gray_Glyph_HQ( out, x,y,tx,ty, OnRender ) then
      TT_Render_Directly_Outline_HQ := error
    else
      TT_Render_Directly_Outline_HQ := TT_Err_Ok;
  end;

  (*****************************************************************)
  (*  Compute an outline's bounding box                            *)
  (*                                                               *)
  function TT_Get_Outline_BBox( var out  : TT_Outline;
                                var bbox : TT_Bbox;
                                nbPhantomPoints : integer ) : TT_Error;
  var
    x,    y    : TT_Pos;
    n          : Int;
  begin

    if out.n_points-nbPhantomPoints <= 0 then
    with bbox do
    begin
      xMin := 0;
      xMax := 0;
      yMin := 0;
      yMax := 0;
    end
    else
    with bbox do
    begin
      xMin := $7FFFFFFF;
      xMax := -$80000000;
      yMin := $7FFFFFFF;
      yMax := -$80000000;

      for n := 0 to out.n_points-1-nbPhantomPoints do
      begin
        x := out.points^[n].x;
        if x < xMin then xMin := x;
        if x > xMax then xMax := x;
        y := out.points^[n].y;
        if y < yMin then yMin := y;
        if y > yMax then yMax := y;
      end;
    end;

    TT_Get_Outline_BBox := TT_Err_Ok;
  end;

  (*****************************************************************)
  (*  Get the kerning between two glyph                            *)
  (*                                                               *)
  function TT_Get_KerningInfo( _Face: TT_Face;
                           glyph_left, glyph_right: Word) : TT_KerningInfo;
  var
    p: PFace;
  begin
    p := PFace(_Face.z);
    if p^.kernings = nil then
    begin
      p^.kernings := TKerningTables.Create;
      LoadKerningTables(p, TKerningTables(p^.kernings));
    end;
    result := TKerningTables(p^.kernings).GetKerning(glyph_left, glyph_right);
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Translate_Outline( var out : TT_Outline;
                                 x, y    : TT_F26Dot6 ) : TT_Error;
  var
    n : integer;
  begin
    if x <> 0 then
      for n := 0 to out.n_points-1 do
        inc( out.points^[n].x, x );

    if y <> 0 then
      for n := 0 to out.n_points-1 do
        inc( out.points^[n].y, y );

    TT_Translate_Outline := TT_Err_Ok;
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Transform_Outline( var out : TT_Outline;
                                 var mat : TT_Matrix ) : TT_Error;
  var
    n            : integer;
    x, y, nx, ny : TT_F26Dot6;
  begin
    for n := 0 to out.n_points-1 do
    begin
      x  := out.points^[n].x;
      y  := out.points^[n].y;

      nx := MulDiv_Round( mat.xx, x, $10000 ) +
            MulDiv_Round( mat.xy, y, $10000 );

      ny := MulDiv_ROund( mat.yx, x, $10000 ) +
            MulDiv_Round( mat.yy, y, $10000 );

      out.points^[n].x := nx;
      out.points^[n].y := ny;
    end;

    TT_Transform_Outline := TT_Err_Ok;
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function TT_Transform_Vector( var x, y : TT_F26Dot6;
                                var mat  : TT_Matrix ) : TT_Error;
  var
    nx, ny : TT_F26Dot6;
  begin
    nx := MulDiv_Round( mat.xx, x, $10000 ) +
          MulDiv_Round( mat.xy, y, $10000 );

    ny := MulDiv_Round( mat.yx, x, $10000 ) +
          MulDiv_Round( mat.yy, y, $10000 );

    x := nx;
    y := ny;

    TT_Transform_Vector := TT_Err_Ok;
  end;

  (***********************************************************************)
  (*                                                                     *)
  (*                     Character Mapping support                       *)
  (*                                                                     *)
  (***********************************************************************)

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function  TT_Get_CharMap_Count( face : TT_Face ) : integer;
  var
    faze : PFace;
  begin
    faze := PFace(face.z);
    if faze = nil then
      TT_Get_CharMap_Count := -1
    else
      TT_Get_CharMap_Count := faze^.numCMaps;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function  TT_Get_CharMap_ID( face         : TT_Face;
                               charmapIndex : integer;
                               var platform : integer;
                               var encoding : integer ) : TT_Error;
  var
    faze : PFace;
    cmap : PCMapTable;
  begin
    faze := PFace(face.z);
    if faze = nil then
    begin
      TT_Get_CharMap_ID := TT_Err_Invalid_Face_Handle;
      exit;
    end;

    if (charmapIndex < 0) or (charmapIndex >= faze^.numCMaps) then
    begin
      TT_Get_CharMap_ID := TT_Err_Invalid_Argument;
      exit;
    end;

    cmap     := @faze^.cMaps^[charmapIndex];
    platform := cmap^.platformID;
    encoding := cmap^.platformEncodingID;

    TT_Get_CharMap_ID := TT_Err_Ok;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function  TT_Get_CharMap( face         : TT_Face;
                            charmapIndex : integer;
                            var charMap  : TT_CharMap ) : TT_Error;
  var
    faze : PFace;
  begin
    faze := PFace(face.z);
    if faze = nil then
    begin
      TT_Get_CharMap := TT_Err_Invalid_Face_Handle;
      exit;
    end;

    if (charmapIndex < 0) or (charmapIndex >= faze^.numCMaps) then
    begin
      TT_Get_CharMap := TT_Err_Invalid_Argument;
      exit;
    end;

    charmap.z := @faze^.cMaps^[charmapIndex];

    TT_Get_CharMap := TT_Err_Ok;
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function  TT_Char_Index( charmap  : TT_CharMap;
                           charCode : Longint ) : Word;
  begin
    TT_Char_Index := CharMap_Index( PCMapTable(charmap.z)^, charCode );
  end;

  (***********************************************************************)
  (*                                                                     *)
  (*                        Names Table support                          *)
  (*                                                                     *)
  (***********************************************************************)

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function  TT_Get_Name_Count( face : TT_Face ) : integer;
  var
    faze : PFace;
  begin
    TT_Get_Name_Count := 0;

    faze := PFace( face.z );
    if faze = nil then exit;

    TT_Get_Name_Count := faze^.nameTable.numNameRecords;
  end;


  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function  TT_Get_Name_ID( face         : TT_Face;
                            nameIndex    : integer;
                            out platform : integer;
                            out encoding : integer;
                            out language : integer;
                            out nameid   : integer ) : TT_Error;
  var
    faze  : PFace;
    table : PName_Table;
    rec   : PName_Record;
  label
    Fail;
  begin
    faze := PFace( face.z );
    if faze = nil then
    begin
      TT_Get_Name_Id := TT_Err_Invalid_Face_Handle;
      goto Fail;
    end;

    table := @faze^.nameTable;
    if (nameIndex < 0) or (nameIndex > table^.numNameRecords) then
    begin
      TT_Get_Name_Id := TT_Err_Bad_Argument;
      goto Fail;
    end;

    rec := @table^.names^[nameIndex];

    platform := rec^.platformID;
    encoding := rec^.encodingID;
    language := rec^.languageID;
    nameid   := rec^.nameID;

    TT_Get_Name_ID := TT_Err_Ok;
    exit;

  Fail:
    platform := -1;
    encoding := -1;
    language := -1;
    nameid   := -1;
  end;

  (*****************************************************************)
  (*                                                               *)
  (*                                                               *)
  function  TT_Get_Name_String( face      : TT_Face;
                                nameIndex : integer;
                                out str   : Pointer;
                                out len   : integer ) : TT_Error;
  var
    faze  : PFace;
    table : PName_Table;
    rec   : PName_Record;
  label
    Fail;
  begin
    faze := PFace( face.z );
    if faze = nil then
    begin
      TT_Get_Name_String := TT_Err_Invalid_Face_Handle;
      goto Fail;
    end;

    table := @faze^.nameTable;
    if (nameIndex < 0) or (nameIndex > table^.numNameRecords) then
    begin
      TT_Get_Name_String := TT_Err_Bad_Argument;
      goto Fail;
    end;

    rec := @table^.names^[nameIndex];

    str := @table^.storage^[rec^.offset];
    len := rec^.length;

    TT_Get_Name_String := TT_Err_Ok;
    exit;

  Fail:
    str := nil;
    len := 0;
  end;

  function TT_Get_Name_String(face: TT_Face; nameIndex: integer): string;
  var
    str: pointer;
    len: integer;
  begin
    TT_Get_Name_String(face, nameIndex, str, len);
    setlength(result,len);
    if len <> 0 then move(str^, result[1], len);
  end;

  (*****************************************************************)
  (*  Access font data and copies it into user block               *)
  (*                                                               *)
  function  TT_Get_Font_Data( face       : TT_Face;
                              tableTag   : Longint;
                              offset     : Longint;
                              var buffer;
                              var length : longint ) : TT_Error;
  var
    faze : PFace;
  begin
    faze := PFace(face.z);
    if faze = nil then
      begin
        TT_Get_Font_Data := TT_Err_Invalid_Face_Handle;
        length := 0;
      end
    else
      begin
        TT_Get_Font_Data := TT_Err_Ok;
        if Load_TrueType_Any( faze, tableTag, offset, buffer, length ) then
          TT_Get_Font_Data := error;
      end;
  end;


end.

