unit vnm_v8f;
{****************************************************************************}
{Unit VNM_V8F - it is a addon unit for graphics library VenomGFX.            }
{It brings a loader for V8F font format (baicaly compressed VGA charset)     }
{****************************************************************************}
{$IFDEF VER2}{$DEFINE NEWFPC}{$ENDIF}
{$IFDEF VER3}{$DEFINE NEWFPC}{$ENDIF}
{$IFDEF NEWFPC}{$CALLING OLDFPCCALL}{$ENDIF}
interface
uses Objects,VnmFnHlp;


Function Zkontroluj_Format_V8F(s:string):boolean;
Function Load_V8F_font(s:string;size:longint):pointer; {realne PObecnyFont}


var global_v8f_loader_popisek:string;

implementation
uses GrpFile,VNM_FV,VNM_V8FI,VenomMng;


Function Zkontroluj_Format_V8F(s:string):boolean;
var grp:TGrpStream;
    a,i:longint;
    t,u:string;
begin
grp.Init(DoplnJmenoFontu(s),grpOpenRead);
if grp.status<>grpOK then Exit(false);
i:=grp.GetSize;
if (i<10) or (i>(MAX_FV_CHARSET_HIGH+1)*256) then
   begin
   Grp.Done;
   Exit(false);
   end;

grp.ReadStream(t[1],255);
Grp.Done;
t[0]:=#255;
u:=Copy(t,1,8);

if u<>'V8FONT'#13#10 then Exit(false);
a:=Pos(#26,t);
Zkontroluj_Format_V8F:=a<>0;
end;




Function V8F_font_setstyle(fnt:pointer;podfunkce,param1,param2:longint):pointer;
var hf:PObecnyFont;
    n,m:byte;
begin
hf:=fnt;
if podfunkce=2 then
   if (param1 and prop_fn)<>0
      then VNMFN_PROP_MODE:=true
      else VNMFN_PROP_MODE:=false;
V8F_font_setstyle:=hf;
end;


Function Load_V8F_font(s:string;size:longint):pointer; {realne PObecnyFont}
var grp:TGrpStream;
    ms:PMemoryStream;
    a,b,c,l,m,dm:longint;
    w:^word;
    ok:boolean;
    pf:PFontFV;
    hf:PObecnyFont;
    p,pp:pchar;
    znaky:pchar;
    res:pointer;
    mn:set of byte;
    zns,vel:longint;
    first,count:longint;

begin
ok:=Zkontroluj_Format_V8F(s);
if ok=false then Exit(nil);

grp.Init(DoplnJmenoFontu(s),grpOpenRead);
l:=Grp.GetSize;
GetMem(p,l);
grp.ReadStream(p^,l);
grp.Done;

for a:=8 to l do
    if p[a]=#26 then begin m:=a;Break;end;

global_v8f_loader_popisek[0]:=char(m-8);
Move(p[8],global_v8f_loader_popisek[1],m-4);

for a:=Length(global_v8f_loader_popisek) downto 1 do
    if global_v8f_loader_popisek[a] in [#0,#10,#13]
       then dec(global_v8f_loader_popisek[0])
       else Break;

vel:=0;  {zatim nevime, jakou ma font vysku}
zns:=0;  {zatim nevime, v jake to bude znakove sade}
mn:=[];  {zatim nebyl definovan zadny znak}
inc(m);  {jsme znak za #26, zde by mel zacinat prvni blok}
repeat
if m>=l    then Break;        {neocekavany konec souboru? Konec}
if p[m]=#0 then Break;        {blok typu 0? Konec}

w:=@p[m+1];                {velikost bloku snizena o 1}
dm:=w^+1;                   {dopocitame pozici dalsiho bloku}
case p[m] of
  #16: begin               {informace o znakove sade?}
       if p[m+3]=#0 then   {podtyp bloku 0?  (jediny definovany)}
          begin
          w:=@p[m+4];
          zns:=w^;
          end;
       end;

  #1:  if (p[m+7]=#8) and (p[m+8]=#0) then {budeme podporovat jen znaky o sirce 8px}
          begin
          w:=@p[m+9];
          if (vel=0) or (vel=w^) then
             begin   {trvame na tom, ze znaky musi mit jednotnou vysku}
             if vel=0 then
                begin
                vel:=w^;
                GetMem(znaky,vel*256); {uz vime, jak jsou znaky vysoke, tak alokuji pamet}
                end;
             w:=@p[m+3];first:=w^;
             w:=@p[m+5];count:=w^;
             b:=first*vel;
             Move(p[m+11],znaky[b],count*vel);
             for a:=first to first+count-1 do mn:=mn+[a];
             end;
          end;
end; {case}

inc(m,dm);                  {a konecne preskocime na zacatek dalsiho bloku}
until 1=2;

{Vyborne! Ted mame hotovou prvni cast - znaky definovane v souboru.
 Ted jeste musime projit znaky, ktere donacteme z BIOSove definice.
 To ale realne nebudu tahat z BIOSu, ale z predpripravenych dat}

if vel=16 then pp:=@BIOS_FONT_16_DATA else
if vel=14 then pp:=@BIOS_FONT_14_DATA else
if vel=8 then pp:=@BIOS_FONT_8_DATA else pp:=nil;

if pp<>nil then
   for a:=0 to 255 do
       if not (a in mn) then
          begin
          c:=a*vel;
          for b:=0 to vel-1 do znaky[c+b]:=pp[c+b];
          end;

b:=vel*256;
ms:=New(PMemoryStream,Init(1,b));
ms^.Write(znaky^,b);

res:=Load_FV_font_from_stream(ms,s,vel);
{realne PObecnyFont}

if res<>nil then
   begin
   hf:=res;
   pf:=pointer(hf^.fdata);
   pf^.kodova_stranka:=zns;
   end;

Dispose(ms,Done);
FreeMem(znaky);
FreeMem(p);

Load_V8F_font:=res;
end;



Function V8F_Font_PrepChar(fnt:pointer;znak:word):pointer;
var hf:PObecnyFont;
begin
hf:=fnt;
V8F_Font_PrepChar:=hf^.FData^.PrepChar(znak);
end;


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

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



Function V8F_Font_GetInfo(fnt:pointer;param1,param2:longint):longint;
var hf:PObecnyFont;
    i:longint;

begin
hf:=fnt;
i:=hf^.GetInfo(param1,param2);
V8F_Font_GetInfo:=i;
end;


Function V8F_Font_delete(fnt:pointer;mode:byte):boolean;
var hf:PObecnyFont;
    pf:PFontFV;
begin
hf:=fnt;
Dispose(hf,Done);  {automaticky smaze i hf^.FData (ve formatu PFontFV)}
V8F_Font_delete:=true;
end;



Procedure Register_V8F_Loader;
begin
RegisterFontEngine('V8F',
                   @Load_V8F_font,
                   @V8F_Font_PrepChar,
                   @V8F_Font_OutText,
                   @V8F_Font_setstyle,
                   @V8F_Font_GetInfo,
                   @V8F_Font_delete);

end;




begin
Register_V8F_Loader;
end.
