浏览代码

rendere: UpdateRenderedAttributes

mattias 2 年之前
父节点
当前提交
9d6cbf3369
共有 4 个文件被更改,包括 148 次插入28 次删除
  1. 9 0
      src/fresnelcontrols.pas
  2. 93 2
      src/fresneldom.pas
  3. 3 1
      src/fresnellayouter.pas
  4. 43 25
      src/fresnelrenderer.pas

+ 9 - 0
src/fresnelcontrols.pas

@@ -61,6 +61,7 @@ type
     class constructor InitFresnelLabelClass;
   private
     FCaption: String;
+    FRenderedCaption: String;
   protected
     FLabelStates: TFresnelLabelStates;
     FMinCaption: String; // Caption with linebreak after each word
@@ -75,9 +76,11 @@ type
     function GetCSSInitialAttribute(const AttrID: TCSSNumericalID): TCSSString;
       override;
     procedure ClearCSSValues; override;
+    procedure UpdateRenderedAttributes; override;
     class function CSSTypeID: TCSSNumericalID; override;
     class function CSSTypeName: TCSSString; override;
     property Caption: String read FCaption write SetCaption;
+    property RenderedCaption: String read FRenderedCaption write FRenderedCaption;
   end;
 
   { TFresnelBody }
@@ -368,6 +371,12 @@ begin
   FCSSAttributes[fcaDisplayOutside]:='inline';
 end;
 
+procedure TFresnelLabel.UpdateRenderedAttributes;
+begin
+  inherited UpdateRenderedAttributes;
+  FRenderedCaption:=Caption;
+end;
+
 class function TFresnelLabel.CSSTypeID: TCSSNumericalID;
 begin
   Result:=FFresnelLabelTypeID;

+ 93 - 2
src/fresneldom.pas

@@ -35,7 +35,10 @@ type
     Left, Top, Right, Bottom: TFresnelLength;
   end;
 
-  EFresnelFont = class(Exception)
+  EFresnel = class(Exception)
+  end;
+
+  EFresnelFont = class(EFresnel)
   end;
 
 const
@@ -209,6 +212,10 @@ const
     );
 
 type
+  IFresnelFormDesigner = interface
+    ['{095CB7DD-E291-45B6-892E-F486A38E597C}']
+  end;
+
   TFresnelViewport = class;
   TFresnelElement = class;
 
@@ -284,6 +291,9 @@ type
     function GetCSSElAttribute(Attr: TFresnelCSSAttribute): string;
     function GetCSSElComputedAttribute(Attr: TFresnelCSSAttribute): string;
     procedure SetCSSElComputedAttribute(Attr: TFresnelCSSAttribute; AValue: string);
+    function GetCSSRenderedAttribute(Attr: TFresnelCSSAttribute): string;
+    procedure SetCSSRenderedAttribute(Attr: TFresnelCSSAttribute; const AValue: string
+      );
   private
     FDOMIndex: integer;
     FFont: IFresnelFont;
@@ -302,6 +312,7 @@ type
     FCSSAttributes: array[TFresnelCSSAttribute] of string;
     FCSSClasses: TStrings;
     FCSSComputed: array[TFresnelCSSAttribute] of string;
+    FCSSRendered: array[TFresnelCSSAttribute] of string;
     FChildren: TFPList; // list of TFresnelElement
     FParent: TFresnelElement;
     FStyle: string;
@@ -432,6 +443,14 @@ type
     function GetPreferredBorderBox_MaxWidth(MaxWidth: TFresnelLength): TFresnelPoint; virtual; // this element, excluding children
     property DOMIndex: integer read FDOMIndex write FDOMIndex;
     property LayoutNode: TFresnelLayoutNode read FLayoutNode write FLayoutNode;
+    // renderer
+    procedure UpdateRenderedAttributes; virtual;
+    function GetRenderedCSSLength(Attr: TFresnelCSSAttribute; UseInherited: boolean; UseNaNOnFail: boolean = false): TFresnelLength; virtual; // on fail returns NaN
+    function GetRenderedCSString(Attr: TFresnelCSSAttribute; UseInherited: boolean): string; virtual;
+    //function GetRenderedContentBox: TFresnelRect; virtual;
+    //function GetRenderedBorderBox: TFresnelRect; virtual;
+    //function GetRenderedFixedLeftTop: TFresnelPoint; virtual;
+    property CSSRenderedAttribute[Attr: TFresnelCSSAttribute]: string read GetCSSRenderedAttribute write SetCSSRenderedAttribute;
     // font
     property Font: IFresnelFont read GetFont write FFont;
   published
@@ -901,6 +920,18 @@ begin
   FCSSComputed[Attr]:=AValue;
 end;
 
+function TFresnelElement.GetCSSRenderedAttribute(Attr: TFresnelCSSAttribute
+  ): string;
+begin
+  Result:=FCSSRendered[Attr];
+end;
+
+procedure TFresnelElement.SetCSSRenderedAttribute(Attr: TFresnelCSSAttribute;
+  const AValue: string);
+begin
+  FCSSRendered[Attr]:=AValue;
+end;
+
 procedure TFresnelElement.SetCSSClasses(const AValue: TStrings);
 begin
   if FCSSClasses=AValue then Exit;
@@ -1888,6 +1919,8 @@ begin
   if AComponent=Self then exit;
   if Operation=opRemove then
   begin
+    if FParent=AComponent then
+      FParent:=nil;
     if FChildren<>nil then
       FChildren.Remove(AComponent);
   end;
@@ -2222,6 +2255,62 @@ begin
   Result.Y:=Result.Y+ExtraHeight;
 end;
 
+procedure TFresnelElement.UpdateRenderedAttributes;
+var
+  Attr: TFresnelCSSAttribute;
+begin
+  for Attr in TFresnelCSSAttribute do
+    FCSSRendered[Attr]:=FCSSComputed[Attr];
+end;
+
+function TFresnelElement.GetRenderedCSSLength(Attr: TFresnelCSSAttribute;
+  UseInherited: boolean; UseNaNOnFail: boolean): TFresnelLength;
+var
+  El: TFresnelElement;
+  s: String;
+begin
+  if CSSStrToFloat(FCSSRendered[Attr],Result) then
+    exit;
+  if UseInherited then
+  begin
+    El:=Parent;
+    while El<>nil do
+    begin
+      if CSSStrToFloat(El.FCSSRendered[Attr],Result) then
+        exit;
+      El:=El.Parent;
+    end;
+  end;
+  s:=GetCSSInitialAttribute(ElementAttrToAttrId(Attr));
+  if CSSStrToFloat(s,Result) then
+    exit;
+  if UseNaNOnFail then
+    Result:=NaN
+  else
+    Result:=0;
+end;
+
+function TFresnelElement.GetRenderedCSString(Attr: TFresnelCSSAttribute;
+  UseInherited: boolean): string;
+var
+  El: TFresnelElement;
+begin
+  Result:=FCSSRendered[Attr];
+  if Result<>'' then exit;
+  if UseInherited then
+  begin
+    El:=Parent;
+    while El<>nil do
+    begin
+      Result:=El.CSSRenderedAttribute[Attr];
+      if Result<>'' then
+        exit;
+      El:=El.Parent;
+    end;
+  end;
+  Result:=GetCSSInitialAttribute(ElementAttrToAttrId(Attr));
+end;
+
 function TFresnelElement.ElementAttrToAttrId(Attr: TFresnelCSSAttribute
   ): TCSSNumericalID;
 begin
@@ -2266,7 +2355,9 @@ end;
 procedure TFresnelElement.SetParentComponent(Value: TComponent);
 begin
   if Value is TFresnelElement then
-    Parent:=TFresnelElement(Value);
+    Parent:=TFresnelElement(Value)
+  else
+    raise EFresnel.Create('TFresnelElement.SetParentComponent Self='+DbgSName(Self)+' NewParentComponent='+DbgSName(Value));
 end;
 
 procedure TFresnelElement.GetChildren(Proc: TGetChildProc; Root: TComponent);

+ 3 - 1
src/fresnellayouter.pas

