Browse Source

dom: split border-radius

mattias 11 months ago
parent
commit
ce3582a8fb
2 changed files with 150 additions and 19 deletions
  1. 37 19
      src/base/fresnel.dom.pas
  2. 113 0
      tests/base/TCFresnelCSS.pas

+ 37 - 19
src/base/fresnel.dom.pas

@@ -97,8 +97,8 @@ type
     fcaBorder, // shorthand for border-width border-style border-color
     fcaBorderTopLeftRadius,
     fcaBorderTopRightRadius,
-    fcaBorderBottomLeftRadius,
     fcaBorderBottomRightRadius,
+    fcaBorderBottomLeftRadius,
     fcaBorderRadius, // shorthand for border-[top-left,top-right,bottom-right,bottom-left]-radius
     fcaFontFeatureSettings,
     fcaFontFamily,
@@ -252,8 +252,8 @@ type
     // one of four corner(s)
     fcsTopLeft,
     fcsTopRight,
-    fcsBottomLeft,
-    fcsBottomRight
+    fcsBottomRight,
+    fcsBottomLeft
     );
   TFresnelCSSCorners = set of TFresnelCSSCorner;
 
@@ -387,7 +387,7 @@ type
     procedure SplitLonghandSides(var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray;
       Top, Right, Bottom, Left: TFresnelCSSAttribute; const Found: TCSSStringArray);
     procedure SplitLonghandCorners(var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray;
-      TopLeft, TopRight, BottomLeft, BottomRight: TFresnelCSSAttribute; const Found: TCSSStringArray);
+      TopLeft, TopRight, BottomRight, BottomLeft: TFresnelCSSAttribute; const Found: TCSSStringArray);
 
     // split shorthands
     procedure SplitBackground(Resolver: TCSSBaseResolver; var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray); virtual;
@@ -406,6 +406,7 @@ type
 
     // get computed attribute as string
     function GetBackground(El: TFresnelElement): string; virtual;
+    function GetBackgroundPosition(El: TFresnelElement): string; virtual;
     function GetBorder(El: TFresnelElement): string; virtual;
     function GetBorderColor(El: TFresnelElement): string; virtual;
     function GetBorderSide(El: TFresnelElement; Side: TFresnelCSSSide): string; virtual;
@@ -2553,6 +2554,21 @@ begin
   if El=nil then ;
 end;
 
+function TFresnelCSSRegistry.GetBackgroundPosition(El: TFresnelElement): string;
+var
+  X, Y: String;
+begin
+  X:=El.GetComputedString(fcaBackgroundPositionX);
+  Y:=El.GetComputedString(fcaBackgroundPositionY);
+  if X>'' then
+  begin
+    Result:=X;
+    if Y>'' then
+      Result+=' '+Y;
+  end else
+    Result:=Y;
+end;
+
 function TFresnelCSSRegistry.GetBorder(El: TFresnelElement): string;
 var
   aLeft, aRight, aTop, aBottom: String;
@@ -2772,7 +2788,7 @@ begin
   SetLength(AttrIDs,2);
   SetLength(Values,2);
   AttrIDs[0]:=FresnelAttrs[fcaBackgroundPositionX].Index;
-  AttrIDs[1]:=FresnelAttrs[fcaBackgroundPositionX].Index;
+  AttrIDs[1]:=FresnelAttrs[fcaBackgroundPositionY].Index;
   Values[0]:=X;
   Values[1]:=Y;
 end;
@@ -3118,12 +3134,12 @@ begin
   // border-radius
   AddFresnelLonghand(fcaBorderTopLeftRadius,false,@CheckBorderRadius);
   AddFresnelLonghand(fcaBorderTopRightRadius,false,@CheckBorderRadius);
-  AddFresnelLonghand(fcaBorderBottomLeftRadius,false,@CheckBorderRadius);
   AddFresnelLonghand(fcaBorderBottomRightRadius,false,@CheckBorderRadius);
+  AddFresnelLonghand(fcaBorderBottomLeftRadius,false,@CheckBorderRadius);
   Chk_BorderRadius_Dim.AllowedUnits:=cuAllLengthsAndPercent;
   Chk_BorderRadius_Dim.AllowFrac:=true;
   AddFresnelShorthand(fcaBorderRadius,@CheckBorderRadius,@SplitBorderRadius,@GetBorderRadius,
-    [fcaBorderTopLeftRadius,fcaBorderTopRightRadius,fcaBorderBottomLeftRadius,fcaBorderBottomRightRadius]);
+    [fcaBorderTopLeftRadius,fcaBorderTopRightRadius,fcaBorderBottomRightRadius,fcaBorderBottomLeftRadius]);
 
   // float
   AddFresnelLonghand(fcaFloat,false,@CheckFloat,'none');
@@ -3244,8 +3260,9 @@ begin
   Chk_BackgroundPositionY_Dim.AllowedKeywordIDs:=[kwTop,kwCenter,kwBottom];
   Chk_BackgroundPositionY_Dim.AllowedUnits:=cuAllLengthsAndPercent;
   Chk_BackgroundPositionY_Dim.AllowFrac:=true;
-  // background-position-y
-  AddFresnelLonghand(fcaBackgroundPosition,false,@CheckBackgroundPosition,'0% 0%');
+  // background-position
+  AddFresnelShorthand(fcaBackgroundPosition,@CheckBackgroundPosition,@SplitBackgroundPosition,
+    @GetBackgroundPosition,[fcaBackgroundPositionX,fcaBackgroundPositionY]);
   Chk_BackgroundPosition_Dim.AllowedKeywordIDs:=[kwLeft,kwRight,kwTop,kwBottom,kwCenter];
   Chk_BackgroundPosition_Dim.AllowedUnits:=cuAllLengthsAndPercent;
   Chk_BackgroundPosition_Dim.AllowFrac:=true;
@@ -3334,14 +3351,14 @@ begin
 end;
 
 procedure TFresnelCSSRegistry.SplitLonghandCorners(var AttrIDs: TCSSNumericalIDArray;
-  var Values: TCSSStringArray; TopLeft, TopRight, BottomLeft, BottomRight: TFresnelCSSAttribute;
+  var Values: TCSSStringArray; TopLeft, TopRight, BottomRight, BottomLeft: TFresnelCSSAttribute;
   const Found: TCSSStringArray);
 begin
   AddSplitLonghandCorners(AttrIDs,Values,
     FresnelAttrs[TopLeft].Index,
     FresnelAttrs[TopRight].Index,
-    FresnelAttrs[BottomLeft].Index,
     FresnelAttrs[BottomRight].Index,
+    FresnelAttrs[BottomLeft].Index,
     Found);
 end;
 
@@ -3378,11 +3395,11 @@ end;
 
 function TFresnelRoundRect.ToString: String;
 begin
-  Result:='['+Box.TopLeft.ToString+','+Box.BottomRight.ToString+'] - [';
-  Result:=Result+Radii[fcsTopLeft].ToString+',';
-  Result:=Result+Radii[fcsTopRight].ToString+',';
-  Result:=Result+Radii[fcsBottomLeft].ToString+',';
-  Result:=Result+Radii[fcsBottomRight].ToString+']';
+  Result:='['+Box.ToString+'] - [';
+  Result:=Result+'TL='+Radii[fcsTopLeft].ToString+',';
+  Result:=Result+'TR='+Radii[fcsTopRight].ToString+',';
+  Result:=Result+'BR='+Radii[fcsBottomRight].ToString+',';
+  Result:=Result+'BL='+Radii[fcsBottomLeft].ToString+']';
 end;
 
 { TFresnelLayoutNode }
@@ -4865,15 +4882,16 @@ begin
   Result.X:=0;
   Result.Y:=0;
 
-  Attr:=TFresnelCSSAttribute(ord(fcaBorderTopLeftRadius)+ord(Corner)-ord(fcsTopLeft));
+  Attr:=TFresnelCSSAttribute(ord(fcaBorderTopLeftRadius)+ord(Corner));
   AttrID:=CSSRegistry.FresnelAttrs[Attr].Index;
   s:=GetCSSString(AttrID,false,Complete);
   aComp.EndP:=PChar(s);
   if not Resolver.ReadComp(aComp) then exit;
   if not GetRadius(X,true) then exit;
-  if Resolver.ReadComp(aComp) then
+  if Resolver.ReadComp(aComp) and (aComp.Kind=rvkSymbol) and (aComp.StartP^='/') then
   begin
-    if not GetRadius(Y,true) then exit;
+    if not Resolver.ReadComp(aComp) then exit;
+    if not GetRadius(Y,false) then exit;
   end else
     Y:=X;
   Result.X:=X;

+ 113 - 0
tests/base/TCFresnelCSS.pas

@@ -129,6 +129,12 @@ type
     procedure Test_BorderStyle_AsString;
     procedure Test_BorderWidth_AsString;
     procedure Test_Border_AsString;
+    procedure Test_BorderRadius_AsString;
+    procedure Test_Margin_AsString;
+    procedure Test_MarginBlock_AsString; // todo
+    //procedure Test_MarginInline_AsString; // todo
+    procedure Test_Padding_AsString;
+    procedure Test_BackgroundPosition_AsString;
 
     procedure TestVar_NoDefault;
     procedure TestVar_Initial;
@@ -859,6 +865,113 @@ begin
   AssertEquals('Div1.GetComputedString(fcaBorderWidth)','red solid 1px',Div1.GetComputedString(fcaBorder));
 end;
 
+procedure TTestFresnelCSS.Test_BorderRadius_AsString;
+var
+  Div1: TDiv;
+  p: TFresnelPoint;
+begin
+  Viewport.Stylesheet.Text:=LinesToStr([
+    'div {',
+    'border-radius:1px 2px 3px 4px / 5px 6px 7px 8px;',
+    '}']);
+  Div1:=TDiv.Create(Viewport);
+  Div1.Name:='Div1';
+  Div1.Parent:=Viewport;
+
+  Viewport.ApplyCSS;
+  AssertEquals('Div1.GetComputedString(fcaBorderTopLeftRadius)','1px / 5px',Div1.GetComputedString(fcaBorderTopLeftRadius));
+  AssertEquals('Div1.GetComputedString(fcaBorderTopRightRadius)','2px / 6px',Div1.GetComputedString(fcaBorderTopRightRadius));
+  AssertEquals('Div1.GetComputedString(fcaBorderBottomRightRadius)','3px / 7px',Div1.GetComputedString(fcaBorderBottomRightRadius));
+  AssertEquals('Div1.GetComputedString(fcaBorderBottomLeftRadius)','4px / 8px',Div1.GetComputedString(fcaBorderBottomLeftRadius));
+
+  p:=Div1.GetComputedBorderRadius(fcsTopLeft);
+  AssertEquals('Div1.GetComputedBorderRadius(fcsTopLeft)','(1,5)',p.ToString);
+
+  AssertEquals('Div1.GetComputedString(fcaBorderRadius)','1px 2px 3px 4px / 5px 6px 7px 8px',Div1.GetComputedString(fcaBorderRadius));
+end;
+
+procedure TTestFresnelCSS.Test_Margin_AsString;
+var
+  Div1: TDiv;
+begin
+  Viewport.Stylesheet.Text:=LinesToStr([
+    'div {',
+    'margin:1px 2px 3px 4px;',
+    '}']);
+  Div1:=TDiv.Create(Viewport);
+  Div1.Name:='Div1';
+  Div1.Parent:=Viewport;
+
+  Viewport.ApplyCSS;
+  AssertEquals('Div1.GetComputedString(fcaMarginTop)','1px',Div1.GetComputedString(fcaMarginTop));
+  AssertEquals('Div1.GetComputedString(fcaMarginRight)','2px',Div1.GetComputedString(fcaMarginRight));
+  AssertEquals('Div1.GetComputedString(fcaMarginBottom)','3px',Div1.GetComputedString(fcaMarginBottom));
+  AssertEquals('Div1.GetComputedString(fcaMarginLeft)','4px',Div1.GetComputedString(fcaMarginLeft));
+  AssertEquals('Div1.GetComputedString(fcaMargin)','1px 2px 3px 4px',Div1.GetComputedString(fcaMargin));
+end;
+
+procedure TTestFresnelCSS.Test_MarginBlock_AsString;
+var
+  Div1: TDiv;
+begin
+  exit;
+
+  Viewport.Stylesheet.Text:=LinesToStr([
+    'div {',
+    'margin-block:1px 2px;',
+    '}']);
+  Div1:=TDiv.Create(Viewport);
+  Div1.Name:='Div1';
+  Div1.Parent:=Viewport;
+
+  Viewport.ApplyCSS;
+  AssertEquals('Div1.GetComputedString(fcaMarginBlockStart)','1px',Div1.GetComputedString(fcaMarginBlockStart));
+  AssertEquals('Div1.GetComputedString(fcaMarginBlockEnd)','2px',Div1.GetComputedString(fcaMarginBlockEnd));
+  AssertEquals('Div1.GetComputedString(fcaMarginTop)','3px',Div1.GetComputedString(fcaMarginTop));
+  AssertEquals('Div1.GetComputedString(fcaMarginRight)','4px',Div1.GetComputedString(fcaMarginRight));
+  AssertEquals('Div1.GetComputedString(fcaMarginBottom)','3px',Div1.GetComputedString(fcaMarginBottom));
+  AssertEquals('Div1.GetComputedString(fcaMarginLeft)','4px',Div1.GetComputedString(fcaMarginLeft));
+  AssertEquals('Div1.GetComputedString(fcaMarginWidth)','1px 2px 3px 4px',Div1.GetComputedString(fcaMargin));
+end;
+
+procedure TTestFresnelCSS.Test_Padding_AsString;
+var
+  Div1: TDiv;
+begin
+  Viewport.Stylesheet.Text:=LinesToStr([
+    'div {',
+    'padding:1px 2px 3px 4px;',
+    '}']);
+  Div1:=TDiv.Create(Viewport);
+  Div1.Name:='Div1';
+  Div1.Parent:=Viewport;
+
+  Viewport.ApplyCSS;
+  AssertEquals('Div1.GetComputedString(fcaPaddingTop)','1px',Div1.GetComputedString(fcaPaddingTop));
+  AssertEquals('Div1.GetComputedString(fcaPaddingRight)','2px',Div1.GetComputedString(fcaPaddingRight));
+  AssertEquals('Div1.GetComputedString(fcaPaddingBottom)','3px',Div1.GetComputedString(fcaPaddingBottom));
+  AssertEquals('Div1.GetComputedString(fcaPaddingLeft)','4px',Div1.GetComputedString(fcaPaddingLeft));
+  AssertEquals('Div1.GetComputedString(fcaPadding)','1px 2px 3px 4px',Div1.GetComputedString(fcaPadding));
+end;
+
+procedure TTestFresnelCSS.Test_BackgroundPosition_AsString;
+var
+  Div1: TDiv;
+begin
+  Viewport.Stylesheet.Text:=LinesToStr([
+    'div {',
+    'background-position:left 10px bottom 15%;',
+    '}']);
+  Div1:=TDiv.Create(Viewport);
+  Div1.Name:='Div1';
+  Div1.Parent:=Viewport;
+
+  Viewport.ApplyCSS;
+  AssertEquals('Div1.GetComputedString(fcaBackgroundPositionX)','left 10px',Div1.GetComputedString(fcaBackgroundPositionX));
+  AssertEquals('Div1.GetComputedString(fcaBackgroundPositionY)','bottom 15%',Div1.GetComputedString(fcaBackgroundPositionY));
+  AssertEquals('Div1.GetComputedString(fcaBackgroundPosition)','left 10px bottom 15%',Div1.GetComputedString(fcaBackgroundPosition));
+end;
+
 procedure TTestFresnelCSS.TestVar_NoDefault;
 var
   Body: TBody;