GR32_ExtImage.pas 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  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. {$include 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 ClearBuffer: Boolean read FClearBuffer write FClearBuffer;
  81. property RenderMode: TRenderMode read FRenderMode write SetRenderMode;
  82. property Color;
  83. end;
  84. { TRenderThread }
  85. TRenderThread = class(TThread)
  86. private
  87. FDest: TBitmap32;
  88. FRasterizer: TRasterizer;
  89. FOldAreaChanged: TAreaChangedEvent;
  90. FArea: TRect;
  91. FDstRect: TRect;
  92. procedure SynchronizedAreaChanged;
  93. procedure AreaChanged(Sender: TObject; const Area: TRect; const Hint: Cardinal);
  94. protected
  95. procedure Execute; override;
  96. procedure Rasterize;
  97. public
  98. constructor Create(Rasterizer: TRasterizer; Dst: TBitmap32; DstRect: TRect;
  99. Suspended: Boolean);
  100. end;
  101. procedure Rasterize(Rasterizer: TRasterizer; Dst: TBitmap32; DstRect: TRect);
  102. implementation
  103. uses
  104. Forms, SysUtils, Graphics;
  105. procedure Rasterize(Rasterizer: TRasterizer; Dst: TBitmap32; DstRect: TRect);
  106. var
  107. R: TRenderThread;
  108. begin
  109. R := TRenderThread.Create(Rasterizer, Dst, DstRect, True);
  110. R.FreeOnTerminate := True;
  111. {$IFDEF USETHREADRESUME}
  112. R.Resume;
  113. {$ELSE}
  114. R.Start;
  115. {$ENDIF}
  116. end;
  117. { TSyntheticImage32 }
  118. constructor TSyntheticImage32.Create(AOwner: TComponent);
  119. begin
  120. inherited;
  121. FRasterizer := TRegularRasterizer.Create;
  122. FRasterizer.Sampler := Buffer.Resampler;
  123. FAutoRasterize := True;
  124. FResized := False;
  125. RepaintMode := rmDirect;
  126. RenderMode := rnmFull;
  127. BufferOversize := 0;
  128. end;
  129. destructor TSyntheticImage32.Destroy;
  130. var
  131. ParentForm: TCustomForm;
  132. begin
  133. StopRenderThread;
  134. if Assigned(FRenderThread) then FRenderThread.Free;
  135. if Assigned(FDefaultProc) then
  136. begin
  137. ParentForm := GetParentForm(Self);
  138. if ParentForm <> nil then
  139. ParentForm.WindowProc := FDefaultProc;
  140. end;
  141. FRasterizer.Free;
  142. inherited;
  143. end;
  144. procedure TSyntheticImage32.DoRasterize;
  145. begin
  146. if FAutoRasterize then Rasterize;
  147. end;
  148. {$IFDEF FPC}
  149. procedure TSyntheticImage32.FormWindowProc(var Message: TLMessage);
  150. var
  151. CmdType: Integer;
  152. begin
  153. FDefaultProc(Message);
  154. case Message.Msg of
  155. 534: FResized := False;
  156. 562:
  157. begin
  158. if FResized then DoRasterize;
  159. FResized := True;
  160. end;
  161. 274:
  162. begin
  163. CmdType := Message.WParam and $FFF0;
  164. if (CmdType = SC_MAXIMIZE) or (CmdType = SC_RESTORE) then
  165. DoRasterize;
  166. end;
  167. end;
  168. end;
  169. {$ELSE}
  170. procedure TSyntheticImage32.FormWindowProc(var Message: TMessage);
  171. var
  172. CmdType: Integer;
  173. begin
  174. FDefaultProc(Message);
  175. case Message.Msg of
  176. WM_MOVING: FResized := False;
  177. WM_EXITSIZEMOVE:
  178. begin
  179. if FResized then DoRasterize;
  180. FResized := True;
  181. end;
  182. WM_SYSCOMMAND:
  183. begin
  184. CmdType := Message.WParam and $FFF0;
  185. if (CmdType = SC_MAXIMIZE) or (CmdType = SC_RESTORE) then
  186. DoRasterize;
  187. end;
  188. end;
  189. end;
  190. {$ENDIF}
  191. procedure TSyntheticImage32.Rasterize;
  192. var
  193. BackgroundColor: TColor;
  194. R: TRect;
  195. begin
  196. { Clear buffer before rasterization }
  197. if FClearBuffer then
  198. begin
  199. BackgroundColor := Color;
  200. {$ifdef FPC}
  201. if (BackgroundColor = clDefault) then
  202. BackgroundColor := GetDefaultColor(dctBrush);
  203. {$endif}
  204. Buffer.Clear(Color32(BackgroundColor));
  205. Invalidate;
  206. end;
  207. { Create rendering thread }
  208. StopRenderThread;
  209. FOldAreaChanged := Buffer.OnAreaChanged;
  210. if FRenderMode = rnmFull then
  211. R := Rect(0, 0, Buffer.Width, Buffer.Height)
  212. else
  213. R := FDstRect;
  214. FRenderThread := TRenderThread.Create(FRasterizer, Buffer, R, False);
  215. FResized := True;
  216. end;
  217. procedure TSyntheticImage32.RasterizerChanged(Sender: TObject);
  218. begin
  219. DoRasterize;
  220. end;
  221. procedure TSyntheticImage32.Resize;
  222. begin
  223. if not FResized then StopRenderThread;
  224. inherited;
  225. end;
  226. procedure TSyntheticImage32.SetDstRect(const Value: TRect);
  227. begin
  228. FDstRect := Value;
  229. end;
  230. procedure TSyntheticImage32.SetParent(AParent: TWinControl);
  231. var
  232. ParentForm: TCustomForm;
  233. begin
  234. ParentForm := GetParentForm(Self);
  235. if ParentForm = AParent then Exit;
  236. if ParentForm <> nil then
  237. if Assigned(FDefaultProc) then
  238. ParentForm.WindowProc := FDefaultProc;
  239. inherited;
  240. if AParent <> nil then
  241. begin
  242. ParentForm := GetParentForm(Self);
  243. if ParentForm <> nil then
  244. begin
  245. FDefaultProc := ParentForm.WindowProc;
  246. ParentForm.WindowProc := FormWindowProc;
  247. end;
  248. end;
  249. end;
  250. procedure TSyntheticImage32.SetRasterizer(const Value: TRasterizer);
  251. begin
  252. if Value <> FRasterizer then
  253. begin
  254. StopRenderThread;
  255. if Assigned(FRasterizer) then FRasterizer.Free;
  256. FRasterizer := Value;
  257. FRasterizer.OnChange := RasterizerChanged;
  258. DoRasterize;
  259. Changed;
  260. end;
  261. end;
  262. procedure TSyntheticImage32.SetRenderMode(const Value: TRenderMode);
  263. begin
  264. FRenderMode := Value;
  265. end;
  266. procedure TSyntheticImage32.StopRenderThread;
  267. begin
  268. if Assigned(FRenderThread) and (not FRenderThread.Terminated) then
  269. begin
  270. FRenderThread.Synchronize(FRenderThread.Terminate);
  271. FRenderThread.WaitFor;
  272. FreeAndNil(FRenderThread);
  273. end;
  274. end;
  275. { TRenderThread }
  276. constructor TRenderThread.Create(Rasterizer: TRasterizer; Dst: TBitmap32;
  277. DstRect: TRect; Suspended: Boolean);
  278. begin
  279. {$IFDEF USETHREADRESUME}
  280. inherited Create(True);
  281. {$ELSE}
  282. inherited Create(Suspended);
  283. {$ENDIF}
  284. FRasterizer := Rasterizer;
  285. FDest := Dst;
  286. FDstRect := DstRect;
  287. {$IFDEF USETHREADRESUME}
  288. if not Suspended then Resume;
  289. {$ENDIF}
  290. end;
  291. procedure TRenderThread.Execute;
  292. begin
  293. Rasterize;
  294. end;
  295. procedure TRenderThread.Rasterize;
  296. begin
  297. FRasterizer.Lock;
  298. { Save current AreaChanged handler }
  299. FOldAreaChanged := FDest.OnAreaChanged;
  300. FDest.OnAreaChanged := AreaChanged;
  301. try
  302. FRasterizer.Rasterize(FDest, FDstRect);
  303. except
  304. on EAbort do;
  305. end;
  306. { Reset old AreaChanged handler }
  307. FDest.OnAreaChanged := FOldAreaChanged;
  308. Synchronize(FRasterizer.Unlock);
  309. end;
  310. procedure TRenderThread.AreaChanged(Sender: TObject; const Area: TRect;
  311. const Hint: Cardinal);
  312. begin
  313. if Terminated then Abort else
  314. begin
  315. FArea := Area;
  316. Synchronize(SynchronizedAreaChanged);
  317. end;
  318. end;
  319. procedure TRenderThread.SynchronizedAreaChanged;
  320. begin
  321. if Assigned(FOldAreaChanged) then
  322. FOldAreaChanged(FDest, FArea, AREAINFO_RECT);
  323. end;
  324. end.