lcl: Pen and Font cache

- simplify some Font cache methods
  - rewrite Pen cache to store pattern separate of LogPen

git-svn-id: trunk@17305 -
This commit is contained in:
paul 2008-11-10 04:14:15 +00:00
parent 80581bd7cb
commit 1f905fd95f
4 changed files with 172 additions and 44 deletions

View File

@ -552,11 +552,27 @@ type
TPenPattern = array of LongWord; TPenPattern = array of LongWord;
TPenHandleCache = class(TBlockResourceCache) { TPenHandleCacheDescriptor }
TPenHandleCacheDescriptor = class(TResourceCacheDescriptor)
public
ExtPen: TExtLogPen;
Pattern: TPenPattern;
end;
{ TPenHandleCache }
TPenHandleCache = class(TResourceCache)
protected protected
procedure RemoveItem(Item: TResourceCacheItem); override; procedure RemoveItem(Item: TResourceCacheItem); override;
public public
constructor Create; constructor Create;
function CompareDescriptors(Tree: TAvgLvlTree; Desc1, Desc2: Pointer): integer; override;
function FindPen(APen: TLCLHandle): TResourceCacheItem;
function FindPenDesc(const AExtPen: TExtLogPen;
const APattern: TPenPattern): TPenHandleCacheDescriptor;
function Add(APen: TLCLHandle; const AExtPen: TExtLogPen;
const APattern: TPenPattern): TPenHandleCacheDescriptor;
end; end;
TPen = class(TFPCustomPen) TPen = class(TFPCustomPen)
@ -2399,7 +2415,6 @@ begin
FreeAndNil(BrushResourceCache); FreeAndNil(BrushResourceCache);
end; end;
initialization initialization
UpdateLock := TCriticalSection.Create; UpdateLock := TCriticalSection.Create;
RegisterIntegerConsts(TypeInfo(TColor), @IdentToColor, @ColorToIdent); RegisterIntegerConsts(TypeInfo(TColor), @IdentToColor, @ColorToIdent);

View File

@ -51,13 +51,12 @@ end;
function TFontHandleCache.CompareDescriptors(Tree: TAvgLvlTree; Desc1, function TFontHandleCache.CompareDescriptors(Tree: TAvgLvlTree; Desc1,
Desc2: Pointer): integer; Desc2: Pointer): integer;
var var
Descriptor1: TFontHandleCacheDescriptor; Descriptor1: TFontHandleCacheDescriptor absolute Desc1;
Descriptor2: TFontHandleCacheDescriptor; Descriptor2: TFontHandleCacheDescriptor absolute Desc2;
begin begin
Descriptor1:=TFontHandleCacheDescriptor(Desc1);
Descriptor2:=TFontHandleCacheDescriptor(Desc2);
Result := CompareStr(Descriptor1.LongFontName, Descriptor2.LongFontName); Result := CompareStr(Descriptor1.LongFontName, Descriptor2.LongFontName);
if Result<>0 then exit; if Result <> 0 then
Exit;
Result := CompareMemRange(@Descriptor1.LogFont, @Descriptor2.LogFont, Result := CompareMemRange(@Descriptor1.LogFont, @Descriptor2.LogFont,
SizeOf(Descriptor1.LogFont)); SizeOf(Descriptor1.LogFont));
end; end;
@ -100,7 +99,8 @@ begin
// find cache item with TheFont // find cache item with TheFont
Item := FindFont(TheFont); Item := FindFont(TheFont);
if Item=nil then begin if Item = nil then
begin
// create new item // create new item
Item := TResourceCacheItem.Create(Self, TheFont); Item := TResourceCacheItem.Create(Self, TheFont);
FItems.Add(Item); FItems.Add(Item);
@ -111,13 +111,13 @@ begin
Result.LongFontName := LongFontName; Result.LongFontName := LongFontName;
Result.LogFont := LogFont; Result.LogFont := LogFont;
FDescriptors.Add(Result); FDescriptors.Add(Result);
if FindFontDesc(LogFont,LongFontName)=nil then begin if FindFontDesc(LogFont, LongFontName) = nil then
begin
DebugLn('TFontHandleCache.Add Added: %p LongFontName=%s', [Pointer(Result), Result.LongFontName]); DebugLn('TFontHandleCache.Add Added: %p LongFontName=%s', [Pointer(Result), Result.LongFontName]);
RaiseGDBException(''); RaiseGDBException('');
end; end;
end; end;
{ TFont } { TFont }
procedure GetCharsetValues(Proc: TGetStrProc); procedure GetCharsetValues(Proc: TGetStrProc);

