Browse Source

dom: started parsing flex attributes

mattias 11 months ago
parent
commit
ba6aaf4742
1 changed files with 265 additions and 9 deletions
  1. 265 9
      src/base/fresnel.dom.pas

+ 265 - 9
src/base/fresnel.dom.pas

@@ -21,7 +21,7 @@ unit Fresnel.DOM;
 
 {$mode ObjFPC}{$H+}
 {$IF FPC_FULLVERSION>30300}
-{$WARN 6060 off} // Case statement does not handle all possible cases
+  {$WARN 6060 off} // Case statement does not handle all possible cases
 {$ENDIF}
 {$Interfaces CORBA} // no reference counting
 {$ModeSwitch AdvancedRecords}
@@ -142,7 +142,14 @@ type
     fcaBackgroundSize,
     fcaBackground, // shorthand for background-[attachment,clip,color,image,origin,position,repeat,size]
     fcaColor,     // text color
-    fcaCursor
+    fcaCursor,
+    fcaFlexBasis,
+    fcaFlexDirection,
+    fcaFlexGrow,
+    fcaFlexShrink,
+    fcaFlexWrap,
+    fcaFlexFlow,
+    fcaFlex
     );
   TFresnelCSSAttributes = set of TFresnelCSSAttribute;
   TFresnelCSSAttributeArray = array of TFresnelCSSAttribute;
@@ -237,7 +244,14 @@ const
     'background-size',
     'background',
     'color',
-    'cursor'
+    'cursor',
+    'flex-basis',
+    'flex-direction',
+    'flex-grow',
+    'flex-shrink',
+    'flex-wrap',
+    'flex-flow',
+    'flex'
     );
 
 type
@@ -386,6 +400,13 @@ type
     function CheckBackgroundSize(Resolver: TCSSBaseResolver): boolean; virtual;
     function CheckBackground(Resolver: TCSSBaseResolver): boolean; virtual;
     function CheckCursor(Resolver: TCSSBaseResolver): boolean; virtual;
+    function CheckFlexBasis(Resolver: TCSSBaseResolver): boolean; virtual;
+    function CheckFlexDirection(Resolver: TCSSBaseResolver): boolean; virtual;
+    function CheckFlexGrow(Resolver: TCSSBaseResolver): boolean; virtual;
+    function CheckFlexShrink(Resolver: TCSSBaseResolver): boolean; virtual;
+    function CheckFlexWrap(Resolver: TCSSBaseResolver): boolean; virtual;
+    function CheckFlexFlow(Resolver: TCSSBaseResolver): boolean; virtual;
+    function CheckFlex(Resolver: TCSSBaseResolver): boolean; virtual;
 
     // utility check/parse functions
     function CheckLinearGradient(Resolver: TCSSBaseResolver; Check: boolean): boolean; virtual;
@@ -398,6 +419,8 @@ type
       out aAttachment, aClip, aColor, aImage, aOrigin, aPositionX, aPositionY, aRepeat, aSize: TCSSString): boolean; virtual;
     function ReadFont(Resolver: TCSSBaseResolver; Check: boolean;
       out aSystemFont: TCSSNumericalID; out aFamily, aStyle, aVariant, aWeight, aWidth, aSize, aLineHeight: TCSSString): boolean; virtual;
+    function ReadFlex(Resolver: TCSSBaseResolver; Check: boolean; out Grow, Shrink, Basis: TCSSString): boolean; virtual;
+    function ReadFlexFlow(Resolver: TCSSBaseResolver; Check: boolean; out Direction, Wrap: TCSSString): boolean; virtual;
     function IsColor(const ResValue: TCSSResCompValue): boolean; virtual;
     procedure SplitLonghandSides(var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray;
       Top, Right, Bottom, Left: TFresnelCSSAttribute; const Found: TCSSStringArray);
@@ -412,6 +435,8 @@ type
     procedure SplitBorderRadius(Resolver: TCSSBaseResolver; var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray); virtual;
     procedure SplitBorderStyle(Resolver: TCSSBaseResolver; var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray); virtual;
     procedure SplitBorderWidth(Resolver: TCSSBaseResolver; var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray); virtual;
+    procedure SplitFlex(Resolver: TCSSBaseResolver; var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray); virtual;
+    procedure SplitFlexFlow(Resolver: TCSSBaseResolver; var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray); virtual;
     procedure SplitFont(Resolver: TCSSBaseResolver; var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray); virtual; // todo systemfont
     procedure SplitFontStretch(Resolver: TCSSBaseResolver; var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray); virtual; // todo systemfont
     procedure SplitMargin(Resolver: TCSSBaseResolver; var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray); virtual;
