{%MainUnit ../graphics.pp} {****************************************************************************** TBrush ****************************************************************************** ***************************************************************************** This file is part of the Lazarus Component Library (LCL) See the file COPYING.modifiedLGPL.txt, included in this distribution, for details about the license. ***************************************************************************** } { TBrushHandleCache } procedure TBrushHandleCache.RemoveItem(Item: TResourceCacheItem); begin DeleteObject(HGDIOBJ(Item.Handle)); inherited RemoveItem(Item); end; constructor TBrushHandleCache.Create; begin inherited Create(SizeOf(TLogBrush)); end; { TBrush } {------------------------------------------------------------------------------ Method: TBrush.SetColor Params: Value: the new value Returns: nothing Sets the style of a brush ------------------------------------------------------------------------------} procedure TBrush.SetColor(Value: TColor); begin SetColor(Value, TColorToFPColor(Value)); end; {------------------------------------------------------------------------------ Method: TBrush.SetStyle Params: Value: the new value Returns: nothing Sets the style of a brush ------------------------------------------------------------------------------} procedure TBrush.SetStyle(Value : TBrushStyle); begin if Style <> Value then begin FreeReference; // reset bitmap FBitmap := nil; inherited SetStyle(Value); Changed; end; end; {------------------------------------------------------------------------------ Method: TBrush.SetBitmap Params: Value: the new value Returns: nothing Sets the style of a brush ------------------------------------------------------------------------------} procedure TBrush.SetBitmap(Value: TCustomBitmap); begin if FBitmap <> Value then begin FreeReference; FBitmap := Value; // reset style and color inherited SetStyle(bsSolid); FColor := clWhite; inherited SetFPColor(TColorToFPColor(FColor)); Changed; end; end; {------------------------------------------------------------------------------ Method: TBrush.Create Params: none Returns: Nothing Constructor for the class. ------------------------------------------------------------------------------} constructor TBrush.Create; begin inherited Create; FBitmap := nil; FColor := clWhite; inherited SetFPColor(TColorToFPColor(FColor)); DelayAllocate := True; FInternalUpdateIndex := -1; inherited SetStyle(bsSolid); end; {------------------------------------------------------------------------------ Method: TBrush.Destroy Params: None Returns: Nothing Destructor for the class. ------------------------------------------------------------------------------} destructor TBrush.Destroy; begin FreeReference; inherited Destroy; end; function TBrush.EqualsBrush(ABrush: TBrush): boolean; begin Result := Assigned(ABrush) and (Color = ABrush.Color) and (FPColor = ABrush.FPColor) and (Style = ABrush.Style) and (Bitmap = ABrush.Bitmap); end; {------------------------------------------------------------------------------ Method: TBrush.Assign Params: Source: Another brush Returns: nothing Copies the source brush to itself ------------------------------------------------------------------------------} procedure TBrush.Assign(Source: TPersistent); begin if Source is TBrush then begin if not EqualsBrush(TBrush(Source)) then begin FreeReference; FColor := TBrush(Source).Color; inherited SetFPColor(TFPCanvasHelper(Source).FPColor); inherited SetStyle(TBrush(Source).Style); FBitmap := TBrush(Source).Bitmap; Changed; end; end else inherited Assign(Source); end; {------------------------------------------------------------------------------ Method: TBrush.SetHandle Params: a brush handle Returns: nothing sets the brush to an external created brush ------------------------------------------------------------------------------} procedure TBrush.SetHandle(const Value: HBRUSH); begin if HBRUSH(FReference.Handle) = Value then Exit; FreeReference; FReference._lclHandle := TLCLHandle(Value); FInternalUpdateIndex := GraphicsUpdateCount; Changed; end; {------------------------------------------------------------------------------ Function: TBrush.GetHandle Params: none Returns: a handle to a brush gdiobject Creates a brush if needed ------------------------------------------------------------------------------} function TBrush.GetHandle: HBRUSH; begin Result := HBRUSH(Reference.Handle); end; {------------------------------------------------------------------------------ Method: TBrush.FreeReference Params: none Returns: Nothing Frees a brush handle if needed ------------------------------------------------------------------------------} procedure TBrush.FreeReference; var CacheItem: TResourceCacheItem; begin if not FReference.Allocated then Exit; Changing; if FBrushHandleCached then begin BrushResourceCache.Lock; try CacheItem := BrushResourceCache.FindItem(FReference.Handle); if CacheItem <> nil then CacheItem.DecreaseRefCount; FBrushHandleCached := False; finally BrushResourceCache.Unlock; end; end else DeleteObject(HGDIOBJ(FReference.Handle)); FReference._lclHandle := 0; end; function TBrush.GetReference: TWSBrushReference; begin if FInternalUpdateIndex <> GraphicsUpdateCount then FreeReference; ReferenceNeeded; Result := FReference; end; function TBrush.GetColor: TColor; begin Result := FColor; if (Result = clDefault) and Assigned(Canvas) and (Canvas is TCanvas) then Result := TCanvas(Canvas).GetDefaultColor(dctBrush); end; procedure TBrush.ReferenceNeeded; var LogBrush: TLogBrush; CachedBrush: TBlockResourceCacheDescriptor; begin if FReference.Allocated then Exit; FillChar(LogBrush, SizeOf(LogBrush), 0); with LogBrush do begin if FBitmap <> nil then begin lbStyle := BS_PATTERN; lbHatch := FBitmap.Handle; end else begin lbHatch := 0; case Style of bsSolid: lbStyle := BS_SOLID; bsClear: lbStyle := BS_HOLLOW; else lbStyle := BS_HATCHED; lbHatch := Ord(Style) - Ord(bsHorizontal); end; end; lbColor := ColorRef(GetColor); end; BrushResourceCache.Lock; try CachedBrush := BrushResourceCache.FindDescriptor(@LogBrush); if CachedBrush <> nil then begin CachedBrush.Item.IncreaseRefCount; FReference._lclHandle := CachedBrush.Item.Handle; end else begin if LogBrush.lbStyle <> BS_PATTERN then if (LogBrush.lbStyle = BS_SOLID) and IsSysColor(LogBrush.lbColor) then FReference._lclHandle := TLCLHandle(GetSysColorBrush(SysColorToSysColorIndex(TColor(LogBrush.lbColor)))) else FReference._lclHandle := TLCLHandle(CreateBrushIndirect(LogBrush)) else FReference._lclHandle := TLCLHandle(CreatePatternBrush(LogBrush.lbHatch)); BrushResourceCache.AddResource(FReference.Handle, @LogBrush); end; FBrushHandleCached := True; finally BrushResourceCache.Unlock; end; FInternalUpdateIndex := GraphicsUpdateCount; end; procedure TBrush.DoChange(var Msg); begin Changed; end; procedure TBrush.DoAllocateResources; begin inherited DoAllocateResources; GetReference; end; procedure TBrush.DoDeAllocateResources; begin FreeReference; inherited DoDeAllocateResources; end; procedure TBrush.DoCopyProps(From: TFPCanvasHelper); begin if From is TBrush then begin FreeReference; inherited DoCopyProps(From); //TODO: query new parameters Changed; end else inherited DoCopyProps(From); end; procedure TBrush.SetColor(const NewColor: TColor; const NewFPColor: TFPColor); begin if (NewColor = Color) and (NewFPColor = FPColor) and (Style <> bsClear) then Exit; FreeReference; // reset bitmap FBitmap := nil; FColor := NewColor; inherited SetFPColor(NewFPColor); if Style = bsClear then inherited SetStyle(bsSolid); Changed; end; procedure TBrush.SetFPColor(const AValue: TFPColor); begin if FPColor <> AValue then SetColor(FPColorToTColor(AValue), AValue); end;