Browse Source

changed Node.Left/Top to paddingbox

mattias 3 months ago
parent
commit
de2b4fae93

+ 1 - 1
src/base/fcl-css/fpcssparser.pp

@@ -1256,7 +1256,7 @@ function TCSSParser.ParseSelector: TCSSElement;
 
 
 var
 var
   ok, OldReturnWhiteSpace: Boolean;
   ok, OldReturnWhiteSpace: Boolean;
-  Bin, PseudoBin: TCSSBinaryElement;
+  Bin: TCSSBinaryElement;
   El, Sub: TCSSElement;
   El, Sub: TCSSElement;
   List: TCSSListElement;
   List: TCSSListElement;
 begin
 begin

+ 0 - 1
src/base/fcl-css/fpcssresolver.pas

@@ -1382,7 +1382,6 @@ function TCSSResolver.SelectorBinaryMatches(aBinary: TCSSBinaryElement;
 var
 var
   aParent, Sibling: ICSSNode;
   aParent, Sibling: ICSSNode;
   aSpecificity: TCSSSpecificity;
   aSpecificity: TCSSSpecificity;
-  PseudoEl: TCSSElement;
 begin
 begin
   if OnlySpecificity then
   if OnlySpecificity then
   begin
   begin

+ 6 - 1
src/base/fresnel.classes.pas

@@ -200,7 +200,7 @@ function DbgSName(const p: TObject): string; overload;
 function DbgSName(const p: TClass): string; overload;
 function DbgSName(const p: TClass): string; overload;
 function dbgs(const p: TFresnelPoint): string; overload;
 function dbgs(const p: TFresnelPoint): string; overload;
 function dbgs(const r: TFresnelRect): string; overload;
 function dbgs(const r: TFresnelRect): string; overload;
-
+procedure DumpStack;
 Var
 Var
   MinStrokeWidth : TFresnelLength = 0.09;
   MinStrokeWidth : TFresnelLength = 0.09;
 
 
@@ -371,6 +371,11 @@ begin
   Result:=FloatToStr(r.Left)+','+FloatToStr(r.Top)+','+FloatToStr(r.Right)+','+FloatToStr(r.Bottom);
   Result:=FloatToStr(r.Left)+','+FloatToStr(r.Top)+','+FloatToStr(r.Right)+','+FloatToStr(r.Bottom);
 end;
 end;
 
 
+procedure DumpStack;
+begin
+  Dump_Stack(StdOut, get_frame);
+end;
+
 { TFresnelPoint }
 { TFresnelPoint }
 
 
 class function TFresnelPoint.Zero: TFresnelPoint;
 class function TFresnelPoint.Zero: TFresnelPoint;

+ 21 - 20
src/base/fresnel.dom.pas

@@ -1146,11 +1146,11 @@ type
     // the result is the MarginBox
     // the result is the MarginBox
     // attributes depending on position:
     // attributes depending on position:
     //  static: left, top, right, bottom are ignored
     //  static: left, top, right, bottom are ignored
-    //  relative: relative to layout position. left 10px moves 10px to the right, right 10px moves 10px to the left
-    //  absolute: relative to container's contentbox. left 10px moves 10px to the right, right 10px moves 10px to the left
+    //  relative: relative to static position. left 10px moves 10px to the right, right 10px moves 10px to the left
+    //  absolute: relative to container's paddingbox. left 10px moves 10px to the right, right 10px moves 10px to the left
     //  fixed: as absolute, except relative to viewport
     //  fixed: as absolute, except relative to viewport
-    //  sticky: as relative, except to container's non-scrolled contentbox
-    Left: TFresnelLength; // after computation: margin-boxed
+    //  sticky: as relative, except to container's non-scrolled paddingbox
+    Left: TFresnelLength; // after computation: margin-boxed relative to container's padding-box
     Top: TFresnelLength; // after computation: margin-boxed
     Top: TFresnelLength; // after computation: margin-boxed
     Right: TFresnelLength; // after computation: margin-boxed
     Right: TFresnelLength; // after computation: margin-boxed
     Bottom: TFresnelLength; // after computation: margin-boxed
     Bottom: TFresnelLength; // after computation: margin-boxed
@@ -1522,7 +1522,7 @@ type
     property LayoutNode: TFresnelLayoutNode read FLayoutNode write FLayoutNode;
     property LayoutNode: TFresnelLayoutNode read FLayoutNode write FLayoutNode;
     property UsedBorderBox: TFresnelRect read FUsedBorderBox write FUsedBorderBox; // relative to layout parent's clientbox
     property UsedBorderBox: TFresnelRect read FUsedBorderBox write FUsedBorderBox; // relative to layout parent's clientbox
     property UsedContentBox: TFresnelRect read FUsedContentBox write FUsedContentBox; // the content including scroll gutters, relative to layout parent's clientbox
     property UsedContentBox: TFresnelRect read FUsedContentBox write FUsedContentBox; // the content including scroll gutters, relative to layout parent's clientbox
-    property UsedClientBox: TFresnelRect read FUsedClientBox write FUsedClientBox; // the content excluding scroll gutters, relative to layout parent's clientbox
+    property UsedClientBox: TFresnelRect read FUsedClientBox write FUsedClientBox; // the padding excluding scroll gutters, relative to layout parent's clientbox
     // Scrolling
     // Scrolling
     property ScrollLeft: TFresnelLength read FScrollLeft write SetScrollLeft;
     property ScrollLeft: TFresnelLength read FScrollLeft write SetScrollLeft;
     property ScrollTop: TFresnelLength read FScrollTop write SetScrollTop;
     property ScrollTop: TFresnelLength read FScrollTop write SetScrollTop;
@@ -7271,15 +7271,15 @@ begin
   Node:=El.LayoutNode;
   Node:=El.LayoutNode;
   if Node.SkipRendering then exit;
   if Node.SkipRendering then exit;
   c:=El.UsedClientBox;
   c:=El.UsedClientBox;
-  Result.X+=c.Left;
-  Result.Y+=c.Top;
+  Result.X:=Result.X+c.Left;
+  Result.Y:=Result.Y+c.Top;
   repeat
   repeat
     Node:=Node.Parent;
     Node:=Node.Parent;
     if Node=nil then exit;
     if Node=nil then exit;
     El:=Node.Element;
     El:=Node.Element;
     c:=El.UsedClientBox;
     c:=El.UsedClientBox;
-    Result.X+=c.Left-El.ScrollLeft;
-    Result.Y+=c.Top-El.ScrollTop;
+    Result.X:=Result.X+c.Left-El.ScrollLeft;
+    Result.Y:=Result.Y+c.Top-El.ScrollTop;
   until false;
   until false;
 end;
 end;
 
 
@@ -8690,9 +8690,10 @@ begin
   El:=Parent;
   El:=Parent;
   while El<>Container do
   while El<>Container do
   begin
   begin
-    // Note: scrolling creates a container, so it can be ignored and
-    // it must be ignored as this is used by the layouter
-    c:=El.UsedContentBox;
+    // Note: scrolling creates a container,
+    // so ScrollLeft/Top and gutters can be ignored
+    // And they must be ignored as this is used by the layouter
+    c:=El.GetUsedPaddingBox;
     Result.X:=Result.X+c.Left;
     Result.X:=Result.X+c.Left;
     Result.Y:=Result.Y+c.Top;
     Result.Y:=Result.Y+c.Top;
     El:=El.Parent;
     El:=El.Parent;
@@ -8745,10 +8746,10 @@ var
 begin
 begin
   Result:=UsedBorderBox;
   Result:=UsedBorderBox;
   Node:=LayoutNode;
   Node:=LayoutNode;
-  Result.Left+=Node.BorderLeft;
-  Result.Top+=Node.BorderTop;
-  Result.Right-=Node.BorderRight;
-  Result.Bottom-=Node.BorderBottom;
+  Result.Left:=Result.Left+Node.BorderLeft;
+  Result.Top:=Result.Top+Node.BorderTop;
+  Result.Right:=Result.Right-Node.BorderRight;
+  Result.Bottom:=Result.Bottom-Node.BorderBottom;
 end;
 end;
 
 
 function TFresnelElement.GetBorderBoxOnViewport: TFresnelRect;
 function TFresnelElement.GetBorderBoxOnViewport: TFresnelRect;
@@ -8784,8 +8785,8 @@ var
   N: TFresnelLayoutNode;
   N: TFresnelLayoutNode;
 begin
 begin
   N:=LayoutNode;
   N:=LayoutNode;
-  Result.X:=X+N.ScrollGutterLeft+N.PaddingLeft+N.BorderLeft;
-  Result.Y:=Y+N.ScrollGutterTop+N.PaddingTop+N.BorderTop;
+  Result.X:=X+N.ScrollGutterLeft+N.BorderLeft;
+  Result.Y:=Y+N.ScrollGutterTop+N.BorderTop;
 end;
 end;
 
 
 function TFresnelElement.BorderToClientPos(const X, Y: TFresnelLength): TFresnelPoint;
 function TFresnelElement.BorderToClientPos(const X, Y: TFresnelLength): TFresnelPoint;
@@ -8793,8 +8794,8 @@ var
   N: TFresnelLayoutNode;
   N: TFresnelLayoutNode;
 begin
 begin
   N:=LayoutNode;
   N:=LayoutNode;
-  Result.X:=X-N.ScrollGutterLeft-N.PaddingLeft-N.BorderLeft;
-  Result.Y:=Y-N.ScrollGutterTop-N.PaddingTop-N.BorderTop;
+  Result.X:=X-N.ScrollGutterLeft-N.BorderLeft;
+  Result.Y:=Y-N.ScrollGutterTop-N.BorderTop;
 end;
 end;
 
 
 function TFresnelElement.GetComputedBorderRadius(Corner: TFresnelCSSCorner
 function TFresnelElement.GetComputedBorderRadius(Corner: TFresnelCSSCorner

+ 72 - 43
src/base/fresnel.layouter.pas

@@ -259,7 +259,7 @@ end;
 
 
 procedure TFLNodeLayouter.Apply;
 procedure TFLNodeLayouter.Apply;
 var
 var
-  MaxWidth, MaxHeight, aClientWidth, aClientHeight: TFresnelLength;
+  MaxWidth, MaxHeight, AvailWidth, AvailHeight: TFresnelLength;
   Size: TFreIntrinsicContentSize;
   Size: TFreIntrinsicContentSize;
   HasMaxWidth, HasMaxHeight: Boolean;
   HasMaxWidth, HasMaxHeight: Boolean;
   El: TFresnelElement;
   El: TFresnelElement;
@@ -299,44 +299,44 @@ begin
     aClientBox.Bottom-=Node.ScrollGutterBottom;
     aClientBox.Bottom-=Node.ScrollGutterBottom;
     El.UsedClientBox:=aClientBox;
     El.UsedClientBox:=aClientBox;
 
 
-    aClientWidth:=MaxWidth;
+    AvailWidth:=MaxWidth;
     if HasMaxWidth then
     if HasMaxWidth then
-      aClientWidth:=aClientWidth-Node.ScrollGutterLeft-Node.ScrollGutterRight;
-    aClientHeight:=MaxHeight;
+      AvailWidth:=AvailWidth-Node.ScrollGutterLeft-Node.ScrollGutterRight;
+    AvailHeight:=MaxHeight;
     if HasMaxHeight then
     if HasMaxHeight then
-      aClientHeight:=aClientHeight-Node.ScrollGutterTop-Node.ScrollGutterBottom;
+      AvailHeight:=AvailHeight-Node.ScrollGutterTop-Node.ScrollGutterBottom;
 
 
     {$IFDEF VerboseFresnelScrolling}
     {$IFDEF VerboseFresnelScrolling}
-    writeln('TFLNodeLayouter.Apply "',Node.Element.Name,'" CanScrollX=',Node.CanScrollX,' CanScrollY=',Node.CanScrollY,' MaxSize=',FloatToCSSStr(MaxWidth),'x',FloatToCSSStr(MaxHeight),' Client=',FloatToCSSStr(aClientWidth),'x',FloatToCSSStr(aClientHeight));
+    writeln('TFLNodeLayouter.Apply "',Node.Element.Name,'" CanScrollX=',Node.CanScrollX,' CanScrollY=',Node.CanScrollY,' MaxSize=',FloatToCSSStr(MaxWidth),'x',FloatToCSSStr(MaxHeight),' Available=',FloatToCSSStr(aClientWidth),'x',FloatToCSSStr(aClientHeight));
     {$ENDIF}
     {$ENDIF}
-    Size:=ComputeLayoutContent(flmMax,aClientWidth,aClientHeight,true);
+    Size:=ComputeLayoutContent(flmMax,AvailWidth,AvailHeight,true);
     {$IFDEF VerboseFresnelScrolling}
     {$IFDEF VerboseFresnelScrolling}
     writeln('TFLNodeLayouter.Apply "',Node.Element.Name,'" Size: ',FloatToCSSStr(Size.Width),'x',FloatToCSSStr(Size.Height),' Scroll: ',FloatToCSSStr(Size.ScrollWidth),'x',FloatToCSSStr(Size.ScrollWidth));
     writeln('TFLNodeLayouter.Apply "',Node.Element.Name,'" Size: ',FloatToCSSStr(Size.Width),'x',FloatToCSSStr(Size.Height),' Scroll: ',FloatToCSSStr(Size.ScrollWidth),'x',FloatToCSSStr(Size.ScrollWidth));
     {$ENDIF}
     {$ENDIF}
     if IsNan(Node.Width) then
     if IsNan(Node.Width) then
     begin
     begin
       Node.Width:=Size.Width;
       Node.Width:=Size.Width;
-      if Node.Width>aClientWidth then
-        Node.Width:=aClientWidth;
+      if Node.Width>AvailWidth then
+        Node.Width:=AvailWidth;
     end;
     end;
     if IsNan(Node.Height) then
     if IsNan(Node.Height) then
     begin
     begin
       Node.Height:=Node.FitHeight(Size.Height);
       Node.Height:=Node.FitHeight(Size.Height);
-      if Node.Height>aClientHeight then
-        Node.Height:=aClientHeight;
+      if Node.Height>AvailHeight then
+        Node.Height:=AvailHeight;
     end;
     end;
-    Node.ScrollWidth:=Max(Size.ScrollWidth,aClientWidth);
-    Node.ScrollHeight:=Max(Size.ScrollHeight,aClientHeight);
+    Node.ScrollWidth:=Max(Size.ScrollWidth,AvailWidth);
+    Node.ScrollHeight:=Max(Size.ScrollHeight,AvailHeight);
     {$IFDEF VerboseFresnelScrolling}
     {$IFDEF VerboseFresnelScrolling}
     writeln('TFLNodeLayouter.Apply "',Node.Element.Name,'" ScrollSize: ',FloatToCSSStr(Node.ScrollWidth),'x',FloatToCSSStr(Node.ScrollHeight),' Width=',FloatToCSSStr(Node.Width),' Height=',FloatToCSSStr(Node.Height));
     writeln('TFLNodeLayouter.Apply "',Node.Element.Name,'" ScrollSize: ',FloatToCSSStr(Node.ScrollWidth),'x',FloatToCSSStr(Node.ScrollHeight),' Width=',FloatToCSSStr(Node.Width),' Height=',FloatToCSSStr(Node.Height));
     {$ENDIF}
     {$ENDIF}
 
 
     if Node.ScrollbarWidth<>CSSRegistry.kwNone then
     if Node.ScrollbarWidth<>CSSRegistry.kwNone then
     begin
     begin
-      if (Node.ScrollWidth>aClientWidth)
+      if (Node.ScrollWidth>AvailWidth)
           and (El.ComputedOverflowX in [CSSRegistry.kwScroll,CSSRegistry.kwAuto]) then
           and (El.ComputedOverflowX in [CSSRegistry.kwScroll,CSSRegistry.kwAuto]) then
         Include(Node.Flags,flfScrollbarHorizontal);
         Include(Node.Flags,flfScrollbarHorizontal);
-      if (Node.ScrollHeight>aClientHeight)
+      if (Node.ScrollHeight>AvailHeight)
           and (El.ComputedOverflowY in [CSSRegistry.kwScroll,CSSRegistry.kwAuto]) then
           and (El.ComputedOverflowY in [CSSRegistry.kwScroll,CSSRegistry.kwAuto]) then
         Include(Node.Flags,flfScrollbarVertical);
         Include(Node.Flags,flfScrollbarVertical);
     end;
     end;
@@ -490,7 +490,6 @@ var
     if not GetCachedLayoutSize(CurMode,CurMaxWidth,CurMaxHeight,false,Result) then
     if not GetCachedLayoutSize(CurMode,CurMaxWidth,CurMaxHeight,false,Result) then
     begin
     begin
       Result:=ComputeLayoutContent(CurMode,CurMaxWidth,CurMaxHeight,false);
       Result:=ComputeLayoutContent(CurMode,CurMaxWidth,CurMaxHeight,false);
-      Result:=Default(TFreIntrinsicContentSize);
       AddCachedLayoutSize(CurMode,CurMaxWidth,CurMaxHeight,false,Result);
       AddCachedLayoutSize(CurMode,CurMaxWidth,CurMaxHeight,false,Result);
     end;
     end;
     if AddGutter then begin
     if AddGutter then begin
@@ -543,7 +542,6 @@ var
   end;
   end;
 
 
 var
 var
-  aSize: TFresnelPoint;
   OldNeedVert: Boolean;
   OldNeedVert: Boolean;
 begin
 begin
   case aMode of
   case aMode of
@@ -561,8 +559,12 @@ begin
     aWithScroll:=false;
     aWithScroll:=false;
   end;
   end;
 
 
+  //writeln('TFLNodeLayouter.GetIntrinsicContentSize ',Node.Element.Name,' ',aMode,' ',FloatToCSSStr(aMaxWidth),' ',FloatToCSSStr(aMaxHeight));
   if GetCachedLayoutSize(aMode,aMaxWidth,aMaxHeight,aWithScroll,Result) then
   if GetCachedLayoutSize(aMode,aMaxWidth,aMaxHeight,aWithScroll,Result) then
+  begin
+    //writeln('TFLNodeLayouter.GetIntrinsicContentSize FromCache: ',Result.ToString);
     exit;
     exit;
+  end;
 
 
   Done:=false;
   Done:=false;
   if aWithScroll then
   if aWithScroll then
@@ -618,6 +620,7 @@ begin
   if not Done then
   if not Done then
   begin
   begin
     Result:=ComputeLayoutContent(aMode,aMaxWidth,aMaxHeight,false);
     Result:=ComputeLayoutContent(aMode,aMaxWidth,aMaxHeight,false);
+    //writeln('TFLNodeLayouter.GetIntrinsicContentSize ',Node.Element.Name,' ',aMode,' ',FloatToCSSStr(aMaxWidth),' ',FloatToCSSStr(aMaxHeight),' Computed=',Result.ToString);
   end;
   end;
   AddCachedLayoutSize(aMode,aMaxWidth,aMaxHeight,aWithScroll,Result);
   AddCachedLayoutSize(aMode,aMaxWidth,aMaxHeight,aWithScroll,Result);
 end;
 end;
@@ -1277,7 +1280,7 @@ begin
     begin
     begin
       ChildPrefSize:=ChildEl.GetIntrinsicContentSize(aMode,CurSpace,NaN);
       ChildPrefSize:=ChildEl.GetIntrinsicContentSize(aMode,CurSpace,NaN);
       //if ChildEl.Name='CaptionLabel' then
       //if ChildEl.Name='CaptionLabel' then
-        writeln('TFLFlowLayouter.ComputeLayoutContent ',ChildEl.GetPath,' MaxWidth=',FloatToCSSStr(CurSpace),' Preferred=',ChildPrefSize.ToString,' ChildPadBorderX=',FloatToCSSStr(ChildPadBorderX),' ChildPadBorderY=',FloatToCSSStr(ChildPadBorderY));
+        //writeln('TFLFlowLayouter.ComputeLayoutContent ',ChildEl.GetPath,' MaxWidth=',FloatToCSSStr(CurSpace),' Preferred=',ChildPrefSize.ToString,' ChildPadBorderX=',FloatToCSSStr(ChildPadBorderX),' ChildPadBorderY=',FloatToCSSStr(ChildPadBorderY),' Commit=',Commit);
       // apply min, max
       // apply min, max
       if IsNan(ChildWidth) then
       if IsNan(ChildWidth) then
       begin
       begin
@@ -1956,7 +1959,7 @@ var
   ChildNode: TUsedLayoutNode;
   ChildNode: TUsedLayoutNode;
   ChildEl: TFresnelElement;
   ChildEl: TFresnelElement;
   NewLeft, NewTop, FrameLeft, FrameRight, FrameTop, FrameBottom: TFresnelLength;
   NewLeft, NewTop, FrameLeft, FrameRight, FrameTop, FrameBottom: TFresnelLength;
-  aBorderBox, aContentBox: TFresnelRect;
+  aBorderBox, aContentBox, aClientBox: TFresnelRect;
 begin
 begin
   for i:=0 to FLineItems.Count-1 do
   for i:=0 to FLineItems.Count-1 do
   begin
   begin
@@ -2004,10 +2007,14 @@ begin
     aContentBox.Bottom:=aContentBox.Top+Item.ContentBoxHeight;
     aContentBox.Bottom:=aContentBox.Top+Item.ContentBoxHeight;
     aBorderBox.Right:=aContentBox.Right+FrameRight;
     aBorderBox.Right:=aContentBox.Right+FrameRight;
     aBorderBox.Bottom:=aContentBox.Bottom+FrameBottom;
     aBorderBox.Bottom:=aContentBox.Bottom+FrameBottom;
+    aClientBox.Left:=aBorderBox.Left+ChildNode.PaddingLeft;
+    aClientBox.Top:=aBorderBox.Top+ChildNode.PaddingTop;
+    aClientBox.Right:=aBorderBox.Right-ChildNode.PaddingRight;
+    aClientBox.Bottom:=aBorderBox.Bottom-ChildNode.PaddingBottom;
 
 
     ChildEl.UsedBorderBox:=aBorderBox;
     ChildEl.UsedBorderBox:=aBorderBox;
     ChildEl.UsedContentBox:=aContentBox;
     ChildEl.UsedContentBox:=aContentBox;
-    ChildEl.UsedClientBox:=aContentBox;
+    ChildEl.UsedClientBox:=aClientBox;
     ChildNode.Left:=NewLeft;
     ChildNode.Left:=NewLeft;
     ChildNode.Top:=NewTop;
     ChildNode.Top:=NewTop;
     ChildNode.Right:=aBorderBox.Right+ChildNode.MarginRight;
     ChildNode.Right:=aBorderBox.Right+ChildNode.MarginRight;
@@ -2043,51 +2050,61 @@ begin
     writeln('TFLLineLayouter.PlaceAbsoluteItem ',ChildEl.GetPath,' ',aMode,' Commit=',Commit,' Left=',FloatToCSSStr(ChildNode.Left),',Top=',FloatToCSSStr(ChildNode.Top),',Right=',FloatToCSSStr(ChildNode.Right),',Bottom=',FloatToCSSStr(ChildNode.Bottom),' Width=',FloatToCSSStr(ChildNode.Width),' Height=',FloatToCSSStr(ChildNode.Height),' Default=',FloatToCSSStr(DefaultPos.X),',',FloatToCSSStr(DefaultPos.Y));
     writeln('TFLLineLayouter.PlaceAbsoluteItem ',ChildEl.GetPath,' ',aMode,' Commit=',Commit,' Left=',FloatToCSSStr(ChildNode.Left),',Top=',FloatToCSSStr(ChildNode.Top),',Right=',FloatToCSSStr(ChildNode.Right),',Bottom=',FloatToCSSStr(ChildNode.Bottom),' Width=',FloatToCSSStr(ChildNode.Width),' Height=',FloatToCSSStr(ChildNode.Height),' Default=',FloatToCSSStr(DefaultPos.X),',',FloatToCSSStr(DefaultPos.Y));
     writeln('TFLLineLayouter.PlaceAbsoluteItem ',CSSRegistry.Keywords[ChildEl.ComputedDisplayOutside],' ',CSSRegistry.Keywords[ChildEl.ComputedDisplayInside],' Style=',ChildEl.Style);
     writeln('TFLLineLayouter.PlaceAbsoluteItem ',CSSRegistry.Keywords[ChildEl.ComputedDisplayOutside],' ',CSSRegistry.Keywords[ChildEl.ComputedDisplayInside],' Style=',ChildEl.Style);
   {$ENDIF}
   {$ENDIF}
+  FrameLeft:=ChildNode.MarginLeft+ChildNode.BorderLeft+ChildNode.PaddingLeft;
+  FrameRight:=ChildNode.PaddingRight+ChildNode.BorderRight+ChildNode.MarginRight;
+  FrameTop:=ChildNode.MarginTop+ChildNode.BorderTop+ChildNode.PaddingTop;
+  FrameBottom:=ChildNode.PaddingBottom+ChildNode.BorderBottom+ChildNode.MarginBottom;
+
   NewLeft:=ChildNode.Left;
   NewLeft:=ChildNode.Left;
   NewTop:=ChildNode.Top;
   NewTop:=ChildNode.Top;
   NewRight:=ChildNode.Right;
   NewRight:=ChildNode.Right;
   NewBottom:=ChildNode.Bottom;
   NewBottom:=ChildNode.Bottom;
+  if aMode=flmMax then
+  begin
+    NewWidth:=ChildNode.Width;
+    NewHeight:=ChildNode.Height;
+
+    if IsNan(NewWidth) and not IsNan(aMaxWidth)
+        and not IsNan(NewLeft) and not IsNan(NewRight) then
+      NewWidth:=aMaxWidth-NewLeft-NewRight-FrameLeft-FrameRight;
+    if IsNan(NewHeight) and not IsNan(aMaxHeight)
+        and not IsNan(NewTop) and not IsNan(NewBottom) then
+      NewHeight:=aMaxHeight-NewTop-NewBottom-FrameTop-FrameBottom;
+  end else begin
+    NewWidth:=NaN;
+    NewHeight:=NaN;
+  end;
+
   p.X:=NaN;
   p.X:=NaN;
   if IsNan(NewLeft) and IsNan(NewRight) then
   if IsNan(NewLeft) and IsNan(NewRight) then
   begin
   begin
+    // no left or right => use default static position
     p:=ChildEl.GetContainerOffset;
     p:=ChildEl.GetContainerOffset;
     NewLeft:=p.X+DefaultPos.X;
     NewLeft:=p.X+DefaultPos.X;
   end;
   end;
   if IsNan(NewTop) and IsNan(NewBottom) then
   if IsNan(NewTop) and IsNan(NewBottom) then
   begin
   begin
+    // no top or bottom => use default static position
     if IsNan(p.X) then
     if IsNan(p.X) then
       p:=ChildEl.GetContainerOffset;
       p:=ChildEl.GetContainerOffset;
     NewTop:=p.y+DefaultPos.Y;
     NewTop:=p.y+DefaultPos.Y;
   end;
   end;
 
 
+  // Note: The DeductUsedLengths has already computed based solely on css values.
+
   if aMode=flmMax then
   if aMode=flmMax then
   begin
   begin
-    NewWidth:=ChildNode.Width;
-    NewHeight:=ChildNode.Height;
-  end else begin
-    NewWidth:=NaN;
-    NewHeight:=NaN;
+    if IsNan(aMaxWidth) then
+      aMaxWidth:=ChildNode.MaxWidth;
+    if IsNan(aMaxHeight) then
+      aMaxHeight:=ChildNode.MaxHeight;
   end;
   end;
-
-  // Note: The DeductUsedLengths has already computed simple cases
-  //   e.g. given container's width and child's left and right => child's width
-
-  aMaxWidth:=NewWidth;
-  aMaxHeight:=NewHeight;
-  if IsNan(aMaxWidth) then
-    aMaxWidth:=ChildNode.MaxWidth;
-  if IsNan(aMaxHeight) then
-    aMaxHeight:=ChildNode.MaxHeight;
   Size:=ChildEl.GetIntrinsicContentSize(aMode,aMaxWidth,aMaxHeight);
   Size:=ChildEl.GetIntrinsicContentSize(aMode,aMaxWidth,aMaxHeight);
   if IsNan(NewWidth) then
   if IsNan(NewWidth) then
     NewWidth:=ChildNode.FitWidth(Size.Width);
     NewWidth:=ChildNode.FitWidth(Size.Width);
   if IsNan(NewHeight) then
   if IsNan(NewHeight) then
     NewHeight:=ChildNode.FitHeight(Size.Height);
     NewHeight:=ChildNode.FitHeight(Size.Height);
 
 
-  FrameLeft:=ChildNode.MarginLeft+ChildNode.BorderLeft+ChildNode.PaddingLeft;
-  FrameRight:=ChildNode.PaddingRight+ChildNode.BorderRight+ChildNode.MarginRight;
-  FrameTop:=ChildNode.MarginTop+ChildNode.BorderTop+ChildNode.PaddingTop;
-  FrameBottom:=ChildNode.PaddingBottom+ChildNode.BorderBottom+ChildNode.MarginBottom;
   if IsNan(NewLeft) then
   if IsNan(NewLeft) then
   begin
   begin
     if IsNan(aMaxWidth) or IsNan(NewRight) then
     if IsNan(aMaxWidth) or IsNan(NewRight) then
@@ -2095,6 +2112,13 @@ begin
     else
     else
       NewLeft:=aMaxWidth-NewRight-NewWidth-FrameLeft-FrameRight;
       NewLeft:=aMaxWidth-NewRight-NewWidth-FrameLeft-FrameRight;
   end;
   end;
+  if IsNan(NewRight) then
+  begin
+    if IsNan(aMaxWidth) then
+      NewRight:=0
+    else
+      NewRight:=aMaxWidth-NewWidth-FrameLeft-FrameRight-NewLeft;
+  end;
   if IsNan(NewTop) then
   if IsNan(NewTop) then
   begin
   begin
     if IsNan(aMaxHeight) or IsNan(NewBottom) then
     if IsNan(aMaxHeight) or IsNan(NewBottom) then
@@ -2104,9 +2128,7 @@ begin
   end;
   end;
 
 
   // compute right, bottom of marginbox
   // compute right, bottom of marginbox
-  Result.Width:=FrameLeft+NewWidth+FrameRight;
-  if not IsNan(NewLeft) then
-    Result.Width:=Result.Width+NewLeft;
+  Result.Width:=NewLeft+FrameLeft+NewWidth+FrameRight;
   if not IsNan(NewRight) then
   if not IsNan(NewRight) then
     Result.Width:=Result.Width+NewRight;
     Result.Width:=Result.Width+NewRight;
   Result.ScrollWidth:=Result.Width;
   Result.ScrollWidth:=Result.Width;
@@ -2143,19 +2165,26 @@ begin
     ChildNode.Width:=NewWidth;
     ChildNode.Width:=NewWidth;
     ChildNode.Height:=NewHeight;
     ChildNode.Height:=NewHeight;
 
 
+    // used borderbox
     r.Left:=NewLeft+ChildNode.MarginLeft;
     r.Left:=NewLeft+ChildNode.MarginLeft;
     r.Top:=NewTop+ChildNode.MarginTop;
     r.Top:=NewTop+ChildNode.MarginTop;
     r.Right:=NewLeft+FrameLeft+NewWidth+FrameRight-ChildNode.MarginRight;
     r.Right:=NewLeft+FrameLeft+NewWidth+FrameRight-ChildNode.MarginRight;
     r.Bottom:=NewTop+FrameTop+NewHeight+FrameBottom-ChildNode.MarginBottom;
     r.Bottom:=NewTop+FrameTop+NewHeight+FrameBottom-ChildNode.MarginBottom;
     ChildEl.UsedBorderBox:=r;
     ChildEl.UsedBorderBox:=r;
 
 
+    // used clientbox
+    r.Left:=r.Left+ChildNode.PaddingLeft;
+    r.Right:=r.Right-ChildNode.PaddingRight;
+    r.Top:=r.Top+ChildNode.PaddingTop;
+    r.Bottom:=r.Bottom-ChildNode.PaddingBottom;
+    ChildEl.UsedClientBox:=r;
+
     // used contentbox
     // used contentbox
     r.Left:=NewLeft+FrameLeft;
     r.Left:=NewLeft+FrameLeft;
     r.Top:=NewTop+FrameTop;
     r.Top:=NewTop+FrameTop;
     r.Right:=r.Left+NewWidth;
     r.Right:=r.Left+NewWidth;
     r.Bottom:=R.Top+NewHeight;
     r.Bottom:=R.Top+NewHeight;
     ChildEl.UsedContentBox:=r;
     ChildEl.UsedContentBox:=r;
-    ChildEl.UsedClientBox:=r;
 
 
     {$IFDEF VerboseFresnelPlacing}
     {$IFDEF VerboseFresnelPlacing}
     writeln('TFLLineLayouter.PlaceAbsoluteItem '+ChildEl.GetPath+' BorderBox='+ChildEl.UsedBorderBox.ToString);
     writeln('TFLLineLayouter.PlaceAbsoluteItem '+ChildEl.GetPath+' BorderBox='+ChildEl.UsedBorderBox.ToString);

+ 2 - 2
src/base/fresnel.renderer.pas

@@ -591,7 +591,7 @@ end;
 
 
 procedure TRendererScrollBar.Draw(Renderer: TFresnelRenderer);
 procedure TRendererScrollBar.Draw(Renderer: TFresnelRenderer);
 var
 var
-  FromPos, ToPos, l, RadiusX, RadiusY: TFresnelLength;
+  RadiusX, RadiusY: TFresnelLength;
   r: TFresnelRect;
   r: TFresnelRect;
   ThumbR: TFresnelRoundRect;
   ThumbR: TFresnelRoundRect;
   c: TFresnelCSSCorner;
   c: TFresnelCSSCorner;
@@ -699,7 +699,7 @@ end;
 
 
 function TRendererScrollBar.GetHit(const X, Y: TFresnelLength; out aPosition: TFresnelLength): TSBHit;
 function TRendererScrollBar.GetHit(const X, Y: TFresnelLength; out aPosition: TFresnelLength): TSBHit;
 var
 var
-  LT, RB, l: TFresnelLength;
+  l: TFresnelLength;
 begin
 begin
   Result:=TSBHit.hNone;
   Result:=TSBHit.hNone;
   aPosition:=0;
   aPosition:=0;

+ 0 - 2
src/base/fresnel.textlayouter.pas

@@ -224,8 +224,6 @@ Type
   end;
   end;
   TTextBlockClass = Class of TTextBlock;
   TTextBlockClass = Class of TTextBlock;
 
 
-  { FTextBlockList }
-
   { TTextBlockList }
   { TTextBlockList }
 
 
   TTextBlockList = Class(TFPObjectList)
   TTextBlockList = Class(TFPObjectList)

+ 2 - 0
src/base/fresnelbase.lpk

@@ -16,6 +16,8 @@
       </Parsing>
       </Parsing>
       <Linking>
       <Linking>
         <Debugging>
         <Debugging>
+          <GenerateDebugInfo Value="False"/>
+          <RunWithoutDebug Value="True"/>
           <DebugInfoType Value="dsDwarf3"/>
           <DebugInfoType Value="dsDwarf3"/>
         </Debugging>
         </Debugging>
       </Linking>
       </Linking>

+ 2 - 0
src/fresnel.lpk

@@ -74,6 +74,8 @@ end;"/>
       </Parsing>
       </Parsing>
       <Linking>
       <Linking>
         <Debugging>
         <Debugging>
+          <GenerateDebugInfo Value="False"/>
+          <RunWithoutDebug Value="True"/>
           <DebugInfoType Value="dsDwarf3"/>
           <DebugInfoType Value="dsDwarf3"/>
         </Debugging>
         </Debugging>
       </Linking>
       </Linking>

+ 101 - 14
tests/base/TCFresnelCSS.pas

@@ -27,12 +27,18 @@ type
   TTestFont = class(TInterfacedObject,IFresnelFont)
   TTestFont = class(TInterfacedObject,IFresnelFont)
   public
   public
     Desc: TFresnelFontDesc;
     Desc: TFresnelFontDesc;
+    function GetAlternates: string;
+    function GetCaps: TFresnelCSSFontVarCaps;
     function GetDescription: String;
     function GetDescription: String;
+    function GetEastAsians: TFresnelCSSFontVarEastAsians;
+    function GetEmoji: TFresnelCSSFontVarEmoji;
     function GetFamily: string;
     function GetFamily: string;
     function GetKerning: TFresnelCSSKerning;
     function GetKerning: TFresnelCSSKerning;
+    function GetLigatures: TFresnelCSSFontVarLigaturesSet;
+    function GetNumerics: TFresnelCSSFontVarNumerics;
+    function GetPosition: TFresnelCSSFontVarPosition;
     function GetSize: double;
     function GetSize: double;
     function GetStyle: string;
     function GetStyle: string;
-    function GetVariant: string;
     function GetWidth: double;
     function GetWidth: double;
     function GetWeight: double;
     function GetWeight: double;
     function TextSize(const aText: string): TFresnelPoint;
     function TextSize(const aText: string): TFresnelPoint;
@@ -56,13 +62,21 @@ type
   { TTestRenderer }
   { TTestRenderer }
 
 
   TTestRenderer = class(TFresnelRenderer)
   TTestRenderer = class(TFresnelRenderer)
+  protected
+    FSavedContexts: TFresnelRectDynArray;
   public
   public
+    ClipR: TFresnelRect;
     procedure Arc(const aColor: TFPColor; const aCenter, aRadii: TFresnelPoint;
     procedure Arc(const aColor: TFPColor; const aCenter, aRadii: TFresnelPoint;
-      aStartAngle: TFresnelLength=0; aStopAngle: TFresnelLength=DoublePi); override;
+      aStartAngle: TFresnelLength=0; aStopAngle: TFresnelLength=Tau); override;
+    procedure ClipRect(const aRect: TFresnelRect); override;
     procedure FillRect(const aColor: TFPColor; const aRect: TFresnelRect); override;
     procedure FillRect(const aColor: TFPColor; const aRect: TFresnelRect); override;
     procedure Line(const aColor: TFPColor; const x1, y1, x2, y2: TFresnelLength); override;
     procedure Line(const aColor: TFPColor; const x1, y1, x2, y2: TFresnelLength); override;
+    procedure Polygon(const aColor: TFPColor; const p: PFresnelPoint;
+      Count: integer); override;
+    procedure Restore; override;
     procedure RoundRect(const aColor: TFPColor; const aRect: TFresnelRoundRect; Fill: Boolean);
     procedure RoundRect(const aColor: TFPColor; const aRect: TFresnelRoundRect; Fill: Boolean);
       override;
       override;
+    procedure Save; override;
     procedure TextOut(const aLeft, aTop: TFresnelLength;
     procedure TextOut(const aLeft, aTop: TFresnelLength;
       const aFont: IFresnelFont; const aColor: TFPColor;
       const aFont: IFresnelFont; const aColor: TFPColor;
       const aText: string); override;
       const aText: string); override;
@@ -74,6 +88,7 @@ type
 
 
   TTestViewport = class(TFresnelViewport)
   TTestViewport = class(TFresnelViewport)
   private
   private
+    fDrawing: Boolean;
     FLayoutQueued: boolean;
     FLayoutQueued: boolean;
     FRenderer: TFresnelRenderer;
     FRenderer: TFresnelRenderer;
   protected
   protected
@@ -84,6 +99,7 @@ type
     destructor Destroy; override;
     destructor Destroy; override;
     procedure DomChanged; override;
     procedure DomChanged; override;
     procedure Draw; virtual;
     procedure Draw; virtual;
+    function IsDrawing: boolean; override;
     property LayoutQueued: boolean read FLayoutQueued write FLayoutQueued;
     property LayoutQueued: boolean read FLayoutQueued write FLayoutQueued;
     property Renderer: TFresnelRenderer read FRenderer write FRenderer;
     property Renderer: TFresnelRenderer read FRenderer write FRenderer;
   end;
   end;
@@ -302,11 +318,46 @@ begin
   Result:=Desc.Family;
   Result:=Desc.Family;
 end;
 end;
 
 
+function TTestFont.GetAlternates: string;
+begin
+  Result:='';
+end;
+
+function TTestFont.GetCaps: TFresnelCSSFontVarCaps;
+begin
+  Result:=ffvcNormal;
+end;
+
+function TTestFont.GetEastAsians: TFresnelCSSFontVarEastAsians;
+begin
+  Result:=[ffveaNormal];
+end;
+
+function TTestFont.GetEmoji: TFresnelCSSFontVarEmoji;
+begin
+  Result:=ffveNormal;
+end;
+
 function TTestFont.GetKerning: TFresnelCSSKerning;
 function TTestFont.GetKerning: TFresnelCSSKerning;
 begin
 begin
   Result:=Desc.Kerning;
   Result:=Desc.Kerning;
 end;
 end;
 
 
+function TTestFont.GetLigatures: TFresnelCSSFontVarLigaturesSet;
+begin
+  Result:=[ffvlNormal];
+end;
+
+function TTestFont.GetNumerics: TFresnelCSSFontVarNumerics;
+begin
+  Result:=[ffvnNormal];
+end;
+
+function TTestFont.GetPosition: TFresnelCSSFontVarPosition;
+begin
+  Result:=ffvpNormal;
+end;
+
 function TTestFont.GetSize: double;
 function TTestFont.GetSize: double;
 begin
 begin
   Result:=Desc.Size;
   Result:=Desc.Size;
@@ -317,11 +368,6 @@ begin
   Result:=Desc.Style;
   Result:=Desc.Style;
 end;
 end;
 
 
-function TTestFont.GetVariant: string;
-begin
-  Result:=Desc.Variant_;
-end;
-
 function TTestFont.GetWidth: double;
 function TTestFont.GetWidth: double;
 begin
 begin
   Result:=Desc.Width;
   Result:=Desc.Width;
@@ -463,6 +509,11 @@ begin
   if aStopAngle=0 then;
   if aStopAngle=0 then;
 end;
 end;
 
 
+procedure TTestRenderer.ClipRect(const aRect: TFresnelRect);
+begin
+  ClipR:=aRect;
+end;
+
 procedure TTestRenderer.FillRect(const aColor: TFPColor;
 procedure TTestRenderer.FillRect(const aColor: TFPColor;
   const aRect: TFresnelRect);
   const aRect: TFresnelRect);
 begin
 begin
@@ -477,6 +528,25 @@ begin
   if x1+y1+x2+y2=0 then ;
   if x1+y1+x2+y2=0 then ;
 end;
 end;
 
 
+procedure TTestRenderer.Polygon(const aColor: TFPColor; const p: PFresnelPoint;
+  Count: integer);
+begin
+  if aColor=colBlack then ;
+  if Count=0 then ;
+  if p=nil then ;
+end;
+
+procedure TTestRenderer.Restore;
+var
+  l: SizeInt;
+begin
+  l:=Length(FSavedContexts)-1;
+  if l<0 then
+    raise Exception.Create('20250429101125 TTestRenderer.Restore');
+  ClipR:=FSavedContexts[l];
+  SetLength(FSavedContexts,l);
+end;
+
 procedure TTestRenderer.RoundRect(const aColor: TFPColor; const aRect: TFresnelRoundRect;
 procedure TTestRenderer.RoundRect(const aColor: TFPColor; const aRect: TFresnelRoundRect;
   Fill: Boolean);
   Fill: Boolean);
 begin
 begin
@@ -485,6 +555,15 @@ begin
   if Fill then;
   if Fill then;
 end;
 end;
 
 
+procedure TTestRenderer.Save;
+var
+  l: SizeInt;
+begin
+  l:=Length(FSavedContexts);
+  SetLength(FSavedContexts,l+1);
+  FSavedContexts[l]:=ClipR;
+end;
+
 procedure TTestRenderer.TextOut(const aLeft, aTop: TFresnelLength;
 procedure TTestRenderer.TextOut(const aLeft, aTop: TFresnelLength;
   const aFont: IFresnelFont; const aColor: TFPColor; const aText: string);
   const aFont: IFresnelFont; const aColor: TFPColor; const aText: string);
 begin
 begin
@@ -527,6 +606,7 @@ begin
   TViewportLayouter(Layouter).Viewport:=Self;
   TViewportLayouter(Layouter).Viewport:=Self;
   FontEngine:=TTestFontEngine.Create(Self);
   FontEngine:=TTestFontEngine.Create(Self);
   Renderer:=TTestRenderer.Create(Self);
   Renderer:=TTestRenderer.Create(Self);
+  DomChanged;
 end;
 end;
 
 
 destructor TTestViewport.Destroy;
 destructor TTestViewport.Destroy;
@@ -548,6 +628,9 @@ end;
 procedure TTestViewport.Draw;
 procedure TTestViewport.Draw;
 begin
 begin
   //debugln(['TTestViewport.WSDraw ',DbgSName(Self),' ',DbgSName(Renderer)]);
   //debugln(['TTestViewport.WSDraw ',DbgSName(Self),' ',DbgSName(Renderer)]);
+  if fDrawing then
+    raise Exception.Create('20250429140551');
+  fDrawing:=true;
   if LayoutQueued then
   if LayoutQueued then
   begin
   begin
     LayoutQueued:=false;
     LayoutQueued:=false;
@@ -555,6 +638,12 @@ begin
     //Layouter.WriteLayoutTree;
     //Layouter.WriteLayoutTree;
   end;
   end;
   Renderer.Draw(Self);
   Renderer.Draw(Self);
+  fDrawing:=false;
+end;
+
+function TTestViewport.IsDrawing: boolean;
+begin
+  Result:=fDrawing;
 end;
 end;
 
 
 { TCustomTestFresnelCSS }
 { TCustomTestFresnelCSS }
@@ -575,18 +664,20 @@ end;
 
 
 procedure TTestFresnelCSS.TestEmptyViewport;
 procedure TTestFresnelCSS.TestEmptyViewport;
 begin
 begin
-  Viewport.Draw;
+  Viewport.ApplyCSS;
 end;
 end;
 
 
 procedure TTestFresnelCSS.TestBody;
 procedure TTestFresnelCSS.TestBody;
 var
 var
   Body: TBody;
   Body: TBody;
 begin
 begin
+  writeln('TTestFresnelCSS.TestBody START');
   Body:=TBody.Create(Viewport);
   Body:=TBody.Create(Viewport);
   Body.Name:='Body';
   Body.Name:='Body';
   Body.Parent:=Viewport;
   Body.Parent:=Viewport;
-  Viewport.Draw;
+  Viewport.ApplyCSS;
   //Body.WriteComputedAttributes('Body');
   //Body.WriteComputedAttributes('Body');
+  writeln('TTestFresnelCSS.TestBody END');
 end;
 end;
 
 
 procedure TTestFresnelCSS.TestGetStyleAttr_OneValue;
 procedure TTestFresnelCSS.TestGetStyleAttr_OneValue;
@@ -773,7 +864,6 @@ begin
     'font-style:italic;',
     'font-style:italic;',
     'font-weight:250;',
     'font-weight:250;',
     'font-width:condensed;',
     'font-width:condensed;',
-    'font-variant:normal;',
     'line-height:20px;',
     'line-height:20px;',
     '}']);
     '}']);
   Body:=TBody.Create(Viewport);
   Body:=TBody.Create(Viewport);
