📄 sf_bitmap.pas
字号:
TFasterHashedStringList = class(TStringList)
private
FValueHash: TIntegerHash;
FValueHashValid: Boolean;
procedure UpdateValueHash;
protected
procedure Changed; override;
public
destructor Destroy; override;
function IndexOfDC(const DC: Cardinal): Integer;
end;
const
BitmapList: TFasterHashedStringList = nil;
{ TIntegerHash }
procedure TIntegerHash.Add(const Key: Cardinal; Value: Integer);
var
Hash: Integer;
Bucket: PHashItem;
begin
Hash := HashOfInteger(Key) mod Cardinal(Length(Buckets));
New(Bucket);
Bucket^.Key := Key;
Bucket^.Value := Value;
Bucket^.Next := Buckets[Hash];
Buckets[Hash] := Bucket;
end;
procedure TIntegerHash.Clear;
var
I: Integer;
P, N: PHashItem;
begin
for I := 0 to Length(Buckets) - 1 do
begin
P := Buckets[I];
while P <> nil do
begin
N := P^.Next;
Dispose(P);
P := N;
end;
Buckets[I] := nil;
end;
end;
constructor TIntegerHash.Create(Size: Cardinal);
begin
inherited Create;
SetLength(Buckets, Size);
end;
destructor TIntegerHash.Destroy;
begin
Clear;
inherited Destroy;
end;
function TIntegerHash.Find(const Key: Cardinal): PPHashItem;
var
Hash: Integer;
begin
Hash := HashOfInteger(Key) mod Cardinal(Length(Buckets));
Result := @Buckets[Hash];
while Result^ <> nil do
begin
if Result^.Key = Key then
Exit
else
Result := @Result^.Next;
end;
end;
function TIntegerHash.HashOfInteger(const Key: Cardinal): Cardinal;
type
TBuffer = array[0..0] of Cardinal;
PBuffer = ^TBuffer;
var
P: PBuffer;
h: Cardinal;
begin
// start with a good "random" bit pattern so that
// even single byte hashes are well scattered over
// a 32-bit range
Result := $9E3779B9;
P := @Key;
h := P[0];
Inc(Result, ($9E3779B9 * h));
// i.e. rotate the Result bit-pattern to the right to keep
// early bits in the key from getting completely lost
Result := (Result shr 15) or (Result shl 17);
end;
function TIntegerHash.ValueOf(const Key: Cardinal): Integer;
var
P: PHashItem;
begin
P := Find(Key)^;
if P <> nil then
Result := P^.Value
else
Result := -1;
end;
{ TFasterHashedStringList }
procedure TFasterHashedStringList.Changed;
begin
inherited Changed;
FValueHashValid := False;
end;
destructor TFasterHashedStringList.Destroy;
begin
FValueHash.Free;
inherited Destroy;
end;
function TFasterHashedStringList.IndexOfDC(const DC: Cardinal): Integer;
begin
UpdateValueHash;
Result := FValueHash.ValueOf(DC);
end;
function FastIntToStr(I: LongWord): string;
begin
Str(I, result);
end;
function StrToCardinal(const S: string): Cardinal;
var
I,L: Word;
begin
I := 1;
Result := 0;
L:= Length(s);
while I <= L do
begin
Result := Result * 10 + Ord(s[I]) - Ord('0');
Inc(I);
end;
end;
procedure TFasterHashedStringList.UpdateValueHash;
var
I: Integer;
begin
if FValueHashValid then Exit;
if FValueHash = nil then
FValueHash := TIntegerHash.Create
else
FValueHash.Clear;
for I := 0 to Count - 1 do
FValueHash.Add(StrToCardinal(Self[I]), I);
FValueHashValid := True;
end;
{ BitmapList Routines }
procedure AddBitmapToList(B: TsfBitmap);
begin
if BitmapList = nil then
begin
BitmapList := TFasterHashedStringList.Create;
{$IFDEF AL_COMPILER6_UP}
BitmapList.CaseSensitive := true; // Faster acces
{$ENDIF}
end;
BitmapList.AddObject(FastIntToStr(B.DC),B); //Search based on DC
end;
procedure RemoveBitmapFromList(B: TsfBitmap);
var Index: Integer;
begin
if BitmapList <> nil then
begin
Index := BitmapList.IndexOfDC(B.DC);
if Index <> -1 then
BitmapList.Delete(Index);
end;
end;
function FindBitmapByDC(DC: HDC): TsfBitmap;
var
i: integer;
begin
i:= BitmapList.IndexOfDC(DC);
if i <> -1 then
Result := TsfBitmap(BitmapList.Objects[i])
else
Result := nil;
end;
procedure FreeBitmapList;
begin
if BitmapList <> nil then FreeAndNil(BitmapList);
end;
{$ELSE }
const
BitmapList: TList = nil;
{ BitmapList Routines }
procedure AddBitmapToList(B: TsfBitmap);
begin
if BitmapList = nil then BitmapList := TList.Create;
BitmapList.Add(B);
end;
procedure RemoveBitmapFromList(B: TsfBitmap);
begin
if BitmapList <> nil then
BitmapList.Remove(B);
end;
function FindBitmapByDC(DC: HDC): TsfBitmap;
var
i: integer;
begin
for i := 0 to BitmapList.Count - 1 do
if TsfBitmap(BitmapList[i]).DC = DC then
begin
Result := TsfBitmap(BitmapList[i]);
Exit;
end;
Result := nil;
end;
procedure FreeBitmapList;
begin
if BitmapList <> nil then FreeAndNil(BitmapList);
end;
{$ENDIF}
{ Color function }
{$IFDEF AL_CLX}
function RGB(R, G, B: byte): TColor;
begin
Result := (B shl 16) or (G shl 8) or R;
end;
{$ENDIF}
function sfColor(Color: TColor; A: Byte = $FF): TsfColor;
var
C: TColor;
Tmp: cardinal;
begin
C := ColorToRGB(Color);
Tmp := A;
Result := FromRGB(C) + (Tmp shl 24);
end;
function sfColor(R, G, B: SmallInt; A: Byte = $FF): TsfColor;
begin
if R > $FF then R := $FF;
if G > $FF then G := $FF;
if B > $FF then B := $FF;
if R < 0 then R := 0;
if G < 0 then G := 0;
if B < 0 then B := 0;
TsfColorRec(Result).R := R;
TsfColorRec(Result).G := G;
TsfColorRec(Result).B := B;
TsfColorRec(Result).A := A;
end;
function sfColor(ColorRec: TsfColorRec): TsfColor;
begin
Result := ToRGB(Longword(ColorRec));
end;
function sfColorToColor(Color: TsfColor): TColor;
begin
Result := ToRGB(Color);
end;
function sfColorToColor16(Color: TsfColor): word; // 16-bit, 5-6-5
begin
with TsfColorRec(Color) do
Result :=
(R shr 3 shl 11) or // R-5bit
(G shr 2 shl 5) or // G-6bit
(B shr 3); // B-5bit
end;
function sfColorToColor15(Color: TsfColor): word; // 15-bit, 5-5-5
begin
with TsfColorRec(Color) do
Result :=
(R shr 3 shl 10) or // R-5bit
(G shr 3 shl 5) or // G-5bit
(B shr 3); // B-5bit
end;
{ Color space conversions }
{$Q-}
function HSLtoRGB(H, S, L: Single): TsfColor;
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 + 1 / 3);
G := HueToColor(H);
B := HueToColor(H - 1 / 3)
end;
Result := sfColor(R, G, B);
end;
procedure RGBtoHSL(RGB: TsfColor; out H, S, L: single);
var
R, G, B, D, Cmax, Cmin: Single;
begin
R := TsfColorRec(RGB).R / 255;
G := TsfColorRec(RGB).G / 255;
B := TsfColorRec(RGB).B / 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 SetHue(Color: TsfColor; Hue: integer): TsfColor;
var
H, S, L: single;
HValue: integer;
begin
RGBtoHSL(Color, H, S, L);
if Hue > $FF then Hue := $Ff;
if Hue < 0 then Hue := 0;
Result := HSLtoRGB(Hue / 255, S, L);
end;
function ChangeSat(Color: TsfColor; DeltaSat: integer): TsfColor;
var
H, S, L: single;
SValue: integer;
begin
RGBtoHSL(Color, H, S, L);
SValue := Round(S * 255);
Inc(SValue, DeltaSat);
if SValue > $FF then SValue := SValue - $FF;
if SValue < 0 then SValue := $FF + SValue;
Result := HSLtoRGB(H, SValue / $FF, L);
end;
function ChangeHue(Color: TsfColor; DeltaHue: integer): TsfColor;
var
H, S, L: single;
HValue: integer;
begin
RGBtoHSL(Color, H, S, L);
HValue := Round(H * 255);
Inc(HValue, DeltaHue);
if HValue > 255 then HValue := HValue - 255;
if HValue < 0 then HValue := 255 + HValue;
Result := HSLtoRGB(HValue / 255, S, L);
end;
function ChangeBrightness(Color: TsfColor; DeltaBrightness: integer): TsfColor;
var
R, G, B: integer;
begin
R := TsfColorRec(Color).R;
G := TsfColorRec(Color).G;
B := TsfColorRec(Color).B;
Inc(R, DeltaBrightness);
Inc(G, DeltaBrightness);
Inc(B, DeltaBrightness);
Result := sfColor(R, G, B);
end;
function ChangeColor(Color: TsfColor; Dr, Dg, Db: smallint; Da: smallint = 0): TsfColor; overload;
begin
with TsfColorRec(Color) do
Result := sfColor(R + DR, G + DG, B + DB, A + DA);
end;
function ChangeColor(Color: TsfColor; Dx: smallint): TsfColor; overload;
begin
Result := ChangeColor(Color, Dx, Dx, Dx);
end;
function StdChangeColor(Color: TColor; Dr, Dg, Db: smallint; Da: smallint = 0): TColor; overload;
begin
Color := FromRGB(ColorToRGB(Color));
Color := ChangeColor(Color, Dr, Dg, Db);
Result := ToRGB(Color);
end;
function StdChangeColor(Color: TColor; Dx: smallint): TColor; overload;
begin
Result := StdChangeColor(Color, Dx, Dx, Dx);
end;
function SunkenColor(Color: TsfColor; Dr, Dg, Db: smallint; Da: smallint = 0): TsfColor; overload;
begin
Result := ChangeColor(Color, -Dr, -Dg, -Db, -Da);
end;
function SunkenColor(Color: TsfColor; Dx: smallint): TsfColor; overload;
begin
Result := ChangeColor(Color, -Dx);
end;
function RaisedColor(Color: TsfColor; Dr, Dg, Db: smallint; Da: smallint = 0): TsfColor; overload;
begin
Result := ChangeColor(Color, Dr, Dg, Db, Da);
end;
function RaisedColor(Color: TsfColor; Dx: smallint): TsfColor; overload;
begin
Result := ChangeColor(Color, Dx);
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -