Browse Source

layrouter: started flex

mattias 11 months ago
parent
commit
fb5f8dad21
2 changed files with 668 additions and 357 deletions
  1. 141 64
      src/base/fresnel.dom.pas
  2. 527 293
      src/base/fresnel.layouter.pas

+ 141 - 64
src/base/fresnel.dom.pas

@@ -962,7 +962,11 @@ type
     FAfterRender: TNotifyEvent;
     FBeforeRender: TNotifyEvent;
     FComputedBorderBox: TFresnelRect;
+    FComputedBoxSizing: TCSSNumericalID;
     FComputedContentBox: TFresnelRect;
+    FComputedDirection: TCSSNumericalID;
+    FComputedVisibility: TCSSNumericalID;
+    FComputedWritingMode: TCSSNumericalID;
     FDOMIndex: integer;
     FFont: IFresnelFont;
     FLayoutNode: TFresnelLayoutNode;
@@ -987,10 +991,10 @@ type
     FChildren: TFPList; // list of TFresnelElement
     FCSSClasses: TStrings;
     FCSSValues: TCSSAttributeValues;
-    FDisplayInside: TCSSNumericalID;
-    FDisplayOutside: TCSSNumericalID;
+    FComputedDisplayInside: TCSSNumericalID;
+    FComputedDisplayOutside: TCSSNumericalID;
     FParent: TFresnelElement;
-    FPosition: TCSSNumericalID;
+    FComputedPosition: TCSSNumericalID;
     FResolver: TCSSResolver;
     FStyle: string;
     FStyleElement: TCSSRuleElement;
@@ -1012,9 +1016,13 @@ type
     procedure FPOObservedChanged(ASender: TObject; Operation: TFPObservedOperation; Data: Pointer); virtual;
     // compute
     procedure UnsetValue(AttrID: TCSSNumericalID); virtual;
-    function ConvertCSSValueToPixel(IsHorizontal: boolean; const Value: string): TFresnelLength; virtual;
+    function ConvertCSSValueToPixel(IsHorizontal: boolean; const Value: string; UseNaNOnFail: boolean): TFresnelLength; virtual;
+    procedure ComputeBoxSizing; virtual;
+    procedure ComputeDirection; virtual;
     procedure ComputeDisplay; virtual;
     procedure ComputePosition; virtual;
+    procedure ComputeVisibility; virtual;
+    procedure ComputeWritingMode; virtual;
     function ComputeAttribute(aDesc: TCSSAttributeDesc; var aValue: String): TCSSAttributeValue.TState; virtual;
     function GetShorthandSpaceSeparated(AttrDesc: TCSSAttributeDesc): string;
   protected
@@ -1074,7 +1082,8 @@ type
     procedure ComputeCSSValues; virtual; // call resolver to collect CSS values and resolve shorthands
     procedure ComputeCSSAfterLayoutNode(Layouter: TFresnelLayouter); virtual; // after layouter node, before layouter traverse children
     function GetCSSString(AttrID: TCSSNumericalID; Compute: boolean; out Complete: boolean): string; virtual;
-    function GetComputedLength(Attr: TFresnelCSSAttribute; UseNaNOnFail: boolean = false): TFresnelLength; virtual; // on fail returns NaN
+    function GetComputedLength(Attr: TFresnelCSSAttribute; UseNaNOnFail: boolean = false): TFresnelLength; virtual; overload;
+    function GetComputedLength(const aComp: TCSSResCompValue; Attr: TFresnelCSSAttribute; UseNaNOnFail: boolean = false): TFresnelLength; virtual; overload;
     function GetComputedString(Attr: TFresnelCSSAttribute): string; virtual;
     function GetComputedCSSString(AttrID: TCSSNumericalID): string; virtual; overload;
     function GetComputedCSSString(const AttrName: string): string; overload;
@@ -1094,10 +1103,14 @@ type
     procedure WriteComputedAttributes(Title: string);
     property ComputedAttribute[Attr: TFresnelCSSAttribute]: string read GetComputedString write SetComputedCSSString;
     property ComputedBorderBox: TFresnelRect read FComputedBorderBox write FComputedBorderBox; // relative to layout parent
+    property ComputedBoxSizing: TCSSNumericalID read FComputedBoxSizing;
     property ComputedContentBox: TFresnelRect read FComputedContentBox write FComputedContentBox; // relative to layout parent
