Explorar el Código

TFresnelCSSAttribute: added fcaBorderRadius

mattias hace 1 año
padre
commit
a539424470
Se han modificado 1 ficheros con 127 adiciones y 11 borrados
  1. 127 11
      src/base/fresnel.dom.pas

+ 127 - 11
src/base/fresnel.dom.pas

@@ -82,6 +82,11 @@ type
     fcaBorderRightStyle,
     fcaBorderTopStyle,
     fcaBorderBottomStyle,
+    fcaBorderRadius, // shorthand for border-[top-left,top-right,bottom-right,bottom-left]-radius
+    fcaBorderTopLeftRadius,
+    fcaBorderTopRightRadius,
+    fcaBorderBottomRightRadius,
+    fcaBorderBottomLeftRadius,
     fcaBoxSizing,
     fcaFloat,
     fcaFont, // shorthand
@@ -115,8 +120,9 @@ type
     fcaPaddingRight,
     fcaPaddingBottom,
     fcaVisibility,
+    // todo: fcaBackground shorthand
     fcaBackgroundColor,
-    fcaColor
+    fcaColor     // text color
     );
   TFresnelCSSAttributes = set of TFresnelCSSAttribute;
 
@@ -160,6 +166,11 @@ const
     'border-right-style',
     'border-top-style',
     'border-bottom-style',
+    'border-radius',
+    'border-top-left-radius',
+    'border-top-right-radius',
+    'border-bottom-right-radius',
+    'border-bottom-left-radius',
     'box-sizing',
     'float',
     'font',
@@ -312,6 +323,7 @@ type
   PFresnelFontDesc = ^TFresnelFontDesc;
 
   TFresnelLengthCheck = (
+    fclNoWarn,
     flcNoNegative,
     flcNoPercentage,
     flcInteger
@@ -393,6 +405,8 @@ type
     function CheckCSSBorderXColor(Attr: TFresnelCSSAttribute; const AValue: string): boolean; virtual;
     function CheckOrSetCSSBorderStyle(const AValue: string; Check: boolean): boolean; virtual;
     function CheckCSSBorderXStyle(Attr: TFresnelCSSAttribute; const AValue: string): boolean; virtual;
+    function CheckOrSetCSSBorderRadius(const AValue: string; Check: boolean): boolean; virtual;
+    function CheckCSSBorderXRadius(Attr: TFresnelCSSAttribute; const AValue: string): boolean; virtual;
     function CheckCSSBoxSizing(const AValue: string): boolean; virtual;
     function CheckCSSFloat(const AValue: string): boolean; virtual;
     function CheckCSSLineHeight(const AValue: string): boolean; virtual;
@@ -1503,6 +1517,7 @@ begin
   fcaBorderWidth: CheckOrSetCSSBorderWidth(AValue,false);
   fcaBorderStyle: CheckOrSetCSSBorderStyle(AValue,false);
   fcaBorderColor: CheckOrSetCSSBorderColor(AValue,false);
+  fcaBorderRadius: CheckOrSetCSSBorderRadius(AValue,false);
   fcaFont: CheckOrSetCSSFont(AValue,false);
   fcaMargin: CheckOrSetCSSMargin(AValue,false);
   fcaMarginBlock: CheckOrSetCSSMarginBlock(AValue,false);
@@ -2041,6 +2056,93 @@ begin
   end;
 end;
 
+function TFresnelElement.CheckOrSetCSSBorderRadius(const AValue: string;
+  Check: boolean): boolean;
+// 1..4 lengths, e.g. 10px 20px 30px 40px
+// Plus optional separated by / 1..4 lengths for vertical radius
+// e.g. 10px / 20px 30px
+// border-radius: 10px; -> set for all 4 sides
+// border-radius: 10px 5%; -> top-left-and-bottom-right top-right-and-bottom-left
+// border-radius: 2px 4px 2px; -> top-left top-right-and-bottom-left bottom-right
+// border-radius: 1px 0 3px 4px; -> top-left top-right bottom-right bottom-left
+
+var
+  r: array[1..2,1..4] of String;
+  p, Side, i: Integer;
+  Attr: TFresnelCSSAttribute;
+
+  procedure Fill;
+  begin
+    if r[Side,2]='' then
+      r[Side,2]:=r[Side,1];
+    if r[Side,3]='' then
+      r[Side,3]:=r[Side,2];
+    if r[Side,4]='' then
+      r[Side,4]:=r[Side,1];
+  end;
+
+begin
+  Result:=false;
+  p:=1;
+  r[1,1]:=CSSReadNextValue(AValue,p);
+  if not CheckCSSLength(fcaBorderTopLeftRadius,r[1,1]) then
+    exit;
+  Side:=1;
+  i:=2;
+  while i<=4 do
+  begin
+    r[Side,i]:=CSSReadNextValue(AValue,p);
+    if r[Side,i]='' then
+    begin
+      Fill;
+      break;
+    end;
+    if (Side=1) and (r[Side,i]='/') then
+    begin
+      // separate vertical radii
+      Fill;
+      Side:=2;
+      r[Side,1]:=CSSReadNextValue(AValue,p);
+      if not CheckCSSLength(fcaBorderTopLeftRadius,r[Side,1]) then
+        exit;
+      i:=2;
+      continue;
+    end;
+    inc(i);
+  end;
+  if CSSReadNextValue(AValue,p)>'' then
+    exit(false);
+  if not Check then
+  begin
+    for i:=1 to 4 do
+    begin
+      Attr:=TFresnelCSSAttribute(ord(fcaBorderTopLeftRadius)+i-1);
+      if r[2,i]>'' then
+        SetCSSElAttribute(Attr,r[1,i]+' '+r[2,i])
+      else
+        SetCSSElAttribute(Attr,r[1,i]);
+    end;
+  end;
+end;
+
+function TFresnelElement.CheckCSSBorderXRadius(Attr: TFresnelCSSAttribute;
+  const AValue: string): boolean;
+// 10px
+// 10px 20px
+var
+  p: Integer;
+  aRadius: String;
+begin
+  p:=1;
+  aRadius:=CSSReadNextValue(AValue,p);
+  if not CheckCSSLength(Attr,aRadius,[]) then
+    exit(false);
+  aRadius:=CSSReadNextValue(AValue,p);
+  if (aRadius>'') and not CheckCSSLength(Attr,aRadius,[]) then
+    exit(false);
+  Result:=true;
+end;
+
 function TFresnelElement.CheckCSSBoxSizing(const AValue: string): boolean;
 begin
   case AValue of
@@ -2645,6 +2747,13 @@ end;
 
 function TFresnelElement.CheckCSSLength(Attr: TFresnelCSSAttribute;
   const AValue: string; const Checks: TFresnelLengthChecks): boolean;
+
+  procedure Invalid(const ID: int64);
+  begin
+    if fclNoWarn in Checks then exit;
+    CSSInvalidValueWarning(ID,Attr,AValue);
+  end;
+
 var
   p, StartP: PChar;
 begin
@@ -2652,8 +2761,10 @@ begin
   if AValue='auto' then
     Result:=true
   else if AValue='' then
-    CSSWarning(20221016220554,'missing '+FresnelCSSAttributeNames[Attr]+' value')
-  else begin
+  begin
+    if not (fclNoWarn in Checks) then
+      CSSWarning(20221016220554,'missing '+FresnelCSSAttributeNames[Attr]+' value')
+  end else begin
     // <float><unit>
     StartP:=PChar(AValue);
     p:=StartP;
@@ -2661,14 +2772,14 @@ begin
     begin
       if flcNoNegative in Checks then
       begin
-        CSSInvalidValueWarning(20221103222222,Attr,AValue);
+        Invalid(20221103222222);
         exit;
       end;
       inc(p);
     end;
     if not (p^ in ['0'..'9']) then
     begin
-      CSSInvalidValueWarning(20221016220901,Attr,AValue);
+      Invalid(20221016220901);
       exit;
     end;
     inc(p);
@@ -2678,13 +2789,13 @@ begin
       // float
       if flcInteger in Checks then
       begin
-        CSSInvalidValueWarning(20221103222126,Attr,AValue);
+        Invalid(20221103222126);
         exit;
       end;
       inc(p);
       if not (p^ in ['0'..'9']) then
       begin
-        CSSInvalidValueWarning(20221016221010,Attr,AValue);
+        Invalid(20221016221010);
         exit;
       end;
       inc(p);
@@ -2695,7 +2806,7 @@ begin
       // exponent
       if flcInteger in Checks then
       begin
-        CSSInvalidValueWarning(20221103222139,Attr,AValue);
+        Invalid(20221103222139);
         exit;
       end;
       inc(p);
@@ -2703,7 +2814,7 @@ begin
         inc(p);
       if not (p^ in ['0'..'9']) then
       begin
-        CSSInvalidValueWarning(20221016220901,Attr,AValue);
+        Invalid(20221016220901);
         exit;
       end;
       inc(p);
@@ -2715,7 +2826,7 @@ begin
       begin
         if flcNoPercentage in Checks then
         begin
-          CSSInvalidValueWarning(20221103222155,Attr,AValue);
+          Invalid(20221103222155);
           exit;
         end;
         inc(p);
@@ -2752,7 +2863,7 @@ begin
     end;
     // note: no unit is ok
     if p-StartP<>length(AValue) then
-      CSSInvalidValueWarning(20221016221747,Attr,AValue)
+      Invalid(20221016221747)
     else
       Result:=true;
   end;
@@ -3508,6 +3619,11 @@ begin
     fcaBorderRightStyle,
     fcaBorderTopStyle,
     fcaBorderBottomStyle: Result:=CheckCSSBorderXStyle(Attr,s);
+    fcaBorderRadius: Result:=CheckOrSetCSSBorderRadius(s,true);
+    fcaBorderTopLeftRadius,
+    fcaBorderTopRightRadius,
+    fcaBorderBottomRightRadius,
+    fcaBorderBottomLeftRadius: Result:=CheckCSSBorderXRadius(Attr,s);
     fcaBoxSizing: Result:=CheckCSSBoxSizing(s);
     fcaFloat: Result:=CheckCSSFloat(s);
     fcaFont: Result:=CheckCSSFontKerning(s);