@@ -434,6 +459,8 @@ type
     function GetBorderRadius(El: TFresnelElement): string; virtual;
     function GetBorderWidth(El: TFresnelElement): string; virtual;
     function GetSideLengths(El: TFresnelElement; LeftAttr: TFresnelCSSAttribute): string; virtual;
+    function GetFlex(El: TFresnelElement): string; virtual;
+    function GetFlexFlow(El: TFresnelElement): string; virtual;
     function GetFont(El: TFresnelElement): string; virtual;
     function GetFontFamily(El: TFresnelElement): string; virtual;
     function GetFontKerning(El: TFresnelElement): string; virtual;
@@ -480,10 +507,13 @@ type
       kwClip = kwCenter+1;
       kwCollapse = kwClip+1;
       kwColResize = kwCollapse+1; // col-resize
-      kwCommonLigatures = kwColResize+1; // common-ligatures
+      kwColumn = kwColResize+1;
+      kwColumnReverse = kwColumn+1; // column-reversed
+      kwCommonLigatures = kwColumnReverse+1; // common-ligatures
       kwCondensed = kwCommonLigatures+1;
       kwContain = kwCondensed+1;
-      kwContentBox = kwContain+1; // content-box
+      kwContent = kwContain+1;
+      kwContentBox = kwContent+1; // content-box
       kwContents = kwContentBox+1;
       kwContextMenu = kwContents+1;
       kwCopy = kwContextMenu+1;
@@ -537,7 +567,8 @@ type
       kwNoRepeat = kwNoDrop+1; // no-repeat
       kwNormal = kwNoRepeat+1;
       kwNotAllowed = kwNormal+1; // not-allowed
-      kwNResize = kwNotAllowed+1; // n-resize
+      kwNoWrap = kwNotAllowed+1; // nowrap
+      kwNResize = kwNoWrap+1; // n-resize
       kwNSResize = kwNResize+1; // ns-resize
       kwNWResize = kwNSResize+1; // nw-resize
       kwNWSEResize = kwNWResize+1; // nwse-resize
@@ -553,8 +584,10 @@ type
       kwRidge = kwRepeatY+1;
       kwRight = kwRidge+1;
       kwRound = kwRight+1;
-      kwRowResize = kwRound+1; // row-resize
-      kwRTL = kwRowResize+1;
+      kwRow = kwRound+1;
+      kwRowResize = kwRow+1; // row-resize
+      kwRowReverse = kwRowResize+1; // row-reversed
+      kwRTL = kwRowReverse+1;
       kwScroll = kwRTL+1;
       kwSemiCondensed = kwScroll+1; // semi-condensed
       kwSemiExpanded = kwSemiCondensed+1; // semi-expanded
@@ -580,7 +613,9 @@ type
       kwVerticalText = kwUltraExpanded+1; // vertical-text
       kwVisible = kwVerticalText+1;
       kwWait = kwVisible+1;
-      kwWResize = kwWait+1; // w-resize
+      kwWrap = kwWait+1; // w-resize
+      kwWrapReverse = kwWrap+1; // wrap-reverse
+      kwWResize = kwWrapReverse+1; // w-resize
       kwXLarge = kwWResize+1; // x-large
       kwXSmall = kwXLarge+1; // x-small
       kwXXLarge = kwXSmall+1; // xx-large
@@ -689,6 +724,11 @@ type
     Chk_BackgroundRepeat_KeywordIDs: TCSSNumericalIDArray;
     Chk_BackgroundSize_Dim: TCSSCheckAttrParams_Dimension;
     Chk_Cursor_KeywordIDs: TCSSNumericalIDArray;
+    Chk_FlexBasis_Dim: TCSSCheckAttrParams_Dimension;
+    Chk_FlexDirection_KeywordIDs: TCSSNumericalIDArray;
+    Chk_FlexGrow_Dim: TCSSCheckAttrParams_Dimension;
+    Chk_FlexShrink_Dim: TCSSCheckAttrParams_Dimension;
+    Chk_FlexWrap_KeywordIDs: TCSSNumericalIDArray;
 
     constructor Create;
     procedure Init; override;
@@ -1904,6 +1944,45 @@ begin
   Result:=Resolver.CheckAttribute_Keyword(Chk_Cursor_KeywordIDs);
 end;
 