@@ -801,9 +891,6 @@ begin
   AssertEquals('Body.GetComputedString(fcaFontWidth)','75%',Body.GetComputedString(fcaFontWidth));
   AssertEquals('Body.GetComputedString(fcaFontWidth)','75%',Body.GetComputedString(fcaFontWidth));
   AssertEquals('Body.GetComputedString(fcaFontStretch)','75%',Body.GetComputedString(fcaFontStretch));
   AssertEquals('Body.GetComputedString(fcaFontStretch)','75%',Body.GetComputedString(fcaFontStretch));
 
 
-  AssertEquals('Body.Font.GetVariant','normal',Body.Font.GetVariant);
-  AssertEquals('Body.GetComputedString(fcaFontVariant)','normal',Body.GetComputedString(fcaFontVariant));
-
   AssertEquals('Body.GetComputedString(fcaFont)','italic 250 12px/20px condensed Arial',Body.GetComputedString(fcaFont));
   AssertEquals('Body.GetComputedString(fcaFont)','italic 250 12px/20px condensed Arial',Body.GetComputedString(fcaFont));
 end;
 end;
 
 
@@ -822,7 +909,7 @@ begin
   Viewport.ApplyCSS;
   Viewport.ApplyCSS;
   AssertEquals('Body.GetComputedString(fcaOverflowX)','visible',Body.GetComputedString(fcaOverflowX));
   AssertEquals('Body.GetComputedString(fcaOverflowX)','visible',Body.GetComputedString(fcaOverflowX));
   AssertEquals('Body.GetComputedString(fcaOverflowY)','hidden',Body.GetComputedString(fcaOverflowY));
   AssertEquals('Body.GetComputedString(fcaOverflowY)','hidden',Body.GetComputedString(fcaOverflowY));
