unit vnm_chr;
{****************************************************************************}
{Unit VNM_CHR - it is a addon unit for graphics library VenomGFX.            }
{It brings a loader for .CHR vector font files.                              }
{Written by Laaca.                                                           }
{   (inspired by sources from Jean-Pierre Planas and Michael Knapp)          }
{****************************************************************************}
{$IFDEF VER2}{$DEFINE NEWFPC}{$ENDIF}
{$IFDEF VER3}{$DEFINE NEWFPC}{$ENDIF}
{$IFDEF NEWFPC}{$CALLING OLDFPCCALL}{$ENDIF}

{$ASMMODE INTEL}
interface
uses VnmFnHlp;

const
CHR_MAX_BITMAP_EXPORT  = 32;
CHR_MAX_BODU_ZNAKU = 1000;

var global_chr_loader_popisek:string;

type
PCHR_kontejner=^TCHR_kontejner;
TCHR_kontejner=object
       Org_to_cap   :longint; {* Height from origin to top of capitol      *}
       Org_to_base  :longint; {* Height from origin to baseline            *}
       Org_to_dec   :longint; {* Height from origin to bot of decender     *}
       Num_chrs     :longint;
       First        :Byte;    {* First character in file                   *}
       {italic      :boolean;}
       fontorigin   :byte;
       Char_Width   :Array[0..255] of byte;  {* Character Width Table	   *}
       Offset       :Array[0..255] of word;
       BitmapExport :Array[1..CHR_MAX_BITMAP_EXPORT] of record ptr:pointer;size:longint;end;

       Chrloaded    : Boolean;
       divider:longint;
       fontdir:longint;
       fontsize:longint;
       sinus,cosinus:longint;
       fontdatasize:longint;
       fontdataptr:pointer;
       BitmapExportNum:byte;
       codepage:longint;
       ldfcy:longint;
       rez:string;

       Constructor Init;
       Function LoadFont(nazev:string):boolean;
       Procedure Draw_char(virt:pointer {realne PVirtualwindow};x,y:longint;i:Byte;color:word;italic:boolean);
       Procedure Vector_outtext(virt:pointer {realne PVirtualwindow};x,y:longint;s:string;color:word;italic:boolean);
       Function Vector_textlength(s:string):longint;
       Function Vector_fontheight:longint;
       Function Pretvor_do_bitmapove_sady(velikost:longint;italic:boolean):PBitMapZnaky256;
       Procedure RegisterBitmapExport(fnt:PObecnyFont;size:longint);
       Function FindExportedBitmap(size:longint):pointer;
       Procedure RemoveExportedBitmapRecord(size:longint);
       Procedure RemoveFont;
       Destructor Done;
       end;


Function CheckFormat_CHR(nazev:string):byte;



{Vektorove fonty mam ulozene podobne jako kontejnery s bitmapovymi fonty.
 Pracuje s PObecnyFont, ktery obsahuje:<fdata:PBitMapZnaky256> a
                                       <odkaz_na_pointer:PCHR_kontejner>


Prvni nahravani fontu probehne pres CHR_Font_LoadFont.
Toto volani nahraje vektorovy format, ale netvori z neho bitmapove sady.

Bitmapove sady pro dane velikosti se vytvori az pozdeji,
pri volani CHR_Font_SetParams
}




Function CHR_Font_LoadFont(s:string;size:longint):pointer;
Procedure CHR_Font_Vector_OutText(fnt:pointer;kam:pointer;x,y:longint;s:string;color:word;italic:boolean);
Function CHR_Font_SetStyle(fnt:pointer;podfunkce,param1,param2:longint):pointer;
Function CHR_Font_Delete(fnt:pointer;mode:byte):boolean;

implementation

uses VenomGFX,VenomMng, GrpFile;


type

TCHRHeaderFirst = PACKED RECORD  {V jednotce neni realne pouzito}
       eight_bytes:array[0..7] of byte;
       variable_length_desctiption:array[0..255 {realne neznamy pocet}] of char;
       end;

