[LFC] Implement width computation for non-replaced out of flow elements.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 May 2018 14:52:50 +0000 (14:52 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 May 2018 14:52:50 +0000 (14:52 +0000)
https://bugs.webkit.org/show_bug.cgi?id=185598

Reviewed by Antti Koivisto.

* layout/FormattingContext.cpp:
(WebCore::Layout::FormattingContext::computeWidth const):
(WebCore::Layout::FormattingContext::computeOutOfFlowWidth const):
(WebCore::Layout::FormattingContext::layoutOutOfFlowDescendants const):
(WebCore::Layout::FormattingContext::computeOutOfFlowNonReplacedWidth const):
(WebCore::Layout::FormattingContext::shrinkToFitWidth const):
* layout/FormattingContext.h:
* layout/blockformatting/BlockFormattingContext.cpp:
(WebCore::Layout::BlockFormattingContext::layout const):
* layout/displaytree/DisplayBox.h:

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

Source/WebCore/ChangeLog
Source/WebCore/layout/FormattingContext.cpp
Source/WebCore/layout/FormattingContext.h
Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp
Source/WebCore/layout/displaytree/DisplayBox.h

index f6345b0..0640c1c 100644 (file)
@@ -1,3 +1,21 @@
+2018-05-14  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC] Implement width computation for non-replaced out of flow elements.
+        https://bugs.webkit.org/show_bug.cgi?id=185598
+
+        Reviewed by Antti Koivisto.
+
+        * layout/FormattingContext.cpp:
+        (WebCore::Layout::FormattingContext::computeWidth const):
+        (WebCore::Layout::FormattingContext::computeOutOfFlowWidth const):
+        (WebCore::Layout::FormattingContext::layoutOutOfFlowDescendants const):
+        (WebCore::Layout::FormattingContext::computeOutOfFlowNonReplacedWidth const):
+        (WebCore::Layout::FormattingContext::shrinkToFitWidth const):
+        * layout/FormattingContext.h:
+        * layout/blockformatting/BlockFormattingContext.cpp:
+        (WebCore::Layout::BlockFormattingContext::layout const):
+        * layout/displaytree/DisplayBox.h:
+
 2018-05-14  Zan Dobersek  <zdobersek@igalia.com>
 
         Drop the m_compositorTexture member variable in TextureMapperGC3DPlatformLayer.
index 3c1189c..10f41f3 100644 (file)
@@ -28,6 +28,7 @@
 
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
+#include "DisplayBox.h"
 #include "LayoutBox.h"
 #include "LayoutContainer.h"
 #include "LayoutContext.h"
@@ -59,10 +60,10 @@ void FormattingContext::computeOutOfFlowPosition(const Box&, Display::Box&) cons
 {
 }
 
