source: trunk/Packages/Graphics32/GR32_ExtImage.pas

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