GR32_ExtImage.pas 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. unit GR32_ExtImage;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Extended Image components for Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Mattias Andersson <[email protected]>
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2005-2009
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * Contributor(s):
  31. *
  32. * ***** END LICENSE BLOCK ***** *)
  33. interface
  34. {$I GR32.inc}
  35. uses
  36. {$IFDEF FPC}
  37. LCLIntf, LCLType, LMessages,
  38. {$ELSE}
  39. Windows, Messages,
  40. {$ENDIF}
  41. GR32, GR32_Image, GR32_Rasterizers, Classes, Controls;
  42. type
  43. TRenderThread = class;
  44. TRenderMode = (rnmFull, rnmConstrained);
  45. { TSyntheticImage32 }
  46. TSyntheticImage32 = class(TPaintBox32)
  47. private
  48. FRasterizer: TRasterizer;
  49. FAutoRasterize: Boolean;
  50. FDefaultProc: TWndMethod;
  51. FResized: Boolean;
  52. FRenderThread: TRenderThread;
  53. FOldAreaChanged: TAreaChangedEvent;
  54. FDstRect: TRect;
  55. FRenderMode: TRenderMode;
  56. FClearBuffer: Boolean;
  57. procedure SetRasterizer(const Value: TRasterizer);
  58. procedure StopRenderThread;
  59. procedure SetDstRect(const Value: TRect);
  60. procedure SetRenderMode(const Value: TRenderMode);
  61. protected
  62. procedure RasterizerChanged(Sender: TObject);
  63. procedure SetParent(AParent: TWinControl); override;
  64. {$IFDEF FPC}
  65. procedure FormWindowProc(var Message: TLMessage);
  66. {$ELSE}
  67. procedure FormWindowProc(var Message: TMessage);
  68. {$ENDIF}
  69. procedure DoRasterize;
  70. property RepaintMode;
  71. public
  72. constructor Create(AOwner: TComponent); override;
  73. destructor Destroy; override;
  74. procedure Resize; override;
  75. procedure Rasterize;
  76. property DstRect: TRect read FDstRect write SetDstRect;
  77. published
  78. property AutoRasterize: Boolean read FAutoRasterize write FAutoRasterize;
  79. property Rasterizer: TRasterizer read FRasterizer write SetRasterizer;
  80. property Buffer;
  81. property Color;
  82. property ClearBuffer: Boolean read FClearBuffer write FClearBuffer;
  83. property RenderMode: TRenderMode read FRenderMode write SetRenderMode;
  84. end;
  85. { TRenderThread }
  86. TRenderThread = class(TThread)
  87. private
  88. FDest: TBitmap32;
  89. FRasterizer: TRasterizer;
  90. FOldAreaChanged: TAreaChangedEvent;
  91. FArea: TRect;
  92. FDstRect: TRect;
  93. procedure SynchronizedAreaChanged;
  94. procedure AreaChanged(Sender: TObject; const Area: TRect; const Hint: Cardinal);
  95. protected
  96. procedure Execute; override;
  97. procedure Rasterize;
  98. public
  99. constructor Create(Rasterizer: TRasterizer; Dst: TBitmap32; DstRect: TRect;
  100. Suspended: Boolean);
  101. end;
  102. procedure Rasterize(Rasterizer: TRasterizer; Dst: TBitmap32; DstRect: TRect);
  103. implementation
  104. uses
  105. Forms, SysUtils;
  106. procedure Rasterize(Rasterizer: TRasterizer; Dst: TBitmap32; DstRect: TRect);
  107. var
  108. R: TRenderThread;
  109. begin
  110. R := TRenderThread.Create(Rasterizer, Dst, DstRect, True);
  111. R.FreeOnTerminate := True;
  112. {$IFDEF USETHREADRESUME}
  113. R.Resume;
  114. {$ELSE}
  115. R.Start;
  116. {$ENDIF}
  117. end;
  118. { TSyntheticImage32 }
  119. constructor TSyntheticImage32.Create(AOwner: TComponent);
  120. begin
  121. inherited;
  122. FRasterizer := TRegularRasterizer.Create;
  123. FRasterizer.Sampler := Buffer.Resampler;
  124. FAutoRasterize := True;
  125. FResized := False;
  126. RepaintMode := rmDirect;
  127. RenderMode := rnmFull;
  128. BufferOversize := 0;
  129. end;
  130. destructor TSyntheticImage32.Destroy;
  131. var
  132. ParentForm: TCustomForm;
  133. begin
  134. StopRenderThread;
  135. if Assigned(FRenderThread) then FRenderThread.Free;
  136. if Assigned(FDefaultProc) then
  137. begin
  138. ParentForm := GetParentForm(Self);
  139. if ParentForm <> nil then
  140. ParentForm.WindowProc := FDefaultProc;
  141. end;
  142. FRasterizer.Free;
  143. inherited;
  144. end;
  145. procedure TSyntheticImage32.DoRasterize;
  146. begin
  147. if FAutoRasterize then Rasterize;
  148. end;
  149. {$IFDEF FPC}
  150. procedure TSyntheticImage32.FormWindowProc(var Message: TLMessage);
  151. var
  152. CmdType: Integer;
  153. begin
  154. FDefaultProc(Message);
  155. case Message.Msg of
  156. 534: FResized := False;
  157. 562:
  158. begin
  159. if FResized then DoRasterize;
  160. FResized := True;
  161. end;
  162. 274:
  163. begin
  164. CmdType := Message.WParam and $FFF0;
  165. if (CmdType = SC_MAXIMIZE) or (CmdType = SC_RESTORE) then
  166. DoRasterize;
  167. end;
  168. end;
  169. end;
  170. {$ELSE}
  171. procedure TSyntheticImage32.FormWindowProc(var Message: TMessage);
  172. var
  173. CmdType: Integer;
  174. begin
  175. FDefaultProc(Message);
  176. case Message.Msg of
  177. WM_MOVING: FResized := False;
  178. WM_EXITSIZEMOVE:
  179. begin
  180. if FResized then DoRasterize;
  181. FResized := True;
  182. end;
  183. WM_SYSCOMMAND:
  184. begin
  185. CmdType := Message.WParam and $FFF0;
  186. if (CmdType = SC_MAXIMIZE) or (CmdType = SC_RESTORE) then
  187. DoRasterize;
  188. end;
  189. end;
  190. end;
  191. {$ENDIF}
  192. procedure TSyntheticImage32.Rasterize;
  193. var
  194. R: TRect;
  195. begin
  196. { Clear buffer before rasterization }
  197. if FClearBuffer then
  198. begin
  199. Buffer.Clear(Color32(Color));
  200. Invalidate;
  201. end;
  202. { Create rendering thread }
  203. StopRenderThread;
  204. FOldAreaChanged := Buffer.OnAreaChanged;
  205. if FRenderMode = rnmFull then
  206. R := Rect(0, 0, Buffer.Width, Buffer.Height)
  207. else
  208. R := FDstRect;
  209. FRenderThread := TRenderThread.Create(FRasterizer, Buffer, R, False);
  210. FResized := True;
  211. end;
  212. procedure TSyntheticImage32.RasterizerChanged(Sender: TObject);
  213. begin
  214. DoRasterize;
  215. end;
  216. procedure TSyntheticImage32.Resize;
  217. begin
  218. if not FResized then StopRenderThread;
  219. inherited;
  220. end;
  221. procedure TSyntheticImage32.SetDstRect(const Value: TRect);
  222. begin
  223. FDstRect := Value;
  224. end;
  225. procedure TSyntheticImage32.SetParent(AParent: TWinControl);
  226. var
  227. ParentForm: TCustomForm;
  228. begin
  229. ParentForm := GetParentForm(Self);
  230. if ParentForm = AParent then Exit;
  231. if ParentForm <> nil then
  232. if Assigned(FDefaultProc) then
  233. ParentForm.WindowProc := FDefaultProc;
  234. inherited;
  235. if AParent <> nil then
  236. begin
  237. ParentForm := GetParentForm(Self);
  238. if ParentForm <> nil then
  239. begin
  240. FDefaultProc := ParentForm.WindowProc;
  241. ParentForm.WindowProc := FormWindowProc;
  242. end;
  243. end;
  244. end;
  245. procedure TSyntheticImage32.SetRasterizer(const Value: TRasterizer);
  246. begin
  247. if Value <> FRasterizer then
  248. begin
  249. StopRenderThread;
  250. if Assigned(FRasterizer) then FRasterizer.Free;
  251. FRasterizer := Value;
  252. FRasterizer.OnChange := RasterizerChanged;
  253. DoRasterize;
  254. Changed;
  255. end;
  256. end;
  257. procedure TSyntheticImage32.SetRenderMode(const Value: TRenderMode);
  258. begin
  259. FRenderMode := Value;
  260. end;
  261. procedure TSyntheticImage32.StopRenderThread;
  262. begin
  263. if Assigned(FRenderThread) and (not FRenderThread.Terminated) then
  264. begin
  265. FRenderThread.Synchronize(FRenderThread.Terminate);
  266. FRenderThread.WaitFor;
  267. FreeAndNil(FRenderThread);
  268. end;
  269. end;
  270. { TRenderThread }
  271. constructor TRenderThread.Create(Rasterizer: TRasterizer; Dst: TBitmap32;
  272. DstRect: TRect; Suspended: Boolean);
  273. begin
  274. {$IFDEF USETHREADRESUME}
  275. inherited Create(True);
  276. {$ELSE}
  277. inherited Create(Suspended);
  278. {$ENDIF}
  279. FRasterizer := Rasterizer;
  280. FDest := Dst;
  281. FDstRect := DstRect;
  282. {$IFDEF USETHREADRESUME}
  283. if not Suspended then Resume;
  284. {$ENDIF}
  285. end;
  286. procedure TRenderThread.Execute;
  287. begin
  288. Rasterize;
  289. end;
  290. procedure TRenderThread.Rasterize;
  291. begin
  292. FRasterizer.Lock;
  293. { Save current AreaChanged handler }
  294. FOldAreaChanged := FDest.OnAreaChanged;
  295. FDest.OnAreaChanged := AreaChanged;
  296. try
  297. FRasterizer.Rasterize(FDest, FDstRect);
  298. except
  299. on EAbort do;
  300. end;
  301. { Reset old AreaChanged handler }
  302. FDest.OnAreaChanged := FOldAreaChanged;
  303. Synchronize(FRasterizer.Unlock);
  304. end;
  305. procedure TRenderThread.AreaChanged(Sender: TObject; const Area: TRect;
  306. const Hint: Cardinal);
  307. begin
  308. if Terminated then Abort else
  309. begin
  310. FArea := Area;
  311. Synchronize(SynchronizedAreaChanged);
  312. end;
  313. end;
  314. procedure TRenderThread.SynchronizedAreaChanged;
  315. begin
  316. if Assigned(FOldAreaChanged) then
  317. FOldAreaChanged(FDest, FArea, AREAINFO_RECT);
  318. end;
  319. end.