-    property DisplayInside: TCSSNumericalID read FDisplayInside;
-    property DisplayOutside: TCSSNumericalID read FDisplayOutside;
-    property Position: TCSSNumericalID read FPosition;
+    property ComputedDirection: TCSSNumericalID read FComputedDirection;
+    property ComputedDisplayInside: TCSSNumericalID read FComputedDisplayInside;
+    property ComputedDisplayOutside: TCSSNumericalID read FComputedDisplayOutside;
+    property ComputedPosition: TCSSNumericalID read FComputedPosition;
+    property ComputedVisibility: TCSSNumericalID read FComputedVisibility;
+    property ComputedWritingMode: TCSSNumericalID read FComputedWritingMode;
     // CSS pseudo classes
     property CSSPseudoClass[Pseudo: TFresnelCSSPseudoClass]: boolean read GetCSSPseudoClass write SetCSSPseudoClass;
     // layouter
@@ -6218,6 +6231,29 @@ end;
 
 function TFresnelElement.GetComputedLength(Attr: TFresnelCSSAttribute; UseNaNOnFail: boolean
   ): TFresnelLength;
+var
+  s: String;
+  aComp: TCSSResCompValue;
+  AttrID: TCSSNumericalID;
+  Complete: boolean;
+begin
+  if UseNaNOnFail then
+    Result:=NaN
+  else
+    Result:=0;
+
+  AttrID:=CSSRegistry.FresnelAttrs[Attr].Index;
+  s:=GetCSSString(AttrID,true,Complete);
+  if s='' then exit;
+
+  aComp.EndP:=PChar(s);
+  if (not Resolver.ReadComp(aComp)) or (aComp.Kind<>rvkFloat) then
+    exit;
+  Result:=GetComputedLength(aComp,Attr);
+end;
+
+function TFresnelElement.GetComputedLength(const aComp: TCSSResCompValue;
+  Attr: TFresnelCSSAttribute; UseNaNOnFail: boolean): TFresnelLength;
 
   function GetIsHorizontal: boolean;
   begin
@@ -6238,26 +6274,18 @@ function TFresnelElement.GetComputedLength(Attr: TFresnelCSSAttribute; UseNaNOnF
       fcaPaddingTop, // padding-top, -bottom percentage uses the container width
       fcaPaddingBottom,
       fcaBackgroundPositionX,
-      fcaBackgroundSize];
+      fcaBackgroundSize,
+      fcaColumnGap];
   end;
 
 var
-  s: String;
-  aComp: TCSSResCompValue;
-  AttrID: TCSSNumericalID;
-  IsHorizontal, Complete: boolean;
+  IsHorizontal: Boolean;
 begin
   if UseNaNOnFail then
     Result:=NaN
   else
     Result:=0;
-
-  AttrID:=CSSRegistry.FresnelAttrs[Attr].Index;
-  s:=GetCSSString(AttrID,true,Complete);
-  if s='' then exit;
-
-  aComp.EndP:=PChar(s);
-  if (not Resolver.ReadComp(aComp)) or (aComp.Kind<>rvkFloat) or IsNan(aComp.Float) then
+  if (aComp.Kind<>rvkFloat) or IsNan(aComp.Float) then
     exit;
   case aComp.FloatUnit of
   cuNone:
@@ -6272,21 +6300,26 @@ begin
     exit(aComp.Float);
   cuPercent:
     begin
-      // todo: depends on attribute
-      IsHorizontal:=GetIsHorizontal;
-      if IsHorizontal then
-      begin
-        if Attr in [fcaLeft,fcaRight,fcaWidth,fcaMinWidth,fcaMaxWidth] then
-          Result:=GetBlockContainerWH(true,UseNaNOnFail)
-        else
-          Result:=GetComputedLength(fcaWidth,UseNaNOnFail);
-      end else begin
-        if Attr in [fcaTop,fcaBottom,fcaHeight,fcaMinHeight,fcaMaxHeight] then
-          Result:=GetBlockContainerWH(false,UseNaNOnFail)
+      case Attr of
+      fcaLeft,fcaRight,fcaWidth,fcaMinWidth,fcaMaxWidth:
+        Result:=GetBlockContainerWH(true,UseNaNOnFail);
+      fcaTop,fcaBottom,fcaHeight,fcaMinHeight,fcaMaxHeight:
+        Result:=GetBlockContainerWH(false,UseNaNOnFail);
+      else
+        IsHorizontal:=GetIsHorizontal;
+        if IsHorizontal then
+          Result:=GetComputedLength(fcaWidth,UseNaNOnFail)
         else
           Result:=GetComputedLength(fcaHeight,UseNaNOnFail);
       end;
-      if IsNan(Result) then exit;
+      if IsNan(Result) then
+      begin
+        if UseNaNOnFail then
+          Result:=NaN
+        else
+          Result:=0;
+        exit;
+      end;
       Result:=aComp.Float*Result/100;
       exit;
     end;
@@ -6359,7 +6392,8 @@ begin
   'medium': exit(1);
   'thick': exit(2);
   end;
-  Result:=ConvertCSSValueToPixel(Attr in [fcaBorderLeftWidth,fcaBorderRightWidth],s);
+  // Note: border-top and border-bottom percentage use container's width
+  Result:=ConvertCSSValueToPixel(true,s,false);
 end;
 
 procedure TFresnelElement.WriteComputedAttributes(Title: string);
@@ -6646,6 +6680,7 @@ var
   aValue: String;
   aComp: TCSSResCompValue;
   Complete: boolean;
+  AttrDesc: TCSSAttributeDesc;
 begin
   Result:=CSSIDNone;
   aValue:=GetCSSString(AttrID,false,Complete);
@@ -6655,6 +6690,16 @@ begin
     if (aComp.Kind=rvkKeyword) and Resolver.IsKeywordIn(aComp.KeywordID,AllowedKeywords) then
       exit(aComp.KeywordID);
   until false;
+  // use initial value
+  AttrDesc:=CSSRegistry.Attributes[AttrID];
+  aValue:=AttrDesc.InitialValue;
+  aComp.EndP:=PChar(aValue);
+  if Resolver.ReadComp(aComp)
+      and (aComp.Kind=rvkKeyword)
+      and Resolver.IsKeywordIn(aComp.KeywordID,AllowedKeywords) then
+    exit(aComp.KeywordID);
+  // use default
+  Result:=AllowedKeywords[0];
 end;
 
 function TFresnelElement.GetComputedTextShadow(out aOffsetX, aOffsetY,
@@ -7260,34 +7305,46 @@ begin
   FCSSValues.Values[i].State:=cavsInvalid;
 end;
 
-function TFresnelElement.ConvertCSSValueToPixel(IsHorizontal: boolean; const Value: string
-  ): TFresnelLength;
+function TFresnelElement.ConvertCSSValueToPixel(IsHorizontal: boolean; const Value: string;
+  UseNaNOnFail: boolean): TFresnelLength;
 var
   aComp: TCSSResCompValue;
 begin
-  Result:=NaN;
+  if UseNaNOnFail then
+    Result:=NaN
+  else
+    Result:=0;
 
   if Value='' then
     exit;
   aComp.EndP:=PChar(Value);
   if (not Resolver.ReadComp(aComp)) or (aComp.Kind<>rvkFloat) or IsNan(aComp.Float) then
     exit;
-  Result:=aComp.Float;
   case aComp.FloatUnit of
   cuNone:
-    if Result=0 then
+    if aComp.Float=0 then
     begin
-      exit;
+      exit(aComp.Float);
     end else begin
       // number without unit is not allowed for pixel length
-      exit(NaN);
+      exit;
     end;
   cu_px:
-    exit;
+    exit(aComp.Float);
   end;
   if not (aComp.FloatUnit in cuAllLengths) then
-    exit(NaN);
-  Result:=Result*GetPixPerUnit(aComp.FloatUnit,IsHorizontal);
+    exit;
+  Result:=aComp.Float*GetPixPerUnit(aComp.FloatUnit,IsHorizontal);
+end;
+
+procedure TFresnelElement.ComputeBoxSizing;
+begin
+  FComputedBoxSizing:=GetComputedKeyword(fcaBoxSizing,CSSRegistry.Chk_BoxSizing_KeywordIDs);
+end;
+
+procedure TFresnelElement.ComputeDirection;
+begin
+  FComputedDirection:=GetComputedKeyword(fcaDirection,CSSRegistry.Chk_Direction_KeywordIDs);
 end;
 
 procedure TFresnelElement.ComputeDisplay;
@@ -7297,8 +7354,11 @@ var
   aComp: TCSSResCompValue;
   KW: TCSSNumericalID;
 begin
-  FDisplayInside:=CSSIDNone;
-  FDisplayOutside:=CSSIDNone;
+  FComputedDisplayInside:=CSSIDNone;
+  FComputedDisplayOutside:=CSSIDNone;
+  if FComputedVisibility=CSSRegistry.kwCollapse then
+    exit;
+
   aValue:=GetCSSString(CSSRegistry.FresnelAttrs[fcaDisplay].Index,false,Complete);
   aComp.EndP:=PChar(aValue);
   repeat
@@ -7309,57 +7369,70 @@ begin
       case KW of
       CSSRegistry.kwNone:
         begin
-          FDisplayInside:=CSSRegistry.kwNone;
-          FDisplayOutside:=CSSRegistry.kwNone;
+          FComputedDisplayInside:=CSSIDNone;
+          FComputedDisplayOutside:=CSSIDNone;
+          FComputedVisibility:=CSSRegistry.kwCollapse;
           break;
         end;
       CSSRegistry.kwContents:
         begin
-          FDisplayInside:=CSSRegistry.kwContents;
-          FDisplayOutside:=CSSRegistry.kwContents;
+          FComputedDisplayInside:=CSSRegistry.kwContents;
+          FComputedDisplayOutside:=CSSRegistry.kwContents;
           break;
         end;
       CSSRegistry.kwBlock,
       CSSRegistry.kwInline:
-        if FDisplayOutside=CSSIDNone then
-          FDisplayOutside:=KW;
+        if FComputedDisplayOutside=CSSIDNone then
+          FComputedDisplayOutside:=KW;
       CSSRegistry.kwFlow,
       CSSRegistry.kwFlowRoot,
       CSSRegistry.kwGrid,
       CSSRegistry.kwFlex:
-        if FDisplayInside=CSSIDNone then
-          FDisplayInside:=KW;
+        if FComputedDisplayInside=CSSIDNone then
+          FComputedDisplayInside:=KW;
       CSSRegistry.kwInlineBlock:
         begin
           // inline-block -> inline flow-root
-          FDisplayOutside:=CSSRegistry.kwInline;
-          FDisplayInside:=CSSRegistry.kwFlowRoot;
+          FComputedDisplayOutside:=CSSRegistry.kwInline;
+          FComputedDisplayInside:=CSSRegistry.kwFlowRoot;
+          break;
         end;
       CSSRegistry.kwInlineFlow:
         begin
-          FDisplayOutside:=CSSRegistry.kwInline;
-          FDisplayInside:=CSSRegistry.kwFlow;
+          FComputedDisplayOutside:=CSSRegistry.kwInline;
+          FComputedDisplayInside:=CSSRegistry.kwFlow;
+          break;
         end;
       end;
     end;
   until false;
-  if (FDisplayOutside=CSSIDNone) and (FDisplayInside>CSSIDNone) then
+  if (FComputedDisplayOutside=CSSIDNone) and (FComputedDisplayInside>CSSIDNone) then
   begin
-    case FDisplayInside of
+    case FComputedDisplayInside of
     CSSRegistry.kwGrid,
     CSSRegistry.kwFlex:
-      FDisplayOutside:=CSSRegistry.kwBlock;
+      FComputedDisplayOutside:=CSSRegistry.kwBlock;
     else
-      FDisplayOutside:=CSSRegistry.kwInline;
+      FComputedDisplayOutside:=CSSRegistry.kwInline;
     end;
   end;
-  if (FDisplayInside=CSSIDNone) and (FDisplayOutside>CSSIDNone) then
-    FDisplayInside:=CSSRegistry.kwFlow;
+  if (FComputedDisplayInside=CSSIDNone) and (FComputedDisplayOutside>CSSIDNone) then
+    FComputedDisplayInside:=CSSRegistry.kwFlow;
 end;
 
 procedure TFresnelElement.ComputePosition;
 begin
-  FPosition:=GetComputedKeyword(fcaPosition,CSSRegistry.Chk_Position_KeywordIDs);
+  FComputedPosition:=GetComputedKeyword(fcaPosition,CSSRegistry.Chk_Position_KeywordIDs);
+end;
+
+procedure TFresnelElement.ComputeVisibility;
+begin
+  FComputedVisibility:=GetComputedKeyword(fcaVisibility,CSSRegistry.Chk_Visible_KeywordIDs);
+end;
+
+procedure TFresnelElement.ComputeWritingMode;
+begin
+  FComputedWritingMode:=GetComputedKeyword(fcaWritingMode,CSSRegistry.Chk_WritingMode_KeywordIDs);
 end;
 
 function TFresnelElement.ComputeAttribute(aDesc: TCSSAttributeDesc; var aValue: String
@@ -7651,8 +7724,12 @@ begin
     end;
   end;
 
+  ComputeVisibility;
   ComputeDisplay;
   ComputePosition;
+  ComputeBoxSizing;
+  ComputeDirection;
+  ComputeWritingMode;
 end;
 
 procedure TFresnelElement.ComputeCSSAfterLayoutNode(Layouter: TFresnelLayouter);

File diff suppressed because it is too large
+ 527 - 293
src/base/fresnel.layouter.pas


Some files were not shown because too many files changed in this diff