Title: [246457] trunk/Source/WebCore
Revision
246457
Author
[email protected]
Date
2019-06-15 07:03:23 -0700 (Sat, 15 Jun 2019)

Log Message

[LFC][IFC] Add support for vertical-align: top and bottom
https://bugs.webkit.org/show_bug.cgi?id=198697
<rdar://problem/51556188>

Reviewed by Antti Koivisto.

Use the layout box's vertical alignment to adjust line baseline and height and set the run's logical top when the line is being closed.

* layout/inlineformatting/InlineLine.cpp:
(WebCore::Layout::Line::isVisuallyEmpty const):
(WebCore::Layout::Line::close):
(WebCore::Layout::Line::appendInlineContainerStart):
(WebCore::Layout::Line::appendTextContent):
(WebCore::Layout::Line::appendNonReplacedInlineBox):
(WebCore::Layout::Line::appendHardLineBreak):
(WebCore::Layout::Line::adjustBaselineAndLineHeight):
(WebCore::Layout::Line::inlineItemHeight const):
(WebCore::Layout::Line::Content::isVisuallyEmpty const): Deleted.
* layout/inlineformatting/InlineLine.h:
(WebCore::Layout::Line::Content::isVisuallyEmpty const):
(WebCore::Layout::Line::Content::setIsVisuallyEmpty):
(WebCore::Layout::Line::hasContent const):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (246456 => 246457)


--- trunk/Source/WebCore/ChangeLog	2019-06-15 03:20:42 UTC (rev 246456)
+++ trunk/Source/WebCore/ChangeLog	2019-06-15 14:03:23 UTC (rev 246457)
@@ -1,3 +1,28 @@
+2019-06-15  Zalan Bujtas  <[email protected]>
+
+        [LFC][IFC] Add support for vertical-align: top and bottom
+        https://bugs.webkit.org/show_bug.cgi?id=198697
+        <rdar://problem/51556188>
+
+        Reviewed by Antti Koivisto.
+
+        Use the layout box's vertical alignment to adjust line baseline and height and set the run's logical top when the line is being closed.
+
+        * layout/inlineformatting/InlineLine.cpp:
+        (WebCore::Layout::Line::isVisuallyEmpty const):
+        (WebCore::Layout::Line::close):
+        (WebCore::Layout::Line::appendInlineContainerStart):
+        (WebCore::Layout::Line::appendTextContent):
+        (WebCore::Layout::Line::appendNonReplacedInlineBox):
+        (WebCore::Layout::Line::appendHardLineBreak):
+        (WebCore::Layout::Line::adjustBaselineAndLineHeight):
+        (WebCore::Layout::Line::inlineItemHeight const):
+        (WebCore::Layout::Line::Content::isVisuallyEmpty const): Deleted.
+        * layout/inlineformatting/InlineLine.h:
+        (WebCore::Layout::Line::Content::isVisuallyEmpty const):
+        (WebCore::Layout::Line::Content::setIsVisuallyEmpty):
+        (WebCore::Layout::Line::hasContent const):
+
 2019-06-14  Antoine Quint  <[email protected]>
 
         [Pointer Events] button property is -1 for pointerdown and pointerup

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLine.cpp (246456 => 246457)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLine.cpp	2019-06-15 03:20:42 UTC (rev 246456)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLine.cpp	2019-06-15 14:03:23 UTC (rev 246457)
@@ -35,18 +35,6 @@
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(Line);
 
-bool Line::Content::isVisuallyEmpty() const
-{
-    // Return true for empty inline containers like <span></span>.
-    for (auto& run : m_runs) {
-        if (run->inlineItem.isContainerStart() || run->inlineItem.isContainerEnd())
-            continue;
-        if (!run->isCollapsed)
-            return false;
-    }
-    return true;
-}
-
 Line::Content::Run::Run(const InlineItem& inlineItem, const Display::Rect& logicalRect, TextContext textContext, bool isCollapsed, bool canBeExtended)
     : inlineItem(inlineItem)
     , logicalRect(logicalRect)
@@ -75,16 +63,65 @@
 {
 }
 
+bool Line::isVisuallyEmpty() const
+{
+    // FIXME: This should be cached instead -as the inline items are being added.
+    // Return true for empty inline containers like <span></span>.
+    for (auto& run : m_content->runs()) {
+        if (run->inlineItem.isContainerStart()) {
+            auto& displayBox = m_layoutState.displayBoxForLayoutBox(run->inlineItem.layoutBox());
+            if (displayBox.horizontalBorder() || (displayBox.horizontalPadding() && displayBox.horizontalPadding().value()))
+                return false;
+            continue;
+        }
+        if (run->inlineItem.isContainerEnd())
+            continue;
+        if (!run->isCollapsed)
+            return false;
+    }
+    return true;
+}
+
 std::unique_ptr<Line::Content> Line::close()
 {
     removeTrailingTrimmableContent();
     if (!m_skipVerticalAligment) {
-        // Convert inline run geometry from relative to the baseline to relative to logical top.
         for (auto& run : m_content->runs()) {
-            auto adjustedLogicalTop = run->logicalRect.top() + baselineOffset();
-            run->logicalRect.setTop(adjustedLogicalTop);
+            LayoutUnit logicalTop;
+            auto& inlineItem = run->inlineItem;
+            auto& layoutBox = inlineItem.layoutBox();
+            auto ascent = inlineItem.style().fontMetrics().ascent();
+
+            switch (inlineItem.style().verticalAlign()) {
+            case VerticalAlign::Baseline:
+                if (inlineItem.isLineBreak() || inlineItem.isText())
+                    logicalTop = baselineOffset() - ascent;
+                else if (inlineItem.isContainerStart()) {
+                    auto& displayBox = m_layoutState.displayBoxForLayoutBox(layoutBox);
+                    logicalTop = baselineOffset() - ascent - displayBox.borderTop() - displayBox.paddingTop().valueOr(0);
+                } else if (layoutBox.isInlineBlockBox() && layoutBox.establishesInlineFormattingContext()) {
+                    auto& formattingState = downcast<InlineFormattingState>(m_layoutState.establishedFormattingState(layoutBox));
+                    // Spec makes us generate at least one line -even if it is empty.
+                    ASSERT(!formattingState.lineBoxes().isEmpty());
+                    auto inlineBlockBaseline = formattingState.lineBoxes().last().baseline();
+                    logicalTop = baselineOffset() - inlineBlockBaseline.ascent;
+                } else
+                    logicalTop = baselineOffset() - run->logicalRect.height();
+                break;
+            case VerticalAlign::Top:
+                logicalTop = { };
+                break;
+            case VerticalAlign::Bottom:
+                logicalTop = logicalBottom() - run->logicalRect.height();
+                break;
+            default:
+                ASSERT_NOT_IMPLEMENTED_YET();
+                break;
+            }
+            run->logicalRect.setTop(logicalTop);
         }
     }
+    m_content->setIsVisuallyEmpty(isVisuallyEmpty());
     m_content->setLogicalRect({ logicalTop(), logicalLeft(), contentLogicalWidth(), logicalHeight() });
     m_content->setBaseline(m_baseline);
     return WTFMove(m_content);
@@ -142,10 +179,6 @@
     if (!m_skipVerticalAligment) {
         auto logicalHeight = inlineItemHeight(inlineItem);
         adjustBaselineAndLineHeight(inlineItem, logicalHeight);
-
-        auto& displayBox = m_layoutState.displayBoxForLayoutBox(inlineItem.layoutBox());
-        auto logicalTop = -inlineItem.style().fontMetrics().ascent() - displayBox.borderTop() - displayBox.paddingTop().valueOr(0);
-        logicalRect.setTop(logicalTop);
         logicalRect.setHeight(logicalHeight);
     }
     appendNonBreakableSpace(inlineItem, logicalRect);
@@ -190,10 +223,8 @@
     auto logicalRect = Display::Rect { };
     logicalRect.setLeft(contentLogicalRight());
     logicalRect.setWidth(logicalWidth);
-    if (!m_skipVerticalAligment) {
-        logicalRect.setTop(-inlineItem.style().fontMetrics().ascent());
+    if (!m_skipVerticalAligment)
         logicalRect.setHeight(inlineItemHeight(inlineItem));
-    }
 
     auto textContext = Content::Run::TextContext { inlineItem.start(), inlineItem.isCollapsed() ? 1 : inlineItem.length() };
     auto lineItem = std::make_unique<Content::Run>(inlineItem, logicalRect, textContext, isCompletelyCollapsed, canBeExtended);
@@ -215,8 +246,6 @@
     if (!m_skipVerticalAligment) {
         auto logicalHeight = inlineItemHeight(inlineItem);
         adjustBaselineAndLineHeight(inlineItem, logicalHeight);
-
-        logicalRect.setTop(-logicalHeight);
         logicalRect.setHeight(logicalHeight);
     }
 
@@ -233,8 +262,11 @@
 
 void Line::appendHardLineBreak(const InlineItem& inlineItem)
 {
-    auto ascent = inlineItem.layoutBox().style().fontMetrics().ascent();
-    auto logicalRect = Display::Rect { -ascent, contentLogicalRight(), { }, logicalHeight() };
+    auto logicalRect = Display::Rect { };
+    logicalRect.setLeft(contentLogicalRight());
+    logicalRect.setWidth({ });
+    if (!m_skipVerticalAligment)
+        logicalRect.setHeight(logicalHeight());
     m_content->runs().append(std::make_unique<Content::Run>(inlineItem, logicalRect, Content::Run::TextContext { }, false, false));
 }
 
@@ -255,20 +287,37 @@
         return;
     }
     // Replaced and non-replaced inline level box.
