[LayoutReloaded] Introduce FloatingState.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Mar 2018 05:21:47 +0000 (05:21 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Mar 2018 05:21:47 +0000 (05:21 +0000)
https://bugs.webkit.org/show_bug.cgi?id=184126

Reviewed by Antti Koivisto.

It holds the floating state (left/right floating stack) for a given formatting state (Block or Inline).
(FormattingState -> FloatingState/FormattingContext -> FloatingContext)

* LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js:
(BlockFormattingContext):
* LayoutReloaded/FormattingContext/FloatingContext.js:
(FloatingContext):
(FloatingContext.prototype.computePosition):
(FloatingContext.prototype.bottom):
(FloatingContext.prototype._positionForFloating):
(FloatingContext.prototype._positionForClear):
(FloatingContext.prototype._findInnerMostLeftAndRight):
(FloatingContext.prototype._isEmpty):
(FloatingContext.prototype._floatingState):
(FloatingContext.prototype._formattingContext):
(FloatingContext.prototype._lastFloating):
(FloatingContext.prototype._leftFloatingStack):
(FloatingContext.prototype._rightFloatingStack):
(FloatingContext.prototype._addFloating): Deleted.
* LayoutReloaded/FormattingContext/FormattingContext.js:
(FormattingContext):
* LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js:
(InlineFormattingContext):
* LayoutReloaded/FormattingState/BlockFormattingState.js:
(BlockFormattingState):
* LayoutReloaded/FormattingState/FloatingState.js: Copied from Tools/LayoutReloaded/FormattingState/InlineFormattingState.js.
(FloatingState):
(FloatingState.prototype.addFloating):
(FloatingState.prototype.leftFloatingStack):
(FloatingState.prototype.rightFloatingStack):
(FloatingState.prototype.lastFloating):
(FloatingState.prototype.formattingContext):
* LayoutReloaded/FormattingState/FormattingState.js:
(FormattingState):
(FormattingState.prototype.floatingState):
* LayoutReloaded/FormattingState/InlineFormattingState.js:
(InlineFormattingState):
* LayoutReloaded/test/index.html:

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

Tools/ChangeLog
Tools/LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js
Tools/LayoutReloaded/FormattingContext/FloatingContext.js
Tools/LayoutReloaded/FormattingContext/FormattingContext.js
Tools/LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js
Tools/LayoutReloaded/FormattingState/BlockFormattingState.js
Tools/LayoutReloaded/FormattingState/FloatingState.js [new file with mode: 0644]
Tools/LayoutReloaded/FormattingState/FormattingState.js
Tools/LayoutReloaded/FormattingState/InlineFormattingState.js
Tools/LayoutReloaded/test/index.html

index 12ebc1d..00b8317 100644 (file)
@@ -1,5 +1,51 @@
 2018-03-28  Zalan Bujtas  <zalan@apple.com>
 
+        [LayoutReloaded] Introduce FloatingState.
+        https://bugs.webkit.org/show_bug.cgi?id=184126
+
+        Reviewed by Antti Koivisto.
+
+        It holds the floating state (left/right floating stack) for a given formatting state (Block or Inline).
+        (FormattingState -> FloatingState/FormattingContext -> FloatingContext)
+
+        * LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js:
+        (BlockFormattingContext):
+        * LayoutReloaded/FormattingContext/FloatingContext.js:
+        (FloatingContext):
+        (FloatingContext.prototype.computePosition):
+        (FloatingContext.prototype.bottom):
+        (FloatingContext.prototype._positionForFloating):
+        (FloatingContext.prototype._positionForClear):
+        (FloatingContext.prototype._findInnerMostLeftAndRight):
+        (FloatingContext.prototype._isEmpty):
+        (FloatingContext.prototype._floatingState):
+        (FloatingContext.prototype._formattingContext):
+        (FloatingContext.prototype._lastFloating):
+        (FloatingContext.prototype._leftFloatingStack):
+        (FloatingContext.prototype._rightFloatingStack):
+        (FloatingContext.prototype._addFloating): Deleted.
+        * LayoutReloaded/FormattingContext/FormattingContext.js:
+        (FormattingContext):
+        * LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js:
+        (InlineFormattingContext):
+        * LayoutReloaded/FormattingState/BlockFormattingState.js:
+        (BlockFormattingState):
+        * LayoutReloaded/FormattingState/FloatingState.js: Copied from Tools/LayoutReloaded/FormattingState/InlineFormattingState.js.
+        (FloatingState):
+        (FloatingState.prototype.addFloating):
+        (FloatingState.prototype.leftFloatingStack):
+        (FloatingState.prototype.rightFloatingStack):
+        (FloatingState.prototype.lastFloating):
+        (FloatingState.prototype.formattingContext):
+        * LayoutReloaded/FormattingState/FormattingState.js:
+        (FormattingState):
+        (FormattingState.prototype.floatingState):
+        * LayoutReloaded/FormattingState/InlineFormattingState.js:
+        (InlineFormattingState):
+        * LayoutReloaded/test/index.html:
+
+2018-03-28  Zalan Bujtas  <zalan@apple.com>
+
         [LayoutReloaded] Convert floating left/right stack display boxes absolute to the formatting context's root.
         https://bugs.webkit.org/show_bug.cgi?id=184123
 
index 2679b9d..4be0688 100644 (file)
@@ -25,8 +25,6 @@
 class BlockFormattingContext extends FormattingContext {
     constructor(blockFormattingState) {
         super(blockFormattingState);
-        // New block formatting context always establishes a new floating context.
-        this.m_floatingContext = new FloatingContext(this);
     }
 
     layout() {
index 5572d85..960e942 100644 (file)
 
 // All geometry here is absolute to the formatting context's root.
 class FloatingContext {
-    constructor(formattingContext) {
-        this.m_leftFloatingBoxStack = new Array();
-        this.m_rightFloatingBoxStack = new Array();
-        this.m_lastFloating = null;
-        this.m_formattingContext = formattingContext;
+    constructor(floatingState) {
+        this.m_floatingState = floatingState;
     }
 
     computePosition(layoutBox) {
@@ -38,7 +35,7 @@ class FloatingContext {
         let displayBox = this._formattingContext().displayBox(layoutBox);
         if (layoutBox.isFloatingPositioned()) {
             displayBox.setTopLeft(this._positionForFloating(layoutBox));
-            this._addFloating(layoutBox);
+            this._floatingState().addFloating(layoutBox);
             return;
         }
         if (Utils.hasClear(layoutBox))
@@ -48,8 +45,8 @@ class FloatingContext {
     }
 
     bottom() {
-        let leftBottom = this._bottom(this.m_leftFloatingBoxStack);
-        let rightBottom = this._bottom(this.m_rightFloatingBoxStack);
+        let leftBottom = this._bottom(this._leftFloatingStack());
+        let rightBottom = this._bottom(this._rightFloatingStack());
         if (Number.isNaN(leftBottom) && Number.isNaN(rightBottom))
             return Number.NaN;
         if (!Number.isNaN(leftBottom) && !Number.isNaN(rightBottom))
@@ -63,7 +60,7 @@ class FloatingContext {
         let absoluteFloatingBox = this._formattingContext().absoluteMarginBox(floatingBox);
         if (this._isEmpty())
             return this._adjustedFloatingPosition(floatingBox, absoluteFloatingBox.top());
-        let verticalPosition = Math.max(absoluteFloatingBox.top(), this.m_lastFloating.top());
+        let verticalPosition = Math.max(absoluteFloatingBox.top(), this._lastFloating().top());
         let spaceNeeded = absoluteFloatingBox.width();
         while (true) {
             let floatingPair = this._findInnerMostLeftAndRight(verticalPosition);
@@ -83,9 +80,9 @@ class FloatingContext {
         let leftBottom = Number.NaN;
         let rightBottom = Number.NaN;
         if (Utils.hasClearLeft(layoutBox) || Utils.hasClearBoth(layoutBox))
-            leftBottom = this._bottom(this.m_leftFloatingBoxStack);
+            leftBottom = this._bottom(this._leftFloatingStack());
         if (Utils.hasClearRight(layoutBox) || Utils.hasClearBoth(layoutBox))
-            rightBottom = this._bottom(this.m_rightFloatingBoxStack);
+            rightBottom = this._bottom(this._rightFloatingStack());
 
         if (!Number.isNaN(leftBottom) && !Number.isNaN(rightBottom))
             return new LayoutPoint(Math.max(leftBottom, rightBottom), displayBox.left());
@@ -106,21 +103,9 @@ class FloatingContext {
         return this._positionForFloating(layoutBox);
     }
 
-    _addFloating(floatingBox) {
-        // Convert floating box to absolute.
-        let floatingDisplayBox = this._formattingContext().displayBox(floatingBox).clone();
-        floatingDisplayBox.setRect(this._formattingContext().absoluteMarginBox(floatingBox));
-        this.m_lastFloating = floatingDisplayBox;
-        if (Utils.isFloatingLeft(floatingBox)) {
-            this.m_leftFloatingBoxStack.push(floatingDisplayBox);
-            return;
-        }
-        this.m_rightFloatingBoxStack.push(floatingDisplayBox);
-    }
-
     _findInnerMostLeftAndRight(verticalPosition) {
-        let leftFloating = this._findFloatingAtVerticalPosition(verticalPosition, this.m_leftFloatingBoxStack);
-        let rightFloating = this._findFloatingAtVerticalPosition(verticalPosition, this.m_rightFloatingBoxStack);
+        let leftFloating = this._findFloatingAtVerticalPosition(verticalPosition, this._leftFloatingStack());
+        let rightFloating = this._findFloatingAtVerticalPosition(verticalPosition, this._rightFloatingStack());
         return { left: leftFloating, right: rightFloating };
     }
 
@@ -154,7 +139,7 @@ class FloatingContext {
     }
 
     _isEmpty() {
-        return !this.m_leftFloatingBoxStack.length && !this.m_rightFloatingBoxStack.length;
+        return !this._leftFloatingStack().length && !this._rightFloatingStack().length;
     }
 
     _adjustedFloatingPosition(floatingBox, verticalPosition, leftRightFloatings) {
@@ -199,7 +184,23 @@ class FloatingContext {
         return max;
     }
 
+    _floatingState() {
+        return this.m_floatingState;
+    }
+
     _formattingContext() {
-        return this.m_formattingContext;
+        return this._floatingState().formattingContext();
+    }
+
+    _lastFloating() {
+        return this._floatingState().lastFloating();
+    }
+
+    _leftFloatingStack() {
+        return this._floatingState().leftFloatingStack();
+    }
+
+    _rightFloatingStack() {
+        return this._floatingState().rightFloatingStack();
     }
 }
index 3996c9d..732c288 100644 (file)
@@ -26,7 +26,7 @@
 class FormattingContext {
     constructor(formattingState) {
         this.m_formattingState = formattingState;
-        this.m_floatingContext = null;
+        this.m_floatingContext = new FloatingContext(formattingState.floatingState());
         this.m_layoutStack = new Array();
     }
 
index 1ade11b..aec81d3 100644 (file)
 class InlineFormattingContext extends FormattingContext {
     constructor(inlineFormattingState) {
         super(inlineFormattingState);
-        // If the block container box that initiates this inline formatting contex also establishes a block context, create a new float for us.
         ASSERT(this.formattingRoot().isBlockContainerBox());
-        if (this.formattingRoot().establishesBlockFormattingContext())
-            this.m_floatingContext = new FloatingContext(this);
     }
 
     layout() {
index e4fa533..df60dd1 100644 (file)
@@ -26,6 +26,8 @@
 class BlockFormattingState extends FormattingState {
     constructor(formattingRoot, layoutState) {
         super(layoutState, formattingRoot);
+        // New block formatting context always establishes a new floating context.
+        this.m_floatingState = new FloatingState(this);
         this.m_formattingContext = new BlockFormattingContext(this);
     }
 }
diff --git a/Tools/LayoutReloaded/FormattingState/FloatingState.js b/Tools/LayoutReloaded/FormattingState/FloatingState.js
new file mode 100644 (file)
index 0000000..17ad1a2
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+class FloatingState {
+    constructor(formattingState) {
+        this.m_formattingState = formattingState;
+        this.m_leftFloatingBoxStack = new Array();
+        this.m_rightFloatingBoxStack = new Array();
+        this.m_lastFloating = null;
+    }
+
+    addFloating(floatingBox) {
+        // Convert floating box to absolute.
+        let floatingDisplayBox = this.formattingContext().displayBox(floatingBox).clone();
+        floatingDisplayBox.setRect(this.formattingContext().absoluteMarginBox(floatingBox));
+        this.m_lastFloating = floatingDisplayBox;
+        if (Utils.isFloatingLeft(floatingBox)) {
+            this.m_leftFloatingBoxStack.push(floatingDisplayBox);
+            return;
+        }
+        this.m_rightFloatingBoxStack.push(floatingDisplayBox);
+    }
+
+    leftFloatingStack() {
+        return this.m_leftFloatingBoxStack;
+    }
+
+    rightFloatingStack() {
+        return this.m_rightFloatingBoxStack;
+    }
+
+    lastFloating() {
+        return this.m_lastFloating;
+    }
+
+    formattingContext() {
+        return this.m_formattingState.formattingContext();
+    }
+}
index 41b561a..2a9eb86 100644 (file)
@@ -28,6 +28,7 @@ class FormattingState {
         this.m_layoutState = layoutState;
         this.m_formattingContext = null;
         this.m_formattingRoot = formattingRoot;
+        this.m_floatingState = null;
         this.m_displayToLayout = new Map();
     }
 
@@ -43,6 +44,10 @@ class FormattingState {
         return this.m_layoutState;
     }
 
+    floatingState() {
+        return this.m_floatingState;
+    }
+
     createDisplayBox(layoutBox) {
         let displayBox = new Display.Box(layoutBox.node());
         this.m_displayToLayout.set(layoutBox, displayBox);
index b236719..25aafff 100644 (file)
 class InlineFormattingState extends FormattingState {
     constructor(formattingRoot, layoutState) {
         super(layoutState, formattingRoot);
+        // If the block container box that initiates this inline formatting contex also establishes a block context, create a new float for us.
+        if (this.formattingRoot().establishesBlockFormattingContext())
+            this.m_floatingState = new FloatingState(this);
+        else {
+            // TODO: use parent formatting context's floating state.
+        }
         this.m_formattingContext = new InlineFormattingContext(this);
         this.m_lines = new Array();
     }
index 0787d37..1ad0885 100644 (file)
@@ -90,6 +90,7 @@ addJS("../DisplayTree/Box.js");
 addJS("../FormattingState/FormattingState.js");
 addJS("../FormattingState/BlockFormattingState.js");
 addJS("../FormattingState/InlineFormattingState.js");
+addJS("../FormattingState/FloatingState.js");
 addJS("../FormattingContext/FormattingContext.js");
 addJS("../FormattingContext/FloatingContext.js");
 addJS("../FormattingContext/BlockFormatting/BlockFormattingContext.js");