- Revision
- 230318
- Author
- za...@apple.com
- Date
- 2018-04-05 19:12:26 -0700 (Thu, 05 Apr 2018)
Log Message
[LayoutReloaded] Move floating box to the next line when needed
https://bugs.webkit.org/show_bug.cgi?id=184349
Reviewed by Antti Koivisto.
* LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js:
(InlineFormattingContext.prototype.layout):
(InlineFormattingContext.prototype._handleContent):
(InlineFormattingContext.prototype._handleText):
(InlineFormattingContext.prototype._handleFloatingBox):
(InlineFormattingContext.prototype._mapFloatingHorizontalPosition):
(InlineFormattingContext):
(InlineFormattingContext.prototype._handleFloatingBoxes): Deleted.
(InlineFormattingContext.prototype._floatingBoxes): Deleted.
* LayoutReloaded/FormattingContext/InlineFormatting/Line.js:
(Line.prototype.addTextLineBox):
(Line.prototype.addFloatingBox):
(Line):
* LayoutReloaded/Utils.js:
(LayoutRect.prototype.moveHorizontally):
(LayoutRect.prototype.moveVertically):
* LayoutReloaded/test/index.html:
* LayoutReloaded/test/inline-with-floats-when-they-dont-fit.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/Tools/ChangeLog (230317 => 230318)
--- trunk/Tools/ChangeLog 2018-04-06 01:29:26 UTC (rev 230317)
+++ trunk/Tools/ChangeLog 2018-04-06 02:12:26 UTC (rev 230318)
@@ -1,3 +1,29 @@
+2018-04-05 Zalan Bujtas <za...@apple.com>
+
+ [LayoutReloaded] Move floating box to the next line when needed
+ https://bugs.webkit.org/show_bug.cgi?id=184349
+
+ Reviewed by Antti Koivisto.
+
+ * LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js:
+ (InlineFormattingContext.prototype.layout):
+ (InlineFormattingContext.prototype._handleContent):
+ (InlineFormattingContext.prototype._handleText):
+ (InlineFormattingContext.prototype._handleFloatingBox):
+ (InlineFormattingContext.prototype._mapFloatingHorizontalPosition):
+ (InlineFormattingContext):
+ (InlineFormattingContext.prototype._handleFloatingBoxes): Deleted.
+ (InlineFormattingContext.prototype._floatingBoxes): Deleted.
+ * LayoutReloaded/FormattingContext/InlineFormatting/Line.js:
+ (Line.prototype.addTextLineBox):
+ (Line.prototype.addFloatingBox):
+ (Line):
+ * LayoutReloaded/Utils.js:
+ (LayoutRect.prototype.moveHorizontally):
+ (LayoutRect.prototype.moveVertically):
+ * LayoutReloaded/test/index.html:
+ * LayoutReloaded/test/inline-with-floats-when-they-dont-fit.html: Added.
+
2018-04-05 Brady Eidson <beid...@apple.com>
Process Swap on Navigation causes many webpages to hang due to attempted process swap for iframe navigations.
Modified: trunk/Tools/LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js (230317 => 230318)
--- trunk/Tools/LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js 2018-04-06 01:29:26 UTC (rev 230317)
+++ trunk/Tools/LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js 2018-04-06 02:12:26 UTC (rev 230318)
@@ -37,10 +37,7 @@
// This is a post-order tree traversal layout.
// The root container layout is done in the formatting context it lives in, not that one it creates, so let's start with the first child.
this.m_line = this._createNewLine();
- // Collect floating boxes and layout them first.
- this._handleFloatingBoxes();
- //
- this._addToLayoutQueue(this.formattingRoot().firstInFlowChild());
+ this._addToLayoutQueue(this.formattingRoot().firstInFlowOrFloatChild());
while (this._descendantNeedsLayout()) {
// Travers down on the descendants until we find a leaf node.
while (true) {
@@ -49,18 +46,17 @@
this.layoutState().layout(layoutBox);
break;
}
- if (!layoutBox.isContainer() || !layoutBox.hasChild())
+ if (!layoutBox.isContainer() || !layoutBox.hasInFlowOrFloatChild())
break;
- this._addToLayoutQueue(layoutBox.firstInFlowChild());
+ this._addToLayoutQueue(layoutBox.firstInFlowOrFloatChild());
}
while (this._descendantNeedsLayout()) {
let layoutBox = this._nextInLayoutQueue();
- if (layoutBox instanceof Layout.InlineBox)
- this._handleInlineBox(layoutBox);
+ this._handleContent(layoutBox);
// We are done with laying out this box.
this._removeFromLayoutQueue(layoutBox);
- if (layoutBox.nextInFlowSibling()) {
- this._addToLayoutQueue(layoutBox.nextInFlowSibling());
+ if (layoutBox.nextInFlowOrFloatSibling()) {
+ this._addToLayoutQueue(layoutBox.nextInFlowOrFloatSibling());
break;
}
}
@@ -69,6 +65,18 @@
this._commitLine();
}
+ _handleContent(layoutBox) {
+ if (layoutBox instanceof Layout.InlineBox) {
+ this._handleInlineBox(layoutBox);
+ return;
+ }
+ if (layoutBox.isFloatingPositioned()) {
+ this._handleFloatingBox(layoutBox);
+ return;
+ }
+ ASSERT_NOT_REACHED();
+ }
+
_handleInlineBox(inlineBox) {
if (inlineBox.text())
return this._handleText(inlineBox);
@@ -85,25 +93,22 @@
for (let run of textRuns)
this._line().addTextLineBox(run.startPosition, run.endPosition, new LayoutSize(run.width, Utils.textHeight(inlineBox)));
text = text.slice(textRuns[textRuns.length - 1].endPosition, text.length);
- this._commitLine();
+ // Commit the line unless we run out of content.
+ if (text.length)
+ this._commitLine();
}
}
- _handleFloatingBoxes() {
- let floatingBoxes = this._floatingBoxes();
- for (let floatingBox of floatingBoxes) {
- this._addToLayoutQueue(floatingBox);
- this._handleFloatingBox(floatingBox);
- this._removeFromLayoutQueue(floatingBox);
- }
- }
-
_handleFloatingBox(floatingBox) {
- this.layoutState().layout(floatingBox);
this._computeFloatingWidth(floatingBox);
this._computeFloatingHeight(floatingBox);
+ let displayFloatingBox = this.displayBox(floatingBox);
+ if (displayFloatingBox.width() > this._line().availableWidth())
+ this._commitLine();
+ // Position this float statically first, the floating context will figure it out the final position.
+ displayFloatingBox.setTopLeft(this._line().rect().topLeft());
this.floatingContext().computePosition(floatingBox);
- this._line().addFloatingBox(this.displayBox(floatingBox).size());
+ this._line().addFloatingBox(displayFloatingBox.size());
}
_commitLine() {
@@ -164,33 +169,5 @@
return root.contentBox().left();
return horizontalPosition - rootLeft;
}
-
- _floatingBoxes() {
- ASSERT(this.formattingRoot().firstChild());
- // FIXME: This is highly inefficient but will do for now.
- let floatingBoxes = new Array();
- let stack = new Array();
- stack.push(this.formattingRoot().firstChild());
- while (stack.length) {
- while (true) {
- let box = stack[stack.length - 1];
- if (box.isFloatingPositioned())
- floatingBoxes.push(box);
- if (box.establishesFormattingContext())
- break;
- if (!box.isContainer() || !box.hasChild())
- break;
- stack.push(box.firstChild());
- }
- while (stack.length) {
- let box = stack.pop();
- if (box.nextSibling()) {
- stack.push(box.nextSibling());
- break;
- }
- }
- }
- return floatingBoxes;
- }
}
Modified: trunk/Tools/LayoutReloaded/FormattingContext/InlineFormatting/Line.js (230317 => 230318)
--- trunk/Tools/LayoutReloaded/FormattingContext/InlineFormatting/Line.js 2018-04-06 01:29:26 UTC (rev 230317)
+++ trunk/Tools/LayoutReloaded/FormattingContext/InlineFormatting/Line.js 2018-04-06 02:12:26 UTC (rev 230318)
@@ -47,6 +47,7 @@
}
addTextLineBox(startPosition, endPosition, size) {
+ ASSERT(size.width() <= this.m_availableWidth);
this.m_availableWidth -= size.width();
// TODO: use the actual height instead of the line height.
let lineBoxRect = new LayoutRect(this.rect().topRight(), new LayoutSize(size.width(), this.rect().height()));
@@ -55,8 +56,11 @@
}
addFloatingBox(size) {
- // TODO: Add missing cases.
+ ASSERT(size.width() <= this.m_availableWidth);
+ // Push non-floating boxes to the right.
this.m_availableWidth -= size.width();
- this.m_lineRect.moveBy(new LayoutSize(size.width(), 0));
+ for (let lineBox of this.m_lineBoxes)
+ lineBox.lineBoxRect.moveHorizontally(size.width());
+ this.m_lineRect.moveHorizontally(size.width());
}
}
Modified: trunk/Tools/LayoutReloaded/Utils.js (230317 => 230318)
--- trunk/Tools/LayoutReloaded/Utils.js 2018-04-06 01:29:26 UTC (rev 230317)
+++ trunk/Tools/LayoutReloaded/Utils.js 2018-04-06 02:12:26 UTC (rev 230318)
@@ -207,7 +207,15 @@
moveBy(distance) {
this.m_topLeft.moveBy(distance);
}
-
+
+ moveHorizontally(distance) {
+ this.m_topLeft.shiftLeft(distance);
+ }
+
+ moveVertically(distance) {
+ this.m_topLeft.shiftTop(distance);
+ }
+
isEmpty() {
return this.m_size.isEmpty();
}
Modified: trunk/Tools/LayoutReloaded/test/index.html (230317 => 230318)
--- trunk/Tools/LayoutReloaded/test/index.html 2018-04-06 01:29:26 UTC (rev 230317)
+++ trunk/Tools/LayoutReloaded/test/index.html 2018-04-06 02:12:26 UTC (rev 230318)
@@ -69,7 +69,8 @@
"inline-formatting-context-with-floats2.html",
"float-is-inside-inline-formatting-context-simple.html",
"multiple-left-floats-on-line-simple.html",
- "multiple-left-floats-on-line-from-parent-formatting-context.html"
+ "multiple-left-floats-on-line-from-parent-formatting-context.html",
+ "inline-with-floats-when-they-dont-fit.html"
];
let debugThis = [];
Added: trunk/Tools/LayoutReloaded/test/inline-with-floats-when-they-dont-fit.html (0 => 230318)
--- trunk/Tools/LayoutReloaded/test/inline-with-floats-when-they-dont-fit.html (rev 0)
+++ trunk/Tools/LayoutReloaded/test/inline-with-floats-when-they-dont-fit.html 2018-04-06 02:12:26 UTC (rev 230318)
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div style="width: 100px; height: 100px;">foobar<div style="float: left; width: 20px; height: 20px;"></div><div style="float: left; width: 60px; height: 20px;"></div></div>
+</body>
+</html>