ソースを参照

TFresnelRect methods, TFresnelPoint methods, fixed design coords

mattias 2 年 前
コミット
d72bf6c74c
3 ファイル変更420 行追加49 行削除
  1. 2 9
      design/fresnel.register.pas
  2. 402 32
      src/fresnel.dom.pas
  3. 16 8
      src/fresnel.renderer.pas

+ 2 - 9
design/fresnel.register.pas

@@ -148,7 +148,6 @@ procedure TFresnelFormMediator.GetBounds(AComponent: TComponent; out
 var
   El: TFresnelElement;
   aBox: TFresnelRect;
-  aPaddingLeft, aPaddingTop: TFresnelLength;
 begin
   if AComponent=FDsgnForm then
   begin
@@ -157,13 +156,6 @@ begin
   begin
     El:=TFresnelElement(AComponent);
     aBox:=El.GetBoundingClientRect;
-    //aBox:=El.RenderedBorderBox;
-    //aPaddingLeft:=El.GetRenderedCSSLength(fcaPaddingLeft,false);
-    //aPaddingTop:=El.GetRenderedCSSLength(fcaPaddingTop,false);
-    //aBox.Left:=aBox.Left+aPaddingLeft;
-    //aBox.Top:=aBox.Top+aPaddingTop;
-    //aBox.Right:=aBox.Right+aPaddingLeft;
-    //aBox.Bottom:=aBox.Bottom+aPaddingTop;
     FresnelRectToRect(aBox,CurBounds);
   end else
     inherited GetBounds(AComponent,CurBounds);
@@ -180,6 +172,7 @@ begin
   end else if AComponent is TFresnelElement then
   begin
     // bounds are controlled by CSS
+    // todo: absolute, fixed
   end else begin
     inherited SetBounds(AComponent, NewBounds);
   end;
@@ -211,7 +204,7 @@ begin
     El:=TFresnelElement(AComponent);
     if not El.Rendered then
       exit(Point(0,0));
-    BorderBox:=El.RenderedBorderBox;
+    BorderBox:=El.GetBoundingClientRect;
     Result.X:=round(BorderBox.Left);
     Result.Y:=round(BorderBox.Top);
   end else

+ 402 - 32
src/fresnel.dom.pas

@@ -20,26 +20,81 @@ unit Fresnel.DOM;
 
 {$mode ObjFPC}{$H+}
 {$WARN 6060 off} // Case statement does not handle all possible cases
+{$ModeSwitch AdvancedRecords}
 
 interface
 
 uses
-  Classes, SysUtils, Math, FPImage, sortbase,
+  Classes, SysUtils, Math, Types, FPImage, sortbase,
   fpCSSResolver, fpCSSTree, fpCSSParser, fcl.events, fresnel.events,
   LazLoggerBase;
 
 type
-  TFresnelLength = double;
-  TFresnelPoint = record
-    X, Y: TFresnelLength;
-  end;
-  TFresnelRect = record
-    Left, Top, Right, Bottom: TFresnelLength;
-  end;
+  { EFresnel }
 
   EFresnel = class(Exception)
   end;
 
+  TFresnelLength = double;
+  TArray4FresnelLength =  array[0..3] of TFresnelLength;
+
+  { TFresnelPoint }
+
+  TFresnelPoint = packed record
+    X, Y: TFresnelLength;
+    class function PointInCircle(const aPoint, aCenter: TFresnelPoint; const aRadius: TFresnelLength): Boolean; static; inline;
+    class function Zero: TFresnelPoint; static; inline;
+    class operator + (const p1, p2: TFresnelPoint): TFresnelPoint;
+    class operator - (const p1, p2: TFresnelPoint): TFresnelPoint;
+    class operator <> (const p1, p2: TFresnelPoint): Boolean;
+    class operator = (const p1, p2: TFresnelPoint): Boolean;
+    function Add(const p: TFresnelPoint): TFresnelPoint;
+    function Angle(const p: TFresnelPoint): TFresnelLength;
+    function Distance(const p: TFresnelPoint): TFresnelLength;
+    function IsZero: Boolean;
+    function Subtract(const p: TFresnelPoint): TFresnelPoint;
+    procedure Offset(const dx,dy: TFresnelLength);
+    procedure Offset(const p: TFresnelPoint);
+    procedure SetLocation(const ax, ay: TFresnelLength);
+    procedure SetLocation(const p: TFresnelPoint);
+  end;
+
+  { TFresnelRect }
+
+  TFresnelRect = packed record
+    procedure Clear;
+    constructor Create(const ALeft, ATop, ARight, ABottom: TFresnelLength);
+    class operator = (const L, R: TFresnelRect): Boolean;
+    class operator <> (const L, R: TFresnelRect): Boolean;
+    class operator + (const L, R: TFresnelRect): TFresnelRect; // union
+    class operator * (const L, R: TFresnelRect): TFresnelRect; // intersection
+    class function Empty: TFresnelRect; static;
+    procedure NormalizeRect;
+    function IsEmpty: Boolean;
+    function Contains(const P: TFresnelPoint): Boolean;
+    function Contains(const R: TFresnelRect): Boolean;
+    function Contains(const ax, ay: TFresnelLength): Boolean;
+    function IntersectsWith(const R: TFresnelRect): Boolean;
+    class function Intersect(const R1, R2: TFresnelRect): TFresnelRect; static;
+    procedure Intersect(const R: TFresnelRect);
+    class function Union(const R1, R2: TFresnelRect): TFresnelRect; static;
+    procedure Union(const R: TFresnelRect);
+    class function Union(const Points: array of TFresnelPoint): TFresnelRect; static;
+    procedure Offset(const DX, DY: TFresnelLength);
+    procedure Offset(const DP: TFresnelPoint);
+    procedure SetLocation(const X, Y: TFresnelLength);
+    procedure SetLocation(const P: TFresnelPoint);
+    procedure Inflate(const DX, DY: TFresnelLength);
+    procedure Inflate(const DL, DT, DR, DB: TFresnelLength);
+    function CenterPoint: TFresnelPoint;
+  public
+    case Longint of
+      0: (Left, Top, Right, Bottom: TFresnelLength);
+      1: (TopLeft, BottomRight: TFresnelPoint);
+      2: (Vector: TArray4FresnelLength);
+  end;
+
+  { EFresnelFont }
 
   EFresnelFont = class(EFresnel)
   end;
@@ -303,6 +358,7 @@ type
     FFontDescValid: boolean;
     FRendered: boolean;
     FRenderedBorderBox: TFresnelRect;
+    FRenderedContentBox: TFresnelRect;
     // Todo: change to dictionary to reduce mem footprint
     FStandardEvents : Array[0..MaxFresnelEvents] of TEventHandlerItem;
     FEventDispatcher : TFresnelEventDispatcher;
@@ -462,6 +518,7 @@ type
     function GetRenderedCSString(Attr: TFresnelCSSAttribute; UseInherited: boolean): string; virtual;
     property Rendered: boolean read FRendered write FRendered;
     property RenderedBorderBox: TFresnelRect read FRenderedBorderBox write FRenderedBorderBox; // relative to layout parent
+    property RenderedContentBox: TFresnelRect read FRenderedContentBox write FRenderedContentBox; // relative to layout parent
     property CSSRenderedAttribute[Attr: TFresnelCSSAttribute]: string read GetCSSRenderedAttribute write SetCSSRenderedAttribute;
     // Events
     Procedure AddEventListener(aID : TEventID; aHandler : TFresnelEventHandler);
@@ -598,6 +655,9 @@ function CompareFresnelRect(const A, B: TFresnelRect): integer;
 function FPColorToCSS(const c: TFPColor): string;
 function CSSToFPColor(const s: string; out c: TFPColor): boolean;
 
+function dbgs(const p: TFresnelPoint): string;
+function dbgs(const r: TFresnelRect): string;
+
 implementation
 
 function FloatToCSSStr(const f: TFresnelLength): string;
@@ -808,6 +868,16 @@ begin
   Result:=true;
 end;
 
+function dbgs(const p: TFresnelPoint): string;
+begin
+  Result:=FloatToStr(p.X)+','+FloatToStr(p.Y);
+end;
+
+function dbgs(const r: TFresnelRect): string;
+begin
+  Result:=FloatToStr(r.Left)+','+FloatToStr(r.Top)+','+FloatToStr(r.Right)+','+FloatToStr(r.Bottom);
+end;
+
 { TFresnelLayoutNode }
 
 procedure TFresnelLayoutNode.SetElement(const AValue: TFresnelElement);
@@ -879,6 +949,314 @@ begin
   FNodes.Sort(Compare,Context,SortBase.DefaultSortingAlgorithm);
 end;
 
+{ TFresnelPoint }
+
+class function TFresnelPoint.Zero: TFresnelPoint;
+begin
+  Result.x := 0.0;
+  Result.y := 0.0;
+end;
+
+function TFresnelPoint.Add(const p: TFresnelPoint): TFresnelPoint;
+begin
+  Result.x := X+p.X;
+  Result.y := Y+p.Y;
+end;
+
+function TFresnelPoint.Distance(const p: TFresnelPoint): TFresnelLength;
+begin
+  Result := Sqrt(Sqr(p.X-X)+Sqr(p.Y-Y));
+end;
+
+function TFresnelPoint.IsZero: Boolean;
+begin
+  Result:=SameValue(X,0) and SameValue(y,0);
+end;
+
+function TFresnelPoint.Subtract(const p: TFresnelPoint): TFresnelPoint;
+begin
+  Result.x := X-p.X;
+  Result.y := Y-p.Y;
+end;
+
+procedure TFresnelPoint.SetLocation(const p: TFresnelPoint);
+begin
+  X:=p.X;
+  Y:=p.Y;
+end;
+
+procedure TFresnelPoint.SetLocation(const ax, ay: TFresnelLength);
+begin
+  X:=ax;
+  Y:=ay;
+end;
+
+procedure TFresnelPoint.Offset(const p: TFresnelPoint);
+begin
+  X:=X+p.X;
+  Y:=Y+p.Y;
+end;
+
+procedure TFresnelPoint.Offset(const dx, dy: TFresnelLength);
+begin
+  X:=X+dX;
+  Y:=Y+dY;
+end;
+
+function TFresnelPoint.Angle(const p: TFresnelPoint): TFresnelLength;
+
+  function ArcTan2(const y,x: TFresnelLength): TFresnelLength;
+    begin
+      if x=0 then
+        begin
+          if y=0 then
+            Result:=0.0
+          else if y>0 then
+            Result:=pi/2
+          else
+            Result:=-pi/2;
+        end
+      else
+        begin
+          Result:=ArcTan(y/x);
+          if x<0 then
+            if y<0 then
+              Result:=Result-pi
+            else
+              Result:=Result+pi;
+        end;
+    end;
+
+begin
+  Result:=ArcTan2(Y-p.Y,X-p.X);
+end;
+
+class function TFresnelPoint.PointInCircle(const aPoint,
+  aCenter: TFresnelPoint; const aRadius: TFresnelLength): Boolean;
+begin
+  Result := aPoint.Distance(aCenter) <= aRadius;
+end;
+
+class operator TFresnelPoint.=(const p1, p2: TFresnelPoint): Boolean;
+begin
+  Result:=SameValue(p1.X,p2.X) and SameValue(p1.Y,p2.Y);
+end;
+
+class operator TFresnelPoint.<>(const p1, p2: TFresnelPoint): Boolean;
+begin
+  Result:=(not SameValue(p1.X,p2.X)) or (not SameValue(p1.Y,p2.Y));
+end;
+
+class operator TFresnelPoint.+(const p1, p2: TFresnelPoint): TFresnelPoint;
+begin
+  Result.X:=p1.X+p2.X;
+  Result.Y:=p1.Y+p2.Y;
+end;
+
+class operator TFresnelPoint.-(const p1, p2: TFresnelPoint): TFresnelPoint;
+begin
+  Result.X:=p1.X-p2.X;
+  Result.Y:=p1.Y-p2.Y;
+end;
+
+{ TFresnelRect }
+
+procedure TFresnelRect.Clear;
+begin
+  Left:=0.0;
+  Top:=0.0;
+  Right:=0.0;
+  Bottom:=0.0;
+end;
+
+constructor TFresnelRect.Create(const ALeft, ATop, ARight,
+  ABottom: TFresnelLength);
+begin
+  Left := ALeft;
+  Top := ATop;
+  Right := ARight;
+  Bottom := ABottom;
+end;
+
+class operator TFresnelRect.=(const L, R: TFresnelRect): Boolean;
+begin
+  Result := SameValue(L.Left,R.Left) and SameValue(L.Right,R.Right)
+        and SameValue(L.Top,R.Top) and SameValue(L.Bottom,R.Bottom);
+end;
+
+class operator TFresnelRect.<>(const L, R: TFresnelRect): Boolean;
+begin
+  Result := (not SameValue(L.Left,R.Left)) and (not SameValue(L.Right,R.Right))
+        and (not SameValue(L.Top,R.Top)) and (not SameValue(L.Bottom,R.Bottom));
+end;
+
+class operator TFresnelRect.+(const L, R: TFresnelRect): TFresnelRect;
+begin
+  Result := TFresnelRect.Union(L, R);
+end;
+
+class operator TFresnelRect.*(const L, R: TFresnelRect): TFresnelRect;
+begin
+  Result := TFresnelRect.Intersect(L, R);
+end;
+
+class function TFresnelRect.Empty: TFresnelRect;
+begin
+  Result := TFresnelRect.Create(0,0,0,0);
+end;
+
+procedure TFresnelRect.NormalizeRect;
+var
+  h: TFresnelLength;
+begin
+  if Top>Bottom then
+  begin
+    h := Top;
+    Top := Bottom;
+    Bottom := h;
+  end;
+  if Left>Right then
+  begin
+    h := Left;
+    Left := Right;
+    Right := h;
+  end
+end;
+
+function TFresnelRect.IsEmpty: Boolean;
+begin
+  Result := (Right <= Left) or (Bottom <= Top);
+end;
+
+function TFresnelRect.Contains(const P: TFresnelPoint): Boolean;
+begin
+  Result := (Left <= P.X) and (P.X < Right) and (Top <= P.Y) and (P.Y < Bottom);
+end;
+
+function TFresnelRect.Contains(const R: TFresnelRect): Boolean;
+begin
+  Result := (Left <= R.Left) and (R.Right <= Right) and (Top <= R.Top) and (R.Bottom <= Bottom);
+end;
+
+function TFresnelRect.Contains(const ax, ay: TFresnelLength): Boolean;
+begin
+  Result := (Left <= ax) and (ax < Right) and (Top <= ay) and (ay < Bottom);
+end;
+
+function TFresnelRect.IntersectsWith(const R: TFresnelRect): Boolean;
+begin
+  Result := (Left < R.Right) and (R.Left < Right) and (Top < R.Bottom) and (R.Top < Bottom);
+end;
+
+class function TFresnelRect.Intersect(const R1, R2: TFresnelRect): TFresnelRect;
+begin
+  Result.Left:=Max(R1.Left,R2.Left);
+  Result.Right:=Min(R1.Right,R2.Right);
+  Result.Top:=Max(R1.Top,R2.Top);
+  Result.Bottom:=Min(R1.Bottom,R2.Bottom);
+  if Result.IsEmpty then
+    FillByte(Result,SizeOf(TFresnelRect),0);
+end;
+
+procedure TFresnelRect.Intersect(const R: TFresnelRect);
+begin
+  if Left<R.Left then Left:=R.Left;
+  if Right>R.Right then Right:=R.Right;
+  if Top<R.Top then Top:=R.Top;
+  if Bottom>R.Bottom then Bottom:=R.Bottom;
+  if IsEmpty then
+    FillByte(Self,SizeOf(TFresnelRect),0);
+end;
+
+class function TFresnelRect.Union(const R1, R2: TFresnelRect): TFresnelRect;
+begin
+  Result.Left:=Min(R1.Left,R2.Left);
+  Result.Right:=Max(R1.Right,R2.Right);
+  Result.Top:=Min(R1.Top,R2.Top);
+  Result.Bottom:=Max(R1.Bottom,R2.Bottom);
+  if Result.IsEmpty then
+    FillByte(Result,SizeOf(TFresnelRect),0);
+end;
+
+procedure TFresnelRect.Union(const R: TFresnelRect);
+begin
+  if Left>R.Left then Left:=R.Left;
+  if Right<R.Right then Right:=R.Right;
+  if Top>R.Top then Top:=R.Top;
+  if Bottom<R.Bottom then Bottom:=R.Bottom;
+  if IsEmpty then
+    FillByte(Self,SizeOf(TFresnelRect),0);
+end;
+
+class function TFresnelRect.Union(const Points: array of TFresnelPoint
+  ): TFresnelRect;
+var
+  i: Integer;
+begin
+  if Length(Points) > 0 then
+  begin
+    Result.TopLeft := Points[Low(Points)];
+    Result.BottomRight := Points[Low(Points)];
+
+    for i := Low(Points)+1 to High(Points) do
+    begin
+      if Points[i].X < Result.Left then Result.Left := Points[i].X;
+      if Points[i].X > Result.Right then Result.Right := Points[i].X;
+      if Points[i].Y < Result.Top then Result.Top := Points[i].Y;
+      if Points[i].Y > Result.Bottom then Result.Bottom := Points[i].Y;
+    end;
+  end else
+    Result := Empty;
+end;
+
+procedure TFresnelRect.Offset(const DX, DY: TFresnelLength);
+begin
+  Left:=Left+DX;
+  Top:=Top+DY;
+  Right:=Right+DX;
+  Bottom:=Bottom+DY;
+end;
+
+procedure TFresnelRect.Offset(const DP: TFresnelPoint);
+begin
+  Left:=Left+DP.X;
+  Top:=Top+DP.Y;
+  Right:=Right+DP.X;
+  Bottom:=Bottom+DP.Y;
+end;
+
+procedure TFresnelRect.SetLocation(const X, Y: TFresnelLength);
+begin
+  Offset(X-Left, Y-Top);
+end;
+
+procedure TFresnelRect.SetLocation(const P: TFresnelPoint);
+begin
+  Offset(P.X-Left, P.Y-Top);
+end;
+
+procedure TFresnelRect.Inflate(const DX, DY: TFresnelLength);
+begin
+  Left:=Left-DX;
+  Top:=Top-DY;
+  Right:=Right+DX;
+  Bottom:=Bottom+DY;
+end;
+
+procedure TFresnelRect.Inflate(const DL, DT, DR, DB: TFresnelLength);
+begin
+  Left:=Left-DL;
+  Top:=Top-DT;
+  Right:=Right+DR;
+  Bottom:=Bottom+DB;
+end;
+
+function TFresnelRect.CenterPoint: TFresnelPoint;
+begin
+  Result.X := (Left+Right)/2;
+  Result.Y := (Top+Bottom)/2;
+end;
+
 { TFresnelViewport }
 
 procedure TFresnelViewport.CSSResolverLog(Sender: TObject;
@@ -1148,28 +1526,23 @@ function TFresnelViewport.GetElementAt(const x, y: TFresnelLength
   var
     El: TFresnelElement;
     i: Integer;
-    aLeft, aTop, aPaddingLeft, aPaddingTop: TFresnelLength;
     BorderBox: TFresnelRect;
+    aContentOffset: TFresnelPoint;
   begin
     Result:=nil;
     if Node=nil then exit;
     El:=Node.Element;
     if not El.Rendered then exit;
-    BorderBox:=El.RenderedBorderBox;
     if Node.NodeCount>0 then begin
-      aPaddingLeft:=El.GetRenderedCSSLength(fcaPaddingLeft,false);
-      aPaddingTop:=El.GetRenderedCSSLength(fcaPaddingTop,false);
-      aLeft:=BorderBox.Left+aPaddingLeft;
-      aTop:=BorderBox.Top+aPaddingTop;
-
+      aContentOffset:=El.RenderedContentBox.TopLeft;
       for i:=Node.NodeCount-1 downto 0 do
       begin
-        Result:=Check(Node.Nodes[i],dx+aLeft,dy+aTop);
+        Result:=Check(Node.Nodes[i],dx+aContentOffset.X,dy+aContentOffset.Y);
         if Result<>nil then exit;
       end;
     end;
-    if (x>=BorderBox.Left+dx) and (y>=BorderBox.Top+dy)
-        and (x<=BorderBox.Right+dx) and (y<=BorderBox.Right+dy) then
+    BorderBox:=El.RenderedBorderBox;
+    if BorderBox.Contains(x-dx,y-dy) then
       Result:=El
     else
       Result:=nil;
@@ -2613,23 +2986,20 @@ end;
 
 function TFresnelElement.GetBoundingClientRect: TFresnelRect;
 var
-  Box: TFresnelRect;
-  aPaddingLeft, aPaddingTop, aLeft, aTop: TFresnelLength;
+  Node: TFresnelLayoutNode;
 begin
-  Result:=RenderedBorderBox;
-  if Parent<>nil then
+  if (not Rendered) then
   begin
-    Box:=Parent.GetBoundingClientRect;
-    aPaddingLeft:=Parent.GetRenderedCSSLength(fcaPaddingLeft,false);
-    aPaddingTop:=Parent.GetRenderedCSSLength(fcaPaddingTop,false);
-    debugln(['TFresnelElement.GetBoundingClientRect ',Name,' RenderedBorderBox=',Result.Left,',',Result.Top,',',Result.Right,',',Result.Bottom,' Parent=',Parent.Name,' ',Box.Left,',',Box.Top,' Pad=',aPaddingLeft,',',aPaddingTop]);
-    aLeft:=Box.Left+aPaddingLeft;
-    aTop:=Box.Top+aPaddingTop;
-    Result.Left:=Result.Left+aLeft;
-    Result.Top:=Result.Top+aTop;
-    Result.Right:=Result.Right+aLeft;
-    Result.Bottom:=Result.Bottom+aTop;
+    Result.Clear;
+    exit;
+  end;
+  Result:=RenderedBorderBox;
+  Node:=LayoutNode.Parent;
+  while Node<>nil do begin
+    Result.Offset(Node.Element.RenderedContentBox.TopLeft);
+    Node:=Node.Parent;
   end;
+  //debugln(['TFresnelElement.GetBoundingClientRect ',Name,' Result=',Result.Left,',',Result.Top,',',Result.Right,',',Result.Bottom]);
 end;
 
 function TFresnelElement.GetRenderedCSSLength(Attr: TFresnelCSSAttribute;

+ 16 - 8
src/fresnel.renderer.pas

@@ -6,7 +6,7 @@ interface
 
 uses
   Classes, SysUtils, Math, FPImage, Fresnel.DOM, Fresnel.Controls,
-  Fresnel.Layouter;
+  Fresnel.Layouter, LazLoggerBase;
 
 type
 
@@ -59,9 +59,10 @@ var
     aPaddingLeft, aPaddingRight, aPaddingTop, aPaddingBottom: TFresnelLength;
   aBorderBox, aContentBox: TFresnelRect;
   i: Integer;
-  OldOrigin, CurOrigin: TFresnelPoint;
+  OldOrigin: TFresnelPoint;
+  VP: TFresnelViewport;
 begin
-  //DebugLn(['TFresnelLCLControl.DrawElement ',El.GetPath]);
+  //DebugLn(['TFresnelRenderer.DrawElement ',El.GetPath,' Origin=',dbgs(Origin)]);
   LNode:=TSimpleFresnelLayoutNode(El.LayoutNode);
   if LNode.SkipRendering then exit;
 
@@ -70,6 +71,13 @@ begin
   begin
     aLeft:=0;
     aTop:=0;
+    VP:=TFresnelViewport(El);
+    aContentBox.Left:=0;
+    aContentBox.Top:=0;
+    aContentBox.Right:=Vp.Width;
+    aContentBox.Bottom:=Vp.Height;
+    El.RenderedBorderBox:=aContentBox;
+    El.RenderedContentBox:=aContentBox;
   end else begin
     aLeft:=El.GetRenderedCSSLength(fcaLeft,false);
     aTop:=El.GetRenderedCSSLength(fcaTop,false);
@@ -95,18 +103,19 @@ begin
     aBorderBox.Top:=aTop+aMarginTop;
     aBorderBox.Right:=aRight-aMarginRight;
     aBorderBox.Bottom:=aBottom-aMarginBottom;
+    El.RenderedBorderBox:=aBorderBox;
     if not SubPixel then
       MathRoundRect(aBorderBox);
-    El.RenderedBorderBox:=aBorderBox;
 
     aContentBox.Left:=aLeft+aMarginLeft+aBorderLeft+aPaddingLeft;
     aContentBox.Top:=aTop+aMarginTop+aBorderTop+aPaddingTop;
     aContentBox.Right:=aRight-aMarginRight-aBorderRight-aPaddingRight;
     aContentBox.Bottom:=aBottom-aMarginBottom-aBorderBottom-aPaddingBottom;
+    El.RenderedContentBox:=aContentBox;
     if not SubPixel then
       MathRoundRect(aContentBox);
 
-    //debugln(['TFresnelRenderer.DrawElement ',El.Name,' Border=',dbgs(aBorderBox),' Content=',dbgs(aContentBox)]);
+    //DebugLn(['TFresnelRenderer.DrawElement ',El.Name,' Border=',dbgs(aBorderBox),' Content=',dbgs(aContentBox)]);
 
     aBackgroundColor:=El.CSSRenderedAttribute[fcaBackgroundColor];
     if not CSSToFPColor(aBackgroundColor,aBackgroundColorFP) then
@@ -153,11 +162,9 @@ begin
   end;
 
   OldOrigin:=Origin;
+  Origin:=OldOrigin+El.RenderedContentBox.TopLeft;
   for i:=0 to LNode.NodeCount-1 do
   begin
-    CurOrigin.X:=OldOrigin.X+aLeft+aMarginLeft+aBorderLeft+aPaddingLeft;
-    CurOrigin.Y:=OldOrigin.Y+aTop+aMarginTop+aBorderTop+aPaddingTop;
-    Origin:=CurOrigin;
     DrawElement(TSimpleFresnelLayoutNode(LNode.Nodes[i]).Element);
   end;
   Origin:=OldOrigin;
@@ -178,6 +185,7 @@ end;
 
 procedure TFresnelRenderer.Draw(Viewport: TFresnelViewport);
 begin
+  //debugln(['TFresnelRenderer.Draw Origin=',dbgs(Origin)]);
   UpdateRenderedAttributes(Viewport);
   DrawElement(Viewport);
 end;