unit TTMyf;

{ TrueType support for MyFonts Unit,
  Copr. 1994,95 Matthias K"oppe

  $Id: ttmyf.pas 1.3 1999/02/09 10:50:53 mkoeppe Exp $
 
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library 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.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
}

interface

uses MyFonts;

type
  PTransMatrix = ^TTransMatrix;
  TTransMatrix = record
    a11, a12,
    a21, a22: Real
  end;

function LoadTTFont(Filename: string; ScaleX, ScaleY: Integer): PFontRec;

function LoadTTFontExt(Filename: string;
  ScaleX, ScaleY: Integer;
  TransMatrix: PTransMatrix;
  Attr: Word): PFontRec;

{ Matrix functions
}
function Identity(TransMatrix: PTransMatrix): PTransMatrix;
function Rotate(Angle: Real; TransMatrix: PTransMatrix): PTransMatrix;
function Italicize(Angle: Real; TransMatrix: PTransMatrix): PTransMatrix;
function Scale(FactorX, FactorY: Real; TransMatrix: PTransMatrix): PTransMatrix;
function Combine(First, Second: PTransMatrix): PTransMatrix;

implementation

uses Objects, Memory, Gr, TTF, WinRes;

procedure createwinMetrics(ttfont: pttfont; var metrics: TTextMetric);
var
  os2: tos2;
  FontBounds: TRectInt;


	function ScX(eulav: Word): Integer;
	begin
	  ScX := (ttf.Scale(SwapWord(eulav), ttfont^.Scaling.x) + $8000) shr 16;
	end;

	function ScY(eulav: Word): Integer;
	begin
	  ScY := (ttf.Scale(SwapWord(eulav), ttfont^.Scaling.y) + $8000) shr 16;
	end;


Begin
  ttfont^.GetOs2(os2);
  ttfont^.GetFontBounds(FontBounds);
  FillChar(metrics, SizeOf(metrics), 0);
  with metrics do begin
    tmAscent := ScY(os2.usWinAscent);
    tmDescent := ScY(os2.usWinDescent);
    tmHeight := tmAscent + tmDescent;
    tmAveCharWidth := ScX(os2.xAvgCharWidth);
    tmMaxCharWidth := FontBounds.B.x - FontBounds.A.x;
    tmLastChar := 255;
    tmDefaultChar := 32;
  end
End;

function ConvertTType(FontRec: PFontRec; var s: string): Boolean; far;
var
  Index: Integer;
  Hmtx: THMtx;
  GlyphBounds: TRectInt;
  Width, Height: TRectInt;
  ch: Char;
  i: Byte;
Begin
  ConvertTType := true;
  if FontRec^.CodePage = $FFFF
  then AnsiFrom437Str(@s);
  with pttfont(SharedList^[FontRec^.srcHandle].p)^ do
    For i := 1 to Length(s) do
    begin
      ch := s[i];
      with PABCLongArray(SharedList^[FontRec^.FontHandle].p)^[Ch] do
      if Bits = nil
      then begin
	Index := getIndexOf(Ch);
	If Index > 0
	then begin
	  Size := GetBitmap(Index, Bits);
	  If Bits = nil
	  then ConvertTType := false
	  else begin
	    GetHMtx(Index, HMtx);
	    GetGlyphBounds(GlyphBounds);
	    GetGlyphExtent(Width, Height);

	    A := HMtx.lsb.x - Width.A.x + GlyphBounds.A.x;
	    D := - (HMtx.lsb.y - Width.A.y);

	    B := GlyphBounds.B.x - GlyphBounds.A.x;

    {	C := HMtx.Advancewidth.x - (A + B);
	    H := - HMtx.Advancewidth.y - D}

	    C := Width.A.x - HMtx.lsb.x + HMtx.AdvanceWidth.x - GlyphBounds.B.x;
	    H := - (Width.A.y - HMtx.lsb.y + HMtx.AdvanceWidth.y)
	  end
	end
      end
    end
