Componentes.Terceros.DevExp.../official/x.35/ExpressEditors Library 5/Sources/cxEditPaintUtils.pas
2008-05-12 15:08:14 +00:00

337 lines
9.6 KiB
ObjectPascal

{********************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressEditors }
{ }
{ Copyright (c) 1998-2008 Developer Express Inc. }
{ ALL RIGHTS RESERVED }
{ }
{ The entire contents of this file is protected by U.S. and }
{ International Copyright Laws. Unauthorized reproduction, }
{ reverse-engineering, and distribution of all or any portion of }
{ the code contained in this file is strictly prohibited and may }
{ result in severe civil and criminal penalties and will be }
{ prosecuted to the maximum extent possible under the law. }
{ }
{ RESTRICTIONS }
{ }
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
{ LICENSED TO DISTRIBUTE THE EXPRESSEDITORS AND ALL }
{ ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
{ }
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
{ }
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
{ ADDITIONAL RESTRICTIONS. }
{ }
{********************************************************************}
unit cxEditPaintUtils;
{$I cxVer.inc}
interface
uses
Windows, Classes, Controls, Graphics, SysUtils, cxClasses,
cxControls, cxGraphics, cxLookAndFeels;
const
cxSolidBrushCacheDefaultMaxDepth = 128;
type
{ TcxSolidBrushCache }
TcxSolidBrushCache = class
private
FBrushColors: array of TColor;
FBrushes: array of TBrushHandle;
FCounts: array of Cardinal;
FDepth: Integer;
FMaxDepth: Integer;
FSystemPaletteChangedNotifier: TcxSystemPaletteChangedNotifier;
protected
procedure SystemPaletteChanged; virtual;
public
constructor Create; overload;
constructor Create(AMaxDepth: Integer); overload;
destructor Destroy; override;
procedure Clear;
function GetBrush(ABrushColor: TColor): TBrushHandle;
end;
function GetSolidBrush(ABrushColor: TColor): TBrushHandle; overload;
function GetSolidBrush(ACanvas: TCanvas; ABrushColor: TColor): TBrushHandle; overload;
function GetSolidBrush(ACanvas: TcxCanvas; ABrushColor: TColor): TBrushHandle; overload;
procedure ResetSolidBrushCache;
implementation
uses
Forms;
const
cxSysColorPrefix: Cardinal = {$IFDEF DELPHI7}clSystemColor{$ELSE}$80000000{$ENDIF};
var
FSolidBrushCache: TcxSolidBrushCache = nil;
FSystemBrushes: array of TBrushHandle;
function GetSolidBrush(ABrushColor: TColor): TBrushHandle;
begin
Result := FSolidBrushCache.GetBrush(ABrushColor);
end;
function GetSolidBrush(ACanvas: TCanvas; ABrushColor: TColor): TBrushHandle;
begin
Result := FSolidBrushCache.GetBrush(ABrushColor);
end;
function GetSolidBrush(ACanvas: TcxCanvas; ABrushColor: TColor): TBrushHandle;
begin
Result := FSolidBrushCache.GetBrush(ABrushColor);
end;
procedure ResetSolidBrushCache;
begin
FSolidBrushCache.Clear;
end;
procedure CreateSystemBrushes;
var
I: Word;
begin
SetLength(FSystemBrushes, COLOR_ENDCOLORS - COLOR_SCROLLBAR + 1);
for I := COLOR_SCROLLBAR to COLOR_ENDCOLORS do
FSystemBrushes[I] := GetSysColorBrush(I);
end;
procedure DestroySystemBrushes;
begin
FSystemBrushes := nil;
end;
{ TcxSolidBrushCache }
constructor TcxSolidBrushCache.Create;
begin
Create(cxSolidBrushCacheDefaultMaxDepth);
end;
constructor TcxSolidBrushCache.Create(AMaxDepth: Integer);
begin
inherited Create;
FMaxDepth := AMaxDepth;
SetLength(FBrushColors, FMaxDepth);
SetLength(FBrushes, FMaxDepth);
SetLength(FCounts, FMaxDepth);
FSystemPaletteChangedNotifier := TcxSystemPaletteChangedNotifier.Create(True);
FSystemPaletteChangedNotifier.OnSystemPaletteChanged := SystemPaletteChanged;
end;
destructor TcxSolidBrushCache.Destroy;
begin
FreeAndNil(FSystemPaletteChangedNotifier);
Clear;
FBrushColors := nil;
FBrushes := nil;
FCounts := nil;
inherited Destroy;
end;
procedure TcxSolidBrushCache.Clear;
var
I: Integer;
begin
for I := 0 to FDepth - 1 do
DeleteObject(FBrushes[I]);
FDepth := 0;
end;
function TcxSolidBrushCache.GetBrush(ABrushColor: TColor): TBrushHandle;
function GetColorIndex(AColor: TColor; out AIndex: Integer): Boolean; assembler;
var
ADepth: Integer;
APBrushColors, APIndex: ^Integer;
begin
ADepth := FDepth;
APBrushColors := @FBrushColors[0];
APIndex := @AIndex;
asm
push ebx
push edi
push esi
mov edi, ADepth
or edi, edi
jne @@0
mov eax, edi
jmp @@5
@@0:
mov ebx, APBrushColors
mov edx, AColor
mov esi, ebx
dec edi
shl edi, 2
add esi, edi
jmp @@3
@@1:
mov edi, ebx
add edi, esi
shr edi, 1
and di, $FFFC
cmp edx, [edi]
je @@4
ja @@2
mov esi, edi
sub edi, ebx
jmp @@3
@@2:
mov ebx, edi
sub edi, esi
neg edi
@@3:
cmp edi, 4
ja @@1
mov edi, ebx
cmp edx, [edi]
jbe @@4
mov edi, esi
cmp edx, [edi]
jbe @@4
add edi, 4
@@4:
mov eax, edi
sub eax, APBrushColors
shr eax, 2
@@5:
mov ebx, APIndex
mov [ebx], eax
cmp eax, ADepth
jae @@6
shl eax, 2
add eax, APBrushColors
cmp [eax], edx
jne @@6
xor al, al
inc al
jmp @@7
@@6:
xor al, al
@@7:
pop esi
pop edi
pop ebx
mov Result, al
end;
end;
function GetRarestColorIndex: Integer;
var
ADepth: Integer;
APCounts: ^Integer;
begin
ADepth := FDepth;
APCounts := @FCounts[0];
asm
push ebx
push esi
mov ebx, APCounts
mov eax, [ebx]
mov ecx, ADepth
mov edx, ebx
@@0:
dec ecx
jz @@1
add ebx, 4
mov esi, [ebx]
cmp eax, esi
jbe @@0
mov eax, esi
mov edx, ebx
jmp @@0
@@1:
sub edx, APCounts
shr edx, 2
mov Result, edx
pop esi
pop ebx
end;
end;
function PrepareNewItem(AIndex: Integer): TBrushHandle;
var
ACount, ARarestColorIndex: Integer;
begin
if FDepth = FMaxDepth then
begin
ARarestColorIndex := GetRarestColorIndex;
DeleteObject(FBrushes[ARarestColorIndex]);
Dec(FDepth);
if ARarestColorIndex < FDepth then
begin
ACount := (FDepth - ARarestColorIndex) shl 2;
Move(FBrushColors[ARarestColorIndex + 1], FBrushColors[ARarestColorIndex], ACount);
Move(FBrushes[ARarestColorIndex + 1], FBrushes[ARarestColorIndex], ACount);
Move(FCounts[ARarestColorIndex + 1], FCounts[ARarestColorIndex], ACount);
end;
if AIndex > ARarestColorIndex then
Dec(AIndex);
end;
if AIndex < FDepth then
begin
ACount := (FDepth - AIndex) shl 2;
Move(FBrushColors[AIndex], FBrushColors[AIndex + 1], ACount);
Move(FBrushes[AIndex], FBrushes[AIndex + 1], ACount);
Move(FCounts[AIndex], FCounts[AIndex + 1], ACount);
end;
Inc(FDepth);
Result := CreateSolidBrush(ColorToRGB(ABrushColor));
FBrushColors[AIndex] := ABrushColor;
FBrushes[AIndex] := Result;
FCounts[AIndex] := 0;
end;
var
AColorIndex: Integer;
begin
if FSystemBrushes <> nil then
if (Cardinal(ABrushColor) >= cxSysColorPrefix) and (Cardinal(ABrushColor) <= cxSysColorPrefix or COLOR_ENDCOLORS) then
begin
Result := FSystemBrushes[ABrushColor and not cxSysColorPrefix];
Exit;
end;
if GetColorIndex(ABrushColor, AColorIndex) then
begin
Inc(FCounts[AColorIndex]);
Result := FBrushes[AColorIndex];
end
else
Result := PrepareNewItem(AColorIndex);
end;
procedure TcxSolidBrushCache.SystemPaletteChanged;
begin
Clear;
end;
initialization
CreateSystemBrushes;
FSolidBrushCache := TcxSolidBrushCache.Create;
finalization
FreeAndNil(FSolidBrushCache);
DestroySystemBrushes;
end.