unit Utils;

interface

uses Graphics, Types, Classes, SysUtils, Dialogs;

type BRenderFrame = function:TBitmap of object;

type BRect = class
               private
                rect:TRect;
               published

             end;

type BUtils = class
                public
                  txtTrue,
                  txtFalse:string;
                  flagDrawComments:boolean;
              end;

Function Rev(_s:string): string;
function getFileList(search:String; exts:TStringList): TStringList;
function Explode(delimiter : string; source : string) : TStringList;
function ExplodeWithDelimiter(delimiter : string; source : string) : TStringList;
procedure coloredTextOut(_text:string; _vars,_colors:TStringList; _canvas:TCanvas; _x,_y:word);
function coloredTextOutWidth(_text:string; _vars,_colors:TStringList; _canvas:TCanvas):word;

//function getTrue: string;    // 1.25
//function getFalse: string;   // 1.25
//function getFor: string;     // 1.25
//function getWhile: string;   // 1.25
//function getRepeat: string;  // 1.25

const commentColor:TColor = clBlack;

var vars,colors:TStringlist;
    //drawComments:boolean;
    NSDUtils:BUtils;

implementation

uses form_main;

(*******************************************
 * BUtils
 *******************************************)


(*******************************************
 * Other
 *******************************************)

(*
function getTrue: string;
begin
 result:=mainform.strAlternativeTrue.caption;
end;

function getFalse: string;
begin
 result:=mainform.strAlternativeFalse.caption;
end;

function getFor: string;
begin
 result:=mainform.strFor.caption;
end;

function getWhile: string;
begin
 result:=mainform.strWhile.caption;
end;

function getRepeat: string;
begin
 result:=mainform.strRepeat.caption;
end;
*)


procedure coloredTextOut(_text:string; _vars,_colors:TStringList; _canvas:TCanvas; _x,_y:word);
var words:TStringlist;
    i,j:integer;
    width,th,tb:word;
    oldCol:TColor;
    oldFont:string;
    bmp:TBitmap;

 procedure CutInto(_del:String);
 var i:integer;
     str:TStringlist;
 begin
   str:=tStringlist.Create;
   for i:=0 to words.count-1 do
   begin
     if(_vars.IndexOf(words[i])<0)
     then str.AddStrings(ExplodeWithDelimiter(_del,words[i]))
     else str.Add(words[i]);
   end;
   words.text:=str.text;
   str.free;
 end;

begin
  words:=TStringlist.Create;
  words.Add(_text);
//   showmessage(words.text);
  for i:=0 to _vars.count-1 do
  begin
   CutInto(_vars[i]);
//   showmessage(words.text);
  end;
  CutInto('<-');
//   showmessage(words.text);
  width:=0;
  for i:=0 to words.count-1 do
  begin

    if(words[i]='<-') then
    begin
      oldFont:=_canvas.Font.Name;
      th:=_canvas.TextHeight('I');
      _canvas.Font.Name:='Monotype Sorts';
      //_canvas.Font.Name:='Symbol';
      tb:=_canvas.TextHeight(ansitoutf8(chr(217)));

      bmp:=TBitmap.create;
      bmp.height:=tb;
      bmp.width:=_canvas.TextWidth(ansitoutf8(chr(217)));
      bmp.Canvas.Font:=_canvas.font;
      bmp.Canvas.TextOut(0,0,ansitoutf8(chr(217)));
      _canvas.Draw(_x+width,_y+((th-tb) div 2),
//                  FlipReverseCopyRect(false,false,bmp));
                  bmp);
      bmp.free;

      //_canvas.TextOut(_x+width,_y+((th-tb)),'¨');
      //_canvas.TextOut(_x+width,_y+((th-tb) div 2),ansitoutf8(chr(217)));
      //width:=width+_canvas.TextWidth('¨');
      width:=width+_canvas.TextWidth(ansitoutf8(chr(217)));
      _canvas.font.name:=oldFont;
    end
    else

    begin
      oldCol:=_canvas.Font.color;
      for j:=0 to _vars.count-1 do if(_vars[j]=words[i]) then
      begin
        _canvas.Font.color:=StrtoInt('$'+Rev(_colors[j]));
        _canvas.Font.Style:=[fsBold];
        if(_canvas.Font.color=clGray) then
        begin
         _canvas.Font.color:=clBlack;
         _canvas.Font.Style:=[];
        end;
      end;
      _canvas.TextOut(_x+width,_y,words[i]);
      width:=width+_canvas.TextWidth(words[i]);
      _canvas.Font.Style:=[];
      _canvas.font.color:=oldCol;
    end;
  end;

end;

