2013-09-01 05:11:20 +00:00
|
|
|
unit SpkGUITools;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2011-06-18 01:46:25 +00:00
|
|
|
{$mode ObjFpc}
|
|
|
|
{$H+}
|
2011-06-17 20:53:01 +00:00
|
|
|
{$DEFINE SPKGUITOOLS}
|
2011-06-18 01:46:25 +00:00
|
|
|
{.$define EnhancedRecordSupport}
|
2011-06-20 20:35:07 +00:00
|
|
|
//the fpcbugworkaround is only necessary when using inline for DrawRoundRect
|
|
|
|
{.$define FpcBugWorkAround}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
|
|
|
interface
|
|
|
|
|
2016-08-05 21:11:23 +00:00
|
|
|
{$MESSAGE HINT 'Every rect in this module are exact rectanges (not like in WINAPI without right and bottom)'}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2011-06-18 01:46:25 +00:00
|
|
|
uses
|
2018-02-10 00:38:06 +00:00
|
|
|
LCLType, LCLVersion, Graphics, SysUtils, Classes, Controls, StdCtrls,
|
|
|
|
SpkGraphTools, SpkMath;
|
2011-06-18 01:46:25 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
TCornerPos = (cpLeftTop, cpRightTop, cpLeftBottom, cpRightBottom);
|
|
|
|
TCornerKind = (cpRound, cpNormal);
|
|
|
|
TBackgroundKind = (bkSolid, bkVerticalGradient, bkHorizontalGradient,
|
|
|
|
bkConcave);
|
|
|
|
|
2018-02-04 17:29:22 +00:00
|
|
|
TSpkButtonState = (bsIdle,
|
|
|
|
bsBtnHottrack, bsBtnPressed, bsDropdownHottrack, bsDropdownPressed);
|
|
|
|
|
2012-06-04 00:49:51 +00:00
|
|
|
TSpkCheckboxStyle = (cbsCheckbox, cbsRadioButton);
|
2018-02-04 17:29:22 +00:00
|
|
|
// TSpkCheckboxState = (cbsIdle, cbsHotTrack, cbsPressed, cbsDisabled);
|
2012-06-04 00:49:51 +00:00
|
|
|
|
2011-06-18 01:46:25 +00:00
|
|
|
TGUITools = class(TObject)
|
|
|
|
protected
|
2017-10-12 17:48:39 +00:00
|
|
|
class procedure FillGradientRectangle(ACanvas: TCanvas; Rect: T2DIntRect;
|
|
|
|
ColorFrom, ColorTo: TColor; GradientKind: TBackgroundKind);
|
2018-02-05 12:05:26 +00:00
|
|
|
class procedure SaveClipRgn(DC: HDC; out OrgRgnExists: boolean; out OrgRgn: HRGN);
|
2017-10-12 17:48:39 +00:00
|
|
|
class procedure RestoreClipRgn(DC: HDC; OrgRgnExists: boolean; var OrgRgn: HRGN);
|
2011-06-18 01:46:25 +00:00
|
|
|
public
|
|
|
|
// *** Lines ***
|
|
|
|
|
|
|
|
// Performance:
|
|
|
|
// w/ClipRect: Bitmap is faster (2x)
|
|
|
|
// wo/ClipRect: Canvas is faster (a little)
|
|
|
|
class procedure DrawHLine(ABitmap : TBitmap;
|
|
|
|
x1, x2 : integer;
|
|
|
|
y : integer;
|
2011-06-20 20:35:07 +00:00
|
|
|
Color : TColor); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawHLine(ABitmap : TBitmap;
|
|
|
|
x1, x2 : integer;
|
|
|
|
y : integer;
|
|
|
|
Color : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawHLine(ACanvas : TCanvas;
|
|
|
|
x1, x2 : integer;
|
|
|
|
y : integer;
|
2011-06-20 20:35:07 +00:00
|
|
|
Color : TColor); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawHLine(ACanvas : TCanvas;
|
|
|
|
x1, x2 : integer;
|
|
|
|
y : integer;
|
|
|
|
Color : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Performance:
|
|
|
|
// w/ClipRect: Bitmap is faster (2x)
|
|
|
|
// wo/ClipRect: Canvas is faster (a little)
|
|
|
|
class procedure DrawVLine(ABitmap : TBitmap;
|
|
|
|
x : integer;
|
|
|
|
y1, y2 : integer;
|
2011-06-20 20:35:07 +00:00
|
|
|
Color : TColor); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawVLine(ABitmap : TBitmap;
|
|
|
|
x : integer;
|
|
|
|
y1, y2 : integer;
|
|
|
|
Color : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawVLine(ACanvas : TCanvas;
|
|
|
|
x : integer;
|
|
|
|
y1, y2 : integer;
|
2011-06-20 20:35:07 +00:00
|
|
|
Color : TColor); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawVLine(ACanvas : TCanvas;
|
|
|
|
x : integer;
|
|
|
|
y1, y2 : integer;
|
|
|
|
Color : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
|
|
|
|
// *** Background and frame tools ***
|
|
|
|
|
|
|
|
// Performance:
|
|
|
|
// w/ClipRect: Bitmap is faster (extremely)
|
|
|
|
// wo/ClipRect: Bitmap is faster (extremely)
|
|
|
|
class procedure DrawAARoundCorner(ABitmap : TBitmap;
|
|
|
|
Point : T2DIntVector;
|
|
|
|
Radius : integer;
|
|
|
|
CornerPos : TCornerPos;
|
2011-06-20 20:35:07 +00:00
|
|
|
Color : TColor); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawAARoundCorner(ABitmap : TBitmap;
|
|
|
|
Point : T2DIntVector;
|
|
|
|
Radius : integer;
|
|
|
|
CornerPos : TCornerPos;
|
|
|
|
Color : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawAARoundCorner(ACanvas : TCanvas;
|
|
|
|
Point : T2DIntVector;
|
|
|
|
Radius : integer;
|
|
|
|
CornerPos : TCornerPos;
|
2011-06-20 20:35:07 +00:00
|
|
|
Color : TColor); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawAARoundCorner(ACanvas : TCanvas;
|
|
|
|
Point : T2DIntVector;
|
|
|
|
Radius : integer;
|
|
|
|
CornerPos : TCornerPos;
|
|
|
|
Color : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2011-06-18 01:46:25 +00:00
|
|
|
// Performance:
|
|
|
|
// w/ClipRect: Bitmap is faster (extremely)
|
|
|
|
// wo/ClipRect: Bitmap is faster (extremely)
|
|
|
|
class procedure DrawAARoundFrame(ABitmap : TBitmap;
|
|
|
|
Rect : T2DIntRect;
|
|
|
|
Radius : integer;
|
2011-06-20 20:35:07 +00:00
|
|
|
Color : TColor); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawAARoundFrame(ABitmap : TBitmap;
|
|
|
|
Rect : T2DIntRect;
|
|
|
|
Radius : integer;
|
|
|
|
Color : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawAARoundFrame(ACanvas : TCanvas;
|
|
|
|
Rect : T2DIntRect;
|
|
|
|
Radius : integer;
|
2011-06-20 20:35:07 +00:00
|
|
|
Color : TColor); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawAARoundFrame(ACanvas : TCanvas;
|
|
|
|
Rect : T2DIntRect;
|
|
|
|
Radius : integer;
|
|
|
|
Color : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
|
|
|
|
class procedure RenderBackground(ABuffer : TBitmap;
|
|
|
|
Rect : T2DIntRect;
|
|
|
|
Color1, Color2 : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
BackgroundKind : TBackgroundKind);
|
2011-06-18 01:46:25 +00:00
|
|
|
|
|
|
|
class procedure CopyRoundCorner(ABuffer : TBitmap;
|
|
|
|
ABitmap : TBitmap;
|
|
|
|
SrcPoint : T2DIntVector;
|
|
|
|
DstPoint : T2DIntVector;
|
|
|
|
Radius : integer;
|
|
|
|
CornerPos : TCornerPos;
|
2011-06-20 20:35:07 +00:00
|
|
|
Convex : boolean = true); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure CopyRoundCorner(ABuffer : TBitmap;
|
|
|
|
ABitmap : TBitmap;
|
|
|
|
SrcPoint : T2DIntVector;
|
|
|
|
DstPoint : T2DIntVector;
|
|
|
|
Radius : integer;
|
|
|
|
CornerPos : TCornerPos;
|
|
|
|
ClipRect : T2DIntRect;
|
2011-06-20 20:35:07 +00:00
|
|
|
Convex : boolean = true); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
|
|
|
|
class procedure CopyCorner(ABuffer : TBitmap;
|
|
|
|
ABitmap: TBitmap;
|
|
|
|
SrcPoint : T2DIntVector;
|
|
|
|
DstPoint: T2DIntVector;
|
|
|
|
Radius: integer); overload; inline;
|
|
|
|
class procedure CopyCorner(ABuffer : TBitmap;
|
|
|
|
ABitmap: TBitmap;
|
|
|
|
SrcPoint : T2DIntVector;
|
|
|
|
DstPoint: T2DIntVector;
|
|
|
|
Radius: integer;
|
|
|
|
ClipRect : T2DIntRect); overload; inline;
|
|
|
|
|
|
|
|
class procedure CopyRectangle(ABuffer : TBitmap;
|
|
|
|
ABitmap: TBitmap;
|
|
|
|
SrcPoint : T2DIntVector;
|
|
|
|
DstPoint: T2DIntVector;
|
|
|
|
Width: integer;
|
2011-06-20 20:35:07 +00:00
|
|
|
Height : integer); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure CopyRectangle(ABuffer : TBitmap;
|
|
|
|
ABitmap : TBitmap;
|
|
|
|
SrcPoint : T2DIntVector;
|
|
|
|
DstPoint : T2DIntVector;
|
|
|
|
Width : integer;
|
|
|
|
Height : integer;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure CopyMaskRectangle(ABuffer : TBitmap;
|
|
|
|
AMask : TBitmap;
|
|
|
|
ABitmap : TBitmap;
|
2011-06-17 20:53:01 +00:00
|
|
|
SrcPoint : T2DIntVector;
|
2011-06-18 01:46:25 +00:00
|
|
|
DstPoint : T2DIntVector;
|
|
|
|
Width : integer;
|
2011-06-20 20:35:07 +00:00
|
|
|
Height : integer); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure CopyMaskRectangle(ABuffer : TBitmap;
|
|
|
|
AMask : TBitmap;
|
2011-06-17 20:53:01 +00:00
|
|
|
ABitmap : TBitmap;
|
|
|
|
SrcPoint : T2DIntVector;
|
|
|
|
DstPoint : T2DIntVector;
|
|
|
|
Width : integer;
|
|
|
|
Height : integer;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2011-06-18 01:46:25 +00:00
|
|
|
// Performance (RenderBackground + CopyRoundRect vs DrawRoundRect):
|
|
|
|
// w/ClipRect : Bitmap faster for smaller radiuses, Canvas faster for larger
|
|
|
|
// wo/ClipRect : Bitmap faster for smaller radiuses, Canvas faster for larger
|
|
|
|
class procedure CopyRoundRect(ABuffer : TBitmap;
|
|
|
|
ABitmap : TBitmap;
|
|
|
|
SrcPoint : T2DIntVector;
|
|
|
|
DstPoint : T2DIntVector;
|
|
|
|
Width, Height : integer;
|
|
|
|
Radius : integer;
|
|
|
|
LeftTopRound : boolean = true;
|
|
|
|
RightTopRound : boolean = true;
|
|
|
|
LeftBottomRound : boolean = true;
|
2011-06-20 20:35:07 +00:00
|
|
|
RightBottomRound : boolean = true); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure CopyRoundRect(ABuffer : TBitmap;
|
|
|
|
ABitmap : TBitmap;
|
|
|
|
SrcPoint : T2DIntVector;
|
|
|
|
DstPoint : T2DIntVector;
|
|
|
|
Width, Height : integer;
|
|
|
|
Radius : integer;
|
|
|
|
ClipRect : T2DIntRect;
|
|
|
|
LeftTopRound : boolean = true;
|
|
|
|
RightTopRound : boolean = true;
|
|
|
|
LeftBottomRound : boolean = true;
|
2011-06-20 20:35:07 +00:00
|
|
|
RightBottomRound : boolean = true); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
class procedure DrawRoundRect(ACanvas : TCanvas;
|
|
|
|
Rect : T2DIntRect;
|
|
|
|
Radius : integer;
|
|
|
|
ColorFrom : TColor;
|
|
|
|
ColorTo : TColor;
|
|
|
|
GradientKind : TBackgroundKind;
|
|
|
|
LeftTopRound : boolean = true;
|
|
|
|
RightTopRound : boolean = true;
|
|
|
|
LeftBottomRound : boolean = true;
|
2011-06-20 20:35:07 +00:00
|
|
|
RightBottomRound : boolean = true); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawRoundRect(ACanvas : TCanvas;
|
|
|
|
Rect : T2DIntRect;
|
|
|
|
Radius : integer;
|
|
|
|
ColorFrom : TColor;
|
|
|
|
ColorTo : TColor;
|
|
|
|
GradientKind : TBackgroundKind;
|
|
|
|
ClipRect : T2DIntRect;
|
|
|
|
LeftTopRound : boolean = true;
|
|
|
|
RightTopRound : boolean = true;
|
|
|
|
LeftBottomRound : boolean = true;
|
2011-06-20 20:35:07 +00:00
|
|
|
RightBottomRound : boolean = true); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
|
|
|
|
class procedure DrawRegion(ACanvas : TCanvas;
|
|
|
|
Region : HRGN;
|
|
|
|
Rect : T2DIntRect;
|
|
|
|
ColorFrom : TColor;
|
|
|
|
ColorTo : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
GradientKind : TBackgroundKind); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawRegion(ACanvas : TCanvas;
|
|
|
|
Region : HRGN;
|
|
|
|
Rect : T2DIntRect;
|
|
|
|
ColorFrom : TColor;
|
|
|
|
ColorTo : TColor;
|
|
|
|
GradientKind : TBackgroundKind;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
|
|
|
|
// Imagelist tools
|
|
|
|
class procedure DrawImage(ABitmap : TBitmap;
|
|
|
|
Imagelist : TImageList;
|
|
|
|
ImageIndex : integer;
|
|
|
|
Point : T2DIntVector); overload; inline;
|
|
|
|
class procedure DrawImage(ABitmap : TBitmap;
|
|
|
|
Imagelist : TImageList;
|
|
|
|
ImageIndex : integer;
|
|
|
|
Point : T2DIntVector;
|
|
|
|
ClipRect : T2DIntRect); overload; inline;
|
|
|
|
class procedure DrawImage(ACanvas : TCanvas;
|
|
|
|
Imagelist : TImageList;
|
|
|
|
ImageIndex : integer;
|
|
|
|
Point : T2DIntVector); overload; inline;
|
|
|
|
class procedure DrawImage(ACanvas : TCanvas;
|
|
|
|
Imagelist : TImageList;
|
|
|
|
ImageIndex : integer;
|
|
|
|
Point : T2DIntVector;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2018-02-10 00:38:06 +00:00
|
|
|
class procedure DrawImage(ACanvas: TCanvas;
|
|
|
|
Imagelist: TImageList;
|
|
|
|
ImageIndex: integer;
|
|
|
|
Point : T2DIntVector;
|
|
|
|
ClipRect: T2DIntRect;
|
|
|
|
AImageWidthAt96PPI, ATargetPPI: Integer;
|
|
|
|
ACanvasFactor: Double); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
|
|
|
|
class procedure DrawDisabledImage(ABitmap : TBitmap;
|
|
|
|
Imagelist : TImageList;
|
|
|
|
ImageIndex : integer;
|
|
|
|
Point : T2DIntVector); overload; inline;
|
|
|
|
class procedure DrawDisabledImage(ABitmap : TBitmap;
|
|
|
|
Imagelist : TImageList;
|
|
|
|
ImageIndex : integer;
|
|
|
|
Point : T2DIntVector;
|
|
|
|
ClipRect : T2DIntRect); overload; inline;
|
|
|
|
class procedure DrawDisabledImage(ACanvas : TCanvas;
|
|
|
|
Imagelist : TImageList;
|
|
|
|
ImageIndex : integer;
|
2011-06-20 20:35:07 +00:00
|
|
|
Point : T2DIntVector); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawDisabledImage(ACanvas : TCanvas;
|
|
|
|
Imagelist : TImageList;
|
|
|
|
ImageIndex : integer;
|
|
|
|
Point : T2DIntVector;
|
|
|
|
ClipRect : T2DIntRect); overload; inline;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2012-06-04 00:49:51 +00:00
|
|
|
// Checkbox
|
|
|
|
class procedure DrawCheckbox(ACanvas: TCanvas;
|
|
|
|
x,y: Integer;
|
|
|
|
AState: TCheckboxState;
|
2018-02-04 17:29:22 +00:00
|
|
|
AButtonState: TSpkButtonState;
|
2012-06-04 00:49:51 +00:00
|
|
|
AStyle: TSpkCheckboxStyle); overload;
|
|
|
|
class procedure DrawCheckbox(ACanvas: TCanvas;
|
|
|
|
x,y: Integer;
|
|
|
|
AState: TCheckboxState;
|
2018-02-04 17:29:22 +00:00
|
|
|
AButtonState: TSpkButtonState;
|
2012-06-04 00:49:51 +00:00
|
|
|
AStyle: TSpkCheckboxStyle;
|
|
|
|
ClipRect: T2DIntRect); overload;
|
|
|
|
|
2011-06-18 01:46:25 +00:00
|
|
|
// Text tools
|
|
|
|
class procedure DrawText(ABitmap : TBitmap;
|
|
|
|
x, y : integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText : string;
|
|
|
|
TextColor: TColor); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawText(ABitmap : TBitmap;
|
|
|
|
x, y : integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText : string;
|
2011-06-18 01:46:25 +00:00
|
|
|
TextColor : TColor;
|
2011-06-21 02:04:04 +00:00
|
|
|
ClipRect: T2DIntRect); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawMarkedText(ACanvas : TCanvas;
|
|
|
|
x, y : integer;
|
2011-06-18 13:46:52 +00:00
|
|
|
const AText, AMarkPhrase : string;
|
2011-06-18 01:46:25 +00:00
|
|
|
TextColor : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
CaseSensitive : boolean = false); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawMarkedText(ACanvas : TCanvas;
|
|
|
|
x, y : integer;
|
2011-06-18 13:46:52 +00:00
|
|
|
const AText, AMarkPhrase : string;
|
2011-06-18 01:46:25 +00:00
|
|
|
TextColor : TColor;
|
|
|
|
ClipRect : T2DIntRect;
|
2011-06-20 20:35:07 +00:00
|
|
|
CaseSensitive : boolean = false); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawText(ACanvas : TCanvas;
|
|
|
|
x, y : integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText : string;
|
2011-06-20 20:35:07 +00:00
|
|
|
TextColor : TColor); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawText(ACanvas : TCanvas;
|
|
|
|
x, y : integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText : string;
|
2011-06-18 01:46:25 +00:00
|
|
|
TextColor : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawFitWText(ABitmap : TBitmap;
|
|
|
|
x1, x2 : integer;
|
|
|
|
y : integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText : string;
|
2011-06-18 01:46:25 +00:00
|
|
|
TextColor : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
Align : TAlignment); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawFitWText(ACanvas : TCanvas;
|
|
|
|
x1, x2 : integer;
|
|
|
|
y : integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText : string;
|
2011-06-18 01:46:25 +00:00
|
|
|
TextColor : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
Align : TAlignment); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
|
|
|
|
class procedure DrawOutlinedText(ABitmap : TBitmap;
|
|
|
|
x, y : integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText : string;
|
2011-06-17 20:53:01 +00:00
|
|
|
TextColor : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
OutlineColor : TColor); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawOutlinedText(ABitmap : TBitmap;
|
|
|
|
x, y : integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText : string;
|
2011-06-17 20:53:01 +00:00
|
|
|
TextColor : TColor;
|
2011-06-18 01:46:25 +00:00
|
|
|
OutlineColor : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawOutlinedText(ACanvas : TCanvas;
|
|
|
|
x, y : integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText : string;
|
2011-06-18 01:46:25 +00:00
|
|
|
TextColor : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
OutlineColor : TColor); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawOutlinedText(ACanvas : TCanvas;
|
|
|
|
x, y : integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText : string;
|
2011-06-18 01:46:25 +00:00
|
|
|
TextColor : TColor;
|
|
|
|
OutlineColor : TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
ClipRect : T2DIntRect); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawFitWOutlinedText(ABitmap: TBitmap;
|
|
|
|
x1, x2 : integer;
|
|
|
|
y: integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText: string;
|
2011-06-18 01:46:25 +00:00
|
|
|
TextColor,
|
|
|
|
OutlineColor: TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
Align: TAlignment); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
class procedure DrawFitWOutlinedText(ACanvas: TCanvas;
|
|
|
|
x1, x2 : integer;
|
|
|
|
y: integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText: string;
|
2011-06-18 01:46:25 +00:00
|
|
|
TextColor,
|
|
|
|
OutlineColor: TColor;
|
2011-06-20 20:35:07 +00:00
|
|
|
Align: TAlignment); overload;
|
2011-06-18 01:46:25 +00:00
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
|
|
|
implementation
|
|
|
|
|
2011-06-18 12:34:17 +00:00
|
|
|
uses
|
2018-02-05 12:05:26 +00:00
|
|
|
Types, LCLIntf, IntfGraphics, Themes;
|
2011-06-18 12:34:17 +00:00
|
|
|
|
2011-06-17 20:53:01 +00:00
|
|
|
{ TSpkGUITools }
|
|
|
|
|
|
|
|
class procedure TGUITools.CopyRoundCorner(ABuffer, ABitmap: TBitmap; SrcPoint,
|
|
|
|
DstPoint: T2DIntVector; Radius: integer; CornerPos: TCornerPos;
|
|
|
|
ClipRect: T2DIntRect; Convex: boolean);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
BufferRect, BitmapRect, TempRect: T2DIntRect;
|
|
|
|
OrgSrcRect, UnClippedDstRect, OrgDstRect: T2DIntRect;
|
|
|
|
SrcRect: T2DIntRect;
|
|
|
|
Offset: T2DIntVector;
|
|
|
|
Center: T2DIntVector;
|
|
|
|
y: Integer;
|
|
|
|
SrcLine: Pointer;
|
|
|
|
DstLine: Pointer;
|
|
|
|
SrcPtr, DstPtr : PByte;
|
|
|
|
x: Integer;
|
|
|
|
Dist : double;
|
|
|
|
SrcImg, DestImg: TLazIntfImage;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.PixelFormat <> pf24Bit) or (ABitmap.PixelFormat <> pf24Bit) then
|
|
|
|
raise Exception.Create('TSpkGUITools.CopyRoundCorner: Only 24-bit bitmaps are accepted!');
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Validation
|
|
|
|
if Radius < 1 then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.Width = 0) or (ABuffer.Height = 0) or
|
|
|
|
(ABitmap.Width = 0) or (ABitmap.Height = 0) then exit;
|
|
|
|
|
|
|
|
//todo minimize use of temps here
|
|
|
|
{$ifdef EnhancedRecordSupport}
|
|
|
|
BufferRect := T2DIntRect.Create(0, 0, ABuffer.width-1, ABuffer.height-1);
|
|
|
|
if not BufferRect.IntersectsWith(
|
|
|
|
T2DIntRect.Create(SrcPoint.x, SrcPoint.y, SrcPoint.x+Radius-1, SrcPoint.y+Radius-1),
|
|
|
|
OrgSrcRect
|
|
|
|
)
|
|
|
|
then
|
|
|
|
exit;
|
|
|
|
{$else}
|
|
|
|
BufferRect.Create(0, 0, ABuffer.Width-1, ABuffer.Height-1);
|
|
|
|
TempRect.Create(SrcPoint.x, SrcPoint.y, SrcPoint.x+Radius-1, SrcPoint.y+Radius-1);
|
|
|
|
if not BufferRect.IntersectsWith(TempRect, OrgSrcRect) then
|
|
|
|
exit;
|
|
|
|
{$endif}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$ifdef EnhancedRecordSupport}
|
|
|
|
BitmapRect := T2DIntRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
if not BitmapRect.IntersectsWith(
|
|
|
|
T2DIntRect.Create(DstPoint.x, DstPoint.y, DstPoint.x+Radius-1, DstPoint.y+Radius-1),
|
|
|
|
UnClippedDstRect
|
|
|
|
)
|
|
|
|
then
|
|
|
|
exit;
|
|
|
|
{$else}
|
|
|
|
BitmapRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
//todo: calling create twice
|
|
|
|
TempRect.Create(DstPoint.x, DstPoint.y, DstPoint.x+Radius-1, DstPoint.y+Radius-1);
|
|
|
|
if not(BitmapRect.IntersectsWith(TempRect, UnClippedDstRect)) then
|
|
|
|
exit;
|
|
|
|
{$endif}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if not(ClipRect.IntersectsWith(UnClippedDstRect, OrgDstRect)) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
Offset := DstPoint - SrcPoint;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if not(OrgSrcRect.IntersectsWith(OrgDstRect - Offset, SrcRect)) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// We position the center of the arc
|
|
|
|
{$ifdef EnhancedRecordSupport}
|
|
|
|
case CornerPos of
|
|
|
|
cpLeftTop:
|
|
|
|
Center := T2DIntVector.Create(SrcPoint.x + Radius - 1, SrcPoint.y + Radius - 1);
|
|
|
|
cpRightTop:
|
|
|
|
Center := T2DIntVector.Create(SrcPoint.x, SrcPoint.y + Radius - 1);
|
|
|
|
cpLeftBottom:
|
|
|
|
Center := T2DIntVector.Create(SrcPoint.x + Radius - 1, SrcPoint.y);
|
|
|
|
cpRightBottom:
|
|
|
|
Center := T2DIntVector.Create(SrcPoint.x, SrcPoint.y);
|
|
|
|
end;
|
|
|
|
{$else}
|
|
|
|
case CornerPos of
|
|
|
|
cpLeftTop:
|
|
|
|
Center.Create(SrcPoint.x + Radius - 1, SrcPoint.y + Radius - 1);
|
|
|
|
cpRightTop:
|
|
|
|
Center.Create(SrcPoint.x, SrcPoint.y + Radius - 1);
|
|
|
|
cpLeftBottom:
|
|
|
|
Center.Create(SrcPoint.x + Radius - 1, SrcPoint.y);
|
|
|
|
cpRightBottom:
|
|
|
|
Center.Create(SrcPoint.x, SrcPoint.y);
|
|
|
|
end;
|
|
|
|
{$endif}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Is there anything to be processed?
|
|
|
|
if Convex then
|
|
|
|
begin
|
|
|
|
//todo: remove the check since is not necessary
|
|
|
|
if (SrcRect.Left <= SrcRect.right) and (SrcRect.Top <= SrcRect.Bottom) then
|
|
|
|
begin
|
|
|
|
SrcImg := ABuffer.CreateIntfImage;
|
|
|
|
DestImg := ABitmap.CreateIntfImage;
|
|
|
|
for y := SrcRect.Top to SrcRect.Bottom do
|
|
|
|
begin
|
|
|
|
SrcLine := SrcImg.GetDataLineStart(y);
|
|
|
|
DstLine := DestImg.GetDataLineStart(y+Offset.y);
|
2018-02-05 12:05:26 +00:00
|
|
|
SrcPtr := {%H-}pointer({%H-}PtrInt(SrcLine) + SrcRect.Left*3);
|
|
|
|
DstPtr := {%H-}pointer({%H-}PtrInt(DstLine) + 3*(SrcRect.Left + Offset.x));
|
2017-10-12 17:48:39 +00:00
|
|
|
for x := SrcRect.Left to SrcRect.Right do
|
|
|
|
begin
|
|
|
|
{$ifdef EnhancedRecordSupport}
|
|
|
|
Dist := Center.DistanceTo(T2DIntVector.Create(x, y));
|
|
|
|
{$else}
|
|
|
|
Dist := Center.DistanceTo(x, y);
|
|
|
|
{$endif}
|
|
|
|
if Dist <= (Radius-1) then
|
|
|
|
Move(SrcPtr^, DstPtr^, 3);
|
|
|
|
inc(SrcPtr, 3);
|
|
|
|
inc(DstPtr, 3);
|
|
|
|
end;
|
|
|
|
end;
|
2011-06-18 12:34:17 +00:00
|
|
|
ABitmap.LoadFromIntfImage(DestImg);
|
|
|
|
SrcImg.Destroy;
|
|
|
|
DestImg.Destroy;
|
2017-10-12 17:48:39 +00:00
|
|
|
end;
|
|
|
|
end else
|
|
|
|
begin
|
|
|
|
if (SrcRect.Left <= SrcRect.Right) and (SrcRect.Top <= SrcRect.Bottom) then
|
|
|
|
begin
|
|
|
|
SrcImg := ABuffer.CreateIntfImage;
|
|
|
|
DestImg := ABitmap.CreateIntfImage;
|
|
|
|
for y := SrcRect.Top to SrcRect.Bottom do
|
|
|
|
begin
|
|
|
|
SrcLine := SrcImg.GetDataLineStart(y);
|
|
|
|
DstLine := DestImg.GetDataLineStart(y+Offset.y);
|
2018-02-05 12:05:26 +00:00
|
|
|
SrcPtr := {%H-}pointer({%H-}PtrInt(SrcLine) + 3*SrcRect.Left);
|
|
|
|
DstPtr := {%H-}pointer({%H-}PtrInt(DstLine) + 3*(SrcRect.Left + Offset.x));
|
2017-10-12 17:48:39 +00:00
|
|
|
for x := SrcRect.Left to SrcRect.Right do
|
|
|
|
begin
|
|
|
|
{$ifdef EnhancedRecordSupport}
|
|
|
|
Dist := Center.DistanceTo(T2DIntVector.Create(x, y));
|
|
|
|
{$else}
|
|
|
|
Dist := Center.DistanceTo(x, y);
|
|
|
|
{$endif}
|
|
|
|
if Dist >= (Radius-1) then
|
|
|
|
Move(SrcPtr^, DstPtr^, 3);
|
|
|
|
inc(SrcPtr,3);
|
|
|
|
inc(DstPtr,3);
|
|
|
|
end;
|
|
|
|
end;
|
2011-06-18 12:34:17 +00:00
|
|
|
ABitmap.LoadFromIntfImage(DestImg);
|
|
|
|
SrcImg.Destroy;
|
|
|
|
DestImg.Destroy;
|
2017-10-12 17:48:39 +00:00
|
|
|
end;
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.CopyRoundRect(ABuffer, ABitmap: TBitmap; SrcPoint,
|
|
|
|
DstPoint: T2DIntVector; Width, Height, Radius: integer; ClipRect: T2DIntRect;
|
|
|
|
LeftTopRound, RightTopRound, LeftBottomRound, RightBottomRound: boolean);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.PixelFormat <> pf24Bit) or (ABitmap.PixelFormat <> pf24Bit) then
|
|
|
|
raise Exception.Create('TSpkGUITools.CopyBackground: Only 24 bit bitmaps are accepted!');
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if Radius < 0 then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (Radius > Width div 2) or (Radius > Height div 2) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.Width = 0) or (ABuffer.Height = 0) or
|
|
|
|
(ABitmap.Width = 0) or (ABitmap.Height = 0) then exit;
|
|
|
|
|
|
|
|
{$REGION 'We fill the rectangles'}
|
|
|
|
// Mountain /????
|
|
|
|
// Góra
|
|
|
|
CopyRectangle(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$ifdef EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x + Radius, SrcPoint.y),
|
|
|
|
T2DIntPoint.Create(DstPoint.x + Radius, DstPoint.y),
|
|
|
|
{$else}
|
|
|
|
Create2DIntPoint(SrcPoint.x + Radius, SrcPoint.y),
|
|
|
|
Create2DIntPoint(DstPoint.x + Radius, DstPoint.y),
|
|
|
|
{$endif}
|
|
|
|
Width - 2*Radius,
|
|
|
|
Radius,
|
|
|
|
ClipRect);
|
|
|
|
// Down
|
|
|
|
// Dó³
|
|
|
|
CopyRectangle(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x + Radius, SrcPoint.y + Height - Radius),
|
|
|
|
T2DIntPoint.Create(DstPoint.x + Radius, DstPoint.y + Height - Radius),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x + Radius, SrcPoint.y + Height - Radius),
|
|
|
|
Create2DIntPoint(DstPoint.x + Radius, DstPoint.y + Height - Radius),
|
|
|
|
{$ENDIF}
|
|
|
|
Width - 2*Radius,
|
|
|
|
Radius,
|
|
|
|
ClipRect);
|
|
|
|
// Agent (???)
|
|
|
|
// Œrodek
|
|
|
|
CopyRectangle(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x, SrcPoint.y + Radius),
|
|
|
|
T2DIntPoint.Create(DstPoint.x, DstPoint.y + Radius),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x, SrcPoint.y + Radius),
|
|
|
|
Create2DIntPoint(DstPoint.x, DstPoint.y + Radius),
|
|
|
|
{$ENDIF}
|
|
|
|
Width,
|
|
|
|
Height - 2*Radius,
|
|
|
|
ClipRect);
|
2011-06-17 20:53:01 +00:00
|
|
|
{$ENDREGION}
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// We fill the corners
|
|
|
|
{$REGION 'Left upper'}
|
|
|
|
if LeftTopRound then
|
|
|
|
TGUITools.CopyRoundCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x, SrcPoint.y),
|
|
|
|
T2DIntPoint.Create(DstPoint.x, DstPoint.y),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x, SrcPoint.y),
|
|
|
|
Create2DIntPoint(DstPoint.x, DstPoint.y),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius,
|
|
|
|
cpLeftTop,
|
|
|
|
ClipRect,
|
|
|
|
true)
|
|
|
|
else
|
|
|
|
TGUITools.CopyCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x, SrcPoint.y),
|
|
|
|
T2DIntPoint.Create(DstPoint.x, DstPoint.y),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x, SrcPoint.y),
|
|
|
|
Create2DIntPoint(DstPoint.x, DstPoint.y),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius,
|
|
|
|
ClipRect);
|
2011-06-17 20:53:01 +00:00
|
|
|
{$ENDREGION}
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$REGION 'Right upper'}
|
|
|
|
if RightTopRound then
|
|
|
|
TGUITools.CopyRoundCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x + Width - Radius, SrcPoint.y),
|
|
|
|
T2DIntPoint.Create(DstPoint.x + Width - Radius, DstPoint.y),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x + Width - Radius, SrcPoint.y),
|
|
|
|
Create2DIntPoint(DstPoint.x + Width - Radius, DstPoint.y),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius,
|
|
|
|
cpRightTop,
|
|
|
|
ClipRect,
|
|
|
|
true)
|
|
|
|
else
|
|
|
|
TGUITools.CopyCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x + Width - Radius, SrcPoint.y),
|
|
|
|
T2DIntPoint.Create(DstPoint.x + Width - Radius, DstPoint.y),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x + Width - Radius, SrcPoint.y),
|
|
|
|
Create2DIntPoint(DstPoint.x + Width - Radius, DstPoint.y),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius,
|
|
|
|
ClipRect);
|
2011-06-17 20:53:01 +00:00
|
|
|
{$ENDREGION}
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$REGION 'Left bottom'}
|
|
|
|
if LeftBottomRound then
|
|
|
|
TGUITools.CopyRoundCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x, SrcPoint.y + Height - Radius),
|
|
|
|
T2DIntPoint.Create(DstPoint.x, DstPoint.y + Height - Radius),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x, SrcPoint.y + Height - Radius),
|
|
|
|
Create2DIntPoint(DstPoint.x, DstPoint.y + Height - Radius),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius,
|
|
|
|
cpLeftBottom,
|
|
|
|
ClipRect,
|
|
|
|
true)
|
|
|
|
else
|
|
|
|
TGUITools.CopyCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x, SrcPoint.y + Height - Radius),
|
|
|
|
T2DIntPoint.Create(DstPoint.x, DstPoint.y + Height - Radius),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x, SrcPoint.y + Height - Radius),
|
|
|
|
Create2DIntPoint(DstPoint.x, DstPoint.y + Height - Radius),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius,
|
|
|
|
ClipRect);
|
2011-06-17 20:53:01 +00:00
|
|
|
{$ENDREGION}
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$REGION 'Right bottom'}
|
|
|
|
if RightBottomRound then
|
|
|
|
TGUITools.CopyRoundCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x + Width - Radius, SrcPoint.y + Height - Radius),
|
|
|
|
T2DIntPoint.Create(DstPoint.x + Width - Radius, DstPoint.y + Height - Radius),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x + Width - Radius, SrcPoint.y + Height - Radius),
|
|
|
|
Create2DIntPoint(DstPoint.x + Width - Radius, DstPoint.y + Height - Radius),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius,
|
|
|
|
cpRightBottom,
|
|
|
|
ClipRect,
|
|
|
|
true)
|
|
|
|
else
|
|
|
|
TGUITools.CopyCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x + Width - Radius, SrcPoint.y + Height - Radius),
|
|
|
|
T2DIntPoint.Create(DstPoint.x + Width - Radius, DstPoint.y + Height - Radius),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x + Width - Radius, SrcPoint.y + Height - Radius),
|
|
|
|
Create2DIntPoint(DstPoint.x + Width - Radius, DstPoint.y + Height - Radius),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius,
|
|
|
|
ClipRect);
|
2011-06-17 20:53:01 +00:00
|
|
|
{$ENDREGION'}
|
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.CopyRoundRect(ABuffer : TBitmap; ABitmap: TBitmap; SrcPoint,
|
|
|
|
DstPoint: T2DIntVector; Width, Height, Radius: integer; LeftTopRound,
|
|
|
|
RightTopRound, LeftBottomRound, RightBottomRound: boolean);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.PixelFormat <> pf24bit) or (ABitmap.PixelFormat <> pf24bit) then
|
|
|
|
raise exception.create('TSpkGUITools.CopyBackground: Only 24 bit bitmaps are accepted!');
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if Radius < 0 then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (Radius > Width div 2) or (Radius > Height div 2) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.Width = 0) or (ABuffer.Height = 0) or
|
|
|
|
(ABitmap.Width = 0) or (ABitmap.Height = 0) then exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$REGION 'We fill the rectangles'}
|
|
|
|
// Góra
|
|
|
|
CopyRectangle(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x + Radius, SrcPoint.y),
|
|
|
|
T2DIntPoint.Create(DstPoint.x + Radius, DstPoint.y),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x + Radius, SrcPoint.y),
|
|
|
|
Create2DIntPoint(DstPoint.x + Radius, DstPoint.y),
|
|
|
|
{$ENDIF}
|
|
|
|
Width - 2*Radius,
|
|
|
|
Radius);
|
|
|
|
// Dó³
|
|
|
|
CopyRectangle(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x + Radius, SrcPoint.y + Height - radius),
|
|
|
|
T2DIntPoint.Create(DstPoint.x + Radius, DstPoint.y + Height - radius),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x + Radius, SrcPoint.y + Height - radius),
|
|
|
|
Create2DIntPoint(DstPoint.x + Radius, DstPoint.y + Height - radius),
|
|
|
|
{$ENDIF}
|
|
|
|
Width - 2*Radius,
|
|
|
|
Radius);
|
|
|
|
// Œrodek
|
|
|
|
CopyRectangle(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x, SrcPoint.y + Radius),
|
|
|
|
T2DIntPoint.Create(DstPoint.x, DstPoint.y + Radius),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x, SrcPoint.y + Radius),
|
|
|
|
Create2DIntPoint(DstPoint.x, DstPoint.y + Radius),
|
|
|
|
{$ENDIF}
|
|
|
|
Width,
|
|
|
|
Height - 2*Radius);
|
2011-06-17 20:53:01 +00:00
|
|
|
{$ENDREGION}
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// We fill the corners
|
|
|
|
{$REGION 'Left upper'}
|
|
|
|
if LeftTopRound then
|
|
|
|
TGUITools.CopyRoundCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x, SrcPoint.y),
|
|
|
|
T2DIntPoint.Create(DstPoint.x, DstPoint.y),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x, SrcPoint.y),
|
|
|
|
Create2DIntPoint(DstPoint.x, DstPoint.y),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius,
|
|
|
|
cpLeftTop,
|
|
|
|
true)
|
|
|
|
else
|
|
|
|
TGUITools.CopyCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x, SrcPoint.y),
|
|
|
|
T2DIntPoint.Create(DstPoint.x, DstPoint.y),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x, SrcPoint.y),
|
|
|
|
Create2DIntPoint(DstPoint.x, DstPoint.y),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius);
|
2011-06-17 20:53:01 +00:00
|
|
|
{$ENDREGION}
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$REGION 'Right upper'}
|
|
|
|
if RightTopRound then
|
|
|
|
TGUITools.CopyRoundCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x + Width - Radius, SrcPoint.y),
|
|
|
|
T2DIntPoint.Create(DstPoint.x + Width - Radius, DstPoint.y),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x + Width - Radius, SrcPoint.y),
|
|
|
|
Create2DIntPoint(DstPoint.x + Width - Radius, DstPoint.y),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius,
|
|
|
|
cpRightTop,
|
|
|
|
true)
|
|
|
|
else
|
|
|
|
TGUITools.CopyCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x + Width - Radius, SrcPoint.y),
|
|
|
|
T2DIntPoint.Create(DstPoint.x + Width - Radius, DstPoint.y),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x + Width - Radius, SrcPoint.y),
|
|
|
|
Create2DIntPoint(DstPoint.x + Width - Radius, DstPoint.y),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius);
|
2011-06-17 20:53:01 +00:00
|
|
|
{$ENDREGION}
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$REGION 'Left bottom'}
|
|
|
|
if LeftBottomRound then
|
|
|
|
TGUITools.CopyRoundCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x, SrcPoint.y + Height - Radius),
|
|
|
|
T2DIntPoint.Create(DstPoint.x, DstPoint.y + Height - Radius),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x, SrcPoint.y + Height - Radius),
|
|
|
|
Create2DIntPoint(DstPoint.x, DstPoint.y + Height - Radius),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius,
|
|
|
|
cpLeftBottom,
|
|
|
|
true)
|
|
|
|
else
|
|
|
|
TGUITools.CopyCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x, SrcPoint.y + Height - Radius),
|
|
|
|
T2DIntPoint.Create(DstPoint.x, DstPoint.y + Height - Radius),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x, SrcPoint.y + Height - Radius),
|
|
|
|
Create2DIntPoint(DstPoint.x, DstPoint.y + Height - Radius),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius);
|
2011-06-17 20:53:01 +00:00
|
|
|
{$ENDREGION}
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$REGION 'Right bottom'}
|
|
|
|
if RightBottomRound then
|
|
|
|
TGUITools.CopyRoundCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x + Width - Radius, SrcPoint.y + Height - Radius),
|
|
|
|
T2DIntPoint.Create(DstPoint.x + Width - Radius, DstPoint.y + Height - Radius),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x + Width - Radius, SrcPoint.y + Height - Radius),
|
|
|
|
Create2DIntPoint(DstPoint.x + Width - Radius, DstPoint.y + Height - Radius),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius,
|
|
|
|
cpRightBottom,
|
|
|
|
true)
|
|
|
|
else
|
|
|
|
TGUITools.CopyCorner(ABuffer,
|
|
|
|
ABitmap,
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
T2DIntPoint.Create(SrcPoint.x + Width - Radius, SrcPoint.y + Height - Radius),
|
|
|
|
T2DIntPoint.Create(DstPoint.x + Width - Radius, DstPoint.y + Height - Radius),
|
|
|
|
{$ELSE}
|
|
|
|
Create2DIntPoint(SrcPoint.x + Width - Radius, SrcPoint.y + Height - Radius),
|
|
|
|
Create2DIntPoint(DstPoint.x + Width - Radius, DstPoint.y + Height - Radius),
|
|
|
|
{$ENDIF}
|
|
|
|
Radius);
|
|
|
|
{$ENDREGION}
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.CopyRectangle(ABuffer, ABitmap: TBitmap; SrcPoint,
|
|
|
|
DstPoint: T2DIntVector; Width, Height: integer);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
BufferRect, BitmapRect: T2DIntRect;
|
|
|
|
SrcRect, DstRect: T2DIntRect;
|
|
|
|
ClippedSrcRect: T2DIntRect;
|
|
|
|
Offset: T2DIntVector;
|
|
|
|
y: Integer;
|
|
|
|
SrcLine: Pointer;
|
|
|
|
DstLine: Pointer;
|
|
|
|
SrcImg: TLazIntfImage;
|
|
|
|
DestImg: TLazIntfImage;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.PixelFormat <> pf24Bit) or (ABitmap.PixelFormat <> pf24Bit) then
|
|
|
|
raise exception.create('TSpkGUITools.CopyRoundCorner: Only 24 bit bitmaps are accepted!');
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Validation
|
|
|
|
if (Width < 1) or (Height < 1) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.Width = 0) or (ABuffer.Height = 0) or
|
|
|
|
(ABitmap.Width = 0) or (ABitmap.Height = 0) then exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
// Truncate the source rect to the source bitmap
|
|
|
|
BufferRect := T2DIntRect.Create(0, 0, ABuffer.Width-1, ABuffer.Height-1);
|
|
|
|
if not BufferRect.IntersectsWith(
|
|
|
|
T2DIntRect.Create(SrcPoint.x, SrcPoint.y, SrcPoint.x+Width-1, SrcPoint.y+Height-1),
|
|
|
|
SrcRect
|
|
|
|
)
|
|
|
|
then
|
|
|
|
exit;
|
2011-06-18 13:46:52 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// We cut the target rect to the target bitmap
|
|
|
|
BitmapRect := T2DIntRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
if not BitmapRect.IntersectsWith(
|
|
|
|
T2DIntRect.Create(DstPoint.x, DstPoint.y, DstPoint.x+Width-1, DstPoint.y+Height-1),
|
|
|
|
DstRect
|
|
|
|
)
|
|
|
|
then
|
|
|
|
exit;
|
|
|
|
{$ELSE}
|
|
|
|
// Truncate the source rect to the source bitmap
|
|
|
|
BufferRect.Create(0, 0, ABuffer.Width-1, ABuffer.Height-1);
|
|
|
|
if not BufferRect.IntersectsWith(
|
|
|
|
Create2DIntRect(SrcPoint.x, SrcPoint.y, SrcPoint.x+Width-1, SrcPoint.y+Height-1),
|
|
|
|
SrcRect
|
|
|
|
)
|
|
|
|
then
|
|
|
|
exit;
|
2011-06-18 13:46:52 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// We cut the target rect to the target bitmap
|
|
|
|
BitmapRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
if not BitmapRect.IntersectsWith(
|
|
|
|
Create2DIntRect(DstPoint.x, DstPoint.y, DstPoint.x+Width-1, DstPoint.y+Height-1),
|
|
|
|
DstRect
|
|
|
|
)
|
|
|
|
then
|
|
|
|
exit;
|
2011-06-18 13:46:52 +00:00
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// We are counting the source offset to the target recta
|
|
|
|
Offset := DstPoint - SrcPoint;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Sprawdzamy, czy na³o¿one na siebie recty: Ÿród³owy i docelowy przesuniêty o
|
|
|
|
// offset maj¹ jak¹œ czêœæ wspóln¹
|
|
|
|
// Google-translated:
|
|
|
|
// Verify that the rectangular overhead: source and target shifted by offset have some common
|
|
|
|
if not SrcRect.IntersectsWith(DstRect - Offset, ClippedSrcRect) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// If there is anything to process, do the operation
|
|
|
|
if (ClippedSrcRect.Left <= ClippedSrcRect.Right) and
|
|
|
|
(ClippedSrcRect.Top <= ClippedSrcRect.Bottom) then
|
2011-06-18 12:34:17 +00:00
|
|
|
begin
|
|
|
|
SrcImg := ABuffer.CreateIntfImage;
|
|
|
|
DestImg := ABitmap.CreateIntfImage;
|
2017-10-12 17:48:39 +00:00
|
|
|
for y := ClippedSrcRect.Top to ClippedSrcRect.Bottom do
|
|
|
|
begin
|
|
|
|
SrcLine := SrcImg.GetDataLineStart(y);
|
|
|
|
DstLine := DestImg.GetDataLineStart(y+Offset.y);
|
2018-02-05 12:05:26 +00:00
|
|
|
Move({%H-}pointer({%H-}PtrInt(SrcLine) + 3*ClippedSrcRect.Left)^,
|
|
|
|
{%H-}pointer({%H-}PtrInt(DstLine) + 3*(ClippedSrcRect.Left + Offset.x))^,
|
2017-10-12 17:48:39 +00:00
|
|
|
3*ClippedSrcRect.Width);
|
|
|
|
end;
|
|
|
|
ABitmap.LoadFromIntfImage(DestImg);
|
|
|
|
SrcImg.Destroy;
|
|
|
|
DestImg.Destroy;
|
2011-06-18 12:34:17 +00:00
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
class procedure TGUITools.CopyCorner(ABuffer, ABitmap: TBitmap;
|
2011-06-17 20:53:01 +00:00
|
|
|
SrcPoint, DstPoint: T2DIntVector; Radius: integer);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
CopyRectangle(ABuffer, ABitmap, SrcPoint, DstPoint, Radius, Radius);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.CopyCorner(ABuffer, ABitmap: TBitmap; SrcPoint,
|
|
|
|
DstPoint: T2DIntVector; Radius: integer; ClipRect: T2DIntRect);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
CopyRectangle(ABuffer, ABitmap, SrcPoint, DstPoint, Radius, Radius, ClipRect);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.CopyMaskRectangle(ABuffer, AMask, ABitmap: TBitmap;
|
|
|
|
SrcPoint, DstPoint: T2DIntVector; Width, Height: integer);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
BufferRect, BitmapRect: T2DIntRect;
|
|
|
|
SrcRect, DstRect: T2DIntRect;
|
|
|
|
ClippedSrcRect: T2DIntRect;
|
|
|
|
Offset: T2DIntVector;
|
|
|
|
y: Integer;
|
|
|
|
SrcLine: Pointer;
|
|
|
|
MaskLine: Pointer;
|
|
|
|
DstLine: Pointer;
|
|
|
|
SrcImg: TLazIntfImage;
|
|
|
|
MaskImg: TLazIntfImage;
|
|
|
|
DestImg: TLazIntfImage;
|
|
|
|
i: Integer;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.PixelFormat <> pf24Bit) or (ABitmap.PixelFormat <> pf24Bit) then
|
|
|
|
raise Exception.Create('TSpkGUITools.CopyRoundCorner: Only 24 bit bitmaps are accepted!');
|
2011-06-18 13:46:52 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (AMask.PixelFormat <> pf8bit) then
|
|
|
|
raise Exception.Create('TSpkGUITools.CopyRoundCorner: Only 8-bit masks are accepted!');
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Validation
|
|
|
|
if (Width < 1) or (Height < 1) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.Width = 0) or (ABuffer.Height = 0) or
|
|
|
|
(ABitmap.Width = 0) or (ABitmap.Height = 0) then exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.Width <> AMask.Width) or (ABuffer.Height <> AMask.Height) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
// Truncate the source rect to the source bitmap
|
|
|
|
BufferRect := T2DIntRect.Create(0, 0, ABuffer.Width-1, ABuffer.Height-1);
|
|
|
|
if not BufferRect.IntersectsWith(
|
|
|
|
T2DIntRect.Create(SrcPoint.x, SrcPoint.y, SrcPoint.x+Width-1, SrcPoint.y+Height-1),
|
|
|
|
SrcRect
|
|
|
|
) then
|
|
|
|
exit;
|
|
|
|
// We cut the target rect to the target bitmap
|
|
|
|
BitmapRect := T2DIntRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
if not BitmapRect.IntersectsWith(
|
|
|
|
T2DIntRect.Create(DstPoint.x, DstPoint.y, DstPoint.x+Width-1, DstPoint.y+Height-1),
|
|
|
|
DstRect
|
|
|
|
) then
|
|
|
|
exit;
|
|
|
|
{$ELSE}
|
|
|
|
// Truncate the source rect to the source bitmap
|
|
|
|
BufferRect.Create(0, 0, ABuffer.Width-1, ABuffer.Height-1);
|
|
|
|
if not BufferRect.IntersectsWith(
|
|
|
|
Create2DIntRect(SrcPoint.x, SrcPoint.y, SrcPoint.x+Width-1, SrcPoint.y+Height-1),
|
|
|
|
SrcRect
|
|
|
|
) then
|
|
|
|
exit;
|
|
|
|
// Trim the target rect to the target bitmap
|
|
|
|
BitmapRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
if not BitmapRect.IntersectsWith(
|
|
|
|
Create2DIntRect(DstPoint.x, DstPoint.y, DstPoint.x+Width-1, DstPoint.y+Height-1),
|
|
|
|
DstRect
|
|
|
|
) then
|
|
|
|
exit;
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// We are counting the source offset to the target recta
|
|
|
|
Offset := DstPoint - SrcPoint;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Sprawdzamy, czy na³o¿one na siebie recty: Ÿród³owy i docelowy przesuniêty o
|
|
|
|
// offset maj¹ jak¹œ czêœæ wspóln¹
|
|
|
|
// Google-translated:
|
|
|
|
// We check that the rectangles that are superimposed on each other:
|
|
|
|
// source and target shifted by offset have some common
|
|
|
|
if not(SrcRect.IntersectsWith(DstRect - Offset, ClippedSrcRect)) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// If there is anything to process, do the operation
|
|
|
|
if (ClippedSrcRect.Left <= ClippedSrcRect.Right) and
|
|
|
|
(ClippedSrcRect.Top <= ClippedSrcRect.Bottom) then
|
|
|
|
begin
|
|
|
|
SrcImg := ABuffer.CreateIntfImage;
|
|
|
|
DestImg := ABitmap.CreateIntfImage;
|
|
|
|
MaskImg := AMask.CreateIntfImage;
|
|
|
|
for y := ClippedSrcRect.Top to ClippedSrcRect.Bottom do
|
|
|
|
begin
|
|
|
|
SrcLine := SrcImg.GetDataLineStart(y);
|
2018-02-05 12:05:26 +00:00
|
|
|
SrcLine := {%H-}pointer({%H-}PtrInt(SrcLine) + 3 * ClippedSrcRect.left);
|
2017-10-12 17:48:39 +00:00
|
|
|
MaskLine := MaskImg.GetDataLineStart(y);
|
2018-02-05 12:05:26 +00:00
|
|
|
MaskLine := {%H-}pointer({%H-}PtrInt(MaskLine) + ClippedSrcRect.left);
|
2017-10-12 17:48:39 +00:00
|
|
|
DstLine := DestImg.GetDataLineStart(y+Offset.y);
|
2018-02-05 12:05:26 +00:00
|
|
|
DstLine := {%H-}pointer({%H-}PtrInt(DstLine) + 3 * (ClippedSrcRect.left + Offset.x));
|
2017-10-12 17:48:39 +00:00
|
|
|
for i := 0 to ClippedSrcRect.Width - 1 do
|
|
|
|
begin
|
|
|
|
if PByte(MaskLine)^ < 128 then
|
|
|
|
Move(SrcLine^, DstLine^, 3);
|
2018-02-05 12:05:26 +00:00
|
|
|
SrcLine := {%H-}pointer({%H-}PtrInt(SrcLine)+3);
|
|
|
|
DstLine := {%H-}pointer({%H-}PtrInt(DstLine)+3);
|
|
|
|
MaskLine := {%H-}pointer({%H-}PtrInt(MaskLine)+1);
|
2017-10-12 17:48:39 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
ABitmap.LoadFromIntfImage(DestImg);
|
|
|
|
DestImg.Destroy;
|
|
|
|
SrcImg.Destroy;
|
|
|
|
MaskImg.Destroy;
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.CopyMaskRectangle(ABuffer, AMask, ABitmap: TBitmap;
|
|
|
|
SrcPoint, DstPoint: T2DIntVector; Width, Height: integer;
|
|
|
|
ClipRect: T2DIntRect);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
BufferRect, BitmapRect: T2DIntRect;
|
|
|
|
SrcRect, DstRect: T2DIntRect;
|
|
|
|
ClippedSrcRect, ClippedDstRect: T2DIntRect;
|
|
|
|
Offset: T2DIntVector;
|
|
|
|
y: Integer;
|
|
|
|
SrcImg: TLazIntfImage;
|
|
|
|
MaskImg: TLazIntfImage;
|
|
|
|
DestImg: TLazIntfImage;
|
|
|
|
SrcLine: Pointer;
|
|
|
|
DstLine: Pointer;
|
|
|
|
i: Integer;
|
|
|
|
MaskLine: Pointer;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.PixelFormat <> pf24Bit) or (ABitmap.PixelFormat <> pf24Bit) then
|
|
|
|
raise Exception.Create('TSpkGUITools.CopyMaskRectangle: Only 24 bit bitmaps are accepted!');
|
|
|
|
if AMask.PixelFormat<>pf8bit then
|
|
|
|
raise Exception.Create('TSpkGUITools.CopyMaskRectangle: Only 8-bit masks are accepted!');
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Validation
|
|
|
|
if (Width < 1) or (Height < 1) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.Width = 0) or (ABuffer.Height = 0) or
|
|
|
|
(ABitmap.Width = 0) or (ABitmap.Height = 0) then exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABuffer.Width <> AMask.Width) or
|
|
|
|
(ABuffer.Height <> AMask.Height)
|
|
|
|
then
|
|
|
|
raise Exception.Create('TSpkGUITools.CopyMaskRectangle: The mask has incorrect dimensions!');
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
// Truncate the source rect to the source bitmap
|
|
|
|
BufferRect := T2DIntRect.Create(0, 0, ABuffer.Width-1, ABuffer.Height-1);
|
|
|
|
if not BufferRect.IntersectsWith(
|
|
|
|
T2DIntRect.Create(SrcPoint.x, SrcPoint.y, SrcPoint.x+Width-1, SrcPoint.y+Height-1),
|
|
|
|
SrcRect
|
|
|
|
)
|
|
|
|
then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
|
|
|
// Przycinamy docelowy rect do obszaru docelowej bitmapy
|
|
|
|
BitmapRect:=T2DIntRect.create(0, 0, ABitmap.width-1, ABitmap.height-1);
|
|
|
|
if not(BitmapRect.IntersectsWith(T2DIntRect.create(DstPoint.x,
|
|
|
|
DstPoint.y,
|
|
|
|
DstPoint.x+Width-1,
|
|
|
|
DstPoint.y+Height-1),
|
|
|
|
DstRect)) then exit;
|
2011-06-18 13:46:52 +00:00
|
|
|
{$ELSE}
|
|
|
|
// Przycinamy Ÿród³owy rect do obszaru Ÿród³owej bitmapy
|
|
|
|
BufferRect.create(0, 0, ABuffer.width-1, ABuffer.height-1);
|
|
|
|
if not(BufferRect.IntersectsWith(Create2DIntRect(SrcPoint.x,
|
|
|
|
SrcPoint.y,
|
|
|
|
SrcPoint.x+Width-1,
|
|
|
|
SrcPoint.y+Height-1),
|
|
|
|
SrcRect)) then exit;
|
|
|
|
|
|
|
|
// Przycinamy docelowy rect do obszaru docelowej bitmapy
|
|
|
|
BitmapRect.create(0, 0, ABitmap.width-1, ABitmap.height-1);
|
|
|
|
if not(BitmapRect.IntersectsWith(Create2DIntRect(DstPoint.x,
|
|
|
|
DstPoint.y,
|
|
|
|
DstPoint.x+Width-1,
|
|
|
|
DstPoint.y+Height-1),
|
|
|
|
DstRect)) then exit;
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
|
|
|
// Dodatkowo przycinamy docelowy rect
|
|
|
|
if not(DstRect.IntersectsWith(ClipRect, ClippedDstRect)) then
|
|
|
|
Exit;
|
|
|
|
|
2011-06-17 21:12:21 +00:00
|
|
|
// Liczymy offset Ÿród³owego do docelowego recta
|
2011-06-17 20:53:01 +00:00
|
|
|
Offset:=DstPoint - SrcPoint;
|
|
|
|
|
2011-06-17 21:12:21 +00:00
|
|
|
// Sprawdzamy, czy na³o¿one na siebie recty: Ÿród³owy i docelowy przesuniêty o
|
|
|
|
// offset maj¹ jak¹œ czêœæ wspóln¹
|
2011-06-17 20:53:01 +00:00
|
|
|
if not(SrcRect.IntersectsWith(ClippedDstRect - Offset, ClippedSrcRect)) then exit;
|
|
|
|
|
2011-06-17 21:12:21 +00:00
|
|
|
// Jeœli jest cokolwiek do przetworzenia, wykonaj operacjê
|
2011-06-17 20:53:01 +00:00
|
|
|
if (ClippedSrcRect.left<=ClippedSrcRect.right) and (ClippedSrcRect.top<=ClippedSrcRect.bottom) then
|
2011-06-18 12:34:17 +00:00
|
|
|
begin
|
|
|
|
SrcImg := ABuffer.CreateIntfImage;
|
|
|
|
DestImg := ABitmap.CreateIntfImage;
|
|
|
|
MaskImg := ABitmap.CreateIntfImage;
|
2011-06-17 20:53:01 +00:00
|
|
|
for y := ClippedSrcRect.top to ClippedSrcRect.bottom do
|
|
|
|
begin
|
2011-06-18 12:34:17 +00:00
|
|
|
SrcLine:=SrcImg.GetDataLineStart(y);
|
2018-02-05 12:05:26 +00:00
|
|
|
SrcLine:={%H-}pointer({%H-}PtrInt(SrcLine) + 3 * ClippedSrcRect.left);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2011-06-18 13:46:52 +00:00
|
|
|
MaskLine:=MaskImg.GetDataLineStart(y);
|
2018-02-05 12:05:26 +00:00
|
|
|
MaskLine:={%H-}pointer({%H-}PtrInt(MaskLine) + ClippedSrcRect.left);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2011-06-18 12:34:17 +00:00
|
|
|
DstLine:=DestImg.GetDataLineStart(y+Offset.y);
|
2018-02-05 12:05:26 +00:00
|
|
|
DstLine:={%H-}pointer({%H-}PtrInt(DstLine) + 3 * (ClippedSrcRect.left + Offset.x));
|
2011-06-17 20:53:01 +00:00
|
|
|
|
|
|
|
for i := 0 to ClippedSrcRect.width - 1 do
|
|
|
|
begin
|
|
|
|
if PByte(MaskLine)^<128 then
|
|
|
|
Move(SrcLine^, DstLine^, 3);
|
|
|
|
|
2018-02-05 12:05:26 +00:00
|
|
|
SrcLine:={%H-}pointer({%H-}PtrInt(SrcLine)+3);
|
|
|
|
DstLine:={%H-}pointer({%H-}PtrInt(DstLine)+3);
|
|
|
|
MaskLine:={%H-}pointer({%H-}PtrInt(MaskLine)+1);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
end;
|
2011-06-18 12:34:17 +00:00
|
|
|
ABitmap.LoadFromIntfImage(DestImg);
|
|
|
|
SrcImg.Destroy;
|
|
|
|
DestImg.Destroy;
|
|
|
|
MaskImg.Destroy;
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.CopyRectangle(ABuffer, ABitmap: TBitmap; SrcPoint,
|
|
|
|
DstPoint: T2DIntVector; Width, Height: integer; ClipRect: T2DIntRect);
|
|
|
|
|
|
|
|
var BufferRect, BitmapRect : T2DIntRect;
|
|
|
|
SrcRect, DstRect : T2DIntRect;
|
|
|
|
ClippedSrcRect, ClippedDstRect : T2DIntRect;
|
|
|
|
Offset : T2DIntVector;
|
|
|
|
y: Integer;
|
2011-06-18 12:34:17 +00:00
|
|
|
DestImg: TLazIntfImage;
|
|
|
|
SrcImg: TLazIntfImage;
|
2011-06-17 20:53:01 +00:00
|
|
|
SrcLine: Pointer;
|
|
|
|
DstLine: Pointer;
|
|
|
|
|
|
|
|
begin
|
|
|
|
if (ABuffer.PixelFormat<>pf24bit) or (ABitmap.PixelFormat<>pf24bit) then
|
2011-06-17 21:12:21 +00:00
|
|
|
raise exception.create('TSpkGUITools.CopyRoundCorner: Tylko 24-bitowe bitmapy s¹ akceptowane!');
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2011-06-17 21:12:21 +00:00
|
|
|
// Sprawdzanie poprawnoœci
|
2011-06-17 20:53:01 +00:00
|
|
|
if (Width<1) or (Height<1) then
|
|
|
|
exit;
|
|
|
|
|
|
|
|
if (ABuffer.width=0) or (ABuffer.height=0) or
|
|
|
|
(ABitmap.width=0) or (ABitmap.height=0) then exit;
|
|
|
|
|
2011-06-18 13:46:52 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
2011-06-17 21:12:21 +00:00
|
|
|
// Przycinamy Ÿród³owy rect do obszaru Ÿród³owej bitmapy
|
2011-06-17 20:53:01 +00:00
|
|
|
BufferRect:=T2DIntRect.create(0, 0, ABuffer.width-1, ABuffer.height-1);
|
|
|
|
if not(BufferRect.IntersectsWith(T2DIntRect.create(SrcPoint.x,
|
|
|
|
SrcPoint.y,
|
|
|
|
SrcPoint.x+Width-1,
|
|
|
|
SrcPoint.y+Height-1),
|
|
|
|
SrcRect)) then exit;
|
|
|
|
|
|
|
|
// Przycinamy docelowy rect do obszaru docelowej bitmapy
|
|
|
|
BitmapRect:=T2DIntRect.create(0, 0, ABitmap.width-1, ABitmap.height-1);
|
|
|
|
if not(BitmapRect.IntersectsWith(T2DIntRect.create(DstPoint.x,
|
|
|
|
DstPoint.y,
|
|
|
|
DstPoint.x+Width-1,
|
|
|
|
DstPoint.y+Height-1),
|
|
|
|
DstRect)) then exit;
|
2011-06-18 13:46:52 +00:00
|
|
|
{$ELSE}
|
|
|
|
// Przycinamy Ÿród³owy rect do obszaru Ÿród³owej bitmapy
|
|
|
|
BufferRect.create(0, 0, ABuffer.width-1, ABuffer.height-1);
|
|
|
|
if not(BufferRect.IntersectsWith(Create2DIntRect(SrcPoint.x,
|
|
|
|
SrcPoint.y,
|
|
|
|
SrcPoint.x+Width-1,
|
|
|
|
SrcPoint.y+Height-1),
|
|
|
|
SrcRect)) then exit;
|
|
|
|
|
|
|
|
// Przycinamy docelowy rect do obszaru docelowej bitmapy
|
|
|
|
BitmapRect.create(0, 0, ABitmap.width-1, ABitmap.height-1);
|
|
|
|
if not(BitmapRect.IntersectsWith(Create2DIntRect(DstPoint.x,
|
|
|
|
DstPoint.y,
|
|
|
|
DstPoint.x+Width-1,
|
|
|
|
DstPoint.y+Height-1),
|
|
|
|
DstRect)) then exit;
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
|
|
|
// Dodatkowo przycinamy docelowy rect
|
|
|
|
if not(DstRect.IntersectsWith(ClipRect, ClippedDstRect)) then
|
|
|
|
Exit;
|
|
|
|
|
2011-06-17 21:12:21 +00:00
|
|
|
// Liczymy offset Ÿród³owego do docelowego recta
|
2011-06-17 20:53:01 +00:00
|
|
|
Offset:=DstPoint - SrcPoint;
|
|
|
|
|
2011-06-17 21:12:21 +00:00
|
|
|
// Sprawdzamy, czy na³o¿one na siebie recty: Ÿród³owy i docelowy przesuniêty o
|
|
|
|
// offset maj¹ jak¹œ czêœæ wspóln¹
|
2011-06-17 20:53:01 +00:00
|
|
|
if not(SrcRect.IntersectsWith(ClippedDstRect - Offset, ClippedSrcRect)) then exit;
|
|
|
|
|
2011-06-17 21:12:21 +00:00
|
|
|
// Jeœli jest cokolwiek do przetworzenia, wykonaj operacjê
|
2011-06-17 20:53:01 +00:00
|
|
|
if (ClippedSrcRect.left<=ClippedSrcRect.right) and (ClippedSrcRect.top<=ClippedSrcRect.bottom) then
|
2011-06-18 12:34:17 +00:00
|
|
|
begin
|
|
|
|
SrcImg := ABuffer.CreateIntfImage;
|
|
|
|
DestImg := ABitmap.CreateIntfImage;
|
2011-06-17 20:53:01 +00:00
|
|
|
for y := ClippedSrcRect.top to ClippedSrcRect.bottom do
|
|
|
|
begin
|
2011-06-18 12:34:17 +00:00
|
|
|
SrcLine:=SrcImg.GetDataLineStart(y);
|
|
|
|
DstLine:=DestImg.GetDataLineStart(y+Offset.y);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2018-02-05 12:05:26 +00:00
|
|
|
Move({%H-}pointer({%H-}PtrInt(SrcLine) + 3*ClippedSrcRect.left)^,
|
|
|
|
{%H-}pointer({%H-}PtrInt(DstLine) + 3*(ClippedSrcRect.left + Offset.x))^,
|
2011-06-17 20:53:01 +00:00
|
|
|
3*ClippedSrcRect.Width);
|
|
|
|
end;
|
2011-06-18 12:34:17 +00:00
|
|
|
ABitmap.LoadFromIntfImage(DestImg);
|
|
|
|
DestImg.Destroy;
|
|
|
|
SrcImg.Destroy;
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.CopyRoundCorner(ABuffer: TBitmap; ABitmap: TBitmap;
|
|
|
|
SrcPoint, DstPoint: T2DIntVector; Radius: integer; CornerPos: TCornerPos;
|
|
|
|
Convex: boolean);
|
|
|
|
|
|
|
|
var BufferRect, BitmapRect : T2DIntRect;
|
|
|
|
OrgSrcRect, OrgDstRect : T2DIntRect;
|
|
|
|
SrcRect : T2DIntRect;
|
|
|
|
Offset : T2DIntVector;
|
|
|
|
Center: T2DIntVector;
|
|
|
|
y: Integer;
|
2011-06-18 12:34:17 +00:00
|
|
|
SrcImg: TLazIntfImage;
|
|
|
|
DestImg: TLazIntfImage;
|
2011-06-17 20:53:01 +00:00
|
|
|
SrcLine: Pointer;
|
|
|
|
DstLine: Pointer;
|
|
|
|
SrcPtr, DstPtr : PByte;
|
|
|
|
x: Integer;
|
|
|
|
Dist : double;
|
|
|
|
|
|
|
|
begin
|
|
|
|
if (ABuffer.PixelFormat<>pf24bit) or (ABitmap.PixelFormat<>pf24bit) then
|
2011-06-17 21:12:21 +00:00
|
|
|
raise exception.create('TSpkGUITools.CopyRoundCorner: Tylko 24-bitowe bitmapy s¹ akceptowane!');
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2011-06-17 21:12:21 +00:00
|
|
|
// Sprawdzanie poprawnoœci
|
2011-06-17 20:53:01 +00:00
|
|
|
if Radius<1 then
|
|
|
|
exit;
|
|
|
|
|
|
|
|
if (ABuffer.width=0) or (ABuffer.height=0) or
|
|
|
|
(ABitmap.width=0) or (ABitmap.height=0) then exit;
|
|
|
|
|
2011-06-18 13:46:52 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
2011-06-17 20:53:01 +00:00
|
|
|
BufferRect:=T2DIntRect.create(0, 0, ABuffer.width-1, ABuffer.height-1);
|
|
|
|
if not(BufferRect.IntersectsWith(T2DIntRect.create(SrcPoint.x,
|
|
|
|
SrcPoint.y,
|
|
|
|
SrcPoint.x+Radius-1,
|
|
|
|
SrcPoint.y+Radius-1),
|
|
|
|
OrgSrcRect)) then exit;
|
|
|
|
|
|
|
|
BitmapRect:=T2DIntRect.create(0, 0, ABitmap.width-1, ABitmap.height-1);
|
|
|
|
if not(BitmapRect.IntersectsWith(T2DIntRect.create(DstPoint.x,
|
|
|
|
DstPoint.y,
|
|
|
|
DstPoint.x+Radius-1,
|
|
|
|
DstPoint.y+Radius-1),
|
|
|
|
OrgDstRect)) then exit;
|
2011-06-18 13:46:52 +00:00
|
|
|
{$ELSE}
|
|
|
|
BufferRect.create(0, 0, ABuffer.width-1, ABuffer.height-1);
|
|
|
|
if not(BufferRect.IntersectsWith(Create2DIntRect(SrcPoint.x,
|
|
|
|
SrcPoint.y,
|
|
|
|
SrcPoint.x+Radius-1,
|
|
|
|
SrcPoint.y+Radius-1),
|
|
|
|
OrgSrcRect)) then exit;
|
|
|
|
|
|
|
|
BitmapRect.create(0, 0, ABitmap.width-1, ABitmap.height-1);
|
|
|
|
if not(BitmapRect.IntersectsWith(Create2DIntRect(DstPoint.x,
|
|
|
|
DstPoint.y,
|
|
|
|
DstPoint.x+Radius-1,
|
|
|
|
DstPoint.y+Radius-1),
|
|
|
|
OrgDstRect)) then exit;
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
|
|
|
Offset:=DstPoint - SrcPoint;
|
|
|
|
|
|
|
|
if not(OrgSrcRect.IntersectsWith(OrgDstRect - Offset, SrcRect)) then exit;
|
|
|
|
|
2011-06-17 21:12:21 +00:00
|
|
|
// Ustalamy pozycjê œrodka ³uku
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2011-06-18 13:46:52 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
2011-06-17 20:53:01 +00:00
|
|
|
case CornerPos of
|
|
|
|
cpLeftTop: Center:=T2DIntVector.create(SrcPoint.x + radius - 1, SrcPoint.y + Radius - 1);
|
|
|
|
cpRightTop: Center:=T2DIntVector.create(SrcPoint.x, SrcPoint.y + Radius - 1);
|
|
|
|
cpLeftBottom: Center:=T2DIntVector.Create(SrcPoint.x + radius - 1, SrcPoint.y);
|
|
|
|
cpRightBottom: Center:=T2DIntVector.Create(SrcPoint.x, SrcPoint.y);
|
|
|
|
end;
|
2011-06-18 13:46:52 +00:00
|
|
|
{$ELSE}
|
|
|
|
case CornerPos of
|
|
|
|
cpLeftTop: Center.create(SrcPoint.x + radius - 1, SrcPoint.y + Radius - 1);
|
|
|
|
cpRightTop: Center.create(SrcPoint.x, SrcPoint.y + Radius - 1);
|
|
|
|
cpLeftBottom: Center.Create(SrcPoint.x + radius - 1, SrcPoint.y);
|
|
|
|
cpRightBottom: Center.Create(SrcPoint.x, SrcPoint.y);
|
|
|
|
end;
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
|
|
|
// Czy jest cokolwiek do przetworzenia?
|
|
|
|
if Convex then
|
|
|
|
begin
|
|
|
|
if (SrcRect.left<=SrcRect.right) and (SrcRect.top<=SrcRect.bottom) then
|
2011-06-18 12:34:17 +00:00
|
|
|
begin
|
|
|
|
SrcImg := ABuffer.CreateIntfImage;
|
|
|
|
DestImg := ABitmap.CreateIntfImage;
|
2011-06-17 20:53:01 +00:00
|
|
|
for y := SrcRect.top to SrcRect.bottom do
|
|
|
|
begin
|
2011-06-18 12:34:17 +00:00
|
|
|
SrcLine:=SrcImg.GetDataLineStart(y);
|
|
|
|
DstLine:=DestImg.GetDataLineStart(y+Offset.y);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2018-02-05 12:05:26 +00:00
|
|
|
SrcPtr:={%H-}pointer({%H-}PtrInt(SrcLine) + 3*SrcRect.left);
|
|
|
|
DstPtr:={%H-}pointer({%H-}PtrInt(DstLine) + 3*(SrcRect.left + Offset.x));
|
2011-06-17 20:53:01 +00:00
|
|
|
for x := SrcRect.left to SrcRect.right do
|
|
|
|
begin
|
2011-06-18 13:46:52 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
2011-06-17 20:53:01 +00:00
|
|
|
Dist:=Center.DistanceTo(T2DVector.create(x, y));
|
2011-06-18 13:46:52 +00:00
|
|
|
{$ELSE}
|
|
|
|
Dist:=Center.DistanceTo(x, y);
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
if Dist <= (Radius-1) then
|
|
|
|
Move(SrcPtr^,DstPtr^,3);
|
|
|
|
|
|
|
|
inc(SrcPtr,3);
|
|
|
|
inc(DstPtr,3);
|
|
|
|
end;
|
|
|
|
end;
|
2011-06-18 12:34:17 +00:00
|
|
|
ABitmap.LoadFromIntfImage(DestImg);
|
|
|
|
SrcImg.Destroy;
|
|
|
|
DestImg.Destroy;
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
if (SrcRect.left<=SrcRect.right) and (SrcRect.top<=SrcRect.bottom) then
|
2011-06-18 12:34:17 +00:00
|
|
|
begin
|
|
|
|
SrcImg := ABuffer.CreateIntfImage;
|
|
|
|
DestImg := ABitmap.CreateIntfImage;
|
2011-06-17 20:53:01 +00:00
|
|
|
for y := SrcRect.top to SrcRect.bottom do
|
|
|
|
begin
|
2011-06-18 12:34:17 +00:00
|
|
|
SrcLine:=SrcImg.GetDataLineStart(y);
|
|
|
|
DstLine:=DestImg.GetDataLineStart(y+Offset.y);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2018-02-05 12:05:26 +00:00
|
|
|
SrcPtr:={%H-}pointer({%H-}PtrInt(SrcLine) + 3*SrcRect.left);
|
|
|
|
DstPtr:={%H-}pointer({%H-}PtrInt(DstLine) + 3*(SrcRect.left + Offset.x));
|
2011-06-17 20:53:01 +00:00
|
|
|
for x := SrcRect.left to SrcRect.right do
|
|
|
|
begin
|
2011-06-18 13:46:52 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
2011-06-17 20:53:01 +00:00
|
|
|
Dist:=Center.DistanceTo(T2DVector.create(x, y));
|
2011-06-18 13:46:52 +00:00
|
|
|
{$ELSE}
|
|
|
|
Dist:=Center.DistanceTo(x, y);
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
if Dist >= (Radius-1) then
|
|
|
|
Move(SrcPtr^,DstPtr^,3);
|
|
|
|
|
|
|
|
inc(SrcPtr,3);
|
|
|
|
inc(DstPtr,3);
|
|
|
|
end;
|
|
|
|
end;
|
2011-06-18 12:34:17 +00:00
|
|
|
ABitmap.LoadFromIntfImage(DestImg);
|
|
|
|
SrcImg.Destroy;
|
|
|
|
DestImg.Destroy;
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawAARoundCorner(ABitmap: TBitmap; Point: T2DIntVector;
|
|
|
|
Radius: integer; CornerPos: TCornerPos; Color: TColor);
|
2014-10-15 22:46:07 +00:00
|
|
|
var
|
|
|
|
CornerRect: T2DIntRect;
|
|
|
|
Center: T2DIntVector;
|
|
|
|
colorR, colorG, colorB: byte;
|
|
|
|
x, y: integer;
|
|
|
|
RadiusDist: double;
|
|
|
|
OrgCornerRect: T2DIntRect;
|
|
|
|
BitmapRect: T2DIntRect;
|
|
|
|
cr, cg, cb: Byte;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2014-10-15 22:46:07 +00:00
|
|
|
if ABitmap.PixelFormat <> pf24bit then
|
|
|
|
raise Exception.Create('TSpkGUITools.DrawAARoundCorner: Bitmapa musi byæ w trybie 24-bitowym!');
|
|
|
|
|
|
|
|
// Sprawdzamy poprawnoϾ
|
|
|
|
if Radius < 1 then
|
|
|
|
exit;
|
|
|
|
if (ABitmap.Width=0) or (ABitmap.Height=0) then
|
|
|
|
exit;
|
|
|
|
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
// �?ród³owy rect...
|
|
|
|
OrgCornerRect := T2DIntRect.Create(Point.x,
|
|
|
|
Point.y,
|
|
|
|
Point.x + radius - 1,
|
|
|
|
Point.y + radius - 1);
|
|
|
|
|
|
|
|
// ...przycinamy do rozmiarów bitmapy
|
|
|
|
BitmapRect := T2DIntRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
{$ELSE}
|
|
|
|
// �?ród³owy rect...
|
|
|
|
OrgCornerRect.Create(Point.x,
|
|
|
|
Point.y,
|
|
|
|
Point.x + radius - 1,
|
|
|
|
Point.y + radius - 1);
|
|
|
|
|
|
|
|
// ...przycinamy do rozmiarów bitmapy
|
|
|
|
BitmapRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
{$ENDIF}
|
|
|
|
|
|
|
|
if not BitmapRect.intersectsWith(OrgCornerRect, CornerRect) then
|
|
|
|
exit;
|
|
|
|
|
|
|
|
// Jeœli nie ma czego rysowaæ, wychodzimy
|
|
|
|
if (CornerRect.Left > CornerRect.Right) or (CornerRect.Top > CornerRect.Bottom) then
|
|
|
|
exit;
|
|
|
|
|
|
|
|
// Szukamy œrodka ³uku - zale¿nie od rodzaju naro¿nika
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
case CornerPos of
|
|
|
|
cpLeftTop:
|
|
|
|
Center := T2DIntVector.Create(Point.x + radius - 1, Point.y + Radius - 1);
|
|
|
|
cpRightTop:
|
|
|
|
Center := T2DIntVector.Create(Point.x, Point.y + Radius - 1);
|
|
|
|
cpLeftBottom:
|
|
|
|
Center := T2DIntVector.Create(Point.x + radius - 1, Point.y);
|
|
|
|
cpRightBottom:
|
|
|
|
Center := T2DIntVector.Create(Point.x, Point.y);
|
|
|
|
end;
|
|
|
|
{$ELSE}
|
|
|
|
case CornerPos of
|
|
|
|
cpLeftTop:
|
|
|
|
Center.Create(Point.x + radius - 1, Point.y + Radius - 1);
|
|
|
|
cpRightTop:
|
|
|
|
Center.Create(Point.x, Point.y + Radius - 1);
|
|
|
|
cpLeftBottom:
|
|
|
|
Center.Create(Point.x + radius - 1, Point.y);
|
|
|
|
cpRightBottom:
|
|
|
|
Center.Create(Point.x, Point.y);
|
|
|
|
end;
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2014-10-15 22:46:07 +00:00
|
|
|
Color := ColorToRGB(Color);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2014-10-15 22:46:07 +00:00
|
|
|
colorR := GetRValue(Color);
|
|
|
|
colorG := GetGValue(Color);
|
|
|
|
colorB := GetBValue(Color);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2014-10-15 22:46:07 +00:00
|
|
|
for y := CornerRect.Top to CornerRect.Bottom do
|
|
|
|
begin
|
|
|
|
for x := CornerRect.Left to CornerRect.Right do
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2014-10-15 22:46:07 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
RadiusDist := 1 - abs((Radius - 1) - Center.DistanceTo(T2DIntVector.create(x, y)));
|
|
|
|
{$ELSE}
|
|
|
|
RadiusDist := 1 - abs((Radius - 1) - Center.DistanceTo(x, y));
|
|
|
|
{$ENDIF}
|
|
|
|
if RadiusDist > 0 then
|
|
|
|
begin
|
|
|
|
RedGreenBlue(ColorToRGB(ABitmap.Canvas.Pixels[x,y]), cr, cg, cb);
|
|
|
|
cb := round(cb + (ColorB - cb) * RadiusDist);
|
|
|
|
cg := round(cg + (ColorG - cg) * RadiusDist);
|
|
|
|
cr := round(cr + (ColorR - cr) * RadiusDist);
|
|
|
|
ABitmap.Canvas.Pixels[x,y] := RGBToColor(cr,cg,cb);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
2014-10-15 22:46:07 +00:00
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawAARoundCorner(ABitmap: TBitmap;
|
|
|
|
Point: T2DIntVector; Radius: integer; CornerPos: TCornerPos; Color: TColor;
|
|
|
|
ClipRect: T2DIntRect);
|
2014-10-15 22:46:07 +00:00
|
|
|
var
|
|
|
|
CornerRect: T2DIntRect;
|
|
|
|
Center: T2DIntVector;
|
|
|
|
colorR, colorG, colorB: byte;
|
|
|
|
x, y: integer;
|
|
|
|
RadiusDist: double;
|
|
|
|
OrgCornerRect: T2DIntRect;
|
|
|
|
UnClippedCornerRect : T2DIntRect;
|
|
|
|
BitmapRect: T2DIntRect;
|
|
|
|
cr,cb,cg: byte;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2014-10-15 22:46:07 +00:00
|
|
|
if ABitmap.PixelFormat<>pf24bit then
|
2017-10-12 17:48:39 +00:00
|
|
|
raise Exception.Create('TSpkGUITools.DrawAARoundCorner: Bitmap must be in 24-bit mode!');
|
2014-10-15 22:46:07 +00:00
|
|
|
|
|
|
|
if Radius < 1 then
|
|
|
|
exit;
|
2017-10-12 17:48:39 +00:00
|
|
|
if (ABitmap.Width = 0) or (ABitmap.Height = 0) then
|
2014-10-15 22:46:07 +00:00
|
|
|
exit;
|
|
|
|
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
2017-10-12 17:48:39 +00:00
|
|
|
// Source rect...
|
|
|
|
OrgCornerRect := T2DIntRect.Create(
|
|
|
|
Point.x, Point.y, Point.x + radius - 1, Point.y + radius - 1
|
|
|
|
);
|
|
|
|
// ... cut to size bitmap
|
|
|
|
BitmapRect := T2DIntRect.Create(
|
|
|
|
0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
2014-10-15 22:46:07 +00:00
|
|
|
{$ELSE}
|
2017-10-12 17:48:39 +00:00
|
|
|
// Source rect...
|
2014-10-15 22:46:07 +00:00
|
|
|
OrgCornerRect.Create(Point.x,
|
|
|
|
Point.y,
|
|
|
|
Point.x + radius - 1,
|
|
|
|
Point.y + radius - 1);
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// ... cut to size bitmap
|
2014-10-15 22:46:07 +00:00
|
|
|
BitmapRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
{$ENDIF}
|
|
|
|
|
|
|
|
if not BitmapRect.IntersectsWith(OrgCornerRect, UnClippedCornerRect) then
|
|
|
|
exit;
|
|
|
|
|
|
|
|
// ClipRect
|
|
|
|
if not UnClippedCornerRect.IntersectsWith(ClipRect, CornerRect) then
|
|
|
|
exit;
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// If there is nothing to draw, we leave
|
|
|
|
if (CornerRect.Left > CornerRect.Right) or
|
|
|
|
(CornerRect.Top > CornerRect.Bottom)
|
|
|
|
then
|
2014-10-15 22:46:07 +00:00
|
|
|
exit;
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// We seek the center of the arc - depending on the type of corner
|
2014-10-15 22:46:07 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
case CornerPos of
|
|
|
|
cpLeftTop:
|
|
|
|
Center := T2DIntVector.Create(Point.x + radius - 1, Point.y + Radius - 1);
|
|
|
|
cpRightTop:
|
|
|
|
Center := T2DIntVector.Create(Point.x, Point.y + Radius - 1);
|
|
|
|
cpLeftBottom:
|
|
|
|
Center := T2DIntVector.Create(Point.x + radius - 1, Point.y);
|
|
|
|
cpRightBottom:
|
|
|
|
Center := T2DIntVector.Create(Point.x, Point.y);
|
|
|
|
end;
|
|
|
|
{$ELSE}
|
|
|
|
case CornerPos of
|
|
|
|
cpLeftTop:
|
|
|
|
Center.Create(Point.x + radius - 1, Point.y + Radius - 1);
|
|
|
|
cpRightTop:
|
|
|
|
Center.Create(Point.x, Point.y + Radius - 1);
|
|
|
|
cpLeftBottom:
|
|
|
|
Center.Create(Point.x + radius - 1, Point.y);
|
|
|
|
cpRightBottom:
|
|
|
|
Center.Create(Point.x, Point.y);
|
|
|
|
end;
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2014-10-15 22:46:07 +00:00
|
|
|
Color := ColorToRGB(Color);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2014-10-15 22:46:07 +00:00
|
|
|
colorR := GetRValue(Color);
|
|
|
|
colorG := GetGValue(Color);
|
|
|
|
colorB := GetBValue(Color);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2014-10-15 22:46:07 +00:00
|
|
|
for y := CornerRect.Top to CornerRect.Bottom do
|
|
|
|
begin
|
|
|
|
for x := CornerRect.Left to CornerRect.Right do
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2014-10-15 22:46:07 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
RadiusDist := 1 - abs((Radius - 1) - Center.DistanceTo(T2DIntVector.create(x, y)));
|
|
|
|
{$ELSE}
|
|
|
|
RadiusDist := 1 - abs((Radius - 1) - Center.DistanceTo(x, y));
|
|
|
|
{$ENDIF}
|
|
|
|
if RadiusDist > 0 then
|
|
|
|
begin
|
|
|
|
RedGreenBlue(ColorToRGB(ABitmap.Canvas.Pixels[x,y]), cr, cg, cb);
|
|
|
|
cb := round(cb + (ColorB - cb) * RadiusDist);
|
|
|
|
cg := round(cg + (ColorG - cg) * RadiusDist);
|
|
|
|
cr := round(cr + (ColorR - cr) * RadiusDist);
|
|
|
|
ABitmap.Canvas.Pixels[x,y] := RGBToColor(cr,cg,cb);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
2014-10-15 22:46:07 +00:00
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawAARoundCorner(ACanvas: TCanvas;
|
|
|
|
Point: T2DIntVector; Radius: integer; CornerPos: TCornerPos; Color: TColor);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
Center: T2DIntVector;
|
|
|
|
OrgColor: TColor;
|
|
|
|
x, y: integer;
|
|
|
|
RadiusDist: double;
|
|
|
|
CornerRect: T2DIntRect;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if Radius<1 then
|
|
|
|
exit;
|
2011-06-18 13:46:52 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
// Source rect
|
|
|
|
CornerRect := T2DIntRect.Create(
|
|
|
|
Point.x, Point.y, Point.x + radius - 1, Point.y + radius - 1
|
|
|
|
);
|
|
|
|
// We seek the center of the arc - depending on the type of corner
|
|
|
|
case CornerPos of
|
|
|
|
cpLeftTop:
|
|
|
|
Center := T2DIntVector.Create(Point.x + radius - 1, Point.y + Radius - 1);
|
|
|
|
cpRightTop:
|
|
|
|
Center := T2DIntVector.Create(Point.x, Point.y + Radius - 1);
|
|
|
|
cpLeftBottom:
|
|
|
|
Center := T2DIntVector.Create(Point.x + radius - 1, Point.y);
|
|
|
|
cpRightBottom:
|
|
|
|
Center := T2DIntVector.Create(Point.x, Point.y);
|
|
|
|
end;
|
|
|
|
{$ELSE}
|
|
|
|
// Source rect
|
|
|
|
CornerRect.Create(Point.x, Point.y, Point.x + radius - 1, Point.y + radius - 1);
|
|
|
|
// We seek the center of the arc - depending on the type of corner
|
|
|
|
case CornerPos of
|
|
|
|
cpLeftTop:
|
|
|
|
Center.Create(Point.x + radius - 1, Point.y + Radius - 1);
|
|
|
|
cpRightTop:
|
|
|
|
Center.Create(Point.x, Point.y + Radius - 1);
|
|
|
|
cpLeftBottom:
|
|
|
|
Center.Create(Point.x + radius - 1, Point.y);
|
|
|
|
cpRightBottom:
|
|
|
|
Center.Create(Point.x, Point.y);
|
|
|
|
end;
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
Color := ColorToRGB(Color);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
for y := CornerRect.Top to CornerRect.Bottom do
|
|
|
|
begin
|
|
|
|
for x := CornerRect.Left to CornerRect.Right do
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
RadiusDist := 1 - abs((Radius - 1) - Center.DistanceTo(T2DIntVector.Create(x, y)));
|
|
|
|
{$ELSE}
|
|
|
|
RadiusDist := 1 - abs((Radius - 1) - Center.DistanceTo(x, y));
|
|
|
|
{$ENDIF}
|
|
|
|
if RadiusDist > 0 then
|
|
|
|
begin
|
|
|
|
OrgColor := ACanvas.Pixels[x, y];
|
|
|
|
ACanvas.Pixels[x, y] := TColorTools.Shade(OrgColor, Color, RadiusDist);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
2017-10-12 17:48:39 +00:00
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawAARoundCorner(ACanvas: TCanvas;
|
|
|
|
Point: T2DIntVector; Radius: integer; CornerPos: TCornerPos; Color: TColor;
|
|
|
|
ClipRect: T2DIntRect);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
UseOrgClipRgn: boolean;
|
|
|
|
ClipRgn: HRGN;
|
|
|
|
OrgRgn: HRGN;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
// Store the original ClipRgn and set a new one
|
|
|
|
SaveClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ClipRgn := CreateRectRgn(ClipRect.Left, ClipRect.Top, ClipRect.Right+1, ClipRect.Bottom+1);
|
|
|
|
if UseOrgClipRgn then
|
|
|
|
CombineRgn(ClipRgn, ClipRgn, OrgRgn, RGN_AND);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
SelectClipRgn(ACanvas.Handle, ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
DrawAARoundCorner(ACanvas, Point, Radius, CornerPos, Color);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Restores previous ClipRgn and removes used regions
|
|
|
|
RestoreClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
DeleteObject(ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawAARoundFrame(ABitmap: TBitmap; Rect: T2DIntRect;
|
|
|
|
Radius: integer; Color: TColor; ClipRect: T2DIntRect);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if ABitmap.PixelFormat <> pf24Bit then
|
|
|
|
raise Exception.Create('TGUITools.DrawAARoundFrame: Bitmap must be in 24-bit mode!');
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if Radius < 1 then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (Radius > Rect.Width div 2) or (Radius > Rect.Height div 2) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// DrawAARoundCorner is protected against drawing outside the area
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
DrawAARoundCorner(ABitmap, T2DIntVector.Create(Rect.Left, Rect.Top), Radius, cpLeftTop, Color, ClipRect);
|
|
|
|
DrawAARoundCorner(ABitmap, T2DIntVector.Create(Rect.Right - Radius + 1, Rect.Top), Radius, cpRightTop, Color, ClipRect);
|
|
|
|
DrawAARoundCorner(ABitmap, T2DIntVector.Create(Rect.Left, Rect.Bottom - Radius + 1), Radius, cpLeftBottom, Color, ClipRect);
|
|
|
|
DrawAARoundCorner(ABitmap, T2DIntVector.Create(Rect.Right - Radius + 1, Rect.Bottom - Radius + 1), Radius, cpRightBottom, Color, ClipRect);
|
|
|
|
{$ELSE}
|
|
|
|
DrawAARoundCorner(ABitmap, Create2DIntVector(Rect.Left, Rect.Top), Radius, cpLeftTop, Color, ClipRect);
|
|
|
|
DrawAARoundCorner(ABitmap, Create2DIntVector(Rect.Right - Radius + 1, Rect.Top), Radius, cpRightTop, Color, ClipRect);
|
|
|
|
DrawAARoundCorner(ABitmap, Create2DIntVector(Rect.Left, Rect.Bottom - Radius + 1), Radius, cpLeftBottom, Color, ClipRect);
|
|
|
|
DrawAARoundCorner(ABitmap, Create2DIntVector(Rect.Right - Radius + 1, Rect.Bottom - Radius + 1), Radius, cpRightBottom, Color, ClipRect);
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ABitmap.Canvas.Pen.Color := Color;
|
|
|
|
ABitmap.Canvas.pen.Style := psSolid;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Draw*Line is protected against drawing outside the area
|
|
|
|
DrawVLine(ABitmap, Rect.Left, Rect.top + Radius, Rect.Bottom - Radius, Color, ClipRect);
|
|
|
|
DrawVLine(ABitmap, Rect.Right, Rect.top + Radius, Rect.Bottom - Radius, Color, ClipRect);
|
|
|
|
DrawHLine(ABitmap, Rect.Left + Radius, Rect.Right - Radius, Rect.Top, Color, ClipRect);
|
|
|
|
DrawHLine(ABitmap, Rect.Left + Radius, Rect.Right - Radius, Rect.Bottom, Color, ClipRect);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawAARoundFrame(ABitmap: TBitmap; Rect: T2DIntRect;
|
|
|
|
Radius: integer; Color: TColor);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if ABitmap.PixelFormat <> pf24Bit then
|
|
|
|
raise Exception.Create('TGUITools.DrawAARoundFrame: Bitmap must be in 24-bit mode!');
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if Radius < 1 then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (Radius > Rect.Width div 2) or (Radius > Rect.Height div 2) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// DrawAARoundCorner is protected against drawing outside the area
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
DrawAARoundCorner(ABitmap, T2DIntVector.Create(Rect.Left, Rect.Top), Radius, cpLeftTop, Color);
|
|
|
|
DrawAARoundCorner(ABitmap, T2DIntVector.Create(Rect.Right - Radius + 1, Rect.Top), Radius, cpRightTop, Color);
|
|
|
|
DrawAARoundCorner(ABitmap, T2DIntVector.Create(Rect.Left, Rect.Bottom - Radius + 1), Radius, cpLeftBottom, Color);
|
|
|
|
DrawAARoundCorner(ABitmap, T2DIntVector.Create(Rect.Right - Radius + 1, Rect.Bottom - Radius + 1), Radius, cpRightBottom, Color);
|
|
|
|
{$ELSE}
|
|
|
|
DrawAARoundCorner(ABitmap, Create2DIntVector(Rect.Left, Rect.Top), Radius, cpLeftTop, Color);
|
|
|
|
DrawAARoundCorner(ABitmap, Create2DIntVector(Rect.Right - Radius + 1, Rect.top), Radius, cpRightTop, Color);
|
|
|
|
DrawAARoundCorner(ABitmap, Create2DIntVector(Rect.Left, Rect.Bottom - Radius + 1), Radius, cpLeftBottom, Color);
|
|
|
|
DrawAARoundCorner(ABitmap, Create2DIntVector(Rect.Right - Radius + 1, Rect.Bottom - Radius + 1), Radius, cpRightBottom, Color);
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ABitmap.Canvas.Pen.Color := Color;
|
|
|
|
ABitmap.Canvas.pen.Style := psSolid;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Draw*Line is protected against drawing outside the area
|
|
|
|
DrawVLine(ABitmap, Rect.Left, Rect.Top + Radius, Rect.bottom - Radius, Color);
|
|
|
|
DrawVLine(ABitmap, Rect.Right, Rect.Top + Radius, Rect.bottom - Radius, Color);
|
|
|
|
DrawHLine(ABitmap, Rect.Left + Radius, Rect.Right - Radius, Rect.Top, Color);
|
|
|
|
DrawHLine(ABitmap, Rect.Left + Radius, Rect.Right - Radius, Rect.Bottom, Color);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawFitWText(ABitmap: TBitmap; x1, x2, y: integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText: string; TextColor: TColor; Align : TAlignment);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
tw: integer;
|
|
|
|
s: string;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
with ABitmap.Canvas do
|
|
|
|
begin
|
2018-02-05 12:05:26 +00:00
|
|
|
Font.Color := TextColor;
|
2017-10-12 17:48:39 +00:00
|
|
|
s := AText;
|
|
|
|
tw := TextWidth(s);
|
|
|
|
if tw <= x2-x1+1 then
|
|
|
|
case Align of
|
|
|
|
taLeftJustify : TextOut(x1,y,AText);
|
|
|
|
taRightJustify : TextOut(x2-tw+1,y,AText);
|
|
|
|
taCenter : TextOut(x1 + ((x2-x1 - tw) div 2), y, AText);
|
|
|
|
end else
|
|
|
|
begin
|
|
|
|
while (s <> '') and (tw > x2-x1+1) do
|
|
|
|
begin
|
|
|
|
Delete(s, Length(s), 1);
|
|
|
|
tw := TextWidth(s+'...');
|
|
|
|
end;
|
|
|
|
if tw <= x2-x1+1 then
|
|
|
|
TextOut(x1, y, s+'...');
|
|
|
|
end;
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawHLine(ACanvas: TCanvas; x1, x2, y: integer;
|
|
|
|
Color: TColor);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
EnsureOrder(x1, x2);
|
|
|
|
ACanvas.Pen.Color := Color;
|
|
|
|
ACanvas.MoveTo(x1, y);
|
|
|
|
ACanvas.LineTo(x2+1,y);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawHLine(ACanvas: TCanvas; x1, x2, y: integer;
|
|
|
|
Color: TColor; ClipRect: T2DIntRect);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
UseOrgClipRgn: boolean;
|
|
|
|
ClipRgn: HRGN;
|
|
|
|
OrgRgn: HRGN;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
// Store the original ClipRgn and set a new one
|
|
|
|
SaveClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ClipRgn := CreateRectRgn(ClipRect.left, ClipRect.Top, ClipRect.Right+1, ClipRect.Bottom+1);
|
|
|
|
if UseOrgClipRgn then
|
|
|
|
CombineRgn(ClipRgn, ClipRgn, OrgRgn, RGN_AND);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
SelectClipRgn(ACanvas.Handle, ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
DrawHLine(ACanvas, x1, x2, y, Color);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Restores previous ClipRgn and removes used regions
|
|
|
|
RestoreClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
DeleteObject(ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawImage(ABitmap: TBitmap; Imagelist: TImageList;
|
|
|
|
ImageIndex: integer; Point : T2DIntVector; ClipRect: T2DIntRect);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
DrawImage(ABitmap.Canvas, ImageList, ImageIndex, Point, ClipRect);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawImage(ABitmap: TBitmap; Imagelist: TImageList;
|
|
|
|
ImageIndex: integer; Point: T2DIntVector);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
DrawImage(ABitmap.Canvas, ImageList, ImageIndex, Point);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawImage(ACanvas: TCanvas; Imagelist: TImageList;
|
|
|
|
ImageIndex: integer; Point : T2DIntVector; ClipRect: T2DIntRect);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
UseOrgClipRgn: Boolean;
|
|
|
|
OrgRgn: HRGN;
|
|
|
|
ClipRgn: HRGN;
|
|
|
|
//ImageIcon: TIcon; // wp: no longer needed -- see below
|
|
|
|
ImageBitmap: TBitmap;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
// Storing original ClipRgn and applying a new one
|
|
|
|
SaveClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ClipRgn := CreateRectRgn(ClipRect.left, ClipRect.Top, ClipRect.Right+1, ClipRect.Bottom+1);
|
|
|
|
if UseOrgClipRgn then
|
|
|
|
CombineRgn(ClipRgn, ClipRgn, OrgRgn, RGN_AND);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
SelectClipRgn(ACanvas.Handle, ClipRgn);
|
2018-02-10 00:38:06 +00:00
|
|
|
ImageList.Draw(ACanvas, Point.X, Point.Y, ImageIndex);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2018-02-10 00:38:06 +00:00
|
|
|
(*
|
2017-10-12 17:48:39 +00:00
|
|
|
{ wp: Next part fixes issue https://sourceforge.net/p/lazarus-ccr/bugs/35/ }
|
|
|
|
ImageBitmap := TBitmap.Create;
|
|
|
|
ImageList.GetBitmap(ImageIndex, ImageBitmap);
|
|
|
|
ACanvas.Draw(Point.x, Point.y, ImageBitmap);
|
|
|
|
ImageBitmap.Free;
|
2018-02-10 00:38:06 +00:00
|
|
|
*)
|
2017-10-12 10:37:39 +00:00
|
|
|
|
|
|
|
{ wp: The following lines were removed and replaced by the "ImageBitmap" lines
|
|
|
|
above in order to fix the "handle leak" of
|
|
|
|
https://sourceforge.net/p/lazarus-ccr/bugs/35/
|
|
|
|
Not daring to touch the ImageList.Draw which would have worked as well. }
|
2018-02-05 12:05:26 +00:00
|
|
|
(*
|
2017-10-12 17:48:39 +00:00
|
|
|
// avoid exclusive draw. draw with local canvas itself.
|
|
|
|
//ImageList.Draw(ACanvas, Point.x, Point.y, ImageIndex);
|
|
|
|
{$IfDef LCLWin32}
|
|
|
|
ImageIcon := TIcon.Create;
|
|
|
|
ImageList.GetIcon(ImageIndex, ImageIcon);
|
|
|
|
ACanvas.Draw(Point.x, Point.y, ImageIcon);
|
|
|
|
ImageIcon.Free;
|
|
|
|
{$Else}
|
|
|
|
ImageBitmap := TBitmap.Create;
|
|
|
|
ImageList.GetBitmap(ImageIndex, ImageBitmap);
|
|
|
|
ACanvas.Draw(Point.x, Point.y, ImageBitmap);
|
|
|
|
ImageBitmap.Free;
|
|
|
|
{$EndIf}
|
2018-02-05 12:05:26 +00:00
|
|
|
*)
|
2017-10-12 17:48:39 +00:00
|
|
|
RestoreClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
DeleteObject(ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
2018-02-10 00:38:06 +00:00
|
|
|
class procedure TGUITools.DrawImage(ACanvas: TCanvas; Imagelist: TImageList;
|
|
|
|
ImageIndex: integer; Point : T2DIntVector; ClipRect: T2DIntRect;
|
|
|
|
AImageWidthAt96PPI, ATargetPPI: Integer; ACanvasFactor: Double);
|
|
|
|
var
|
|
|
|
UseOrgClipRgn: Boolean;
|
|
|
|
OrgRgn: HRGN;
|
|
|
|
ClipRgn: HRGN;
|
|
|
|
//ImageIcon: TIcon; // wp: no longer needed -- see below
|
|
|
|
ImageBitmap: TBitmap;
|
|
|
|
begin
|
|
|
|
// Storing original ClipRgn and applying a new one
|
|
|
|
SaveClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
|
|
|
|
ClipRgn := CreateRectRgn(ClipRect.left, ClipRect.Top, ClipRect.Right+1, ClipRect.Bottom+1);
|
|
|
|
if UseOrgClipRgn then
|
|
|
|
CombineRgn(ClipRgn, ClipRgn, OrgRgn, RGN_AND);
|
|
|
|
|
|
|
|
SelectClipRgn(ACanvas.Handle, ClipRgn);
|
|
|
|
|
|
|
|
{$IF LCL_FULLVERSION >= 1090000}
|
|
|
|
ImageList.DrawForPPI(ACanvas, Point.X, Point.Y, ImageIndex,
|
|
|
|
AImageWidthAt96PPI, ATargetPPI, ACanvasFactor);
|
|
|
|
{$ELSE}
|
|
|
|
ImageList.Draw(ACanvas, Point.X, Point.Y, ImageIndex);
|
|
|
|
{$ENDIF}
|
|
|
|
|
|
|
|
(*
|
|
|
|
{ wp: Next part fixes issue https://sourceforge.net/p/lazarus-ccr/bugs/35/ }
|
|
|
|
ImageBitmap := TBitmap.Create;
|
|
|
|
ImageList.GetBitmap(ImageIndex, ImageBitmap);
|
|
|
|
ACanvas.Draw(Point.x, Point.y, ImageBitmap);
|
|
|
|
ImageBitmap.Free;
|
|
|
|
*)
|
|
|
|
|
|
|
|
{ wp: The following lines were removed and replaced by the "ImageBitmap" lines
|
|
|
|
above in order to fix the "handle leak" of
|
|
|
|
https://sourceforge.net/p/lazarus-ccr/bugs/35/
|
|
|
|
Not daring to touch the ImageList.Draw which would have worked as well. }
|
|
|
|
(*
|
|
|
|
// avoid exclusive draw. draw with local canvas itself.
|
|
|
|
//ImageList.Draw(ACanvas, Point.x, Point.y, ImageIndex);
|
|
|
|
{$IfDef LCLWin32}
|
|
|
|
ImageIcon := TIcon.Create;
|
|
|
|
ImageList.GetIcon(ImageIndex, ImageIcon);
|
|
|
|
ACanvas.Draw(Point.x, Point.y, ImageIcon);
|
|
|
|
ImageIcon.Free;
|
|
|
|
{$Else}
|
|
|
|
ImageBitmap := TBitmap.Create;
|
|
|
|
ImageList.GetBitmap(ImageIndex, ImageBitmap);
|
|
|
|
ACanvas.Draw(Point.x, Point.y, ImageBitmap);
|
|
|
|
ImageBitmap.Free;
|
|
|
|
{$EndIf}
|
|
|
|
*)
|
|
|
|
RestoreClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
DeleteObject(ClipRgn);
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2011-06-18 13:46:52 +00:00
|
|
|
class procedure TGUITools.DrawMarkedText(ACanvas: TCanvas; x, y: integer; const AText,
|
2011-06-17 20:53:01 +00:00
|
|
|
AMarkPhrase: string; TextColor : TColor; ClipRect: T2DIntRect; CaseSensitive: boolean);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
UseOrgClipRgn: Boolean;
|
2018-02-05 12:05:26 +00:00
|
|
|
OrgRgn: HRGN = 0;
|
|
|
|
ClipRgn: HRGN = 0;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
// Store the original ClipRgn and set a new one
|
|
|
|
SaveClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ClipRgn := CreateRectRgn(ClipRect.left, ClipRect.Top, ClipRect.Right+1, ClipRect.Bottom+1);
|
|
|
|
if UseOrgClipRgn then
|
|
|
|
CombineRgn(ClipRgn, ClipRgn, OrgRgn, RGN_AND);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
SelectClipRgn(ACanvas.Handle, ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
DrawMarkedText(ACanvas, x, y, AText, AMarkPhrase, TextColor, CaseSensitive);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
RestoreClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
DeleteObject(ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
2011-06-18 13:46:52 +00:00
|
|
|
class procedure TGUITools.DrawMarkedText(ACanvas: TCanvas; x, y: integer; const AText,
|
2011-06-17 20:53:01 +00:00
|
|
|
AMarkPhrase: string; TextColor : TColor; CaseSensitive : boolean);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
TextToDraw: string;
|
|
|
|
BaseText: string;
|
|
|
|
MarkText: string;
|
|
|
|
MarkPos: Integer;
|
|
|
|
x1: integer;
|
|
|
|
s: string;
|
|
|
|
MarkTextLength: Integer;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
TextToDraw := AText;
|
|
|
|
if CaseSensitive then
|
|
|
|
begin
|
|
|
|
BaseText := AText;
|
|
|
|
MarkText := AMarkPhrase;
|
|
|
|
end else
|
|
|
|
begin
|
|
|
|
BaseText := AnsiUpperCase(AText);
|
|
|
|
MarkText := AnsiUpperCase(AMarkPhrase);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
x1 := x;
|
|
|
|
MarkTextLength := Length(MarkText);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ACanvas.Font.Color := TextColor;
|
|
|
|
ACanvas.Brush.Style := bsClear;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
MarkPos := pos(MarkText, BaseText);
|
|
|
|
while MarkPos > 0 do
|
|
|
|
begin
|
|
|
|
if MarkPos > 1 then
|
|
|
|
begin
|
|
|
|
// Drawing text before highlighted
|
|
|
|
ACanvas.Font.Style := ACanvas.Font.Style - [fsBold];
|
|
|
|
s := copy(TextToDraw, 1, MarkPos-1);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ACanvas.TextOut(x1, y, s);
|
|
|
|
inc(x1, ACanvas.TextWidth(s)+1);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
Delete(TextToDraw, 1, MarkPos-1);
|
|
|
|
Delete(BaseText, 1, MarkPos-1);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Drawing highlighted text
|
|
|
|
ACanvas.Font.Style := ACanvas.Font.Style + [fsBold];
|
|
|
|
s := copy(TextToDraw, 1, MarkTextLength);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ACanvas.TextOut(x1, y, s);
|
|
|
|
inc(x1, ACanvas.TextWidth(s)+1);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
Delete(TextToDraw, 1, MarkTextLength);
|
|
|
|
Delete(BaseText, 1, MarkTextLength);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
MarkPos := pos(MarkText, BaseText);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if Length(BaseText) > 0 then
|
|
|
|
begin
|
|
|
|
ACanvas.Font.Style := ACanvas.Font.Style - [fsBold];
|
|
|
|
ACanvas.TextOut(x1, y, TextToDraw);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawImage(ACanvas: TCanvas; Imagelist: TImageList;
|
|
|
|
ImageIndex: integer; Point: T2DIntVector);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
ImageList.Draw(ACanvas, Point.x, Point.y, ImageIndex);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawOutlinedText(ACanvas: TCanvas; x, y: integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText: string; TextColor, OutlineColor: TColor);
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
with ACanvas do
|
|
|
|
begin
|
|
|
|
Brush.Style := bsClear;
|
|
|
|
Font.Color := OutlineColor;
|
|
|
|
TextOut(x-1, y-1, AText);
|
|
|
|
TextOut(x, y-1, AText);
|
|
|
|
TextOut(x+1, y-1, AText);
|
|
|
|
TextOut(x-1, y, AText);
|
|
|
|
TextOut(x+1, y, AText);
|
|
|
|
TextOut(x-1, y+1, AText);
|
|
|
|
TextOut(x, y+1, AText);
|
|
|
|
TextOut(x+1, y+1, AText);
|
|
|
|
|
|
|
|
Font.Color := TextColor;
|
|
|
|
TextOut(x, y, AText);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawOutlinedText(ACanvas: TCanvas; x, y: integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText: string; TextColor, OutlineColor: TColor; ClipRect: T2DIntRect);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
WinAPIClipRect: TRect;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
WinAPIClipRect := ClipRect.ForWinAPI;
|
|
|
|
with ACanvas do
|
|
|
|
begin
|
|
|
|
Brush.Style := bsClear;
|
|
|
|
Font.Color := OutlineColor;
|
|
|
|
TextRect(WinAPIClipRect, x-1, y-1, AText);
|
|
|
|
TextRect(WinAPIClipRect, x, y-1, AText);
|
|
|
|
TextRect(WinAPIClipRect, x+1, y-1, AText);
|
|
|
|
TextRect(WinAPIClipRect, x-1, y, AText);
|
|
|
|
TextRect(WinAPIClipRect, x+1, y, AText);
|
|
|
|
TextRect(WinAPIClipRect, x-1, y+1, AText);
|
|
|
|
TextRect(WinAPIClipRect, x, y+1, AText);
|
|
|
|
TextRect(WinAPIClipRect, x+1, y+1, AText);
|
|
|
|
|
|
|
|
Font.Color := TextColor;
|
|
|
|
TextRect(WinAPIClipRect, x, y, AText);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawHLine(ABitmap: TBitmap; x1, x2, y: integer;
|
|
|
|
Color: TColor);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
LineRect: T2DIntRect;
|
|
|
|
BitmapRect: T2DIntRect;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if ABitmap.PixelFormat <> pf24Bit then
|
|
|
|
raise Exception.Create('TGUITools.DrawHLine: Bitmap must be in 24-bit mode');
|
|
|
|
EnsureOrder(x1, x2);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
BitmapRect := T2DIntRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
if not BitmapRect.IntersectsWith(T2DIntRect.Create(x1, y, x2, y), LineRect) then
|
|
|
|
exit;
|
|
|
|
{$ELSE}
|
|
|
|
BitmapRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
if not BitmapRect.IntersectsWith(Create2DIntRect(x1, y, x2, y), LineRect) then
|
|
|
|
exit;
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ABitmap.Canvas.Pen.Color := Color;
|
|
|
|
ABitmap.Canvas.Pen.Style := psSolid;
|
|
|
|
ABitmap.Canvas.MoveTo(LineRect.Left, LineRect.Top);
|
|
|
|
ABitmap.canvas.LineTo(LineRect.Right+1, LineRect.Top);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawHLine(ABitmap: TBitmap; x1, x2, y: integer;
|
|
|
|
Color: TColor; ClipRect: T2DIntRect);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
OrgLineRect: T2DIntRect;
|
|
|
|
LineRect: T2DIntRect;
|
|
|
|
BitmapRect: T2DIntRect;
|
|
|
|
begin
|
|
|
|
if ABitmap.PixelFormat<>pf24bit then
|
|
|
|
raise Exception.Create('TGUITools.DrawHLine: Bitmap must be in 24-bit mode!');
|
|
|
|
EnsureOrder(x1, x2);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
BitmapRect := T2DIntRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
if not BitmapRect.IntersectsWith(T2DIntRect.Create(x1, y, x2, y), OrgLineRect) then
|
|
|
|
exit;
|
|
|
|
{$ELSE}
|
|
|
|
BitmapRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
if not BitmapRect.IntersectsWith(Create2DIntRect(x1, y, x2, y), OrgLineRect) then
|
|
|
|
exit;
|
|
|
|
{$ENDIF}
|
|
|
|
|
|
|
|
if not OrgLineRect.IntersectsWith(ClipRect, LineRect) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ABitmap.Canvas.Pen.Color := Color;
|
|
|
|
ABitmap.Canvas.Pen.Style := psSolid;
|
|
|
|
ABitmap.Canvas.MoveTo(LineRect.Left, LineRect.Top);
|
|
|
|
ABitmap.Canvas.LineTo(LineRect.Right+1, LineRect.Top);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawOutlinedText(ABitmap: TBitmap; x, y: integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText: string; TextColor, OutlineColor: TColor; ClipRect: T2DIntRect);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
WinAPIClipRect: TRect;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
WinAPIClipRect := ClipRect.ForWinAPI;
|
|
|
|
with ABitmap.canvas do
|
|
|
|
begin
|
|
|
|
Brush.Style := bsClear;
|
|
|
|
Font.Color := OutlineColor;
|
|
|
|
TextRect(WinAPIClipRect, x-1, y-1, AText);
|
|
|
|
TextRect(WinAPIClipRect, x, y-1, AText);
|
|
|
|
TextRect(WinAPIClipRect, x+1, y-1, AText);
|
|
|
|
TextRect(WinAPIClipRect, x-1, y, AText);
|
|
|
|
TextRect(WinAPIClipRect, x+1, y, AText);
|
|
|
|
TextRect(WinAPIClipRect, x-1, y+1, AText);
|
|
|
|
TextRect(WinAPIClipRect, x, y+1, AText);
|
|
|
|
TextRect(WinAPIClipRect, x+1, y+1, AText);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
Font.Color := TextColor;
|
|
|
|
TextRect(WinAPIClipRect, x, y, AText);
|
|
|
|
end;
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
class procedure TGUITools.DrawRegion(ACanvas: TCanvas; Region: HRGN;
|
|
|
|
Rect : T2DIntRect; ColorFrom, ColorTo: TColor; GradientKind: TBackgroundKind);
|
|
|
|
var
|
|
|
|
UseOrgClipRgn: Boolean;
|
|
|
|
OrgRgn: HRGN;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
// Store the original ClipRgn and set a new one
|
|
|
|
SaveClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
SelectClipRgn(ACanvas.Handle, Region);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
FillGradientRectangle(ACanvas, Rect, ColorFrom, ColorTo, GradientKind);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
RestoreClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
class procedure TGUITools.DrawRegion(ACanvas: TCanvas; Region: HRGN;
|
|
|
|
Rect : T2DIntRect; ColorFrom, ColorTo: TColor; GradientKind: TBackgroundKind;
|
|
|
|
ClipRect: T2DIntRect);
|
|
|
|
var
|
|
|
|
UseOrgClipRgn: boolean;
|
|
|
|
ClipRgn: HRGN;
|
|
|
|
OrgRgn: HRGN;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
// Store the original ClipRgn and set a new one
|
|
|
|
SaveClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ClipRgn := CreateRectRgn(ClipRect.left, ClipRect.Top, ClipRect.Right+1, ClipRect.Bottom+1);
|
|
|
|
if UseOrgClipRgn then
|
|
|
|
CombineRgn(ClipRgn, ClipRgn, OrgRgn, RGN_AND);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
SelectClipRgn(ACanvas.Handle, ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
DrawRegion(ACanvas, Region, Rect, ColorFrom, ColorTo, GradientKind);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Restores previous ClipRgn and removes used regions
|
|
|
|
RestoreClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
DeleteObject(ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawRoundRect(ACanvas: TCanvas; Rect: T2DIntRect;
|
|
|
|
Radius: integer; ColorFrom, ColorTo: TColor; GradientKind: TBackgroundKind;
|
|
|
|
ClipRect: T2DIntRect; LeftTopRound, RightTopRound, LeftBottomRound,
|
|
|
|
RightBottomRound: boolean);
|
2016-11-16 18:56:23 +00:00
|
|
|
var
|
|
|
|
UseOrgClipRgn: boolean;
|
|
|
|
ClipRgn: HRGN;
|
|
|
|
OrgRgn: HRGN;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
// Store the original ClipRgn and set a new one
|
2016-11-16 18:56:23 +00:00
|
|
|
SaveClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ClipRgn := CreateRectRgn(
|
|
|
|
ClipRect.left, ClipRect.Top, ClipRect.Right+1, ClipRect.Bottom+1
|
|
|
|
);
|
2016-11-16 18:56:23 +00:00
|
|
|
if UseOrgClipRgn then
|
|
|
|
CombineRgn(ClipRgn, ClipRgn, OrgRgn, RGN_AND);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2016-11-16 18:56:23 +00:00
|
|
|
SelectClipRgn(ACanvas.Handle, ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
DrawRoundRect(ACanvas, Rect, Radius, ColorFrom, ColorTo, GradientKind,
|
|
|
|
LeftTopRound, RightTopRound, LeftBottomRound, RightBottomRound);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Restores previous ClipRgn and removes used regions
|
2016-11-16 18:56:23 +00:00
|
|
|
RestoreClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
DeleteObject(ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawText(ACanvas: TCanvas; x, y: integer;
|
2016-11-16 18:56:23 +00:00
|
|
|
const AText: string; TextColor: TColor);
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2016-11-16 18:56:23 +00:00
|
|
|
with ACanvas do
|
|
|
|
begin
|
|
|
|
Brush.Style := bsClear;
|
|
|
|
Font.Color := TextColor;
|
|
|
|
TextOut(x, y, AText);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawText(ACanvas: TCanvas; x, y: integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText: string; TextColor: TColor; ClipRect: T2DIntRect);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
WinAPIClipRect: TRect;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
WinAPIClipRect := ClipRect.ForWinAPI;
|
|
|
|
with ACanvas do
|
|
|
|
begin
|
|
|
|
Brush.Style := bsClear;
|
|
|
|
Font.Color := TextColor;
|
|
|
|
TextRect(WinAPIClipRect, x, y, AText);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawRoundRect(ACanvas: TCanvas; Rect: T2DIntRect;
|
|
|
|
Radius: integer; ColorFrom, ColorTo: TColor; GradientKind: TBackgroundKind;
|
|
|
|
LeftTopRound, RightTopRound, LeftBottomRound, RightBottomRound: boolean);
|
2016-11-16 18:56:23 +00:00
|
|
|
var
|
|
|
|
RoundRgn: HRGN;
|
|
|
|
TmpRgn: HRGN;
|
|
|
|
OrgRgn: HRGN;
|
|
|
|
UseOrgClipRgn: Boolean;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2016-11-16 18:56:23 +00:00
|
|
|
if Radius < 0 then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2016-11-16 18:56:23 +00:00
|
|
|
if Radius > 0 then
|
|
|
|
begin
|
|
|
|
//WriteLn('Radius: ', Radius, ' Rect.Width: ', Rect.Width, ' Rect.Height: ', Rect.Height);
|
|
|
|
|
|
|
|
// There's a bug in fpc that evaluates the expression below erroneous when using inline
|
|
|
|
// Radius = 3 and Rect.Width >= 128 and <= 261 will evaluate to true
|
|
|
|
{$ifdef FpcBugWorkAround}
|
|
|
|
if (CompareValue(Radius*2, Rect.width) > 0) and (CompareValue(Radius*2, Rect.Height) > 0) then
|
|
|
|
exit;
|
|
|
|
{$else}
|
|
|
|
if (Radius*2 > Rect.Width) or (Radius*2 > Rect.Height) then
|
|
|
|
exit;
|
|
|
|
{$endif}
|
|
|
|
|
|
|
|
// Zapamiêtywanie oryginalnego ClipRgn i ustawianie nowego
|
|
|
|
SaveClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
|
|
|
|
if not(LeftTopRound) and
|
|
|
|
not(RightTopRound) and
|
|
|
|
not(LeftBottomRound) and
|
|
|
|
not (RightBottomRound) then
|
|
|
|
begin
|
|
|
|
RoundRgn := CreateRectRgn(Rect.Left, Rect.Top, Rect.Right + 1, Rect.Bottom + 1);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
RoundRgn := CreateRoundRectRgn(Rect.Left, Rect.Top, Rect.Right +2, Rect.Bottom + 2, Radius*2, Radius*2);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if not LeftTopRound then
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2016-11-16 18:56:23 +00:00
|
|
|
TmpRgn := CreateRectRgn(Rect.Left, Rect.Top, Rect.Left + Radius, Rect.Top + Radius);
|
|
|
|
CombineRgn(RoundRgn, RoundRgn, TmpRgn, RGN_OR);
|
|
|
|
DeleteObject(TmpRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if not RightTopRound then
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2016-11-16 18:56:23 +00:00
|
|
|
TmpRgn := CreateRectRgn(Rect.Right - Radius + 1, Rect.Top, Rect.Right + 1, Rect.Top + Radius);
|
|
|
|
CombineRgn(RoundRgn, RoundRgn, TmpRgn, RGN_OR);
|
|
|
|
DeleteObject(TmpRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if not LeftBottomRound then
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2016-11-16 18:56:23 +00:00
|
|
|
TmpRgn := CreateRectRgn(Rect.Left, Rect.Bottom - Radius + 1, Rect.Left + Radius, Rect.Bottom + 1);
|
|
|
|
CombineRgn(RoundRgn, RoundRgn, TmpRgn, RGN_OR);
|
|
|
|
DeleteObject(TmpRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if not RightBottomRound then
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2016-11-16 18:56:23 +00:00
|
|
|
TmpRgn := CreateRectRgn(Rect.Right - Radius + 1, Rect.Bottom - Radius + 1, Rect.Right + 1, Rect.Bottom + 1);
|
|
|
|
CombineRgn(RoundRgn, RoundRgn, TmpRgn, RGN_OR);
|
|
|
|
DeleteObject(TmpRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
2016-11-16 18:56:23 +00:00
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2016-11-16 18:56:23 +00:00
|
|
|
if UseOrgClipRgn then
|
|
|
|
CombineRgn(RoundRgn, RoundRgn, OrgRgn, RGN_AND);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2016-11-16 18:56:23 +00:00
|
|
|
SelectClipRgn(ACanvas.Handle, RoundRgn);
|
|
|
|
end; // if Radius > 0
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2016-11-16 18:56:23 +00:00
|
|
|
ColorFrom := ColorToRGB(ColorFrom);
|
|
|
|
ColorTo := ColorToRGB(ColorTo);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2016-11-16 18:56:23 +00:00
|
|
|
FillGradientRectangle(ACanvas, Rect, ColorFrom, ColorTo, GradientKind);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2016-11-16 18:56:23 +00:00
|
|
|
if Radius > 0 then
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
// Restores previous ClipRgn and removes used regions
|
2016-11-16 18:56:23 +00:00
|
|
|
RestoreClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
DeleteObject(RoundRgn);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawOutlinedText(ABitmap: TBitmap; x, y: integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText: string; TextColor, OutlineColor: TColor);
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
with ABitmap.Canvas do
|
|
|
|
begin
|
|
|
|
Brush.Style := bsClear;
|
|
|
|
Font.Color := OutlineColor;
|
|
|
|
TextOut(x-1, y-1, AText);
|
|
|
|
TextOut(x, y-1, AText);
|
|
|
|
TextOut(x+1, y-1, AText);
|
|
|
|
TextOut(x-1, y, AText);
|
|
|
|
TextOut(x+1, y, AText);
|
|
|
|
TextOut(x-1, y+1, AText);
|
|
|
|
TextOut(x, y+1, AText);
|
|
|
|
TextOut(x+1, y+1, AText);
|
|
|
|
|
|
|
|
Font.Color := TextColor;
|
|
|
|
TextOut(x, y, AText);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawText(ABitmap: TBitmap; x, y: integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText: string; TextColor: TColor; ClipRect: T2DIntRect);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
WinAPIClipRect : TRect;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
WinAPIClipRect := ClipRect.ForWinAPI;
|
|
|
|
with ABitmap.Canvas do
|
|
|
|
begin
|
|
|
|
Brush.Style := bsClear;
|
|
|
|
Font.Color := TextColor;
|
|
|
|
TextRect(WinAPIClipRect, x, y, AText);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
class procedure TGUITools.DrawFitWOutlinedText(ABitmap: TBitmap;
|
|
|
|
x1, x2, y: integer; const AText: string; TextColor, OutlineColor: TColor;
|
|
|
|
Align: TAlignment);
|
|
|
|
var
|
|
|
|
tw: integer;
|
|
|
|
s: string;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
with ABitmap.Canvas do
|
|
|
|
begin
|
|
|
|
s := AText;
|
|
|
|
tw := TextWidth(s) + 2;
|
|
|
|
if tw <= x2 - x1 + 1 then
|
|
|
|
case Align of
|
|
|
|
taLeftJustify:
|
|
|
|
TGUITools.DrawOutlinedText(ABitmap,x1, y, AText, TextColor, OutlineColor);
|
|
|
|
taRightJustify:
|
|
|
|
TGUITools.DrawOutlinedText(ABitmap,x2-tw+1, y, AText, TextColor, OutlineColor);
|
|
|
|
taCenter:
|
|
|
|
TGUITools.DrawOutlinedText(ABitmap,x1 + ((x2-x1 - tw) div 2), y, AText, TextColor, OutlineColor);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
while (s <> '') and (tw > x2 - x1 + 1) do
|
|
|
|
begin
|
|
|
|
Delete(s, Length(s), 1);
|
|
|
|
tw := TextWidth(s + '...') + 2;
|
|
|
|
end;
|
|
|
|
if tw <= x2 - x1 + 1 then
|
|
|
|
TGUITools.DrawOutlinedText(ABitmap, x1, y, s+'...', TextColor, OutlineColor);
|
|
|
|
end;
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
class procedure TGUITools.DrawFitWOutlinedText(ACanvas: TCanvas;
|
|
|
|
x1, x2, y: integer; const AText: string; TextColor, OutlineColor: TColor;
|
2011-06-17 20:53:01 +00:00
|
|
|
Align: TAlignment);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
tw: integer;
|
|
|
|
s: string;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
with ACanvas do
|
|
|
|
begin
|
|
|
|
s := AText;
|
|
|
|
tw := TextWidth(s) + 2;
|
|
|
|
if tw <= x2 - x1 + 1 then
|
|
|
|
case Align of
|
|
|
|
taLeftJustify:
|
|
|
|
TGUITools.DrawOutlinedText(ACanvas,x1, y, AText, TextColor, OutlineColor);
|
|
|
|
taRightJustify:
|
|
|
|
TGUITools.DrawOutlinedText(ACanvas,x2-tw+1, y, AText, TextColor, OutlineColor);
|
|
|
|
taCenter:
|
|
|
|
TGUITools.DrawOutlinedText(ACanvas,x1 + (x2-x1 - tw) div 2, y, AText, TextColor, OutlineColor);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
while (s <> '') and (tw > x2 - x1 + 1) do
|
|
|
|
begin
|
|
|
|
Delete(s, Length(s), 1);
|
|
|
|
tw := TextWidth(s + '...') + 2;
|
|
|
|
end;
|
|
|
|
if tw <= x2 - x1 + 1 then
|
|
|
|
TGUITools.DrawOutlinedText(ACanvas, x1, y, s+'...', TextColor, OutlineColor);
|
|
|
|
end;
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
class procedure TGUITools.FillGradientRectangle(ACanvas: TCanvas;
|
|
|
|
Rect: T2DIntRect; ColorFrom: TColor; ColorTo: TColor;
|
|
|
|
GradientKind: TBackgroundKind);
|
2011-06-17 20:53:01 +00:00
|
|
|
var
|
2011-06-18 13:46:52 +00:00
|
|
|
Mesh: array of GRADIENTRECT;
|
|
|
|
GradientVertice: array of TRIVERTEX;
|
2011-06-17 20:53:01 +00:00
|
|
|
ConcaveColor: TColor;
|
|
|
|
begin
|
|
|
|
case GradientKind of
|
|
|
|
bkSolid:
|
|
|
|
begin
|
2011-06-20 18:49:36 +00:00
|
|
|
ACanvas.Brush.Style := bsSolid;
|
2011-06-17 20:53:01 +00:00
|
|
|
ACanvas.brush.color := ColorFrom;
|
|
|
|
ACanvas.fillrect(Rect.ForWinAPI);
|
|
|
|
end;
|
|
|
|
bkVerticalGradient, bkHorizontalGradient:
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
SetLength(GradientVertice, 2);
|
2011-06-17 20:53:01 +00:00
|
|
|
with GradientVertice[0] do
|
|
|
|
begin
|
|
|
|
x := Rect.left;
|
|
|
|
y := Rect.top;
|
|
|
|
Red := GetRValue(ColorFrom) shl 8;
|
|
|
|
Green := GetGValue(ColorFrom) shl 8;
|
|
|
|
Blue := GetBValue(ColorFrom) shl 8;
|
|
|
|
Alpha := 255 shl 8;
|
|
|
|
end;
|
|
|
|
with GradientVertice[1] do
|
|
|
|
begin
|
|
|
|
x := Rect.Right + 1;
|
|
|
|
y := Rect.bottom + 1;
|
|
|
|
Red := GetRValue(ColorTo) shl 8;
|
|
|
|
Green := GetGValue(ColorTo) shl 8;
|
|
|
|
Blue := GetBValue(ColorTo) shl 8;
|
|
|
|
Alpha := 255 shl 8;
|
|
|
|
end;
|
2017-10-12 17:48:39 +00:00
|
|
|
SetLength(Mesh, 1);
|
2011-06-17 20:53:01 +00:00
|
|
|
Mesh[0].UpperLeft := 0;
|
|
|
|
Mesh[0].LowerRight := 1;
|
|
|
|
if GradientKind = bkVerticalGradient then
|
|
|
|
GradientFill(ACanvas.Handle, @GradientVertice[0], 2, @Mesh[0], 1, GRADIENT_FILL_RECT_V)
|
|
|
|
else
|
|
|
|
GradientFill(ACanvas.Handle, @GradientVertice[0], 2, @Mesh[0], 1, GRADIENT_FILL_RECT_H);
|
|
|
|
end;
|
|
|
|
bkConcave:
|
|
|
|
begin
|
|
|
|
ConcaveColor:=TColorTools.Brighten(ColorFrom, 20);
|
2017-10-12 17:48:39 +00:00
|
|
|
SetLength(GradientVertice, 4);
|
2011-06-17 20:53:01 +00:00
|
|
|
with GradientVertice[0] do
|
|
|
|
begin
|
|
|
|
x := Rect.left;
|
|
|
|
y := Rect.top;
|
|
|
|
Red := GetRValue(ColorFrom) shl 8;
|
|
|
|
Green := GetGValue(ColorFrom) shl 8;
|
|
|
|
Blue := GetBValue(ColorFrom) shl 8;
|
|
|
|
Alpha := 255 shl 8;
|
|
|
|
end;
|
|
|
|
with GradientVertice[1] do
|
|
|
|
begin
|
|
|
|
x := Rect.Right + 1;
|
|
|
|
y := Rect.Top + (Rect.height) div 4;
|
|
|
|
Red := GetRValue(ConcaveColor) shl 8;
|
|
|
|
Green := GetGValue(ConcaveColor) shl 8;
|
|
|
|
Blue := GetBValue(ConcaveColor) shl 8;
|
|
|
|
Alpha := 255 shl 8;
|
|
|
|
end;
|
|
|
|
with GradientVertice[2] do
|
|
|
|
begin
|
|
|
|
x := Rect.left;
|
|
|
|
y := Rect.Top + (Rect.height) div 4;
|
|
|
|
Red := GetRValue(ColorTo) shl 8;
|
|
|
|
Green := GetGValue(ColorTo) shl 8;
|
|
|
|
Blue := GetBValue(ColorTo) shl 8;
|
|
|
|
Alpha := 255 shl 8;
|
|
|
|
end;
|
|
|
|
with GradientVertice[3] do
|
|
|
|
begin
|
|
|
|
x := Rect.Right + 1;
|
|
|
|
y := Rect.bottom + 1;
|
|
|
|
Red := GetRValue(ColorFrom) shl 8;
|
|
|
|
Green := GetGValue(ColorFrom) shl 8;
|
|
|
|
Blue := GetBValue(ColorFrom) shl 8;
|
|
|
|
Alpha := 255 shl 8;
|
|
|
|
end;
|
2017-10-12 17:48:39 +00:00
|
|
|
SetLength(Mesh, 2);
|
2011-06-17 20:53:01 +00:00
|
|
|
Mesh[0].UpperLeft := 0;
|
|
|
|
Mesh[0].LowerRight := 1;
|
|
|
|
Mesh[1].UpperLeft := 2;
|
|
|
|
Mesh[1].LowerRight := 3;
|
|
|
|
GradientFill(ACanvas.Handle, @GradientVertice[0], 4, @Mesh[0], 2, GRADIENT_FILL_RECT_V);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawFitWText(ACanvas: TCanvas; x1, x2, y: integer;
|
2011-06-21 02:04:04 +00:00
|
|
|
const AText: string; TextColor: TColor; Align: TAlignment);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
tw: integer;
|
|
|
|
s: string;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
with ACanvas do
|
|
|
|
begin
|
2018-02-05 12:05:26 +00:00
|
|
|
Font.Color := TextColor;
|
2017-10-12 17:48:39 +00:00
|
|
|
s := AText;
|
|
|
|
tw := TextWidth(s);
|
|
|
|
// We draw if the text is changed
|
|
|
|
if tw <= x2 - x1 + 1 then
|
|
|
|
case Align of
|
|
|
|
taLeftJustify : TextOut(x1, y, AText);
|
|
|
|
taRightJustify : TextOut(x2-tw+1, y, AText);
|
|
|
|
taCenter : TextOut(x1 + (x2-x1 - tw) div 2, y, AText);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
while (s <> '') and (tw > x2 - x1 + 1) do
|
|
|
|
begin
|
|
|
|
Delete(s, Length(s), 1);
|
|
|
|
tw := TextWidth(s + '...');
|
|
|
|
end;
|
|
|
|
if tw <= x2 - x1 + 1 then
|
|
|
|
TextOut(x1, y, s + '...');
|
|
|
|
end;
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.RenderBackground(ABuffer: TBitmap;
|
|
|
|
Rect: T2DIntRect; Color1, Color2: TColor; BackgroundKind: TBackgroundKind);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
TempRect: T2DIntRect;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if ABuffer.PixelFormat<>pf24bit then
|
|
|
|
raise Exception.Create('TGUITools.RenderBackground: Bitmap must be in 24-bit mode');
|
|
|
|
if (Rect.Left > Rect.Right) or (Rect.Top > Rect.Bottom) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Both the FillRect method and the WinAPI gradient drawing are
|
|
|
|
// protected from drawing outside the canvas area.
|
|
|
|
case BackgroundKind of
|
|
|
|
bkSolid:
|
|
|
|
begin
|
|
|
|
ABuffer.Canvas.Brush.Color := Color1;
|
|
|
|
ABuffer.Canvas.Brush.Style := bsSolid;
|
|
|
|
ABuffer.Canvas.FillRect(Rect.ForWinAPI);
|
|
|
|
end;
|
|
|
|
bkVerticalGradient:
|
|
|
|
TGradientTools.VGradient(ABuffer.Canvas, Color1, Color2, Rect.ForWinAPI);
|
|
|
|
bkHorizontalGradient:
|
|
|
|
TGradientTools.HGradient(ABuffer.Canvas, Color1, Color2, Rect.ForWinAPI);
|
|
|
|
bkConcave:
|
|
|
|
begin
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
TempRect := T2DIntRect.Create(
|
|
|
|
{$ELSE}
|
|
|
|
TempRect.Create(
|
|
|
|
{$ENDIF}
|
|
|
|
Rect.Left, Rect.Top, Rect.Right, Rect.Top + (Rect.Bottom - Rect.Top) div 4
|
|
|
|
);
|
|
|
|
TGradientTools.VGradient(ABuffer.Canvas, Color1, TColorTools.Shade(Color1, Color2, 20), TempRect.ForWinAPI);
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
TempRect := T2DIntRect.Create(
|
|
|
|
{$ELSE}
|
|
|
|
TempRect.Create(
|
|
|
|
{$ENDIF}
|
|
|
|
Rect.Left, Rect.Top + (Rect.Bottom - Rect.Top) div 4 + 1, Rect.Right, Rect.Bottom
|
|
|
|
);
|
|
|
|
TGradientTools.VGradient(ABuffer.Canvas, Color2, Color1, TempRect.ForWinAPI);
|
|
|
|
end;
|
|
|
|
end; // case
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.RestoreClipRgn(DC: HDC; OrgRgnExists: boolean;
|
|
|
|
var OrgRgn: HRGN);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if OrgRgnExists then
|
|
|
|
SelectClipRgn(DC, OrgRgn) else
|
|
|
|
SelectClipRgn(DC, 0);
|
|
|
|
DeleteObject(OrgRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
2018-02-05 12:05:26 +00:00
|
|
|
class procedure TGUITools.SaveClipRgn(DC: HDC; out OrgRgnExists: boolean;
|
|
|
|
out OrgRgn: HRGN);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
i: integer;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
OrgRgn := CreateRectRgn(0, 0, 1, 1);
|
|
|
|
i := GetClipRgn(DC, OrgRgn);
|
|
|
|
OrgRgnExists := (i=1);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
2011-06-21 02:04:04 +00:00
|
|
|
class procedure TGUITools.DrawText(ABitmap: TBitmap; x, y: integer; const AText: string;
|
2011-06-17 20:53:01 +00:00
|
|
|
TextColor: TColor);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
with ABitmap.Canvas do
|
|
|
|
begin
|
|
|
|
Brush.Style := bsClear;
|
|
|
|
Font.Color:= TextColor;
|
|
|
|
TextOut(x, y, AText);
|
|
|
|
end;
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawVLine(ABitmap: TBitmap; x, y1, y2: integer;
|
|
|
|
Color: TColor);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
LineRect: T2DIntRect;
|
|
|
|
BitmapRect: T2DIntRect;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if ABitmap.PixelFormat <> pf24bit then
|
|
|
|
raise Exception.Create('TGUITools.DrawHLine: Bitmap must be in 24-bit mode!');
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
EnsureOrder(y1, y2);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
BitmapRect := T2DIntRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
if not (BitmapRect.IntersectsWith(T2DIntRect.Create(x, y1, x, y2), LineRect)) then
|
|
|
|
exit;
|
|
|
|
{$ELSE}
|
|
|
|
BitmapRect.create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
if not (BitmapRect.IntersectsWith(Create2DIntRect(x, y1, x, y2), LineRect)) then
|
|
|
|
exit;
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ABitmap.Canvas.Pen.color := Color;
|
|
|
|
ABitmap.Canvas.Pen.style := psSolid;
|
|
|
|
ABitmap.Canvas.Moveto(LineRect.Left, LineRect.Top);
|
|
|
|
ABitmap.Canvas.Lineto(LineRect.Left, Linerect.Bottom+1);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawVLine(ABitmap: TBitmap; x, y1, y2: integer;
|
|
|
|
Color: TColor; ClipRect: T2DIntRect);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
OrgLineRect: T2DIntRect;
|
|
|
|
LineRect: T2DIntRect;
|
|
|
|
BitmapRect: T2DIntRect;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if ABitmap.PixelFormat <> pf24bit then
|
|
|
|
raise Exception.Create('TGUITools.DrawHLine: Bitmap must be in 24-bit mode!');
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
EnsureOrder(y1, y2);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
BitmapRect := T2DIntRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
if not(BitmapRect.IntersectsWith(T2DIntRect.Create(x, y1, x, y2), OrgLineRect)) then
|
|
|
|
exit;
|
|
|
|
{$ELSE}
|
|
|
|
BitmapRect.Create(0, 0, ABitmap.Width-1, ABitmap.Height-1);
|
|
|
|
if not(BitmapRect.IntersectsWith(Create2DIntRect(x, y1, x, y2), OrgLineRect)) then
|
|
|
|
exit;
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if not(OrgLineRect.IntersectsWith(ClipRect, LineRect)) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ABitmap.Canvas.Pen.Color := Color;
|
|
|
|
ABitmap.Canvas.Pen.Style := psSolid;
|
|
|
|
ABitmap.Canvas.Moveto(LineRect.Left, LineRect.Top);
|
|
|
|
ABitmap.Canvas.Lineto(LineRect.Left, Linerect.Bottom+1);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawVLine(ACanvas: TCanvas; x, y1, y2: integer;
|
|
|
|
Color: TColor);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
EnsureOrder(y1, y2);
|
|
|
|
ACanvas.Pen.Color := Color;
|
|
|
|
ACanvas.Moveto(x, y1);
|
|
|
|
ACanvas.Lineto(x, y2+1);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawVLine(ACanvas: TCanvas; x, y1, y2: integer;
|
|
|
|
Color: TColor; ClipRect: T2DIntRect);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
UseOrgClipRgn: boolean;
|
|
|
|
ClipRgn: HRGN;
|
|
|
|
OrgRgn: HRGN;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
// Store the original ClipRgn and set a new one
|
|
|
|
SaveClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ClipRgn := CreateRectRgn(ClipRect.left, ClipRect.Top, ClipRect.Right+1, ClipRect.Bottom+1);
|
|
|
|
if UseOrgClipRgn then
|
|
|
|
CombineRgn(ClipRgn, ClipRgn, OrgRgn, RGN_AND);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
SelectClipRgn(ACanvas.Handle, ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
DrawVLine(ACanvas, x, y1, y2, Color);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Restores previous ClipRgn and removes used regions
|
|
|
|
RestoreClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
DeleteObject(ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawAARoundFrame(ACanvas: TCanvas; Rect: T2DIntRect;
|
|
|
|
Radius: integer; Color: TColor);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
if Radius < 1 then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
if (Radius > Rect.Width div 2) or (Radius > Rect.Height div 2) then
|
|
|
|
exit;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// DrawAARoundCorner is protected against drawing outside the area
|
|
|
|
{$IFDEF EnhancedRecordSupport}
|
|
|
|
DrawAARoundCorner(ACanvas, T2DIntVector.create(Rect.Left, Rect.Top), Radius, cpLeftTop, Color);
|
|
|
|
DrawAARoundCorner(ACanvas, T2DIntVector.create(Rect.Right - Radius + 1, Rect.Top), Radius, cpRightTop, Color);
|
|
|
|
DrawAARoundCorner(ACanvas, T2DIntVector.create(Rect.Left, Rect.Bottom - Radius + 1), Radius, cpLeftBottom, Color);
|
|
|
|
DrawAARoundCorner(ACanvas, T2DIntVector.create(Rect.Right - Radius + 1, Rect.Bottom - Radius + 1), Radius, cpRightBottom, Color);
|
|
|
|
{$ELSE}
|
|
|
|
DrawAARoundCorner(ACanvas, Create2DIntVector(Rect.Left, Rect.Top), Radius, cpLeftTop, Color);
|
|
|
|
DrawAARoundCorner(ACanvas, Create2DIntVector(Rect.Right - Radius + 1, Rect.Top), Radius, cpRightTop, Color);
|
|
|
|
DrawAARoundCorner(ACanvas, Create2DIntVector(Rect.Left, Rect.Bottom - Radius + 1), Radius, cpLeftBottom, Color);
|
|
|
|
DrawAARoundCorner(ACanvas, Create2DIntVector(Rect.Right - Radius + 1, Rect.Bottom - Radius + 1), Radius, cpRightBottom, Color);
|
|
|
|
{$ENDIF}
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ACanvas.Pen.color := Color;
|
|
|
|
ACanvas.pen.style := psSolid;
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Draw * Line is protected against drawing outside the area
|
|
|
|
DrawVLine(ACanvas, Rect.Left, Rect.Top + Radius, Rect.Bottom - Radius, Color);
|
|
|
|
DrawVLine(ACanvas, Rect.Right, Rect.Top + Radius, Rect.Bottom - Radius, Color);
|
|
|
|
DrawHLine(ACanvas, Rect.Left + Radius, Rect.Right - Radius, Rect.Top, Color);
|
|
|
|
DrawHLine(ACanvas, Rect.Left + Radius, Rect.Right - Radius, Rect.Bottom, Color);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawAARoundFrame(ACanvas: TCanvas; Rect: T2DIntRect;
|
|
|
|
Radius: integer; Color: TColor; ClipRect: T2DIntRect);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
UseOrgClipRgn: boolean;
|
|
|
|
ClipRgn: HRGN;
|
|
|
|
OrgRgn: HRGN;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
// Store the original ClipRgn and set a new one
|
|
|
|
SaveClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ClipRgn := CreateRectRgn(ClipRect.left, ClipRect.Top, ClipRect.Right+1, ClipRect.Bottom+1);
|
|
|
|
if UseOrgClipRgn then
|
|
|
|
CombineRgn(ClipRgn, ClipRgn, OrgRgn, RGN_AND);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
SelectClipRgn(ACanvas.Handle, ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
DrawAARoundFrame(ACanvas, Rect, Radius, Color);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Restores previous ClipRgn and removes used regions
|
|
|
|
RestoreClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
DeleteObject(ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawDisabledImage(ABitmap: TBitmap;
|
|
|
|
Imagelist: TImageList; ImageIndex: integer; Point: T2DIntVector;
|
|
|
|
ClipRect: T2DIntRect);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
DrawDisabledImage(ABitmap.Canvas, ImageList, ImageIndex, Point, ClipRect);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawDisabledImage(ABitmap: TBitmap;
|
|
|
|
Imagelist: TImageList; ImageIndex: integer; Point: T2DIntVector);
|
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
DrawDisabledImage(ABitmap.Canvas, ImageList, ImageIndex, Point);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawDisabledImage(ACanvas: TCanvas;
|
|
|
|
Imagelist: TImageList; ImageIndex: integer; Point: T2DIntVector;
|
|
|
|
ClipRect: T2DIntRect);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
UseOrgClipRgn: Boolean;
|
|
|
|
OrgRgn: HRGN;
|
|
|
|
ClipRgn: HRGN;
|
|
|
|
DCStackPos : integer;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
// Store the original ClipRgn and set a new one
|
|
|
|
SaveClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
ClipRgn := CreateRectRgn(ClipRect.left, ClipRect.Top, ClipRect.Right+1, ClipRect.Bottom+1);
|
|
|
|
if UseOrgClipRgn then
|
|
|
|
CombineRgn(ClipRgn, ClipRgn, OrgRgn, RGN_AND);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
SelectClipRgn(ACanvas.Handle, ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
// Hack fixes the bug in ImageList.Draw which does not restore the previous one /???
|
|
|
|
// Font color for canvas
|
|
|
|
DcStackPos := SaveDC(ACanvas.Handle);
|
|
|
|
ImageList.Draw(ACanvas, Point.x, Point.y, ImageIndex, false);
|
|
|
|
RestoreDC(ACanvas.Handle, DcStackPos);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
RestoreClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
|
2017-10-12 17:48:39 +00:00
|
|
|
DeleteObject(ClipRgn);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawDisabledImage(ACanvas: TCanvas;
|
|
|
|
Imagelist: TImageList; ImageIndex: integer; Point: T2DIntVector);
|
2017-10-12 17:48:39 +00:00
|
|
|
var
|
|
|
|
DCStackPos : integer;
|
2011-06-17 20:53:01 +00:00
|
|
|
begin
|
2017-10-12 17:48:39 +00:00
|
|
|
//todo: see if is necessary to save the DC
|
|
|
|
DcStackPos := SaveDC(ACanvas.Handle);
|
|
|
|
ImageList.Draw(ACanvas, Point.x, Point.y, ImageIndex, false);
|
|
|
|
RestoreDC(ACanvas.Handle, DcStackPos);
|
2011-06-17 20:53:01 +00:00
|
|
|
end;
|
|
|
|
|
2012-06-04 00:49:51 +00:00
|
|
|
class procedure TGUITools.DrawCheckbox(ACanvas:TCanvas; x,y: Integer;
|
2018-02-04 17:29:22 +00:00
|
|
|
AState: TCheckboxState; AButtonState:TSpkButtonState;
|
2012-06-04 00:49:51 +00:00
|
|
|
AStyle: TSpkCheckboxStyle; ClipRect:T2DIntRect);
|
|
|
|
var
|
|
|
|
UseOrgClipRgn: Boolean;
|
|
|
|
OrgRgn: HRGN;
|
|
|
|
ClipRgn: HRGN;
|
|
|
|
begin
|
|
|
|
SaveClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
ClipRgn := CreateRectRgn(ClipRect.left, ClipRect.Top, ClipRect.Right+1, ClipRect.Bottom+1);
|
|
|
|
if UseOrgClipRgn then
|
|
|
|
CombineRgn(ClipRgn, ClipRgn, OrgRgn, RGN_AND);
|
|
|
|
SelectClipRgn(ACanvas.Handle, ClipRgn);
|
2018-02-04 17:29:22 +00:00
|
|
|
DrawCheckbox(ACanvas, x,y, AState, AButtonState, AStyle);
|
2012-06-04 00:49:51 +00:00
|
|
|
RestoreClipRgn(ACanvas.Handle, UseOrgClipRgn, OrgRgn);
|
|
|
|
DeleteObject(ClipRgn);
|
|
|
|
end;
|
|
|
|
|
|
|
|
class procedure TGUITools.DrawCheckbox(ACanvas: TCanvas; x,y: Integer;
|
2018-02-04 17:29:22 +00:00
|
|
|
AState: TCheckboxState; AButtonState: TSpkButtonState;
|
|
|
|
AStyle: TSpkCheckboxStyle);
|
|
|
|
const
|
|
|
|
NOT_USED = tbCheckboxCheckedNormal;
|
2012-06-04 00:49:51 +00:00
|
|
|
const
|
|
|
|
UNTHEMED_FLAGS: array [TSpkCheckboxStyle, TCheckboxState] of Integer = (
|
|
|
|
(DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED, DFCS_BUTTONCHECK or DFCS_BUTTON3STATE),
|
|
|
|
(DFCS_BUTTONRADIO, DFCS_BUTTONRADIO or DFCS_CHECKED, DFCS_BUTTONRADIO or DFCS_BUTTON3STATE)
|
|
|
|
);
|
2018-02-04 17:29:22 +00:00
|
|
|
THEMED_FLAGS: array [TSpkCheckboxStyle, TCheckboxState, TSpkButtonState] of TThemedButton = (
|
|
|
|
( (tbCheckboxUncheckedNormal, tbCheckboxUncheckedHot, tbCheckboxUncheckedPressed, tbCheckboxUncheckedDisabled, NOT_USED),
|
|
|
|
(tbCheckboxCheckedNormal, tbCheckboxCheckedHot, tbCheckboxCheckedPressed, tbCheckboxCheckedDisabled, NOT_USED),
|
|
|
|
(tbCheckboxMixedNormal, tbCheckboxMixedHot, tbCheckboxMixedPressed, tbCheckboxMixedDisabled, NOT_USED)
|
2012-06-04 00:49:51 +00:00
|
|
|
),
|
2018-02-04 17:29:22 +00:00
|
|
|
( (tbRadioButtonUncheckedNormal, tbRadioButtonUncheckedHot, tbRadioButtonUncheckedPressed, tbRadioButtonUncheckedDisabled, NOT_USED),
|
|
|
|
(tbRadioButtonCheckedNormal, tbRadioButtonCheckedHot, tbRadioButtonCheckedPressed, tbRadioButtonCheckedDisabled, NOT_USED),
|
|
|
|
(tbRadioButtonCheckedNormal, tbRadioButtonCheckedHot, tbRadioButtonCheckedPressed, tbRadioButtonCheckedDisabled, NOT_USED)
|
2012-06-04 00:49:51 +00:00
|
|
|
)
|
|
|
|
);
|
|
|
|
var
|
|
|
|
R: TRect;
|
|
|
|
w: Integer;
|
2014-10-13 19:04:19 +00:00
|
|
|
sz: TSize;
|
2012-06-04 00:49:51 +00:00
|
|
|
te: TThemedElementDetails;
|
|
|
|
begin
|
|
|
|
if ThemeServices.ThemesEnabled then begin
|
2018-02-04 17:29:22 +00:00
|
|
|
te := ThemeServices.GetElementDetails(THEMED_FLAGS[AStyle, AState, AButtonState]);
|
2014-10-13 19:04:19 +00:00
|
|
|
sz := ThemeServices.GetDetailSize(te);
|
|
|
|
R := Bounds(x, y, sz.cx, sz.cy);
|
|
|
|
InflateRect(R, 1, 1);
|
2012-06-04 00:49:51 +00:00
|
|
|
ThemeServices.DrawElement(ACanvas.Handle, te, R);
|
2014-10-13 19:04:19 +00:00
|
|
|
end else begin
|
|
|
|
w := GetSystemMetrics(SM_CYMENUCHECK);
|
|
|
|
R := Bounds(x, y, w, w);
|
2012-06-04 00:49:51 +00:00
|
|
|
DrawFrameControl(
|
|
|
|
ACanvas.Handle, R, DFC_BUTTON, UNTHEMED_FLAGS[AStyle, AState]);
|
2014-10-13 19:04:19 +00:00
|
|
|
end;
|
2012-06-04 00:49:51 +00:00
|
|
|
end;
|
|
|
|
|
2011-06-17 20:53:01 +00:00
|
|
|
end.
|