source: trunk/Packages/Graphics32/GR32_Backends_VCL.pas

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 22.7 KB
Line 
1unit GR32_Backends_VCL;
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 Backend Extension for Graphics32
24 *
25 * The Initial Developer of the Original Code is
26 * Andre Beckedorf - metaException
27 * Andre@metaException.de
28 *
29 * Portions created by the Initial Developer are Copyright (C) 2007-2009
30 * the Initial Developer. All Rights Reserved.
31 *
32 * Contributor(s):
33 *
34 * ***** END LICENSE BLOCK ***** *)
35
36interface
37
38{$I GR32.inc}
39
40uses
41 SysUtils, Classes, Windows, Graphics, GR32, GR32_Backends, GR32_Containers,
42 GR32_Image, GR32_Backends_Generic, GR32_Paths;
43
44type
45 { TGDIBackend }
46 { This backend is the default backend on Windows.
47 It uses the GDI to manage and provide the buffer and additional
48 graphics sub system features. The backing buffer is kept in memory. }
49
50 TGDIBackend = class(TCustomBackend, IPaintSupport,
51 IBitmapContextSupport, IDeviceContextSupport,
52 ITextSupport, IFontSupport, ICanvasSupport, ITextToPathSupport)
53 private
54 procedure FontChangedHandler(Sender: TObject);
55 procedure CanvasChangedHandler(Sender: TObject);
56 procedure CanvasChanged;
57 procedure FontChanged;
58 protected
59 FBitmapInfo: TBitmapInfo;
60 FBitmapHandle: HBITMAP;
61 FHDC: HDC;
62 FFont: TFont;
63 FCanvas: TCanvas;
64 FFontHandle: HFont;
65 FMapHandle: THandle;
66
67 FOnFontChange: TNotifyEvent;
68 FOnCanvasChange: TNotifyEvent;
69
70 procedure InitializeSurface(NewWidth, NewHeight: Integer; ClearBuffer: Boolean); override;
71 procedure FinalizeSurface; override;
72
73 procedure PrepareFileMapping(NewWidth, NewHeight: Integer); virtual;
74 public
75 constructor Create; override;
76 destructor Destroy; override;
77
78 procedure Changed; override;
79
80 function Empty: Boolean; override;
81 public
82 { IPaintSupport }
83 procedure ImageNeeded;
84 procedure CheckPixmap;
85 procedure DoPaint(ABuffer: TBitmap32; AInvalidRects: TRectList; ACanvas: TCanvas; APaintBox: TCustomPaintBox32);
86
87 { IBitmapContextSupport }
88 function GetBitmapInfo: TBitmapInfo;
89 function GetBitmapHandle: THandle;
90
91 property BitmapInfo: TBitmapInfo read GetBitmapInfo;
92 property BitmapHandle: THandle read GetBitmapHandle;
93
94 { IDeviceContextSupport }
95 function GetHandle: HDC;
96
97 procedure Draw(const DstRect, SrcRect: TRect; hSrc: HDC); overload;
98 procedure DrawTo(hDst: HDC; DstX, DstY: Integer); overload;
99 procedure DrawTo(hDst: HDC; const DstRect, SrcRect: TRect); overload;
100
101 property Handle: HDC read GetHandle;
102
103 { ITextSupport }
104 procedure Textout(X, Y: Integer; const Text: string); overload;
105 procedure Textout(X, Y: Integer; const ClipRect: TRect; const Text: string); overload;
106 procedure Textout(var DstRect: TRect; const Flags: Cardinal; const Text: string); overload;
107 function TextExtent(const Text: string): TSize;
108
109 procedure TextoutW(X, Y: Integer; const Text: Widestring); overload;
110 procedure TextoutW(X, Y: Integer; const ClipRect: TRect; const Text: Widestring); overload;
111 procedure TextoutW(var DstRect: TRect; const Flags: Cardinal; const Text: Widestring); overload;
112 function TextExtentW(const Text: Widestring): TSize;
113
114 { IFontSupport }
115 function GetOnFontChange: TNotifyEvent;
116 procedure SetOnFontChange(Handler: TNotifyEvent);
117 function GetFont: TFont;
118 procedure SetFont(const Font: TFont);
119
120 procedure UpdateFont;
121 property Font: TFont read GetFont write SetFont;
122 property OnFontChange: TNotifyEvent read FOnFontChange write FOnFontChange;
123
124 { ITextToPathSupport }
125 procedure TextToPath(Path: TCustomPath; const X, Y: TFloat; const Text: WideString); overload;
126 procedure TextToPath(Path: TCustomPath; const DstRect: TFloatRect; const Text: WideString; Flags: Cardinal); overload;
127 function MeasureText(const DstRect: TFloatRect; const Text: WideString; Flags: Cardinal): TFloatRect;
128
129 { ICanvasSupport }
130 function GetCanvasChange: TNotifyEvent;
131 procedure SetCanvasChange(Handler: TNotifyEvent);
132 function GetCanvas: TCanvas;
133
134 procedure DeleteCanvas;
135 function CanvasAllocated: Boolean;
136
137 property Canvas: TCanvas read GetCanvas;
138 property OnCanvasChange: TNotifyEvent read GetCanvasChange write SetCanvasChange;
139 end;
140
141 { TGDIMMFBackend }
142 { Same as TGDIBackend but relies on memory mapped files or mapped swap space
143 for the backing buffer. }
144
145 TGDIMMFBackend = class(TGDIBackend)
146 private
147 FMapFileHandle: THandle;
148 FMapIsTemporary: Boolean;
149 FMapFileName: string;
150 protected
151 procedure PrepareFileMapping(NewWidth, NewHeight: Integer); override;
152 public
153 constructor Create(Owner: TBitmap32; IsTemporary: Boolean = True; const MapFileName: string = ''); virtual;
154 destructor Destroy; override;
155 end;
156
157 { TGDIMemoryBackend }
158 { A backend that keeps the backing buffer entirely in memory and offers
159 IPaintSupport without allocating a GDI handle }
160
161 TGDIMemoryBackend = class(TMemoryBackend, IPaintSupport, IDeviceContextSupport)
162 private
163 procedure DoPaintRect(ABuffer: TBitmap32; ARect: TRect; ACanvas: TCanvas);
164
165 function GetHandle: HDC; // Dummy
166 protected
167 FBitmapInfo: TBitmapInfo;
168
169 procedure InitializeSurface(NewWidth: Integer; NewHeight: Integer;
170 ClearBuffer: Boolean); override;
171 public
172 constructor Create; override;
173
174 { IPaintSupport }
175 procedure ImageNeeded;
176 procedure CheckPixmap;
177 procedure DoPaint(ABuffer: TBitmap32; AInvalidRects: TRectList; ACanvas: TCanvas; APaintBox: TCustomPaintBox32);
178
179 { IDeviceContextSupport }
180 procedure Draw(const DstRect, SrcRect: TRect; hSrc: HDC); overload;
181 procedure DrawTo(hDst: HDC; DstX, DstY: Integer); overload;
182 procedure DrawTo(hDst: HDC; const DstRect, SrcRect: TRect); overload;
183 end;
184
185implementation
186
187uses
188 GR32_Text_VCL;
189
190var
191 StockFont: HFONT;
192
193{ TGDIBackend }
194
195constructor TGDIBackend.Create;
196begin
197 inherited;
198
199 FillChar(FBitmapInfo, SizeOf(TBitmapInfo), 0);
200 with FBitmapInfo.bmiHeader do
201 begin
202 biSize := SizeOf(TBitmapInfoHeader);
203 biPlanes := 1;
204 biBitCount := 32;
205 biCompression := BI_RGB;
206 end;
207
208 FMapHandle := 0;
209
210 FFont := TFont.Create;
211 FFont.OnChange := FontChangedHandler;
212 FFont.OwnerCriticalSection := @FLock;
213end;
214
215destructor TGDIBackend.Destroy;
216begin
217 DeleteCanvas;
218 FFont.Free;
219
220 inherited;
221end;
222
223procedure TGDIBackend.InitializeSurface(NewWidth, NewHeight: Integer; ClearBuffer: Boolean);
224begin
225 with FBitmapInfo.bmiHeader do
226 begin
227 biWidth := NewWidth;
228 biHeight := -NewHeight;
229 biSizeImage := NewWidth * NewHeight * 4;
230 end;
231
232 PrepareFileMapping(NewWidth, NewHeight);
233
234 FBitmapHandle := CreateDIBSection(0, FBitmapInfo, DIB_RGB_COLORS, Pointer(FBits), FMapHandle, 0);
235
236 if FBits = nil then
237 raise EBackend.Create(RCStrCannotAllocateDIBHandle);
238
239 FHDC := CreateCompatibleDC(0);
240 if FHDC = 0 then
241 begin
242 DeleteObject(FBitmapHandle);
243 FBitmapHandle := 0;
244 FBits := nil;
245 raise EBackend.Create(RCStrCannotCreateCompatibleDC);
246 end;
247
248 if SelectObject(FHDC, FBitmapHandle) = 0 then
249 begin
250 DeleteDC(FHDC);
251 DeleteObject(FBitmapHandle);
252 FHDC := 0;
253 FBitmapHandle := 0;
254 FBits := nil;
255 raise EBackend.Create(RCStrCannotSelectAnObjectIntoDC);
256 end;
257end;
258
259function TGDIBackend.MeasureText(const DstRect: TFloatRect;
260 const Text: WideString; Flags: Cardinal): TFloatRect;
261begin
262 Result := GR32_Text_VCL.MeasureText(Font.Handle, DstRect, Text, Flags);
263end;
264
265procedure TGDIBackend.FinalizeSurface;
266begin
267 if FHDC <> 0 then DeleteDC(FHDC);
268 FHDC := 0;
269 if FBitmapHandle <> 0 then DeleteObject(FBitmapHandle);
270 FBitmapHandle := 0;
271
272 FBits := nil;
273end;
274
275procedure TGDIBackend.DeleteCanvas;
276begin
277 if Assigned(FCanvas) then
278 begin
279 FCanvas.Handle := 0;
280 FCanvas.Free;
281 FCanvas := nil;
282 end;
283end;
284
285procedure TGDIBackend.PrepareFileMapping(NewWidth, NewHeight: Integer);
286begin
287 // to be implemented by descendants
288end;
289
290procedure TGDIBackend.Changed;
291begin
292 if FCanvas <> nil then FCanvas.Handle := Self.Handle;
293 inherited;
294end;
295
296procedure TGDIBackend.CanvasChanged;
297begin
298 if Assigned(FOnCanvasChange) then
299 FOnCanvasChange(Self);
300end;
301
302procedure TGDIBackend.FontChanged;
303begin
304 if Assigned(FOnFontChange) then
305 FOnFontChange(Self);
306end;
307
308function TGDIBackend.TextExtent(const Text: string): TSize;
309var
310 DC: HDC;
311 OldFont: HGDIOBJ;
312begin
313 UpdateFont;
314 Result.cX := 0;
315 Result.cY := 0;
316 if Handle <> 0 then
317 Windows.GetTextExtentPoint32(Handle, PChar(Text), Length(Text), Result)
318 else
319 begin
320 StockBitmap.Canvas.Lock;
321 try
322 DC := StockBitmap.Canvas.Handle;
323 OldFont := SelectObject(DC, Font.Handle);
324 Windows.GetTextExtentPoint32(DC, PChar(Text), Length(Text), Result);
325 SelectObject(DC, OldFont);
326 finally
327 StockBitmap.Canvas.Unlock;
328 end;
329 end;
330end;
331
332function TGDIBackend.TextExtentW(const Text: Widestring): TSize;
333var
334 DC: HDC;
335 OldFont: HGDIOBJ;
336begin
337 UpdateFont;
338 Result.cX := 0;
339 Result.cY := 0;
340
341 if Handle <> 0 then
342 Windows.GetTextExtentPoint32W(Handle, PWideChar(Text), Length(Text), Result)
343 else
344 begin
345 StockBitmap.Canvas.Lock;
346 try
347 DC := StockBitmap.Canvas.Handle;
348 OldFont := SelectObject(DC, Font.Handle);
349 Windows.GetTextExtentPoint32W(DC, PWideChar(Text), Length(Text), Result);
350 SelectObject(DC, OldFont);
351 finally
352 StockBitmap.Canvas.Unlock;
353 end;
354 end;
355end;
356
357procedure TGDIBackend.Textout(X, Y: Integer; const Text: string);
358var
359 Extent: TSize;
360begin
361 UpdateFont;
362
363 if not FOwner.MeasuringMode then
364 begin
365 if FOwner.Clipping then
366 ExtTextout(Handle, X, Y, ETO_CLIPPED, @FOwner.ClipRect, PChar(Text), Length(Text), nil)
367 else
368 ExtTextout(Handle, X, Y, 0, nil, PChar(Text), Length(Text), nil);
369 end;
370
371 Extent := TextExtent(Text);
372 FOwner.Changed(MakeRect(X, Y, X + Extent.cx + 1, Y + Extent.cy + 1));
373end;
374
375procedure TGDIBackend.TextoutW(X, Y: Integer; const Text: Widestring);
376var
377 Extent: TSize;
378begin
379 UpdateFont;
380
381 if not FOwner.MeasuringMode then
382 begin
383 if FOwner.Clipping then
384 ExtTextoutW(Handle, X, Y, ETO_CLIPPED, @FOwner.ClipRect, PWideChar(Text), Length(Text), nil)
385 else
386 ExtTextoutW(Handle, X, Y, 0, nil, PWideChar(Text), Length(Text), nil);
387 end;
388
389 Extent := TextExtentW(Text);
390 FOwner.Changed(MakeRect(X, Y, X + Extent.cx + 1, Y + Extent.cy + 1));
391end;
392
393procedure TGDIBackend.TextoutW(X, Y: Integer; const ClipRect: TRect; const Text: Widestring);
394var
395 Extent: TSize;
396begin
397 UpdateFont;
398
399 if not FOwner.MeasuringMode then
400 ExtTextoutW(Handle, X, Y, ETO_CLIPPED, @ClipRect, PWideChar(Text), Length(Text), nil);
401
402 Extent := TextExtentW(Text);
403 FOwner.Changed(MakeRect(X, Y, X + Extent.cx + 1, Y + Extent.cy + 1));
404end;
405
406procedure TGDIBackend.Textout(X, Y: Integer; const ClipRect: TRect; const Text: string);
407var
408 Extent: TSize;
409begin
410 UpdateFont;
411
412 if not FOwner.MeasuringMode then
413 ExtTextout(Handle, X, Y, ETO_CLIPPED, @ClipRect, PChar(Text), Length(Text), nil);
414
415 Extent := TextExtent(Text);
416 FOwner.Changed(MakeRect(X, Y, X + Extent.cx + 1, Y + Extent.cy + 1));
417end;
418
419procedure TGDIBackend.TextoutW(var DstRect: TRect; const Flags: Cardinal; const Text: Widestring);
420begin
421 UpdateFont;
422
423 if not FOwner.MeasuringMode then
424 DrawTextW(Handle, PWideChar(Text), Length(Text), DstRect, Flags);
425
426 FOwner.Changed(DstRect);
427end;
428
429procedure TGDIBackend.TextToPath(Path: TCustomPath; const X, Y: TFloat;
430 const Text: WideString);
431var
432 R: TFloatRect;
433begin
434 R := FloatRect(X, Y, X, Y);
435 GR32_Text_VCL.TextToPath(Font.Handle, Path, R, Text, 0);
436end;
437
438procedure TGDIBackend.TextToPath(Path: TCustomPath; const DstRect: TFloatRect;
439 const Text: WideString; Flags: Cardinal);
440begin
441 GR32_Text_VCL.TextToPath(Font.Handle, Path, DstRect, Text, Flags);
442end;
443
444procedure TGDIBackend.UpdateFont;
445begin
446 if (FFontHandle = 0) and (Handle <> 0) then
447 begin
448 SelectObject(Handle, Font.Handle);
449 SetTextColor(Handle, ColorToRGB(Font.Color));
450 SetBkMode(Handle, Windows.TRANSPARENT);
451 FFontHandle := Font.Handle;
452 end
453 else
454 begin
455 SelectObject(Handle, FFontHandle);
456 SetTextColor(Handle, ColorToRGB(Font.Color));
457 SetBkMode(Handle, Windows.TRANSPARENT);
458 end;
459end;
460
461procedure TGDIBackend.Textout(var DstRect: TRect; const Flags: Cardinal; const Text: string);
462begin
463 UpdateFont;
464
465 if not FOwner.MeasuringMode then
466 DrawText(Handle, PChar(Text), Length(Text), DstRect, Flags);
467
468 FOwner.Changed(DstRect);
469end;
470
471procedure TGDIBackend.DrawTo(hDst: HDC; DstX, DstY: Integer);
472begin
473 StretchDIBits(
474 hDst, DstX, DstY, FOwner.Width, FOwner.Height,
475 0, 0, FOwner.Width, FOwner.Height, Bits, FBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
476end;
477
478procedure TGDIBackend.DrawTo(hDst: HDC; const DstRect, SrcRect: TRect);
479begin
480 StretchBlt(
481 hDst,
482 DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left, DstRect.Bottom - DstRect.Top, Handle,
483 SrcRect.Left, SrcRect.Top, SrcRect.Right - SrcRect.Left, SrcRect.Bottom - SrcRect.Top, SRCCOPY);
484end;
485
486function TGDIBackend.GetBitmapHandle: THandle;
487begin
488 Result := FBitmapHandle;
489end;
490
491function TGDIBackend.GetBitmapInfo: TBitmapInfo;
492begin
493 Result := FBitmapInfo;
494end;
495
496function TGDIBackend.GetCanvas: TCanvas;
497begin
498 if not Assigned(FCanvas) then
499 begin
500 FCanvas := TCanvas.Create;
501 FCanvas.Handle := Handle;
502 FCanvas.OnChange := CanvasChangedHandler;
503 end;
504 Result := FCanvas;
505end;
506
507function TGDIBackend.GetCanvasChange: TNotifyEvent;
508begin
509 Result := FOnCanvasChange;
510end;
511
512function TGDIBackend.GetFont: TFont;
513begin
514 Result := FFont;
515end;
516
517function TGDIBackend.GetHandle: HDC;
518begin
519 Result := FHDC;
520end;
521
522function TGDIBackend.GetOnFontChange: TNotifyEvent;
523begin
524 Result := FOnFontChange;
525end;
526
527procedure TGDIBackend.SetCanvasChange(Handler: TNotifyEvent);
528begin
529 FOnCanvasChange := Handler;
530end;
531
532procedure TGDIBackend.SetFont(const Font: TFont);
533begin
534 FFont.Assign(Font);
535 FontChanged;
536end;
537
538procedure TGDIBackend.SetOnFontChange(Handler: TNotifyEvent);
539begin
540 FOnFontChange := Handler;
541end;
542
543procedure TGDIBackend.Draw(const DstRect, SrcRect: TRect; hSrc: HDC);
544begin
545 if FOwner.Empty then Exit;
546
547 if not FOwner.MeasuringMode then
548 StretchBlt(Handle, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left,
549 DstRect.Bottom - DstRect.Top, hSrc, SrcRect.Left, SrcRect.Top,
550 SrcRect.Right - SrcRect.Left, SrcRect.Bottom - SrcRect.Top, SRCCOPY);
551
552 FOwner.Changed(DstRect);
553end;
554
555function TGDIBackend.CanvasAllocated: Boolean;
556begin
557 Result := Assigned(FCanvas);
558end;
559
560function TGDIBackend.Empty: Boolean;
561begin
562 Result := FBitmapHandle = 0;
563end;
564
565procedure TGDIBackend.FontChangedHandler(Sender: TObject);
566begin
567 if FFontHandle <> 0 then
568 begin
569 if Handle <> 0 then SelectObject(Handle, StockFont);
570 FFontHandle := 0;
571 end;
572
573 FontChanged;
574end;
575
576procedure TGDIBackend.CanvasChangedHandler(Sender: TObject);
577begin
578 CanvasChanged;
579end;
580
581{ IPaintSupport }
582
583procedure TGDIBackend.ImageNeeded;
584begin
585
586end;
587
588procedure TGDIBackend.CheckPixmap;
589begin
590
591end;
592
593procedure TGDIBackend.DoPaint(ABuffer: TBitmap32; AInvalidRects: TRectList;
594 ACanvas: TCanvas; APaintBox: TCustomPaintBox32);
595var
596 i: Integer;
597begin
598 if AInvalidRects.Count > 0 then
599 for i := 0 to AInvalidRects.Count - 1 do
600 with AInvalidRects[i]^ do
601 BitBlt(ACanvas.Handle, Left, Top, Right - Left, Bottom - Top, ABuffer.Handle, Left, Top, SRCCOPY)
602 else
603 with APaintBox.GetViewportRect do
604 BitBlt(ACanvas.Handle, Left, Top, Right - Left, Bottom - Top, ABuffer.Handle, Left, Top, SRCCOPY);
605end;
606
607
608{ TGDIMMFBackend }
609
610constructor TGDIMMFBackend.Create(Owner: TBitmap32; IsTemporary: Boolean = True; const MapFileName: string = '');
611begin
612 FMapFileName := MapFileName;
613 FMapIsTemporary := IsTemporary;
614 TMMFBackend.InitializeFileMapping(FMapHandle, FMapFileHandle, FMapFileName);
615 inherited Create(Owner);
616end;
617
618destructor TGDIMMFBackend.Destroy;
619begin
620 TMMFBackend.DeinitializeFileMapping(FMapHandle, FMapFileHandle, FMapFileName);
621 inherited;
622end;
623
624procedure TGDIMMFBackend.PrepareFileMapping(NewWidth, NewHeight: Integer);
625begin
626 TMMFBackend.CreateFileMapping(FMapHandle, FMapFileHandle, FMapFileName, FMapIsTemporary, NewWidth, NewHeight);
627end;
628
629
630{ TGDIMemoryBackend }
631
632constructor TGDIMemoryBackend.Create;
633begin
634 inherited;
635 FillChar(FBitmapInfo, SizeOf(TBitmapInfo), 0);
636 with FBitmapInfo.bmiHeader do
637 begin
638 biSize := SizeOf(TBitmapInfoHeader);
639 biPlanes := 1;
640 biBitCount := 32;
641 biCompression := BI_RGB;
642 biXPelsPerMeter := 96;
643 biYPelsPerMeter := 96;
644 biClrUsed := 0;
645 end;
646end;
647
648procedure TGDIMemoryBackend.InitializeSurface(NewWidth, NewHeight: Integer;
649 ClearBuffer: Boolean);
650begin
651 inherited;
652 with FBitmapInfo.bmiHeader do
653 begin
654 biWidth := NewWidth;
655 biHeight := -NewHeight;
656 end;
657end;
658
659procedure TGDIMemoryBackend.ImageNeeded;
660begin
661
662end;
663
664procedure TGDIMemoryBackend.CheckPixmap;
665begin
666
667end;
668
669procedure TGDIMemoryBackend.DoPaintRect(ABuffer: TBitmap32;
670 ARect: TRect; ACanvas: TCanvas);
671var
672 Bitmap : HBITMAP;
673 DeviceContext : HDC;
674 Buffer : Pointer;
675 OldObject : HGDIOBJ;
676begin
677 if SetDIBitsToDevice(ACanvas.Handle, ARect.Left, ARect.Top, ARect.Right -
678 ARect.Left, ARect.Bottom - ARect.Top, ARect.Left, ARect.Top, 0,
679 ARect.Bottom - ARect.Top, ABuffer.Bits, FBitmapInfo, DIB_RGB_COLORS) = 0 then
680 begin
681 // create compatible device context
682 DeviceContext := CreateCompatibleDC(ACanvas.Handle);
683 if DeviceContext <> 0 then
684 try
685 Bitmap := CreateDIBSection(DeviceContext, FBitmapInfo, DIB_RGB_COLORS,
686 Buffer, 0, 0);
687
688 if Bitmap <> 0 then
689 begin
690 OldObject := SelectObject(DeviceContext, Bitmap);
691 try
692 Move(ABuffer.Bits^, Buffer^, FBitmapInfo.bmiHeader.biWidth *
693 FBitmapInfo.bmiHeader.biHeight * SizeOf(Cardinal));
694 BitBlt(ACanvas.Handle, ARect.Left, ARect.Top, ARect.Right -
695 ARect.Left, ARect.Bottom - ARect.Top, DeviceContext, 0, 0, SRCCOPY);
696 finally
697 if OldObject <> 0 then
698 SelectObject(DeviceContext, OldObject);
699 DeleteObject(Bitmap);
700 end;
701 end else
702 raise EBackend.Create(RCStrCannotCreateCompatibleDC);
703 finally
704 DeleteDC(DeviceContext);
705 end;
706 end;
707end;
708
709procedure TGDIMemoryBackend.Draw(const DstRect, SrcRect: TRect; hSrc: HDC);
710begin
711 if FOwner.Empty then Exit;
712
713 if not FOwner.MeasuringMode then
714 raise EBackend.Create('Not supported!');
715
716 FOwner.Changed(DstRect);
717end;
718
719procedure TGDIMemoryBackend.DrawTo(hDst: HDC; DstX, DstY: Integer);
720var
721 Bitmap : HBITMAP;
722 DeviceContext : HDC;
723 Buffer : Pointer;
724 OldObject : HGDIOBJ;
725begin
726 if SetDIBitsToDevice(hDst, DstX, DstY, FOwner.Width, FOwner.Height, 0, 0, 0,
727 FOwner.Height, FBits, FBitmapInfo, DIB_RGB_COLORS) = 0 then
728 begin
729 // create compatible device context
730 DeviceContext := CreateCompatibleDC(hDst);
731 if DeviceContext <> 0 then
732 try
733 Bitmap := CreateDIBSection(DeviceContext, FBitmapInfo, DIB_RGB_COLORS,
734 Buffer, 0, 0);
735
736 if Bitmap <> 0 then
737 begin
738 OldObject := SelectObject(DeviceContext, Bitmap);
739 try
740 Move(FBits^, Buffer^, FBitmapInfo.bmiHeader.biWidth *
741 FBitmapInfo.bmiHeader.biHeight * SizeOf(Cardinal));
742 BitBlt(hDst, DstX, DstY, FOwner.Width, FOwner.Height, DeviceContext,
743 0, 0, SRCCOPY);
744 finally
745 if OldObject <> 0 then
746 SelectObject(DeviceContext, OldObject);
747 DeleteObject(Bitmap);
748 end;
749 end else
750 raise EBackend.Create(RCStrCannotCreateCompatibleDC);
751 finally
752 DeleteDC(DeviceContext);
753 end;
754 end;
755end;
756
757procedure TGDIMemoryBackend.DrawTo(hDst: HDC;
758 const DstRect, SrcRect: TRect);
759var
760 Bitmap : HBITMAP;
761 DeviceContext : HDC;
762 Buffer : Pointer;
763 OldObject : HGDIOBJ;
764begin
765 if SetDIBitsToDevice(hDst, DstRect.Left, DstRect.Top,
766 DstRect.Right - DstRect.Left, DstRect.Bottom - DstRect.Top, SrcRect.Left,
767 SrcRect.Top, 0, SrcRect.Bottom - SrcRect.Top, FBits, FBitmapInfo,
768 DIB_RGB_COLORS) = 0 then
769 begin
770 // create compatible device context
771 DeviceContext := CreateCompatibleDC(hDst);
772 if DeviceContext <> 0 then
773 try
774 Bitmap := CreateDIBSection(DeviceContext, FBitmapInfo, DIB_RGB_COLORS,
775 Buffer, 0, 0);
776
777 if Bitmap <> 0 then
778 begin
779 OldObject := SelectObject(DeviceContext, Bitmap);
780 try
781 Move(FBits^, Buffer^, FBitmapInfo.bmiHeader.biWidth *
782 FBitmapInfo.bmiHeader.biHeight * SizeOf(Cardinal));
783 BitBlt(hDst, DstRect.Left, DstRect.Top, DstRect.Right -
784 DstRect.Left, DstRect.Bottom - DstRect.Top, DeviceContext, 0, 0, SRCCOPY);
785 finally
786 if OldObject <> 0 then
787 SelectObject(DeviceContext, OldObject);
788 DeleteObject(Bitmap);
789 end;
790 end else
791 raise EBackend.Create(RCStrCannotCreateCompatibleDC);
792 finally
793 DeleteDC(DeviceContext);
794 end;
795 end;
796end;
797
798function TGDIMemoryBackend.GetHandle: HDC;
799begin
800 Result := 0;
801end;
802
803procedure TGDIMemoryBackend.DoPaint(ABuffer: TBitmap32;
804 AInvalidRects: TRectList; ACanvas: TCanvas; APaintBox: TCustomPaintBox32);
805var
806 i : Integer;
807begin
808 if AInvalidRects.Count > 0 then
809 for i := 0 to AInvalidRects.Count - 1 do
810 DoPaintRect(ABuffer, AInvalidRects[i]^, ACanvas)
811 else
812 DoPaintRect(ABuffer, APaintBox.GetViewportRect, ACanvas);
813end;
814
815
816initialization
817 StockFont := GetStockObject(SYSTEM_FONT);
818
819finalization
820
821end.
Note: See TracBrowser for help on using the repository browser.