-  AssertEquals('Body.GetComputedString(fcaOverflow)','visible hidden',Body.GetComputedString(fcaOverflow));
+  AssertEquals('Body.GetComputedString(fcaOverflow)','auto hidden',Body.GetComputedString(fcaOverflow));
 end;
 end;
 
 
 procedure TTestFresnelCSS.Test_BorderColor_AsString;
 procedure TTestFresnelCSS.Test_BorderColor_AsString;

+ 1 - 0
tests/exploration/scroll/.gitignore

@@ -1 +1,2 @@
 ScrollWheelTest1
 ScrollWheelTest1
+ScrollWheelTestLCL1

BIN
tests/exploration/scroll/ScrollWheelTestLCL1.ico


+ 77 - 0
tests/exploration/scroll/ScrollWheelTestLCL1.lpi

@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="12"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <Title Value="ScrollWheelTestLCL1"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <XPManifest>
+        <DpiAware Value="True"/>
+      </XPManifest>
+      <Icon Value="0"/>
+    </General>
+    <BuildModes>
+      <Item Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <UseFileFilters Value="True"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+    </RunParams>
+    <RequiredPackages>
+      <Item>
+        <PackageName Value="FresnelDemoComps"/>
+        <DefaultFilename Value="../../../demo/democomps/fresneldemocomps.lpk" Prefer="True"/>
+      </Item>
+      <Item>
+        <PackageName Value="FresnelLCL"/>
+        <DefaultFilename Value="../../../src/lcl/fresnellcl.lpk" Prefer="True"/>
+      </Item>
+    </RequiredPackages>
+    <Units>
+      <Unit>
+        <Filename Value="ScrollWheelTestLCL1.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="ScrollWheelTestLCL1"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Linking>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions>
+      <Item>
+        <Name Value="EAbort"/>
+      </Item>
+      <Item>
+        <Name Value="ECodetoolError"/>
+      </Item>
+      <Item>
+        <Name Value="EFOpenError"/>
+      </Item>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 82 - 0
tests/exploration/scroll/ScrollWheelTestLCL1.lpr