+function TFresnelCSSRegistry.CheckFlexBasis(Resolver: TCSSBaseResolver): boolean;
+begin
+  Result:=Resolver.CheckAttribute_Dimension(Chk_FlexBasis_Dim);
+end;
+
+function TFresnelCSSRegistry.CheckFlexDirection(Resolver: TCSSBaseResolver): boolean;
+begin
+  Result:=Resolver.CheckAttribute_Keyword(Chk_FlexDirection_KeywordIDs);
+end;
+
+function TFresnelCSSRegistry.CheckFlexGrow(Resolver: TCSSBaseResolver): boolean;
+begin
+  Result:=Resolver.CheckAttribute_Dimension(Chk_FlexGrow_Dim);
+end;
+
+function TFresnelCSSRegistry.CheckFlexShrink(Resolver: TCSSBaseResolver): boolean;
+begin
+  Result:=Resolver.CheckAttribute_Dimension(Chk_FlexShrink_Dim);
+end;
+
+function TFresnelCSSRegistry.CheckFlexWrap(Resolver: TCSSBaseResolver): boolean;
+begin
+  Result:=Resolver.CheckAttribute_Keyword(Chk_FlexWrap_KeywordIDs);
+end;
+
+function TFresnelCSSRegistry.CheckFlexFlow(Resolver: TCSSBaseResolver): boolean;
+var
+  Direction, Wrap: TCSSString;
+begin
+  Result:=ReadFlexFlow(Resolver,true,Direction,Wrap);
+end;
+
+function TFresnelCSSRegistry.CheckFlex(Resolver: TCSSBaseResolver): boolean;
+var
+  Grow, Shrink, Basis: TCSSString;
+begin
+  Result:=ReadFlex(Resolver,true,Grow,Shrink,Basis);
+end;
+
 function TFresnelCSSRegistry.ReadBackgroundRepeat(Resolver: TCSSBaseResolver; Check: boolean; out
   X, Y: TCSSNumericalID): boolean;
 // For example:
@@ -2232,6 +2311,106 @@ begin
   Result:=(aSize>'') and (aFamily>'');
 end;
 
+function TFresnelCSSRegistry.ReadFlex(Resolver: TCSSBaseResolver; Check: boolean; out Grow, Shrink,
+  Basis: TCSSString): boolean;
+var
+  KW: TCSSNumericalID;
+begin
+  Result:=false;
+  Grow:='';
+  Shrink:='';
+  Basis:='';
+  repeat
+    case Resolver.CurComp.Kind of
+    rvkKeyword:
+      begin
+        KW:=Resolver.CurComp.KeywordID;
+        if Resolver.IsKeywordIn(Chk_FlexBasis_Dim.AllowedKeywordIDs) then
+        begin
+          if Basis>'' then
+            exit; // invalid
+        end else if KW=kwNone then
+        begin
+          if (Grow>'') or (Shrink>'') or (Basis>'') then
+            exit; // invalid
+          Grow:='0';
+          Shrink:='0';
+          Basis:='auto';
+        end;
+      end;
+    rvkFloat:
+      if Resolver.CurComp.FloatUnit=cuNone then
+      begin
+        if Grow='' then
+          Grow:=Resolver.GetCompString
+        else if Shrink='' then
+          Shrink:=Resolver.GetCompString
+        else if Basis='' then
+          Basis:=Resolver.GetCompString
+        else
+          exit; // invalid
+      end else if Resolver.CurComp.FloatUnit in cuAllLengthsAndPercent then begin
+        if Basis>'' then
+          exit; // invalid
+        Basis:=Resolver.GetCompString;
+      end;
+    rvkFunction:
+      if Resolver.CurComp.FunctionID=afVar then
+        exit(Check)
+      else begin
+        // todo
+        exit;
+      end;
+    end;
+  until not Resolver.ReadNext;
+
+  if Grow='' then Grow:='1';
+  if Shrink='' then Shrink:='0';
+  if Basis='' then Basis:='auto';
+  Result:=true;
+end;
+
+function TFresnelCSSRegistry.ReadFlexFlow(Resolver: TCSSBaseResolver; Check: boolean; out
+  Direction, Wrap: TCSSString): boolean;
+var
+  KW: TCSSNumericalID;
+begin
+  Result:=false;
+  Direction:='';
+  Wrap:='';
+  repeat
+    case Resolver.CurComp.Kind of
+    rvkKeyword:
+      begin
+        KW:=Resolver.CurComp.KeywordID;
+        if Resolver.IsKeywordIn(Chk_FlexDirection_KeywordIDs) then
+        begin
+          if Direction>'' then
+            exit;
+          Direction:=Keywords[Kw];
+        end else if Resolver.IsKeywordIn(Chk_FlexWrap_KeywordIDs) then
+        begin
+          if Wrap>'' then
+            exit;
+          Wrap:=Keywords[Kw];
+        end else
+          exit; // invalid
+      end;
+    rvkFunction:
+      if Resolver.CurComp.FunctionID=afVar then
+        exit(Check)
+      else
+        exit;
+    else
+      exit; // invalid
+    end;
+  until not Resolver.ReadNext;
+
+  if Direction='' then Direction:='row';
+  if Wrap='' then Wrap:='nowrap';
+  Result:=true;
+end;
+
 procedure TFresnelCSSRegistry.SplitOverflow(Resolver: TCSSBaseResolver;
   var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray);
 var
