📄 gr32.pas
字号:
{$ELSE}
if WinColor < 0 then WinColor := GetSysColor(WinColor and $000000FF);
{$ENDIF}
{$IFDEF WIN_COLOR_FIX}
Result := $FF000000;
I := (WinColor and $00FF0000) shr 16;
if I <> 0 then Result := Result or TColor32(Integer(I) - 1);
I := WinColor and $0000FF00;
if I <> 0 then Result := Result or TColor32(Integer(I) - $00000100);
I := WinColor and $000000FF;
if I <> 0 then Result := Result or TColor32(Integer(I) - 1) shl 16;
{$ELSE}
asm
MOV EAX,WinColor
BSWAP EAX
MOV AL,$FF
ROR EAX,8
MOV Result,EAX
end;
{$ENDIF}
end;
function Color32(R, G, B: Byte; A: Byte = $FF): TColor32; overload;
asm
MOV AH,A
SHL EAX,16
MOV AH,DL
MOV AL,CL
end;
function Color32(Index: Byte; var Palette: TPalette32): TColor32; overload;
begin
Result := Palette[Index];
end;
function Gray32(Intensity: Byte; Alpha: Byte = $FF): TColor32;
begin
Result := TColor32(Alpha) shl 24 + TColor32(Intensity) shl 16 +
TColor32(Intensity) shl 8 + TColor32(Intensity);
end;
function WinColor(Color32: TColor32): TColor;
asm
// the alpha channel byte is set to zero!
ROL EAX,8 // ABGR -> BGRA
XOR AL,AL // BGRA -> BGR0
BSWAP EAX // BGR0 -> 0RGB
end;
function ArrayOfColor32(Colors: array of TColor32): TArrayOfColor32;
var
L: Integer;
begin
// build a dynamic color array from specified colors
L := High(Colors) + 1;
SetLength(Result, L);
MoveLongword(Colors[0], Result[0], L);
end;
procedure Color32ToRGB(Color32: TColor32; var R, G, B: Byte);
begin
R := (Color32 and $00FF0000) shr 16;
G := (Color32 and $0000FF00) shr 8;
B := Color32 and $000000FF;
end;
procedure Color32ToRGBA(Color32: TColor32; var R, G, B, A: Byte);
begin
A := Color32 shr 24;
R := (Color32 and $00FF0000) shr 16;
G := (Color32 and $0000FF00) shr 8;
B := Color32 and $000000FF;
end;
function RedComponent(Color32: TColor32): Integer;
begin
Result := (Color32 and $00FF0000) shr 16;
end;
function GreenComponent(Color32: TColor32): Integer;
begin
Result := (Color32 and $0000FF00) shr 8;
end;
function BlueComponent(Color32: TColor32): Integer;
begin
Result := Color32 and $000000FF;
end;
function AlphaComponent(Color32: TColor32): Integer;
begin
Result := Color32 shr 24;
end;
function Intensity(Color32: TColor32): Integer;
begin
// (R * 61 + G * 174 + B * 21) / 256
Result := (
(Color32 and $00FF0000) shr 16 * 61 +
(Color32 and $0000FF00) shr 8 * 174 +
(Color32 and $000000FF) * 21
) shr 8;
end;
function SetAlpha(Color32: TColor32; NewAlpha: Integer): TColor32;
begin
if NewAlpha < 0 then NewAlpha := 0
else if NewAlpha > 255 then NewAlpha := 255;
Result := (Color32 and $00FFFFFF) or (TColor32(NewAlpha) shl 24);
end;
{ Color space conversions }
function HSLtoRGB(H, S, L: Single): TColor32;
const
OneOverThree = 1 / 3;
var
M1, M2: Single;
R, G, B: Byte;
function HueToColor(Hue: Single): Byte;
var
V: Double;
begin
Hue := Hue - Floor(Hue);
if 6 * Hue < 1 then V := M1 + (M2 - M1) * Hue * 6
else if 2 * Hue < 1 then V := M2
else if 3 * Hue < 2 then V := M1 + (M2 - M1) * (2 / 3 - Hue) * 6
else V := M1;
Result := Round(255 * V);
end;
begin
if S = 0 then
begin
R := Round(255 * L);
G := R;
B := R;
end
else
begin
if L <= 0.5 then M2 := L * (1 + S)
else M2 := L + S - L * S;
M1 := 2 * L - M2;
R := HueToColor(H + OneOverThree);
G := HueToColor(H);
B := HueToColor(H - OneOverThree)
end;
Result := Color32(R, G, B, 255);
end;
procedure RGBtoHSL(RGB: TColor32; out H, S, L : Single);
var
R, G, B, D, Cmax, Cmin: Single;
begin
R := RedComponent(RGB) / 255;
G := GreenComponent(RGB) / 255;
B := BlueComponent(RGB) / 255;
Cmax := Max(R, Max(G, B));
Cmin := Min(R, Min(G, B));
L := (Cmax + Cmin) / 2;
if Cmax = Cmin then
begin
H := 0;
S := 0
end
else
begin
D := Cmax - Cmin;
if L < 0.5 then S := D / (Cmax + Cmin)
else S := D / (2 - Cmax - Cmin);
if R = Cmax then H := (G - B) / D
else
if G = Cmax then H := 2 + (B - R) / D
else H := 4 + (R - G) / D;
H := H / 6;
if H < 0 then H := H + 1
end;
end;
function HSLtoRGB(H, S, L: Integer): TColor32;
var
V, M, M1, M2, VSF: Integer;
begin
if L <= $7F then
V := L * (256 + S) shr 8
else
V := L + S - L * S div 255;
if V <= 0 then
Result := Color32(0, 0, 0, 0)
else
begin
M := L * 2 - V;
H := H * 6;
VSF := (V - M) * (H and $FF) shr 8;
M1 := M + VSF;
M2 := V - VSF;
case H shr 8 of
0: Result := Color32(V, M1, M, 0);
1: Result := Color32(M2, V, M, 0);
2: Result := Color32(M, V, M1, 0);
3: Result := Color32(M, M2, V, 0);
4: Result := Color32(M1, M, V, 0);
5: Result := Color32(V, M, M2, 0);
else
Result := 0;
end;
end;
end;
function Max(const A, B, C: Integer): Integer; overload;
asm
CMP EDX,EAX
db $0F,$4F,$C2 /// CMOVG EAX,EDX
CMP ECX,EAX
db $0F,$4F,$C1 /// CMOVG EAX,ECX
end;
function Min(const A, B, C: Integer): Integer; overload;
asm
CMP EDX,EAX
db $0F,$4C,$C2 /// CMOVL EAX,EDX
CMP ECX,EAX
db $0F,$4C,$C1 /// CMOVL EAX,ECX
end;
procedure RGBtoHSL(RGB: TColor32; out H, S, L: Byte);
var
R, G, B, D, Cmax, Cmin, HL: Integer;
begin
R := (RGB shr 16) and $ff;
G := (RGB shr 8) and $ff;
B := RGB and $ff;
Cmax := Max(R, G, B);
Cmin := Min(R, G, B);
L := (Cmax + Cmin) div 2;
if Cmax = Cmin then
begin
H := 0;
S := 0
end
else
begin
D := (Cmax - Cmin) * 255;
if L <= $7F then
S := D div (Cmax + Cmin)
else
S := D div (255 * 2 - Cmax - Cmin);
D := D * 6;
if R = Cmax then
HL := (G - B) * 255 * 255 div D
else if G = Cmax then
HL := 255 * 2 div 6 + (B - R) * 255 * 255 div D
else
HL := 255 * 4 div 6 + (R - G) * 255 * 255 div D;
if HL < 0 then HL := HL + 255 * 2;
H := HL;
end;
end;
{ Palette conversion }
{$IFNDEF CLX}
function WinPalette(const P: TPalette32): HPALETTE;
var
L: TMaxLogPalette;
L0: LOGPALETTE absolute L;
I: Cardinal;
Cl: TColor32;
begin
L.palVersion := $300;
L.palNumEntries := 256;
for I := 0 to 255 do
begin
Cl := P[I];
with L.palPalEntry[I] do
begin
peFlags := 0;
peRed := RedComponent(Cl);
peGreen := GreenComponent(Cl);
peBlue := BlueComponent(Cl);
end;
end;
Result := CreatePalette(l0);
end;
{$ENDIF}
{ Fixed-point conversion routines }
function Fixed(S: Single): TFixed;
begin
Result := Round(S * 65536);
end;
function Fixed(I: Integer): TFixed;
begin
Result := I shl 16;
end;
{ Points }
function Point(X, Y: Integer): TPoint;
begin
Result.X := X;
Result.Y := Y;
end;
function Point(const FP: TFloatPoint): TPoint;
begin
Result.X := Round(FP.X);
Result.Y := Round(FP.Y);
end;
function Point(const FXP: TFixedPoint): TPoint;
begin
Result.X := FixedRound(FXP.X);
Result.Y := FixedRound(FXP.Y);
end;
function FloatPoint(X, Y: Single): TFloatPoint;
begin
Result.X := X;
Result.Y := Y;
end;
function FloatPoint(const P: TPoint): TFloatPoint;
begin
Result.X := P.X;
Result.Y := P.Y;
end;
function FloatPoint(const FXP: TFixedPoint): TFloatPoint;
const
F = 1 / 65536;
begin
with FXP do
begin
Result.X := X * F;
Result.Y := Y * F;
end;
end;
function FixedPoint(X, Y: Integer): TFixedPoint; overload;
begin
Result.X := X shl 16;
Result.Y := Y shl 16;
end;
function FixedPoint(X, Y: Single): TFixedPoint; overload;
begin
Result.X := Round(X * 65536);
Result.Y := Round(Y * 65536);
end;
function FixedPoint(const P: TPoint): TFixedPoint; overload;
begin
Result.X := P.X shl 16;
Result.Y := P.Y shl 16;
end;
function FixedPoint(const FP: TFloatPoint): TFixedPoint; overload;
begin
Result.X := Round(FP.X * 65536);
Result.Y := Round(FP.Y * 65536);
end;
{ Rectangles }
function MakeRect(const L, T, R, B: Integer): TRect;
begin
with Result do
begin
Left := L;
Top := T;
Right := R;
Bottom := B;
end;
end;
function MakeRect(const FR: TFloatRect; Rounding: TRectRounding): TRect;
begin
with FR do
case Rounding of
rrClosest:
begin
Result.Left := Round(Left);
Result.Top := Round(Top);
Result.Right := Round(Right);
Result.Bottom := Round(Bottom);
end;
rrInside:
begin
Result.Left := Ceil(Left);
Result.Top := Ceil(Top);
Result.Right := Ceil(Right);
Result.Bottom := Ceil(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 := Floor(Left);
Result.Top := Floor(Top);
Result.Right := Ceil(Right);
Result.Bottom := Ceil(Bottom);
end;
end;
end;
function MakeRect(const FXR: TFixedRect; Rounding: TRectRounding): TRect;
begin
with FXR do
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -