[LFC] Implement width computation for replaced inflow elements.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 May 2018 14:51:39 +0000 (14:51 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 May 2018 14:51:39 +0000 (14:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=185672

Reviewed by Antti Koivisto.

Replaced width for block, inline and float elements compute the same way.

* layout/FormattingContext.cpp:
(WebCore::Layout::FormattingContext::computeWidth const):
(WebCore::Layout::FormattingContext::computeFloatingWidth const):
(WebCore::Layout::FormattingContext::computeInFlowReplacedWidth const):
* layout/FormattingContext.h:
* layout/blockformatting/BlockFormattingContext.cpp:
(WebCore::Layout::BlockFormattingContext::computeInFlowWidth const):
* layout/layouttree/LayoutBox.cpp:
(WebCore::Layout::Box::hasIntrinsicWidth const):
(WebCore::Layout::Box::hasIntrinsicHeight const):
(WebCore::Layout::Box::hasIntrinsicRatio const):
(WebCore::Layout::Box::intrinsicWidth const):
(WebCore::Layout::Box::intrinsicHeight const):
(WebCore::Layout::Box::intrinsicRatio const):
* layout/layouttree/LayoutBox.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@231847 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/layouttree/LayoutBox.cpp
Source/WebCore/layout/layouttree/LayoutBox.h

index 71b75e4..5046fa4 100644 (file)
@@ -1,5 +1,30 @@
 2018-05-16  Zalan Bujtas  <zalan@apple.com>
 
+        [LFC] Implement width computation for replaced inflow elements.
+        https://bugs.webkit.org/show_bug.cgi?id=185672
+
+        Reviewed by Antti Koivisto.
+
+        Replaced width for block, inline and float elements compute the same way. 
+
+        * layout/FormattingContext.cpp:
+        (WebCore::Layout::FormattingContext::computeWidth const):
+        (WebCore::Layout::FormattingContext::computeFloatingWidth const):
+        (WebCore::Layout::FormattingContext::computeInFlowReplacedWidth const):
+        * layout/FormattingContext.h:
+        * layout/blockformatting/BlockFormattingContext.cpp:
+        (WebCore::Layout::BlockFormattingContext::computeInFlowWidth const):
+        * layout/layouttree/LayoutBox.cpp:
+        (WebCore::Layout::Box::hasIntrinsicWidth const):
+        (WebCore::Layout::Box::hasIntrinsicHeight const):
+        (WebCore::Layout::Box::hasIntrinsicRatio const):
+        (WebCore::Layout::Box::intrinsicWidth const):
+        (WebCore::Layout::Box::intrinsicHeight const):
+        (WebCore::Layout::Box::intrinsicRatio const):
+        * layout/layouttree/LayoutBox.h:
+
+2018-05-16  Zalan Bujtas  <zalan@apple.com>
+
         [LFC] Make Display::Box box sizing aware
         https://bugs.webkit.org/show_bug.cgi?id=185649
 
index 0949598..8df9dff 100644 (file)
@@ -65,7 +65,7 @@ void FormattingContext::computeWidth(LayoutContext& layoutContext, const Box& la
     if (layoutBox.isOutOfFlowPositioned())
         return computeOutOfFlowWidth(layoutContext, layoutBox, displayBox);
     if (layoutBox.isFloatingPositioned())
-        return computeFloatingWidth(layoutBox, displayBox);
+        return computeFloatingWidth(layoutContext, layoutBox, displayBox);
     return computeInFlowWidth(layoutContext, layoutBox, displayBox);
 }
 
@@ -87,8 +87,13 @@ void FormattingContext::computeOutOfFlowWidth(LayoutContext& layoutContext, cons
     ASSERT_NOT_REACHED();
 }
 
-void FormattingContext::computeFloatingWidth(const Box&, Display::Box&) const
+void FormattingContext::computeFloatingWidth(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
 {
+    if (!layoutBox.isReplaced()) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+    computeInFlowReplacedWidth(layoutContext, layoutBox, displayBox);
 }
 
 void FormattingContext::computeOutOfFlowHeight(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
@@ -203,6 +208,55 @@ void FormattingContext::computeOutOfFlowNonReplacedHeight(LayoutContext& layoutC
     displayBox.setHeight(computedHeightValue);
 }
 
+void FormattingContext::computeInFlowReplacedWidth(LayoutContext&, const Box& layoutBox, Display::Box& displayBox) const
+{
+    // 10.3.4 Block-level, replaced elements in normal flow: The used value of 'width' is determined as for inline replaced elements
+    // 10.3.6 Floating, replaced elements: The used value of 'width' is determined as for inline replaced elements.   
+
+    // 10.3.2 Inline, replaced elements
+    //
+    // 1. If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic width, then that intrinsic width is the used value of 'width'.
+    //
+    // 2. If 'height' and 'width' both have computed values of 'auto' and the element has no intrinsic width, but does have an intrinsic height and intrinsic ratio; 
+    //    or if 'width' has a computed value of 'auto', 'height' has some other computed value, and the element does have an intrinsic ratio;
+    //    then the used value of 'width' is: (used height) * (intrinsic ratio)
+    //
+    // 3. If 'height' and 'width' both have computed values of 'auto' and the element has an intrinsic ratio but no intrinsic height or width,
+    //    then the used value of 'width' is undefined in CSS 2.2. However, it is suggested that, if the containing block's width does not itself depend on the replaced 
+    //    element's width, then the used value of 'width' is calculated from the constraint equation used for block-level, non-replaced elements in normal flow.
+    //
+    // 4. Otherwise, if 'width' has a computed value of 'auto', and the element has an intrinsic width, then that intrinsic width is the used value of 'width'.
+    // 
+    // 5. Otherwise, if 'width' has a computed value of 'auto', but none of the conditions above are met, then the used value of 'width' becomes 300px. 
+    //    If 300px is too wide to fit the device, UAs should use the width of the largest rectangle that has a 2:1 ratio and fits the device instead.
+    auto& style = layoutBox.style();
+    auto width = style.logicalWidth();
+    auto height = style.logicalHeight();
+
+    LayoutUnit computedWidthValue;
+
+    if (width.isAuto() && height.isAuto() && layoutBox.hasIntrinsicWidth()) {
+        // #1
+        computedWidthValue = layoutBox.intrinsicWidth();
+    } else if (width.isAuto() && (height.isCalculated() || layoutBox.hasIntrinsicHeight()) && layoutBox.hasIntrinsicRatio()) {
+        // #2
+        auto usedHeight = height.isCalculated() ? LayoutUnit(height.value()) : layoutBox.intrinsicHeight();   
+        computedWidthValue = usedHeight * layoutBox.intrinsicRatio();
+    } else if (width.isAuto() && height.isAuto() && layoutBox.hasIntrinsicRatio()) {
+        // #3
+        // FIXME: undefined but surely doable.
+        ASSERT_NOT_REACHED();
+    } else if (width.isAuto() && layoutBox.hasIntrinsicWidth()) {
+        // #4
+        computedWidthValue = layoutBox.intrinsicWidth();
+    } else {
+        // #5
+        computedWidthValue = 300;
+    }
+
+    displayBox.setWidth(computedWidthValue);   
+}
+
 LayoutUnit FormattingContext::contentHeightForFormattingContextRoot(LayoutContext& layoutContext, const Box& layoutBox) const
 {
     ASSERT(layoutBox.style().logicalHeight().isAuto());
index 2424b1a..2fbff65 100644 (file)
@@ -72,7 +72,7 @@ protected:
     virtual void computeHeight(LayoutContext&, const Box&, Display::Box&) const;
 
     virtual void computeOutOfFlowWidth(LayoutContext&, const Box&, Display::Box&) const;
-    virtual void computeFloatingWidth(const Box&, Display::Box&) const;
+    virtual void computeFloatingWidth(LayoutContext&, const Box&, Display::Box&) const;
     virtual void computeInFlowWidth(LayoutContext&, const Box&, Display::Box&) const = 0;
 
     virtual void computeOutOfFlowHeight(LayoutContext&, const Box&, Display::Box&) const;
@@ -87,6 +87,8 @@ protected:
     void placeInFlowPositionedChildren(const Container&) const;
     void layoutOutOfFlowDescendants(LayoutContext&s) const;
 
+    void computeInFlowReplacedWidth(LayoutContext&, const Box&, Display::Box&) const;
+
 private:
     void computeOutOfFlowNonReplacedHeight(LayoutContext&, const Box&, Display::Box&) const;
     void computeOutOfFlowNonReplacedWidth(LayoutContext&, const Box&, Display::Box&) const;
index 4c3f41b..e78b592 100644 (file)
@@ -149,7 +149,7 @@ void BlockFormattingContext::computeInFlowWidth(LayoutContext& layoutContext, co
         computeInFlowNonReplacedWidth(layoutContext, layoutBox, displayBox);
         return;
     }
-    ASSERT_NOT_REACHED();
+    computeInFlowReplacedWidth(layoutContext, layoutBox, displayBox);
 }
 
 void BlockFormattingContext::computeInFlowNonReplacedWidth(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
index fe0d5ca..940f908 100644 (file)
@@ -230,6 +230,39 @@ bool Box::isOverflowVisible() const
     return m_style.overflowX() == OVISIBLE || m_style.overflowY() == OVISIBLE;
 }
 
+bool Box::hasIntrinsicWidth() const
+{
+    return false;
+}
+
+bool Box::hasIntrinsicHeight() const
+{
+    return false;
+}
+
+bool Box::hasIntrinsicRatio() const
+{
+    return false;
+}
+
+LayoutUnit Box::intrinsicWidth() const
+{
+    ASSERT(hasIntrinsicWidth());
+    return { };
+}
+
+LayoutUnit Box::intrinsicHeight() const
+{
+    ASSERT(hasIntrinsicHeight());
+    return { };
+}
+
+LayoutUnit Box::intrinsicRatio() const
+{
+    ASSERT(hasIntrinsicRatio());
+    return { };
+}
+
 }
 }
 
index 23af846..70437c9 100644 (file)
@@ -72,7 +72,6 @@ public:
     bool isInlineBlockBox() const;
     bool isBlockContainerBox() const;
     bool isInitialContainingBlock() const;
-    bool isReplaced() const;
 
     const Container* parent() const { return m_parent; }
     const Box* nextSibling() const { return m_nextSibling; }
@@ -91,6 +90,15 @@ public:
     const RenderStyle& style() const { return m_style; }
     auto& weakPtrFactory() const { return m_weakFactory; }
 
+    bool isReplaced() const;
+    // FIXME: find out how to not pollute the Box interface
+    bool hasIntrinsicWidth() const;
+    bool hasIntrinsicHeight() const;
+    bool hasIntrinsicRatio() const;
+    LayoutUnit intrinsicWidth() const;
+    LayoutUnit intrinsicHeight() const;
+    LayoutUnit intrinsicRatio() const;
+
 protected:
     enum BaseTypeFlag {
         ContainerFlag         = 1 << 0,