FMX: How to use ClearRect in combination with IntersectClipRect?

  

I’m using TCanvas.ClearRect to clear an area of a canvas. However, I’ve discovered that this doesn’t seem to work when a clipping rectangle is being used. Why is this and how can I resolve it? Note that I can’t use FillRect instead because there are cases where I may want to clear an area to fully transparent, which I believe can only be done with ClearRect. I’m using Delphi 10.4.
In the example below I would expect Button1 and Button2 to give the same behaviour. However, button2, which sets the clipping rectangle to the size of the whole image, doesn’t perform the clearRect. Note also that Button1 (without clip) doesn’t work immediately after using Button2, but does work on the second try.
Note that SaveState is needed prior to calling IntersectClipRect as mentioned in the documentation. See the example here.
http://docwiki.embarcadero.com/Libraries/Rio/en/FMX.Graphics.TCanvas.IntersectClipRect
unit Unit1;

interface

uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects,
FMX.StdCtrls, FMX.Controls.Presentation, System.UIConsts;

type
TForm1 = class(TForm)
Image1: TImage;
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
procedure Draw;
public
{ Public declarations }
end;

var
Form1: TForm1;
MyBitmap: TBitmap;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
var
MyRect: TRectF;
begin
Draw;

//the rectangle to be cleared
MyRect.Create(10,30,100,80);

if Image1.Bitmap.Canvas.BeginScene then begin
try
Image1.Bitmap.Canvas.ClearRect(MyRect, TAlphaColorRec.Red);
finally
Image1.Bitmap.Canvas.EndScene;
end;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
MyRect: TRectF;
LSave : TCanvasSaveState;
begin
Draw;

//the rectangle to be cleared
MyRect.Create(10,30,100,80);

LSave := Image1.Bitmap.Canvas.SaveState;

try
Image1.Bitmap.Canvas.IntersectClipRect(Image1.Bitmap.Bounds);

if Image1.Bitmap.Canvas.BeginScene then begin
try
Image1.Bitmap.Canvas.ClearRect(MyRect, TAlphaColorRec.Red);
finally
Image1.Bitmap.Canvas.EndScene;
end;
end;

finally
Image1.Bitmap.Canvas.RestoreState(LSave);
end;
end;

procedure TForm1.Draw;
begin
Image1.Bitmap.Clear(TAlphaColorRec.Blue);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
//creates an empty bitmap
Image1.Bitmap := TBitmap.Create(Trunc(Image1.Width), Trunc(Image1.Height));
//loads the initial bitmap (to be manipulated) to Image1
Draw;
end;

end.

form code:
object Form1: TForm1
Left = 0
Top = 0
Caption = ‘Form1’
ClientHeight = 349
ClientWidth = 346
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
OnCreate = FormCreate
DesignerMasterStyle = 0
object Image1: TImage
MultiResBitmap = <
item
end>
Position.X = 8.000000000000000000
Position.Y = 8.000000000000000000
Size.Width = 329.000000000000000000
Size.Height = 273.000000000000000000
Size.PlatformDefault = False
end
object Button1: TButton
Position.X = 48.000000000000000000
Position.Y = 304.000000000000000000
Text = ‘ClearRect’
OnClick = Button1Click
end
object Button2: TButton
Position.X = 208.000000000000000000
Position.Y = 304.000000000000000000
Size.Width = 105.000000000000000000
Size.Height = 22.000000000000000000
Size.PlatformDefault = False
Text = ‘ClearRect Clipped’
OnClick = Button2Click
end
end

Result From clicking Button1. MyRect is the red region. No clipping rect is set.

Result from clicking Button2. MyRect is the same as above. Clipping rect is set to the whole image area and so should make no difference to what gets drawn.

Comments are closed.