Tools/ChangeLog

 12018-04-05 Zalan Bujtas <zalan@apple.com>
 2
 3 [LayoutReloaded] Move floating box to the next line when needed
 4 https://bugs.webkit.org/show_bug.cgi?id=184349
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js:
 9 (InlineFormattingContext.prototype.layout):
 10 (InlineFormattingContext.prototype._handleContent):
 11 (InlineFormattingContext.prototype._handleText):
 12 (InlineFormattingContext.prototype._handleFloatingBox):
 13 (InlineFormattingContext.prototype._mapFloatingHorizontalPosition):
 14 (InlineFormattingContext):
 15 (InlineFormattingContext.prototype._handleFloatingBoxes): Deleted.
 16 (InlineFormattingContext.prototype._floatingBoxes): Deleted.
 17 * LayoutReloaded/FormattingContext/InlineFormatting/Line.js:
 18 (Line.prototype.addTextLineBox):
 19 (Line.prototype.addFloatingBox):
 20 (Line):
 21 * LayoutReloaded/Utils.js:
 22 (LayoutRect.prototype.moveHorizontally):
 23 (LayoutRect.prototype.moveVertically):
 24 * LayoutReloaded/test/index.html:
 25 * LayoutReloaded/test/inline-with-floats-when-they-dont-fit.html: Added.
 26
1272018-04-05 Brady Eidson <beidson@apple.com>
228
329 Process Swap on Navigation causes many webpages to hang due to attempted process swap for iframe navigations.

Tools/LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js

