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;