@@ -0,0 +1,82 @@
+program ScrollWheelTestLCL1;
+
+{$mode objfpc}{$H+}
+
+uses
+  {$IFDEF UNIX}
+  cthreads,
+  {$ENDIF}
+  Interfaces, // this includes the LCL widgetset
+  Fresnel, // initializes the widgetset
+  Classes, SysUtils, Fresnel.Forms, Fresnel.Controls, Fresnel.Events,
+  FCL.Events, Fresnel.Classes, Forms;
+
+type
+
+  { TMainForm }
+
+  TMainForm = class(TFresnelForm)
+    Body: TBody;
+    HeaderLabel: TLabel;
+    BlaLabel: TLabel;
+  public
+    constructor CreateNew(AOwner: TComponent); override;
+  end;
+
+{ TMainForm }
+
+constructor TMainForm.CreateNew(AOwner: TComponent);
+begin
+  inherited CreateNew(AOwner);
+  Name:='MainForm';
+
+  FormBounds:=BoundsRectFre(100,100,200,150);
+
+  Stylesheet.Text:=''
+    +'div {'+LineEnding
+    +'  border: 2px solid blue;'
+    +'  padding: 10px;'
+    +'}'+LineEnding;
+
+  Body:=TBody.Create(Self);
+  with Body do begin
+    Name:='Body';
+    Style:='border: 1px solid green;';
+    Parent:=Self;
+  end;
+
+  HeaderLabel:=TLabel.Create(Self);
+  with HeaderLabel do begin
+    Name:='HeaderLabel';
+    Style:='border: 1px solid red;';
+    Caption:='Fresnel is a visual component library based on CSS and custom drawn components';
+    Parent:=Body;
+  end;
+
+  BlaLabel:=TLabel.Create(Self);
+  with BlaLabel do begin
+    Name:='BlaLabel';
+    Style:='border: 1px solid blue; position: absolute; right: 1px;';
+    Caption:='Bla';
+    Parent:=Body;
+  end;
+
+  Visible:=true;
+end;
+
+var
+  MainForm: TMainForm;
+
+{$R *.res}
+
+begin
+  RequireDerivedFormResource:=True;
+  Application.Scaled:=True;
+  {$PUSH}{$WARN 5044 OFF}
+  Application.MainFormOnTaskbar:=True;
+  {$POP}
+  Application.Initialize;
+  Application.CreateForm(TMainForm, MainForm);
+  Application.Run;
+end.
+

BIN
tests/exploration/scroll/ScrollWheelTestLCL1.res