TCHRHeaderSecond = PACKED RECORD        {Zahlavi CHR fontu}
       b_pre,b_26:byte;
       offset_to_third:byte;
       internal_font_name:array[0..3] of char;
       datasize:word;
       fontmaj,fontmin:byte;
       revmaj,revmin:byte;
       padding:array[0..49 {realne neznamy pocet}] of char;
       end;


TCHRHeaderThird = PACKED RECORD        {Pokracovani zahlavi CHR fontu}
       Sig         :char;	{* signatura (podpis)                    *}
       Nchrs       :smallint;	{* pocet definivanych znaku              *}
       Mystery     :char;       {* rezervovano                           *}
       First	   :byte;    	{* prvni znak v souboru                  *}
       Cdefs	   :smallint;   {* offset k definicim znaku              *}
       Scan_Flag   :char;	{* TRUE je-li zvetsovaci                 *}
       Org_To_Cap  :Shortint;	{* Vyska z pocatku na vrsek vel. pismen  *}
       Org_To_Base :Shortint;	{* Vyska z pocatku na zakladni linku     *}
       Org_To_Dec  :Shortint;	{* Vyska z pocatku na spodky nozicek     *}
       FntName     :Array[0..3] of char;{* 4 znaky jmena fontu           *}
       Unused      :char;       {* nedefinovano                          *}
       End;



Function CheckFormat_CHR(nazev:string):byte;
var a:longint;
    grp:TGRPStream;
    n1,n2:string;
begin
grp.Init(nazev,grpOpenRead);   {otevru soubor}
if grp.status<>grpOK then
   begin
   grp.Done;
   CheckFormat_CHR:=2;
   Exit;
   end;

if grp.GetSize<1024 then
   begin
   grp.Done;
   CheckFormat_CHR:=3;
   Exit;
   end;

n1:='PK'#8#8'BGI ';
grp.ReadStream(n2[1],8);n2[0]:=#8;
grp.Done;
if n1=n2 then CheckFormat_CHR:=0 else CheckFormat_CHR:=3;
end;


Constructor TCHR_Kontejner.Init;
var a:byte;
begin
chrloaded:=false;
for a:=1 to CHR_MAX_BITMAP_EXPORT do
    begin
    BitmapExport[a].ptr:=nil;
    BitmapExport[a].size:=0;
    end;
BitmapExportNum:=0;
end;




Function TCHR_kontejner.LoadFont(nazev:string):boolean;
VAR grp:tGRPstream;
    Header2:TCHRHeaderSecond;
    Header3:TCHRHeaderThird;
    i,j,k:longint;
    s,t:string;

Begin
NUM_chrs:=0;  {zatim mame definovanych 0 znaku}
fontdatasize:=0;
fontdataptr:=nil;

grp.Init(DoplnJmenoFontu(nazev),grpOpenRead);   {otevru soubor}
if grp.status<>grpOK then
   begin
   grp.Done;
   chrloaded:=false;
   Exit;
   end;

For i:=0 to 255 do   {pro vsech 256 znaku...}
    Begin
    Offset[i]:=0;      {vynuluju offset na definici znaku}
    Char_Width[i]:=0;  {vynuluje sirku znaku}
    End;

