[LayoutReloaded] Move statically positioned absolute box positioning to _computeOutOf...
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 19 Mar 2018 22:58:10 +0000 (22:58 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 19 Mar 2018 22:58:10 +0000 (22:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=183750

Reviewed by Antti Koivisto.

* LayoutReloaded/DisplayTree/Box.js:
(Display.Box.prototype.setTop):
(Display.Box.prototype.paddingBox):
(Display.Box.prototype.contentBox):
(Display.Box):
* LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js:
(BlockFormattingContext.prototype._computeStaticPosition):
(BlockFormattingContext.prototype._layoutOutOfFlowDescendants):
(BlockFormattingContext.prototype._computeOutOfFlowPosition):
* LayoutReloaded/FormattingContext/FormattingContext.js:
(FormattingContext.prototype.absoluteMarginBox):
(FormattingContext.prototype.absoluteBorderBox):
(FormattingContext.prototype.absolutePaddingBox):
(FormattingContext.prototype.absoluteContentBox):
(FormattingContext.prototype._toAbsolutePosition):
(FormattingContext.prototype._toRootAbsolutePosition):
(FormattingContext.prototype.toDisplayBox):
* LayoutReloaded/LayoutTree/InitialBlockContainer.js:
(Layout.InitialBlockContainer.prototype.establishesBlockFormattingContext):
(Layout.InitialBlockContainer):
(Layout.InitialBlockContainer.prototype.paddingBox): Deleted.
(Layout.InitialBlockContainer.prototype.contentBox): Deleted.
* LayoutReloaded/Utils.js:
(Utils.isStaticallyPositioned):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@229725 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/LayoutReloaded/DisplayTree/Box.js
Tools/LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js
Tools/LayoutReloaded/FormattingContext/FormattingContext.js
Tools/LayoutReloaded/LayoutTree/InitialBlockContainer.js
Tools/LayoutReloaded/Utils.js

index b546dda..05ab62a 100644 (file)
@@ -1,3 +1,35 @@
+2018-03-19  Zalan Bujtas  <zalan@apple.com>
+
+        [LayoutReloaded] Move statically positioned absolute box positioning to _computeOutOfFlowPosition
+        https://bugs.webkit.org/show_bug.cgi?id=183750
+
+        Reviewed by Antti Koivisto.
+
+        * LayoutReloaded/DisplayTree/Box.js:
+        (Display.Box.prototype.setTop):
+        (Display.Box.prototype.paddingBox):
+        (Display.Box.prototype.contentBox):
+        (Display.Box):
+        * LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js:
+        (BlockFormattingContext.prototype._computeStaticPosition):
+        (BlockFormattingContext.prototype._layoutOutOfFlowDescendants):
+        (BlockFormattingContext.prototype._computeOutOfFlowPosition):
+        * LayoutReloaded/FormattingContext/FormattingContext.js:
+        (FormattingContext.prototype.absoluteMarginBox):
+        (FormattingContext.prototype.absoluteBorderBox):
+        (FormattingContext.prototype.absolutePaddingBox):
+        (FormattingContext.prototype.absoluteContentBox):
+        (FormattingContext.prototype._toAbsolutePosition):
+        (FormattingContext.prototype._toRootAbsolutePosition):
+        (FormattingContext.prototype.toDisplayBox):
+        * LayoutReloaded/LayoutTree/InitialBlockContainer.js:
+        (Layout.InitialBlockContainer.prototype.establishesBlockFormattingContext):
+        (Layout.InitialBlockContainer):
+        (Layout.InitialBlockContainer.prototype.paddingBox): Deleted.
+        (Layout.InitialBlockContainer.prototype.contentBox): Deleted.
+        * LayoutReloaded/Utils.js:
+        (Utils.isStaticallyPositioned):
+
 2018-03-19  Chris Dumez  <cdumez@apple.com>
 
         WebKit.WebsitePoliciesAutoplayQuirks API test times out with async policy delegates
index 991ee64..67ef0a6 100644 (file)
@@ -75,6 +75,10 @@ Display.Box = class Box {
         this.m_rect.setTopLeft(topLeft);
     }
 
+    setTop(top) {
+        this.m_rect.setTop(top);
+    }
+
     setSize(size) {
         this.m_rect.setSize(size);
     }
@@ -92,6 +96,9 @@ Display.Box = class Box {
     }
 
     paddingBox() {
+        // ICB does not have associated node.
+        if (!this.m_node)
+            return this.borderBox();
         let paddingBox = this.borderBox();
         let borderSize = Utils.computedBorderTopLeft(this.m_node);
         paddingBox.moveBy(borderSize);
@@ -101,6 +108,9 @@ Display.Box = class Box {
     }
 
     contentBox() {
+        // ICB does not have associated node.
+        if (!this.m_node)
+            return this.borderBox();
         let contentBox = this.paddingBox();
         let paddingSize = Utils.computedPaddingTopLeft(this.m_node);
         contentBox.moveBy(paddingSize);
index 8db2213..0bb1273 100644 (file)
@@ -109,13 +109,13 @@ class BlockFormattingContext extends FormattingContext {
         // In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block.
         // The vertical distance between two sibling boxes is determined by the 'margin' properties.
         // Vertical margins between adjacent block-level boxes in a block formatting context collapse.
-        let parent = layoutBox.parent();
+        let containingBlockContentBox = this.toDisplayBox(layoutBox.containingBlock()).contentBox();
         // Start from the top of the container's content box.
         let previousInFlowSibling = layoutBox.previousInFlowSibling();
-        let contentBottom = parent.contentBox().top()
+        let contentBottom = containingBlockContentBox.top()
         if (previousInFlowSibling)
-            contentBottom = this.toDisplayBox(previousInFlowSibling).bottomRight().top() + this.marginBottom(previousInFlowSibling);
-        let position = new LayoutPoint(contentBottom, parent.contentBox().left());
+            contentBottom = this.toDisplayBox(previousInFlowSibling).bottom() + this.marginBottom(previousInFlowSibling);
+        let position = new LayoutPoint(contentBottom, containingBlockContentBox.left());
         position.moveBy(new LayoutSize(this.marginLeft(layoutBox), this.marginTop(layoutBox)));
         this.toDisplayBox(layoutBox).setTopLeft(position);
     }
@@ -141,7 +141,6 @@ class BlockFormattingContext extends FormattingContext {
         for (let outOfFlowBox of outOfFlowDescendants) {
             this._addToLayoutQueue(outOfFlowBox);
             this.computeWidth(outOfFlowBox);
-            this._computeStaticPosition(outOfFlowBox);
             layoutContext.layoutFormattingContext(outOfFlowBox.establishedFormattingContext());
             this.computeHeight(outOfFlowBox);
             this._computeOutOfFlowPosition(outOfFlowBox);
@@ -312,12 +311,21 @@ class BlockFormattingContext extends FormattingContext {
 
     _computeOutOfFlowPosition(layoutBox) {
         let displayBox = this.toDisplayBox(layoutBox);
+        let top = Number.NaN;
         let containerSize = layoutBox.containingBlock().contentBox().size();
         // Top/bottom
-        let top = Number.NaN;
         if (Utils.isTopAuto(layoutBox) && Utils.isBottomAuto(layoutBox)) {
-            // Convert static position to absolute.
-            top = this._toAbsolutePosition(layoutBox).top();
+            ASSERT(Utils.isStaticallyPositioned(layoutBox));
+            // Vertically statically positioned.
+            // FIXME: Figure out if it is actually valid that we use the parent box as the container (which is not even in this formatting context).
+            let parent = layoutBox.parent();
+            let parentDisplayBox = parent.displayBox();
+            let previousInFlowSibling = layoutBox.previousInFlowSibling();
+            let contentBottom = previousInFlowSibling ? previousInFlowSibling.displayBox().bottom() : parentDisplayBox.contentBox().top();
+            top = contentBottom + this.marginTop(layoutBox);
+            // Convert static position (in parent coordinate system) to absolute (in containing block coordindate system).
+            if (parent != layoutBox.containingBlock())
+                top += this._toAbsolutePosition(parentDisplayBox.topLeft(), parent, layoutBox.containingBlock()).top();
         } else if (!Utils.isTopAuto(layoutBox))
             top = Utils.top(layoutBox) + this.marginTop(layoutBox);
         else if (!Utils.isBottomAuto(layoutBox))
@@ -327,8 +335,15 @@ class BlockFormattingContext extends FormattingContext {
         // Left/right
         let left = Number.NaN;
         if (Utils.isLeftAuto(layoutBox) && Utils.isRightAuto(layoutBox)) {
-            // Convert static position to absolute.
-            left = this._toAbsolutePosition(layoutBox).left();
+            ASSERT(Utils.isStaticallyPositioned(layoutBox));
+            // Horizontally statically positioned.
+            // FIXME: Figure out if it is actually valid that we use the parent box as the container (which is not even in this formatting context).
+            let parent = layoutBox.parent();
+            let parentDisplayBox = parent.displayBox();
+            left = parentDisplayBox.contentBox().left() + this.marginLeft(layoutBox);
+            // Convert static position (in parent coordinate system) to absolute (in containing block coordindate system).
+            if (parent != layoutBox.containingBlock())
+                left += this._toAbsolutePosition(parentDisplayBox.rect(), parent, layoutBox.containingBlock()).left();
         } else if (!Utils.isLeftAuto(layoutBox))
             left = Utils.left(layoutBox) + this.marginLeft(layoutBox);
         else if (!Utils.isRightAuto(layoutBox))
index 767148f..dd42cf7 100644 (file)
@@ -66,7 +66,8 @@ class FormattingContext {
     }
 
     absoluteMarginBox(layoutBox) {
-        let absoluteContentBox = this._toRootAbsolutePosition(layoutBox);
+        let displayBox = this.toDisplayBox(layoutBox);
+        let absoluteContentBox = new LayoutRect(this._toRootAbsolutePosition(layoutBox), displayBox.size());
         absoluteContentBox.moveBy(new LayoutSize(-this.marginLeft(layoutBox), -this.marginTop(layoutBox)));
         absoluteContentBox.growBy(new LayoutSize(this.marginLeft(layoutBox) + this.marginRight(layoutBox), this.marginTop(layoutBox) + this.marginBottom(layoutBox)));
         return absoluteContentBox;
@@ -74,51 +75,42 @@ class FormattingContext {
 
     absoluteBorderBox(layoutBox) {
         let borderBox = layoutBox.borderBox();
-        let absoluteRect = new LayoutRect(this._toRootAbsolutePosition(layoutBox).topLeft(), borderBox.size());
+        let absoluteRect = new LayoutRect(this._toRootAbsolutePosition(layoutBox), borderBox.size());
         absoluteRect.moveBy(borderBox.topLeft());
         return absoluteRect;
     }
 
     absolutePaddingBox(layoutBox) {
         let paddingBox = layoutBox.paddingBox();
-        let absoluteRect = new LayoutRect(this._toRootAbsolutePosition(layoutBox).topLeft(), paddingBox.size());
+        let absoluteRect = new LayoutRect(this._toRootAbsolutePosition(layoutBox), paddingBox.size());
         absoluteRect.moveBy(paddingBox.topLeft());
         return absoluteRect;
     }
 
     absoluteContentBox(layoutBox) {
         let contentBox = layoutBox.contentBox();
-        let absoluteRect = new LayoutRect(this._toRootAbsolutePosition(layoutBox).topLeft(), contentBox.size());
+        let absoluteRect = new LayoutRect(this._toRootAbsolutePosition(layoutBox), contentBox.size());
         absoluteRect.moveBy(contentBox.topLeft());
         return absoluteRect;
     }
 
-    _toAbsolutePosition(layoutBox) {
+    _toAbsolutePosition(position, layoutBox, container) {
         // We should never need to go beyond the root container.
-        let containingBlock = layoutBox.containingBlock();
-        ASSERT(containingBlock == this.rootContainer() || containingBlock.isDescendantOf(this.rootContainer()));
-        let topLeft = this.toDisplayBox(layoutBox).topLeft();
-        let ascendant = layoutBox.parent();
-        while (ascendant && ascendant != containingBlock) {
-            topLeft.moveBy(this.toDisplayBox(ascendant).topLeft());
-            ascendant = ascendant.parent();
+        ASSERT(container == this.rootContainer() || container.isDescendantOf(this.rootContainer()));
+        let absolutePosition = position;
+        let ascendant = layoutBox.containingBlock();
+        while (ascendant && ascendant != container) {
+            ASSERT(ascendant.isDescendantOf(this.rootContainer()));
+            absolutePosition.moveBy(this.toDisplayBox(ascendant).topLeft());
+            ascendant = ascendant.containingBlock();
         }
-        return new LayoutRect(topLeft, this.toDisplayBox(layoutBox).size());
+        return absolutePosition;
     }
 
     _toRootAbsolutePosition(layoutBox) {
-        let displayBox = this.toDisplayBox(layoutBox);
-        let topLeft = displayBox.topLeft();
-        let ascendant = layoutBox.parent();
-        while (ascendant && ascendant != this.rootContainer()) {
-            topLeft.moveBy(this.toDisplayBox(ascendant).topLeft());
-            ascendant = ascendant.parent();
-        }
-        ASSERT(ascendant);
-        return new LayoutRect(topLeft, displayBox.size());
+        return this._toAbsolutePosition(this.toDisplayBox(layoutBox).topLeft(), layoutBox, this.rootContainer());
     }
 
-
     _descendantNeedsLayout() {
         return this.m_layoutStack.length;
     }
@@ -151,7 +143,9 @@ class FormattingContext {
 
     toDisplayBox(layoutBox) {
         ASSERT(layoutBox);
-        ASSERT(this.m_layoutToDisplay.has(layoutBox));
+        ASSERT(this.m_layoutToDisplay.has(layoutBox) || layoutBox.establishedFormattingContext() == this);
+        if (layoutBox.establishedFormattingContext() == this)
+            return layoutBox.displayBox();
         return this.m_layoutToDisplay.get(layoutBox);
     }
 
index 9f80f85..d36acee 100644 (file)
@@ -32,12 +32,4 @@ Layout.InitialBlockContainer = class InitialBlockContainer extends Layout.BlockC
         // ICB always creates a new (inital) block formatting context.
         return true;
     }
-
-    paddingBox() {
-        return this.borderBox();
-    }
-
-    contentBox() {
-        return this.borderBox();
-    }
 }
index abeb0ec..9e63f38 100644 (file)
@@ -452,6 +452,13 @@ class Utils {
         return window.getComputedStyle(node).position == "fixed";
     }
 
+    static isStaticallyPositioned(box) {
+        if (box.isAnonymous())
+            return true;
+        let node = box.node();
+        return (Utils.propertyIsAuto("top", box) && Utils.propertyIsAuto("bottom", box)) || (Utils.propertyIsAuto("left", box) && Utils.propertyIsAuto("right", box));
+    }
+
     static isOverflowVisible(box) {
         return window.getComputedStyle(box.node()).overflow == "visible";
     }