Pārlūkot izejas kodu

lcl skia: added TSkCustomWinControl

mattias 1 gadu atpakaļ
vecāks
revīzija
ac6e930688
1 mainītis faili ar 318 papildinājumiem un 6 dzēšanām
  1. 318 6
      demo/LCLSkiaPaintBox/LCL.Skia.pas

+ 318 - 6
demo/LCLSkiaPaintBox/LCL.Skia.pas

@@ -49,6 +49,7 @@ type
     constructor Create(AOwner: TComponent); override;
     destructor Destroy; override;
     procedure Redraw; virtual;
+    procedure Invalidate; override;
     property Opacity: Byte read FOpacity write SetOpacity default 255;
     property ScaleFactor: Single read FScaleFactor;
   end;
@@ -171,14 +172,14 @@ type
     function GetCanvas: TCanvas;
     //function GetDeviceContext(var WindowHandle: HWND): HDC;
     function GetDrawCacheKind: TSkDrawCacheKind;
-    function GetHeight: Integer;
+    function GetClientHeight: Integer;
     function GetScaleFactor: Single;
-    function GetWidth: Integer;
+    function GetClientWidth: Integer;
     property Canvas: TCanvas read GetCanvas;
     property DrawCacheKind: TSkDrawCacheKind read GetDrawCacheKind;
-    property Height: Integer read GetHeight;
+    property ClientHeight: Integer read GetClientHeight;
     property ScaleFactor: Single read GetScaleFactor;
-    property Width: Integer read GetWidth;
+    property ClientWidth: Integer read GetClientWidth;
   end;
 
   { ISkControlRender }
@@ -197,6 +198,48 @@ type
     class function MakeRender(const ATarget: ISkControlRenderTarget; const ABackend: TSkControlRenderBackend): ISkControlRender; static;
   end;
 
+  { TSkCustomWinControl }
+
+  TSkCustomWinControl = class abstract(TCustomControl, ISkControlRenderTarget)
+  private
+    FBackendRender: TSkControlRenderBackend;
+    FBackgroundColor: TAlphaColor;
+    FDrawCacheKind: TSkDrawCacheKind;
+    FOnDraw: TSkDrawEvent;
+    FRender: ISkControlRender;
+    FScaleFactor: Single;
+    function GetRender: ISkControlRender;
+    procedure DeleteBuffers;
+    procedure SetBackendRender(AValue: TSkControlRenderBackend);
+    procedure SetBackgroundColor(AValue: TAlphaColor);
+    procedure SetDrawCacheKind(AValue: TSkDrawCacheKind);
+    procedure SetOnDraw(AValue: TSkDrawEvent);
+  protected
+    procedure DestroyWnd; override; // called after child handles are freed
+    procedure DrawContent(const ACanvas: ISkCanvas; const ADest: TRectF; const AOpacity: Single); virtual;
+    function MakeRender(ABackendRender: TSkControlRenderBackend): ISkControlRender; virtual;
+    procedure Paint; override;
+    procedure Resize; override;
+    procedure ChangeScale(Multiplier, Divider: Integer); override;
+    class function GetControlClassDefaultSize: TSize; override;
+    // for interface ISkControlRenderTarget:
+    procedure Draw(const ACanvas: ISkCanvas; const ADest: TRectF; const AOpacity: Single); virtual;
+    function GetCanvas: TCanvas; virtual;
+    function GetDrawCacheKind: TSkDrawCacheKind; virtual;
+    function GetClientHeight: Integer; virtual;
+    function GetScaleFactor: Single; virtual;
+    function GetClientWidth: Integer; virtual;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    property BackendRender: TSkControlRenderBackend read FBackendRender write SetBackendRender default TSkControlRenderBackend.Default;
+    property BackgroundColor: TAlphaColor read FBackgroundColor write SetBackgroundColor default TAlphaColors.White;
+    property DrawCacheKind: TSkDrawCacheKind read FDrawCacheKind write SetDrawCacheKind default TSkDrawCacheKind.Raster;
+    property OnDraw: TSkDrawEvent read FOnDraw write SetOnDraw;
+    property Render: ISkControlRender read GetRender;
+    property ScaleFactor: Single read FScaleFactor;
+  end;
+
   { TSkDefaultProviders }
 
   TSkDefaultProviders = class
@@ -486,6 +529,12 @@ begin
   Repaint;
 end;
 
+procedure TSkCustomControl.Invalidate;
+begin
+  FDrawCached := false;
+  inherited Invalidate;
+end;
+
 { TSkSvgBrush }
 
 function TSkSvgBrush.GetDOM: ISkSVGDOM;
@@ -794,23 +843,286 @@ begin
   inherited Destroy;
 end;
 
