Recent

Author Topic: BGRACanvas2D Save and Restore Problem  (Read 828 times)

Coxy

  • New Member
  • *
  • Posts: 32
BGRACanvas2D Save and Restore Problem
« on: September 22, 2020, 12:19:04 pm »
When I use BGRACanvas2D Save and Restore with baseline set to 'top' I get different output from when no Save and Restore called.

Lazarus: 2.0.10
FPC Version: 3.2.0
bgrabitmappack: 11.2.1.0

Example Code:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, BGRABitmap,
  9.   BGRACanvas2D, BGRABitmapTypes;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     Label1: TLabel;
  17.     Label2: TLabel;
  18.     procedure FormCreate(Sender: TObject);
  19.     procedure FormDestroy(Sender: TObject);
  20.     procedure FormPaint(Sender: TObject);
  21.   private
  22.     FImg : TBGRABitmap;
  23.   public
  24.  
  25.     procedure PrepImg;
  26.   end;
  27.  
  28. var
  29.   Form1: TForm1;
  30.  
  31. implementation
  32.  
  33. {$R *.lfm}
  34.  
  35. { TForm1 }
  36.  
  37. procedure TForm1.FormCreate(Sender: TObject);
  38. begin
  39.   PrepImg;
  40. end;
  41.  
  42. procedure TForm1.FormDestroy(Sender: TObject);
  43. begin
  44.   FImg.Free;
  45. end;
  46.  
  47. procedure TForm1.FormPaint(Sender: TObject);
  48. begin
  49.   FImg.Draw(Canvas,100,100);
  50. end;
  51.  
  52. procedure TForm1.PrepImg;
  53. const
  54.   TextLine = 'Test Text';
  55. var
  56.   ts : TCanvas2dTextSize;
  57.   ctx : TBGRACanvas2D;
  58. begin
  59.   FImg.Free;
  60.   FImg := TBGRABitmap.Create(1,1);
  61.  
  62.   ctx := FImg.Canvas2D;
  63.  
  64.   ctx.textBaseline:='top';
  65.   ctx.fontName:='Tohoma';
  66.   ctx.fontStyle:=[];
  67.   ctx.fontEmHeight:=100;
  68.   ctx.fillStyle(BGRA(240,0,0));
  69.  
  70.   ts := ctx.measureText(TextLine);
  71.  
  72.   FImg.SetSize(trunc(ts.width),trunc(ts.height));
  73.   FImg.FillTransparent;
  74.  
  75.   //ctx.save;
  76.   //ctx.restore;
  77.  
  78.   //ctx.textBaseline:='top';
  79.  
  80.   ctx.fillText(TextLine,0,0);
  81. end;
  82.  
  83. end.
  84.  

Run three times

i) Save, Restore and baseline commented out.
ii) Save and Restore uncommented, baseline commented out.
iii) Save, Restore and baseline uncommented.

Looks like an 'alphabetic' baseline is used after restore. You shouldn't need to set this after a Restore.

Output from these runs below.

Coxy

  • New Member
  • *
  • Posts: 32
Re: BGRACanvas2D Save and Restore Problem
« Reply #1 on: September 22, 2020, 01:56:03 pm »
A little more info for this issue.

Modified unit BGRACanvas2D and added property to TBGRACanvas2D

Code: Pascal  [Select][+][-]
  1.     property currState:TBGRACanvasState2D read currentState;
  2.  

Original example code modified to,

Code: Pascal  [Select][+][-]
  1.   a := ctx.currState;
  2.   ctx.save;
  3.   ctx.restore;
  4.   b := ctx.currState;
  5.  

Inspecting 'a' and 'b' shows 'TEXTBASELINE' changed to 'alphabetic' from 'top', see images below.

TBGRACanvas2D.Save calls TBGRACanvasState2D.Duplicate to create copy of current state, it does not copy 'textBaseline'. I've added code to copy this value which resolves this issue.

Code: Pascal  [Select][+][-]
  1.   result.fontStyle := fontStyle;
  2.   result.textDirection:= textDirection;
  3.   result.textBaseline:=textBaseline;      // Mod by Coxy
  4.  
  5.   result.lineWidth := lineWidth;
  6.   result.penStroker.LineCap := penStroker.LineCap;
  7.  


Is this a valid fix or was the value not copied for some obscure reason?

Other members that have changed are 'FCLIPMASKOWNED' and 'PENSTROKER'.


circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: BGRACanvas2D Save and Restore Problem
« Reply #2 on: September 23, 2020, 12:14:02 pm »
Thanks for reporting the problem.

I have applied your change in the Duplicate function of the state.

Regarding ClipMaskOwned and PenStroker, it is normal that the value would change. The mask is not actually duplicated when the state is duplicated and the pen stroker is a helper class and what matters here is that its properties would be the same.
Conscience is the debugger of the mind

 

TinyPortal © 2005-2018