unit convinf;

interface

uses windows,Graphics,classes,iniFiles,SysUtils,StrUtils,Jpeg,TextImages,
light,Messages,types;    //  ,cwMaps
var
 h2:HWND;
 function EnumWndProc(hWindow: HWND; lData: LPARAM):BOOL; stdcall;
type                       

 emTrans = (ts25, ts50, ts75 ,tsAnd,tsOr);

 TAnimeInf = record
  wait:DWORD;
  waitHold,isClip:boolean;
  paintMode:Integer;
  animeMode:Integer;
  animeSpeed:Integer;
  alpha:byte;
  x,y,w,h:Integer;
  cx,cy,cw,ch:Integer;
 end;

 TCacheBox=class(TObject)
 private
  cacheBitmaps:array[1..8] of TBitmap;
 public
  function setBitmap(var bitmap:TBitmap;index:Integer):boolean;
  function getBitmap(var bitmap:TBitmap;index:Integer):boolean;
  destructor destroy();override;
 end;

 TImageDirector=class(TObject)
 private
  cacheBox:TCacheBox;
  dirInf:TDirInf;
  OriginalProc: TFNWndProc;
  function loadText(fileName:string;var bitmap:TBitmap):boolean;
  function loadJPY(fileName:string;var bitmap:TBitmap;lcount:Integer=0):boolean;
 // function loadJPW(fileName:string;var bitmap:TBitmap):boolean;
  procedure setHandle();
  procedure undoDraw();
  procedure setBaseDir(const baseDir:string);
  function getBaseDir():string;
 protected
  resumeBitmap,backBitmap:TBitmap;
  resumePoint:TPoint;
  paintInf:TPaintInf;
  function loadJPV(fileName:string;var bitmap:TBitmap;lcount:Integer=0):boolean;virtual;
  function waitTime(t:Cardinal;hold:boolean=false;holdName:PChar=nil):boolean;
  function loadJpeg(fileName:string;var bitmap:TBitmap):boolean;virtual;
  procedure DrawAnimation(var bitmap:TBitmap;inf:TAnimeInf);virtual;
  procedure DrawHDC(var bitmap:TBitmap;const inf:TAnimeInf);virtual;
 public
  visibleDialog:boolean;
  isSound,isSave:boolean;
  whandle:HWND;
  cwDC:HDC;
  animation:boolean;
  adCanvas:TADCanvas;
  searched:boolean;
  needErase:byte;
  procedure reset();
  function loadImage(fileName:string;var bitmap:TBitmap;lcount:Integer=0):boolean;
  constructor create();
  destructor destroy();override;
  property basedir:string read getBaseDir write setBaseDir;
  function getPaintInf(const inf:TAnimeInf):TPaintInf;
 end;