@@ -2290,6 +2469,37 @@ begin
     fcaBorderTopWidth,fcaBorderRightWidth,fcaBorderBottomWidth,fcaBorderLeftWidth,Found);
 end;
 
+procedure TFresnelCSSRegistry.SplitFlex(Resolver: TCSSBaseResolver;
+  var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray);
+var
+  Grow, Shrink, Basis: String;
+begin
+  if not ReadFlex(Resolver,false,Grow,Shrink,Basis) then exit;
+
+  SetLength(AttrIDs,3);
+  AttrIDs[0]:=FresnelAttrs[fcaFlexGrow].Index;
+  AttrIDs[1]:=FresnelAttrs[fcaFlexShrink].Index;
+  AttrIDs[2]:=FresnelAttrs[fcaFlexBasis].Index;
+  SetLength(Values,3);
+  Values[0]:=Grow;
+  Values[1]:=Shrink;
+  Values[2]:=Basis;
+end;
+
+procedure TFresnelCSSRegistry.SplitFlexFlow(Resolver: TCSSBaseResolver;
+  var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray);
+var
+  Direction, Wrap: String;
+begin
+  if not ReadFlexFlow(Resolver,false,Direction,Wrap) then exit;
+  SetLength(AttrIDs,2);
+  AttrIDs[0]:=FresnelAttrs[fcaFlexDirection].Index;
+  AttrIDs[1]:=FresnelAttrs[fcaFlexWrap].Index;
+  SetLength(Values,2);
+  Values[0]:=Direction;
+  Values[1]:=Wrap;
+end;
+
 procedure TFresnelCSSRegistry.SplitBorderColor(Resolver: TCSSBaseResolver;
   var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray);
 var
@@ -2731,6 +2941,25 @@ begin
      +' '+FloatToCSSPx(Sides[ffsLeft]);
 end;
 
+function TFresnelCSSRegistry.GetFlex(El: TFresnelElement): string;
+var
+  Grow, Shrink, Basis: String;
+begin
+  Basis:=El.GetComputedString(fcaFlexShrink);
+  Grow:=El.GetComputedString(fcaFlexGrow);
+  Shrink:=El.GetComputedString(fcaFlexShrink);
+  Result:=Basis+' '+Grow+' '+Shrink;
+end;
+
+function TFresnelCSSRegistry.GetFlexFlow(El: TFresnelElement): string;
+var
+  Direction, Wrap: String;
+begin
+  Direction:=El.GetComputedString(fcaFlexDirection);
+  Wrap:=El.GetComputedString(fcaFlexWrap);
+  Result:=Direction+' '+Wrap;
+end;
+
 function TFresnelCSSRegistry.GetFont(El: TFresnelElement): string;
 
   procedure Add(const aValue, aDefault: string);
@@ -3019,9 +3248,12 @@ begin
   AddKW(kwClip,'clip'); // e.g. overflow-x
   AddKW(kwCollapse,'collapse'); // e.g. visible
   AddKW(kwColResize,'col-resize'); // e.g. cursor
+  AddKW(kwColumn,'column'); // e.g. flex-direction
+  AddKW(kwColumnReverse,'column-reverse'); // e.g. flex-direction
   AddKW(kwCommonLigatures,'common-ligatures'); // e.g. font-variant
   AddKW(kwCondensed,'condensed'); // e.g. font-width
   AddKW(kwContain,'contain'); // e.g. background-size
