Changeset 234927 in webkit
- Timestamp:
- Aug 16, 2018 8:43:53 AM (6 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r234925 r234927 1 2018-08-16 Zalan Bujtas <zalan@apple.com> 2 3 [lFC][Floating] Add estimated margin top computation. 4 https://bugs.webkit.org/show_bug.cgi?id=188619 5 6 Reviewed by Antti Koivisto. 7 8 In order to figure out whether a box should avoid a float, we need to know the final positions of both (ignore relative positioning for now). 9 In block formatting context the final position for a normal flow box includes 10 1. the static position and 11 2. the corresponding (non)collapsed margins. 12 Now the vertical margins are computed when all the descendants are finalized, because the margin values might be depending on the height of the box 13 (and the height might be based on the content). 14 So when we get to the point where we intersect the box with the float to decide if the box needs to move, we don't yet have the final vertical position. 15 16 The idea here is that as long as we don't cross the block formatting context boundary, we should be able to pre-compute the final top margin. 17 (if this holds true for all the cases, the estimated prefix could be removed and just use marginTop() instead.) 18 19 Covered by existing block-only tests. 20 21 * layout/blockformatting/BlockFormattingContext.cpp: 22 (WebCore::Layout::BlockFormattingContext::layout const): 23 (WebCore::Layout::BlockFormattingContext::computeEstimatedMarginTop const): 24 (WebCore::Layout::BlockFormattingContext::computeEstimatedMarginTopForAncestors const): 25 (WebCore::Layout::BlockFormattingContext::computeFloatingPosition const): 26 (WebCore::Layout::BlockFormattingContext::computeVerticalPositionForFloatClear const): 27 (WebCore::Layout::BlockFormattingContext::computeInFlowHeightAndMargin const): 28 * layout/blockformatting/BlockFormattingContext.h: 29 * layout/blockformatting/BlockMarginCollapse.cpp: 30 (WebCore::Layout::BlockFormattingContext::MarginCollapse::estimatedMarginTop): 31 * layout/displaytree/DisplayBox.cpp: 32 (WebCore::Display::Box::Box): 33 * layout/displaytree/DisplayBox.h: 34 (WebCore::Display::Box::setHasValidTop): 35 (WebCore::Display::Box::setHasValidLeft): 36 (WebCore::Display::Box::top const): 37 (WebCore::Display::Box::left const): 38 (WebCore::Display::Box::topLeft const): 39 (WebCore::Display::Box::setTopLeft): 40 (WebCore::Display::Box::setTop): 41 (WebCore::Display::Box::setLeft): 42 (WebCore::Display::Box::setVerticalMargin): 43 (WebCore::Display::Box::setEstimatedMarginTop): 44 (WebCore::Display::Box::estimatedMarginTop const): 45 1 46 2018-08-16 Zalan Bujtas <zalan@apple.com> 2 47 -
trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp
r234847 r234927 114 114 // Finalize position with clearance. 115 115 if (layoutBox.hasFloatClear()) 116 computeVerticalPositionForFloatClear( floatingContext, layoutBox, displayBox);116 computeVerticalPositionForFloatClear(layoutContext, floatingContext, layoutBox, displayBox); 117 117 if (!is<Container>(layoutBox)) 118 118 continue; … … 157 157 } 158 158 159 void BlockFormattingContext::computeEstimatedMarginTop(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const 160 { 161 auto estimatedMarginTop = MarginCollapse::estimatedMarginTop(layoutContext, layoutBox); 162 displayBox.setEstimatedMarginTop(estimatedMarginTop); 163 displayBox.moveVertically(estimatedMarginTop); 164 } 165 166 void BlockFormattingContext::computeEstimatedMarginTopForAncestors(LayoutContext& layoutContext, const Box& layoutBox) const 167 { 168 // We only need to estimate margin top for float related layout. 169 ASSERT(layoutBox.isFloatingPositioned() || layoutBox.hasFloatClear()); 170 171 // In order to figure out whether a box should avoid a float, we need to know the final positions of both (ignore relative positioning for now). 172 // In block formatting context the final position for a normal flow box includes 173 // 1. the static position and 174 // 2. the corresponding (non)collapsed margins. 175 // Now the vertical margins are computed when all the descendants are finalized, because the margin values might be depending on the height of the box 176 // (and the height might be based on the content). 177 // So when we get to the point where we intersect the box with the float to decide if the box needs to move, we don't yet have the final vertical position. 178 // 179 // The idea here is that as long as we don't cross the block formatting context boundary, we should be able to pre-compute the final top margin. 180 181 for (auto* ancestor = layoutBox.containingBlock(); ancestor && !ancestor->establishesBlockFormattingContext(); ancestor = ancestor->containingBlock()) { 182 auto* displayBox = layoutContext.displayBoxForLayoutBox(*ancestor); 183 ASSERT(displayBox); 184 // FIXME: with incremental layout, we might actually have a valid (non-estimated) margin top as well. 185 if (displayBox->estimatedMarginTop()) 186 return; 187 188 computeEstimatedMarginTop(layoutContext, *ancestor, *displayBox); 189 } 190 } 191 159 192 void BlockFormattingContext::computeFloatingPosition(LayoutContext& layoutContext, FloatingContext& floatingContext, const Box& layoutBox, Display::Box& displayBox) const 160 193 { … … 167 200 displayBox.moveVertically(previousDisplayBox.nonCollapsedMarginBottom() - previousDisplayBox.marginBottom()); 168 201 } 202 computeEstimatedMarginTopForAncestors(layoutContext, layoutBox); 169 203 displayBox.setTopLeft(floatingContext.positionForFloat(layoutBox)); 170 204 floatingContext.floatingState().append(layoutBox); 171 205 } 172 206 173 void BlockFormattingContext::computeVerticalPositionForFloatClear( const FloatingContext& floatingContext, const Box& layoutBox, Display::Box& displayBox) const207 void BlockFormattingContext::computeVerticalPositionForFloatClear(LayoutContext& layoutContext, const FloatingContext& floatingContext, const Box& layoutBox, Display::Box& displayBox) const 174 208 { 175 209 ASSERT(layoutBox.hasFloatClear()); 210 if (floatingContext.floatingState().isEmpty()) 211 return; 212 213 computeEstimatedMarginTopForAncestors(layoutContext, layoutBox); 176 214 if (auto verticalPositionWithClearance = floatingContext.verticalPositionWithClearance(layoutBox)) 177 215 displayBox.setTop(*verticalPositionWithClearance); … … 209 247 auto heightAndMargin = Geometry::inFlowHeightAndMargin(layoutContext, layoutBox); 210 248 displayBox.setContentBoxHeight(heightAndMargin.height); 211 displayBox.moveVertically(heightAndMargin.collapsedMargin.value_or(heightAndMargin.margin).top);212 displayBox.setVerticalMargin( heightAndMargin.collapsedMargin.value_or(heightAndMargin.margin));249 auto marginValue = heightAndMargin.collapsedMargin.value_or(heightAndMargin.margin); 250 displayBox.setVerticalMargin(marginValue); 213 251 displayBox.setVerticalNonCollapsedMargin(heightAndMargin.margin); 252 253 // This box has already been moved by the estimated vertical margin. No need to move it again. 254 if (!displayBox.estimatedMarginTop()) 255 displayBox.moveVertically(marginValue.top); 214 256 } 215 257 -
trunk/Source/WebCore/layout/blockformatting/BlockFormattingContext.h
r234847 r234927 58 58 void computeStaticPosition(LayoutContext&, const Box&, Display::Box&) const override; 59 59 void computeFloatingPosition(LayoutContext&, FloatingContext&, const Box&, Display::Box&) const; 60 void computeVerticalPositionForFloatClear( const FloatingContext&, const Box&, Display::Box&) const;60 void computeVerticalPositionForFloatClear(LayoutContext&, const FloatingContext&, const Box&, Display::Box&) const; 61 61 void computeInFlowPositionedPosition(LayoutContext&, const Box&, Display::Box&) const override; 62 62 void computeInFlowWidthAndMargin(LayoutContext&, const Box&, Display::Box&) const; 63 63 void computeInFlowHeightAndMargin(LayoutContext&, const Box&, Display::Box&) const; 64 void computeEstimatedMarginTop(LayoutContext&, const Box&, Display::Box&) const; 65 void computeEstimatedMarginTopForAncestors(LayoutContext&, const Box&) const; 64 66 65 67 FormattingContext::InstrinsicWidthConstraints instrinsicWidthConstraints(LayoutContext&, const Box&) const override; … … 88 90 public: 89 91 static LayoutUnit marginTop(const LayoutContext&, const Box&); 92 static LayoutUnit estimatedMarginTop(const LayoutContext&, const Box&); 90 93 static LayoutUnit marginBottom(const LayoutContext&, const Box&); 91 94 -
trunk/Source/WebCore/layout/blockformatting/BlockMarginCollapse.cpp
r234786 r234927 333 333 } 334 334 335 LayoutUnit BlockFormattingContext::MarginCollapse::estimatedMarginTop(const LayoutContext& layoutContext, const Box& layoutBox) 336 { 337 ASSERT(layoutBox.isBlockLevelBox()); 338 // Can't estimate vertical margins for out of flow boxes (and we shouldn't need to do it for float boxes). 339 ASSERT(layoutBox.isInFlow()); 340 // Can't cross block formatting context boundary. 341 ASSERT(!layoutBox.establishesBlockFormattingContext()); 342 343 // Let's just use the normal path for now. 344 return marginTop(layoutContext, layoutBox); 345 } 346 335 347 } 336 348 } -
trunk/Source/WebCore/layout/displaytree/DisplayBox.cpp
r234476 r234927 60 60 , m_margin(other.m_margin) 61 61 , m_verticalNonCollapsedMargin(other.m_verticalNonCollapsedMargin) 62 , m_estimatedMarginTop(other.m_estimatedMarginTop) 62 63 , m_border(other.m_border) 63 64 , m_padding(other.m_padding) 64 65 #if !ASSERT_DISABLED 66 , m_hasValidTop(other.m_hasValidTop) 67 , m_hasValidLeft(other.m_hasValidLeft) 65 68 , m_hasValidHorizontalMargin(other.m_hasValidHorizontalMargin) 66 69 , m_hasValidVerticalMargin(other.m_hasValidVerticalMargin) -
trunk/Source/WebCore/layout/displaytree/DisplayBox.h
r234925 r234927 118 118 ~Box(); 119 119 120 LayoutUnit top() const { return m_topLeft.y(); }121 LayoutUnit left() const { return m_topLeft.x(); }120 LayoutUnit top() const; 121 LayoutUnit left() const; 122 122 LayoutUnit bottom() const { return top() + height(); } 123 123 LayoutUnit right() const { return left() + width(); } 124 124 125 LayoutPoint topLeft() const { return m_topLeft; }125 LayoutPoint topLeft() const; 126 126 LayoutPoint bottomRight() const { return { right(), bottom() }; } 127 127 … … 139 139 LayoutUnit nonCollapsedMarginTop() const; 140 140 LayoutUnit nonCollapsedMarginBottom() const; 141 std::optional<LayoutUnit> estimatedMarginTop() const { return m_estimatedMarginTop; } 141 142 142 143 LayoutUnit borderTop() const; … … 173 174 }; 174 175 175 void setTopLeft(const LayoutPoint& topLeft) { m_topLeft = topLeft; }176 void setTop(LayoutUnit top) { m_topLeft.setY(top); }177 void setLeft(LayoutUnit left) { m_topLeft.setX(left); }176 void setTopLeft(const LayoutPoint&); 177 void setTop(LayoutUnit); 178 void setLeft(LayoutUnit); 178 179 void moveHorizontally(LayoutUnit offset) { m_topLeft.move(offset, { }); } 179 180 void moveVertically(LayoutUnit offset) { m_topLeft.move({ }, offset); } … … 185 186 void setVerticalMargin(Layout::VerticalEdges); 186 187 void setVerticalNonCollapsedMargin(Layout::VerticalEdges); 188 void setEstimatedMarginTop(LayoutUnit marginTop) { m_estimatedMarginTop = marginTop; } 187 189 188 190 void setBorder(Layout::Edges); … … 194 196 void invalidatePadding() { m_hasValidPadding = false; } 195 197 198 void setHasValidTop() { m_hasValidTop = true; } 199 void setHasValidLeft() { m_hasValidLeft = true; } 196 200 void setHasValidVerticalMargin() { m_hasValidVerticalMargin = true; } 197 201 void setHasValidVerticalNonCollapsedMargin() { m_hasValidVerticalNonCollapsedMargin = true; } … … 213 217 Layout::Edges m_margin; 214 218 Layout::VerticalEdges m_verticalNonCollapsedMargin; 219 std::optional<LayoutUnit> m_estimatedMarginTop; 215 220 216 221 Layout::Edges m_border; … … 218 223 219 224 #if !ASSERT_DISABLED 225 bool m_hasValidTop { false }; 226 bool m_hasValidLeft { false }; 220 227 bool m_hasValidHorizontalMargin { false }; 221 228 bool m_hasValidVerticalMargin { false }; … … 417 424 } 418 425 426 inline LayoutUnit Box::top() const 427 { 428 ASSERT(m_hasValidTop && (m_estimatedMarginTop || m_hasValidVerticalMargin)); 429 return m_topLeft.y(); 430 } 431 432 inline LayoutUnit Box::left() const 433 { 434 ASSERT(m_hasValidLeft && m_hasValidHorizontalMargin); 435 return m_topLeft.x(); 436 } 437 438 inline LayoutPoint Box::topLeft() const 439 { 440 ASSERT(m_hasValidTop && (m_estimatedMarginTop || m_hasValidVerticalMargin)); 441 ASSERT(m_hasValidLeft && m_hasValidHorizontalMargin); 442 return m_topLeft; 443 } 444 445 inline void Box::setTopLeft(const LayoutPoint& topLeft) 446 { 447 #if !ASSERT_DISABLED 448 setHasValidTop(); 449 setHasValidLeft(); 450 #endif 451 m_topLeft = topLeft; 452 } 453 454 inline void Box::setTop(LayoutUnit top) 455 { 456 #if !ASSERT_DISABLED 457 setHasValidTop(); 458 #endif 459 m_topLeft.setY(top); 460 } 461 462 inline void Box::setLeft(LayoutUnit left) 463 { 464 #if !ASSERT_DISABLED 465 setHasValidLeft(); 466 #endif 467 m_topLeft.setX(left); 468 } 469 419 470 inline void Box::setContentBoxHeight(LayoutUnit height) 420 471 { … … 458 509 setHasValidVerticalMargin(); 459 510 #endif 511 ASSERT(!m_estimatedMarginTop || *m_estimatedMarginTop == margin.top); 460 512 m_margin.vertical = margin; 461 513 }
Note: See TracChangeset
for help on using the changeset viewer.