RVJvGifAnimate.pas
上传用户:daoqigc
上传日期:2021-04-20
资源大小:2795k
文件大小:9k
源码类别:

RichEdit

开发平台:

Delphi

  1. {*******************************************************}
  2. {                                                       }
  3. {       RichView                                        }
  4. {       TRVJvGIFImageAnimator: displaying animation for }
  5. {       TJvGIFImage from Project JEDI's JVCL.           }
  6. {       http://jvcl.sourceforge.net                     }
  7. {                                                       }
  8. {       Copyright (c) Sergey Tkachenko                  }
  9. {       svt@trichview.com                               }
  10. {       http://www.trichview.com                        }
  11. {                                                       }
  12. {*******************************************************}
  13. {$I RV_Defs.inc}
  14. unit RVJvGifAnimate;
  15. interface
  16. {$IFNDEF RVDONOTUSEANIMATION}
  17. uses Windows, Classes, Graphics, DLines,
  18.      CRVFData, RVAnimate, RVItem, JvGif;
  19. type
  20.   { ---------------------------------------------------------------------------
  21.     TRVJvGifImageAnimator: displaying animations for gif images
  22.     (using TJvGIFImage from Project JEDI's JVCL)
  23.     Variables:
  24.       bmp: the current frame of animation
  25.       bmpsrc: background under the image (if it is not a plain color, otherwise
  26.         it's nil)
  27.       FX, FY - the stored values of image position. Used to check if the image
  28.         is moved.
  29.       FParaNo - the stored value of paragraph image. Used to check if the
  30.         paragraph is changed (may be it's background was changed?)
  31.       FLastDrawnFrameIndex - index of the frame drawn in bmp.
  32.   }
  33.   TRVJvGifImageAnimator = class (TRVAnimator)
  34.     private
  35.       bmp, bmpsrc: TBitmap;
  36.       FBackColor: TColor;
  37.       FX,FY, FParaNo, FLastDrawnFrameIndex: Integer;
  38.       procedure CalcInterval;
  39.     protected
  40.       function GetFrameCount: Integer; override;
  41.       procedure ResetBackground; override;
  42.     public
  43.       destructor Destroy; override;
  44.       procedure Reset; override;
  45.       procedure ChangeFrame; override;
  46.       procedure Draw(X, Y: Integer; Canvas: TCanvas; Animation: Boolean); override;
  47.   end;
  48. {$ENDIF}
  49. implementation
  50. {$IFNDEF RVDONOTUSEANIMATION}
  51. {================================= TRVJvGifImageAnimator ========================}
  52. { Destructor }
  53. destructor TRVJvGifImageAnimator.Destroy;
  54. begin
  55.   bmp.Free;
  56.   bmpsrc.Free;
  57.   inherited;
  58. end;
  59. {------------------------------------------------------------------------------}
  60. { Determines how long to display the current frame. }
  61. procedure TRVJvGifImageAnimator.CalcInterval;
  62. var gif: TJvGIFImage;
  63. begin
  64.   gif := TJvGIFImage(TRVGraphicItemInfo(item).Image);
  65.   Interval := 100;
  66.   if gif.Frames[FrameIndex].AnimateInterval > 0 then begin
  67.     Interval := gif.Frames[FrameIndex].AnimateInterval;
  68.   end;
  69. end;
  70. {------------------------------------------------------------------------------}
  71. { Change frame to the next one. Updates Interval. }
  72. procedure TRVJvGifImageAnimator.ChangeFrame;
  73. begin
  74.   CalcNextFrameIndex;
  75.   CalcInterval;
  76. end;
  77. {------------------------------------------------------------------------------}
  78. { Clears the stored background info }
  79. procedure TRVJvGifImageAnimator.ResetBackground;
  80. begin
  81.   bmpsrc.Free;
  82.   bmpsrc := nil;
  83.   bmp.Free;
  84.   bmp := nil;
  85. end;
  86. {------------------------------------------------------------------------------}
  87. { Draws the current frame }
  88. procedure TRVJvGifImageAnimator.Draw(X, Y: Integer; Canvas: TCanvas; Animation: Boolean);
  89. var gif: TJvGIFImage;
  90.     i: Integer;
  91.     UseSrcBitmap: Boolean;
  92.     r: TRect;
  93.     function ScaleRect(const DestRect: TRect; FrameIndex: Integer): TRect;
  94.     var
  95.       HeightMul  ,
  96.       HeightDiv  : integer;
  97.       WidthMul  ,
  98.       WidthDiv  : integer;
  99.     begin
  100.       with gif.Frames[FrameIndex] do begin
  101.         HeightDiv := gif.Height;
  102.         HeightMul := DestRect.Bottom-DestRect.Top;
  103.         WidthDiv := gif.Width;
  104.         WidthMul := DestRect.Right-DestRect.Left;
  105.         Result.Left := DestRect.Left + muldiv(Origin.X, WidthMul, WidthDiv);
  106.         Result.Top := DestRect.Top + muldiv(Origin.Y, HeightMul, HeightDiv);
  107.         Result.Right := DestRect.Left + muldiv(Origin.X+Width, WidthMul, WidthDiv);
  108.         Result.Bottom := DestRect.Top + muldiv(Origin.Y+Height, HeightMul, HeightDiv);
  109.       end;
  110.     end;
  111.     procedure MakeBitmap(FrameIndex: Integer);
  112.     var r: TRect;
  113.     begin
  114.       if FrameIndex>0 then
  115.         case gif.Frames[FrameIndex-1].DisposalMethod of
  116.           dmRestoreBackground:
  117.             begin
  118.               r := Rect(0,0,bmp.Width,bmp.Height);
  119.               if bmpsrc<>nil then
  120.                 bmp.Canvas.CopyRect(r, bmpsrc.Canvas, r)
  121.               else begin
  122.                 bmp.Canvas.Brush.Color := FBackColor;
  123.                 bmp.Canvas.FillRect(r);
  124.               end;
  125.             end;
  126.         end
  127.       else begin
  128.         if bmpsrc<>nil then
  129.           bmp.Assign(bmpsrc)
  130.         else begin
  131.           bmp.Canvas.Brush.Color := FBackColor;
  132.           bmp.Canvas.FillRect(Rect(0,0,bmp.Width,bmp.Height));
  133.         end;
  134.       end;
  135.       r := ScaleRect(Rect(0, 0, item.GetImageWidth(nil), item.GetImageHeight(nil)), FrameIndex);
  136.       gif.Frames[FrameIndex].Draw(bmp.Canvas, r, gif.Transparent);
  137.     end;
  138. begin
  139.   gif := TJvGIFImage(TRVGraphicItemInfo(item).Image);
  140.   if (bmp=nil) or
  141.     (item.ParaNo<>FParaNo) or
  142.     (X<>FX) or
  143.     (Y<>FY) or
  144.     (bmp.Width<>item.GetImageWidth(nil)) or
  145.     (bmp.Height<>item.GetImageHeight(nil)) then begin
  146.     bmp.Free;
  147.     bmp := TBitmap.Create;
  148.     bmp.Width := item.GetImageWidth(nil);
  149.     bmp.Height := item.GetImageHeight(nil);
  150.     FParaNo := item.ParaNo;
  151.     FX := X;
  152.     FY := Y;
  153.     if gif.Transparent then begin
  154.       r := Rect(0,0,0,0);
  155.       RVData.GetItemBackground(RVData.DrawItems[item.DrawItemNo].ItemNo, r, True,
  156.         FBackColor, bmpsrc, UseSrcBitmap);
  157.       if not UseSrcBitmap then begin
  158.         bmp.Canvas.Brush.Color := RVData.GetColor;
  159.         bmp.Canvas.FillRect(Rect(0,0,bmp.Width,bmp.Height));
  160.       end;
  161.       end
  162.     else begin
  163.       FBackColor := clWhite;
  164.       UseSrcBitmap := False;
  165.     end;
  166.     if not UseSrcBitmap then begin
  167.       bmpsrc.Free;
  168.       bmpsrc := nil;
  169.     end;
  170.     for i := 0 to FrameIndex-1 do
  171.       MakeBitmap(i);
  172.     end
  173.   else if (FrameIndex=FLastDrawnFrameIndex) then begin
  174.     Canvas.Draw(X,Y,bmp);
  175.     exit;
  176.     end
  177.   else if (FrameIndex>0) and (FLastDrawnFrameIndex<>FrameIndex-1) then begin
  178.     if FLastDrawnFrameIndex<FrameIndex then begin
  179.       for i := FLastDrawnFrameIndex+1 to FrameIndex-1 do
  180.         MakeBitmap(i);
  181.       end
  182.     else
  183.       for i := 0 to FrameIndex-1 do
  184.         MakeBitmap(i);
  185.   end;
  186.   MakeBitmap(FrameIndex);
  187.   FLastDrawnFrameIndex := FrameIndex;
  188.   Canvas.Draw(X,Y,bmp);
  189. end;
  190. {------------------------------------------------------------------------------}
  191. { Returns a number of frames in gif }
  192. function GetGifFrameCount(gif: TJvGIFImage): Integer;
  193. begin
  194.   Result := gif.Count;
  195. end;
  196. {------------------------------------------------------------------------------}
  197. { Returns a number of frames }
  198. function TRVJvGifImageAnimator.GetFrameCount: Integer;
  199. begin
  200.   Result := TJvGIFImage(TRVGraphicItemInfo(item).Image).Count;
  201. end;
  202. {------------------------------------------------------------------------------}
  203. { Rewinds to the first frame. Updates Interval. }
  204. procedure TRVJvGifImageAnimator.Reset;
  205. begin
  206.   bmp.Free;
  207.   bmp := nil;
  208.   bmpsrc.Free;
  209.   bmpsrc := nil;
  210.   FrameIndex := 0;
  211.   FLastDrawnFrameIndex := -1;
  212.   CalcInterval;
  213. end;
  214. {==============================================================================}
  215. var DefMakeAnimator: TRVMakeAnimatorProc;
  216. { This procedure creates an animator (anim) for the item, if it's necessary.
  217.   This procedure can create only TRVJvGifImageAnimator.
  218.   If it cannot be applied, it calls the stored value of RV_MakeAnimator. }
  219. procedure RV_MakeAnimatorGif(item: TCustomRVItemInfo; RVData: TCustomRVFormattedData;
  220.   var anim: TRVAnimator);
  221. begin
  222.   if (item is TRVGraphicItemInfo) and
  223.      (TRVGraphicItemInfo(item).Image is TJvGifImage) and
  224.      (GetGifFrameCount(TJvGIFImage(TRVGraphicItemInfo(item).Image))>1) then begin
  225.     if (anim<>nil) and not (anim is TRVJvGifImageAnimator) then begin
  226.       anim.Free;
  227.       anim := nil;
  228.     end;
  229.     if anim=nil then begin
  230.       anim := TRVJvGifImageAnimator.Create(RVData, Item);
  231.       RVData.InsertAnimator(TObject(anim));
  232.       end
  233.     else if anim<>nil then begin
  234.       anim.Update(RVData, Item);
  235.       anim.Reset;
  236.     end;
  237.     exit;
  238.   end;
  239.   DefMakeAnimator(item, RVData, anim)
  240. end;
  241. initialization
  242.   DefMakeAnimator := RV_MakeAnimator;
  243.   RV_MakeAnimator := RV_MakeAnimatorGif;
  244. {$ENDIF}
  245. end.