|
@@ -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);
|