+type
+  { TSkRasterControlRender }
+
+  TSkRasterControlRender = class(TSkControlRender, ISkControlRender)
+  strict private
+    FDrawCached: Boolean;
+    FIntfImg: TLazIntfImage;
+    FTarget: ISkControlRenderTarget;
+    procedure DeleteBuffers;
+    procedure DoRender(const AWidth, AHeight: Integer; const AScaleFactor: Single;
+      const ACanvas: TCanvas{; const ABackgroundBuffer: TBitmap; const AOpacity: Byte});
+  public
+    constructor Create(const ATarget: ISkControlRenderTarget);
+    destructor Destroy; override;
+    procedure Redraw;
+    procedure Resized;
+    procedure ISkControlRender.Resized = DeleteBuffers;
+    function TryRender(const ABackgroundBuffer: TBitmap; const AOpacity: Byte): Boolean;
+  end;
+
+procedure TSkRasterControlRender.DeleteBuffers;
+begin
+  FDrawCached := False;
+  FreeAndNil(FIntfImg);
+end;
+
+procedure TSkRasterControlRender.DoRender(const AWidth, AHeight: Integer;
+  const AScaleFactor: Single; const ACanvas: TCanvas);
+
+  procedure InternalDraw;
+  var
+    LSurface: ISkSurface;
+    LDestRect: TRectF;
+  begin
+    LSurface := TSkSurface.MakeRasterDirect(TSkImageInfo.Create(AWidth, AHeight),
+      FIntfImg.PixelData, FIntfImg.DataDescription.BytesPerLine);
+    if LSurface = nil then
+      Exit;
+    LSurface.Canvas.Concat(TMatrix.CreateScaling(AScaleFactor, AScaleFactor));
+    LDestRect := RectF(0, 0, AWidth / AScaleFactor, AHeight / AScaleFactor);
+    LSurface.Canvas.Clear(TAlphaColors.Null);
+    FTarget.Draw(LSurface.Canvas, LDestRect, 1);
+    FDrawCached := True;
+  end;
+
+var
+  Desc: TRawImageDescription;
+  Bmp: TBitmap;
+begin
+  if (AWidth <= 0) or (AHeight <= 0) then
+    Exit;
+
+  if FIntfImg=nil then
+  begin
+    if SkNative32ColorType=TSkColorType.BGRA8888 then
+      Desc.Init_BPP32_B8G8R8A8_BIO_TTB(AWidth, AHeight)
+    else
+      Desc.Init_BPP32_R8G8B8A8_BIO_TTB(AWidth, AHeight);
+    FIntfImg:=TLazIntfImage.Create(0,0);
+    FIntfImg.DataDescription:=Desc;
+    FIntfImg.SetSize(AWidth,AHeight);
+  end else if (FIntfImg.Width<>AWidth) or (FIntfImg.Height<>AHeight) then begin
+    FIntfImg.SetSize(AWidth,AHeight);
+  end;
+
+  if (not FDrawCached) or (FTarget.DrawCacheKind = TSkDrawCacheKind.Never) then
+    InternalDraw;
+
+  Bmp:=TBitmap.Create;
+  try
+    Bmp.LoadFromIntfImage(FIntfImg);
+    ACanvas.Draw(0,0,Bmp);
+  finally
+    Bmp.Free;
+  end;
+end;
+
+constructor TSkRasterControlRender.Create(
+  const ATarget: ISkControlRenderTarget);
+begin
+  inherited Create;
+  FTarget := ATarget;
+end;
+
+destructor TSkRasterControlRender.Destroy;
+begin
+  DeleteBuffers;
+  inherited;
+end;
+
+procedure TSkRasterControlRender.Redraw;
+begin
+  FDrawCached := False;
+end;
+
+procedure TSkRasterControlRender.Resized;
+begin
+
+end;
+
+function TSkRasterControlRender.TryRender(const ABackgroundBuffer: TBitmap; const AOpacity: Byte): Boolean;
+begin
+  DoRender(FTarget.ClientWidth, FTarget.ClientHeight, FTarget.ScaleFactor, FTarget.Canvas{, ABackgroundBuffer, AOpacity});
+  Result := True;
+end;
+
 { TSkControlRender }
 
 class function TSkControlRender.MakeRender(
   const ATarget: ISkControlRenderTarget; const ABackend: TSkControlRenderBackend
   ): ISkControlRender;
 begin
-  raise ESkLcl.Create('TSkControlRender.MakeRender ToDo');
   if ATarget=nil then ;
   case ABackend of
     TSkControlRenderBackend.Default,
-    TSkControlRenderBackend.Raster: Result := nil; //TSkRasterControlRender.Create(ATarget);
+    TSkControlRenderBackend.Raster: Result := TSkRasterControlRender.Create(ATarget);
     TSkControlRenderBackend.HardwareAcceleration: Result := nil; //TSkGlControlRender.Create(ATarget);
   else
     Result := nil{%H-};
   end;
 end;
 
