Browse Source

* Implement background/roundrect/gradient

Michaël Van Canneyt 1 year ago
parent
commit
fe69e3496c
3 changed files with 218 additions and 27 deletions
  1. 24 3
      src/wasm/fresnel.wasm.app.pp
  2. 6 14
      src/wasm/fresnel.wasm.font.pp
  3. 188 10
      src/wasm/fresnel.wasm.render.pp

+ 24 - 3
src/wasm/fresnel.wasm.app.pp

@@ -76,6 +76,7 @@ Type
     FLastTick: Int64;
     FLastTick: Int64;
     FPrevTick: Int64;
     FPrevTick: Int64;
     procedure CheckMessages;
     procedure CheckMessages;
+    procedure HandleProcessMessages(aCurrent, aPrevious: Double);
   protected
   protected
     procedure DoTick(aCurrent, aPrevious: Double); virtual;
     procedure DoTick(aCurrent, aPrevious: Double); virtual;
     Procedure DoLog(EventType : TEventType; const Msg : String);  override;
     Procedure DoLog(EventType : TEventType; const Msg : String);  override;
@@ -166,7 +167,6 @@ constructor TFresnelWasmForm.Create(AOwner: TComponent);
 
 
 begin
 begin
   Inherited;
   Inherited;
-  Writeln('Setting renderer');
   SetRenderer(TWasmFresnelRenderer.Create(Self));
   SetRenderer(TWasmFresnelRenderer.Create(Self));
 end;
 end;
 
 
@@ -222,7 +222,7 @@ end;
 constructor TFresnelWasmWidgetSet.Create(AOwner: TComponent);
 constructor TFresnelWasmWidgetSet.Create(AOwner: TComponent);
 begin
 begin
   inherited Create(AOwner);
   inherited Create(AOwner);
-  Options:=[wsClick, wsDoubleClick];
+  Options:=[wsClick,wsDoubleClick];
   FForms:=TFPList.Create;
   FForms:=TFPList.Create;
 end;
 end;
 
 
@@ -307,7 +307,12 @@ end;
 
 
 procedure TFresnelWasmWidgetSet.HandleFresnelMouseScrollEvent(aForm: TFresnelWasmForm; Data: PCanvasMessageData);
 procedure TFresnelWasmWidgetSet.HandleFresnelMouseScrollEvent(aForm: TFresnelWasmForm; Data: PCanvasMessageData);
 
 
+var
+  Init : TFresnelMouseEventInit;
+
 begin
 begin
+  InitMouseXYEvent(Init,Data);
+  aForm.form.WSMouseXY(Init,evtMouseWheel);
 end;
 end;
 
 
 
 
@@ -461,10 +466,25 @@ begin
   TFresnelWasmWidgetSet.Create(Nil);
   TFresnelWasmWidgetSet.Create(Nil);
 end;
 end;
 
 
+procedure TFresnelWasmApplication.HandleProcessMessages(aCurrent, aPrevious: Double);
+
+begin
+  FLastTick:=Round(aCurrent);
+  FPrevTick:=Round(aPrevious);
+  try
+    ProcessMessages;
+  except
+    On E : Exception do
+      begin
+      FLLog(etError,'Exception %s during process messages: %s',[E.ClassName,E.Message]);
+      ShowException(E);
+      end;
+  end;
+end;
+
 procedure TFresnelWasmApplication.DoTick(aCurrent, aPrevious: Double);
 procedure TFresnelWasmApplication.DoTick(aCurrent, aPrevious: Double);
 
 
 begin
 begin
-//  FLLog(etDebug,'Tick');
   FLastTick:=Round(aCurrent);
   FLastTick:=Round(aCurrent);
   FPrevTick:=Round(aPrevious);
   FPrevTick:=Round(aPrevious);
   try
   try
@@ -481,6 +501,7 @@ end;
 procedure TFresnelWasmApplication.SetTickHook;
 procedure TFresnelWasmApplication.SetTickHook;
 begin
 begin
   OnFresnelWasmTick:=@DoTick;
   OnFresnelWasmTick:=@DoTick;
