Changeset 246457 in webkit
- Timestamp:
- Jun 15, 2019, 7:03:23 AM (7 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
-
ChangeLog (modified) (1 diff)
-
layout/inlineformatting/InlineLine.cpp (modified) (8 diffs)
-
layout/inlineformatting/InlineLine.h (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r246445 r246457 1 2019-06-15 Zalan Bujtas <zalan@apple.com> 2 3 [LFC][IFC] Add support for vertical-align: top and bottom 4 https://bugs.webkit.org/show_bug.cgi?id=198697 5 <rdar://problem/51556188> 6 7 Reviewed by Antti Koivisto. 8 9 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. 10 11 * layout/inlineformatting/InlineLine.cpp: 12 (WebCore::Layout::Line::isVisuallyEmpty const): 13 (WebCore::Layout::Line::close): 14 (WebCore::Layout::Line::appendInlineContainerStart): 15 (WebCore::Layout::Line::appendTextContent): 16 (WebCore::Layout::Line::appendNonReplacedInlineBox): 17 (WebCore::Layout::Line::appendHardLineBreak): 18 (WebCore::Layout::Line::adjustBaselineAndLineHeight): 19 (WebCore::Layout::Line::inlineItemHeight const): 20 (WebCore::Layout::Line::Content::isVisuallyEmpty const): Deleted. 21 * layout/inlineformatting/InlineLine.h: 22 (WebCore::Layout::Line::Content::isVisuallyEmpty const): 23 (WebCore::Layout::Line::Content::setIsVisuallyEmpty): 24 (WebCore::Layout::Line::hasContent const): 25 1 26 2019-06-14 Antoine Quint <graouts@apple.com> 2 27 -
trunk/Source/WebCore/layout/inlineformatting/InlineLine.cpp
r246234 r246457 36 36 WTF_MAKE_ISO_ALLOCATED_IMPL(Line); 37 37 38 bool Line::Content::isVisuallyEmpty() const39 {40 // Return true for empty inline containers like <span></span>.41 for (auto& run : m_runs) {42 if (run->inlineItem.isContainerStart() || run->inlineItem.isContainerEnd())43 continue;44 if (!run->isCollapsed)45 return false;46 }47 return true;48 }49 50 38 Line::Content::Run::Run(const InlineItem& inlineItem, const Display::Rect& logicalRect, TextContext textContext, bool isCollapsed, bool canBeExtended) 51 39 : inlineItem(inlineItem) … … 76 64 } 77 65 66 bool Line::isVisuallyEmpty() const 67 { 68 // FIXME: This should be cached instead -as the inline items are being added. 69 // Return true for empty inline containers like <span></span>. 70 for (auto& run : m_content->runs()) { 71 if (run->inlineItem.isContainerStart()) { 72 auto& displayBox = m_layoutState.displayBoxForLayoutBox(run->inlineItem.layoutBox()); 73 if (displayBox.horizontalBorder() || (displayBox.horizontalPadding() && displayBox.horizontalPadding().value())) 74 return false; 75 continue; 76 } 77 if (run->inlineItem.isContainerEnd()) 78 continue; 79 if (!run->isCollapsed) 80 return false; 81 } 82 return true; 83 } 84 78 85 std::unique_ptr<Line::Content> Line::close() 79 86 { 80 87 removeTrailingTrimmableContent(); 81 88 if (!m_skipVerticalAligment) { 82 // Convert inline run geometry from relative to the baseline to relative to logical top.83 89 for (auto& run : m_content->runs()) { 84 auto adjustedLogicalTop = run->logicalRect.top() + baselineOffset(); 85 run->logicalRect.setTop(adjustedLogicalTop); 86 } 87 } 90 LayoutUnit logicalTop; 91 auto& inlineItem = run->inlineItem; 92 auto& layoutBox = inlineItem.layoutBox(); 93 auto ascent = inlineItem.style().fontMetrics().ascent(); 94 95 switch (inlineItem.style().verticalAlign()) { 96 case VerticalAlign::Baseline: 97 if (inlineItem.isLineBreak() || inlineItem.isText()) 98 logicalTop = baselineOffset() - ascent; 99 else if (inlineItem.isContainerStart()) { 100 auto& displayBox = m_layoutState.displayBoxForLayoutBox(layoutBox); 101 logicalTop = baselineOffset() - ascent - displayBox.borderTop() - displayBox.paddingTop().valueOr(0); 102 } else if (layoutBox.isInlineBlockBox() && layoutBox.establishesInlineFormattingContext()) { 103 auto& formattingState = downcast<InlineFormattingState>(m_layoutState.establishedFormattingState(layoutBox)); 104 // Spec makes us generate at least one line -even if it is empty. 105 ASSERT(!formattingState.lineBoxes().isEmpty()); 106 auto inlineBlockBaseline = formattingState.lineBoxes().last().baseline(); 107 logicalTop = baselineOffset() - inlineBlockBaseline.ascent; 108 } else 109 logicalTop = baselineOffset() - run->logicalRect.height(); 110 break; 111 case VerticalAlign::Top: 112 logicalTop = { }; 113 break; 114 case VerticalAlign::Bottom: 115 logicalTop = logicalBottom() - run->logicalRect.height(); 116 break; 117 default: 118 ASSERT_NOT_IMPLEMENTED_YET(); 119 break; 120 } 121 run->logicalRect.setTop(logicalTop); 122 } 123 } 124 m_content->setIsVisuallyEmpty(isVisuallyEmpty()); 88 125 m_content->setLogicalRect({ logicalTop(), logicalLeft(), contentLogicalWidth(), logicalHeight() }); 89 126 m_content->setBaseline(m_baseline); … … 143 180 auto logicalHeight = inlineItemHeight(inlineItem); 144 181 adjustBaselineAndLineHeight(inlineItem, logicalHeight); 145 146 auto& displayBox = m_layoutState.displayBoxForLayoutBox(inlineItem.layoutBox());147 auto logicalTop = -inlineItem.style().fontMetrics().ascent() - displayBox.borderTop() - displayBox.paddingTop().valueOr(0);148 logicalRect.setTop(logicalTop);149 182 logicalRect.setHeight(logicalHeight); 150 183 } … … 191 224 logicalRect.setLeft(contentLogicalRight()); 192 225 logicalRect.setWidth(logicalWidth); 193 if (!m_skipVerticalAligment) { 194 logicalRect.setTop(-inlineItem.style().fontMetrics().ascent()); 226 if (!m_skipVerticalAligment) 195 227 logicalRect.setHeight(inlineItemHeight(inlineItem)); 196 }197 228 198 229 auto textContext = Content::Run::TextContext { inlineItem.start(), inlineItem.isCollapsed() ? 1 : inlineItem.length() }; … … 216 247 auto logicalHeight = inlineItemHeight(inlineItem); 217 248 adjustBaselineAndLineHeight(inlineItem, logicalHeight); 218 219 logicalRect.setTop(-logicalHeight);220 249 logicalRect.setHeight(logicalHeight); 221 250 } … … 234 263 void Line::appendHardLineBreak(const InlineItem& inlineItem) 235 264 { 236 auto ascent = inlineItem.layoutBox().style().fontMetrics().ascent(); 237 auto logicalRect = Display::Rect { -ascent, contentLogicalRight(), { }, logicalHeight() }; 265 auto logicalRect = Display::Rect { }; 266 logicalRect.setLeft(contentLogicalRight()); 267 logicalRect.setWidth({ }); 268 if (!m_skipVerticalAligment) 269 logicalRect.setHeight(logicalHeight()); 238 270 m_content->runs().append(std::make_unique<Content::Run>(inlineItem, logicalRect, Content::Run::TextContext { }, false, false)); 239 271 } … … 256 288 } 257 289 // Replaced and non-replaced inline level box. 258 // FIXME: We need to look inside the inline-block's formatting context and check the lineboxes (if any) to be able to baseline align. 259 if (layoutBox.establishesInlineFormattingContext()) { 260 if (runHeight == logicalHeight()) 261 return; 262 // FIXME: This fails when the line height difference comes from font-size diff. 290 switch (inlineItem.style().verticalAlign()) { 291 case VerticalAlign::Baseline: 292 if (layoutBox.isInlineBlockBox() && layoutBox.establishesInlineFormattingContext()) { 293 // Inline-blocks with inline content always have baselines. 294 auto& formattingState = downcast<InlineFormattingState>(m_layoutState.establishedFormattingState(layoutBox)); 295 // Spec makes us generate at least one line -even if it is empty. 296 ASSERT(!formattingState.lineBoxes().isEmpty()); 297 auto inlineBlockBaseline = formattingState.lineBoxes().last().baseline(); 298 m_baseline.descent = std::max(inlineBlockBaseline.descent, m_baseline.descent); 299 m_baseline.ascent = std::max(inlineBlockBaseline.ascent, m_baseline.ascent); 300 m_contentLogicalHeight = std::max(std::max(m_contentLogicalHeight, runHeight), baselineAlignedContentHeight()); 301 break; 302 } 263 303 m_baseline.descent = std::max<LayoutUnit>(0, m_baseline.descent); 264 304 m_baseline.ascent = std::max(runHeight, m_baseline.ascent); 265 305 m_contentLogicalHeight = std::max(m_contentLogicalHeight, baselineAlignedContentHeight()); 266 return; 267 } 268 // 0 descent -> baseline aligment for now. 269 m_baseline.descent = std::max<LayoutUnit>(0, m_baseline.descent); 270 m_baseline.ascent = std::max(runHeight, m_baseline.ascent); 271 m_contentLogicalHeight = std::max(m_contentLogicalHeight, baselineAlignedContentHeight()); 306 break; 307 case VerticalAlign::Top: 308 // Top align content never changes the baseline offset, it only pushes the bottom of the line further down. 309 m_contentLogicalHeight = std::max(runHeight, m_contentLogicalHeight); 310 break; 311 case VerticalAlign::Bottom: 312 if (m_contentLogicalHeight < runHeight) { 313 m_baseline.offset = m_baseline.offset + (runHeight - m_contentLogicalHeight); 314 m_contentLogicalHeight = runHeight; 315 } 316 break; 317 default: 318 ASSERT_NOT_IMPLEMENTED_YET(); 319 break; 320 } 272 321 } 273 322 … … 293 342 294 343 // Non-replaced inline box (e.g. inline-block) 295 return displayBox. height();344 return displayBox.marginBox().height(); 296 345 } 297 346 -
trunk/Source/WebCore/layout/inlineformatting/InlineLine.h
r246234 r246457 52 52 53 53 const InlineItem& inlineItem; 54 // Relative to the baseline.55 54 Display::Rect logicalRect; 55 LayoutUnit baseline; 56 56 Optional<TextContext> textContext; 57 57 bool isCollapsed { false }; … … 62 62 bool isEmpty() const { return m_runs.isEmpty(); } 63 63 // Not in painting sense though. 64 bool isVisuallyEmpty() const ;64 bool isVisuallyEmpty() const { return m_isVisuallyEmpty; } 65 65 66 66 LayoutUnit logicalTop() const { return m_logicalRect.top(); } … … 77 77 void setLogicalRect(const Display::Rect& logicalRect) { m_logicalRect = logicalRect; } 78 78 void setBaseline(LineBox::Baseline baseline) { m_baseline = baseline; } 79 void setIsVisuallyEmpty(bool isVisuallyEmpty) { m_isVisuallyEmpty = isVisuallyEmpty; } 79 80 Runs& runs() { return m_runs; } 80 81 … … 82 83 LineBox::Baseline m_baseline; 83 84 Runs m_runs; 85 bool m_isVisuallyEmpty { true }; 84 86 }; 85 87 std::unique_ptr<Content> close(); … … 92 94 void appendHardLineBreak(const InlineItem&); 93 95 94 bool hasContent() const { return ! m_content->isVisuallyEmpty(); }96 bool hasContent() const { return !isVisuallyEmpty(); } 95 97 96 98 LayoutUnit trailingTrimmableWidth() const; … … 122 124 void adjustBaselineAndLineHeight(const InlineItem&, LayoutUnit runHeight); 123 125 LayoutUnit inlineItemHeight(const InlineItem&) const; 126 bool isVisuallyEmpty() const; 124 127 125 128 const LayoutState& m_layoutState;
Note:
See TracChangeset
for help on using the changeset viewer.