+  AddKW(kwContent,'content'); // e.g. flex-basis
   AddKW(kwContentBox,'content-box'); // e.g. box-sizing
   AddKW(kwContents,'contents'); // e.g. display
   AddKW(kwContextMenu,'context-menu'); // e.g. cursor
@@ -3076,6 +3308,7 @@ begin
   AddKW(kwNoRepeat,'no-repeat'); // e.g. background-repeat
   AddKW(kwNormal,'normal'); // e.g. font-feature-settings, font-size
   AddKW(kwNotAllowed,'not-allowed'); // e.g. cursor
+  AddKW(kwNoWrap,'nowrap'); // e.g. flex-wrap
   AddKW(kwNResize,'n-resize'); // e.g. cursor
   AddKW(kwNSResize,'ns-resize'); // e.g. cursor
   AddKW(kwNWResize,'nw-resize'); // e.g. cursor
@@ -3092,7 +3325,9 @@ begin
   AddKW(kwRidge,'ridge'); // e.g. border-style
   AddKW(kwRight,'right'); // e.g. clear, float
   AddKW(kwRound,'round'); // e.g. background-repeat
+  AddKW(kwRow,'row'); // e.g. flex-direction
   AddKW(kwRowResize,'row-resize'); // e.g. cursor
+  AddKW(kwRowReverse,'row-reverse'); // e.g. flex-direction
   AddKW(kwRTL,'rtl'); // e.g. direction
   AddKW(kwScroll,'scroll'); // e.g. overflow-x, background-attachment
   AddKW(kwSemiCondensed,'semi-condensed'); // e.g. font-width
@@ -3119,6 +3354,8 @@ begin
   AddKW(kwVerticalText,'vertical-text'); // e.g. cursor
   AddKW(kwVisible,'visible'); // e.g. overflow-x, visible
   AddKW(kwWait,'wait'); // e.g. cursor
+  AddKW(kwWrap,'wrap'); // e.g. flex-wrap
+  AddKW(kwWrapReverse,'wrap-reverse'); // e.g. flex-wrap
   AddKW(kwWResize,'w-resize'); // e.g. cursor
   AddKW(kwXLarge,'x-large'); // e.g. font-size
   AddKW(kwXSmall,'x-small'); // e.g. font-size
@@ -3429,6 +3666,25 @@ begin
     kwSEResize,kwSWResize,kwWResize,kwEWResize,kwNSResize,kwNESWResize,kwNWSEResize,
     kwColResize,kwRowResize,kwAllScroll,kwZoomIn,kwZoomOut];
 
+  AddFresnelLonghand(fcaFlexBasis,false,@CheckFlexBasis,'auto');
+  Chk_FlexBasis_Dim.AllowedKeywordIDs:=[kwAuto,kwMaxContent,kwMinContent,kwFitContent,kwContent];
+  Chk_FlexBasis_Dim.AllowedUnits:=cuAllLengthsAndPercent;
+  Chk_FlexBasis_Dim.AllowFrac:=true;
+  AddFresnelLonghand(fcaFlexDirection,false,@CheckFlexDirection,'row');
+  Chk_FlexDirection_KeywordIDs:=[kwColumn,kwColumnReverse,kwRow,kwRowResize];
+  AddFresnelLonghand(fcaFlexGrow,false,@CheckFlexGrow,'0');
+  Chk_FlexGrow_Dim.AllowedUnits:=[cuNone];
+  Chk_FlexGrow_Dim.AllowFrac:=true;
+  AddFresnelLonghand(fcaFlexShrink,false,@CheckFlexShrink,'1');
+  Chk_FlexShrink_Dim.AllowedUnits:=[cuNone];
+  Chk_FlexShrink_Dim.AllowFrac:=true;
+  AddFresnelLonghand(fcaFlexWrap,false,@CheckFlexWrap,'nowrap');
+  Chk_FlexWrap_KeywordIDs:=[kwNoWrap,kwWrap,kwWrapReverse];
+  AddFresnelShorthand(fcaFlexFlow,@CheckFlexFlow,@SplitFlexFlow,@GetFlexFlow,
+    [fcaFlexDirection,fcaFlexWrap]);
+  AddFresnelShorthand(fcaFlex,@CheckFlex,@SplitFlex,@GetFlex,
+    [fcaFlexGrow,fcaFlexShrink,fcaFlexBasis]);
+
   // pseudo classes - - - - - - - - - - - - - - - - - - - - - -
   for PseudoCl in TFresnelCSSPseudoClass do
     AddFresnelPseudoClass(PseudoCl);