+  OnFresnelProcessMessage:=@HandleProcessMessages;
 end;
 end;
 
 
 constructor TFresnelWasmApplication.Create(AOwner: TComponent);
 constructor TFresnelWasmApplication.Create(AOwner: TComponent);

+ 6 - 14
src/wasm/fresnel.wasm.font.pp

@@ -1,6 +1,7 @@
 unit fresnel.wasm.font;
 unit fresnel.wasm.font;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
+{ $DEFINE DEBUGWASMFONT}
 
 
 interface
 interface
 
 
@@ -84,11 +85,11 @@ var
 begin
 begin
   Result:=CompareText(Desc^.Family,aFont.Family);
   Result:=CompareText(Desc^.Family,aFont.Family);
   if Result<>0 then exit;
   if Result<>0 then exit;
-  Result:=Ord(Abs(Desc^.Size-aFont.Size)<Delta);
+  Result:=CompareValue(Desc^.Size,aFont.Size);
   if Result<>0 then exit;
   if Result<>0 then exit;
   Result:=CompareText(Desc^.Style,aFont.Style);
   Result:=CompareText(Desc^.Style,aFont.Style);
   if Result<>0 then exit;
   if Result<>0 then exit;
-  Result:=Ord(Abs(Desc^.Weight-aFont.Weight)<Delta);
+  Result:=CompareValue(Desc^.Weight,aFont.Weight);
   if Result<>0 then exit;
   if Result<>0 then exit;
   Result:=CompareText(Desc^.Variant_,aFont.Variant_);
   Result:=CompareText(Desc^.Variant_,aFont.Variant_);
   if Result<>0 then exit;
   if Result<>0 then exit;
@@ -136,7 +137,6 @@ begin
   p:=Engine.TextSize(Self,aText);
   p:=Engine.TextSize(Self,aText);
   Result.X:=p.X;
   Result.X:=p.X;
   Result.Y:=p.Y;
   Result.Y:=p.Y;