@@class InlineFormattingContext extends FormattingContext {
3737 // This is a post-order tree traversal layout.
3838 // 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.
3939 this.m_line = this._createNewLine();
40  // Collect floating boxes and layout them first.
41  this._handleFloatingBoxes();
42  //
43  this._addToLayoutQueue(this.formattingRoot().firstInFlowChild());
 40 this._addToLayoutQueue(this.formattingRoot().firstInFlowOrFloatChild());
4441 while (this._descendantNeedsLayout()) {
4542 // Travers down on the descendants until we find a leaf node.
4643 while (true) {

@@class InlineFormattingContext extends FormattingContext {
4946 this.layoutState().layout(layoutBox);
5047 break;
5148 }
52  if (!layoutBox.isContainer() || !layoutBox.hasChild())
 49 if (!layoutBox.isContainer() || !layoutBox.hasInFlowOrFloatChild())
5350 break;
54  this._addToLayoutQueue(layoutBox.firstInFlowChild());
 51 this._addToLayoutQueue(layoutBox.firstInFlowOrFloatChild());
5552 }
5653 while (this._descendantNeedsLayout()) {
5754 let layoutBox = this._nextInLayoutQueue();
58  if (layoutBox instanceof Layout.InlineBox)
59  this._handleInlineBox(layoutBox);
 55 this._handleContent(layoutBox);
6056 // We are done with laying out this box.
6157 this._removeFromLayoutQueue(layoutBox);
62  if (layoutBox.nextInFlowSibling()) {
63  this._addToLayoutQueue(layoutBox.nextInFlowSibling());
 58 if (layoutBox.nextInFlowOrFloatSibling()) {
 59 this._addToLayoutQueue(layoutBox.nextInFlowOrFloatSibling());
6460 break;
6561 }
6662 }

@@class InlineFormattingContext extends FormattingContext {
6965 this._commitLine();
7066 }
7167
 68 _handleContent(layoutBox) {
 69 if (layoutBox instanceof Layout.InlineBox) {
 70 this._handleInlineBox(layoutBox);
 71 return;
 72 }
 73 if (layoutBox.isFloatingPositioned()) {
 74 this._handleFloatingBox(layoutBox);
 75 return;
 76 }
 77 ASSERT_NOT_REACHED();
 78 }
 79
7280 _handleInlineBox(inlineBox) {
7381 if (inlineBox.text())
7482 return this._handleText(inlineBox);

@@class InlineFormattingContext extends FormattingContext {
8593 for (let run of textRuns)
8694 this._line().addTextLineBox(run.startPosition, run.endPosition, new LayoutSize(run.width, Utils.textHeight(inlineBox)));
8795 text = text.slice(textRuns[textRuns.length - 1].endPosition, text.length);
88  this._commitLine();
89  }
90  }
91 
92  _handleFloatingBoxes() {
93  let floatingBoxes = this._floatingBoxes();
94  for (let floatingBox of floatingBoxes) {
95  this._addToLayoutQueue(floatingBox);
96  this._handleFloatingBox(floatingBox);
97  this._removeFromLayoutQueue(floatingBox);
 96 // Commit the line unless we run out of content.
 97 if (text.length)
 98 this._commitLine();
9899 }
99100 }
100101
101102 _handleFloatingBox(floatingBox) {
102  this.layoutState().layout(floatingBox);
103103 this._computeFloatingWidth(floatingBox);
104104 this._computeFloatingHeight(floatingBox);
 105 let displayFloatingBox = this.displayBox(floatingBox);
 106 if (displayFloatingBox.width() > this._line().availableWidth())
 107 this._commitLine();
 108 // Position this float statically first, the floating context will figure it out the final position.
 109 displayFloatingBox.setTopLeft(this._line().rect().topLeft());
105110 this.floatingContext().computePosition(floatingBox);
106  this._line().addFloatingBox(this.displayBox(floatingBox).size());
 111 this._line().addFloatingBox(displayFloatingBox.size());
107112 }
108113
109114 _commitLine() {

@@class InlineFormattingContext extends FormattingContext {
164169 return root.contentBox().left();
165170 return horizontalPosition - rootLeft;
166171 }
167 
168  _floatingBoxes() {
169  ASSERT(this.formattingRoot().firstChild());
170  // FIXME: This is highly inefficient but will do for now.
171  let floatingBoxes = new Array();
172  let stack = new Array();
173  stack.push(this.formattingRoot().firstChild());
174  while (stack.length) {
175  while (true) {
176  let box = stack[stack.length - 1];
177  if (box.isFloatingPositioned())
178  floatingBoxes.push(box);
179  if (box.establishesFormattingContext())
180  break;
181  if (!box.isContainer() || !box.hasChild())
182  break;
183  stack.push(box.firstChild());
184  }
185  while (stack.length) {
186  let box = stack.pop();
187  if (box.nextSibling()) {
188  stack.push(box.nextSibling());
189  break;
190  }
191  }
192  }
193  return floatingBoxes;
194  }
195172}
196173

Tools/LayoutReloaded/FormattingContext/InlineFormatting/Line.js

@@class Line {
4747 }
4848
4949 addTextLineBox(startPosition, endPosition, size) {
 50 ASSERT(size.width() <= this.m_availableWidth);
5051 this.m_availableWidth -= size.width();
5152 // TODO: use the actual height instead of the line height.
5253 let lineBoxRect = new LayoutRect(this.rect().topRight(), new LayoutSize(size.width(), this.rect().height()));

@@class Line {
5556 }
5657
5758 addFloatingBox(size) {
58  // TODO: Add missing cases.
 59 ASSERT(size.width() <= this.m_availableWidth);
 60 // Push non-floating boxes to the right.
5961 this.m_availableWidth -= size.width();
60  this.m_lineRect.moveBy(new LayoutSize(size.width(), 0));
 62 for (let lineBox of this.m_lineBoxes)
 63 lineBox.lineBoxRect.moveHorizontally(size.width());
 64 this.m_lineRect.moveHorizontally(size.width());
6165 }
6266}

Tools/LayoutReloaded/Utils.js

@@class LayoutRect {
207207 moveBy(distance) {
208208 this.m_topLeft.moveBy(distance);
209209 }
210 
 210
 211 moveHorizontally(distance) {
 212 this.m_topLeft.shiftLeft(distance);
 213 }
 214
 215 moveVertically(distance) {
 216 this.m_topLeft.shiftTop(distance);
 217 }
 218
211219 isEmpty() {
212220 return this.m_size.isEmpty();
213221 }

Tools/LayoutReloaded/test/index.html

@@let testFiles = [
6969 "inline-formatting-context-with-floats2.html",
7070 "float-is-inside-inline-formatting-context-simple.html",
7171 "multiple-left-floats-on-line-simple.html",
72  "multiple-left-floats-on-line-from-parent-formatting-context.html"
 72 "multiple-left-floats-on-line-from-parent-formatting-context.html",
 73 "inline-with-floats-when-they-dont-fit.html"
7374];
7475
7576let debugThis = [];

Tools/LayoutReloaded/test/inline-with-floats-when-they-dont-fit.html

 1<!DOCTYPE html>
 2<html>
 3<body>
 4<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>
 5</body>
 6</html>