Diff
Modified: trunk/Tools/ChangeLog (230483 => 230484)
--- trunk/Tools/ChangeLog 2018-04-10 17:07:47 UTC (rev 230483)
+++ trunk/Tools/ChangeLog 2018-04-10 17:21:50 UTC (rev 230484)
@@ -1,3 +1,38 @@
+2018-04-10 Zalan Bujtas <za...@apple.com>
+
+ [LayoutReloaded] Add support for out-of-flow descendants in inline formatting context.
+ https://bugs.webkit.org/show_bug.cgi?id=184454
+
+ Reviewed by Antti Koivisto.
+
+ When the containing block of an out-of-flow positioned element establishes an inline formatting context.
+ This is mostly about moving out-of-flow logic from BlockFormattingContext to the base class.
+
+ * LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js:
+ (BlockFormattingContext.prototype._adjustBottomWithFIXME):
+ (BlockFormattingContext):
+ (BlockFormattingContext.prototype._layoutOutOfFlowDescendants): Deleted.
+ (BlockFormattingContext.prototype._computeOutOfFlowWidth): Deleted.
+ (BlockFormattingContext.prototype._computeInFlowWidth): Deleted.
+ (BlockFormattingContext.prototype._computeOutOfFlowHeight): Deleted.
+ (BlockFormattingContext.prototype._computeOutOfFlowPosition): Deleted.
+ (BlockFormattingContext.prototype._shrinkToFitWidth): Deleted.
+ * LayoutReloaded/FormattingContext/FormattingContext.js:
+ (FormattingContext.prototype._placeInFlowPositionedChildren):
+ (FormattingContext.prototype._computeInFlowWidth):
+ (FormattingContext.prototype._layoutOutOfFlowDescendants):
+ (FormattingContext.prototype._computeOutOfFlowWidth):
+ (FormattingContext.prototype._computeOutOfFlowHeight):
+ (FormattingContext.prototype._computeOutOfFlowPosition):
+ (FormattingContext.prototype._shrinkToFitWidth):
+ * LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js:
+ (InlineFormattingContext.prototype.layout):
+ (InlineFormattingContext.prototype._handleInlineContainer):
+ (InlineFormattingContext.prototype._handleInlineBlockContainer):
+ (InlineFormattingContext.prototype._placeOutOfFlowDescendants): Deleted.
+ * LayoutReloaded/test/index.html:
+ * LayoutReloaded/test/inline-with-out-of-flow-descendant.html: Added.
+
2018-04-09 Zan Dobersek <zdober...@igalia.com>
WKTR: Enable DOM cache, SW registration directory cleanup on non-Cocoa platforms
Modified: trunk/Tools/LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js (230483 => 230484)
--- trunk/Tools/LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js 2018-04-10 17:07:47 UTC (rev 230483)
+++ trunk/Tools/LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js 2018-04-10 17:21:50 UTC (rev 230484)
@@ -118,95 +118,6 @@
this.displayBox(layoutBox).setTopLeft(position);
}
- _layoutOutOfFlowDescendants() {
- // This lays out all the out-of-flow boxes that belong to this formatting context even if
- // the root container is not the containing block.
- let outOfFlowDescendants = this._outOfFlowDescendants();
- for (let outOfFlowBox of outOfFlowDescendants) {
- this._addToLayoutQueue(outOfFlowBox);
- this.computeWidth(outOfFlowBox);
- this.layoutState().layout(outOfFlowBox);
- this.computeHeight(outOfFlowBox);
- this._computeOutOfFlowPosition(outOfFlowBox);
- this._removeFromLayoutQueue(outOfFlowBox);
- }
- }
-
- _computeOutOfFlowWidth(layoutBox) {
- // 10.3.7 Absolutely positioned, non-replaced elements
-
- // 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the width is shrink-to-fit. Then solve for 'left'
- // 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if the 'direction' property of the element establishing
- // the static-position containing block is 'ltr' set 'left' to the static position, otherwise set 'right' to the static position.
- // Then solve for 'left' (if 'direction is 'rtl') or 'right' (if 'direction' is 'ltr').
- // 3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the width is shrink-to-fit . Then solve for 'right'
- // 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve for 'left'
- // 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve for 'width'
- // 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve for 'right'
- let width = Number.NaN;
- if (Utils.isWidthAuto(layoutBox) && Utils.isLeftAuto(layoutBox) && Utils.isRightAuto(layoutBox))
- width = this._shrinkToFitWidth(layoutBox);
- else if (Utils.isLeftAuto(layoutBox) && Utils.isWidthAuto(layoutBox) && !Utils.isRightAuto(layoutBox))
- width = this._shrinkToFitWidth(layoutBox); // 1
- else if (Utils.isLeftAuto(layoutBox) && Utils.isRightAuto(layoutBox) && !Utils.isWidthAuto(layoutBox))
- width = Utils.width(layoutBox); // 2
- else if (Utils.isWidthAuto(layoutBox) && Utils.isRightAuto(layoutBox) && !Utils.isLeftAuto(layoutBox))
- width = this._shrinkToFitWidth(layoutBox); // 3
- else if (Utils.isLeftAuto(layoutBox) && !Utils.isWidthAuto(layoutBox) && !Utils.isRightAuto(layoutBox))
- width = Utils.width(layoutBox); // 4
- else if (Utils.isWidthAuto(layoutBox) && !Utils.isLeftAuto(layoutBox) && !Utils.isRightAuto(layoutBox))
- width = Math.max(0, this.displayBox(layoutBox.containingBlock()).contentBox().width() - Utils.right(layoutBox) - Utils.left(layoutBox)); // 5
- else if (Utils.isRightAuto(layoutBox) && !Utils.isLeftAuto(layoutBox) && !Utils.isWidthAuto(layoutBox))
- width = Utils.width(layoutBox); // 6
- else
- ASSERT_NOT_REACHED();
- width += Utils.computedHorizontalBorderAndPadding(layoutBox.node());
- this.displayBox(layoutBox).setWidth(width);
- }
-
- _computeInFlowWidth(layoutBox) {
- if (Utils.isWidthAuto(layoutBox))
- return this.displayBox(layoutBox).setWidth(this._horizontalConstraint(layoutBox));
- return this.displayBox(layoutBox).setWidth(Utils.width(layoutBox) + Utils.computedHorizontalBorderAndPadding(layoutBox.node()));
- }
-
- _computeOutOfFlowHeight(layoutBox) {
- // 1. If all three of 'top', 'height', and 'bottom' are auto, set 'top' to the static position and apply rule number three below.
- // 2. If none of the three are 'auto': If both 'margin-top' and 'margin-bottom' are 'auto', solve the equation under
- // the extra constraint that the two margins get equal values. If one of 'margin-top' or 'margin-bottom' is 'auto',
- // solve the equation for that value. If the values are over-constrained, ignore the value for 'bottom' and solve for that value.
- // Otherwise, pick the one of the following six rules that applies.
-
- // 3. 'top' and 'height' are 'auto' and 'bottom' is not 'auto', then the height is based on the content per 10.6.7,
- // set 'auto' values for 'margin-top' and 'margin-bottom' to 0, and solve for 'top'
- // 4. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then set 'top' to the static position, set 'auto' values
- // for 'margin-top' and 'margin-bottom' to 0, and solve for 'bottom'
- // 5. 'height' and 'bottom' are 'auto' and 'top' is not 'auto', then the height is based on the content per 10.6.7,
- // set 'auto' values for 'margin-top' and 'margin-bottom' to 0, and solve for 'bottom'
- // 6. 'top' is 'auto', 'height' and 'bottom' are not 'auto', then set 'auto' values for 'margin-top' and 'margin-bottom' to 0, and solve for 'top'
- // 7. 'height' is 'auto', 'top' and 'bottom' are not 'auto', then 'auto' values for 'margin-top' and 'margin-bottom' are set to 0 and solve for 'height'
- // 8. 'bottom' is 'auto', 'top' and 'height' are not 'auto', then set 'auto' values for 'margin-top' and 'margin-bottom' to 0 and solve for 'bottom'
- let height = Number.NaN;
- if (Utils.isHeightAuto(layoutBox) && Utils.isBottomAuto(layoutBox) && Utils.isTopAuto(layoutBox))
- height = this._contentHeight(layoutBox); // 1
- else if (Utils.isTopAuto((layoutBox)) && Utils.isHeightAuto((layoutBox)) && !Utils.isBottomAuto((layoutBox)))
- height = this._contentHeight(layoutBox); // 3
- else if (Utils.isTopAuto((layoutBox)) && Utils.isBottomAuto((layoutBox)) && !Utils.isHeightAuto((layoutBox)))
- height = Utils.height(layoutBox); // 4
- else if (Utils.isHeightAuto((layoutBox)) && Utils.isBottomAuto((layoutBox)) && !Utils.isTopAuto((layoutBox)))
- height = this._contentHeight(layoutBox); // 5
- else if (Utils.isTopAuto((layoutBox)) && !Utils.isHeightAuto((layoutBox)) && !Utils.isBottomAuto((layoutBox)))
- height = Utils.height(layoutBox); // 6
- else if (Utils.isHeightAuto((layoutBox)) && !Utils.isTopAuto((layoutBox)) && !Utils.isBottomAuto((layoutBox)))
- height = Math.max(0, this.displayBox(layoutBox.containingBlock()).contentBox().height() - Utils.bottom(layoutBox) - Utils.top(layoutBox)); // 7
- else if (Utils.isBottomAuto((layoutBox)) && !Utils.isTopAuto((layoutBox)) && !Utils.isHeightAuto((layoutBox)))
- height = Utils.height(layoutBox); // 8
- else
- ASSERT_NOT_REACHED();
- height += Utils.computedVerticalBorderAndPadding(layoutBox.node());
- this.displayBox(layoutBox).setHeight(height);
- }
-
_computeInFlowHeight(layoutBox) {
if (Utils.isHeightAuto(layoutBox)) {
// Only children in the normal flow are taken into account (i.e., floating boxes and absolutely positioned boxes are ignored,
@@ -264,65 +175,4 @@
}
return bottom;
}
-
- _computeOutOfFlowPosition(layoutBox) {
- let displayBox = this.displayBox(layoutBox);
- let top = Number.NaN;
- let containerSize = this.displayBox(layoutBox.containingBlock()).contentBox().size();
- // Top/bottom
- if (Utils.isTopAuto(layoutBox) && Utils.isBottomAuto(layoutBox)) {
- ASSERT(Utils.isStaticallyPositioned(layoutBox));
- // Vertically statically positioned.
- // FIXME: Figure out if it is actually valid that we use the parent box as the container (which is not even in this formatting context).
- let parent = layoutBox.parent();
- let parentDisplayBox = this.displayBox(parent);
- let previousInFlowSibling = layoutBox.previousInFlowSibling();
- let contentBottom = previousInFlowSibling ? this.displayBox(previousInFlowSibling).bottom() : parentDisplayBox.contentBox().top();
- top = contentBottom + this.marginTop(layoutBox);
- // Convert static position (in parent coordinate system) to absolute (in containing block coordindate system).
- if (parent != layoutBox.containingBlock()) {
- ASSERT(displayBox.parent() == this.displayBox(layoutBox.containingBlock()));
- top += Utils.mapPosition(parentDisplayBox.topLeft(), parentDisplayBox, displayBox.parent()).top();
- }
- } else if (!Utils.isTopAuto(layoutBox))
- top = Utils.top(layoutBox) + this.marginTop(layoutBox);
- else if (!Utils.isBottomAuto(layoutBox))
- top = containerSize.height() - Utils.bottom(layoutBox) - displayBox.height() - this.marginBottom(layoutBox);
- else
- ASSERT_NOT_REACHED();
- // Left/right
- let left = Number.NaN;
- if (Utils.isLeftAuto(layoutBox) && Utils.isRightAuto(layoutBox)) {
- ASSERT(Utils.isStaticallyPositioned(layoutBox));
- // Horizontally statically positioned.
- // FIXME: Figure out if it is actually valid that we use the parent box as the container (which is not even in this formatting context).
- let parent = layoutBox.parent();
- let parentDisplayBox = this.displayBox(parent);
- left = parentDisplayBox.contentBox().left() + this.marginLeft(layoutBox);
- // Convert static position (in parent coordinate system) to absolute (in containing block coordindate system).
- if (parent != layoutBox.containingBlock()) {
- ASSERT(displayBox.parent() == this.displayBox(layoutBox.containingBlock()));
- left += Utils.mapPosition(parentDisplayBox.topLeft(), parentDisplayBox, displayBox.parent()).left();
- }
- } else if (!Utils.isLeftAuto(layoutBox))
- left = Utils.left(layoutBox) + this.marginLeft(layoutBox);
- else if (!Utils.isRightAuto(layoutBox))
- left = containerSize.width() - Utils.right(layoutBox) - displayBox.width() - this.marginRight(layoutBox);
- else
- ASSERT_NOT_REACHED();
- displayBox.setTopLeft(new LayoutPoint(top, left));
- }
-
- _shrinkToFitWidth(layoutBox) {
- // FIXME: this is naive.
- ASSERT(Utils.isWidthAuto(layoutBox));
- if (!layoutBox.isContainer() || !layoutBox.hasChild())
- return 0;
- let width = 0;
- for (let inFlowChild = layoutBox.firstInFlowChild(); inFlowChild; inFlowChild = inFlowChild.nextInFlowSibling()) {
- let widthCandidate = Utils.isWidthAuto(inFlowChild) ? this._shrinkToFitWidth(inFlowChild) : Utils.width(inFlowChild);
- width = Math.max(width, widthCandidate + Utils.computedHorizontalBorderAndPadding(inFlowChild.node()));
- }
- return width;
- }
}
Modified: trunk/Tools/LayoutReloaded/FormattingContext/FormattingContext.js (230483 => 230484)
--- trunk/Tools/LayoutReloaded/FormattingContext/FormattingContext.js 2018-04-10 17:07:47 UTC (rev 230483)
+++ trunk/Tools/LayoutReloaded/FormattingContext/FormattingContext.js 2018-04-10 17:21:50 UTC (rev 230484)
@@ -117,6 +117,20 @@
this.displayBox(layoutBox).setHeight(Utils.height(layoutBox) + Utils.computedVerticalBorderAndPadding(layoutBox.node()));
}
+ _placeInFlowPositionedChildren(container) {
+ if (!container.isContainer())
+ return;
+ // If this layoutBox also establishes a formatting context, then positioning already has happend at the formatting context.
+ if (container.establishesFormattingContext() && container != this.formattingRoot())
+ return;
+ ASSERT(container.isContainer());
+ for (let inFlowChild = container.firstInFlowChild(); inFlowChild; inFlowChild = inFlowChild.nextInFlowSibling()) {
+ if (!inFlowChild.isInFlowPositioned())
+ continue;
+ this._computeInFlowPositionedPosition(inFlowChild);
+ }
+ }
+
_computeInFlowPositionedPosition(layoutBox) {
// Start with the original, static position.
let displayBox = this.displayBox(layoutBox);
@@ -134,20 +148,156 @@
displayBox.setTopLeft(relativePosition);
}
- _placeInFlowPositionedChildren(container) {
- if (!container.isContainer())
- return;
- // If this layoutBox also establishes a formatting context, then positioning already has happend at the formatting context.
- if (container.establishesFormattingContext() && container != this.formattingRoot())
- return;
- ASSERT(container.isContainer());
- for (let inFlowChild = container.firstInFlowChild(); inFlowChild; inFlowChild = inFlowChild.nextInFlowSibling()) {
- if (!inFlowChild.isInFlowPositioned())
- continue;
- this._computeInFlowPositionedPosition(inFlowChild);
+ _computeInFlowWidth(layoutBox) {
+ if (Utils.isWidthAuto(layoutBox))
+ return this.displayBox(layoutBox).setWidth(this._horizontalConstraint(layoutBox));
+ return this.displayBox(layoutBox).setWidth(Utils.width(layoutBox) + Utils.computedHorizontalBorderAndPadding(layoutBox.node()));
+ }
+
+ _layoutOutOfFlowDescendants() {
+ // This lays out all the out-of-flow boxes that belong to this formatting context even if
+ // the root container is not the containing block.
+ let outOfFlowDescendants = this._outOfFlowDescendants();
+ for (let outOfFlowBox of outOfFlowDescendants) {
+ this._addToLayoutQueue(outOfFlowBox);
+ this._computeOutOfFlowWidth(outOfFlowBox);
+ this.layoutState().layout(outOfFlowBox);
+ this._computeOutOfFlowHeight(outOfFlowBox);
+ this._computeOutOfFlowPosition(outOfFlowBox);
+ this._removeFromLayoutQueue(outOfFlowBox);
}
}
+ _computeOutOfFlowWidth(layoutBox) {
+ // 10.3.7 Absolutely positioned, non-replaced elements
+
+ // 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the width is shrink-to-fit. Then solve for 'left'
+ // 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if the 'direction' property of the element establishing
+ // the static-position containing block is 'ltr' set 'left' to the static position, otherwise set 'right' to the static position.
+ // Then solve for 'left' (if 'direction is 'rtl') or 'right' (if 'direction' is 'ltr').
+ // 3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the width is shrink-to-fit . Then solve for 'right'
+ // 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve for 'left'
+ // 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve for 'width'
+ // 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve for 'right'
+ let width = Number.NaN;
+ if (Utils.isWidthAuto(layoutBox) && Utils.isLeftAuto(layoutBox) && Utils.isRightAuto(layoutBox))
+ width = this._shrinkToFitWidth(layoutBox);
+ else if (Utils.isLeftAuto(layoutBox) && Utils.isWidthAuto(layoutBox) && !Utils.isRightAuto(layoutBox))
+ width = this._shrinkToFitWidth(layoutBox); // 1
+ else if (Utils.isLeftAuto(layoutBox) && Utils.isRightAuto(layoutBox) && !Utils.isWidthAuto(layoutBox))
+ width = Utils.width(layoutBox); // 2
+ else if (Utils.isWidthAuto(layoutBox) && Utils.isRightAuto(layoutBox) && !Utils.isLeftAuto(layoutBox))
+ width = this._shrinkToFitWidth(layoutBox); // 3
+ else if (Utils.isLeftAuto(layoutBox) && !Utils.isWidthAuto(layoutBox) && !Utils.isRightAuto(layoutBox))
+ width = Utils.width(layoutBox); // 4
+ else if (Utils.isWidthAuto(layoutBox) && !Utils.isLeftAuto(layoutBox) && !Utils.isRightAuto(layoutBox))
+ width = Math.max(0, this.displayBox(layoutBox.containingBlock()).contentBox().width() - Utils.right(layoutBox) - Utils.left(layoutBox)); // 5
+ else if (Utils.isRightAuto(layoutBox) && !Utils.isLeftAuto(layoutBox) && !Utils.isWidthAuto(layoutBox))
+ width = Utils.width(layoutBox); // 6
+ else
+ ASSERT_NOT_REACHED();
+ width += Utils.computedHorizontalBorderAndPadding(layoutBox.node());
+ this.displayBox(layoutBox).setWidth(width);
+ }
+
+ _computeOutOfFlowHeight(layoutBox) {
+ // 1. If all three of 'top', 'height', and 'bottom' are auto, set 'top' to the static position and apply rule number three below.
+ // 2. If none of the three are 'auto': If both 'margin-top' and 'margin-bottom' are 'auto', solve the equation under
+ // the extra constraint that the two margins get equal values. If one of 'margin-top' or 'margin-bottom' is 'auto',
+ // solve the equation for that value. If the values are over-constrained, ignore the value for 'bottom' and solve for that value.
+ // Otherwise, pick the one of the following six rules that applies.
+
+ // 3. 'top' and 'height' are 'auto' and 'bottom' is not 'auto', then the height is based on the content per 10.6.7,
+ // set 'auto' values for 'margin-top' and 'margin-bottom' to 0, and solve for 'top'
+ // 4. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then set 'top' to the static position, set 'auto' values
+ // for 'margin-top' and 'margin-bottom' to 0, and solve for 'bottom'
+ // 5. 'height' and 'bottom' are 'auto' and 'top' is not 'auto', then the height is based on the content per 10.6.7,
+ // set 'auto' values for 'margin-top' and 'margin-bottom' to 0, and solve for 'bottom'
+ // 6. 'top' is 'auto', 'height' and 'bottom' are not 'auto', then set 'auto' values for 'margin-top' and 'margin-bottom' to 0, and solve for 'top'
+ // 7. 'height' is 'auto', 'top' and 'bottom' are not 'auto', then 'auto' values for 'margin-top' and 'margin-bottom' are set to 0 and solve for 'height'
+ // 8. 'bottom' is 'auto', 'top' and 'height' are not 'auto', then set 'auto' values for 'margin-top' and 'margin-bottom' to 0 and solve for 'bottom'
+ let height = Number.NaN;
+ if (Utils.isHeightAuto(layoutBox) && Utils.isBottomAuto(layoutBox) && Utils.isTopAuto(layoutBox))
+ height = this._contentHeight(layoutBox); // 1
+ else if (Utils.isTopAuto((layoutBox)) && Utils.isHeightAuto((layoutBox)) && !Utils.isBottomAuto((layoutBox)))
+ height = this._contentHeight(layoutBox); // 3
+ else if (Utils.isTopAuto((layoutBox)) && Utils.isBottomAuto((layoutBox)) && !Utils.isHeightAuto((layoutBox)))
+ height = Utils.height(layoutBox); // 4
+ else if (Utils.isHeightAuto((layoutBox)) && Utils.isBottomAuto((layoutBox)) && !Utils.isTopAuto((layoutBox)))
+ height = this._contentHeight(layoutBox); // 5
+ else if (Utils.isTopAuto((layoutBox)) && !Utils.isHeightAuto((layoutBox)) && !Utils.isBottomAuto((layoutBox)))
+ height = Utils.height(layoutBox); // 6
+ else if (Utils.isHeightAuto((layoutBox)) && !Utils.isTopAuto((layoutBox)) && !Utils.isBottomAuto((layoutBox)))
+ height = Math.max(0, this.displayBox(layoutBox.containingBlock()).contentBox().height() - Utils.bottom(layoutBox) - Utils.top(layoutBox)); // 7
+ else if (Utils.isBottomAuto((layoutBox)) && !Utils.isTopAuto((layoutBox)) && !Utils.isHeightAuto((layoutBox)))
+ height = Utils.height(layoutBox); // 8
+ else
+ ASSERT_NOT_REACHED();
+ height += Utils.computedVerticalBorderAndPadding(layoutBox.node());
+ this.displayBox(layoutBox).setHeight(height);
+ }
+
+ _computeOutOfFlowPosition(layoutBox) {
+ let displayBox = this.displayBox(layoutBox);
+ let top = Number.NaN;
+ let containerSize = this.displayBox(layoutBox.containingBlock()).contentBox().size();
+ // Top/bottom
+ if (Utils.isTopAuto(layoutBox) && Utils.isBottomAuto(layoutBox)) {
+ ASSERT(Utils.isStaticallyPositioned(layoutBox));
+ // Vertically statically positioned.
+ // FIXME: Figure out if it is actually valid that we use the parent box as the container (which is not even in this formatting context).
+ let parent = layoutBox.parent();
+ let parentDisplayBox = this.displayBox(parent);
+ let previousInFlowSibling = layoutBox.previousInFlowSibling();
+ let contentBottom = previousInFlowSibling ? this.displayBox(previousInFlowSibling).bottom() : parentDisplayBox.contentBox().top();
+ top = contentBottom + this.marginTop(layoutBox);
+ // Convert static position (in parent coordinate system) to absolute (in containing block coordindate system).
+ if (parent != layoutBox.containingBlock()) {
+ ASSERT(displayBox.parent() == this.displayBox(layoutBox.containingBlock()));
+ top += Utils.mapPosition(parentDisplayBox.topLeft(), parentDisplayBox, displayBox.parent()).top();
+ }
+ } else if (!Utils.isTopAuto(layoutBox))
+ top = Utils.top(layoutBox) + this.marginTop(layoutBox);
+ else if (!Utils.isBottomAuto(layoutBox))
+ top = containerSize.height() - Utils.bottom(layoutBox) - displayBox.height() - this.marginBottom(layoutBox);
+ else
+ ASSERT_NOT_REACHED();
+ // Left/right
+ let left = Number.NaN;
+ if (Utils.isLeftAuto(layoutBox) && Utils.isRightAuto(layoutBox)) {
+ ASSERT(Utils.isStaticallyPositioned(layoutBox));
+ // Horizontally statically positioned.
+ // FIXME: Figure out if it is actually valid that we use the parent box as the container (which is not even in this formatting context).
+ let parent = layoutBox.parent();
+ let parentDisplayBox = this.displayBox(parent);
+ left = parentDisplayBox.contentBox().left() + this.marginLeft(layoutBox);
+ // Convert static position (in parent coordinate system) to absolute (in containing block coordindate system).
+ if (parent != layoutBox.containingBlock()) {
+ ASSERT(displayBox.parent() == this.displayBox(layoutBox.containingBlock()));
+ left += Utils.mapPosition(parentDisplayBox.topLeft(), parentDisplayBox, displayBox.parent()).left();
+ }
+ } else if (!Utils.isLeftAuto(layoutBox))
+ left = Utils.left(layoutBox) + this.marginLeft(layoutBox);
+ else if (!Utils.isRightAuto(layoutBox))
+ left = containerSize.width() - Utils.right(layoutBox) - displayBox.width() - this.marginRight(layoutBox);
+ else
+ ASSERT_NOT_REACHED();
+ displayBox.setTopLeft(new LayoutPoint(top, left));
+ }
+
+ _shrinkToFitWidth(layoutBox) {
+ // FIXME: this is naive and missing the actual preferred width computation.
+ ASSERT(Utils.isWidthAuto(layoutBox));
+ if (!layoutBox.isContainer() || !layoutBox.hasChild())
+ return 0;
+ let width = 0;
+ for (let inFlowChild = layoutBox.firstInFlowChild(); inFlowChild; inFlowChild = inFlowChild.nextInFlowSibling()) {
+ let widthCandidate = Utils.isWidthAuto(inFlowChild) ? this._shrinkToFitWidth(inFlowChild) : Utils.width(inFlowChild);
+ width = Math.max(width, widthCandidate + Utils.computedHorizontalBorderAndPadding(inFlowChild.node()));
+ }
+ return width;
+ }
+
_outOfFlowDescendants() {
// FIXME: This is highly inefficient but will do for now.
// 1. Collect all the out-of-flow descendants first.
Modified: trunk/Tools/LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js (230483 => 230484)
--- trunk/Tools/LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js 2018-04-10 17:07:47 UTC (rev 230483)
+++ trunk/Tools/LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js 2018-04-10 17:21:50 UTC (rev 230484)
@@ -50,7 +50,7 @@
// Place the inflow positioned children.
this._placeInFlowPositionedChildren(this.formattingRoot());
// And take care of out-of-flow boxes as the final step.
- this._placeOutOfFlowDescendants(this.formattingRoot());
+ this._layoutOutOfFlowDescendants(this.formattingRoot());
this._commitLine();
ASSERT(!this.m_inlineContainerStack.length);
}
@@ -69,22 +69,23 @@
this._adjustLineForInlineContainerEnd(inlineContainer);
this._removeFromLayoutQueue(inlineContainer);
this._addToLayoutQueue(inlineContainer.nextInFlowOrFloatSibling());
- // Place the in- and out-of-flow positioned children.
+ // Place inflow positioned children.
this._placeInFlowPositionedChildren(inlineContainer);
- this._placeOutOfFlowDescendants(inlineContainer);
}
_handleInlineBlockContainer(inlineBlockContainer) {
ASSERT(inlineBlockContainer.establishesFormattingContext());
+ let displayBox = this.displayBox(inlineBlockContainer);
+
+ // TODO: auto width/height
this._adjustLineForInlineContainerStart(inlineBlockContainer);
- // TODO: auto width/height
- let displayBox = this.displayBox(inlineBlockContainer);
displayBox.setWidth(Utils.width(inlineBlockContainer) + Utils.computedHorizontalBorderAndPadding(inlineBlockContainer.node()));
+ this.layoutState().layout(inlineBlockContainer);
displayBox.setHeight(Utils.height(inlineBlockContainer) + Utils.computedVerticalBorderAndPadding(inlineBlockContainer.node()));
- this.layoutState().layout(inlineBlockContainer);
+ this._adjustLineForInlineContainerEnd(inlineBlockContainer);
+
this._line().addInlineContainerBox(displayBox.size());
- this._adjustLineForInlineContainerEnd(inlineBlockContainer);
this._removeFromLayoutQueue(inlineBlockContainer);
this._addToLayoutQueue(inlineBlockContainer.nextInFlowOrFloatSibling());
}
@@ -152,10 +153,6 @@
this._line().adjustWithOffset(offset);
}
- _placeOutOfFlowDescendants(container) {
-
- }
-
_commitLine() {
if (this._line().isEmpty())
return;
Modified: trunk/Tools/LayoutReloaded/test/index.html (230483 => 230484)
--- trunk/Tools/LayoutReloaded/test/index.html 2018-04-10 17:07:47 UTC (rev 230483)
+++ trunk/Tools/LayoutReloaded/test/index.html 2018-04-10 17:21:50 UTC (rev 230484)
@@ -80,7 +80,8 @@
"inline-formatting-context-floats2.html",
"inline-with-padding-border-margin-offsets.html",
"inline-block-with-fixed-width-height.html",
- "inline-with-relative-positioning.html"
+ "inline-with-relative-positioning.html",
+ "inline-with-out-of-flow-descendant.html"
];
let debugThis = [];
Added: trunk/Tools/LayoutReloaded/test/inline-with-out-of-flow-descendant.html (0 => 230484)
--- trunk/Tools/LayoutReloaded/test/inline-with-out-of-flow-descendant.html (rev 0)
+++ trunk/Tools/LayoutReloaded/test/inline-with-out-of-flow-descendant.html 2018-04-10 17:21:50 UTC (rev 230484)
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div style="position: relative"><span>foo<span style="position: absolute; left: 100px; top: 100px; width: 100px; height: 100px;">foobar</span></span></div>
+</body>
+</html>