-  Writeln('Textsize : ',Result.ToString);
 end;
 end;
 
 
 function TFresnelWasmFont.TextSizeMaxWidth(const aText: string;
 function TFresnelWasmFont.TextSizeMaxWidth(const aText: string;
@@ -147,7 +147,6 @@ begin
   p:=Engine.TextSizeMaxWidth(Self,aText,Trunc(Max(1,MaxWidth)));
   p:=Engine.TextSizeMaxWidth(Self,aText,Trunc(Max(1,MaxWidth)));
   Result.X:=p.X;
   Result.X:=p.X;
   Result.Y:=p.Y;
   Result.Y:=p.Y;
-  Writeln('TextsizeMaxWidth : ',Result.ToString);
 end;
 end;
 
 
 function TFresnelWasmFont.GetTool: TObject;
 function TFresnelWasmFont.GetTool: TObject;
@@ -236,7 +235,7 @@ var
   aWidth,aHeight : Longint;
   aWidth,aHeight : Longint;
 
 
 begin
 begin
-  Writeln('Enter TFresnelWasmFontEngine.TextSize');
+{$IFDEF DEBUGWASMFONT} FLLog('Enter TFresnelWasmFontEngine.TextSize');{$ENDIF}
   MaybeSetFont(aFont);
   MaybeSetFont(aFont);
   if __fresnel_canvas_measure_text(CanvasID,PByte(aText),Length(aText),@aWidth,@aHeight)<>ECANVAS_SUCCESS then
   if __fresnel_canvas_measure_text(CanvasID,PByte(aText),Length(aText),@aWidth,@aHeight)<>ECANVAS_SUCCESS then
     begin
     begin
@@ -244,15 +243,13 @@ begin
     aHeight:=12;
     aHeight:=12;
     end;
     end;
   Result:=TPoint.Create(aWidth,aHeight);
   Result:=TPoint.Create(aWidth,aHeight);
-  Writeln(Format('Exit TFresnelWasmFontEngine.TextSize: (%d,%d)',[Result.X,Result.Y]));
+{$IFDEF DEBUGWASMFONT}  FLLog('Exit TFresnelWasmFontEngine.TextSize: (%d,%d)',[Result.X,Result.Y]));{$ENDIF}
 end;
 end;
 
 
 function TFresnelWasmFontEngine.TextSizeMaxWidth(aFont: TFresnelWasmFont;
 function TFresnelWasmFontEngine.TextSizeMaxWidth(aFont: TFresnelWasmFont;
   const aText: string; MaxWidth: integer): TPoint;
   const aText: string; MaxWidth: integer): TPoint;
-var
-  aSize: TSize;
+
 begin
 begin
-  Writeln('Enter TFresnelWasmFontEngine.TextSizeMaxWidth');
   MaybeSetFont(aFont);
   MaybeSetFont(aFont);
   Result:=TextSize(aFont,aText);
   Result:=TextSize(aFont,aText);
   if Result.X>MaxWidth then
   if Result.X>MaxWidth then
@@ -260,7 +257,6 @@ begin
     Result.X:=0;
     Result.X:=0;
     Result.Y:=0;
     Result.Y:=0;
     end;
     end;
-  Writeln(Format('Exit TFresnelWasmFontEngine.TextSizeMaxWidth:  (%d,%d)',[Result.X,Result.Y]));
 end;
 end;
 
 
 function TFresnelWasmFontEngine.FontToHTML(aFont: TFresnelWasmFont): String;
 function TFresnelWasmFontEngine.FontToHTML(aFont: TFresnelWasmFont): String;
@@ -273,9 +269,6 @@ function TFresnelWasmFontEngine.FontToHTML(aFont: TFresnelWasmFont): String;
     Result:=Result+aValue
     Result:=Result+aValue
   end;
   end;
 
 
-var
-  v: integer;
-
 begin
 begin
   Result:=aFont.Style;
   Result:=aFont.Style;
   Result:=AddTo(Result,FormatFloat('##00',aFont.Weight));
   Result:=AddTo(Result,FormatFloat('##00',aFont.Weight));
@@ -284,7 +277,6 @@ begin
     Result:=AddTo(Result,'caption')
     Result:=AddTo(Result,'caption')
   else
   else
     Result:=AddTo(Result,aFont.Family);
     Result:=AddTo(Result,aFont.Family);
-  // Writeln('Font to html: ',Result);
 end;
 end;
 
 
 
 

+ 188 - 10
src/wasm/fresnel.wasm.render.pp

@@ -14,6 +14,7 @@ Type
   TWasmFresnelRenderer = Class(TFresnelRenderer)
   TWasmFresnelRenderer = Class(TFresnelRenderer)
   private
   private
     FCanvas: TCanvasID;
     FCanvas: TCanvasID;
+    FFillReset : Boolean;
     FLastFillColor : TFPColor;
     FLastFillColor : TFPColor;
     FLastStrokeColor : TFPColor;
     FLastStrokeColor : TFPColor;
     FLastFontName : String;
     FLastFontName : String;
@@ -21,12 +22,19 @@ Type
     function CheckFont(aFont: IFresnelFont): boolean;
     function CheckFont(aFont: IFresnelFont): boolean;
     function CheckStrokeColor(aColor: TFPColor): Boolean;
     function CheckStrokeColor(aColor: TFPColor): Boolean;
   protected
   protected
+    procedure DoFillRect(const aColor: TFPColor; const aRect: TFresnelRect; CheckFill: Boolean);
+    procedure DoRoundRect(const aColor: TFPColor; const aRect: TFresnelRoundRect; Flags: Integer);
+    // renderer methods
+    procedure SetGradientFillStyle(aGradient : TFresnelCSSLinearGradient);
+    procedure RoundRect(const aColor: TFPColor; const aRect: TFresnelRoundRect; Fill : Boolean); override;
     procedure FillRect(const aColor: TFPColor; const aRect: TFresnelRect); override;
     procedure FillRect(const aColor: TFPColor; const aRect: TFresnelRect); override;
     procedure Line(const aColor: TFPColor; const x1, y1, x2, y2: TFresnelLength); override;
     procedure Line(const aColor: TFPColor; const x1, y1, x2, y2: TFresnelLength); override;
     procedure TextOut(const aLeft, aTop: TFresnelLength;
     procedure TextOut(const aLeft, aTop: TFresnelLength;
       const aFont: IFresnelFont; const aColor: TFPColor;
       const aFont: IFresnelFont; const aColor: TFPColor;
       const aText: string); override;
       const aText: string); override;
     procedure DrawImage(const aLeft, aTop, aWidth, aHeight: TFresnelLength; const aImage: TFPCustomImage); override;
     procedure DrawImage(const aLeft, aTop, aWidth, aHeight: TFresnelLength; const aImage: TFPCustomImage); override;
+    procedure DrawElBackground(El: TFresnelElement; Params: TBorderAndBackground); override;
+    procedure DrawElBorder(El: TFresnelElement; Params: TBorderAndBackground); override;
   public
   public
     constructor Create(AOwner: TComponent); override;
     constructor Create(AOwner: TComponent); override;
     property Canvas: TCanvasID read FCanvas write FCanvas;
     property Canvas: TCanvasID read FCanvas write FCanvas;
@@ -45,15 +53,18 @@ implementation
 
 
 { TWasmFresnelRenderer }
 { TWasmFresnelRenderer }
 
 
-Function FresnelToWasmLength(aLen : TFresnelLength) : Longint;
+Function FresnelToWasmLength(aLen : TFresnelLength; Scaled : boolean = False) : Longint;
 begin
 begin
-  Result:=Round(aLen);
+  if Scaled then
+    Result:=Round(aLen*100)
+  else
+    Result:=Round(aLen);
 end;
 end;
 
 
 function TWasmFresnelRenderer.CheckFillColor(aColor : TFPColor) : Boolean;
 function TWasmFresnelRenderer.CheckFillColor(aColor : TFPColor) : Boolean;
 
 
 begin
 begin
-  Result:=not (aColor=FLastFillColor);
+  Result:=not (aColor=FLastFillColor) or FFillReset;
   if Result then
   if Result then
     begin
     begin
     With aColor do
     With aColor do
@@ -62,6 +73,7 @@ begin
       __fresnel_canvas_set_fillstyle(Canvas,Red,Green,Blue,Alpha);
       __fresnel_canvas_set_fillstyle(Canvas,Red,Green,Blue,Alpha);
       end;
       end;
     FLastFillColor:=aColor;
     FLastFillColor:=aColor;
+    FFillReset:=False;
     end;
     end;
 end;
 end;
 
 
@@ -80,6 +92,86 @@ begin
     end;
     end;
 end;
 end;
 
 
+procedure TWasmFresnelRenderer.SetGradientFillStyle(aGradient: TFresnelCSSLinearGradient);
+
+var
+  Colors : TGradientColorPoints;
+  aX1,aY1,aX2,aY2 : Longint;
+  P : TGradientColorPoint;
+  Len,I : Integer;
+
+begin
+  aX1:=FresnelToWasmLength(aGradient.StartPoint.X);
+  aY1:=FresnelToWasmLength(aGradient.StartPoint.Y);
+  aX2:=FresnelToWasmLength(aGradient.EndPoint.X);
+  aY2:=FresnelToWasmLength(aGradient.EndPoint.Y);
+  Len:=Length(aGradient.Colors);
+  Colors:=[];
+  if Len=1 then
+    SetLength(Colors,Len+1)
+  else
+    SetLength(Colors,Len);
+  SetLength(Colors,Len);
+  For I:=0 to Length(aGradient.Colors)-1 do
+    begin
+    P.Percentage:=FresnelToWasmLength(aGradient.Colors[I].Percentage,True);
+    P.Red:=aGradient.Colors[I].Color.Red;
+    P.Green:=aGradient.Colors[I].Color.Green;
+    P.Blue:=aGradient.Colors[I].Color.Blue;
+    P.Alpha:=aGradient.Colors[I].Color.Alpha;
+    Colors[i]:=P;
+    end;
+  if Len=1 then
+    begin
+    P.Percentage:=100;
+    Colors[1]:=P;
+    end;
+  __fresnel_canvas_linear_gradient_fillstyle(Canvas,aX1,aY1,aX2,aY2,Length(Colors),PGradientColorPoints(Colors));
+  FFillReset:=True;
+end;
+
+procedure TWasmFresnelRenderer.DoRoundRect(const aColor: TFPColor; const aRect: TFresnelRoundRect; Flags: Integer);
+
+var
+  RR : TCanvasRoundRectData; // Array[0..11] of longint;
+  Idx : integer;
+  Corner : TFresnelCSSCorner;
+
+ procedure AddP(apoint : TFresnelPoint; OffSetOrigin : Boolean = False);
+ begin
+   RR[Idx]:=FresnelToWasmLength(aPoint.X+(Ord(OffSetOrigin)*Origin.X),True);
+   Inc(Idx);
+   RR[Idx]:=FresnelToWasmLength(aPoint.Y+(Ord(OffSetOrigin)*Origin.Y),True);
+   Inc(Idx);
+ end;
+
+begin
+  CheckStrokeColor(aColor);
+  FLLog(etDebug,'RoundRect(%d,{%s})',[Canvas,aRect.ToString]);
+  Idx:=0;
+  AddP(aRect.Box.TopLeft,True);
+  AddP(aRect.Box.BottomRight,True);
+  For Corner in TFresnelCSSCorner do
+    AddP(aRect.Radius[Corner]);
+  if __fresnel_canvas_roundrect(Canvas,Flags,@RR)<>ECANVAS_SUCCESS then
+    FLLog(etError,'failed to draw round rectangle on canvas %d',[Canvas]);
+end;
+
+procedure TWasmFresnelRenderer.RoundRect(const aColor: TFPColor; const aRect: TFresnelRoundRect; Fill: Boolean);
+
+var
+  Flags : Integer;
+
+begin
+  Flags:=0;
+  if Fill then
+    begin
+    CheckFillColor(aColor);
+    FLags:=ROUNDRECT_FLAG_FILL;
+    end;
+  DoRoundRect(aColor,aRect,Flags);
+end;
+
 function TWasmFresnelRenderer.CheckFont(aFont : IFresnelFont) : boolean;
 function TWasmFresnelRenderer.CheckFont(aFont : IFresnelFont) : boolean;
 
 
 var
 var
@@ -96,11 +188,18 @@ begin
     end;
     end;
 end;
 end;
 
 
-procedure TWasmFresnelRenderer.FillRect(const aColor: TFPColor; const aRect: TFresnelRect);
+procedure TWasmFresnelRenderer.DoFillRect(const aColor: TFPColor; const aRect: TFresnelRect; CheckFill : Boolean);
+
 begin
 begin
-  CheckFillColor(aColor);
+  if CheckFill then
+    CheckFillColor(aColor);
   FLLog(etDebug,'__fresnel_canvas_fillrect(%d,%d,%d,%d,%d)',[Canvas,FresnelToWasmLength(aRect.Left+Origin.X),FresnelToWasmLength(aRect.Top+Origin.Y),FresnelToWasmLength(aRect.Width),FresnelToWasmLength(aRect.Height)]);
   FLLog(etDebug,'__fresnel_canvas_fillrect(%d,%d,%d,%d,%d)',[Canvas,FresnelToWasmLength(aRect.Left+Origin.X),FresnelToWasmLength(aRect.Top+Origin.Y),FresnelToWasmLength(aRect.Width),FresnelToWasmLength(aRect.Height)]);
-  __fresnel_canvas_fillrect(Canvas,FresnelToWasmLength(aRect.Left),FresnelToWasmLength(aRect.Top),FresnelToWasmLength(aRect.Width),FresnelToWasmLength(aRect.Height));
+  __fresnel_canvas_fillrect(Canvas,FresnelToWasmLength(aRect.Left+Origin.X),FresnelToWasmLength(aRect.Top+Origin.Y),FresnelToWasmLength(aRect.Width),FresnelToWasmLength(aRect.Height));
+end;
+
+procedure TWasmFresnelRenderer.FillRect(const aColor: TFPColor; const aRect: TFresnelRect);
+begin
+  DoFillRect(aColor,aRect,True);
 end;
 end;
 
 
 procedure TWasmFresnelRenderer.Line(const aColor: TFPColor; const x1, y1, x2, y2: TFresnelLength);
 procedure TWasmFresnelRenderer.Line(const aColor: TFPColor; const x1, y1, x2, y2: TFresnelLength);
@@ -117,11 +216,34 @@ end;
 procedure TWasmFresnelRenderer.TextOut(const aLeft, aTop: TFresnelLength; const aFont: IFresnelFont; const aColor: TFPColor;
 procedure TWasmFresnelRenderer.TextOut(const aLeft, aTop: TFresnelLength; const aFont: IFresnelFont; const aColor: TFPColor;
   const aText: string);
   const aText: string);
 
 
+var
+  I,Count : integer;
+  aShadow : PFresnelTextShadow;
+
 begin
 begin
   CheckFillColor(aColor);
   CheckFillColor(aColor);
   CheckFont(aFont);
   CheckFont(aFont);
-  if __fresnel_canvas_filltext(Canvas,Round(aLeft+Origin.X),Round(aTop+Origin.Y),PByte(aText),Length(aText))<>ECANVAS_SUCCESS then
-    FLLog(etError,'failed to draw canvas %d text "%s"',[Canvas,aText]);
+  Count:=TextShadowCount;
+  if Count=0 then
+    begin
+    // X,Y,Radius,r,g,b,a)
+    if __fresnel_canvas_set_textshadow_params(Canvas,0,0,0,0,0,0,0)<>ECANVAS_SUCCESS then
+      FLLog(etError,'failed to clear shadow params for text "%s"',[Canvas,aText]);
+    if __fresnel_canvas_filltext(Canvas,FresnelToWasmLength(aLeft+Origin.X),FresnelToWasmLength(aTop+Origin.Y),PByte(aText),Length(aText))<>ECANVAS_SUCCESS then
+      FLLog(etError,'failed to draw canvas %d text "%s"',[Canvas,aText]);
+    end
+  else
+    for I:=0 to TextShadowCount-1 do
+      begin
+      aShadow:=Self.TextShadow[I];
+      With aShadow^ do
+        if __fresnel_canvas_set_textshadow_params(Canvas,FresnelToWasmLength(Offset.X),FresnelToWasmLength(Offset.Y),FresnelToWasmLength(Radius,True),Color.Red,Color.Green,Color.Blue,Color.Alpha)<>ECANVAS_SUCCESS then
+          FLLog(etError,'failed to set shadow params for text "%s"',[Canvas,aText]);
+      if __fresnel_canvas_filltext(Canvas,FresnelToWasmLength(aLeft+Origin.X),FresnelToWasmLength(aTop+Origin.Y),PByte(aText),Length(aText))<>ECANVAS_SUCCESS then
+        FLLog(etError,'failed to draw canvas %d text "%s"',[Canvas,aText]);
+      if __fresnel_canvas_set_textshadow_params(Canvas,0,0,0,0,0,0,0)<>ECANVAS_SUCCESS then
+        FLLog(etError,'failed to clear shadow params for text "%s"',[Canvas,aText]);
+      end;
 end;
 end;
 
 
 procedure TWasmFresnelRenderer.DrawImage(const aLeft, aTop, aWidth, aHeight: TFresnelLength; const aImage: TFPCustomImage);
 procedure TWasmFresnelRenderer.DrawImage(const aLeft, aTop, aWidth, aHeight: TFresnelLength; const aImage: TFPCustomImage);
@@ -138,8 +260,8 @@ begin
     if Img<>aImage then
     if Img<>aImage then
       Img.Assign(aImage);
       Img.Assign(aImage);
     __fresnel_canvas_draw_image(Canvas,
     __fresnel_canvas_draw_image(Canvas,
-                                FresnelToWasmLength({aLeft+}Origin.X),
-                                FresnelToWasmLength({aTop+}Origin.Y),
+                                FresnelToWasmLength(aLeft+Origin.X),
+                                FresnelToWasmLength(aTop+Origin.Y),
                                 FresnelToWasmLength(aWidth),
                                 FresnelToWasmLength(aWidth),
                                 FresnelToWasmLength(aHeight),
                                 FresnelToWasmLength(aHeight),
                                 Img.Width,
                                 Img.Width,
@@ -151,6 +273,62 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TWasmFresnelRenderer.DrawElBackground(El: TFresnelElement; Params: TBorderAndBackground);
+
+begin
+  if el=nil then;
+  if Params.BackgroundImage is TFresnelCSSLinearGradient then
+  begin
+    SetGradientFillStyle(Params.BackgroundImage as TFresnelCSSLinearGradient);
+    if Params.HasRadius then
+      DoRoundRect(Params.BackgroundColorFP,Params.BoundingBox,ROUNDRECT_FLAG_FILL)
+    else
+      DoFillRect(Params.BackgroundColorFP,Params.BoundingBox.Box,False);
+  end else if Params.BackgroundColorFP.Alpha>alphaTransparent then
+  begin
+    //FLLog(etDebug,'TFresnelRenderer.DrawElBorder drawing background %s',[El.GetPath]);
+    if Params.HasRadius then
+      RoundRect(Params.BackgroundColorFP,Params.BoundingBox,True)
+    else
+      FillRect(Params.BackgroundColorFP,Params.BoundingBox.Box);
+  end;
+
+end;
+
+procedure TWasmFresnelRenderer.DrawElBorder(El: TFresnelElement; Params: TBorderAndBackground);
+
+var
+  BB : TFresnelRoundRect;
+  HalfWidth : TFresnelLength;
+  C : TFresnelCSSCorner;
+
+begin
+  FLLog(etDebug,'TWasmFresnelRenderer.DrawElBorder("%s")',[El.GetPath]);
+  if Not Params.HasRadius then
+    Inherited DrawElBorder(El,Params)
+  else if Params.SameBorderWidth then
+    begin
+    __fresnel_canvas_set_linewidth(Canvas,FresnelToWasmLength(Params.Width[ffsLeft],True));
+    BB:=Params.BoundingBox;
+    With Params do
+      begin
+      HalfWidth:=0; // Width[ffsLeft]/2;
+      BB.Box.TopLeft.OffSet(-HalfWidth,-HalfWidth);
+      BB.Box.BottomRight.OffSet(HalfWidth,HalfWidth);
+      For C in TFresnelCSSCorner do
+        begin
+        BB.Radius[C].X:=BB.Radius[C].X+HalfWidth;
+        BB.Radius[C].Y:=BB.Radius[C].Y+HalfWidth;
+        end
+      end;
+    RoundRect(Params.Color[Low(TFresnelCSSSide)],BB,False);
+    end
+  else
+    begin
+    // Todo
+    end;
+end;
+
 constructor TWasmFresnelRenderer.Create(AOwner: TComponent);
 constructor TWasmFresnelRenderer.Create(AOwner: TComponent);
 begin
 begin
   inherited Create(AOwner);
   inherited Create(AOwner);