unit Frost.Font;

interface

uses
  Frost.GL,
  Frost.Renderers,
  _Geometry;

type
TTextAlign = (
  TopLeft      = 0,
  TopRight     = 1,
  TopCenter    = 2,
  MiddleLeft   = 3,
  MiddleRight  = 4,
  MiddleCenter = 5,
  BottomLeft   = 6,
  BottomRight  = 7 ,
  BottomCenter = 8);

TSymbol = record
  Symbol: WideChar; 
  Size:  TVector2;
  Pivot: TVector2;
  Kerning: Single;
  TexRect: Array [0..1] of TVector2;
  end;

TFont = class
  protected
    FHeigth: Single;
    FMaterial: TMaterial;
    FSymbolList: Array of TSymbol;
  public                                 
    function CreateTextMesh(Text: WideString; TextPosition: TTextAlign): TMesh;
    property Material: TMaterial read FMaterial;
  end;

implementation

function TFont.CreateTextMesh(Text: WideString; TextPosition: TTextAlign): TMesh;
var
  Vertex:   TVertexes;
  Textures: TTextures;
  Faces: TFaces;
  Symbol: Array of Word;
  S: Single;
  i, j: Word;
  Count: Word;
  Len: Single;
  Position: TVector3;
  Bound: TVector2;    
  Shift: TVector2;
begin
  Count := 0;
  Len := 0;
  SetLength(Symbol, Length(Text));
  for i := 1 to Length(Text) do
    for j := 0 to Length(FSymbolList) - 1 do
      if FSymbolList[j].Symbol = Text[i] then
      begin
        Inc(Count);
        Break;
      end;
  SetLength(Symbol, Count);
  Count := 0;
  for i := 1 to Length(Text) do
    for j := 0 to Length(FSymbolList) - 1 do
      if FSymbolList[j].Symbol = Text[i] then
      begin
        Symbol[Count] := j;
        Len := Len + FSymbolList[j].Kerning;
        Inc(Count);
        Break;
      end;
  SetLength(Vertex, Count * 4);
  SetLength(Textures, Count * 4);
  SetLength(Faces, Count * 2);
  Position := Vector3(0, 0, 0);
  for i := 0 to Count - 1 do
  begin
    Vertex[i * 4 + 0] := Vector3(Position.X + FSymbolList[Symbol[i]].Size.X + FSymbolList[Symbol[i]].Pivot.X{ - Len * 0.5}, Position.Y                                 + FSymbolList[Symbol[i]].Pivot.Y, 0);
    Vertex[i * 4 + 1] := Vector3(Position.X + FSymbolList[Symbol[i]].Size.X + FSymbolList[Symbol[i]].Pivot.X{ - Len * 0.5}, Position.Y + FSymbolList[Symbol[i]].Size.Y + FSymbolList[Symbol[i]].Pivot.Y, 0);
    Vertex[i * 4 + 2] := Vector3(Position.X                                 + FSymbolList[Symbol[i]].Pivot.X{ - Len * 0.5}, Position.Y + FSymbolList[Symbol[i]].Size.Y + FSymbolList[Symbol[i]].Pivot.Y, 0);
    Vertex[i * 4 + 3] := Vector3(Position.X                                 + FSymbolList[Symbol[i]].Pivot.X{ - Len * 0.5}, Position.Y                                 + FSymbolList[Symbol[i]].Pivot.Y, 0);

    Textures[i * 4 + 0] := Vector2(FSymbolList[Symbol[i]].TexRect[0].X + FSymbolList[Symbol[i]].TexRect[1].X, FSymbolList[Symbol[i]].TexRect[0].Y + FSymbolList[Symbol[i]].TexRect[1].Y);
    Textures[i * 4 + 1] := Vector2(FSymbolList[Symbol[i]].TexRect[0].X + FSymbolList[Symbol[i]].TexRect[1].X, FSymbolList[Symbol[i]].TexRect[0].Y);
    Textures[i * 4 + 2] := Vector2(FSymbolList[Symbol[i]].TexRect[0].X                                      , FSymbolList[Symbol[i]].TexRect[0].Y);
    Textures[i * 4 + 3] := Vector2(FSymbolList[Symbol[i]].TexRect[0].X                                      , FSymbolList[Symbol[i]].TexRect[0].Y + FSymbolList[Symbol[i]].TexRect[1].Y);

    Faces[i * 2 + 0] := Face(i * 4 +  0, i * 4 + 1, i * 4 + 2);
    Faces[i * 2 + 1] := Face(i * 4 +  0, i * 4 + 2, i * 4 + 3);
    Position.X := Position.X + FSymbolList[Symbol[i]].Kerning;
  end;
  // Find maximum farest Point
  for i := 0 to Count * 4 - 1 do
  begin
    if (Bound.X < Vertex[i].X) then
      Bound.X := Vertex[i].X;
    if (Bound.Y < Vertex[i].Y) then
      Bound.Y := Vertex[i].Y;
  end;
  case TextPosition of
    TopLeft:      Shift := Vector2(0, Bound.Y);
    TopRight:     Shift := Vector2(Bound.X, Bound.Y);
    TopCenter:    Shift := Vector2(Bound.X * 0.5, Bound.Y);
    MiddleLeft:   Shift := Vector2(0, Bound.Y * 0.5);
    MiddleRight:  Shift := Vector2(Bound.X, Bound.Y * 0.5);
    MiddleCenter: Shift := Vector2(Bound.X * 0.5, Bound.Y * 0.5);
    BottomLeft:   Shift := Vector2(0, 0);
    BottomRight:  Shift := Vector2(Bound.X, 0);
    BottomCenter: Shift := Vector2(Bound.X * 0.5, 0);
  end;       
  for i := 0 to Count * 4 - 1 do
    Vertex[i] := Vertex[i] - Shift;

  Result := TMesh.Create(Faces, Vertex, Textures);
  SetLength(Vertex, 0);
  SetLength(Textures, 0);
  SetLength(Faces, 0);   
  SetLength(Symbol, 0);
end;

end.