+{ TSkCustomWinControl }
+
+function TSkCustomWinControl.GetRender: ISkControlRender;
+begin
+  if FRender = nil then
+    FRender := MakeRender(FBackendRender);
+  Result := FRender;
+end;
+
+procedure TSkCustomWinControl.DeleteBuffers;
+begin
+
+end;
+
+procedure TSkCustomWinControl.SetBackendRender(AValue: TSkControlRenderBackend);
+begin
+  if FBackendRender=AValue then Exit;
+  FBackendRender := AValue;
+  FRender := nil;
+end;
+
+procedure TSkCustomWinControl.SetBackgroundColor(AValue: TAlphaColor);
+begin
+  if FBackgroundColor=AValue then Exit;
+  FBackgroundColor:=AValue;
+  Invalidate;
+end;
+
+procedure TSkCustomWinControl.SetDrawCacheKind(AValue: TSkDrawCacheKind);
+begin
+  if FDrawCacheKind=AValue then Exit;
+  FDrawCacheKind:=AValue;
+  if FDrawCacheKind <> TSkDrawCacheKind.Always then
+    Invalidate;
+end;
+
+procedure TSkCustomWinControl.SetOnDraw(AValue: TSkDrawEvent);
+begin
+  if FOnDraw=AValue then Exit;
+  FOnDraw:=AValue;
+  Invalidate;
+end;
+
+procedure TSkCustomWinControl.DestroyWnd;
+begin
+  FRender:=nil;
+  inherited DestroyWnd;
+end;
+
+procedure TSkCustomWinControl.DrawContent(const ACanvas: ISkCanvas;
+  const ADest: TRectF; const AOpacity: Single);
+begin
+  if csDesigning in ComponentState then
+    DrawDesignBorder(ACanvas, ADest, AOpacity);
+  if Assigned(FOnDraw) then
+    FOnDraw(Self, ACanvas, ADest, AOpacity);
+end;
+
+procedure TSkCustomWinControl.Draw(const ACanvas: ISkCanvas;
+  const ADest: TRectF; const AOpacity: Single);
+var
+  LPaint: ISkPaint;
+begin
+  if TAlphaColorRec(FBackgroundColor).A > 0 then
+  begin
+    LPaint := TSkPaint.Create;
+    LPaint.Color := FBackgroundColor;
+    LPaint.AntiAlias := True;
+    ACanvas.DrawRect(ADest, LPaint);
+  end;
+  DrawContent(ACanvas,ADest,AOpacity);
+end;
+
+function TSkCustomWinControl.MakeRender(ABackendRender: TSkControlRenderBackend
+  ): ISkControlRender;
+begin
+  Result := TSkControlRender.MakeRender(Self, ABackendRender);
+end;
+
+procedure TSkCustomWinControl.Paint;
+var
+  LBackgroundBuffer: TBitmap;
+begin
+  if (Width <= 0) or (Height <= 0) or (Render = nil) then
+    Exit;
+  LBackgroundBuffer := nil;
+  if not FRender.TryRender(LBackgroundBuffer, 255)
+      and (FBackendRender = TSkControlRenderBackend.HardwareAcceleration) then
+  begin
+    FRender := MakeRender(TSkControlRenderBackend.Raster);
+    if FRender <> nil then
+      FRender.Redraw;
+  end;
+  inherited Paint;
+end;
+
+procedure TSkCustomWinControl.Resize;
+begin
+  if FRender <> nil then
+    FRender.Resized;
+  DeleteBuffers;
+  inherited Resize;
+end;
+
+class function TSkCustomWinControl.GetControlClassDefaultSize: TSize;
+begin
+  Result.cx:=80;
+  Result.cy:=80;
+end;
+
+function TSkCustomWinControl.GetCanvas: TCanvas;
+begin
+  Result := Canvas;
+end;
+
+function TSkCustomWinControl.GetDrawCacheKind: TSkDrawCacheKind;
+begin
+  Result := FDrawCacheKind;
+end;
+
+function TSkCustomWinControl.GetClientHeight: Integer;
+begin
+  Result := ClientHeight;
+end;
+
+function TSkCustomWinControl.GetScaleFactor: Single;
+begin
+  Result := ScaleFactor;
+end;
+
+function TSkCustomWinControl.GetClientWidth: Integer;
+begin
+  Result := ClientWidth;
+end;
+
+procedure TSkCustomWinControl.ChangeScale(Multiplier, Divider: Integer);
+begin
+  if Multiplier <> Divider then
+    FScaleFactor := FScaleFactor * Multiplier / Divider;
+  inherited ChangeScale(Multiplier, Divider);
+end;
+
+constructor TSkCustomWinControl.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FBackgroundColor := TAlphaColors.White;
+  FDrawCacheKind := TSkDrawCacheKind.Raster;
+  FScaleFactor := 1;
+  ControlStyle:=ControlStyle+[csAcceptsControls,csOpaque];
+end;
+
+destructor TSkCustomWinControl.Destroy;
+begin
+  DeleteBuffers;
+  FRender := nil;
+  inherited Destroy;
+end;
+
 { TSkDefaultProviders }
 
 class constructor TSkDefaultProviders.Create;