[LFC] Compute static position for out-of-flow elements only when required.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 27 Jun 2018 16:13:48 +0000 (16:13 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 27 Jun 2018 16:13:48 +0000 (16:13 +0000)
https://bugs.webkit.org/show_bug.cgi?id=187096

Reviewed by Antti Koivisto.

Computing static position for out-of-flow elements could be somewhat expensive, so let's not do it unless we actually need it.

* layout/FormattingContextGeometry.cpp:
(WebCore::Layout::staticVerticalPositionForOutOfFlowPositioned):
(WebCore::Layout::staticHorizontalPositionForOutOfFlowPositioned):
(WebCore::Layout::FormattingContext::Geometry::outOfFlowNonReplacedVerticalGeometry):
(WebCore::Layout::FormattingContext::Geometry::outOfFlowNonReplacedHorizontalGeometry):
(WebCore::Layout::FormattingContext::Geometry::outOfFlowReplacedVerticalGeometry):
(WebCore::Layout::FormattingContext::Geometry::outOfFlowReplacedHorizontalGeometry):
* layout/blockformatting/BlockFormattingContextGeometry.cpp:
(WebCore::Layout::BlockFormattingContext::Geometry::staticPosition):
(WebCore::Layout::BlockFormattingContext::Geometry::staticPositionForOutOfFlowPositioned): Deleted.

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

Source/WebCore/ChangeLog
Source/WebCore/layout/FormattingContextGeometry.cpp
Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp

index 6b4e73b..3e2738a 100644 (file)
@@ -1,3 +1,23 @@
+2018-06-27  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC] Compute static position for out-of-flow elements only when required.
+        https://bugs.webkit.org/show_bug.cgi?id=187096
+
+        Reviewed by Antti Koivisto.
+
+        Computing static position for out-of-flow elements could be somewhat expensive, so let's not do it unless we actually need it.
+
+        * layout/FormattingContextGeometry.cpp:
+        (WebCore::Layout::staticVerticalPositionForOutOfFlowPositioned):
+        (WebCore::Layout::staticHorizontalPositionForOutOfFlowPositioned):
+        (WebCore::Layout::FormattingContext::Geometry::outOfFlowNonReplacedVerticalGeometry):
+        (WebCore::Layout::FormattingContext::Geometry::outOfFlowNonReplacedHorizontalGeometry):
+        (WebCore::Layout::FormattingContext::Geometry::outOfFlowReplacedVerticalGeometry):
+        (WebCore::Layout::FormattingContext::Geometry::outOfFlowReplacedHorizontalGeometry):
+        * layout/blockformatting/BlockFormattingContextGeometry.cpp:
+        (WebCore::Layout::BlockFormattingContext::Geometry::staticPosition):
+        (WebCore::Layout::BlockFormattingContext::Geometry::staticPositionForOutOfFlowPositioned): Deleted.
+
 2018-06-27  Nan Wang  <n_wang@apple.com>
 
         AX: [iOS] Remove the ability to set keyboard focus when VoiceOver takes focus
index f5fa05c..2466f2d 100644 (file)
@@ -75,6 +75,45 @@ std::optional<LayoutUnit> FormattingContext::Geometry::computedValueIfNotAuto(co
     return valueForLength(geometryProperty, containingBlockWidth);
 }
 