@@ -316,6 +316,7 @@ begin
     ChildEl.CSSComputedAttribute[fcaTop]:=FloatToCSSStr(ChildTop);
     ChildEl.CSSComputedAttribute[fcaBottom]:=FloatToCSSStr(ChildBottom);
     ChildEl.CSSComputedAttribute[fcaHeight]:=FloatToCSSStr(BFCNode.Height);
+
     debugln(['TFLBlockFormattingContext.PlaceLineNodes ',ChildEl.GetPath,
       ' Left=',ChildEl.CSSComputedAttribute[fcaLeft],
       ' Top=',ChildEl.CSSComputedAttribute[fcaTop],
@@ -603,6 +604,7 @@ begin
   Result:=default(TFresnelPoint);
   FContentSize:=default(TFresnelPoint);
   FContentSizeMaxWidth:=MaxWidth;
+  // ToDo: fragments
   // ToDo: css float and clear
   // ToDo: css line-height
   // ToDo: fcaMarginBlockEnd, fcaMarginBlockStart, fcaMarginInlineEnd, fcaMarginInlineEnd
@@ -611,7 +613,7 @@ begin
   FLastLineBorderBoxBottom:=FBorderTop+FPaddingTop;
   FLastLineMarginBottom:=0;
 
-  // AddLineNodeCache elements to the line, till full
+  // add elements to the line until full
   StartLine;
   NodeIndex:=0;
   while NodeIndex<Node.NodeCount do

+ 43 - 25
src/fresnelrenderer.pas

@@ -21,6 +21,7 @@ type
     procedure TextOut(const aLeft, aTop: TFresnelLength; const aFont: IFresnelFont; const aColor: TFPColor; const aText: string); virtual; abstract;
     procedure MathRoundRect(var r: TFresnelRect);
     procedure DrawElement(El: TFresnelElement; const dx, dy: TFresnelLength); virtual;
+    procedure UpdateRenderedAttributes(El: TFresnelElement); virtual;
   public
     procedure Draw(Viewport: TFresnelViewport); virtual;
     property SubPixel: boolean read FSubPixel write FSubPixel;
@@ -55,29 +56,32 @@ begin
   LNode:=TSimpleFresnelLayoutNode(El.LayoutNode);
   if LNode.SkipRendering then exit;
 
-  if not (El is TFresnelViewport) then
+  if (El is TFresnelViewport) then
   begin
-    aLeft:=El.GetComputedCSSLength(fcaLeft,false)+dx;
-    aTop:=El.GetComputedCSSLength(fcaTop,false)+dy;
-    //aWidth:=El.GetComputedCSSLength(fcaWidth,false);
-    //aHeight:=El.GetComputedCSSLength(fcaHeight,false);
-    aRight:=El.GetComputedCSSLength(fcaRight,false);
-    aBottom:=El.GetComputedCSSLength(fcaBottom,false);
-
-    aMarginLeft:=El.GetComputedCSSLength(fcaMarginLeft,false);
-    aMarginRight:=El.GetComputedCSSLength(fcaMarginRight,false);
-    aMarginTop:=El.GetComputedCSSLength(fcaMarginTop,false);
-    aMarginBottom:=El.GetComputedCSSLength(fcaMarginBottom,false);
-
-    aBorderLeft:=El.GetComputedCSSLength(fcaBorderLeftWidth,false);
-    aBorderRight:=El.GetComputedCSSLength(fcaBorderRightWidth,false);
-    aBorderTop:=El.GetComputedCSSLength(fcaBorderTopWidth,false);
-    aBorderBottom:=El.GetComputedCSSLength(fcaBorderBottomWidth,false);
-
-    aPaddingLeft:=El.GetComputedCSSLength(fcaPaddingLeft,false);
-    aPaddingRight:=El.GetComputedCSSLength(fcaPaddingRight,false);
-    aPaddingTop:=El.GetComputedCSSLength(fcaPaddingTop,false);
-    aPaddingBottom:=El.GetComputedCSSLength(fcaPaddingBottom,false);
+    aLeft:=0;
+    aTop:=0;
+  end else begin
+    aLeft:=El.GetRenderedCSSLength(fcaLeft,false)+dx;
+    aTop:=El.GetRenderedCSSLength(fcaTop,false)+dy;
+    //aWidth:=El.GetRenderedCSSLength(fcaWidth,false);
+    //aHeight:=El.GetRenderedCSSLength(fcaHeight,false);
+    aRight:=El.GetRenderedCSSLength(fcaRight,false);
+    aBottom:=El.GetRenderedCSSLength(fcaBottom,false);
+
+    aMarginLeft:=El.GetRenderedCSSLength(fcaMarginLeft,false);
+    aMarginRight:=El.GetRenderedCSSLength(fcaMarginRight,false);
+    aMarginTop:=El.GetRenderedCSSLength(fcaMarginTop,false);
+    aMarginBottom:=El.GetRenderedCSSLength(fcaMarginBottom,false);
+
+    aBorderLeft:=El.GetRenderedCSSLength(fcaBorderLeftWidth,false);
+    aBorderRight:=El.GetRenderedCSSLength(fcaBorderRightWidth,false);
+    aBorderTop:=El.GetRenderedCSSLength(fcaBorderTopWidth,false);
+    aBorderBottom:=El.GetRenderedCSSLength(fcaBorderBottomWidth,false);
+
+    aPaddingLeft:=El.GetRenderedCSSLength(fcaPaddingLeft,false);
+    aPaddingRight:=El.GetRenderedCSSLength(fcaPaddingRight,false);
+    aPaddingTop:=El.GetRenderedCSSLength(fcaPaddingTop,false);
+    aPaddingBottom:=El.GetRenderedCSSLength(fcaPaddingBottom,false);
 
     aBorderBox.Left:=aLeft+aMarginLeft;
     aBorderBox.Top:=aTop+aMarginTop;
@@ -95,7 +99,7 @@ begin
 
     //debugln(['TFresnelRenderer.DrawElement ',El.Name,' Border=',dbgs(aBorderBox),' Content=',dbgs(aContentBox)]);
 
-    aBackgroundColor:=El.CSSComputedAttribute[fcaBackgroundColor];
+    aBackgroundColor:=El.CSSRenderedAttribute[fcaBackgroundColor];
     if not TryHtmlToFPColor(aBackgroundColor,aBackgroundColorFP) then
       aBackgroundColorFP:=colTransparent;
     if aBackgroundColorFP.Alpha<>alphaTransparent then
@@ -103,7 +107,7 @@ begin
       FillRect(aBackgroundColorFP,aBorderBox);
     end;
 
-    aBorderColor:=El.CSSComputedAttribute[fcaBorderColor];
+    aBorderColor:=El.CSSRenderedAttribute[fcaBorderColor];
     if not TryHtmlToFPColor(aBorderColor,aBorderColorFP) then
       aBorderColorFP:=colTransparent;
     if aBorderColorFP.Alpha<>alphaTransparent then
@@ -125,7 +129,7 @@ begin
 
     if El is TFresnelLabel then
     begin
-      aCaption:=TFresnelLabel(El).Caption;
+      aCaption:=TFresnelLabel(El).RenderedCaption;
       if aCaption<>'' then
       begin
         TextOut(aContentBox.Left,aContentBox.Top,El.Font,colBlack,aCaption);
@@ -139,8 +143,22 @@ begin
   end;
 end;
 
+procedure TFresnelRenderer.UpdateRenderedAttributes(El: TFresnelElement);
+var
+  LNode: TSimpleFresnelLayoutNode;
+  i: Integer;
+begin
+  LNode:=TSimpleFresnelLayoutNode(El.LayoutNode);
+  if LNode.SkipRendering then exit;
+
+  El.UpdateRenderedAttributes;
+  for i:=0 to LNode.NodeCount-1 do
+    UpdateRenderedAttributes(TSimpleFresnelLayoutNode(LNode.Nodes[i]).Element);
+end;
+
 procedure TFresnelRenderer.Draw(Viewport: TFresnelViewport);
 begin
+  UpdateRenderedAttributes(Viewport);
   DrawElement(Viewport,0,0);
 end;