function coloredTextOutWidth(_text:string; _vars,_colors:TStringList; _canvas:TCanvas):word;
var words:TStringlist;
    i,j:integer;
    width,th,tb:word;
    oldCol:TColor;
    oldFont:string;

 procedure CutInto(_del:String);
 var i:integer;
     str:TStringlist;
 begin
   str:=tStringlist.Create;
   for i:=0 to words.count-1 do
   begin
     if(_vars.IndexOf(words[i])<0)
     then str.AddStrings(ExplodeWithDelimiter(_del,words[i]))
     else str.Add(words[i]);
   end;
   words.text:=str.text;
   str.free;
 end;

begin
  words:=TStringlist.Create;
  words.Add(_text);
//   showmessage(words.text);
  for i:=0 to _vars.count-1 do
  begin
   CutInto(_vars[i]);
//   showmessage(words.text);
  end;
  CutInto('<-');
//   showmessage(words.text);
  width:=0;
  for i:=0 to words.count-1 do
  begin
    if(words[i]='<-') then
    begin
      oldFont:=_canvas.Font.Name;
      th:=_canvas.TextHeight('I');
      _canvas.Font.Name:='Monotype Sorts';
      tb:=_canvas.TextHeight(ansitoutf8(chr(217)));
      //_canvas.TextOut(_x+width,_y+((th-tb)),'¨');
      width:=width+_canvas.TextWidth(ansitoutf8(chr(217)));
      _canvas.font.name:=oldFont;
    end
    else
    begin
      oldCol:=_canvas.Font.color;
      for j:=0 to _vars.count-1 do if(_vars[j]=words[i]) then
      begin
        _canvas.Font.color:=StrtoInt('$'+Rev(_colors[j]));
        _canvas.Font.Style:=[fsBold];
        if(_canvas.Font.color=clGray) then
        begin
         _canvas.Font.color:=clBlack;
         _canvas.Font.Style:=[];
        end;
      end;
//      _canvas.TextOut(_x+width,_y,words[i]);
      width:=width+_canvas.TextWidth(words[i]);
      _canvas.Font.Style:=[];
      _canvas.font.color:=oldCol;
    end;
  end;
  result:=width;
end;

{
 Text_Color_Dialog.Color:=StrtoInt('$'+Rev(Box_Color.text));
 Box_Color.text:=Rev(Inttohex(Text_Color_Dialog.Color,6));
}

Function Rev(_s:string): string;
var s:string;
begin
 s:=_s;
 s[1]:=_s[5];
 s[2]:=_s[6];
 s[5]:=_s[1];
 s[6]:=_s[2];
 rev:=copy(s,1,6);
end;

function Explode(delimiter : string; source : string) : TStringList;
var
  c : word;
begin
  Result:=TStringList.Create; 
  c := 0;
  while source <> '' do
  begin
    if Pos(delimiter, source) > 0 then 
    begin
      Result.Add(trim(Copy(Source, 1, Pos(delimiter,source)-1)));
      Delete(Source,1 , Length(Result[c]) + Length(delimiter));
    end
    else
    begin
      Result.Add(trim(Source));
      Source := '';
    end;
    inc(c); 
  end;
end;

function ExplodeWithDelimiter(delimiter : string; source : string) : TStringList;
var
  c : word;
begin
  Result:=TStringList.Create; 
  c := 0;

  while source <> '' do
  begin
    if Pos(delimiter, source) > 0 then
    begin
      Result.Add(Copy(Source, 1, Pos(delimiter,source)-1));
      Result.Add(Copy(Source, Pos(delimiter,source),length(delimiter)));
      Delete(Source,1 , Pos(delimiter,source)+length(delimiter)-1);
    end
    else
    begin
      Result.Add(Source);
      Source := '';
    end;
    inc(c); 
  end;
end;

function getFileList(search:String; exts:TStringList): TStringList;
var sr: TSearchRec;
    FileAttrs: Integer;
    list:TStringList;
begin
 list:=TStringList.create();
 FileAttrs:=faAnyFile;

 //search:='D:\Abc-Text\Programs\Delphi\Dedis\Logs\*.log';
 if FindFirst(search, FileAttrs, sr) = 0 then
 begin
  repeat
   if (sr.Attr and FileAttrs) = sr.Attr then
   begin
    if(exts.IndexOf(AnsiUpperCase(ExtractFileExt(sr.Name)))>=0) then list.Add(sr.Name);
   end;
  until FindNext(sr) <> 0;
  FindClose(sr);
 end;
 getFileList:=list;
end;

procedure RotateBitmap(var hBitmapDC : Longint; var lWidth : Longint;
         var lHeight : Longint; lRadians : real);