function SubClassProc(hWindow: HWND; Msg: UINT;
                       wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;

var
 d:TImageDirector;

implementation
uses MMSystem;

{$R bitmap.res}

function SubClassProc(hWindow: HWND; Msg: UINT;
                       wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin


 result := CallWindowProc(d.OriginalProc,hWindow,Msg,wParam,lParam);

 if(Msg=Messages.WM_PAINT)then
 begin
  if(d.backBitmap<>nil)then
    windows.BitBlt(d.cwDC,0,0,632,420,d.backBitmap.Canvas.Handle,0,0,srcCopy);
 end;

end;

(*ウィンドウを順次拾って、処理を行なう*)
function EnumWndProc(hWindow: HWND; lData: LPARAM):BOOL; stdcall;
var
 c1: array[0..255] of Char;
 id:Cardinal;
begin
 GetWindowThreadProcessId(hWindow,id);

 if(ID=windows.GetCurrentProcessId())then
 begin
  GetClassName(hWindow,c1,255);
  if(c1='TMainWindow')then
  begin
   h2:=hWindow;
   result:=false;
  end
  else
   result:=true;
 end
 else result := true;

end;

{cashbox}
(*キャッシュにビットマップ保存*)
function TCacheBox.setBitmap(var bitmap:TBitmap;index:Integer):boolean;
begin
 if(index>=1)and(index<=8)then
 begin
  if(cacheBitmaps[index]=nil)then cacheBitmaps[index]:=TBitmap.Create();

  bitmap.PixelFormat:=pf32bit;
  cacheBitmaps[index].PixelFormat:=pf32bit;
  cacheBitmaps[index].Width:=bitmap.Width;
  cacheBitmaps[index].Height:=bitmap.Height;
  cacheBitmaps[index].Transparent:=bitmap.Transparent;
  bitmap.Canvas.Pixels[0,0]:=bitmap.TransparentColor;
  bitblt(cacheBitmaps[index].Canvas.Handle,0,0,bitmap.Width,bitmap.Height,
   bitmap.Canvas.Handle,0,0,SrcCopy);
  result:=true;
 end
 else
  result:=false;   
end;


(*キャッシュからビットマップ呼び出し*)
function TCacheBox.getBitmap(var bitmap:TBitmap;index:Integer):boolean;
begin
 result:=false;

 if(index>=1)and(index<=8)then
 if(cacheBitmaps[index]<>nil)then
  begin
   bitmap.PixelFormat:=pf32bit;
   bitmap.Width:=cacheBitmaps[index].Width;
   bitmap.Height:=cacheBitmaps[index].Height;
   bitmap.Transparent:=cacheBitmaps[index].Transparent;
   bitmap.TransparentColor:=bitmap.Canvas.Pixels[0,0];
   bitblt(bitmap.Canvas.Handle,0,0,bitmap.Width,bitmap.Height,
    cacheBitmaps[index].Canvas.Handle,0,0,SrcCopy);
   result:=true;
  end;

end;

(*アンドゥ用ビットマップ保存*)
destructor TCacheBox.destroy();
var
 i:Integer;
begin

 for  i:=1  to Length(cacheBitmaps) do
 begin
 if(cacheBitmaps[i]<>nil)then
  begin
  // windows.MessageBox(0,'','',MB_OK);
   cacheBitmaps[i].Free();
  end;
 end;

 end;

{TImageDirector}
constructor TImageDirector.create();
var
 p:PChar;
begin
 inherited;
 adCanvas:=TADCanvas.create();
 OriginalProc:=nil;
 cwDC:=0;
 whandle:=0;
 isSound:=true;
 isSave:=true;
 visibleDialog:=false;
 resumePoint:=Point(0,0);
 self.searched:=false;
 self.animation:=false;
 self.whandle:=0;
 self.needErase:=0;
 getMem(p,255);
 GetModuleFileName(0,p,255);  //起動プログラムのパスをセット
 dirInf.exeDir:=ExtractFileDir(p);
 FreeMem(p,255);

 self.paintInf.destX:=0;
 self.paintInf.destY:=0;
 self.paintInf.destH:=420;
 self.paintInf.srcW:=632;
end;



destructor TImageDirector.destroy();
begin
 if(cacheBox<>nil)then
  cacheBox.Free();

 if(cwdc<>0)then releaseDC(whandle,cwdc);

 if(needErase>1)then undoDraw();

 if(OriginalProc<>nil)then
  SetWindowLong(whandle,GWL_WNDPROC,integer(OriginalProc));

 if(self.backBitmap<>nil)then backBitmap.Free();
 if(resumeBitmap<>nil)then resumeBitmap.Free();

 adcanvas.Free();



 inherited;
end;

(*情報の初期化*)
procedure TImageDirector.reset();
begin
 if(needErase>1)then undoDraw();
 resumePoint:=Point(0,0);
 self.needErase:=0;
end;

(*初めに読み込んだ基準フォルダを書き込み*)
procedure TImageDirector.setBaseDir(const baseDir:string);
begin
 dirInf.firstDir:=baseDir;
end;

(*初めに読み込んだ基準フォルダを読み出し*)
function TImageDirector.getBaseDir():string;
begin
 result:=dirInf.firstDir;
end;

(*ハンドル絡みの設定を一括セット*)
procedure TImageDirector.setHandle();
var
 c1: array[0..255] of Char;
 id:Cardinal;
begin
 h2:=0;
 h2:=getActiveWindow();
 GetWindowThreadProcessId(h2,id);
 GetClassName(h2,c1,255);

 (*カードワースエンジンでアクティブ中かどうか*)
 if(c1<>'TMainWindow')or(id<>getCurrentThreadID())then
 begin
  h2:=0;
  EnumWindows(@EnumWndProc,0);
 end;  

 timeBeginPeriod(1);

  if(h2<>0)then
  begin
   animation:=true;
   self.whandle:=h2;
   OriginalProc := Pointer(GetWindowLong(whandle,GWL_WNDPROC));
   d:=self;
   SetWindowLong(whandle,GWL_WNDPROC,integer(@SubClassProc));
   cwDC:=getDC(self.whandle);
  end
  else
  begin
   whandle:=getActiveWindow();
   animation:=false;
  end;

  self.searched:=true;
end;

(*タイマー*)
function TImageDirector.waitTime(t:Cardinal;hold:boolean=false;holdName:PChar=nil):boolean;
var
 tick:Cardinal;
 count:byte;
 Msg: tagMsg;
 cs:HICON;
 csback:HICON;
 iconName:PChar;
begin
 result:=true;
 


 if(t>0)then
 begin
  tick:=timeGetTime();
  count:=10;

  if(hold)then
  begin
   if(holdName='')then
    iconName:='rclick'
   else
    iconName:=holdName;


   cs:=LoadIcon(hInstance,iconName);
   csback:=windows.GetCursor();
   SetClassLong(whandle,GCL_HCURSOR,cs);
   SetCursor(cs);
  end
  else
   csback:=0;

  while(hold)or(timeGettime()-tick < t)do
  begin

   if(count>=10)then
   begin
    count:=0;
    if(windows.peekMessage(msg,0,0,0,PM_REMOVE))then
    begin
     case msg.message of
     Messages.WM_RBUTTONUP:
     begin
      result:=(GetKeyState( VK_SHIFT ) >= 0);//シフト押しで負を返す
      break;
     end;

     Messages.WM_KEYDOWN:
     begin
      case msg.wParam of
       windows.VK_ESCAPE:
       begin
        result:=(GetKeyState( VK_SHIFT ) >=  0);
        break;
       end;
       windows.VK_F9:
       begin
        result:=false;
        break;
       end;
       windows.VK_SHIFT:
       begin
        windows.DispatchMessage(msg);
        break;
       end;
       end;
     end;
     Messages.WM_MOUSEMOVE,
     Messages.WM_LBUTTONUP,
     Messages.WM_LBUTTONDown,
     Messages.WM_LBUTTONDBLCLK:;
     else
      windows.DispatchMessage(msg);
     end;
    end;

   end
   else
    sleep(1);

   count:=count+1;
  end;

  if(csback<>0)then
  begin
   SetClassLong(whandle,GCL_HCURSOR,csback);
   setCursor(csback);
  end;

 end
 else
   result:=(GetKeyState( VK_SHIFT ) >= 0);
   
end;

(*一時描画した画像を元に戻す*)
procedure TImageDirector.undoDraw();
begin

 if(resumeBitmap<>nil)then
 begin
  try
   bitblt(cwdc,resumePoint.X,resumePoint.Y,resumebitmap.Width,resumebitmap.Height,
         resumeBitmap.Canvas.Handle,0,0,srccopy);
  finally
  end;
 end;

end;

 (*事前に取得したデバイスコンテクストに描画*)
procedure TImageDirector.DrawHDC(var bitmap:TBitmap;const inf:TAnimeInf);
var
 copybitmap:TBitmap;
 union:TRect;
 pInf:TPaintInf;
begin

   try
     pInf.destX:=inf.cx;
     pInf.destY:=inf.cy;
     pInf.destH:=inf.ch;
     pInf.destW:=inf.cw;
     pInf.isClip:=inf.isClip;

     if(backBitmap=nil)then
     begin
      backBitmap:=TBitmap.Create();
      backBitmap.Width:=632;
      backBitmap.Height:=420;
      bitblt(backBitmap.Canvas.Handle,0,0,632,420,cwdc,0,0,srcCopy);
     end;

     if(needErase=3)then  //滑らか画像:合体した後で描画
     begin
      copyBitmap:=TBitmap.Create();
      copyBitmap.PixelFormat:=pf32bit;
      try
       unionRect(union,Bounds(resumePoint.X,resumePoint.Y,resumeBitmap.Width,resumeBitmap.Height),
        Bounds(inf.x,inf.y,bitmap.Width,bitmap.Height));
       copyBitmap.Width:=union.Right - union.Left;
       copyBitmap.Height:=union.Bottom - union.Top;
       bitblt(copyBitmap.Canvas.Handle,0,0,copyBitmap.Width,copyBitmap.Height,
        cwdc,union.Left,union.Top,SrcCopy);
       bitblt(copyBitmap.Canvas.Handle,resumePoint.X-union.Left,
        resumePoint.Y-union.Top,resumeBitmap.Width,resumeBitmap.Height,
        resumeBitmap.Canvas.Handle,0,0,SrcCopy);

       if(inf.animemode>1)then
       begin
        resumeBitmap.Width:=bitmap.Width;
        resumeBitmap.Height:=bitmap.Height;
        bitBlt(resumeBitmap.Canvas.Handle,0,0,bitmap.Width,bitmap.Height,
         copyBitmap.Canvas.Handle,inf.x-union.Left,inf.y-union.Top,SrcCopy);
       end;

       pInf.destX:=inf.cx-union.Left;
       pInf.destY:=inf.cy-union.Top;
       pInf.destH:=inf.ch;
       pInf.destW:=inf.cw;
       pInf.srcX:=inf.x-union.Left;
       pInf.srcY:=inf.y-union.Top;
       pInf.srcH:=bitmap.Height;
       pInf.srcW:=bitmap.Width;
       pInf.mode:=inf.paintmode;
       pInf.alpha:=inf.alpha;

       adCanvas.setBitmap(copyBitmap);
       adCanvas.StretchDrawEx(bitmap,pInf);
       adCanvas.setBitmap(nil);

       bitBlt(backBitmap.Canvas.Handle,union.Left,union.Top,copyBitmap.Width,
         copyBitmap.Height,copyBitmap.Canvas.Handle,0,0,SrcCopy);

       bitBlt(cwdc,union.Left,union.Top,copyBitmap.Width,
        copyBitmap.Height,copyBitmap.Canvas.Handle,0,0,SrcCopy);

      finally
       copyBitmap.Free();
      end;

     end
     else
     begin

      if(needErase=2)then  //元に戻すだけなので高速描画
      begin

       BitBlt(backBitmap.Canvas.Handle,resumePoint.X,resumePoint.Y,
              resumeBitmap.Width,resumeBitmap.Height,resumeBitmap.Canvas.Handle,
              0,0,srccopy);
       BitBlt(cwdc,resumePoint.X,resumePoint.Y,
              resumeBitmap.Width,resumeBitmap.Height,resumeBitmap.Canvas.Handle,
              0,0,srccopy);
      end;

      if(inf.animemode>1)then
      begin
      if(self.resumeBitmap=nil)then
       begin
        resumeBitmap:=TBitmap.Create();
        resumeBitmap.PixelFormat:=pf32bit;
        resumeBitmap.Transparent:=false;
       end;

      resumeBitmap.Width:=bitmap.Width;
      resumeBitmap.Height:=bitmap.Height;

      bitBlt(resumeBitmap.Canvas.Handle,0,0,resumeBitmap.Width,
       resumeBitmap.Height,backBitmap.Canvas.Handle,inf.x,inf.y,SrcCopy)

     end;

     pInf.srcX:=inf.x;
     pInf.srcY:=inf.y;
     pInf.srcH:=bitmap.Height;
     pInf.srcW:=bitmap.Width;
     pInf.alpha:=inf.alpha;
     pInf.mode:=inf.paintMode;

     adCanvas.setBitmap(backBitmap);
     adCanvas.StretchDrawEx(bitmap,pInf);
     adCanvas.setBitmap(nil);

     bitBlt(cwDC,pInf.srcX,
      pInf.srcY,pInf.srcW,PInf.srcH,backBitmap.Canvas.Handle
      ,pInf.srcX,PInf.srcY,SrcCopy);


    // releaseDC(whandle,adCanvas.Handle);
  //   adCanvas.Handle:=0;

     end;
      needErase:=inf.animemode;
      resumePoint:=Point(inf.x,inf.y);

   finally

   end;


end;


(*ファイルネームから画像を生成する*)
function TImageDirector.loadImage(fileName:string;var bitmap:TBitmap;lcount:Integer=0):boolean;
var
 extName:string;
begin
 if(FileExists(fileName))and(lcount<8)then
 begin
  lcount:=lcount+1;
  extName:=ExtractFileExt(AnsiLowerCase(string(fileName)));

  if((extName)='.bmp')then
  begin
   bitmap.LoadFromFile(fileName);
   result:=true;
  end
  else if((extName)='.jpg')or((extName='.jpeg'))then
   result:=loadJpeg(fileName,bitmap)
  else if((extName)='.txt')or((extName='.jptx'))then
  begin
   result:=loadText(fileName,bitmap);
  end
  else if(extName='.jpy1')then
   result:=loadJPY(fileName,bitmap,lcount)
 // else if(extName='.jpmp')then
 //  result:=loadJPW(fileName,bitmap)
  else if(extName='.jpdc')then
   result:=loadJPV(fileName,bitmap,lcount)
  else if(extName='.wav')then
  begin
   result:=false;
   if(isSound)then
   playsound(PChar(fileName),0,SND_ASYNC);
  end
  else result:=false;
 end
 else if(visibleDialog)then
 begin
  windows.MessageBox(0,PChar(fileName),'ファイルが見つかりません',MB_OK);
  result:=false;
 end
 else
  result:=false;

end;

(*現在のウィンドウを取得*)
function TImageDirector.loadJPV(fileName:string;var bitmap:TBitmap;lcount:Integer=0):boolean;
var
 ini:TMemIniFile;
 copyBitmap:TBitmap;
 x,y,mode:Integer;
 comment,s,savefileName:string;
 vArray:TIntegerDynArray;
 oldName:PChar;
const
 DEFCOPY=0;
 PRECOPY=1;
 METACOPY=2;
 None=3;
 CACHEBOX=4;
begin

  result:=false;

  if not(searched)then setHandle();

  if(cwDC=0)and(whandle=0)then
  begin
   whandle:=getActiveWindow();
   cwDC:=getDC(whandle);
  end;

  if(bitmap=nil)then
  begin
   bitmap:=TBitmap.Create();
  end;

  bitmap.PixelFormat:=pf32bit;

  try
   ini:=TMemIniFile.Create(fileName);
   mode:=ini.ReadInteger('jpdc:init','copymode',DEFCOPY);

   if(mode=DEFCOPY)then
   begin
    if(backBitmap=nil)then mode:=PRECOPY //一時描画前画像をコピー
    else mode:=METACOPY;   //現在表示中のウィンドウをコピー
   end;


   savefileName:=ini.ReadString('jpdc:init','savefilename','');

   if(savefileName<>'')then
    comment:=ini.ReadString('jpdc:init','savecomment','')
   else
    comment:='';

   s:=ini.ReadString('jpdc:init','clip','');
   vArray:=TTagText.getIntArray(s,4,-1);

   if(vArray[0]>-1)then x:=vArray[0]
   else x:=0;
   if(vArray[1]>-1)then y:=vArray[1]
   else y:=0;
   if(vArray[2]>0)then bitmap.Width:=vArray[2]
   else bitmap.Width:=632-x;
   if(vArray[3]>0)then bitmap.Height:=vArray[3]
   else bitmap.Height:=420-y;

  finally
   ini.Free();
  end;

   if(cwdc<>0)then
   begin
    try

     if(mode=PRECOPY)then
     begin
      copyBitmap:=TBitmap.Create();
      copyBitmap.Width:=632;
      copyBitmap.Height:=420;
      (*隠れているウィンドウ部分もコピー*)
      SendMessage(whandle, WM_ERASEBKGND, copyBitmap.Canvas.Handle, 0);
      SendMessage(whandle, WM_PAINT, copyBitmap.Canvas.Handle, 0);
      bitblt(bitmap.Canvas.Handle,0,0,bitmap.Width,bitmap.Height,
       copyBitmap.Canvas.Handle,x,y,srccopy);
      copyBitmap.Free();
      result:=true;
     end
     else if(mode=METACOPY)then
     begin
      if(backBitmap<>nil)then
       bitblt(bitmap.Canvas.Handle,0,0,bitmap.Width,bitmap.Height,
        backBitmap.Canvas.Handle,x,y,srccopy)
      else
       bitblt(bitmap.Canvas.Handle,0,0,bitmap.Width,bitmap.Height,
        cwdc,x,y,srccopy);
      result:=true;
     end
     else if(mode=None)then
     begin
      bitmap.PixelFormat:=pf1bit;
      bitmap.Canvas.Brush.Color:=clwhite;
      bitmap.Canvas.FillRect(bitmap.Canvas.ClipRect);
      result:=true;
     end;


     if(self.isSave)and(lcount=1)then
     begin

      if(savefileName<>'')then
      begin
       savefileName:=concat(extractFileDir(fileName),'\'+savefileName);
       comment:=stringReplace
        (comment,'%file%',extractFileName(saveFileName),[rfIgnoreCase,rfReplaceAll]);
       comment:=stringReplace
        (comment,'%dir%',extractFileDir(saveFileName),[rfIgnoreCase,rfReplaceAll]);


       if(comment='')then
        comment:='画像を'+savefileName+'に保存します';

       getMem(oldName,255);
       windows.GetWindowText(self.whandle,oldName,255);
       windows.SetWindowText(self.whandle,PChar(comment));
       waitTime(Cardinal(-1),true,'save');
       if not(getKeyState(VK_F9)< 0)then
       Bitmap.SaveToFile(savefileName);
       windows.SetWindowText(self.whandle,oldName);

      end;
     end;

    except
     result:=false;
    end;

   end
   else result:=false;

  

end;


(*設定ファイルを読み込んでビットマップ形式にする*)
function TImageDirector.loadJPY(fileName:string;var bitmap:TBitmap;lcount:Integer=0):boolean;
var
 dirName,vString:string;
 ini:TMemIniFile;
 iniList:TStringList;
 i,v,v2,w,h:Integer;
 x,y:Integer;
 isload:boolean;
 bitmap1:TBitmap;
 animeInf:TAnimeInf;
 vArray:TIntegerDynArray;
begin


 dirInf.currentFile:=fileName;
 bitmap1:=TBitmap.Create();
 bitmap1.PixelFormat:=pf32bit;

 iniList:=TStringList.Create();

 try
  ini:=TMemIniFile.Create(fileName);
  ini.ReadSections(iniList);
  v:=iniList.IndexOf('init');

  if(v<>-1)then
   iniList.Delete(v);


  (*基本描画領域の初期化*)


  if(lcount=1)then
  begin
   v:=ini.ReadInteger('init','dirdepth',0);
   if(v>0)then
   begin
    vString:=ExtractFileDrive(baseDir);
    for i:=1 to v do
    begin
     basedir:=ExtractFileDir(basedir);
     if(basedir=vString)then break;
    end;
   end;
  end;

  v:=ini.ReadInteger('init','loadcache',0);
  if(v>0)and(cacheBox<>nil)then
  begin
   isload:=cacheBox.getBitmap(bitmap,v);
  end
  else isload:=false;

  bitmap.Transparent:=false;

  if not(isload)then
  if ini.ValueExists('init','fileName') then
  begin
   dirInf.fileName:=ini.ReadString('init','filename','');

   if(dirInf.fileName<>'')then
   begin
    dirInf.mode:=ini.ReadInteger('init','dirtype',1);

    dirName:=TTagText.serachFileName(dirInf);
    if(dirName<>fileName)then
    begin
     isload:=loadImage(dirName,bitmap,lcount);
     bitmap.PixelFormat:=pf32bit;
    end;
    
   end;

  end;

  if not(isload)then
  begin
   bitmap.Width:=ini.ReadInteger('init','backwidth',632);
   bitmap.Height:=ini.ReadInteger('init','backheight',420);
   fillBMP(bitmap,TTagText.getColor
    (ini.ReadString('init','backcolor','0')),false);
  end
  else
  begin


  v:=ini.ReadInteger('init','backwidth',-1);
  if(v=-1)then
   v:=bitmap.Width;

  v2:=ini.ReadInteger('init','backheight',-1);
  if(v2=-1)then
   v2:=bitmap.Height;

  vString:=ini.ReadString('init','clip','');
  if(vstring<>'')then
  begin
   vArray:=TTagText.getIntArray(vstring,4,-1);
   if(vArray[0]>-1)and(vArray[1]>-1)
    and(vArray[2]>0)and(vArray[3]>0)then
   begin
    light.EffectClip(bitmap,Rect(vArray[0],vArray[1],vArray[2],vArray[3]));
   end;
  end;

  if(v<>bitmap.Width)or(v2<>bitmap.Height)then
   light.EffectResize(bitmap,v,v2,ini.ReadBool('init','smooth',false));

  end;

  (*サブ*)
  for i:=0 to iniList.Count-1 do
  begin
   (*キャッシュ*)
   v:=ini.ReadInteger(iniList.Strings[i],'loadcache',0);

   if(v>0)and(cacheBox<>nil)then
   begin
    isload:=cacheBox.getBitmap(bitmap1,v);
   end
   else isload:=false;

   if not(isload)then
   begin
    dirInf.currentFile:=fileName;
    dirinf.FileName:=ini.ReadString(iniList.Strings[i],'filename','');

    if(dirinf.FileName<>'')then
    begin
     dirInf.mode:=ini.ReadInteger(iniList.Strings[i],'dirtype',1);
     dirName:=TTagText.serachFileName(dirInf);

     if(dirName<>fileName)then
     begin

      isload:=loadImage(dirName,bitmap1,lcount);
      bitmap1.PixelFormat:=pf32bit;
     end
     else
      isload:=false;
      
    end
    else isload:=false;

   end;

   if not(isload)then
   begin
    w:=ini.ReadInteger(iniList.Strings[i],'width',-1);
    h:=ini.ReadInteger(iniList.Strings[i],'height',-1);
    if(w>-1)and(h>-1)then
    begin
     bitmap1.Width:=w;
     bitmap1.Height:=h;
     fillBMP(bitmap1,TTagText.getColor
      (ini.ReadString(iniList.Strings[i],'color','0')),false);
      isload:=true;
    end;
   end;

   if(isload)then
   begin

   (*基本情報*)
    bitmap1.Transparent:=ini.ReadBool(iniList.Strings[i],'transparent',true);

    vString:=ini.ReadString(iniList.Strings[i],'clip','');
    if(vstring<>'')then
    begin
     vArray:=TTagText.getIntArray(vstring,4,-1);
     if(vArray[0]>-1)and(vArray[1]>-1)
      and(vArray[2]>0)and(vArray[3]>0)then
      begin
       light.EffectClip(bitmap1,Bounds(vArray[0],vArray[1],vArray[2],vArray[3]));
      end;
    end;

   vString:=ini.ReadString(iniList.Strings[i],'position','');
   vArray:=TTagText.getIntArray(vString,2,0);
   x:=vArray[0];
   y:=vArray[1];

   w:=ini.ReadInteger(iniList.Strings[i],'width',bitmap1.Width);
   h:=ini.ReadInteger(iniList.Strings[i],'height',bitmap1.Height);

  (*パーツの最終調整*)

   v:=ini.ReadInteger(iniList.Strings[i],'colorexchange',-1);
   if(v>0)then
    light.EffectShiftRGB(bitmap1,v);

   v:=ini.ReadInteger(iniList.Strings[i],'filter',-1);
   case v of
      10:light.EffectEnbos(bitmap1);
       9:light.EffectNOTMask(bitmap1);
       8:light.EffectKakusan(bitmap1);
       7:bitmap1.Mask(bitmap1.Canvas.Pixels[0,0]);
    1..6:light.EffectCustom(bitmap1,v);
   end;

   v:=ini.ReadInteger(iniList.Strings[i],'colormap',-1);
   if(v>-1)then
   begin
    light.EffectSepia(bitmap1,v);
   end;

   if(ini.ReadBool(iniList.Strings[i],'flip',false))then
    light.EffectFlip(bitmap1);

   if(ini.ReadBool(iniList.Strings[i],'mirror',false))then
    light.EffectMirror(bitmap1);

   (*ノイズ*)
   v:=ini.ReadInteger(iniList.Strings[i],'noise',-1);
   if(v>0)then
   begin
    v2:=ini.ReadInteger(iniList.Strings[i],'noisepoint',0);
    case v of
    1:light.EffectLightMode(bitmap1,v2);
    2:light.EffectMono(bitmap1,v2);
    3:light.EffectNoize(bitmap1,v2,1);
    4:light.EffectNoize(bitmap1,v2,2);
    5:light.EffectsMosaic(bitmap1,v2);
    end;
   end;

  bitmap1.TransparentColor:=bitmap1.Canvas.Pixels[0,0];

  (*回転*)
  case ini.ReadInteger(iniList.Strings[i],'turn',0) of
   1:
   begin
    light.EffectsTurn90(bitmap1);
    v:=w;
    w:=h;
    h:=v;
   end;
   2:
   begin
    light.EffectsTurn270(bitmap1);
    v:=w;
    w:=h;
    h:=v;
   end;
  end;

  (*伸縮*)
  if(bitmap1.Width<>w)or(bitmap1.Height<>h)then
   light.EffectResize(bitmap1,w,h,
    ini.ReadBool(iniList.Strings[i],'smooth',false));

  (*マスク*)
  v:=ini.ReadInteger(iniList.Strings[i],'mask',0);
  if(v>0)then
   light.EffectThreadLine(bitmap1,v);

  (*キャッシュ*)
  v:=ini.ReadInteger(iniList.Strings[i],'savecache',0);
  if(v>0)then
  begin
   if(cacheBox=nil)then cacheBox:=TCacheBox.Create();
   cacheBox.setBitmap(bitmap1,v);
  end;

  (*直接描画するか判定*)

  animeInf.animemode:=ini.ReadInteger(iniList.Strings[i],'animation',0);
  animeInf.paintmode:=ini.ReadInteger(iniList.Strings[i],'paintmode',0);
  animeInf.alpha:=ini.ReadInteger(iniList.Strings[i],'alpha',0);

  if(animeInf.animemode>0)then
  begin
   v:=ini.ReadInteger(iniList.Strings[i],'wait',0);
   animeInf.wait:=v;
   animeInf.waitHold:=(v=-1);

   vString:=ini.ReadString(iniList.Strings[i],'animeclip','');
   if(vstring<>'')then
   begin
     vArray:=TTagText.getIntArray(vstring,4,-1);
     animeInf.cx:=vArray[0];
     animeInf.cy:=vArray[1];
     animeInf.cw:=vArray[2];
     animeInf.ch:=vArray[3];

     animeInf.isClip:=
      (vArray[0]>-1)and(vArray[1]>-1)and(vArray[2]>0)and(vArray[3]>0);
   end
   else animeInf.isClip:=false;

   animeInf.w:=bitmap1.Width;
   animeInf.h:=bitmap1.Height;

   vString:=ini.ReadString(iniList.Strings[i],'animemove','');
   if(vString<>'')then
   begin
    vArray:=TTagText.getIntArray(vString,2,0);
    animeInf.x:=resumePoint.X+vArray[0];
    animeInf.y:=resumePoint.Y+vArray[1];
   end
   else
   begin
    vString:=ini.ReadString(iniList.Strings[i],'animeposition','');
    if(vString<>'')then
    begin
     vArray:=TTagText.getIntArray(vString,2,0);
     animeInf.x:=vArray[0];
     animeInf.y:=vArray[1];
    end
    else
    begin
     animeInf.x:=x;
     animeInf.y:=y;
    end;


   end;
   animeInf.animeSpeed:=ini.ReadInteger(iniList.Strings[i],'animespeed',0);

   self.DrawAnimation(bitmap1,animeInf);
  end;


  if not(ini.ReadBool(iniList.Strings[i],'visible',true))then
  continue;


  (*大元のビットマップへ描写*)

  paintInf.srcX:=x;
  paintInf.srcY:=y;
  paintInf.srcH:=bitmap1.Height;
  paintInf.srcW:=bitmap1.Width;
  paintInf.alpha:=animeInf.alpha;
  paintInf.mode:=animeInf.paintMode;
  paintInf.isClip:=false;

  adCanvas.setBitmap(bitmap);
  adcanvas.StretchDrawEx(bitmap1,paintInf);
  adCanvas.setBitmap(nil);

 // releaseDC(0,adCanvas.Handle);
 // adCanvas.Handle:=0;
   end
   else
   begin
    animeInf.animemode:=ini.ReadInteger(iniList.Strings[i],'animation',0);
    if(animeInf.animemode=4)then
    begin
     v:=ini.ReadInteger(iniList.Strings[i],'wait',0);
     animeInf.wait:=v;
     animeInf.waitHold:=(v<0);
     if not(searched)then self.setHandle();
     if(animation)then self.animation:=waitTime(animeInf.wait,animeInf.waitHold);
    end;
   end;
  end;


 (*画像全体の最終調整*)

  v:=ini.ReadInteger('init','filter',-1);
  case v of
     10:light.EffectEnbos(bitmap);
      9:light.EffectNOTMask(bitmap);
      8:light.EffectKakusan(bitmap);
      7:bitmap.Mask(bitmap.Canvas.Pixels[0,0]);
   1..6:light.EffectCustom(bitmap,v);
  end;

  v:=ini.ReadInteger('init','colormap',-1);
  if(v>0)then
   light.EffectSepia(bitmap,v);

  v:=ini.ReadInteger('init','colorexchange',-1);
  if(v>0)then
   light.EffectShiftRGB(bitmap,v);

  if(ini.ReadBool('init','flip',false))then
   light.EffectFlip(bitmap);

  if(ini.ReadBool('init','mirror',false))then
   light.EffectMirror(bitmap);

  (*ノイズ*)
  v:=ini.ReadInteger('init','noise',-1);
  if(v>0)then
  begin
   v2:=ini.ReadInteger('init','noisepoint',0);
   case v of
    1:light.EffectLightMode(bitmap,v2);
    2:light.EffectMono(bitmap,v2);
    3:light.EffectNoize(bitmap,v2,1);
    4:light.EffectNoize(bitmap,v2,2);
    5:light.EffectsMosaic(bitmap,v2);
   end;
  end;

   case ini.ReadInteger('init','turn',0) of
   1:
   begin
    light.EffectsTurn90(bitmap);
   end;
   2:
   begin
    light.EffectsTurn270(bitmap);
   end;
  end;

  v:=ini.ReadInteger('init','mask',0);
  if(v>0)then
   light.EffectThreadLine(bitmap,v);

 (*直接を描画するか判定*)

 animeInf.animemode:=ini.ReadInteger('init','animation',0);

  if(animeInf.animemode>0)then
  begin
   v:=ini.ReadInteger('init','wait',0);
   animeInf.wait:=v;
   animeInf.waitHold:=(v=-1);


   vString:=ini.ReadString('init','animemove','');
   if(vString<>'')then
   begin
    vArray:=TTagText.getIntArray(vString,2,0);
    animeInf.x:=resumePoint.X+vArray[0];
    animeInf.y:=resumePoint.Y+vArray[1];
   end
   else
   begin
    vString:=ini.ReadString('init','animeposition','');
    if(vString<>'')then
    begin
     vArray:=TTagText.getIntArray(vString,2,0);
     animeInf.x:=vArray[0];
     animeInf.y:=vArray[1];
    end
    else
    begin
     vString:=ini.ReadString('init','position','');
     vArray:=TTagText.getIntArray(vString,2,0);
     animeInf.x:=vArray[0];
     animeInf.y:=vArray[1];
    end;
   end;

   animeInf.x:=Max(-2000,Min(animeInf.x,2000));
   animeInf.y:=Max(-2000,Min(animeInf.y,2000));

   animeInf.w:=bitmap.Width;
   animeInf.h:=bitmap.Height;

   animeInf.paintmode:=ini.ReadInteger('init','paintmode',0);
   animeInf.alpha:=ini.ReadInteger('init','alpha',0);

   if(ini.ReadBool('init','transparent',false))then
   begin
    bitmap.Transparent:=true;
    bitmap.TransparentColor:=bitmap.Canvas.Pixels[0,0];
   end
   else
    bitmap.Transparent:=false;

   animeInf.animeSpeed:=ini.ReadInteger('init','animespeed',0);

   vString:=ini.ReadString('init','animeclip','');
   if(vstring<>'')then
   begin
     vArray:=TTagText.getIntArray(vstring,4,-1);
     animeInf.cx:=vArray[0];
     animeInf.cy:=vArray[1];
     animeInf.cw:=vArray[2];
     animeInf.ch:=vArray[3];
     animeInf.isClip:=
      (vArray[0]>-1)and(vArray[1]>-1)and(vArray[2]>0)and(vArray[3]>0);
   end
   else animeInf.isClip:=false;

   self.DrawAnimation(bitmap,animeInf);
  end;

  ini.Free();
  result:=true;
 except
  ini.Free();
  result:=false;
 end;
  

  iniList.Free();
  bitmap1.Free();

end;

(*一時描画情報を描画情報に変換*)
function TImageDirector.getPaintInf(const inf:TAnimeInf):TPaintInf;
begin
 result.alpha:=inf.alpha;
 result.mode:=inf.paintMode;
 result.alpha:=inf.alpha;
 result.srcX:=inf.x;
 result.srcY:=inf.y;
 result.srcH:=inf.h;
 result.srcW:=inf.w;
 result.destX:=inf.cx;
 result.destY:=inf.cy;
 result.destH:=inf.ch;
 result.destW:=inf.cw;
end;



(*JPEGファイルを読み込んでビットマップ形式にする*)
function TImageDirector.loadJpeg(fileName:string;var bitmap:TBitmap):boolean;
var
 jImage:TJpegImage;
begin

  jImage:=TJpegImage.Create();
  
  if(bitmap=nil)then
   bitmap:=TBitmap.create();

  try
   JImage.PixelFormat:=jf24Bit;
   JImage.LoadFromFile(fileName);
   bitmap.Assign(JImage);
   result:=true;
  except
   result:=false;
  end;

  jImage.Free;


end;

(*マップファイルを読み込んでビットマップ形式にする
function TImageDirector.loadJPW(fileName:string;var bitmap:TBitmap):boolean;
var
 map:TCWMap;
begin

  map:=TCWMap.Create();
  map.dirInf:=self.dirInf;

  bitmap:=TBitmap.create();
  try
   bitmap.PixelFormat:=pf32bit;
   map.loadMap(fileName,bitmap);
   result:=true;
  except
   result:=false;
  end;

  map.Free;

end;
*)

(*テキストファイルを読み込んでビットマップ形式にする*)
function TImageDirector.loadText(fileName:string;var bitmap:TBitmap):boolean;
var
 text:TTextImage;
begin

  text:=TTextImage.Create();
  try
   text.loadText(fileName,bitmap);
  finally
   text.Free;
  end;

  result:=(bitmap<>nil)and(bitmap.Width*bitmap.Height<>0);

end;

(*画像をカードワース本体の画面に一時描画*)
procedure TImageDirector.DrawAnimation(var bitmap:TBitmap;inf:TAnimeInf);
var
 goalPoint:TPoint;
 distance,v:double;
 restX,restY:Integer;
 vX,vY:boolean;
begin
 if not(searched)then setHandle();

 if(bitmap<>nil)and(animation)and(inf.animemode>0)then
 begin
  if(cwdc<>0)then
  begin

   if(inf.animemode=4)then  //４だと単なるスキップ
   begin
  //  cs:=LoadIcon(hInstance,'rclick');
 //   csback:=windows.GetCursor();
  //  SetClassLong(whandle,GCL_HCURSOR,cs);
 //   SetCursor(cs);
 //  inf.waitHold:=(Int(inf.wait)<0);

    animation:=waitTime(Inf.wait,inf.waitHold);
   end
    (*いきなり指定座標に描画*)
   else if(inf.animeSpeed=0)then
   begin
    self.DrawHDC(bitmap,inf);
    animation:=waitTime(Inf.wait,inf.waitHold);
   end
   else
   begin

    goalPoint:=Point(inf.x,inf.y);
    inf.x:=resumePoint.X;
    inf.y:=resumePoint.Y;

    restX:=goalPoint.X-inf.x;
    vX:=restX>-1;
    restY:=goalPoint.Y-inf.y;
    vY:=restY>-1;

    (*指定座標まで何度も描画*)
    while(restX<>0)or(restY<>0)do
    begin
     distance:=Sqrt(restX*restX+restY*restY);
     v:=distance / inf.animeSpeed;
     if(v=0)then v:=1;


     (*一時描画が行き過ぎないように調整*)
     if(restX<>0)then
     begin
      inf.x:=inf.x+Round(restX/v);
      restX:=goalPoint.X-inf.x;

      if(restX<0)and(vX)then
      begin
       inf.x:=goalPoint.X;
       restX:=0;
      end
      else if (restX>0)and (not vX)then
      begin
       inf.x:=goalPoint.X;
       restX:=0;
      end;

     end;

     if(restY<>0)then
     begin
      inf.y:=inf.y+Round(restY/v);
      restY:=goalPoint.Y-inf.y;

      if(restY<0)and(vY)then
      begin
       inf.y:=goalPoint.Y;
       restY:=0;
      end
      else if (restY>0)and(not vY)then
      begin
       inf.y:=goalPoint.Y;
       restY:=0;
      end;

   end;

    DrawHDC(bitmap,inf);

     animation:=waitTime(Inf.wait,inf.waitHold);
     if not(self.animation)then break;


    end;
     inf.y:=goalPoint.Y;
     inf.x:=goalPoint.X;
     
   end;

  end;

 end;

end;


end.