-    // FIXME: We need to look inside the inline-block's formatting context and check the lineboxes (if any) to be able to baseline align.
-    if (layoutBox.establishesInlineFormattingContext()) {
-        if (runHeight == logicalHeight())
-            return;
-        // FIXME: This fails when the line height difference comes from font-size diff.
+    switch (inlineItem.style().verticalAlign()) {
+    case VerticalAlign::Baseline:
+        if (layoutBox.isInlineBlockBox() && layoutBox.establishesInlineFormattingContext()) {
+            // Inline-blocks with inline content always have baselines.
+            auto& formattingState = downcast<InlineFormattingState>(m_layoutState.establishedFormattingState(layoutBox));
+            // Spec makes us generate at least one line -even if it is empty.
+            ASSERT(!formattingState.lineBoxes().isEmpty());
+            auto inlineBlockBaseline = formattingState.lineBoxes().last().baseline();
+            m_baseline.descent = std::max(inlineBlockBaseline.descent, m_baseline.descent);
+            m_baseline.ascent = std::max(inlineBlockBaseline.ascent, m_baseline.ascent);
+            m_contentLogicalHeight = std::max(std::max(m_contentLogicalHeight, runHeight), baselineAlignedContentHeight());
+            break;
+        }
         m_baseline.descent = std::max<LayoutUnit>(0, m_baseline.descent);
         m_baseline.ascent = std::max(runHeight, m_baseline.ascent);
         m_contentLogicalHeight = std::max(m_contentLogicalHeight, baselineAlignedContentHeight());
-        return;
+        break;
+    case VerticalAlign::Top:
+        // Top align content never changes the baseline offset, it only pushes the bottom of the line further down.
+        m_contentLogicalHeight = std::max(runHeight, m_contentLogicalHeight);
+        break;
+    case VerticalAlign::Bottom:
+        if (m_contentLogicalHeight < runHeight) {
+            m_baseline.offset = m_baseline.offset + (runHeight - m_contentLogicalHeight);
+            m_contentLogicalHeight = runHeight;
+        }
+        break;
+    default:
+        ASSERT_NOT_IMPLEMENTED_YET();
+        break;
     }
-    // 0 descent -> baseline aligment for now.
-    m_baseline.descent = std::max<LayoutUnit>(0, m_baseline.descent);
-    m_baseline.ascent = std::max(runHeight, m_baseline.ascent);
-    m_contentLogicalHeight = std::max(m_contentLogicalHeight, baselineAlignedContentHeight());
 }
 
 LayoutUnit Line::inlineItemHeight(const InlineItem& inlineItem) const
@@ -292,7 +341,7 @@
         return fontMetrics.height() + displayBox.verticalBorder() + displayBox.verticalPadding().valueOr(0);
 
     // Non-replaced inline box (e.g. inline-block)
-    return displayBox.height();
+    return displayBox.marginBox().height();
 }
 
 LineBox::Baseline Line::halfLeadingMetrics(const FontMetrics& fontMetrics, LayoutUnit lineLogicalHeight)

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLine.h (246456 => 246457)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLine.h	2019-06-15 03:20:42 UTC (rev 246456)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLine.h	2019-06-15 14:03:23 UTC (rev 246457)
@@ -51,8 +51,8 @@
             Run(const InlineItem&, const Display::Rect&, TextContext, bool isCollapsed, bool canBeExtended);
 
             const InlineItem& inlineItem;
-            // Relative to the baseline.
             Display::Rect logicalRect;
+            LayoutUnit baseline;
             Optional<TextContext> textContext;
             bool isCollapsed { false };
             bool canBeExtended { false };
@@ -61,7 +61,7 @@
         const Runs& runs() const { return m_runs; }
         bool isEmpty() const { return m_runs.isEmpty(); }
         // Not in painting sense though.
-        bool isVisuallyEmpty() const;
+        bool isVisuallyEmpty() const { return m_isVisuallyEmpty; }
 
         LayoutUnit logicalTop() const { return m_logicalRect.top(); }
         LayoutUnit logicalLeft() const { return m_logicalRect.left(); }
@@ -76,11 +76,13 @@
 
         void setLogicalRect(const Display::Rect& logicalRect) { m_logicalRect = logicalRect; }
         void setBaseline(LineBox::Baseline baseline) { m_baseline = baseline; }
+        void setIsVisuallyEmpty(bool isVisuallyEmpty) { m_isVisuallyEmpty = isVisuallyEmpty; }
         Runs& runs() { return m_runs; }
 
         Display::Rect m_logicalRect;
         LineBox::Baseline m_baseline;
         Runs m_runs;
+        bool m_isVisuallyEmpty { true };
     };
     std::unique_ptr<Content> close();
 
@@ -91,7 +93,7 @@
     void appendInlineContainerEnd(const InlineItem&, LayoutUnit logicalWidth);
     void appendHardLineBreak(const InlineItem&);
 
-    bool hasContent() const { return !m_content->isVisuallyEmpty(); }
+    bool hasContent() const { return !isVisuallyEmpty(); }
 
     LayoutUnit trailingTrimmableWidth() const;
 
@@ -121,6 +123,7 @@
 
     void adjustBaselineAndLineHeight(const InlineItem&, LayoutUnit runHeight);
     LayoutUnit inlineItemHeight(const InlineItem&) const;
+    bool isVisuallyEmpty() const;
 
     const LayoutState& m_layoutState;
     std::unique_ptr<Content> m_content;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to