Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(540)

Unified Diff: third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp

Issue 2532573003: Position a float before laying it out. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
index dd29fed7bae60dbf585a4a6250e217eff5ff7fa2..402aab313aef5c0bd1185f564cebacd9f6b4e0dd 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -3533,15 +3533,6 @@ FloatingObject* LayoutBlockFlow::insertFloatingObject(LayoutBox& floatBox) {
// Create the special object entry & append it to the list
std::unique_ptr<FloatingObject> newObj = FloatingObject::create(&floatBox);
-
- // TODO(mstensho): Avoid laying out before positioning the object, as that's
- // bad for pagination.
- floatBox.layoutIfNeeded();
-
- setLogicalWidthForFloat(*newObj, logicalWidthForChild(floatBox) +
- marginStartForChild(floatBox) +
- marginEndForChild(floatBox));
-
return m_floatingObjects->add(std::move(newObj));
}
@@ -3675,38 +3666,81 @@ LayoutUnit LayoutBlockFlow::positionAndLayoutFloat(
}
}
+ if (child.needsLayout()) {
+ if (isPaginated) {
+ // Before we can lay out the float, we need to estimate a position for
+ // it. In order to do that, we first need to know its block start margin.
+ child.computeAndSetBlockDirectionMargins(this);
+ LayoutUnit marginBefore = marginBeforeForChild(child);
+
+ // We have found the highest possible position for the float, so we'll
+ // lay out right there. Later on, we may be pushed further down by
+ // adjacent floats which we don't fit beside, or pushed by fragmentation
+ // if we need to break before the top margin edge of the float.
+ setLogicalTopForChild(child, logicalTopMarginEdge + marginBefore);
+ child.layout();
+
+ // May need to push the float to the next fragmentainer before attempting
+ // to place it.
+ logicalTopMarginEdge =
+ adjustFloatLogicalTopForPagination(child, logicalTopMarginEdge);
+ } else {
+ child.layout();
+ }
+ }
+
+ LayoutUnit marginStart = marginStartForChild(child);
+ LayoutUnit marginEnd = marginEndForChild(child);
+ setLogicalWidthForFloat(
+ floatingObject, logicalWidthForChild(child) + marginStart + marginEnd);
+
+ // We have determined the logical width of the float. This is enough
+ // information to fit it among other floats according to float positioning
+ // rules. Note that logical *height* doesn't really matter yet (until we're
+ // going to place subsequent floats or other objects that are affected by
+ // floats), since no float may be positioned above the outer logical top edge
+ // of any other earlier float in the block formatting context.
LayoutUnit marginBefore = marginBeforeForChild(child);
LayoutUnit marginAfter = marginAfterForChild(child);
LayoutPoint floatLogicalLocation =
computeLogicalLocationForFloat(floatingObject, logicalTopMarginEdge);
logicalTopMarginEdge = floatLogicalLocation.y();
-
setLogicalTopForChild(child, logicalTopMarginEdge + marginBefore);
SubtreeLayoutScope layoutScope(child);
- if (!child.needsLayout())
- markChildForPaginationRelayoutIfNeeded(child, layoutScope);
+ // A new position may mean that we need to insert, move or remove breaks
+ // inside the float. We may also need to lay out if we just ceased to be
+ // fragmented, in order to remove pagination struts inside the child.
+ markChildForPaginationRelayoutIfNeeded(child, layoutScope);
child.layoutIfNeeded();
if (isPaginated) {
+ // We may have to insert a break before the float.
LayoutUnit newLogicalTopMarginEdge =
adjustFloatLogicalTopForPagination(child, logicalTopMarginEdge);
if (logicalTopMarginEdge != newLogicalTopMarginEdge) {
+ // We had already found a location for the float, but a soft
+ // fragmentainer break then made us push it further down. This may affect
+ // the inline position of the float (since we may no longer be beside the
+ // same floats anymore). Block position will remain unaffected, though.
floatLogicalLocation = computeLogicalLocationForFloat(
floatingObject, newLogicalTopMarginEdge);
- logicalTopMarginEdge = floatLogicalLocation.y();
+ DCHECK_EQ(floatLogicalLocation.y(), newLogicalTopMarginEdge);
+ logicalTopMarginEdge = newLogicalTopMarginEdge;
+
setLogicalTopForChild(child, logicalTopMarginEdge + marginBefore);
+ // Pushing the child to the next fragmentainer most likely means that we
+ // need to recalculate pagination struts inside it.
if (child.isLayoutBlock())
child.setChildNeedsLayout(MarkOnlyThis);
child.layoutIfNeeded();
}
}
- LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection()
- ? marginStartForChild(child)
- : marginEndForChild(child);
+ LayoutUnit childLogicalLeftMargin =
+ style()->isLeftToRightDirection() ? marginStart : marginEnd;
setLogicalLeftForChild(child,
floatLogicalLocation.x() + childLogicalLeftMargin);
setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x());

Powered by Google App Engine
This is Rietveld 408576698