WebKit Bugzilla
Attachment 371696 Details for
Bug 198697
: [LFC][IFC] Add support for vertical-align: top and bottom
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-198697-20190608190729.patch (text/plain), 13.40 KB, created by
zalan
on 2019-06-08 19:07:31 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
zalan
Created:
2019-06-08 19:07:31 PDT
Size:
13.40 KB
patch
obsolete
>Subversion Revision: 246206 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index ff16d5bad14d1e21b34843da213934a9f1337663..a047cec1bbaadea5093b2dcd044bc96d6f78f554 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,28 @@ >+2019-06-08 Zalan Bujtas <zalan@apple.com> >+ >+ [LFC][IFC] Add support for vertical-align: top and bottom >+ https://bugs.webkit.org/show_bug.cgi?id=198697 >+ <rdar://problem/51556188> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ 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-07 Zalan Bujtas <zalan@apple.com> > > [LFC][IFC] Introduce Baseline to LineBox >diff --git a/Source/WebCore/layout/inlineformatting/InlineLine.cpp b/Source/WebCore/layout/inlineformatting/InlineLine.cpp >index 27f6a785915b6b9b1767fc87b036b533d676a848..191f153c3193044a517c09afee4504a90e270a18 100644 >--- a/Source/WebCore/layout/inlineformatting/InlineLine.cpp >+++ b/Source/WebCore/layout/inlineformatting/InlineLine.cpp >@@ -35,18 +35,6 @@ namespace Layout { > > 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 @@ Line::Line(const LayoutState& layoutState, const LayoutPoint& topLeft, LayoutUni > { > } > >+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 @@ void Line::appendInlineContainerStart(const InlineItem& inlineItem, LayoutUnit l > 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 @@ void Line::appendTextContent(const InlineTextItem& inlineItem, LayoutUnit logica > 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 @@ void Line::appendNonReplacedInlineBox(const InlineItem& inlineItem, LayoutUnit l > if (!m_skipVerticalAligment) { > auto logicalHeight = inlineItemHeight(inlineItem); > adjustBaselineAndLineHeight(inlineItem, logicalHeight); >- >- logicalRect.setTop(-logicalHeight); > logicalRect.setHeight(logicalHeight); > } > >@@ -233,8 +262,11 @@ void Line::appendReplacedInlineBox(const InlineItem& inlineItem, LayoutUnit logi > > 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 @@ void Line::adjustBaselineAndLineHeight(const InlineItem& inlineItem, LayoutUnit > 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 @@ LayoutUnit Line::inlineItemHeight(const InlineItem& inlineItem) const > 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) >diff --git a/Source/WebCore/layout/inlineformatting/InlineLine.h b/Source/WebCore/layout/inlineformatting/InlineLine.h >index 44cc01561f357aa43f9547a7321f5a273864211d..95d2566962c226516ce7e25e10bf2e39678a2f84 100644 >--- a/Source/WebCore/layout/inlineformatting/InlineLine.h >+++ b/Source/WebCore/layout/inlineformatting/InlineLine.h >@@ -51,8 +51,8 @@ public: > 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 @@ public: > 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 @@ public: > > 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 @@ public: > 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 @@ private: > > void adjustBaselineAndLineHeight(const InlineItem&, LayoutUnit runHeight); > LayoutUnit inlineItemHeight(const InlineItem&) const; >+ bool isVisuallyEmpty() const; > > const LayoutState& m_layoutState; > std::unique_ptr<Content> m_content;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 198697
:
371695
| 371696