-void FormattingContext::computeWidth(const Box& layoutBox, Display::Box& displayBox) const
+void FormattingContext::computeWidth(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
 {
     if (layoutBox.isOutOfFlowPositioned())
-        return computeOutOfFlowWidth(layoutBox, displayBox);
+        return computeOutOfFlowWidth(layoutContext, layoutBox, displayBox);
     if (layoutBox.isFloatingPositioned())
         return computeFloatingWidth(layoutBox, displayBox);
     return computeInFlowWidth(layoutBox, displayBox);
@@ -77,8 +78,13 @@ void FormattingContext::computeHeight(LayoutContext& layoutContext, const Box& l
     return computeInFlowHeight(layoutContext, layoutBox, displayBox);
 }
 
-void FormattingContext::computeOutOfFlowWidth(const Box&, Display::Box&) const
+void FormattingContext::computeOutOfFlowWidth(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
 {
+    if (!layoutBox.isReplaced()) {
+        computeOutOfFlowNonReplacedWidth(layoutContext, layoutBox, displayBox);
+        return;
+    }
+    ASSERT_NOT_REACHED();
 }
 
 void FormattingContext::computeFloatingWidth(const Box&, Display::Box&) const
@@ -126,7 +132,7 @@ void FormattingContext::layoutOutOfFlowDescendants(LayoutContext& layoutContext)
         auto& displayBox = layoutContext.createDisplayBox(layoutBox);
 
         computeOutOfFlowPosition(layoutBox, displayBox);
-        computeOutOfFlowWidth(layoutBox, displayBox);
+        computeOutOfFlowWidth(layoutContext, layoutBox, displayBox);
 
         ASSERT(layoutBox.establishesFormattingContext());
         auto formattingContext = layoutContext.formattingContext(layoutBox);
@@ -136,6 +142,61 @@ void FormattingContext::layoutOutOfFlowDescendants(LayoutContext& layoutContext)
     }
 }
 
+void FormattingContext::computeOutOfFlowNonReplacedWidth(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
+{
+    // 'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right'
+    // = width of containing block
+
+    // If all three of 'left', 'width', and 'right' are 'auto': First set any 'auto' values for 'margin-left' and 'margin-right' to 0.
+    // Then, if the 'direction' property of the element establishing the static-position containing block is 'ltr' set 'left' to the static
+    // position and apply rule number three below; otherwise, set 'right' to the static position and apply rule number one below.
+
+    // 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the width is shrink-to-fit. Then solve for 'left'
+    // 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if the 'direction' property of the element establishing the static-position 
+    //    containing block is 'ltr' set 'left' to the static position, otherwise set 'right' to the static position.
+    //    Then solve for 'left' (if 'direction is 'rtl') or 'right' (if 'direction' is 'ltr').
+    // 3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the width is shrink-to-fit . Then solve for 'right'
+    // 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve for 'left'
+    // 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve for 'width'
+    // 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve for 'right'
+    auto& style = layoutBox.style();
+    auto left = style.logicalLeft();
+    auto right = style.logicalRight();
+    auto width = style.logicalWidth();
+
+    auto containingBlockWidth = layoutContext.displayBoxForLayoutBox(*layoutBox.containingBlock())->width();
+    LayoutUnit computedWidthValue;
+
+    if ((left.isAuto() && width.isAuto() && right.isAuto())
+        || (left.isAuto() && width.isAuto() && !right.isAuto())
+        || (!left.isAuto() && width.isAuto() && right.isAuto())) {
+        // All auto (#1), #1 and #3
+        computedWidthValue = shrinkToFitWidth(layoutContext, layoutBox);
+    } else if (!left.isAuto() && width.isAuto() && !right.isAuto()) {
+        // #5
+        auto marginLeft = style.marginLeft().isAuto() ? LayoutUnit() : valueForLength(style.marginLeft(), containingBlockWidth);
+        auto marginRight = style.marginRight().isAuto() ? LayoutUnit() : valueForLength(style.marginRight(), containingBlockWidth);
+    
+        auto paddingLeft = valueForLength(style.paddingTop(), containingBlockWidth);
+        auto paddingRight = valueForLength(style.paddingBottom(), containingBlockWidth);
+
+        auto borderLeftWidth = style.borderStartWidth();
+        auto borderRightWidth = style.borderEndWidth();
+
+        computedWidthValue = containingBlockWidth - (left.value() + marginLeft + borderLeftWidth + paddingLeft + paddingRight + borderRightWidth + marginRight + right.value());
+    } else if (!width.isAuto())
+        computedWidthValue = valueForLength(width, containingBlockWidth);
+    else
+        ASSERT_NOT_REACHED();
+
+    displayBox.setWidth(computedWidthValue);
+}
+
+LayoutUnit FormattingContext::shrinkToFitWidth(LayoutContext&, const Box&) const
+{
+    return 0;
+}
+
 }
 }
 #endif
index 3e5e870..ba83b85 100644 (file)
@@ -68,10 +68,10 @@ protected:
     virtual void computeInFlowPositionedPosition(const Box&, Display::Box&) const;
     virtual void computeOutOfFlowPosition(const Box&, Display::Box&) const;
 
-    virtual void computeWidth(const Box&, Display::Box&) const;
+    virtual void computeWidth(LayoutContext&, const Box&, Display::Box&) const;
     virtual void computeHeight(LayoutContext&, const Box&, Display::Box&) const;
 
-    virtual void computeOutOfFlowWidth(const Box&, Display::Box&) const;
+    virtual void computeOutOfFlowWidth(LayoutContext&, const Box&, Display::Box&) const;
     virtual void computeFloatingWidth(const Box&, Display::Box&) const;
     virtual void computeInFlowWidth(const Box&, Display::Box&) const = 0;
 
@@ -88,6 +88,9 @@ protected:
     void layoutOutOfFlowDescendants(LayoutContext&s) const;
 
 private:
+    void computeOutOfFlowNonReplacedWidth(LayoutContext&, const Box&, Display::Box&) const;
+    LayoutUnit shrinkToFitWidth(LayoutContext&, const Box&) const;
+
     WeakPtr<Box> m_root;
 };
 
index e2c9c2d..0542136 100644 (file)
@@ -74,7 +74,7 @@ void BlockFormattingContext::layout(LayoutContext& layoutContext, FormattingStat
             auto& layoutBox = layoutPair.layoutBox;
             auto& displayBox = layoutPair.displayBox;
             
-            computeWidth(layoutBox, displayBox);
+            computeWidth(layoutContext, layoutBox, displayBox);
             computeStaticPosition(layoutContext, layoutBox, layoutPair.displayBox);
             if (layoutBox.establishesFormattingContext()) {
                 auto formattingContext = layoutContext.formattingContext(layoutBox);
index 3cdfb1c..49a1d10 100644 (file)
@@ -35,8 +35,9 @@
 namespace WebCore {
 
 namespace Layout {
-class LayoutContext;
 class BlockFormattingContext;
+class FormattingContext;
+class LayoutContext;
 }
 
 namespace Display {
@@ -45,6 +46,7 @@ class Box {
     WTF_MAKE_ISO_ALLOCATED(Box);
 public:
     friend class Layout::LayoutContext;
+    friend class Layout::FormattingContext;
     friend class Layout::BlockFormattingContext;
 
     ~Box();