var
         I : Longint;               // loop counter
         J : Longint;               // loop counter
         hNewBitmapDC : Longint;    // DC of the new bitmap
         hNewBitmap : Longint;      // handle to the new bitmap
         lSine : extended;          // sine used in rotation
         lCosine : extended;        // cosine used in rotation
         X1 : Longint;              // used in calculating new
                                    //   bitmap dimensions
         X2 : Longint;              // used in calculating new
                                    //     bitmap dimensions
         X3 : Longint;              // used in calculating new
                                    //     bitmap dimensions
         Y1 : Longint;              // used in calculating new
                                    // bitmap dimensions
         Y2 : Longint;              // used in calculating new
                                    // bitmap dimensions
         Y3 : Longint;              // used in calculating new
                                    // bitmap dimensions
         lMinX : Longint;           // used in calculating new
                                    // bitmap dimensions
         lMaxX : Longint;           // used in calculating new
                                    // bitmap dimensions
         lMinY : Longint;           // used in calculating new
                                    // bitmap dimensions
         lMaxY : Longint;           // used in calculating new
                                    // bitmap dimensions
         lNewWidth : Longint;       // width of new bitmap
         lNewHeight : Longint;      // height of new bitmap
         lSourceX : Longint;        // x pixel coord we are blitting
                                    // from the source  image
         lSourceY : Longint;        // y pixel coord we are blitting
                                    // from the source image
 
begin
         // create a compatible DC from the one just brought
         // into this function
         hNewBitmapDC := CreateCompatibleDC(hBitmapDC);
 
         // compute the sine/cosinse of the radians used to
         // rotate this image
         lSine := Sin(lRadians);
         lCosine := Cos(lRadians);
 
         // compute the size of the new bitmap being created
         X1 := Round(-lHeight * lSine);
         Y1 := Round(lHeight * lCosine);
         X2 := Round(lWidth * lCosine - lHeight * lSine);
         Y2 := Round(lHeight * lCosine + lWidth * lSine);
         X3 := Round(lWidth * lCosine);
         Y3 := Round(lWidth * lSine);
 
         // figure out the max/min size of the new bitmap
         lMinX := Min(0, Min(X1, Min(X2, X3)));
         lMinY := Min(0, Min(Y1, Min(Y2, Y3)));
         lMaxX := Max(X1, Max(X2, X3));
         lMaxY := Max(Y1, Max(Y2, Y3));
 
         // set the new bitmap width/height
         lNewWidth := lMaxX - lMinX;
         lNewHeight := lMaxY - lMinY;
 
         // create a new bitmap based upon the new width/height of the
         // rotated bitmap
         hNewBitmap := CreateCompatibleBitmap(hBitmapDC, lNewWidth, lNewHeight);
 
         //attach the new bitmap to the new device context created
         //above before constructing the rotated bitmap
         SelectObject(hNewBitmapDC, hNewBitmap);
 
         // loop through and translate each pixel to its new location.
         // this is using a standard rotation algorithm
         For I := 0 To lNewHeight do begin
            For J := 0 To lNewWidth do begin
               lSourceX := Round((J + lMinX) * lCosine + (I + lMinY) * lSine);
               lSourceY := Round((I + lMinY) * lCosine - (J + lMinX) * lSine);
               If (lSourceX >= 0) And (lSourceX <= lWidth) And
               (lSourceY >= 0) And (lSourceY <= lHeight) Then
                   BitBlt(hNewBitmapDC, J, I, 1, 1, hBitmapDC,
                              lSourceX, lSourceY, SRCCOPY);
            end;
         end;
 
         // reset the new bitmap width and height
         lWidth := lNewWidth;
         lHeight := lNewHeight;
 
         // return the DC to the new bitmap
         hBitmapDC := hNewBitmapDC;
 
         // destroy the bitmap created
         DeleteObject(hNewBitmap);
 
      End;

procedure FlipHorizontal(var Bitmap:TBitmap);
type
ByteTriple =array[0..2] of byte        ; // musimy czytać po 3 bajty żeby nie zamienić kolejności BGR na RGB
var
ByteL,ByteR:^ByteTriple;
ByteTemp:ByteTriple;
H,V:Integer;
begin
Bitmap.PixelFormat:=pf24bit;
for V:=0 to (Bitmap.Height -1 )  do
  begin
  ByteL:=Bitmap.ScanLine[V];
  ByteR:=Bitmap.ScanLine[V];
  inc(ByteR,Bitmap.Width -1);
    for H:=0 to (Bitmap.Width -1) div 2  do
    begin
    ByteTemp:=ByteL^;
    ByteL^:=ByteR^;
    ByteR^:=ByteTemp;
    Inc(ByteL);
    Dec(ByteR);
    end;
  end;
end;

begin
  NSDUtils:=BUtils.Create;
end.
