Răsfoiți Sursa

dom: removed fcaDisplayOutside,Inside,Box

mattias 1 an în urmă
părinte
comite
ebd5f6fc2c

+ 14 - 14
demo/ButtonGenerator/DemoButtonGenerator.pas

@@ -103,7 +103,7 @@ begin
   with FontSizeSlider do begin
     MinPosition:=5;
     MaxPosition:=40;
-    Position:=12;
+    SliderPosition:=12;
   end;
 
   // padding vertical slider
@@ -111,7 +111,7 @@ begin
   with PaddingVerticalSlider do begin
     MinPosition:=0;
     MaxPosition:=50;
-    Position:=16;
+    SliderPosition:=16;
   end;
 
   // gradient
@@ -122,7 +122,7 @@ begin
   with BorderWidthSlider do begin
     MinPosition:=0;
     MaxPosition:=10;
-    Position:=1;
+    SliderPosition:=1;
   end;
 
   // border-radius corners: four checkboxes
@@ -153,7 +153,7 @@ begin
   with BorderRadiusSlider do begin
     MinPosition:=0;
     MaxPosition:=50;
-    Position:=16;
+    SliderPosition:=16;
   end;
 
   // text-shadow checkbox
@@ -164,7 +164,7 @@ begin
   with TextShadowVertPosSlider do begin
     MinPosition:=-30;
     MaxPosition:=30;
-    Position:=1;
+    SliderPosition:=1;
   end;
 
   // slider for text-shadow horizontal position
@@ -172,7 +172,7 @@ begin
   with TextShadowHorzPosSlider do begin
     MinPosition:=-30;
     MaxPosition:=30;
-    Position:=1;
+    SliderPosition:=1;
   end;
 
   // slider for text-shadow horizontal position
@@ -181,7 +181,7 @@ begin
     ValueFormat:='%.1fpx';
     MinPosition:=0;
     MaxPosition:=5;
-    Position:=0;
+    SliderPosition:=0;
   end;
 
   // the Button
@@ -206,14 +206,14 @@ var
 begin
   if ButtonDiv=nil then exit;
   NewStyle:=
-     'font-size:'+FloatToCSSPx(FontSizeSlider.Position)+';'
-    +'padding: '+FloatToCSSPx(PaddingVerticalSlider.Position)+' 31px;'
-    +'border-width:'+FloatToCSSPx(BorderWidthSlider.Position)+';';
+     'font-size:'+FloatToCSSPx(FontSizeSlider.SliderPosition)+';'
+    +'padding: '+FloatToCSSPx(PaddingVerticalSlider.SliderPosition)+' 31px;'
+    +'border-width:'+FloatToCSSPx(BorderWidthSlider.SliderPosition)+';';
 
   if GradientChkBox.Checked then
     NewStyle+='background-image:linear-gradient('+BackgroundColor1+','+BackgroundColor2+');';
 
-  Radius:=FloatToCSSPx(BorderRadiusSlider.Position);
+  Radius:=FloatToCSSPx(BorderRadiusSlider.SliderPosition);
   s:='';
   if BorderRadiusTopLeftChkBox.Checked then
     s:=Radius
@@ -236,9 +236,9 @@ begin
   s:='';
   if TextShadowChkBox.Checked then
   begin
-    s:=FloatToCSSStr(TextShadowHorzPosSlider.Position)
-      +' '+FloatToCSSStr(TextShadowVertPosSlider.Position)
-      +' '+FloatToCSSStr(TextShadowBlurRadiusSlider.Position)
+    s:=FloatToCSSStr(TextShadowHorzPosSlider.SliderPosition)
+      +' '+FloatToCSSStr(TextShadowVertPosSlider.SliderPosition)
+      +' '+FloatToCSSStr(TextShadowBlurRadiusSlider.SliderPosition)
       +' #2f6627';
   end;
   NewStyle+='text-shadow:'+s+';';

+ 17 - 17
demo/Slider/DemoSlider.pas

@@ -17,7 +17,7 @@ type
     FMaxPosition: TFresnelLength;
     FMinPosition: TFresnelLength;
     FOnChange: TNotifyEvent;
-    FPosition: TFresnelLength;
+    FSliderPosition: TFresnelLength;
     FValueFormat: string;
     function GetCaption: TFresnelCaption;
     procedure OnSliderDivMouse(Event: TAbstractEvent);
@@ -25,10 +25,10 @@ type
     procedure SetCaption(const AValue: TFresnelCaption);
     procedure SetMaxPosition(const AValue: TFresnelLength);
     procedure SetMinPosition(const AValue: TFresnelLength);
-    procedure SetPosition(AValue: TFresnelLength);
+    procedure SetSliderPosition(AValue: TFresnelLength);
     procedure SetValueFormat(const AValue: string);
     procedure UpdateValueLabel;
-    procedure UpdatePosition;
+    procedure UpdateSliderPosition;
   public
     const
       cStyle = ''
@@ -86,7 +86,7 @@ type
     constructor Create(AOwner: TComponent); override;
     property MinPosition: TFresnelLength read FMinPosition write SetMinPosition;
     property MaxPosition: TFresnelLength read FMaxPosition write SetMaxPosition;
-    property Position: TFresnelLength read FPosition write SetPosition;
+    property SliderPosition: TFresnelLength read FSliderPosition write SetSliderPosition;
     property Caption: TFresnelCaption read GetCaption write SetCaption;
     property ValueFormat: string read FValueFormat write SetValueFormat;
     property OnChange: TNotifyEvent read FOnChange write FOnChange;
@@ -113,7 +113,7 @@ begin
     begin
       w:=SliderDiv.RenderedBorderBox.Width;
       if w<1 then exit;
-      Position:=Evt.X/w * (MaxPosition-MinPosition) + MinPosition;
+      SliderPosition:=Evt.X/w * (MaxPosition-MinPosition) + MinPosition;
     end;
   end;
 end;
@@ -132,7 +132,7 @@ begin
       w:=SliderDiv.RenderedBorderBox.Width;
       if w<1 then exit;
       x:=Evt.X + SliderPoint.RenderedContentBox.Left;
-      Position:=x/w * (MaxPosition-MinPosition) + MinPosition;
+      SliderPosition:=x/w * (MaxPosition-MinPosition) + MinPosition;
     end;
   end;
 end;
@@ -147,8 +147,8 @@ begin
   if FMaxPosition=AValue then Exit;
   FMaxPosition:=AValue;
   FMinPosition:=Min(MinPosition,MaxPosition);
-  FPosition:=Min(MaxPosition,Max(MinPosition,Position));
-  UpdatePosition;
+  FSliderPosition:=Min(MaxPosition,Max(MinPosition,SliderPosition));
+  UpdateSliderPosition;
 end;
 
 procedure TDemoSlider.SetMinPosition(const AValue: TFresnelLength);
@@ -156,16 +156,16 @@ begin
   if FMinPosition=AValue then Exit;
   FMinPosition:=AValue;
   FMaxPosition:=Max(MinPosition,MaxPosition);
-  FPosition:=Min(MaxPosition,Max(MinPosition,Position));
-  UpdatePosition;
+  FSliderPosition:=Min(MaxPosition,Max(MinPosition,SliderPosition));
+  UpdateSliderPosition;
 end;
 
-procedure TDemoSlider.SetPosition(AValue: TFresnelLength);
+procedure TDemoSlider.SetSliderPosition(AValue: TFresnelLength);
 begin
   AValue:=Min(MaxPosition,Max(MinPosition,AValue));
-  if AValue=FPosition then exit;
-  FPosition:=AValue;
-  UpdatePosition;
+  if AValue=FSliderPosition then exit;
+  FSliderPosition:=AValue;
+  UpdateSliderPosition;
   if Assigned(OnChange) then OnChange(Self);
 end;
 
@@ -180,16 +180,16 @@ procedure TDemoSlider.UpdateValueLabel;
 var
   s: String;
 begin
-  s:=Format(ValueFormat,[Position]);
+  s:=Format(ValueFormat,[SliderPosition]);
   SliderValue.Caption:=s;
 end;
 
-procedure TDemoSlider.UpdatePosition;
+procedure TDemoSlider.UpdateSliderPosition;
 var
   p: TFresnelLength;
   s: String;
 begin
-  p:=(Position-MinPosition)/(MaxPosition-MinPosition);
+  p:=(SliderPosition-MinPosition)/(MaxPosition-MinPosition);
   s:=FloatToCSSStr(p*100)+'%';
   SliderRange.Style:='width: '+s;
   SliderPoint.Style:='left: '+s;

+ 130 - 100
src/base/fresnel.dom.pas

@@ -56,10 +56,7 @@ type
   //  for corners TopLeft,TopRight,BottomLeft,BottomRight use the order defined in TFresnelCSSCorner
   TFresnelCSSAttribute = (
     fcaFloat, // can modify display
-    fcaDisplayBox, // todo: make layout value
-    fcaDisplayInside, // todo: make layout value
-    fcaDisplayOutside, // todo: make layout value
-    fcaDisplay, // shorthand for display-outside, -inside, -listitem, -internal, -box, modified by float
+    fcaDisplay,
     fcaPosition,
     fcaBoxSizing, // border-box, content-box
     fcaDirection,
@@ -153,9 +150,6 @@ const
   FresnelCSSAttributeNames: array[TFresnelCSSAttribute] of string = (
     // case sensitive!
     'float',
-    'display-box',
-    'display-inside',
-    'display-outside',
     'display',
     'position',
     'box-sizing',
@@ -335,9 +329,6 @@ type
   TFresnelCSSRegistry = class(TCSSRegistry)
   protected
     // check attribute (longhands and shorthands)
-    function CheckDisplayBox(Resolver: TCSSBaseResolver): boolean; virtual;
-    function CheckDisplayInside(Resolver: TCSSBaseResolver): boolean; virtual;
-    function CheckDisplayOutside(Resolver: TCSSBaseResolver): boolean; virtual;
     function CheckDisplay(Resolver: TCSSBaseResolver): boolean; virtual;
     function CheckPosition(Resolver: TCSSBaseResolver): boolean; virtual;
     function CheckBoxSizing(Resolver: TCSSBaseResolver): boolean; virtual;
@@ -397,7 +388,6 @@ type
       TopLeft, TopRight, BottomLeft, BottomRight: TFresnelCSSAttribute; const Found: TCSSStringArray);
 
     // split shorthands
-    procedure SplitDisplay(Resolver: TCSSBaseResolver; var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray); virtual;
     procedure SplitOverflow(Resolver: TCSSBaseResolver; var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray); virtual;
     procedure SplitBorderWidth(Resolver: TCSSBaseResolver; var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray); virtual;
     procedure SplitBorderColor(Resolver: TCSSBaseResolver; var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray); virtual;
@@ -463,18 +453,22 @@ type
       kwExtraExpanded = kwExtraCondensed+1; // extra-expanded
       kwFitContent = kwExtraExpanded+1; // fit-content
       kwFixed = kwFitContent+1;
-      kwFlow = kwFixed+1;
+      kwFlex = kwFixed+1;
+      kwFlow = kwFlex+1;
       kwFlowRoot = kwFlow+1; // flow-root
       kwGrab = kwFlowRoot+1;
       kwGrabbing = kwGrab+1;
-      kwGroove = kwGrabbing+1;
+      kwGrid = kwGrabbing+1;
+      kwGroove = kwGrid+1;
       kwHelp = kwGroove+1;
       kwHidden = kwHelp+1;
       kwIcon = kwHidden+1;
       kwIn = kwIcon+1;
       kwInline = kwIn+1;
-      kwInlineEnd = kwInline+1; // inline-end
-      kwInlineStart = kwInlineEnd+1; // inline-start
+      kwInlineBlock = kwInline+1; // inline-block
+      kwInlineEnd = kwInlineBlock+1; // inline-end
+      kwInlineFlow = kwInlineEnd+1; // inline-flow
+      kwInlineStart = kwInlineFlow+1; // inline-start
       kwInset = kwInlineStart+1;
       kwLarge = kwInset+1;
       kwLarger = kwLarge+1;
@@ -766,11 +760,14 @@ type
     procedure SetFocusEventHandler(AIndex: Integer; AValue: TFresnelFocusEventHandler);
     procedure SetMouseEventHandler(AIndex: Integer; const AValue: TFresnelMouseEventHandler);
   protected
-    FCSSValues: TCSSAttributeValues;
-    FCSSClasses: TStrings;
-    FResolver: TCSSResolver;
     FChildren: TFPList; // list of TFresnelElement
+    FCSSClasses: TStrings;
+    FCSSValues: TCSSAttributeValues;
+    FDisplayInside: TCSSNumericalID;
+    FDisplayOutside: TCSSNumericalID;
     FParent: TFresnelElement;
+    FPosition: TCSSNumericalID;
+    FResolver: TCSSResolver;
     FStyle: string;
     FStyleElement: TCSSRuleElement;
     FViewPort: TFresnelViewport;
@@ -792,6 +789,8 @@ type
     // compute
     procedure UnsetValue(AttrID: TCSSNumericalID); virtual;
     function ConvertCSSValueToPixel(IsHorizontal: boolean; const Value: string): TFresnelLength; virtual;
+    procedure ComputeDisplay; virtual;
+    procedure ComputePosition; virtual;
   protected
     procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
     procedure SetParentComponent(Value: TComponent); override;
@@ -857,6 +856,8 @@ type
     function GetComputedBorderWidth(Attr: TFresnelCSSAttribute): TFresnelLength; virtual;
     function GetComputedBorderRadius(Corner: TFresnelCSSCorner): TFresnelPoint; virtual; // on fail returns 0
     function GetComputedColor(Attr: TFresnelCSSAttribute; const CurrentColor: TFPColor): TFPColor; virtual; // on fail returns transparent
+    function GetComputedKeyword(Attr: TFresnelCSSAttribute; const AllowedKeywords: TCSSNumericalIDArray): TCSSNumericalID; virtual;
+    function GetComputedCSSKeyword(AttrID: TCSSNumericalID; const AllowedKeywords: TCSSNumericalIDArray): TCSSNumericalID; virtual;
     function GetComputedTextShadow(out aOffsetX, aOffsetY, aRadius: TFresnelLength; out aColor: TFPColor): boolean; virtual; // on fail returns 0
     function GetComputedImage(Attr: TFresnelCSSAttribute): TFresnelCSSBackgroundInfo; virtual; // on fail returns nil
     function GetComputedLinearGradient(const LGParams: string): TFresnelCSSLinearGradient; virtual; // on fail returns nil
@@ -867,6 +868,9 @@ type
     property ComputedAttribute[Attr: TFresnelCSSAttribute]: string read GetComputedString write SetComputedCSSString;
     property ComputedBorderBox: TFresnelRect read FComputedBorderBox write FComputedBorderBox; // relative to layout parent
     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;
     // CSS pseudo classes
     property CSSPseudoClass[Pseudo: TFresnelCSSPseudoClass]: boolean read GetCSSPseudoClass write SetCSSPseudoClass;
     // layouter
@@ -1194,21 +1198,6 @@ end;
 
 { TFresnelCSSRegistry }
 
-function TFresnelCSSRegistry.CheckDisplayBox(Resolver: TCSSBaseResolver): boolean;
-begin
-  Result:=Resolver.CheckAttribute_Keyword(Chk_DisplayBox_KeywordIDs);
-end;
-
-function TFresnelCSSRegistry.CheckDisplayInside(Resolver: TCSSBaseResolver): boolean;
-begin
-  Result:=Resolver.CheckAttribute_Keyword(Chk_DisplayInside_KeywordIDs);
-end;
-
-function TFresnelCSSRegistry.CheckDisplayOutside(Resolver: TCSSBaseResolver): boolean;
-begin
-  Result:=Resolver.CheckAttribute_Keyword(Chk_DisplayOutside_KeywordIDs);
-end;
-
 function TFresnelCSSRegistry.CheckDisplay(Resolver: TCSSBaseResolver): boolean;
 begin
   Result:=Resolver.CheckAttribute_Keyword(Chk_Display_KeywordIDs);
@@ -2145,60 +2134,6 @@ begin
   Result:=(aSize>'') and (aFamily>'');
 end;
 
-procedure TFresnelCSSRegistry.SplitDisplay(Resolver: TCSSBaseResolver;
-  var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray);
-var
-  aInside, aOutside, aBox: TCSSNumericalID;
-  KW: TCSSNumericalID;
-begin
-  aBox:=0;
-  aInside:=0;
-  aOutside:=0;
-  repeat
-    if Resolver.CurComp.Kind<>rvkKeyword then
-      exit; // todo warn
-    KW:=Resolver.CurComp.KeywordID;
-    if Resolver.IsKeywordIn(KW,Chk_DisplayBox_KeywordIDs) then
-    begin
-      if aBox>0 then
-        exit;
-      aBox:=KW;
-    end;
-    if Resolver.IsKeywordIn(KW,Chk_DisplayInside_KeywordIDs) then
-    begin
-      if aInside>0 then
-        exit;
-      aInside:=KW;
-    end;
-    if Resolver.IsKeywordIn(KW,Chk_DisplayOutside_KeywordIDs) then
-    begin
-      if aOutside>0 then
-        exit;
-      aOutside:=KW;
-    end;
-  until not Resolver.ReadNext;
-
-  if (aOutside>0) and (aInside=0) then
-    // outside without inside -> flow
-    aInside:=kwFlow
-  else if (aInside>0) and (aOutside=0) then
-    // inside without outside -> block
-    aOutside:=kwBlock
-  else if (aOutside=kwInline) and (aInside=kwBlock) then
-    aInside:=kwFlowRoot;
-
-  // todo: values outside-inside
-
-  SetLength(AttrIDs,3);
-  SetLength(Values,3);
-  AttrIDs[0]:=FresnelAttrs[fcaDisplayBox].Index;
-  AttrIDs[1]:=FresnelAttrs[fcaDisplayInside].Index;
-  AttrIDs[2]:=FresnelAttrs[fcaDisplayOutside].Index;
-  Values[0]:=CSSRegistry.Keywords[aBox];
-  Values[1]:=CSSRegistry.Keywords[aInside];
-  Values[2]:=CSSRegistry.Keywords[aOutside];
-end;
-
 procedure TFresnelCSSRegistry.SplitOverflow(Resolver: TCSSBaseResolver;
   var AttrIDs: TCSSNumericalIDArray; var Values: TCSSStringArray);
 var
@@ -2640,7 +2575,7 @@ begin
   AddKW(kwAbsolute,'absolute'); // e.g. position
   AddKW(kwAlias,'alias'); // e.g. cursor
   AddKW(kwAllScroll,'all-scroll'); // e.g. cursor
-  AddKW(kwBlock,'block'); // e.g. display-outside
+  AddKW(kwBlock,'block'); // e.g. display
   AddKW(kwBlockEnd,'block-end'); // e.g. clear
   AddKW(kwBlockStart,'block-start'); // e.g. clear
   AddKW(kwBold,'bold'); // e.g. font-weight
@@ -2660,7 +2595,7 @@ begin
   AddKW(kwCondensed,'condensed'); // e.g. font-stretch
   AddKW(kwContain,'contain'); // e.g. background-size
   AddKW(kwContentBox,'content-box'); // e.g. box-sizing
-  AddKW(kwContents,'contents'); // e.g. display-box
+  AddKW(kwContents,'contents'); // e.g. display
   AddKW(kwContextMenu,'context-menu'); // e.g. cursor
   AddKW(kwCopy,'copy'); // e.g. cursor
   AddKW(kwCover,'cover'); // e.g. background-size
@@ -2677,17 +2612,21 @@ begin
   AddKW(kwExtraExpanded,'extra-expanded'); // e.g. font-stretch
   AddKW(kwFitContent,'fit-content'); // e.g. width, min-width
   AddKW(kwFixed,'fixed'); // e.g. position, background-attachment
-  AddKW(kwFlow,'flow'); // e.g. display-inside
-  AddKW(kwFlowRoot,'flow-root'); // e.g. display-inside
+  AddKW(kwFlex,'flex'); // e.g. display
+  AddKW(kwFlow,'flow'); // e.g. display
+  AddKW(kwFlowRoot,'flow-root'); // e.g. display
   AddKW(kwGrab,'grab'); // e.g. cursor
   AddKW(kwGrabbing,'grabbing'); // e.g. cursor
+  AddKW(kwGrid,'grid'); // e.g. display
   AddKW(kwGroove,'groove'); // e.g. border-style
   AddKW(kwHelp,'help'); // e.g. cursor
   AddKW(kwHidden,'hidden'); // e.g. overflow-x, border-style, visible
   AddKW(kwIcon,'icon'); // e.g. font
   AddKW(kwIn,'in'); // e.g. background-image
   AddKW(kwInline,'inline'); // e.g. display-outside
+  AddKW(kwInlineBlock,'inline-block'); // e.g. display
   AddKW(kwInlineEnd,'inline-end'); // e.g. clear, float
+  AddKW(kwInlineFlow,'inline-flow'); // e.g. display
   AddKW(kwInlineStart,'inline-start'); // e.g. clear, float
   AddKW(kwInset,'inset'); // e.g. border-style
   AddKW(kwLarge,'large'); // e.g. font-size
@@ -2775,16 +2714,11 @@ begin
   Chk_Color_KeywordIDs:=[kwCurrentcolor];
 
   // display
-  AddFresnelLonghand(fcaDisplayBox,false,@CheckDisplayBox,'contents');
   Chk_DisplayBox_KeywordIDs:=[kwContents,kwNone];
-
-  AddFresnelLonghand(fcaDisplayInside,false,@CheckDisplayInside);
   Chk_DisplayInside_KeywordIDs:=[kwFlow,kwFlowRoot];
-
-  AddFresnelLonghand(fcaDisplayOutside,false,@CheckDisplayOutside);
   Chk_DisplayOutside_KeywordIDs:=[kwBlock,kwInline];
 
-  AddFresnelShorthand(fcaDisplay,@CheckDisplay,@SplitDisplay,[fcaDisplayInside,fcaDisplayOutside]);
+  AddFresnelLonghand(fcaDisplay,false,@CheckDisplay,'inline');
   Chk_Display_KeywordIDs:=concat(Chk_DisplayBox_KeywordIDs,
     Chk_DisplayInside_KeywordIDs,
     Chk_DisplayOutside_KeywordIDs);
@@ -3556,9 +3490,7 @@ begin
     Attr:=TFresnelCSSAttrDesc(Desc).Attr;
     Complete:=true;
     case Attr of
-    fcaDisplayInside: Result:='flow-root';
-    fcaDisplayOutside: Result:='block';
-    fcaDisplayBox: Result:='contents';
+    fcaDisplay: Result:='block flow-root';
     fcaPosition: Result:='absolute';
     fcaBoxSizing: Result:='content-box';
     fcaZIndex: Result:='0';
@@ -4642,6 +4574,29 @@ begin
   end;
 end;
 
+function TFresnelElement.GetComputedKeyword(Attr: TFresnelCSSAttribute;
+  const AllowedKeywords: TCSSNumericalIDArray): TCSSNumericalID;
+begin
+  Result:=GetComputedCSSKeyword(CSSRegistry.FresnelAttrs[Attr].Index,AllowedKeywords);
+end;
+
+function TFresnelElement.GetComputedCSSKeyword(AttrID: TCSSNumericalID;
+  const AllowedKeywords: TCSSNumericalIDArray): TCSSNumericalID;
+var
+  aValue: String;
+  aComp: TCSSResCompValue;
+  Complete: boolean;
+begin
+  Result:=CSSIDNone;
+  aValue:=GetCSSString(AttrID,false,Complete);
+  aComp.EndP:=PChar(aValue);
+  repeat
+    if not Resolver.ReadComp(aComp) then break;
+    if (aComp.Kind=rvkKeyword) and Resolver.IsKeywordIn(aComp.KeywordID,AllowedKeywords) then
+      exit(aComp.KeywordID);
+  until false;
+end;
+
 function TFresnelElement.GetComputedTextShadow(out aOffsetX, aOffsetY,
   aRadius: TFresnelLength; out aColor: TFPColor): boolean;
 // color offset-x offset-y blur-radius
@@ -5205,6 +5160,78 @@ begin
   Result:=Result*GetPixPerUnit(aComp.FloatUnit,IsHorizontal);
 end;
 
+procedure TFresnelElement.ComputeDisplay;
+var
+  Complete: boolean;
+  aValue: String;
+  aComp: TCSSResCompValue;
+  KW: TCSSNumericalID;
+begin
+  FDisplayInside:=CSSIDNone;
+  FDisplayOutside:=CSSIDNone;
+  aValue:=GetCSSString(CSSRegistry.FresnelAttrs[fcaDisplay].Index,false,Complete);
+  aComp.EndP:=PChar(aValue);
+  repeat
+    if not Resolver.ReadComp(aComp) then break;
+    if aComp.Kind=rvkKeyword then
+    begin
+      KW:=aComp.KeywordID;
+      case KW of
+      CSSRegistry.kwNone:
+        begin
+          FDisplayInside:=CSSRegistry.kwNone;
+          FDisplayOutside:=CSSRegistry.kwNone;
+          break;
+        end;
+      CSSRegistry.kwContents:
+        begin
+          FDisplayInside:=CSSRegistry.kwContents;
+          FDisplayOutside:=CSSRegistry.kwContents;
+          break;
+        end;
+      CSSRegistry.kwBlock,
+      CSSRegistry.kwInline:
+        if FDisplayOutside=CSSIDNone then
+          FDisplayOutside:=KW;
+      CSSRegistry.kwFlow,
+      CSSRegistry.kwFlowRoot,
+      CSSRegistry.kwGrid,
+      CSSRegistry.kwFlex:
+        if FDisplayInside=CSSIDNone then
+          FDisplayInside:=KW;
+      CSSRegistry.kwInlineBlock:
+        begin
+          // inline-block -> inline flow-root
+          FDisplayOutside:=CSSRegistry.kwInline;
+          FDisplayInside:=CSSRegistry.kwFlowRoot;
+        end;
+      CSSRegistry.kwInlineFlow:
+        begin
+          FDisplayOutside:=CSSRegistry.kwInline;
+          FDisplayInside:=CSSRegistry.kwFlow;
+        end;
+      end;
+    end;
+  until false;
+  if (FDisplayOutside=CSSIDNone) and (FDisplayInside>CSSIDNone) then
+  begin
+    case FDisplayInside of
+    CSSRegistry.kwGrid,
+    CSSRegistry.kwFlex:
+      FDisplayOutside:=CSSRegistry.kwBlock;
+    else
+      FDisplayOutside:=CSSRegistry.kwInline;
+    end;
+  end;
+  if (FDisplayInside=CSSIDNone) and (FDisplayOutside>CSSIDNone) then
+    FDisplayInside:=CSSRegistry.kwFlow;
+end;
+
+procedure TFresnelElement.ComputePosition;
+begin
+  FPosition:=GetComputedKeyword(fcaPosition,CSSRegistry.Chk_Position_KeywordIDs);
+end;
+
 class function TFresnelElement.GetCSSTypeStyle: TCSSString;
 begin
   Result:='';
@@ -5444,6 +5471,9 @@ begin
       aValue.State:=cavsBaseKeywords;
     end;
   end;
+
+  ComputeDisplay;
+  ComputePosition;
 end;
 
 procedure TFresnelElement.ComputeCSSAfterLayoutNode(Layouter: TFresnelLayouter);

+ 49 - 70
src/base/fresnel.layouter.pas

@@ -18,7 +18,7 @@ unit Fresnel.Layouter;
 interface
 
 uses
-  Classes, SysUtils, Math, fpCSSResolver,
+  Classes, SysUtils, Math, fpCSSResolver, fpCSSResParser,
   Fresnel.Classes, Fresnel.DOM, Fresnel.Controls;
 
 type
@@ -604,7 +604,6 @@ var
   NodeIndex: Integer;
   ChildNode: TSimpleFresnelLayoutNode;
   ChildEl: TFresnelElement;
-  aPosition, aDisplayOutside: String;
   IsInline: Boolean;
   NewChildRight, MaxChildRight, CurSpace, OldMarginBoxBottom,
     ChildMarginLeft, ChildMarginRight, ChildMarginTop, ChildMarginBottom,
@@ -670,9 +669,8 @@ begin
     //writeln('TFLBlockFormattingContext.ComputeLayoutBorderBox ',ChildEl.GetPath);
 
     // skip position: absolute and fixed
-    aPosition:=ChildEl.ComputedAttribute[fcaPosition];
-    case aPosition of
-    '','static','relative','sticky': ;
+    case ChildEl.Position of
+    CSSRegistry.kwStatic,CSSRegistry.kwRelative,CSSRegistry.kwSticky: ;
     else
       if Commit then
         PlaceAbsoluteNode(ChildNode);
@@ -681,10 +679,9 @@ begin
     end;
 
     // display-outside inline or block
-    aDisplayOutside:=ChildEl.ComputedAttribute[fcaDisplayOutside];
-    case aDisplayOutside of
-    '',
-    'inline': IsInline:=true;
+    case ChildEl.DisplayOutside of
+    CSSRegistry.kwInline:
+      IsInline:=true;
     else
       // block -> end line, put element on a line of its own
       IsInline:=false;
@@ -1011,7 +1008,6 @@ end;
 
 procedure TViewportLayouter.Apply(aViewport: TFresnelViewport);
 var
-  aDisplayInside, aPosition, aDisplayOutside, aDisplayBox: String;
   VPNode: TSimpleFresnelLayoutNode;
 begin
   Viewport:=aViewport;
@@ -1025,18 +1021,12 @@ begin
   if Viewport.NodeCount=0 then
     exit; // nothing to do
 
-  aDisplayBox:=Viewport.ComputedAttribute[fcaDisplayBox];
-  if aDisplayBox<>'contents' then
-    ErrorLayout(20221031184139,'TFresnelLayouter.Apply expected viewport.displaybox=contents, but found "'+aDisplayBox+'"');
-  aDisplayOutside:=Viewport.ComputedAttribute[fcaDisplayOutside];
-  if aDisplayOutside<>'block' then
-    ErrorLayout(20221031182815,'TFresnelLayouter.Apply expected viewport.displayoutside=block, but found "'+aDisplayOutside+'"');
-  aDisplayInside:=Viewport.ComputedAttribute[fcaDisplayInside];
-  if aDisplayInside<>'flow-root' then
-    ErrorLayout(20221018142350,'TFresnelLayouter.Apply expected viewport.displayinside=flow-root, but found "'+aDisplayInside+'"');
-  aPosition:=Viewport.ComputedAttribute[fcaPosition];
-  if aPosition<>'absolute' then
-    ErrorLayout(20221031153911,'TFresnelLayouter.Apply expected viewport.position=absolute, but found "'+aPosition+'"');
+  if Viewport.DisplayOutside<>CSSRegistry.kwBlock then
+    ErrorLayout(20221031182815,'TFresnelLayouter.Apply expected viewport.displayoutside=block, but found "'+CSSRegistry.Keywords[Viewport.DisplayOutside]+'"');
+  if Viewport.DisplayInside<>CSSRegistry.kwFlowRoot then
+    ErrorLayout(20221018142350,'TFresnelLayouter.Apply expected viewport.displayinside=flow-root, but found "'+CSSRegistry.Keywords[Viewport.DisplayInside]+'"');
+  if Viewport.Position<>CSSRegistry.kwAbsolute then
+    ErrorLayout(20221031153911,'TFresnelLayouter.Apply expected viewport.position=absolute, but found "'+CSSRegistry.Keywords[Viewport.Position]+'"');
 
   Layout(VPNode);
 end;
@@ -1047,36 +1037,33 @@ function TViewportLayouter.NeedBlockFormattingContext(El: TFresnelElement
 // contain internal and external floats
 // surpress margin collapsing
 var
-  aPosition, aOverflow, aFloat, aDisplayBox, aDisplayInside,
-    aDisplayOutside: String;
+  aOverflow, aFloat: String;
 begin
   if El=nil then
     exit(false);
   if El.Parent=nil then
     exit(true);
 
-  aPosition:=El.ComputedAttribute[fcaPosition];
-  case aPosition of
-  'absolute',
-  'fixed': exit(true);
+  case El.Position of
+  CSSRegistry.kwAbsolute,
+  CSSRegistry.kwFixed:
+    exit(true);
   end;
 
-  aDisplayBox:=El.ComputedAttribute[fcaDisplayBox];
-  if aDisplayBox='none' then
+  if El.DisplayOutside in [CSSIDNone,CSSRegistry.kwNone] then
     exit(false);
 
-  aDisplayOutside:=El.ComputedAttribute[fcaDisplayOutside];
-  case aDisplayOutside of
-  'block': exit(true);
+  case El.DisplayOutside of
+  CSSRegistry.kwBlock: exit(true);
   end;
 
-  aDisplayInside:=El.ComputedAttribute[fcaDisplayInside];
-  case aDisplayInside of
-  'flow-root',
-  'table',
-  'flex',
-  'grid',
-  'ruby': exit(true);
+  case El.DisplayInside of
+  //CSSRegistry.kwtable,
+  CSSRegistry.kwFlex,
+  CSSRegistry.kwGrid,
+  //CSSRegistry.kwRuby,
+  CSSRegistry.kwFlowRoot:
+    exit(true);
   end;
 
   aOverflow:=El.ComputedAttribute[fcaOverflow];
@@ -1092,37 +1079,27 @@ begin
     exit(true);
   end;
 
-  // contain: layout, content, paint
-  // flex items
-  // grid items
-  // multicol containers
-  // column-span
-
   Result:=false;
 end;
 
 function TViewportLayouter.GetBlockContainer(El: TFresnelElement
   ): TFresnelElement;
-var
-  aValue, aPosition: String;
 begin
-  aPosition:=El.ComputedAttribute[fcaPosition];
-  case aPosition of
-  'absolute':
+  case El.Position of
+  CSSRegistry.kwAbsolute:
     begin
       // the containing block is nearest ancestor element that has a position value other than static
       Result:=El.Parent;
       while (Result<>nil) do
       begin
-        aValue:=Result.ComputedAttribute[fcaPosition];
-        if (aValue<>'static') and (aValue<>'') then
+        if not (Result.Position in [CSSRegistry.kwSticky,CSSIDNone]) then
           exit;
         // Note:check for transform<>'none'
         Result:=Result.Parent;
       end;
       Result:=Viewport;
     end;
-  'fixed':
+  CSSRegistry.kwFixed:
     begin
       // viewport
       Result:=Viewport;
@@ -1147,19 +1124,20 @@ end;
 procedure TViewportLayouter.UpdateLayouter(El: TFresnelElement;
   LNode: TSimpleFresnelLayoutNode);
 var
-  aDisplayInside: String;
   LayouterClass: TFLNodeLayouterClass;
 begin
   LayouterClass:=nil;
   if (not LNode.SkipLayout) and (El.NodeCount>0) then
   begin
-    aDisplayInside:=El.ComputedAttribute[fcaDisplayInside];
-    if aDisplayInside='grid' then
-      LayouterClass:=TFLGridLayouter
-    else if aDisplayInside='flex' then
-      LayouterClass:=TFLFlexLayouter
-    else if NeedBlockFormattingContext(El) then
-      LayouterClass:=TFLBlockFormattingContext;
+    case El.DisplayInside of
+    CSSRegistry.kwGrid:
+      LayouterClass:=TFLGridLayouter;
+    CSSRegistry.kwFlex:
+      LayouterClass:=TFLFlexLayouter;
+    else
+      if NeedBlockFormattingContext(El) then
+        LayouterClass:=TFLBlockFormattingContext;
+    end;
   end;
   if (LayouterClass<>nil) then
   begin
@@ -1179,7 +1157,7 @@ end;
 procedure TViewportLayouter.UpdateLayoutParent(El: TFresnelElement;
   LNode: TSimpleFresnelLayoutNode);
 var
-  ZIndexStr, aPosition: String;
+  ZIndexStr: String;
   ZIndexInt, {%H-}Code: Integer;
   NewParent: TFresnelElement;
   ParentLNode: TSimpleFresnelLayoutNode;
@@ -1188,9 +1166,11 @@ begin
   if LNode.SkipLayout or (El.Parent=nil) then
     LNode.Parent:=nil
   else begin
-    aPosition:=El.ComputedAttribute[fcaPosition];
-    case aPosition of
-    'absolute','fixed','relative','sticky':
+    case El.Position of
+    CSSRegistry.kwAbsolute,
+    CSSRegistry.kwFixed,
+    CSSRegistry.kwRelative,
+    CSSRegistry.kwSticky:
       begin
         ZIndexStr:=El.ComputedAttribute[fcaZIndex];
         if (ZIndexStr='') or (ZIndexStr='auto') then
@@ -1223,7 +1203,7 @@ end;
 procedure TViewportLayouter.ComputeCSSLayoutNode(El: TFresnelElement);
 var
   LNode, ParentLNode: TSimpleFresnelLayoutNode;
-  aDisplayBox, aVisibility: String;
+  aVisibility: String;
   {%H-}Code: integer;
 begin
   //FLLog(etDebug,['TSimpleFresnelLayouter.ComputeCSS ',El.GetPath]);
@@ -1243,8 +1223,7 @@ begin
     ParentLNode:=nil;
 
   // display-box
-  aDisplayBox:=El.ComputedAttribute[fcaDisplayBox];
-  if aDisplayBox='none' then
+  if El.DisplayOutside in [CSSIDNone,CSSRegistry.kwNone] then
   begin
     LNode.SkipLayout:=true;
     LNode.SkipRendering:=true;
@@ -1325,7 +1304,7 @@ procedure TViewportLayouter.WriteLayoutTree;
     El: TFresnelElement;
   begin
     El:=Node.Element;
-    FLLog(etError,[El.Name,' NodeCount=',IntToStr(Node.NodeCount),' display-outside=',El.ComputedAttribute[fcaDisplayOutside],' display-inside=',El.ComputedAttribute[fcaDisplayInside],' position=',El.ComputedAttribute[fcaPosition],' z-index=',El.ComputedAttribute[fcaZIndex]]);
+    FLLog(etError,[El.Name,' NodeCount=',IntToStr(Node.NodeCount),' display-outside=',CSSRegistry.Keywords[El.DisplayOutside],' display-inside=',CSSRegistry.Keywords[El.DisplayInside],' position=',CSSRegistry.Keywords[El.Position],' z-index=',El.ComputedAttribute[fcaZIndex]]);
     if Node.Layouter<>nil then
       FLLog(etDebug,[' layouter=',Node.Layouter.ClassName]);
     FLLog(etDebug,'');