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