+static LayoutUnit staticVerticalPositionForOutOfFlowPositioned(const LayoutContext& layoutContext, const Box& layoutBox)
+{
+    ASSERT(layoutBox.isOutOfFlowPositioned());
+
+    LayoutUnit top;
+    // Resolve top all the way up to the containing block.
+    auto* containingBlock = layoutBox.containingBlock();
+    for (auto* parent = layoutBox.parent(); parent; parent = parent->parent()) {
+        auto& displayBox = *layoutContext.displayBoxForLayoutBox(*parent);
+        top += (displayBox.top() + displayBox.contentBoxTop());
+        if (parent == containingBlock)
+            break;
+    }
+    // Add sibling offset
+    if (auto* previousInFlowSibling = layoutBox.previousInFlowSibling()) {
+        auto& previousInFlowDisplayBox = *layoutContext.displayBoxForLayoutBox(*previousInFlowSibling);
+        top += previousInFlowDisplayBox.bottom() + previousInFlowDisplayBox.marginBottom();
+    }
+    // FIXME: floatings need to be taken into account.
+    return top;
+}
+
+static LayoutUnit staticHorizontalPositionForOutOfFlowPositioned(const LayoutContext& layoutContext, const Box& layoutBox)
+{
+    ASSERT(layoutBox.isOutOfFlowPositioned());
+
+    LayoutUnit left;
+    // Resolve left all the way up to the containing block.
+    auto* containingBlock = layoutBox.containingBlock();
+    for (auto* parent = layoutBox.parent(); parent; parent = parent->parent()) {
+        auto& displayBox = *layoutContext.displayBoxForLayoutBox(*parent);
+        left += (displayBox.left() + displayBox.contentBoxLeft());
+        if (parent == containingBlock)
+            break;
+    }
+    // FIXME: floatings need to be taken into account.
+    return left;
+}
+
 FormattingContext::Geometry::VerticalGeometry FormattingContext::Geometry::outOfFlowNonReplacedVerticalGeometry(LayoutContext& layoutContext, const Box& layoutBox)
 {
     ASSERT(layoutBox.isOutOfFlowPositioned() && !layoutBox.replaced());
@@ -120,7 +159,7 @@ FormattingContext::Geometry::VerticalGeometry FormattingContext::Geometry::outOf
     auto borderBottom = displayBox.borderBottom();
 
     if (!top && !height && !bottom)
-        top = displayBox.top();
+        top = staticVerticalPositionForOutOfFlowPositioned(layoutContext, layoutBox);
 
     if (top && height && bottom) {
         if (!marginTop && !marginBottom) {
@@ -146,7 +185,7 @@ FormattingContext::Geometry::VerticalGeometry FormattingContext::Geometry::outOf
 
     if (!top && !bottom && height) {
         // #2
-        top = displayBox.top();
+        top = staticVerticalPositionForOutOfFlowPositioned(layoutContext, layoutBox);
         marginTop = marginTop.value_or(0);
         marginBottom = marginBottom.value_or(0);
         bottom = containingBlockHeight - (*top + *marginTop + borderTop + paddingTop + *height + paddingBottom + borderBottom + *marginBottom); 
@@ -244,10 +283,11 @@ FormattingContext::Geometry::HorizontalGeometry FormattingContext::Geometry::out
         marginLeft = marginLeft.value_or(0);
         marginRight = marginRight.value_or(0);
 
+        auto staticHorizontalPosition = staticHorizontalPositionForOutOfFlowPositioned(layoutContext, layoutBox);
         if (isLeftToRightDirection)
-            left = displayBox.left();
+            left = staticHorizontalPosition;
         else
-            right = displayBox.right();
+            right = staticHorizontalPosition;
     } else if (left && width && right) {
         // If none of the three is 'auto': If both 'margin-left' and 'margin-right' are 'auto', solve the equation under the extra constraint that the two margins get equal values,
         // unless this would make them negative, in which case when direction of the containing block is 'ltr' ('rtl'), set 'margin-left' ('margin-right') to zero and
@@ -301,11 +341,12 @@ FormattingContext::Geometry::HorizontalGeometry FormattingContext::Geometry::out
         left = containingBlockWidth - (*marginLeft + borderLeft + paddingLeft + *width + paddingRight  + borderRight + *marginRight + *right);
     } else if (!left && !right && width) {
         // #2
+        auto staticHorizontalPosition = staticHorizontalPositionForOutOfFlowPositioned(layoutContext, layoutBox);
         if (isLeftToRightDirection) {
-            left = displayBox.left();
+            left = staticHorizontalPosition;
             right = containingBlockWidth - (*left + *marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight);
         } else {
-            right = displayBox.right();
+            right = staticHorizontalPosition;
             left = containingBlockWidth - (*marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight + *right);
         }
     } else if (!width && !right && left) {
@@ -365,7 +406,7 @@ FormattingContext::Geometry::VerticalGeometry FormattingContext::Geometry::outOf
 
     if (!top && !bottom) {
         // #1
-        top = displayBox.top();
+        top = staticVerticalPositionForOutOfFlowPositioned(layoutContext, layoutBox);
     }
 
     if (!bottom) {
@@ -438,10 +479,11 @@ FormattingContext::Geometry::HorizontalGeometry FormattingContext::Geometry::out
 
     if (!left && !right) {
         // #1
+        auto staticHorizontalPosition = staticHorizontalPositionForOutOfFlowPositioned(layoutContext, layoutBox);
         if (isLeftToRightDirection)
-            left = displayBox.left();
+            left = staticHorizontalPosition;
         else
-            right = displayBox.right();
+            right = staticHorizontalPosition;
     }
 
     if (!left || !right) {
index ba65b7e..37e8d2a 100644 (file)
@@ -265,31 +265,6 @@ FormattingContext::Geometry::WidthAndMargin BlockFormattingContext::Geometry::in
     return { width, margin };
 }
 
-FormattingContext::Geometry::Position BlockFormattingContext::Geometry::staticPositionForOutOfFlowPositioned(const LayoutContext& layoutContext, const Box& layoutBox)
-{
-    // FIXME: This is certainly only really needed when top/bottom left/right are auto.
-    ASSERT(layoutBox.isOutOfFlowPositioned());
-    LayoutUnit top;
-    LayoutUnit left;
-    // Resolve top/left all the way up to the containing block.
-    auto* containingBlock = layoutBox.containingBlock();
-    for (auto* parent = layoutBox.parent(); parent; parent = parent->parent()) {
-        auto& displayBox = *layoutContext.displayBoxForLayoutBox(*parent);
-        top += (displayBox.top() + displayBox.contentBoxTop());
-        left += (displayBox.left() + displayBox.contentBoxLeft());
-        if (parent == containingBlock)
-            break;
-    }
-    // Add sibling offset
-    if (auto* previousInFlowSibling = layoutBox.previousInFlowSibling()) {
-        auto& previousInFlowDisplayBox = *layoutContext.displayBoxForLayoutBox(*previousInFlowSibling);
-        top += previousInFlowDisplayBox.bottom() + previousInFlowDisplayBox.marginBottom();
-    }
-
-    LOG_WITH_STREAM(FormattingContextLayout, stream << "[Position] -> out-of-flow -> static -> top(" << top << "px) left(" << left << "px) layoutBox(" << &layoutBox << ")");
-    return { left, top };
-}
-
 FormattingContext::Geometry::Position BlockFormattingContext::Geometry::staticPosition(LayoutContext& layoutContext, const Box& layoutBox)
 {
     // https://www.w3.org/TR/CSS22/visuren.html#block-formatting
@@ -298,9 +273,6 @@ FormattingContext::Geometry::Position BlockFormattingContext::Geometry::staticPo
     // Vertical margins between adjacent block-level boxes in a block formatting context collapse.
     // In a block formatting context, each box's left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch).
 
-    if (layoutBox.isOutOfFlowPositioned())
-        return staticPositionForOutOfFlowPositioned(layoutContext, layoutBox);
-
     LayoutUnit top;
     auto& containingBlockDisplayBox = *layoutContext.displayBoxForLayoutBox(*layoutBox.containingBlock());
     if (auto* previousInFlowSibling = layoutBox.previousInFlowSibling()) {