📄 gr32.pas
字号:
case Rounding of
rrClosest:
begin
Result.Left := FixedRound(Left);
Result.Top := FixedRound(Top);
Result.Right := FixedRound(Right);
Result.Bottom := FixedRound(Bottom);
end;
rrInside:
begin
Result.Left := FixedCeil(Left);
Result.Top := FixedCeil(Top);
Result.Right := FixedFloor(Right);
Result.Bottom := FixedFloor(Bottom);
if Result.Right < Result.Left then Result.Right := Result.Left;
if Result.Bottom < Result.Top then Result.Bottom := Result.Top;
end;
rrOutside:
begin
Result.Left := FixedFloor(Left);
Result.Top := FixedFloor(Top);
Result.Right := FixedCeil(Right);
Result.Bottom := FixedCeil(Bottom);
end;
end;
end;
function FixedRect(const L, T, R, B: TFixed): TFixedRect;
begin
with Result do
begin
Left := L;
Top := T;
Right := R;
Bottom := B;
end;
end;
function FixedRect(const ARect: TRect): TFixedRect;
begin
with Result do
begin
Left := ARect.Left shl 16;
Top := ARect.Top shl 16;
Right := ARect.Right shl 16;
Bottom := ARect.Bottom shl 16;
end;
end;
function FixedRect(const FR: TFloatRect): TFixedRect;
begin
with Result do
begin
Left := Round(FR.Left * 65536);
Top := Round(FR.Top * 65536);
Right := Round(FR.Right * 65536);
Bottom := Round(FR.Bottom * 65536);
end;
end;
function FloatRect(const L, T, R, B: TFloat): TFloatRect;
begin
with Result do
begin
Left := L;
Top := T;
Right := R;
Bottom := B;
end;
end;
function FloatRect(const ARect: TRect): TFloatRect;
begin
with Result do
begin
Left := ARect.Left;
Top := ARect.Top;
Right := ARect.Right;
Bottom := ARect.Bottom;
end;
end;
function FloatRect(const FXR: TFixedRect): TFloatRect;
begin
with Result do
begin
Left := FXR.Left * FixedToFloat;
Top := FXR.Top * FixedToFloat;
Right := FXR.Right * FixedToFloat;
Bottom := FXR.Bottom * FixedToFloat;
end;
end;
function IntersectRect(out Dst: TRect; const R1, R2: TRect): Boolean;
begin
if R1.Left >= R2.Left then Dst.Left := R1.Left else Dst.Left := R2.Left;
if R1.Right <= R2.Right then Dst.Right := R1.Right else Dst.Right := R2.Right;
if R1.Top >= R2.Top then Dst.Top := R1.Top else Dst.Top := R2.Top;
if R1.Bottom <= R2.Bottom then Dst.Bottom := R1.Bottom else Dst.Bottom := R2.Bottom;
Result := (Dst.Right >= Dst.Left) and (Dst.Bottom >= Dst.Top);
if not Result then Dst := ZERO_RECT;
end;
function IntersectRect(out Dst: TFloatRect; const FR1, FR2: TFloatRect): Boolean;
begin
Dst.Left := Max(FR1.Left, FR2.Left);
Dst.Right := Min(FR1.Right, FR2.Right);
Dst.Top := Max(FR1.Top, FR2.Top);
Dst.Bottom := Min(FR1.Bottom, FR2.Bottom);
Result := (Dst.Right >= Dst.Left) and (Dst.Bottom >= Dst.Top);
if not Result then FillLongword(Dst, 4, 0);
end;
function UnionRect(out Rect: TRect; const R1, R2: TRect): Boolean;
begin
Rect := R1;
if not IsRectEmpty(R2) then
begin
if R2.Left < R1.Left then Rect.Left := R2.Left;
if R2.Top < R1.Top then Rect.Top := R2.Top;
if R2.Right > R1.Right then Rect.Right := R2.Right;
if R2.Bottom > R1.Bottom then Rect.Bottom := R2.Bottom;
end;
Result := not IsRectEmpty(Rect);
if not Result then Rect := ZERO_RECT;
end;
function UnionRect(out Rect: TFloatRect; const R1, R2: TFloatRect): Boolean;
begin
Rect := R1;
if not IsRectEmpty(R2) then
begin
if R2.Left < R1.Left then Rect.Left := R2.Left;
if R2.Top < R1.Top then Rect.Top := R2.Top;
if R2.Right > R1.Right then Rect.Right := R2.Right;
if R2.Bottom > R1.Bottom then Rect.Bottom := R2.Bottom;
end;
Result := not IsRectEmpty(Rect);
if not Result then FillLongword(Rect, 4, 0);;
end;
function EqualRect(const R1, R2: TRect): Boolean;
begin
Result := CompareMem(@R1, @R2, SizeOf(TRect));
end;
function EqualRectSize(const R1, R2: TRect): Boolean;
begin
Result := ((R1.Right - R1.Left) = (R2.Right - R2.Left)) and
((R1.Bottom - R1.Top) = (R2.Bottom - R2.Top));
end;
function EqualRectSize(const R1, R2: TFloatRect): Boolean;
var
_R1: TFixedRect;
_R2: TFixedRect;
begin
_R1 := FixedRect(R1);
_R2 := FixedRect(R2);
Result := ((_R1.Right - _R1.Left) = (_R2.Right - _R2.Left)) and
((_R1.Bottom - _R1.Top) = (_R2.Bottom - _R2.Top));
end;
procedure InflateRect(var R: TRect; Dx, Dy: Integer);
begin
Dec(R.Left, Dx); Dec(R.Top, Dy);
Inc(R.Right, Dx); Inc(R.Bottom, Dy);
end;
procedure InflateRect(var FR: TFloatRect; Dx, Dy: TFloat);
begin
with FR do
begin
Left := Left - Dx; Top := Top - Dy;
Right := Right + Dx; Bottom := Bottom + Dy;
end;
end;
procedure OffsetRect(var R: TRect; Dx, Dy: Integer);
begin
Inc(R.Left, Dx); Inc(R.Top, Dy);
Inc(R.Right, Dx); Inc(R.Bottom, Dy);
end;
procedure OffsetRect(var FR: TFloatRect; Dx, Dy: TFloat);
begin
with FR do
begin
Left := Left + Dx; Top := Top + Dy;
Right := Right + Dx; Bottom := Bottom + Dy;
end;
end;
function IsRectEmpty(const R: TRect): Boolean;
begin
Result := (R.Right <= R.Left) or (R.Bottom <= R.Top);
end;
function IsRectEmpty(const FR: TFloatRect): Boolean;
begin
Result := (FR.Right <= FR.Left) or (FR.Bottom <= FR.Top);
end;
function PtInRect(const R: TRect; const P: TPoint): Boolean;
begin
Result := (P.X >= R.Left) and (P.X < R.Right) and
(P.Y >= R.Top) and (P.Y < R.Bottom);
end;
{ Gamma / Pixel Shape Correction table }
procedure SetGamma(Gamma: Single);
var
i: Integer;
begin
for i := 0 to 255 do
GAMMA_TABLE[i] := Round(255 * Power(i / 255, Gamma));
end;
{ TNotifiablePersistent }
procedure TNotifiablePersistent.BeginUpdate;
begin
Inc(FUpdateCount);
end;
procedure TNotifiablePersistent.Changed;
begin
if (FUpdateCount = 0) and Assigned(FOnChange) then FOnChange(Self);
end;
procedure TNotifiablePersistent.EndUpdate;
begin
Assert(FUpdateCount > 0, 'Unpaired TThreadPersistent.EndUpdate');
Dec(FUpdateCount);
end;
{ TThreadPersistent }
constructor TThreadPersistent.Create;
begin
InitializeCriticalSection(FLock);
end;
destructor TThreadPersistent.Destroy;
begin
DeleteCriticalSection(FLock);
inherited;
end;
procedure TThreadPersistent.Lock;
begin
InterlockedIncrement(FLockCount);
EnterCriticalSection(FLock);
end;
procedure TThreadPersistent.Unlock;
begin
LeaveCriticalSection(FLock);
InterlockedDecrement(FLockCount);
end;
{ TCustomMap }
procedure TCustomMap.ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer);
begin
Width := NewWidth;
Height := NewHeight;
end;
procedure TCustomMap.Delete;
begin
SetSize(0, 0);
end;
function TCustomMap.Empty: Boolean;
begin
Result := (Width = 0) or (Height = 0);
end;
procedure TCustomMap.Resized;
begin
if Assigned(FOnResize) then FOnResize(Self);
end;
procedure TCustomMap.SetHeight(NewHeight: Integer);
begin
SetSize(Width, NewHeight);
end;
function TCustomMap.SetSize(NewWidth, NewHeight: Integer): Boolean;
begin
if NewWidth < 0 then NewWidth := 0;
if NewHeight < 0 then NewHeight := 0;
Result := (NewWidth <> FWidth) or (NewHeight <> FHeight);
if Result then
begin
ChangeSize(FWidth, FHeight, NewWidth, NewHeight);
Changed;
Resized;
end;
end;
function TCustomMap.SetSizeFrom(Source: TPersistent): Boolean;
begin
if Source is TCustomMap then
Result := SetSize(TCustomMap(Source).Width, TCustomMap(Source).Height)
else if Source is TGraphic then
Result := SetSize(TGraphic(Source).Width, TGraphic(Source).Height)
else if Source is TControl then
Result := SetSize(TControl(Source).Width, TControl(Source).Height)
else if Source = nil then
Result := SetSize(0, 0)
else
raise Exception.Create('Can''t set size from ''' + Source.ClassName + '''');
end;
procedure TCustomMap.SetWidth(NewWidth: Integer);
begin
SetSize(NewWidth, Height);
end;
{ TBitmap32 }
constructor TBitmap32.Create;
begin
inherited;
{$IFNDEF CLX}
FillChar(FBitmapInfo, SizeOf(TBitmapInfo), 0);
with FBitmapInfo.bmiHeader do
begin
biSize := SizeOf(TBitmapInfoHeader);
biPlanes := 1;
biBitCount := 32;
biCompression := BI_RGB;
end;
{$ENDIF}
FOuterColor := $00000000; // by default as full transparency black
FFont := TFont.Create;
FFont.OnChange := FontChanged;
{$IFNDEF CLX}
FFont.OwnerCriticalSection := @FLock;
{$ENDIF}
FMasterAlpha := $FF;
FPenColor := clWhite32;
FStippleStep := 1;
FCombineMode := cmBlend;
FResampler := TNearestResampler.Create(Self);
end;
destructor TBitmap32.Destroy;
begin
BeginUpdate;
Lock;
try
DeleteCanvas;
SetSize(0, 0);
FFont.Free;
FResampler.Free;
finally
Unlock;
end;
inherited;
end;
procedure TBitmap32.HandleChanged;
begin
if FCanvas <> nil then FCanvas.Handle := Self.Handle;
if Assigned(FOnHandleChanged) then FOnHandleChanged(Self);
end;
procedure TBitmap32.ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer);
begin
try
FontChanged(Self);
DeleteCanvas; // Patch by Thomas Bauer.....
{$IFDEF CLX}
if Assigned(FHDC) then QPainter_destroy(FHDC);
FHDC := nil;
if Assigned(FHandle) then QImage_destroy(FHandle);
FHandle := nil;
if Assigned(FPixmap) then QPixmap_destroy(FPixmap);
FPixmap := nil;
FPixmapChanged := False;
FPixmapActive := False;
{$ELSE}
if FHDC <> 0 then DeleteDC(FHDC);
FHDC := 0;
if FHandle <> 0 then DeleteObject(FHandle);
FHandle := 0;
{$ENDIF}
FBits := nil;
Width := 0;
Height := 0;
if (NewWidth > 0) and (NewHeight > 0) then
begin
{$IFDEF CLX}
FHandle := QImage_create(NewWidth, NewHeight, 32, 1, QImageEndian_IgnoreEndian);
if FHandle <> nil then
begin
FBits := Pointer(QImage_bits(FHandle));
// clear it since QT doesn't initialize the image data:
FillLongword(FBits[0], NewWidth * NewHeight, clBlack32);
end;
{$ELSE}
with FBitmapInfo.bmiHeader do
begin
biWidth := NewWidth;
biHeight := -NewHeight;
end;
FHandle := CreateDIBSection(0, FBitmapInfo, DIB_RGB_COLORS, Pointer(FBits), 0, 0);
{$ENDIF}
if FBits = nil then raise Exception.Create('Can''t allocate the DIB handle');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -