fpc/rtl/objpas/types.pp
2025-01-24 11:53:09 +01:00

2039 lines
52 KiB
ObjectPascal

{
This file is part of the Free Pascal run time library.
Copyright (c) 2002 by Florian Klaempfl,
member of the Free Pascal development team.
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
{$MODE OBJFPC}
{$IFNDEF FPC_DOTTEDUNITS}
unit Types;
{$ENDIF FPC_DOTTEDUNITS}
interface
{$modeswitch advancedrecords}
{$modeswitch class}
{$if defined(win32) or defined(win64) or defined(wince)}
uses
{$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows;
{$elseif defined(win16)}
uses
{$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}WinTypes;
{$endif}
{$if defined(win32) or defined(win64)}
const
RT_RCDATA = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.RT_RCDATA deprecated 'Use Windows.RT_RCDATA instead';
{$elseif defined(win16)}
const
RT_RCDATA = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}WinTypes.RT_RCDATA deprecated 'Use WinTypes.RT_RCDATA instead';
{$endif}
Const
Epsilon: Single = 1E-40;
Epsilon2: Single = 1E-30;
CurveKappa = 0.5522847498;
CurveKappaInv = 1 - CurveKappa;
type
TEndian = Objpas.TEndian;
TDirection = (FromBeginning, FromEnd);
TValueRelationship = -1..1;
const
LessThanValue = Low(TValueRelationship);
EqualsValue = 0;
GreaterThanValue = High(TValueRelationship);
type
DWORD = LongWord;
PLongint = System.PLongint;
PSmallInt = System.PSmallInt;
{$ifndef FPUNONE}
PDouble = System.PDouble;
{$endif}
PByte = System.PByte;
Largeint = int64;
LARGE_INT = LargeInt;
PLargeInt = ^LargeInt;
LargeUint = qword;
LARGE_UINT= LargeUInt;
PLargeuInt = ^LargeuInt;
{ Null dummy type, for compile time null passing }
TNullPtr = record
{ Some operators to make it (more or less) nil compatible }
class operator :=(None: TNullPtr): Pointer; inline;
class operator :=(None: TNullPtr): TObject; inline;
class operator =(LHS: TNullPtr; RHS: Pointer): Boolean; inline;
class operator =(LHS: TNullPtr; RHS: TObject): Boolean; inline;
class operator =(LHS: Pointer; RHS: TNullPtr): Boolean; inline;
class operator =(LHS: TObject; RHS: TNullPtr): Boolean; inline;
class operator <>(LHS: TNullPtr; RHS: Pointer): Boolean; inline;
class operator <>(LHS: TNullPtr; RHS: TObject): Boolean; inline;
class operator <>(LHS: Pointer; RHS: TNullPtr): Boolean; inline;
class operator <>(LHS: TObject; RHS: TNullPtr): Boolean; inline;
end;
{$Push}
{$WriteableConst Off}
const
NullPtr: TNullPtr = ();
{$Pop}
type
TBooleanDynArray = array of Boolean;
TByteDynArray = array of Byte;
TClassicByteDynArray = TByteDynArray;
TCardinalDynArray = array of Cardinal;
TInt64DynArray = array of Int64;
TIntegerDynArray = array of Integer;
TLongWordDynArray = array of LongWord;
TPointerDynArray = array of Pointer;
TQWordDynArray = array of QWord;
TShortIntDynArray = array of ShortInt;
TSmallIntDynArray = array of SmallInt;
TRTLStringDynArray = array of RTLString;
TAnsiStringDynArray = Array of AnsiString;
TWideStringDynArray = array of WideString;
TUnicodeStringDynArray = array of UnicodeString;
{$if SIZEOF(CHAR)=2}
TStringDynArray = Array of UnicodeString;
{$ELSE}
TStringDynArray = Array of AnsiString;
{$ENDIF}
TClassicStringDynArray = TStringDynArray;
TObjectDynArray = array of TObject;
TWordDynArray = array of Word;
TCurrencyArray = Array of currency;
{$ifndef FPUNONE}
TSingleDynArray = array of Single;
TDoubleDynArray = array of Double;
TExtendedDynArray = array of Extended;
TCompDynArray = array of Comp;
{$endif}
{$if defined(win32) or defined(win64) or defined(wince)}
TArray4IntegerType = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.TArray4IntegerType;
TSmallPoint = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.TSmallPoint;
PSmallPoint = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.PSmallPoint;
TSize = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.TSize;
TagSize = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.tagSize deprecated;
PSize = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.PSize;
TPoint = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.TPoint;
TagPoint = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.TagPoint deprecated;
PPoint = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.PPoint;
TRect = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.TRect;
PRect = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.PRect;
TSplitRectType = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.TSplitRectType;
const
srLeft = TSplitRectType.srLeft;
srRight = TSplitRectType.srRight;
srTop = TSplitRectType.srTop;
srBottom = TSplitRectType.srBottom;
type
{$else}
{$i typshrdh.inc}
TagSize = tSize deprecated;
TagPoint = TPoint deprecated;
{$endif}
{ TPointF }
PPointF = ^TPointF;
TPointF =
{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
packed
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
record
x,y : Single;
public
function Add(const apt: TPoint): TPointF;
function Add(const apt: TPointF): TPointF;
function Distance(const apt : TPointF) : Single;
function DotProduct(const apt : TPointF) : Single;
function IsZero : Boolean;
function Subtract(const apt : TPointF): TPointF;
function Subtract(const apt : TPoint): TPointF;
procedure SetLocation(const apt :TPointF);
procedure SetLocation(const apt :TPoint);
procedure SetLocation(ax,ay : Single);
procedure Offset(const apt :TPointF);
procedure Offset(const apt :TPoint);
procedure Offset(dx,dy : Single);
function EqualsTo(const apt: TPointF; const aEpsilon : Single): Boolean; overload;
function EqualsTo(const apt: TPointF): Boolean; overload;
function Scale (afactor:Single) : TPointF;
function Ceiling : TPoint;
function Truncate: TPoint;
function Floor : TPoint;
function Round : TPoint;
function Length : Single;
function Rotate(angle: single): TPointF;
function Reflect(const normal: TPointF): TPointF;
function MidPoint(const b: TPointF): TPointF;
class function PointInCircle(const pt, center: TPointF; radius: single): Boolean; static;
class function PointInCircle(const pt, center: TPointF; radius: integer): Boolean; static;
class function Zero: TPointF; inline; static;
function Angle(const b: TPointF): Single;
function AngleCosine(const b: TPointF): single;
function CrossProduct(const apt: TPointF): Single;
function Normalize: TPointF;
function ToString(aSize,aDecimals : Byte) : RTLString; overload;
function ToString : RTLString; overload; inline;
class function Create(const ax, ay: Single): TPointF; overload; static; inline;
class function Create(const apt: TPoint): TPointF; overload; static; inline;
class operator = (const apt1, apt2 : TPointF) : Boolean;
class operator <> (const apt1, apt2 : TPointF): Boolean;
class operator + (const apt1, apt2 : TPointF): TPointF;
class operator - (const apt1, apt2 : TPointF): TPointF;
class operator - (const apt1 : TPointF): TPointF;
class operator * (const apt1, apt2: TPointF): TPointF;
class operator * (const apt1: TPointF; afactor: single): TPointF;
class operator * (afactor: single; const apt1: TPointF): TPointF;
class operator / (const apt1: TPointF; afactor: single): TPointF;
class operator := (const apt: TPoint): TPointF;
class operator ** (const apt1, apt2: TPointF): Single; // scalar product
end;
{ TSizeF }
PSizeF = ^TSizeF;
TSizeF =
{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
packed
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
record
cx,cy : Single;
public
function Add(const asz: TSize): TSizeF;
function Add(const asz: TSizeF): TSizeF;
function Distance(const asz : TSizeF) : Single;
function IsZero : Boolean;
function Subtract(const asz : TSizeF): TSizeF;
function Subtract(const asz : TSize): TSizeF;
function SwapDimensions:TSizeF;
function Scale (afactor:Single) : TSizeF;
function Ceiling : TSize;
function Truncate: TSize;
function Floor : TSize;
function Round : TSize;
function Length : Single;
function ToString(aSize,aDecimals : Byte) : RTLString; overload;
function ToString : RTLString; overload; inline;
class function Create(const ax, ay: Single): TSizeF; overload; static; inline;
class function Create(const asz: TSize): TSizeF; overload; static; inline;
class operator = (const asz1, asz2 : TSizeF) : Boolean;
class operator <> (const asz1, asz2 : TSizeF): Boolean;
class operator + (const asz1, asz2 : TSizeF): TSizeF;
class operator - (const asz1, asz2 : TSizeF): TSizeF;
class operator - (const asz1 : TSizeF): TSizeF;
class operator * (const asz1: TSizeF; afactor: single): TSizeF;
class operator * (afactor: single; const asz1: TSizeF): TSizeF;
class operator := (const apt: TPointF): TSizeF;
class operator := (const asz: TSize): TSizeF;
class operator := (const asz: TSizeF): TPointF;
property Width: Single read cx write cx;
property Height: Single read cy write cy;
end;
{$SCOPEDENUMS ON}
TVertRectAlign = (Center, Top, Bottom);
THorzRectAlign = (Center, Left, Right);
{$SCOPEDENUMS OFF}
{ TRectF }
PRectF = ^TRectF;
TRectF =
{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
packed
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
record
private
function GetLocation: TPointF;
function GetSize: TSizeF;
procedure SetSize(AValue: TSizeF);
function GetHeight: Single; inline;
function GetWidth: Single; inline;
procedure SetHeight(AValue: Single);
procedure SetWidth (AValue: Single);
public
constructor Create(Origin: TPointF); // empty rect at given origin
constructor Create(Origin: TPointF; AWidth, AHeight: Single);
constructor Create(ALeft, ATop, ARight, ABottom: Single);
constructor Create(P1, P2: TPointF; Normalize: Boolean = False);
constructor Create(R: TRectF; Normalize: Boolean = False);
constructor Create(R: TRect; Normalize: Boolean = False);
class operator = (L, R: TRectF): Boolean;
class operator <> (L, R: TRectF): Boolean;
class operator + (L, R: TRectF): TRectF; // union
class operator * (L, R: TRectF): TRectF; // intersection
class operator := (const arc: TRect): TRectF;
class function Empty: TRectF; static;
class function Intersect(R1: TRectF; R2: TRectF): TRectF; static;
class function Union(const Points: array of TPointF): TRectF; static;
class function Union(R1, R2: TRectF): TRectF; static;
Function Ceiling : TRectF;
function CenterAt(const Dest: TRectF): TRectF;
function CenterPoint: TPointF;
function Contains(Pt: TPointF): Boolean;
function Contains(R: TRectF): Boolean;
function EqualsTo(const R: TRectF; const Epsilon: Single = 0): Boolean;
function Fit(const Dest: TRectF): Single; deprecated 'Use FitInto';
function FitInto(const Dest: TRectF): TRectF; overload;
function FitInto(const Dest: TRectF; out Ratio: Single): TRectF; overload;
function IntersectsWith(R: TRectF): Boolean;
function IsEmpty: Boolean;
function PlaceInto(const Dest: TRectF; const AHorzAlign: THorzRectAlign = THorzRectAlign.Center; const AVertAlign: TVertRectAlign = TVertRectAlign.Center): TRectF;
function Round: TRect;
function SnapToPixel(AScale: Single; APlaceBetweenPixels: Boolean = True): TRectF;
function Truncate: TRect;
procedure Inflate(DL, DT, DR, DB: Single);
procedure Inflate(DX, DY: Single);
procedure Intersect(R: TRectF);
procedure NormalizeRect;
procedure Offset (const dx,dy : Single); inline;
procedure Offset (DP: TPointF); inline;
procedure SetLocation(P: TPointF);
procedure SetLocation(X, Y: Single);
function ToString(aSize,aDecimals : Byte; aUseSize : Boolean = False) : RTLString; overload;
function ToString(aUseSize : Boolean = False) : RTLString; overload; inline;
procedure Union (const r: TRectF); inline;
property Width : Single read GetWidth write SetWidth;
property Height : Single read GetHeight write SetHeight;
property Size : TSizeF read getSize write SetSize;
property Location: TPointF read getLocation write setLocation;
case Integer of
0: (Left, Top, Right, Bottom: Single);
1: (TopLeft, BottomRight: TPointF);
end;
TDuplicates = (dupIgnore, dupAccept, dupError);
TPoint3D =
{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
packed
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
record
public
Type TSingle3Array = array[0..2] of single;
constructor Create(const ax,ay,az:single);
procedure Offset(const adeltax,adeltay,adeltaz:single); inline;
procedure Offset(const adelta:TPoint3D); inline;
function ToString(aSize,aDecimals : Byte) : RTLString; overload;
function ToString : RTLString; overload; inline;
public
case Integer of
0: (data:TSingle3Array);
1: (x,y,z : single);
end;
type
TOleChar = WideChar;
POleStr = PWideChar;
PPOleStr = ^POleStr;
TListCallback = procedure(data,arg:pointer) of object;
TListStaticCallback = procedure(data,arg:pointer);
const
GUID_NULL: TGUID = '{00000000-0000-0000-0000-000000000000}';
STGTY_STORAGE = 1;
STGTY_STREAM = 2;
STGTY_LOCKBYTES = 3;
STGTY_PROPERTY = 4;
STREAM_SEEK_SET = 0;
STREAM_SEEK_CUR = 1;
STREAM_SEEK_END = 2;
LOCK_WRITE = 1;
LOCK_EXCLUSIVE = 2;
LOCK_ONLYONCE = 4;
STATFLAG_DEFAULT = 0;
STATFLAG_NONAME = 1;
STATFLAG_NOOPEN = 2;
{$ifndef Wince}
// in Wince these are in unit windows. Under 32/64 in ActiveX.
// for now duplicate them. Not that bad for untyped constants.
E_FAIL = HRESULT($80004005);
E_INVALIDARG = HRESULT($80070057);
STG_E_INVALIDFUNCTION = HRESULT($80030001);
STG_E_FILENOTFOUND = HRESULT($80030002);
STG_E_PATHNOTFOUND = HRESULT($80030003);
STG_E_TOOMANYOPENFILES = HRESULT($80030004);
STG_E_ACCESSDENIED = HRESULT($80030005);
STG_E_INVALIDHANDLE = HRESULT($80030006);
STG_E_INSUFFICIENTMEMORY = HRESULT($80030008);
STG_E_INVALIDPOINTER = HRESULT($80030009);
STG_E_NOMOREFILES = HRESULT($80030012);
STG_E_DISKISWRITEPROTECTED = HRESULT($80030013);
STG_E_SEEKERROR = HRESULT($80030019);
STG_E_WRITEFAULT = HRESULT($8003001D);
STG_E_READFAULT = HRESULT($8003001E);
STG_E_SHAREVIOLATION = HRESULT($80030020);
STG_E_LOCKVIOLATION = HRESULT($80030021);
STG_E_FILEALREADYEXISTS = HRESULT($80030050);
STG_E_INVALIDPARAMETER = HRESULT($80030057);
STG_E_MEDIUMFULL = HRESULT($80030070);
STG_E_PROPSETMISMATCHED = HRESULT($800300F0);
STG_E_ABNORMALAPIEXIT = HRESULT($800300FA);
STG_E_INVALIDHEADER = HRESULT($800300FB);
STG_E_INVALIDNAME = HRESULT($800300FC);
STG_E_UNKNOWN = HRESULT($800300FD);
STG_E_UNIMPLEMENTEDFUNCTION = HRESULT($800300FE);
STG_E_INVALIDFLAG = HRESULT($800300FF);
STG_E_INUSE = HRESULT($80030100);
STG_E_NOTCURRENT = HRESULT($80030101);
STG_E_REVERTED = HRESULT($80030102);
STG_E_CANTSAVE = HRESULT($80030103);
STG_E_OLDFORMAT = HRESULT($80030104);
STG_E_OLDDLL = HRESULT($80030105);
STG_E_SHAREREQUIRED = HRESULT($80030106);
STG_E_EXTANTMARSHALLINGS = HRESULT($80030108);
STG_E_DOCFILECORRUPT = HRESULT($80030109);
STG_E_BADBASEADDRESS = HRESULT($80030110);
STG_E_INCOMPLETE = HRESULT($80030201);
STG_E_TERMINATED = HRESULT($80030202);
STG_S_CONVERTED = $00030200;
STG_S_BLOCK = $00030201;
STG_S_RETRYNOW = $00030202;
STG_S_MONITORING = $00030203;
{$endif}
{$if (not defined(win32)) and (not defined(win64)) and (not defined(wince))}
type
PCLSID = PGUID;
TCLSID = TGUID;
PDWord = ^DWord;
PDisplay = Pointer;
PEvent = Pointer;
TXrmOptionDescRec = record
end;
XrmOptionDescRec = TXrmOptionDescRec;
PXrmOptionDescRec = ^TXrmOptionDescRec;
Widget = Pointer;
WidgetClass = Pointer;
ArgList = Pointer;
Region = Pointer;
_FILETIME =
{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
packed
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
record
dwLowDateTime : DWORD;
dwHighDateTime : DWORD;
end;
TFileTime = _FILETIME;
FILETIME = _FILETIME;
PFileTime = ^TFileTime;
{$else}
type
PCLSID = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.PCLSID;
TCLSID = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.CLSID;
TFiletime = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.TFileTime;
Filetime = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.FileTime;
PFiletime = {$IFDEF FPC_DOTTEDUNITS}WinApi.{$ENDIF}Windows.PFileTime;
{$endif Windows}
type
tagSTATSTG = record
pwcsName : POleStr;
dwType : DWord;
cbSize : Large_uint;
mtime : TFileTime;
ctime : TFileTime;
atime : TFileTime;
grfMode : DWord;
grfLocksSupported : DWord;
clsid : TCLSID;
grfStateBits : DWord;
reserved : DWord;
end;
TStatStg = tagSTATSTG;
STATSTG = TStatStg;
PStatStg = ^TStatStg;
{ classes depends on these interfaces, we can't use the activex unit in classes though }
IClassFactory = Interface(IUnknown) ['{00000001-0000-0000-C000-000000000046}']
Function CreateInstance(Const unkOuter : IUnknown;Const riid : TGUID;Out vObject) : HResult;StdCall;
Function LockServer(fLock : LongBool) : HResult;StdCall;
End;
ISequentialStream = interface(IUnknown)
['{0c733a30-2a1c-11ce-ade5-00aa0044773d}']
function Read(pv : Pointer;cb : DWORD;pcbRead : PDWORD) : HRESULT;stdcall;
function Write(pv : Pointer;cb : DWORD;pcbWritten : PDWORD): HRESULT;stdcall;
end;
IStream = interface(ISequentialStream) ['{0000000C-0000-0000-C000-000000000046}']
function Seek(dlibMove : LargeInt; dwOrigin : DWORD; out libNewPosition : LargeUInt) : HResult;stdcall;
function SetSize(libNewSize : LargeUInt) : HRESULT;stdcall;
function CopyTo(stm: IStream;cb : LargeUInt;out cbRead : LargeUInt; out cbWritten : LargeUInt) : HRESULT;stdcall;
function Commit(grfCommitFlags : DWORD) : HRESULT;stdcall;
function Revert : HRESULT;stdcall;
function LockRegion(libOffset : LargeUInt;cb : LargeUInt; dwLockType : DWORD) : HRESULT;stdcall;
function UnlockRegion(libOffset : LargeUInt;cb : LargeUInt; dwLockType : DWORD) : HRESULT;stdcall;
Function Stat(out statstg : TStatStg;grfStatFlag : DWORD) : HRESULT;stdcall;
function Clone(out stm : IStream) : HRESULT;stdcall;
end;
function EqualRect(const r1,r2 : TRect) : Boolean;
function EqualRect(const r1,r2 : TRectF) : Boolean;
function NormalizeRectF(const Pts: array of TPointF): TRectF; overload;
function NormalizeRect(const ARect: TRectF): TRectF; overload;
function Rect(Left,Top,Right,Bottom : Integer) : TRect; inline;
function RectF(Left,Top,Right,Bottom : Single) : TRectF; inline;
function Bounds(ALeft,ATop,AWidth,AHeight : Integer) : TRect; inline;
function Point(x,y : Integer) : TPoint; inline;
function PointF(x,y: Single) : TPointF; inline;
function PtInRect(const Rect : TRect; const p : TPoint) : Boolean;
function PtInRect(const Rect : TRectF; const p : TPointF) : Boolean;
function IntersectRect(const Rect1, Rect2: TRect): Boolean;
function IntersectRect(const Rect1, Rect2: TRectF): Boolean;
function IntersectRect(var Rect : TRect; const R1,R2 : TRect) : Boolean;
function IntersectRect(var Rect : TRectF; const R1,R2 : TRectF) : Boolean;
function RectCenter(var R: TRect; const Bounds: TRect): TRect;
function RectCenter(var R: TRectF; const Bounds: TRectF): TRectF;
function RectHeight(const Rect: TRect): Integer; inline;
function RectHeight(const Rect: TRectF): Single; inline;
function RectWidth(const Rect: TRect): Integer; inline;
function RectWidth(const Rect: TRectF): Single; inline;
function UnionRect(var Rect : TRect; const R1,R2 : TRect) : Boolean;
function UnionRect(var Rect : TRectF; const R1,R2 : TRectF) : Boolean;
function UnionRect(const R1,R2 : TRect) : TRect;
function UnionRect(const R1,R2 : TRectF) : TRectF;
function IsRectEmpty(const Rect : TRectF) : Boolean;
function IsRectEmpty(const Rect : TRect) : Boolean;
function OffsetRect(var Rect : TRect;DX : Integer;DY : Integer) : Boolean;
function OffsetRect(var Rect : TRectF;DX : Single;DY : Single) : Boolean;
procedure MultiplyRect(var R: TRectF; const DX, DY: Single);
function CenterPoint(const Rect: TRect): TPoint;
function InflateRect(var Rect: TRect; dx: Integer; dy: Integer): Boolean;
function InflateRect(var Rect: TRectF; dx: single; dy: Single): Boolean;
function Size(AWidth, AHeight: Integer): TSize; inline;
function Size(const ARect: TRect): TSize; inline;
function ScalePoint(const P: TPointF; dX, dY: Single): TPointF; overload;
function ScalePoint(const P: TPoint; dX, dY: Single): TPoint; overload;
function MinPoint(const P1, P2: TPointF): TPointF; overload;
function MinPoint(const P1, P2: TPoint): TPoint; overload;
function SplitRect(const Rect: TRect; SplitType: TSplitRectType; Size: Integer): TRect; overload;
function SplitRect(const Rect: TRect; SplitType: TSplitRectType; Percent: Double): TRect; overload;
function CenteredRect(const SourceRect: TRect; const aCenteredRect: TRect): TRect;
function IntersectRectF(out Rect: TRectF; const R1, R2: TRectF): Boolean;
function UnionRectF(out Rect: TRectF; const R1, R2: TRectF): Boolean;
type
TBitConverter = class
generic class procedure UnsafeFrom<T>(const ASrcValue: T; var ADestination: Array of Byte; AOffset: Integer = 0); static; {inline;}
generic class procedure From<T>(const ASrcValue: T; var ADestination: Array of Byte; AOffset: Integer = 0); static;
generic class function UnsafeInTo<T>(const ASource: Array of Byte; AOffset: Integer = 0): T; static; {inline;}
generic class function InTo<T>(const ASource: Array of Byte; AOffset: Integer = 0): T; static;
end;
Const
cPI: Single = 3.141592654;
cPIdiv180: Single = 0.017453292;
cPIdiv2: Single = 1.570796326;
cPIdiv4: Single = 0.785398163;
implementation
{$IFDEF FPC_DOTTEDUNITS}
Uses System.Math;
{$ELSE FPC_DOTTEDUNITS}
Uses Math;
{$ENDIF FPC_DOTTEDUNITS}
{$if (not defined(win32)) and (not defined(win64)) and (not defined(wince))}
{$i typshrd.inc}
{$endif}
function SmallPoint(X, Y: Integer): TSmallPoint; inline; overload;
begin
Result.X:=X;
Result.Y:=Y;
end;
function SmallPoint(XY: LongWord): TSmallPoint; overload;
begin
Result.X:=SmallInt(XY and $0000FFFF);
Result.Y:=SmallInt(XY shr 16);
end;
function MinPoint(const P1, P2: TPointF): TPointF; overload;
begin
Result:=P1;
if (P2.Y<P1.Y)
or ((P2.Y=P1.Y) and (P2.X<P1.X)) then
Result:=P2;
end;
function MinPoint(const P1, P2: TPoint): TPoint; overload;
begin
Result:=P1;
if (P2.Y<P1.Y)
or ((P2.Y=P1.Y) and (P2.X<P1.X)) then
Result:=P2;
end;
function ScalePoint(const P: TPointF; dX, dY: Single): TPointF; overload;
begin
Result.X:=P.X*dX;
Result.Y:=P.Y*dY;
end;
function ScalePoint(const P: TPoint; dX, dY: Single): TPoint; overload;
begin
Result.X:=Round(P.X*dX);
Result.Y:=Round(P.Y*dY);
end;
function NormalizeRectF(const Pts: array of TPointF): TRectF;
var
Pt: TPointF;
begin
Result.Left:=$FFFF;
Result.Top:=$FFFF;
Result.Right:=-$FFFF;
Result.Bottom:=-$FFFF;
for Pt in Pts do
begin
Result.Left:=Min(Pt.X,Result.left);
Result.Top:=Min(Pt.Y,Result.Top);
Result.Right:=Max(Pt.X,Result.Right);
Result.Bottom:=Max(Pt.Y,Result.Bottom);
end;
end;
function NormalizeRect(const aRect : TRectF): TRectF;
begin
With aRect do
Result:=NormalizeRectF([PointF(Left,Top),
PointF(Right,Top),
PointF(Right,Bottom),
PointF(Left,Bottom)]);
end;
function EqualRect(const r1,r2 : TRect) : Boolean;
begin
EqualRect:=(r1.left=r2.left) and (r1.right=r2.right) and (r1.top=r2.top) and (r1.bottom=r2.bottom);
end;
function EqualRect(const r1,r2 : TRectF) : Boolean;
begin
EqualRect:=r1.EqualsTo(r2);
end;
function Rect(Left,Top,Right,Bottom : Integer) : TRect; inline;
begin
Rect.Left:=Left;
Rect.Top:=Top;
Rect.Right:=Right;
Rect.Bottom:=Bottom;
end;
function RectF(Left,Top,Right,Bottom : Single) : TRectF; inline;
begin
RectF.Left:=Left;
RectF.Top:=Top;
RectF.Right:=Right;
RectF.Bottom:=Bottom;
end;
function Bounds(ALeft,ATop,AWidth,AHeight : Integer) : TRect; inline;
begin
Bounds.Left:=ALeft;
Bounds.Top:=ATop;
Bounds.Right:=ALeft+AWidth;
Bounds.Bottom:=ATop+AHeight;
end;
function Point(x,y : Integer) : TPoint; inline;
begin
Point.x:=x;
Point.y:=y;
end;
function PointF(x,y: Single) : TPointF; inline;
begin
PointF.x:=x;
PointF.y:=y;
end;
function PtInRect(const Rect : TRect;const p : TPoint) : Boolean;
begin
PtInRect:=(p.y>=Rect.Top) and
(p.y<Rect.Bottom) and
(p.x>=Rect.Left) and
(p.x<Rect.Right);
end;
function PtInRect(const Rect : TRectF;const p : TPointF) : Boolean;
begin
PtInRect:=(p.y>=Rect.Top) and
(p.y<Rect.Bottom) and
(p.x>=Rect.Left) and
(p.x<Rect.Right);
end;
function IntersectRectF(out Rect: TRectF; const R1, R2: TRectF): Boolean;
begin
Result:=IntersectRect(Rect,R1,R2);
end;
function UnionRectF(out Rect: TRectF; const R1, R2: TRectF): Boolean;
begin
Result:=UnionRect(Rect,R1,R2);
end;
function IntersectRect(const Rect1, Rect2: TRect): Boolean;
begin
Result:=(Rect1.Left<Rect2.Right)
and (Rect1.Right>Rect2.Left)
and (Rect1.Top<Rect2.Bottom)
and (Rect1.Bottom>Rect2.Top);
end;
function IntersectRect(var Rect : TRect;const R1,R2 : TRect) : Boolean;
var
lRect: TRect;
begin
lRect := R1;
if R2.Left > R1.Left then
lRect.Left := R2.Left;
if R2.Top > R1.Top then
lRect.Top := R2.Top;
if R2.Right < R1.Right then
lRect.Right := R2.Right;
if R2.Bottom < R1.Bottom then
lRect.Bottom := R2.Bottom;
// The var parameter is only assigned in the end to avoid problems
// when passing the same rectangle in the var and const parameters.
// See http://bugs.freepascal.org/view.php?id=17722
Result:=not IsRectEmpty(lRect);
if Result then
Rect := lRect
else
FillChar(Rect,SizeOf(Rect),0);
end;
function IntersectRect(const Rect1, Rect2: TRectF): Boolean;
begin
Result:=(Rect1.Left<Rect2.Right)
and (Rect1.Right>Rect2.Left)
and (Rect1.Top<Rect2.Bottom)
and (Rect1.Bottom>Rect2.Top);
end;
function IntersectRect(var Rect : TRectF;const R1,R2 : TRectF) : Boolean;
var
lRect: TRectF;
begin
lRect := R1;
if R2.Left > R1.Left then
lRect.Left := R2.Left;
if R2.Top > R1.Top then
lRect.Top := R2.Top;
if R2.Right < R1.Right then
lRect.Right := R2.Right;
if R2.Bottom < R1.Bottom then
lRect.Bottom := R2.Bottom;
// The var parameter is only assigned in the end to avoid problems
// when passing the same rectangle in the var and const parameters.
// See http://bugs.freepascal.org/view.php?id=17722
Result:=not IsRectEmpty(lRect);
if Result then
Rect := lRect
else
FillChar(Rect,SizeOf(Rect),0);
end;
function SplitRect(const Rect: TRect; SplitType: TSplitRectType; Size: Integer): TRect; overload;
begin
Result:=Rect.SplitRect(SplitType,Size);
end;
function SplitRect(const Rect: TRect; SplitType: TSplitRectType; Percent: Double): TRect; overload;
begin
Result:=Rect.SplitRect(SplitType,Percent);
end;
function CenteredRect(const SourceRect: TRect; const aCenteredRect: TRect): TRect;
var
W,H: Integer;
Center : TPoint;
begin
W:=aCenteredRect.Width;
H:=aCenteredRect.Height;
Center:=SourceRect.CenterPoint;
With Center do
Result:= Rect(X-(W div 2),Y-(H div 2),X+((W+1) div 2),Y+((H+1) div 2));
end;
function RectWidth(const Rect: TRect): Integer;
begin
Result:=Rect.Width;
end;
function RectWidth(const Rect: TRectF): Single;
begin
Result:=Rect.Width;
end;
function RectHeight(const Rect: TRect): Integer; inline;
begin
Result:=Rect.Height;
end;
function RectHeight(const Rect: TRectF): Single; inline;
begin
Result:=Rect.Height
end;
function RectCenter(var R: TRect; const Bounds: TRect): TRect;
var
C : TPoint;
CS : TPoint;
begin
C:=Bounds.CenterPoint;
CS:=R.CenterPoint;
OffsetRect(R,C.X-CS.X,C.Y-CS.Y);
Result:=R;
end;
function RectCenter(var R: TRectF; const Bounds: TRectF): TRectF;
Var
C,CS : TPointF;
begin
C:=Bounds.CenterPoint;
CS:=R.CenterPoint;
OffsetRect(R,C.X-CS.X,C.Y-CS.Y);
Result:=R;
end;
procedure MultiplyRect(var R: TRectF; const DX, DY: Single);
begin
R.Left:=DX*R.Left;
R.Right:=DX*R.Right;
R.Top:=DY*R.Top;
R.Bottom:=DY*R.Bottom;
end;
function UnionRect(const R1,R2 : TRect) : TRect;
begin
Result:=Default(TRect);
UnionRect(Result,R1,R2);
end;
function UnionRect(const R1,R2 : TRectF) : TRectF;
begin
Result:=Default(TRectF);
UnionRect(Result,R1,R2);
end;
function UnionRect(var Rect : TRect;const R1,R2 : TRect) : Boolean;
var
lRect: TRect;
begin
if IsRectEmpty(R1) then
lRect:=R2
else if IsRectEmpty(R2) then
lRect:=R1
else
begin
lRect:=R1;
if R2.Left<R1.Left then
lRect.Left:=R2.Left;
if R2.Top<R1.Top then
lRect.Top:=R2.Top;
if R2.Right>R1.Right then
lRect.Right:=R2.Right;
if R2.Bottom>R1.Bottom then
lRect.Bottom:=R2.Bottom;
end;
Result:=not IsRectEmpty(lRect);
if Result then
Rect:=lRect
else
FillChar(Rect,SizeOf(Rect),0);
end;
function UnionRect(var Rect : TRectF;const R1,R2 : TRectF) : Boolean;
var
lRect: TRectF;
begin
lRect:=R1;
if R2.Left<R1.Left then
lRect.Left:=R2.Left;
if R2.Top<R1.Top then
lRect.Top:=R2.Top;
if R2.Right>R1.Right then
lRect.Right:=R2.Right;
if R2.Bottom>R1.Bottom then
lRect.Bottom:=R2.Bottom;
Result:=not IsRectEmpty(lRect);
if Result then
Rect := lRect
else
FillChar(Rect,SizeOf(Rect),0);
end;
function IsRectEmpty(const Rect : TRect) : Boolean;
begin
IsRectEmpty:=(Rect.Right<=Rect.Left) or (Rect.Bottom<=Rect.Top);
end;
function IsRectEmpty(const Rect : TRectF) : Boolean;
begin
IsRectEmpty:=(Rect.Right<=Rect.Left) or (Rect.Bottom<=Rect.Top);
end;
function OffsetRect(var Rect : TRect;DX : Integer;DY : Integer) : Boolean;
begin
Result:=assigned(@Rect);
if Result then
with Rect do
begin
inc(Left,dx);
inc(Top,dy);
inc(Right,dx);
inc(Bottom,dy);
end;
end;
function Avg(a, b: Longint): Longint;
begin
if a < b then
Result := a + ((b - a) shr 1)
else
Result := b + ((a - b) shr 1);
end;
function OffsetRect(var Rect: TRectF; DX: Single; DY: Single): Boolean;
begin
Result:=assigned(@Rect);
if Result then
with Rect do
begin
Left:=Left+dx;
Right:=Right+dx;
Top:=Top+dy;
Bottom:=Bottom+dy;
end;
end;
function CenterPoint(const Rect: TRect): TPoint;
begin
with Rect do
begin
Result.X := Avg(Left, Right);
Result.Y := Avg(Top, Bottom);
end;
end;
function InflateRect(var Rect: TRect; dx: Integer; dy: Integer): Boolean;
begin
Result:=assigned(@Rect);
if Result then
with Rect do
begin
dec(Left, dx);
dec(Top, dy);
inc(Right, dx);
inc(Bottom, dy);
end;
end;
function InflateRect(var Rect: TRectF; dx: Single; dy: Single): Boolean;
begin
Result:=assigned(@Rect);
if Result then
with Rect do
begin
Left:=Left-dx;
Top:=Top-dy;
Right:=Right+dx;
Bottom:=Bottom+dy;
end;
end;
function Size(AWidth, AHeight: Integer): TSize; inline;
begin
Result.cx := AWidth;
Result.cy := AHeight;
end;
function Size(const ARect: TRect): TSize; inline;
begin
Result.cx := ARect.Right - ARect.Left;
Result.cy := ARect.Bottom - ARect.Top;
end;
Function SingleToStr(aValue : Single; aSize,aDecimals : Byte) : ShortString; inline;
var
S : ShortString;
Len,P : Byte;
begin
Str(aValue:aSize:aDecimals,S);
Len:=Length(S);
P:=1;
While (P<=Len) and (S[P]=' ') do
Inc(P);
if P>1 then
Delete(S,1,P-1);
Result:=S;
end;
{ TNullPtr }
class operator TNullPtr.:=(None: TNullPtr): Pointer;
begin
Result := nil;
end;
class operator TNullPtr.:=(None: TNullPtr): TObject;
begin
Result := nil;
end;
class operator TNullPtr.=(LHS: TNullPtr; RHS: Pointer): Boolean;
begin
Result := not Assigned(RHS);
end;
class operator TNullPtr.=(LHS: TNullPtr; RHS: TObject): Boolean;
begin
Result := not Assigned(RHS);
end;
class operator TNullPtr.=(LHS: Pointer; RHS: TNullPtr): Boolean;
begin
Result := not Assigned(LHS);
end;
class operator TNullPtr.=(LHS: TObject; RHS: TNullPtr): Boolean;
begin
Result := not Assigned(LHS);
end;
class operator TNullPtr.<>(LHS: TNullPtr; RHS: Pointer): Boolean;
begin
Result := Assigned(RHS);
end;
class operator TNullPtr.<>(LHS: TNullPtr; RHS: TObject): Boolean;
begin
Result := Assigned(RHS);
end;
class operator TNullPtr.<>(LHS: Pointer; RHS: TNullPtr): Boolean;
begin
Result := Assigned(LHS);
end;
class operator TNullPtr.<>(LHS: TObject; RHS: TNullPtr): Boolean;
begin
Result := Assigned(LHS);
end;
{ TPointF}
function TPointF.ToString : RTLString;
begin
Result:=ToString(8,2);
end;
function TPointF.ToString(aSize,aDecimals : Byte) : RTLString;
var
Sx,Sy : shortstring;
begin
Sx:=SingleToStr(X,aSize,aDecimals);
Sy:=SingleToStr(Y,aSize,aDecimals);
Result:='('+Sx+','+Sy+')';
end;
function TPointF.Add(const apt: TPoint): TPointF;
begin
result.x:=x+apt.x;
result.y:=y+apt.y;
end;
function TPointF.Add(const apt: TPointF): TPointF;
begin
result.x:=x+apt.x;
result.y:=y+apt.y;
end;
function TPointF.Subtract(const apt : TPointF): TPointF;
begin
result.x:=x-apt.x;
result.y:=y-apt.y;
end;
function TPointF.Subtract(const apt: TPoint): TPointF;
begin
result.x:=x-apt.x;
result.y:=y-apt.y;
end;
function TPointF.Distance(const apt : TPointF) : Single;
begin
result:=sqrt(sqr(apt.x-x)+sqr(apt.y-y));
end;
function TPointF.DotProduct(const apt: TPointF): Single;
begin
result:=x*apt.x+y*apt.y;
end;
function TPointF.IsZero : Boolean;
begin
result:=SameValue(x,0.0) and SameValue(y,0.0);
end;
procedure TPointF.Offset(const apt :TPointF);
begin
x:=x+apt.x;
y:=y+apt.y;
end;
procedure TPointF.Offset(const apt: TPoint);
begin
x:=x+apt.x;
y:=y+apt.y;
end;
procedure TPointF.Offset(dx,dy : Single);
begin
x:=x+dx;
y:=y+dy;
end;
function TPointF.EqualsTo(const apt: TPointF): Boolean;
begin
Result:=EqualsTo(apt,0);
end;
function TPointF.EqualsTo(const apt: TPointF; const aEpsilon: Single): Boolean;
function Eq(a,b : single) : boolean; inline;
begin
result:=abs(a-b)<=aEpsilon;
end;
begin
Result:=Eq(X,apt.X) and Eq(Y,apt.Y);
end;
function TPointF.Scale(afactor: Single): TPointF;
begin
result.x:=afactor*x;
result.y:=afactor*y;
end;
function TPointF.Ceiling: TPoint;
begin
result.x:=ceil(x);
result.y:=ceil(y);
end;
function TPointF.Truncate: TPoint;
begin
result.x:=trunc(x);
result.y:=trunc(y);
end;
function TPointF.Floor: TPoint;
begin
result.x:={$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Math.floor(x);
result.y:={$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Math.floor(y);
end;
function TPointF.Round: TPoint;
begin
result.x:=System.round(x);
result.y:=System.round(y);
end;
function TPointF.Length: Single;
begin
result:=sqrt(sqr(x)+sqr(y));
end;
function TPointF.Rotate(angle: single): TPointF;
var
sina, cosa: single;
begin
sincos(angle, sina, cosa);
result.x := x * cosa - y * sina;
result.y := x * sina + y * cosa;
end;
function TPointF.Reflect(const normal: TPointF): TPointF;
begin
result := self + (-2 * normal ** self) * normal;
end;
function TPointF.MidPoint(const b: TPointF): TPointF;
begin
result.x := 0.5 * (x + b.x);
result.y := 0.5 * (y + b.y);
end;
class function TPointF.Zero: TPointF;
begin
Result.X:=0;
Result.Y:=0;
end;
class function TPointF.PointInCircle(const pt, center: TPointF; radius: single): Boolean;
begin
result := sqr(center.x - pt.x) + sqr(center.y - pt.y) < sqr(radius);
end;
class function TPointF.PointInCircle(const pt, center: TPointF; radius: integer): Boolean;
begin
result := sqr(center.x - pt.x) + sqr(center.y - pt.y) < sqr(single(radius));
end;
function TPointF.Angle(const b: TPointF): Single;
begin
result := ArcTan2(y - b.y, x - b.x);
end;
function TPointF.AngleCosine(const b: TPointF): single;
begin
result := EnsureRange((self ** b) / sqrt((sqr(x) + sqr(y)) * (sqr(b.x) + sqr(b.y))), -1, 1);
end;
class operator TPointF.= (const apt1, apt2 : TPointF) : Boolean;
begin
result:=SameValue(apt1.x,apt2.x) and SameValue(apt1.y,apt2.y);
end;
class operator TPointF.<> (const apt1, apt2 : TPointF): Boolean;
begin
result:=NOT (SameValue(apt1.x,apt2.x) and Samevalue(apt1.y,apt2.y));
end;
class operator TPointF. * (const apt1, apt2: TPointF): TPointF;
begin
result.x:=apt1.x*apt2.x;
result.y:=apt1.y*apt2.y;
end;
class operator TPointF. * (afactor: single; const apt1: TPointF): TPointF;
begin
result:=apt1.Scale(afactor);
end;
class operator TPointF. * (const apt1: TPointF; afactor: single): TPointF;
begin
result:=apt1.Scale(afactor);
end;
class operator TPointF. ** (const apt1, apt2: TPointF): Single;
begin
result:=apt1.x*apt2.x + apt1.y*apt2.y;
end;
class operator TPointF.+ (const apt1, apt2 : TPointF): TPointF;
begin
result.x:=apt1.x+apt2.x;
result.y:=apt1.y+apt2.y;
end;
class operator TPointF.- (const apt1, apt2 : TPointF): TPointF;
begin
result.x:=apt1.x-apt2.x;
result.y:=apt1.y-apt2.y;
end;
class operator TPointF. - (const apt1: TPointF): TPointF;
begin
Result.x:=-apt1.x;
Result.y:=-apt1.y;
end;
class operator TPointF. / (const apt1: TPointF; afactor: single): TPointF;
begin
result:=apt1.Scale(1/afactor);
end;
class operator TPointF. := (const apt: TPoint): TPointF;
begin
Result.x:=apt.x;
Result.y:=apt.y;
end;
procedure TPointF.SetLocation(const apt :TPointF);
begin
x:=apt.x; y:=apt.y;
end;
procedure TPointF.SetLocation(const apt: TPoint);
begin
x:=apt.x; y:=apt.y;
end;
procedure TPointF.SetLocation(ax,ay : Single);
begin
x:=ax; y:=ay;
end;
class function TPointF.Create(const ax, ay: Single): TPointF;
begin
Result.x := ax;
Result.y := ay;
end;
class function TPointF.Create(const apt: TPoint): TPointF;
begin
Result.x := apt.X;
Result.y := apt.Y;
end;
function TPointF.CrossProduct(const apt: TPointF): Single;
begin
Result:=X*apt.Y-Y*apt.X;
end;
function TPointF.Normalize: TPointF;
var
L: Single;
begin
L:=Sqrt(Sqr(X)+Sqr(Y));
if SameValue(L,0,Epsilon) then
Result:=Self
else
begin
Result.X:=X/L;
Result.Y:=Y/L;
end;
end;
{ TSizeF }
function TSizeF.ToString(aSize,aDecimals : Byte) : RTLString;
var
Sx,Sy : shortstring;
begin
Sx:=SingleToStr(cx,aSize,aDecimals);
Sy:=SingleToStr(cy,aSize,aDecimals);
Result:='('+Sx+'x'+Sy+')';
end;
function TSizeF.ToString : RTLString;
begin
Result:=ToString(8,2);
end;
function TSizeF.Add(const asz: TSize): TSizeF;
begin
result.cx:=cx+asz.cx;
result.cy:=cy+asz.cy;
end;
function TSizeF.Add(const asz: TSizeF): TSizeF;
begin
result.cx:=cx+asz.cx;
result.cy:=cy+asz.cy;
end;
function TSizeF.Subtract(const asz : TSizeF): TSizeF;
begin
result.cx:=cx-asz.cx;
result.cy:=cy-asz.cy;
end;
function TSizeF.SwapDimensions:TSizeF;
begin
result.cx:=cy;
result.cy:=cx;
end;
function TSizeF.Subtract(const asz: TSize): TSizeF;
begin
result.cx:=cx-asz.cx;
result.cy:=cy-asz.cy;
end;
function TSizeF.Distance(const asz : TSizeF) : Single;
begin
result:=sqrt(sqr(asz.cx-cx)+sqr(asz.cy-cy));
end;
function TSizeF.IsZero : Boolean;
begin
result:=SameValue(cx,0.0) and SameValue(cy,0.0);
end;
function TSizeF.Scale(afactor: Single): TSizeF;
begin
result.cx:=afactor*cx;
result.cy:=afactor*cy;
end;
function TSizeF.Ceiling: TSize;
begin
result.cx:=ceil(cx);
result.cy:=ceil(cy);
end;
function TSizeF.Truncate: TSize;
begin
result.cx:=trunc(cx);
result.cy:=trunc(cy);
end;
function TSizeF.Floor: TSize;
begin
result.cx:={$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Math.floor(cx);
result.cy:={$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Math.floor(cy);
end;
function TSizeF.Round: TSize;
begin
result.cx:=System.round(cx);
result.cy:=System.round(cy);
end;
function TSizeF.Length: Single;
begin //distance(self) ?
result:=sqrt(sqr(cx)+sqr(cy));
end;
class operator TSizeF.= (const asz1, asz2 : TSizeF) : Boolean;
begin
result:=SameValue(asz1.cx,asz2.cx) and SameValue(asz1.cy,asz2.cy);
end;
class operator TSizeF.<> (const asz1, asz2 : TSizeF): Boolean;
begin
result:=NOT (SameValue(asz1.cx,asz2.cx) and Samevalue(asz1.cy,asz2.cy));
end;
class operator TSizeF. * (afactor: single; const asz1: TSizeF): TSizeF;
begin
result:=asz1.Scale(afactor);
end;
class operator TSizeF. * (const asz1: TSizeF; afactor: single): TSizeF;
begin
result:=asz1.Scale(afactor);
end;
class operator TSizeF.+ (const asz1, asz2 : TSizeF): TSizeF;
begin
result.cx:=asz1.cx+asz2.cx;
result.cy:=asz1.cy+asz2.cy;
end;
class operator TSizeF.- (const asz1, asz2 : TSizeF): TSizeF;
begin
result.cx:=asz1.cx-asz2.cx;
result.cy:=asz1.cy-asz2.cy;
end;
class operator TSizeF. - (const asz1: TSizeF): TSizeF;
begin
Result.cx:=-asz1.cx;
Result.cy:=-asz1.cy;
end;
class operator TSizeF. := (const apt: TPointF): TSizeF;
begin
Result.cx:=apt.x;
Result.cy:=apt.y;
end;
class operator TSizeF. := (const asz: TSize): TSizeF;
begin
Result.cx := asz.cx;
Result.cy := asz.cy;
end;
class operator TSizeF. := (const asz: TSizeF): TPointF;
begin
Result.x := asz.cx;
Result.y := asz.cy;
end;
class function TSizeF.Create(const ax, ay: Single): TSizeF;
begin
Result.cx := ax;
Result.cy := ay;
end;
class function TSizeF.Create(const asz: TSize): TSizeF;
begin
Result.cx := asz.cX;
Result.cy := asz.cY;
end;
{ TRectF }
function TRectF.ToString(aSize,aDecimals : Byte; aUseSize : Boolean = False) : RTLString;
var
S : RTLString;
begin
if aUseSize then
S:=Size.ToString(aSize,aDecimals)
else
S:=BottomRight.ToString(aSize,aDecimals);
Result:='['+TopLeft.ToString(aSize,aDecimals)+' - '+S+']';
end;
function TRectF.ToString(aUseSize: Boolean = False) : RTLString;
begin
Result:=ToString(8,2,aUseSize);
end;
class operator TRectF. * (L, R: TRectF): TRectF;
begin
Result := TRectF.Intersect(L, R);
end;
class operator TRectF. + (L, R: TRectF): TRectF;
begin
Result := TRectF.Union(L, R);
end;
class operator TRectF. := (const arc: TRect): TRectF;
begin
Result.Left:=arc.Left;
Result.Top:=arc.Top;
Result.Right:=arc.Right;
Result.Bottom:=arc.Bottom;
end;
class operator TRectF. <> (L, R: TRectF): Boolean;
begin
Result := not(L=R);
end;
class operator TRectF. = (L, R: TRectF): Boolean;
begin
Result :=
SameValue(L.Left,R.Left) and SameValue(L.Right,R.Right) and
SameValue(L.Top,R.Top) and SameValue(L.Bottom,R.Bottom);
end;
constructor TRectF.Create(ALeft, ATop, ARight, ABottom: Single);
begin
Left := ALeft;
Top := ATop;
Right := ARight;
Bottom := ABottom;
end;
constructor TRectF.Create(P1, P2: TPointF; Normalize: Boolean);
begin
TopLeft := P1;
BottomRight := P2;
if Normalize then
NormalizeRect;
end;
constructor TRectF.Create(Origin: TPointF);
begin
TopLeft := Origin;
BottomRight := Origin;
end;
constructor TRectF.Create(Origin: TPointF; AWidth, AHeight: Single);
begin
TopLeft := Origin;
Width := AWidth;
Height := AHeight;
end;
constructor TRectF.Create(R: TRectF; Normalize: Boolean);
begin
Self := R;
if Normalize then
NormalizeRect;
end;
constructor TRectF.Create(R: TRect; Normalize: Boolean);
begin
Self := R;
if Normalize then
NormalizeRect;
end;
function TRectF.CenterPoint: TPointF;
begin
Result.X := (Right-Left) / 2 + Left;
Result.Y := (Bottom-Top) / 2 + Top;
end;
function TRectF.Ceiling: TRectF;
begin
Result.BottomRight:=BottomRight.Ceiling;
Result.TopLeft:=TopLeft.Ceiling;
end;
function TRectF.CenterAt(const Dest: TRectF): TRectF;
begin
Result:=Self;
RectCenter(Result,Dest);
end;
function TRectF.Fit(const Dest: TRectF): Single;
var
R : TRectF;
begin
R:=FitInto(Dest,Result);
Self:=R;
end;
function TRectF.FitInto(const Dest: TRectF; out Ratio: Single): TRectF;
begin
if (Dest.Width<=0) or (Dest.Height<=0) then
begin
Ratio:=1.0;
exit(Self);
end;
Ratio:=Max(Self.Width / Dest.Width, Self.Height / Dest.Height);
if Ratio=0 then
exit(Self);
Result.Width:=Self.Width / Ratio;
Result.Height:=Self.Height / Ratio;
// Center the result within the Dest rectangle
Result.Left:=Dest.Left + (Dest.Width - Result.Width) / 2;
Result.Top:=Dest.Top + (Dest.Height - Result.Height) / 2;
end;
function TRectF.FitInto(const Dest: TRectF): TRectF;
var
Ratio: Single;
begin
Result:=FitInto(Dest,Ratio);
end;
function TRectF.PlaceInto(const Dest: TRectF; const AHorzAlign: THorzRectAlign = THorzRectAlign.Center; const AVertAlign: TVertRectAlign = TVertRectAlign.Center): TRectF;
var
R : TRectF;
X,Y : Single;
D : TRectF absolute dest;
begin
if (Height>Dest.Height) or (Width>Dest.Width) then
R:=FitInto(Dest)
else
R:=Self;
case AHorzAlign of
THorzRectAlign.Left:
X:=D.Left;
THorzRectAlign.Center:
X:=(D.Left+D.Right-R.Width)/2;
THorzRectAlign.Right:
X:=D.Right-R.Width;
end;
case AVertAlign of
TVertRectAlign.Top:
Y:=D.Top;
TVertRectAlign.Center:
Y:=(D.Top+D.Bottom-R.Height)/2;
TVertRectAlign.Bottom:
Y:=D.Bottom-R.Height;
end;
R.SetLocation(PointF(X,Y));
Result:=R;
end;
function TRectF.SnapToPixel(AScale: Single; APlaceBetweenPixels: Boolean): TRectF;
function sc (S : single) : single; inline;
begin
Result:=System.Trunc(S*AScale)/AScale;
end;
var
R : TRectF;
Off: Single;
begin
if AScale<=0 then
AScale := 1;
R.Top:=Sc(Top);
R.Left:=Sc(Left);
R.Width:=Sc(Width);
R.Height:=Sc(Height);
if APlaceBetweenPixels then
begin
Off:=1/(2*aScale);
R.Offset(Off,Off);
end;
Result:=R;
end;
function TRectF.Contains(Pt: TPointF): Boolean;
begin
Result := (Left <= Pt.X) and (Pt.X < Right) and (Top <= Pt.Y) and (Pt.Y < Bottom);
end;
function TRectF.Contains(R: TRectF): Boolean;
begin
Result := (Left <= R.Left) and (R.Right <= Right) and (Top <= R.Top) and (R.Bottom <= Bottom);
end;
class function TRectF.Empty: TRectF;
begin
Result := TRectF.Create(0,0,0,0);
end;
function TRectF.EqualsTo(const R: TRectF; const Epsilon: Single): Boolean;
begin
Result:=TopLeft.EqualsTo(R.TopLeft,Epsilon);
Result:=Result and BottomRight.EqualsTo(R.BottomRight,Epsilon);
end;
function TRectF.GetHeight: Single;
begin
result:=bottom-top;
end;
function TRectF.GetLocation: TPointF;
begin
result.x:=Left; result.y:=top;
end;
function TRectF.GetSize: TSizeF;
begin
result.cx:=width; result.cy:=height;
end;
function TRectF.GetWidth: Single;
begin
result:=right-left;
end;
procedure TRectF.Inflate(DX, DY: Single);
begin
Left:=Left-dx;
Top:=Top-dy;
Right:=Right+dx;
Bottom:=Bottom+dy;
end;
procedure TRectF.Intersect(R: TRectF);
begin
Self := Intersect(Self, R);
end;
class function TRectF.Intersect(R1: TRectF; R2: TRectF): TRectF;
begin
Result := R1;
if R2.Left > R1.Left then
Result.Left := R2.Left;
if R2.Top > R1.Top then
Result.Top := R2.Top;
if R2.Right < R1.Right then
Result.Right := R2.Right;
if R2.Bottom < R1.Bottom then
Result.Bottom := R2.Bottom;
end;
function TRectF.IntersectsWith(R: TRectF): Boolean;
begin
Result := (Left < R.Right) and (R.Left < Right) and (Top < R.Bottom) and (R.Top < Bottom);
end;
function TRectF.IsEmpty: Boolean;
begin
Result := (CompareValue(Right,Left)<=0) or (CompareValue(Bottom,Top)<=0);
end;
procedure TRectF.NormalizeRect;
var
x: Single;
begin
if Top>Bottom then
begin
x := Top;
Top := Bottom;
Bottom := x;
end;
if Left>Right then
begin
x := Left;
Left := Right;
Right := x;
end
end;
procedure TRectF.Inflate(DL, DT, DR, DB: Single);
begin
Left:=Left-dl;
Top:=Top-dt;
Right:=Right+dr;
Bottom:=Bottom+db;
end;
procedure TRectF.Offset(const dx, dy: Single);
begin
left:=left+dx; right:=right+dx;
bottom:=bottom+dy; top:=top+dy;
end;
procedure TRectF.Offset(DP: TPointF);
begin
left:=left+DP.x; right:=right+DP.x;
bottom:=bottom+DP.y; top:=top+DP.y;
end;
function TRectF.Truncate: TRect;
begin
Result.BottomRight:=BottomRight.Truncate;
Result.TopLeft:=TopLeft.Truncate;
end;
function TRectF.Round: TRect;
begin
Result.BottomRight:=BottomRight.Round;
Result.TopLeft:=TopLeft.Round;
end;
procedure TRectF.SetHeight(AValue: Single);
begin
bottom:=top+avalue;
end;
procedure TRectF.SetLocation(X, Y: Single);
begin
Offset(X-Left, Y-Top);
end;
procedure TRectF.SetLocation(P: TPointF);
begin
SetLocation(P.X, P.Y);
end;
procedure TRectF.SetSize(AValue: TSizeF);
begin
bottom:=top+avalue.cy;
right:=left+avalue.cx;
end;
procedure TRectF.SetWidth(AValue: Single);
begin
right:=left+avalue;
end;
class function TRectF.Union(const Points: array of TPointF): TRectF;
var
i: Integer;
begin
if Length(Points) > 0 then
begin
Result.TopLeft := Points[Low(Points)];
Result.BottomRight := Points[Low(Points)];
for i := Low(Points)+1 to High(Points) do
begin
if Points[i].X < Result.Left then Result.Left := Points[i].X;
if Points[i].X > Result.Right then Result.Right := Points[i].X;
if Points[i].Y < Result.Top then Result.Top := Points[i].Y;
if Points[i].Y > Result.Bottom then Result.Bottom := Points[i].Y;
end;
end else
Result := Empty;
end;
procedure TRectF.Union(const r: TRectF);
begin
left:=min(r.left,left);
top:=min(r.top,top);
right:=max(r.right,right);
bottom:=max(r.bottom,bottom);
end;
class function TRectF.Union(R1, R2: TRectF): TRectF;
begin
Result:=R1;
Result.Union(R2);
end;
{ TPoint3D }
function TPoint3D.ToString(aSize,aDecimals : Byte) : RTLString;
var
Sx,Sy,Sz : shortstring;
P : integer;
begin
Sx:=SingleToStr(X,aSize,aDecimals);
Sy:=SingleToStr(Y,aSize,aDecimals);
Sz:=SingleToStr(Z,aSize,aDecimals);
Result:='('+Sx+','+Sy+','+Sz+')';
end;
function TPoint3D.ToString : RTLString;
begin
Result:=ToString(8,2);
end;
constructor TPoint3D.Create(const ax,ay,az:single);
begin
x:=ax; y:=ay; z:=az;
end;
procedure TPoint3D.Offset(const adeltax,adeltay,adeltaz:single);
begin
x:=x+adeltax; y:=y+adeltay; z:=z+adeltaz;
end;
procedure TPoint3D.Offset(const adelta:TPoint3D);
begin
x:=x+adelta.x; y:=y+adelta.y; z:=z+adelta.z;
end;
generic class procedure TBitConverter.UnsafeFrom<T>(const ASrcValue: T; var ADestination: Array of Byte; AOffset: Integer = 0);
begin
move(ASrcValue, ADestination[AOffset], SizeOf(T));
end;
generic class procedure TBitConverter.From<T>(const ASrcValue: T; var ADestination: Array of Byte; AOffset: Integer = 0);
begin
if AOffset < 0 then
System.Error(reRangeError);
if IsManagedType(T) then
System.Error(reInvalidCast);
if Length(ADestination) < (SizeOf(T) + AOffset) then
System.Error(reRangeError);
TBitConverter.specialize UnsafeFrom<T>(ASrcValue, ADestination, AOffset);
end;
generic class function TBitConverter.UnsafeInTo<T>(const ASource: Array of Byte; AOffset: Integer = 0): T;
begin
move(ASource[AOffset], Result, SizeOf(T));
end;
generic class function TBitConverter.InTo<T>(const ASource: Array of Byte; AOffset: Integer = 0): T;
begin
if AOffset < 0 then
System.Error(reRangeError);
if IsManagedType(T) then
System.Error(reInvalidCast);
if Length(ASource) < (SizeOf(T) + AOffset) then
System.Error(reRangeError);
Result := TBitConverter.specialize UnsafeInTo<T>(ASource, AOffset);
end;
end.