View File

@ -17,19 +17,122 @@
***************************************************************************** *****************************************************************************
} }
type
TExtPenAndPattern = record
ExtPen: TExtLogPen;
Pattern: TPenPattern;
end;
PExtPenAndPattern = ^TExtPenAndPattern;
function CompareExtPenAndPatternWithResDesc(Key: PExtPenAndPattern; Desc: TPenHandleCacheDescriptor): integer;
begin
Result := CompareMemRange(@Key^.ExtPen, @Desc.ExtPen,
SizeOf(Key^.ExtPen));
if Result <> 0 then
Exit;
Result := CompareValue(Length(Key^.Pattern), Length(Desc.Pattern));
if Result <> 0 then
Exit;
if Length(Key^.Pattern) > 0 then
begin
Result := CompareMemRange(@Key^.Pattern[0], @Desc.Pattern[0],
SizeOf(Key^.Pattern[0]) * Length(Key^.Pattern));
end;
end;
{ TPenHandleCache } { TPenHandleCache }
procedure TPenHandleCache.RemoveItem(Item: TResourceCacheItem); procedure TPenHandleCache.RemoveItem(Item: TResourceCacheItem);
begin begin
if Item = nil then
RaiseGDBException('TPenHandleCache.RemoveItem');
DeleteObject(HGDIOBJ(Item.Handle)); DeleteObject(HGDIOBJ(Item.Handle));
inherited RemoveItem(Item); inherited RemoveItem(Item);
end; end;
constructor TPenHandleCache.Create; constructor TPenHandleCache.Create;
begin begin
inherited Create(SizeOf(TExtLogPen)); inherited Create;
FResourceCacheDescriptorClass := TPenHandleCacheDescriptor;
end;
function TPenHandleCache.CompareDescriptors(Tree: TAvgLvlTree; Desc1,
Desc2: Pointer): integer;
var
Descriptor1: TPenHandleCacheDescriptor absolute Desc1;
Descriptor2: TPenHandleCacheDescriptor absolute Desc2;
begin
Result := CompareMemRange(@Descriptor1.ExtPen, @Descriptor2.ExtPen,
SizeOf(Descriptor1.ExtPen));
if Result <> 0 then
Exit;
Result := CompareValue(Length(Descriptor1.Pattern), Length(Descriptor2.Pattern));
if Result <> 0 then
Exit;
if Length(Descriptor1.Pattern) > 0 then
begin
Result := CompareMemRange(@Descriptor1.Pattern[0], @Descriptor2.Pattern[0],
SizeOf(Descriptor1.Pattern[0]) * Length(Descriptor1.Pattern));
end;
end;
function TPenHandleCache.FindPen(APen: TLCLHandle): TResourceCacheItem;
var
ANode: TAvgLvlTreeNode;
begin
ANode := FItems.FindKey(@APen,
TListSortCompare(@ComparePHandleWithResourceCacheItem));
if ANode <> nil then
Result := TResourceCacheItem(ANode.Data)
else
Result := nil;
end;
function TPenHandleCache.FindPenDesc(const AExtPen: TExtLogPen;
const APattern: TPenPattern): TPenHandleCacheDescriptor;
var
ExtPenAndPattern: TExtPenAndPattern;
ANode: TAvgLvlTreeNode;
begin
ExtPenAndPattern.ExtPen := AExtPen;
ExtPenAndPattern.Pattern := APattern;
ANode := FDescriptors.Findkey(@ExtPenAndPattern,
TListSortCompare(@CompareExtPenAndPatternWithResDesc));
if ANode <> nil then
Result := TPenHandleCacheDescriptor(ANode.Data)
else
Result := nil;
end;
function TPenHandleCache.Add(APen: TLCLHandle; const AExtPen: TExtLogPen;
const APattern: TPenPattern): TPenHandleCacheDescriptor;
var
Item: TResourceCacheItem;
begin
if FindPenDesc(AExtPen, APattern) <> nil then
RaiseGDBException('TPenHandleCache.Add pen desc added twice');
// find cache item with APen
Item := FindPen(APen);
if Item = nil then
begin
// create new item
Item := TResourceCacheItem.Create(Self, APen);
FItems.Add(Item);
end;
// create descriptor
Result := TPenHandleCacheDescriptor.Create(Self, Item);
Result.ExtPen := AExtPen;
Result.Pattern := APattern;
FDescriptors.Add(Result);
if FindPenDesc(AExtPen, APattern) = nil then
begin
DebugLn('TPenHandleCache.Add Added: %p', [Pointer(Result)]);
RaiseGDBException('');
end;
end; end;
{ TPen } { TPen }
@ -262,7 +365,7 @@ var
ALogPen: TLogPen; ALogPen: TLogPen;
AExtPen: TExtLogPen; AExtPen: TExtLogPen;
ALogBrush: TLogBrush; ALogBrush: TLogBrush;
CachedPen: TBlockResourceCacheDescriptor; CachedPen: TPenHandleCacheDescriptor;
begin begin
if FReference.Allocated then Exit; if FReference.Allocated then Exit;
@ -277,7 +380,11 @@ begin
elpColor := FColor; elpColor := FColor;
end; end;
CachedPen := PenResourceCache.FindDescriptor(@AExtPen); if Style = psPattern then
CachedPen := PenResourceCache.FindPenDesc(AExtPen, FPattern)
else
CachedPen := PenResourceCache.FindPenDesc(AExtPen, nil);
if CachedPen <> nil then if CachedPen <> nil then
begin begin
CachedPen.Item.IncreaseRefCount; CachedPen.Item.IncreaseRefCount;
@ -285,7 +392,8 @@ begin
end else end else
begin begin
// choose which function to use: CreatePenIndirect or ExtCreatePen // choose which function to use: CreatePenIndirect or ExtCreatePen
if ((AExtPen.elpPenStyle and PS_STYLE_MASK) = AExtPen.elpPenStyle) and (AExtPen.elpPenStyle <> PS_USERSTYLE) then if ((AExtPen.elpPenStyle and PS_STYLE_MASK) = AExtPen.elpPenStyle) and
(AExtPen.elpPenStyle <> PS_USERSTYLE) then
begin begin
// simple pen // simple pen
ALogPen.lopnStyle := AExtPen.elpPenStyle; ALogPen.lopnStyle := AExtPen.elpPenStyle;
@ -300,11 +408,17 @@ begin
ALogBrush.lbColor := AExtPen.elpColor; ALogBrush.lbColor := AExtPen.elpColor;
ALogBrush.lbHatch := AExtPen.elpHatch; ALogBrush.lbHatch := AExtPen.elpHatch;
if (Style = psPattern) and (Length(FPattern) > 0) then if (Style = psPattern) and (Length(FPattern) > 0) then
FReference._lclHandle := TLCLHandle(ExtCreatePen(AExtPen.elpPenStyle, AExtPen.elpWidth, ALogBrush, Length(FPattern), @FPattern[0])) FReference._lclHandle := TLCLHandle(ExtCreatePen(AExtPen.elpPenStyle,
AExtPen.elpWidth, ALogBrush, Length(FPattern), @FPattern[0]))
else else
FReference._lclHandle := TLCLHandle(ExtCreatePen(AExtPen.elpPenStyle, AExtPen.elpWidth, ALogBrush, 0, nil)); FReference._lclHandle := TLCLHandle(ExtCreatePen(AExtPen.elpPenStyle,
AExtPen.elpWidth, ALogBrush, 0, nil));
end; end;
PenResourceCache.AddResource(FReference.Handle, @AExtPen);
if Style = psPattern then
PenResourceCache.Add(FReference.Handle, AExtPen, FPattern)
else
PenResourceCache.Add(FReference.Handle, AExtPen, nil);
end; end;
FPenHandleCached := True; FPenHandleCached := True;
end; end;
@ -344,7 +458,7 @@ begin
Changing; Changing;
if FPenHandleCached then if FPenHandleCached then
begin begin
PenResourceCache.FindItem(FReference.Handle).DecreaseRefCount; PenResourceCache.FindPen(FReference.Handle).DecreaseRefCount;
FPenHandleCached := False; FPenHandleCached := False;
end else end else
DeleteObject(HGDIOBJ(FReference.Handle)); DeleteObject(HGDIOBJ(FReference.Handle));

View File

@ -150,7 +150,6 @@ function ComparePHandleWithResourceCacheItem(HandlePtr: PLCLHandle; Item:
function CompareDescPtrWithBlockResDesc(DescPtr: Pointer; function CompareDescPtrWithBlockResDesc(DescPtr: Pointer;
Item: TBlockResourceCacheDescriptor): integer; Item: TBlockResourceCacheDescriptor): integer;
implementation implementation