171 lines
4.5 KiB
ObjectPascal
171 lines
4.5 KiB
ObjectPascal
// SPDX-License-Identifier: LGPL-3.0-linking-exception
|
|
{
|
|
BCRoundedImage
|
|
by Lainz
|
|
|
|
Last modified: 2020-09-06 19:16 GMT-3
|
|
|
|
Changelog:
|
|
- 2020-09-06: Initial version supporting circle, rounded rectangle and square.
|
|
Changing the quality of the resample, setting the rounding.
|
|
OnPaintEvent to customize the final drawing.
|
|
}
|
|
unit BCRoundedImage;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
|
|
BGRABitmap, BGRABitmapTypes;
|
|
|
|
type
|
|
TBCRoundedImage = class;
|
|
|
|
// Event to draw before the image is sent to canvas
|
|
TBCRoundedImagePaintEvent = procedure (const Sender: TBCRoundedImage; const Bitmap: TBGRABitmap) of object;
|
|
// Supported styles are circle, rounded rectangle and square
|
|
TBCRoundedImageStyle = (isCircle, isRoundedRectangle, isSquare);
|
|
|
|
// Control that draws an image within a rounded border
|
|
|
|
{ TBCRoundedImage }
|
|
|
|
TBCRoundedImage = class(TGraphicControl)
|
|
private
|
|
FBorderStyle: TRoundRectangleOptions;
|
|
FOnPaintEvent: TBCRoundedImagePaintEvent;
|
|
FPicture: TPicture;
|
|
FQuality: TResampleFilter;
|
|
FStyle: TBCRoundedImageStyle;
|
|
FRounding: single;
|
|
procedure SetBorderStyle(AValue: TRoundRectangleOptions);
|
|
procedure SetPicture(AValue: TPicture);
|
|
procedure SetQuality(AValue: TResampleFilter);
|
|
procedure SetStyle(AValue: TBCRoundedImageStyle);
|
|
procedure SetRounding(AValue: single);
|
|
protected
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure Paint; override;
|
|
published
|
|
// The image that's used as background
|
|
property Picture: TPicture read FPicture write SetPicture;
|
|
// The style can be circle, rounded rectangle or square
|
|
property Style: TBCRoundedImageStyle read FStyle write SetStyle;
|
|
// The style of the rounded rectangle
|
|
property BorderStyle: TRoundRectangleOptions read FBorderStyle write SetBorderStyle;
|
|
// Rounding is used when you choose the rounded rectangle style
|
|
property Rounding: single read FRounding write SetRounding;
|
|
// The quality when resizing the image
|
|
property Quality: TResampleFilter read FQuality write SetQuality;
|
|
// You can paint before the bitmap is drawn on canvas
|
|
property OnPaintEvent: TBCRoundedImagePaintEvent read FOnPaintEvent write FOnPaintEvent;
|
|
published
|
|
property Anchors;
|
|
property Align;
|
|
property OnMouseEnter;
|
|
property OnMouseLeave;
|
|
property OnClick;
|
|
end;
|
|
|
|
procedure Register;
|
|
|
|
implementation
|
|
|
|
procedure Register;
|
|
begin
|
|
RegisterComponents('BGRA Controls', [TBCRoundedImage]);
|
|
end;
|
|
|
|
procedure TBCRoundedImage.SetPicture(AValue: TPicture);
|
|
begin
|
|
if FPicture = AValue then
|
|
Exit;
|
|
FPicture := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TBCRoundedImage.SetBorderStyle(AValue: TRoundRectangleOptions);
|
|
begin
|
|
if FBorderStyle=AValue then Exit;
|
|
FBorderStyle:=AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TBCRoundedImage.SetQuality(AValue: TResampleFilter);
|
|
begin
|
|
if FQuality = AValue then
|
|
Exit;
|
|
FQuality := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TBCRoundedImage.SetStyle(AValue: TBCRoundedImageStyle);
|
|
begin
|
|
if FStyle = AValue then
|
|
Exit;
|
|
FStyle := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TBCRoundedImage.SetRounding(AValue: single);
|
|
begin
|
|
if FRounding = AValue then
|
|
Exit;
|
|
FRounding := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
constructor TBCRoundedImage.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FPicture := TPicture.Create;
|
|
FRounding := 10;
|
|
FQuality := rfBestQuality;
|
|
end;
|
|
|
|
destructor TBCRoundedImage.Destroy;
|
|
begin
|
|
FPicture.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TBCRoundedImage.Paint;
|
|
var
|
|
bgra: TBGRABitmap;
|
|
image: TBGRABitmap;
|
|
begin
|
|
if (FPicture.Width = 0) or (FPicture.Height = 0) then
|
|
Exit;
|
|
// Picture
|
|
image := TBGRABitmap.Create(FPicture.Bitmap);
|
|
bgra := TBGRABitmap.Create(Width, Height, BGRAPixelTransparent);
|
|
try
|
|
// Quality
|
|
image.ResampleFilter := FQuality;
|
|
BGRAReplace(image, image.Resample(Width, Height));
|
|
// Style
|
|
case FStyle of
|
|
isCircle: bgra.FillEllipseAntialias(Width div 2, Height div 2,
|
|
Width div 2, Height div 2, image);
|
|
// Rounding, BorderStyle
|
|
isRoundedRectangle: bgra.FillRoundRectAntialias(0, 0, Width,
|
|
Height, FRounding, FRounding, image, FBorderStyle);
|
|
else
|
|
bgra.PutImage(0, 0, image, dmDrawWithTransparency);
|
|
end;
|
|
// OnPaintEvent
|
|
if Assigned(FOnPaintEvent) then
|
|
FOnPaintEvent(Self, bgra);
|
|
bgra.Draw(Canvas, 0, 0, False);
|
|
finally
|
|
bgra.Free;
|
|
image.Free;
|
|
end;
|
|
end;
|
|
|
|
end.
|