grp.ReadStream(s,7); {preskocim prvnich 7 bajtu a budeme nastaveni na #0}

j:=0;
s[0]:=#255;
grp.ReadStream(s,255);
for i:=1 to 255 do
    if s[i]=#26 then begin j:=i-1;Break;end;

if j=0 then begin grp.Done;Exit(false);end;
s[0]:=char(j);
{rez:=s;}

global_chr_loader_popisek:=s;

codepage:=437;
t:='';
k:=Pos('[cp',s);
if j<>0 then
   begin
   inc(k,3);
   while s[k] in ['0'..'9'] do begin t:=t+s[k];inc(k);end;
   Val(t,i,k);
   if k=0 then codepage:=i;
   end;


grp.Seek(j+7);
grp.ReadStream(header2,sizeof(TCHRHeaderSecond)); {nacte dalsi cast zahlavi}

i:=header2.offset_to_third;
grp.Seek(i);
grp.ReadStream(header3,sizeof(TCHRHeaderThird)); {nacte zahlavi}

if Header3.Sig<>#43 then begin grp.Done;Exit(false);end;

NUM_chrs:=Header3.nchrs;
org_to_cap :=Header3.org_to_cap ;
org_to_base:=Header3.org_to_base;
org_to_dec :=Header3.org_to_dec ;
first      :=header3.first;
{italic:=false;
fontsize:=16;}
fontorigin:=0;


{Nacte tabulku offsetu k jednotlivym znakum}
grp.ReadStream(OFFSET[first],2*NUM_chrs);

{Nacte tabulku sirek k jednotlivym znakum}
grp.ReadStream(CHAR_WIDTH[first],1*NUM_chrs);


fontdatasize:=grp.GetSize-grp.GetPos; {Spocita velikost nutneho bloku pameti}

getmem(fontdataptr,fontdatasize);

grp.ReadStream(fontdataptr^,fontdatasize);
grp.Done;

rez:=NazevBezCesty(nazev);
for i:=1 to Length(rez) do rez[i]:=UpCase(rez[i]);

divider:=abs(org_to_cap)+abs(org_to_dec);
fontdir:=0;
fontsize:=32;        {defaultni velikost fontu}
chrloaded:=true;
Loadfont:=true;
end;



PROCEDURE Decode(w:word;var action:byte;var x,y:longint);assembler;
{nacte WORD a desifruje z neho ACTION a hodnoty X a Y}
{Format:
 bity 1.bajtu = Azxxxxxx
 bity 2.bajtu = Bzyyyyyy

 kombinace A a B urcuje operator
 "z" je v obou bajtech znamenko
 "x" a "y" jsou ostatni bity X a Y souradnice

        A=0  B=0  konec definice znaku
        A=0  B=1  Do scan
        A=1  B=0  posun ukazatel na (x,y)
        A=1  B=1  kresli z momentalni pozice do (x,y)
 }
  asm
    MOV BL,0
    MOV AX,w
    SHL AL,1
    ADC BL,0   {byl predtim nejvyssi bit AL 1? Tak v tom pripade bude BL 1}
    SHL BL,1   {jestli byl predstm BL 1, tak ted bude BL 2, jinak BL=0}
    SHL AH,1         {nejvyssi bit AH je 1?}
    ADC BL,0   {tak zase eventualne pricti k BL 1}
    MOV EDI,action
    MOV [EDI],BL     {action:=bl}

    MOV BL,AH  {7 bitu Y-souradnice schovej do BL (porad je SHL-nute o 1}
    CBW        {je AL (tedy X-souradnice) zaporne? V tom pripade bude AH=FFh (jinak AH=0h)}
    SAR AX,1   {posuneme AX doprava, ale udrzime znamenko}
    CWDE       {podle znamenka rozsir AX do EAX}
    MOV EDI,x
    MOV [EDI],EAX

    MOV AL,BL       {stejny postup pro Y-souradnici, ktera byla predtim v BL}
    CBW
    SAR AX,1
    CWDE
    MOV EDI,y
    MOV [EDI],EAX
  END;


Procedure TCHR_kontejner.Draw_char(virt:pointer {realne PVirtualwindow};x,y:longint;i:Byte;color:word;italic:boolean);
Var p_w     :^word;
    Action  :byte;
    xd,yd   :longint;
    minx,miny,maxx,maxy:longint;
    ssx,ssy:longint;
    Centrage:longint;
    vrt:PVirtualWindow;

    pbuf:array[0..CHR_MAX_BODU_ZNAKU] of longint;
    {pbuf_size_ptr:^longint;
    pbuf_ptr:pointer;}

    sizebuf,polybuf:^longint;
    polynr:word;

    PROCEDURE lt(x,y:longint);  {pridej bod do polygonu}
    BEGIN
      inc(sizebuf^);    {poznamename si zvetseni polygonu o 4 bajty}
      polybuf^:=x;              {vloz X}
      inc(polybuf);
      polybuf^:=y;              {vloz Y}
      inc(polybuf);
    END;

    PROCEDURE mt(x,y:longint);  {zaloz novy polygon}
    BEGIN
      inc(polynr);       {zvys pocet polygonu o jeden}
      sizebuf:=polybuf;   {pocitadlo bodu nastavime na zacatek polyg. bufferu}
      sizebuf^:=1;        {velikost = 1, t.j. definovan jeden bod}
      inc(polybuf);  {v 1.bajtu je pocet bodu, proto prejdu na dalsi bajt}

      polybuf^:=x;      {a do noveho polygonu vlozime X}
      inc(polybuf);
      polybuf^:=y;      {a Y}
      inc(polybuf);
    END;


    Procedure poly_bouncingbox(p:pointer;z:word);
    var q:^longint;
        ox,oy,zx,zy,a,b,c:longint;
    begin
    minx:=maxlongint div 2;
    miny:=minx;
    maxx:=-minx;
    maxy:=-miny;

    q:=p;
    for a:=1 to z do
        begin
        b:=q^;   inc(q);
        ox:=q^;  inc(q);
        oy:=q^;  inc(q);

        if b>1 then
        begin

        if ox<minx then minx:=ox;
        if oy<miny then miny:=oy;
        if ox>maxx then maxx:=ox;
        if oy>maxy then maxy:=oy;

        for c:=2 to B do
            begin
            zx:=q^;   inc(q);
            zy:=q^;   inc(q);

            (*
           { if c=2 then
               begin}
               if ox<minx then minx:=ox;
               if oy<miny then miny:=oy;
               if ox>maxx then maxx:=ox;
               if oy>maxy then maxy:=oy;
             {  end;}
              *)
            if zx<minx then minx:=zx;
            if zy<miny then miny:=zy;
            if zx>maxx then maxx:=zx;
            if zy>maxy then maxy:=zy;
            end;
        end;
        end;
    end;


    Procedure Poly(p:pointer;z:word;sx,sy:longint);
    var q:^longint;
        nx,ny,a,b,c,ox,oy:longint;
    begin
      q:=p;               {nastavime se na zacatek bufferu}
      FOR a:=1 TO z DO    {zpracuj 1. az Z-ty polygon}
        begin
          b:=q^;          {nacti pocet bodu v polygonu}
          inc(q);

          nx:=q^;          {nacti zakladni X}
          inc(q);
          ny:=q^;
          inc(q);         {a zakladni Y}
          ox:=nx;
          oy:=ny;     {z aktualnich souradnic udelej stare souradnice}
          FOR c:=2 TO B DO
            begin
              nx:=q^;      {nacti nove X}
              inc(q);
              ny:=q^;      {a nove Y}
              inc(q);
              line(vrt^,ox-sx,oy-sy,nx-sx,ny-sy,color);  {nakresli caru ze starych do novych souradnic}
              ox:=nx;
              oy:=ny; {z aktualnich souradnic udelej stare souradnice}
            END;
        END;
    END;

Begin
polybuf:=@pbuf;
polynr:=0;
vrt:=virt;

If First+Num_chrs<i Then Exit; {neni definovan znak I ?}

If (OFFSET[i]<>0) or (i=First) Then
   Begin
   CASE fontorigin OF
      0:Centrage:=org_to_cap;
      1:Centrage:=0;
   END;

   mt(x,y);             {zaloz novy polygon, prvni bod bude zadana X,Y pozice}
   p_w:=fontdataptr;     {ukazovatko v nactenem souboru}

   inc(p_w,OFFSET[i] div 2);   {ukazovatko posunu na zacatek definice znaku}
   {div 2 je tu nebot p_w je typova promenna}

   Decode(p_w^,Action,xd,yd);   {dekoduje prvni word}

   IF italic THEN inc(xd,yd DIV 4);
   yd:=yd-centrage;

   While (Action<>0) do
      Begin
      Case Action of
         2:Mt(x+((xd*cosinus+yd*sinus) DIV 65536), {presunuti na novy polygon}
              y+((xd*sinus-yd*cosinus) DIV 65536));

         3:LT(x+((xd*cosinus+yd*sinus) DIV 65536), {novy bod polygonu}
              y+((xd*sinus-yd*cosinus) DIV 65536));
      End;{Case}
      inc(p_w);                  {presun se na dalsi bajt bufferu}
      Decode(p_w^,Action,Xd,Yd); {a dekoduj ho}

      IF italic THEN inc(xd,yd DIV 4);
      yd:=yd-centrage;

      End;

   End; {if (C_Font.OFFSET[i]<>0) or (i=C_Font.First)...}


minx:=0;
if vrt^.segment=0 then
   begin
   poly_bouncingbox(@pbuf,polynr);   {vyplni minx, miny, maxx, maxy}

   {if i=46 then
      i:=i;}

   if minx<>maxlongint div 2 then   {pokud je definovan nejaky kresl. bod...}
      begin                         {...tak definuj pole}
      Init_VW(vrt^,maxx-minx+1,maxy-miny+1,true);
      if minx<x then ssx:=x-minx else ssx:=0;
      {if miny<y then ssy:=y-miny else ssy:=0;}
       if miny<y then ssy:=y-miny else ssy:=miny-y;
      end;

   ldfcy:=miny;

   end
   else begin
   ssx:=0;
   ssy:=0;
   end;

if minx<>maxlongint div 2
   then poly(@pbuf,polynr,ssx,ssy);
End;



PROCEDURE TCHR_kontejner.Vector_outtext(virt:pointer {realne PVirtualwindow};x,y:longint;s:string;color:word;italic:boolean);
VAR i,akku,bfso:longint;
    vrt:PVirtualWindow;

BEGIN
  vrt:=virt;
  sinus:=trunc(((sin((fontdir*2*pi)/65536)*fontsize)/divider)*65536);
  cosinus:=trunc(((cos((fontdir*2*pi)/65536)*fontsize)/divider)*65536);

  bfso:=(Org_to_cap-Org_to_base)*fontsize div divider+1;
  dec(y,bfso);

  akku:=0;
  For i:=1 to Length(s) do
    Begin
      Draw_Char(vrt,x+((akku*cosinus) SHR 16),y+((akku*sinus) SHR 16),ord(s[i]),color,italic);
      inc(akku,Char_Width[ord(s[i])]);
    End;
End;



Function TCHR_kontejner.Pretvor_do_bitmapove_sady(velikost:longint;italic:boolean):PBitMapZnaky256;
var bf:PBitMapZnaky256;
    v:VirtualWindow;
    a:longint;
    j:real;
    dp:longint;
    z:PZnak;

begin
bf:=New(PBitMapZnaky256,Init(velikost));
bf^.first:=first;
bf^.pocetzn:=num_chrs;
bf^.last:=first+num_chrs-1;
bf^.rez:=rez;
bf^.prop:=true;
bf^.kodova_stranka:=codepage;     {mozna se zmeni podle zahlavi CHR fontu}
bf^.format:=FNFMT_CHR;

bf^.so:=(Org_to_cap-Org_to_base)*velikost div divider+1;
bf^.su:=(Org_to_base-Org_to_dec)*velikost div divider+1;
bf^.sosu:=bf^.so+bf^.su;

sinus:=trunc(((sin((fontdir*2*pi)/65536)*velikost)/divider)*65536);
cosinus:=trunc(((cos((fontdir*2*pi)/65536)*velikost)/divider)*65536);

{coshr16:=cosinus shr 16;}

for a:=bf^.first to bf^.last do
    begin
    z:=bf^.PrepChar(a);


    v.segment:=0;   {tim donutime Draw_char alokovat optimalni blok pameti}

    {if a=46 then
       j:=j;}
    Draw_Char(@v,0,0,a,65535,italic);

    z^.ready:=2;

    j:=Char_Width[a];
    j:=j*velikost/divider;

    z^.shift:=round(j);

    if v.segment<>0 then  {v.segment=0 treba pri definici mezery}
       begin
       z^.sirka:=v.breite;
       z^.vyska:=v.hoehe;
       {if a=65 then
          j:=j;}
       z^.rely:=ldfcy{-z^.vyska}-org_to_cap*velikost div divider-1{-org_to_dec-org_to_dec div 2};
       z^.dp:=v.breite*v.hoehe;         {priprava pameti pro dekomprimovanou...}
       BWSpriteToArray(v,z^.data,0,1);  {...a rozepsani bitmapy do dekompr. znaku}
       z^.Komprimuj;  {a nakonec radna komprese znaku, abychom s nim mohli dale pracovat}
       end;

    {if (a=46) then
       begin
       Save_BMP(v,'zn_46.bmp');
       PutSprite(vga,v,500,300);
       end;}

    Kill_VW(v);
    end;


Pretvor_do_bitmapove_sady:=bf;
End;


Procedure TCHR_Kontejner.RegisterBitmapExport(fnt:PObecnyFont;size:longint);
begin
inc(BitmapExportNum);
BitmapExport[BitmapExportNum].ptr:=fnt;
BitmapExport[BitmapExportNum].size:=size;
end;


Procedure TCHR_Kontejner.RemoveExportedBitmapRecord(size:longint);
var a,b:longint;
begin
for a:=1 to BitmapExportNum do
    if BitmapExport[a].size=size then
       begin
       for b:=a to BitmapExportNum do
           BitmapExport[b]:=BitmapExport[b+1];

       dec(BitmapExportNum);
       end;
end;


Function TCHR_Kontejner.FindExportedBitmap(size:longint):pointer;
var a:byte;
begin
for a:=1 to CHR_MAX_BITMAP_EXPORT do
    if BitmapExport[a].size=size then Exit(BitmapExport[a].ptr);
FindExportedBitmap:=nil;
end;


Procedure TCHR_Kontejner.RemoveFont;
BEGIN
  IF chrloaded then
    begin
      freemem(fontdataptr,fontdatasize);
      fontdataptr:=nil;
      chrloaded:=false;
      fontdatasize:=0;
    end;
END;


Destructor TCHR_kontejner.Done;
begin
RemoveFont;
end;


FUNCTION TCHR_kontejner.Vector_textlength(s:string):longint;
Var i:Byte;
    total:Word;
    j:longint;

Begin
  Total:=0;
  For i:=1 to Length(S) do
    inc(Total,Char_Width[ord(s[i])]);
  Vector_textlength:=(Total*fontsize) DIV divider;
End;


FUNCTION TCHR_kontejner.Vector_fontheight:longint;
BEGIN
  Vector_fontheight:=((org_to_cap-org_to_dec)*fontsize) DIV divider;
END;


Function CHR_Font_LoadFont(s:string;size:longint):pointer;
{Provede prvonacteni a dekodovani vektorove casti a pote zavola
 CHR_Font_SetParams, ktery vektorovou cast predela na bitmapovou sadu}

var a:byte;
    chr:PCHR_kontejner;
    hf,nhf:PObecnyFont;
    pf:PBitmapZnaky256;

begin
a:=CheckFormat_CHR(s);
if a<>0 then Exit(nil);
New(chr);
chr:=New(PCHR_kontejner,Init);
chr^.LoadFont(s);
if chr^.chrloaded=false then
   begin
   chr^.RemoveFont;
   Dispose(chr);
   Exit(nil);
   end;

hf:=New(PObecnyFont,Init);
hf^.odkaz_na_kontejner:=chr;

nhf:=pointer(CHR_Font_SetStyle(hf,1,size,0));

Dispose(hf,Done);

CHR_Font_LoadFont:=nhf;
end;


Function CHR_Font_PrepChar(fnt:pointer;znak:word):pointer;
var hf:PObecnyFont;
    pf:PBitmapZnaky256;

begin
hf:=fnt;
pf:=pointer(hf^.fdata);
CHR_Font_PrepChar:=pf^.PrepChar(znak);
end;


Procedure CHR_Font_Vector_OutText(fnt:pointer;kam:pointer;x,y:longint;s:string;color:word;italic:boolean);
var virt:Pvirtualwindow;
    hf:PObecnyFont;
    chr:PCHR_Kontejner;
begin
virt:=kam;
hf:=fnt;
chr:=hf^.odkaz_na_kontejner;
chr^.vector_outtext(virt,x,y,s,color,italic);
end;



Function CHR_Font_SetStyle(fnt:pointer;podfunkce,param1,param2:longint):pointer;
var hf,nhf:PObecnyFont;
    {pf:PFontVGA;}
    chr:PCHR_Kontejner;
    pf:PBitMapZnaky256;
    s2,sv:string;
    n,nn,m:byte;
    italic:boolean;


begin
if podfunkce=2 then
   if (param1 and prop_fn)<>0
      then VNMFN_PROP_MODE:=true
      else VNMFN_PROP_MODE:=false;

if podfunkce<>1 then Exit(nil);

{Dale budeme resit pouze podfunkci 1}

hf:=fnt;


chr:=hf^.odkaz_na_kontejner;

italic:=(param2 and 1)<>0;
pf:=chr^.Pretvor_do_bitmapove_sady(param1 {velikost}, italic);


nhf:=New(PObecnyFont,Init);
nhf^.odkaz_na_kontejner:=chr;
chr^.RegisterBitmapExport(nhf,param1 {velikost});
nhf^.fdata:=pf;
nhf^.typzdroje:=4;   {vektorovy zdroj}
pf^.rukojet:=nhf;

{chr^.fontsize:=size;
chr^.italic:=(flags and 1)<>0;}


CHR_Font_SetStyle:=nhf;
end;



Procedure CHR_font_OutText(kam:pointer;x,y:longint;s:string;fnt:pointer;color:word);
var hf:PObecnyFont;
    pf:PBitMapZnaky256;
    ps:string;

begin
if fnt<>nil then
   begin
   hf:=fnt;
   pf:=PBitMapZnaky256(hf^.fdata);
   VnmFnHlp_OutText(kam,x,y,s,pf,color);
   end;
end;


Function CHR_Font_GetInfo(fnt:pointer;param1,param2:longint):longint;
var hf,hfc:PObecnyFont;
    chr:PCHR_Kontejner;
    i:longint;
    s:string;

begin
hf:=fnt;

if param1=102 then   {funkce Dej odkaz na font s oznacenim Param2}
   begin
   chr:=hf^.odkaz_na_kontejner;
   hfc:=chr^.FindExportedBitmap(byte(param2));
   Exit(longint(hfc));
   end;


if param1=3 then     {vygeneruj retezec, ktery obsahuje vsechny dostupne}
   begin             {velikosti fontu}
   s:='-1'; {bavime se o vektorovem fontu, tak vratime treba toto}
   Move(s,pointer(param2)^,Length(s)+1);
   Exit(-1);
   end;


i:=hf^.GetInfo(param1,param2);
CHR_Font_GetInfo:=i;
end;


Function CHR_Font_Delete(fnt:pointer;mode:byte):boolean;
var hf,hf2:PObecnyFont;
    pf:PBitMapZnaky256;
    chr:PCHR_Kontejner;
    a,vel:longint;

begin

hf:=fnt;
chr:=hf^.odkaz_na_kontejner;
pf:=PBitMapZnaky256(hf^.fdata);
if pf=nil then Exit(true);
vel:=pf^.vel;

if mode=0
   then begin
   chr^.RemoveExportedBitmapRecord(vel); {smazeme zaznam o export. bitmape}
   Dispose(hf,Done)    {i samotnou bitmapu, se vsim vsudy}
   end
   else begin {mode 1}
   for a:=1 to chr^.BitmapExportNum do
       begin
       hf2:=chr^.BitmapExport[a].ptr;
       Dispose(hf2,Done);
       end;
   Dispose(chr,Done);       {smaze vektorova data}
   end;

CHR_Font_Delete:=true;
end;




begin
RegisterFontEngine('CHR',@CHR_Font_LoadFont,
                         @CHR_Font_PrepChar,
                         @CHR_Font_OutText,
                         @CHR_Font_SetStyle,
                         @CHR_Font_GetInfo,
                         @CHR_Font_Delete);
end.