End;

function LoadTTFontExt;
var
  s: PStream;
  FontBounds: trectint;
  textmetric: ttextmetric;
  ttfont: pttfont;
  matrix: tmat2;
  font: PFontRec;
Begin
  LoadTTFontExt := nil;
  s := new(PBufStream, Init(Filename, stOpenRead, 2048));
  If s = nil then Exit;
  ttfont := new(pttfont, init(s));
  If ttfont = nil
  then begin
    Dispose(s, Done);
    Exit
  end;
  with ttFont^ do
  begin
    if TransMatrix <> nil
    then begin
      with TransMatrix^, Matrix do
      begin
	LongInt(eM11) := Round(a11 * 65536);
	LongInt(eM12) := Round(a12 * 65536);
	LongInt(eM21) := Round(a21 * 65536);
	LongInt(eM22) := Round(a22 * 65536);
      end;
      ttfont^.SetMat2(Matrix)
    end;
    ttfont^.SetPointSize(ScaleX, ScaleY);
    ttfont^.SetResolution(GetResX, GetResY);
    ttfont^.GetFontBounds(FontBounds)
  end;
  CreateWinMetrics(ttfont, TextMetric);
  Font := LoadHugeFont(ttfont, ConvertTType, TextMetric,
    FontBounds.B.y - FontBounds.A.y + 1);
  If Font <> nil
  then begin
    Font^.CodePage := ttfont^.CodePage;
    Font^.DiffAttr := Attr;
  end
  else
    Dispose(ttfont, Done);
  LoadTTFontExt := Font
End;

function LoadTTFont(Filename: string; ScaleX, ScaleY: Integer): PFontRec;
begin
  LoadTTFont := LoadTTFontExt(Filename, ScaleX, ScaleY, nil, ftNormal)
end;

function Identity(TransMatrix: PTransMatrix): PTransMatrix;
begin
  Identity := TransMatrix;
  with TransMatrix^ do begin
    a11 := 1.0; a21 := 0.0;
    a12 := 0.0; a22 := 1.0
  end
end;

function Rotate(Angle: Real; TransMatrix: PTransMatrix): PTransMatrix;
var
  Matrix: TTransMatrix;
  Sine, Cosine: Real;
begin
  Angle := Angle * (pi / 180.0);
  Sine := sin(Angle);
  Cosine := cos(Angle);
  with Matrix do
  begin
    a11 := Cosine; a12 := - Sine;
    a21 := Sine;   a22 := Cosine
  end;
  Rotate := Combine(TransMatrix, @Matrix)
end;

function Italicize(Angle: Real; TransMatrix: PTransMatrix): PTransMatrix;
var
  Matrix: TTransMatrix;
begin
  Italicize := TransMatrix;
  with Matrix do
  begin
    a11 := 1.0;    a12 := sin(Angle * (pi / 180.0));
    a21 := 0.0;    a22 := 1.0
  end;
  Italicize := Combine(TransMatrix, @Matrix)
end;

function Scale(FactorX, FactorY: Real; TransMatrix: PTransMatrix): PTransMatrix;
begin
  with TransMatrix^ do
  begin
    a11 := FactorX * a11;   a12 := FactorX * a12;
    a21 := FactorY * a21;   a22 := FactorY * a22
  end;
  Scale := TransMatrix
end;

function Combine(First, Second: PTransMatrix): PTransMatrix;
var
  a: TTransMatrix;
begin
  Combine := First;
  a := First^;
  with First^ do
  begin
    a11 := a.a11 * Second^.a11 + a.a12 * Second^.a21;
    a12 := a.a11 * Second^.a12 + a.a12 * Second^.a22;
    a21 := a.a21 * Second^.a11 + a.a22 * Second^.a21;
    a22 := a.a21 * Second^.a12 + a.a22 * Second^.a22
  end
end;

end.
