Skip to content
Permalink
Browse files
[LayoutReloaded] Collect out-of-flow positioned boxes for a given for…
…matting context.

https://bugs.webkit.org/show_bug.cgi?id=183730

Reviewed by Antti Koivisto.

Collect and layout out-of-flow positioned boxes as the final step of the formatting context layout.

* LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js:
(BlockFormattingContext.prototype.layout):
(BlockFormattingContext.prototype._placeInFlowPositionedChildren):
(BlockFormattingContext.prototype._layoutOutOfFlowDescendants):
(BlockFormattingContext.prototype._placePositionedDescendants): Deleted.
(BlockFormattingContext.prototype._placeOutOfFlowDescendants): Deleted.
* LayoutReloaded/FormattingContext/FormattingContext.js:
(FormattingContext.prototype._toAbsolutePosition):
(FormattingContext.prototype._outOfFlowDescendants):
(FormattingContext):
* LayoutReloaded/LayoutTree/Box.js:
(Layout.Box.prototype.nextInFlowOrFloatSibling):
(Layout.Box.prototype.isDescendantOf):
* LayoutReloaded/LayoutTree/Container.js:
(Layout.Container.prototype.firstInFlowOrFloatChild):
(Layout.Container.prototype.hasInFlowOrFloatChild):
(Layout.Container.prototype.outOfFlowDescendants):
(Layout.Container):
* LayoutReloaded/Utils.js:
(Utils.isDescendantOf): Deleted.
(Utils.collectOutOfFlowDescendants): Deleted.

Canonical link: https://commits.webkit.org/199368@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@229701 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
alanbujtas committed Mar 18, 2018
1 parent c0127fb commit cece1ed599a1b0b94bf34d73bedc528f475fa0b6
@@ -1,3 +1,34 @@
2018-03-18 Zalan Bujtas <zalan@apple.com>

[LayoutReloaded] Collect out-of-flow positioned boxes for a given formatting context.
https://bugs.webkit.org/show_bug.cgi?id=183730

Reviewed by Antti Koivisto.

Collect and layout out-of-flow positioned boxes as the final step of the formatting context layout.

* LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js:
(BlockFormattingContext.prototype.layout):
(BlockFormattingContext.prototype._placeInFlowPositionedChildren):
(BlockFormattingContext.prototype._layoutOutOfFlowDescendants):
(BlockFormattingContext.prototype._placePositionedDescendants): Deleted.
(BlockFormattingContext.prototype._placeOutOfFlowDescendants): Deleted.
* LayoutReloaded/FormattingContext/FormattingContext.js:
(FormattingContext.prototype._toAbsolutePosition):
(FormattingContext.prototype._outOfFlowDescendants):
(FormattingContext):
* LayoutReloaded/LayoutTree/Box.js:
(Layout.Box.prototype.nextInFlowOrFloatSibling):
(Layout.Box.prototype.isDescendantOf):
* LayoutReloaded/LayoutTree/Container.js:
(Layout.Container.prototype.firstInFlowOrFloatChild):
(Layout.Container.prototype.hasInFlowOrFloatChild):
(Layout.Container.prototype.outOfFlowDescendants):
(Layout.Container):
* LayoutReloaded/Utils.js:
(Utils.isDescendantOf): Deleted.
(Utils.collectOutOfFlowDescendants): Deleted.

2018-03-17 Jiewen Tan <jiewen_tan@apple.com>

[WebAuthN] Implement authenticatorMakeCredential
@@ -34,11 +34,11 @@ class BlockFormattingContext extends FormattingContext {
// In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block.
// The vertical distance between two sibling boxes is determined by the 'margin' properties.
// Vertical margins between adjacent block-level boxes in a block formatting context collapse.
if (!this.rootContainer().firstChild())
return;

// 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._addToLayoutQueue(this.rootContainer().firstChild());
if (this.rootContainer().firstInFlowOrFloatChild())
this._addToLayoutQueue(this.rootContainer().firstInFlowOrFloatChild());
// 1. Go all the way down to the leaf node
// 2. Compute static position and width as we travers down
// 3. As we climb back on the tree, compute height and finialize position
@@ -53,9 +53,9 @@ class BlockFormattingContext extends FormattingContext {
layoutContext.layoutFormattingContext(layoutBox.establishedFormattingContext());
break;
}
if (!layoutBox.isContainer() || !layoutBox.hasChild())
if (!layoutBox.isContainer() || !layoutBox.hasInFlowOrFloatChild())
break;
this._addToLayoutQueue(layoutBox.firstChild());
this._addToLayoutQueue(layoutBox.firstInFlowOrFloatChild());
}

// Climb back on the ancestors and compute height/final position.
@@ -65,18 +65,20 @@ class BlockFormattingContext extends FormattingContext {
this.computeHeight(layoutBox);
// Adjust position now that we have all the previous floats placed in this context -if needed.
this.floatingContext().computePosition(layoutBox);
// Move positioned children to their final position.
this._placePositionedDescendants(layoutBox);
// Move in-flow positioned children to their final position.
this._placeInFlowPositionedChildren(layoutBox);
// We are done with laying out this box.
this._removeFromLayoutQueue(layoutBox);
if (layoutBox.nextSibling()) {
this._addToLayoutQueue(layoutBox.nextSibling());
if (layoutBox.nextInFlowOrFloatSibling()) {
this._addToLayoutQueue(layoutBox.nextInFlowOrFloatSibling());
break;
}
}
}
// And finally place the in- and out-of-flow descendants.
this._placePositionedDescendants(this.rootContainer());
// Place the inflow positioned children.
this._placeInFlowPositionedChildren(this.rootContainer());
// And take care of out-of-flow boxes as the final step.
this._layoutOutOfFlowDescendants(layoutContext);
}

computeWidth(layoutBox) {
@@ -116,17 +118,12 @@ class BlockFormattingContext extends FormattingContext {
layoutBox.setTopLeft(position);
}

_placePositionedDescendants(layoutBox) {
if (!layoutBox.isContainer())
_placeInFlowPositionedChildren(container) {
if (!container.isContainer())
return;
// If this layoutBox also establishes a formatting context, then positioning already has happend at the formatting context.
if (layoutBox.establishesFormattingContext() && layoutBox != this.rootContainer())
if (container.establishesFormattingContext() && container != this.rootContainer())
return;
this._placeInFlowPositionedChildren(layoutBox);
this._placeOutOfFlowDescendants(layoutBox);
}

_placeInFlowPositionedChildren(container) {
ASSERT(container.isContainer());
for (let inFlowChild = container.firstInFlowChild(); inFlowChild; inFlowChild = inFlowChild.nextInFlowSibling()) {
if (!inFlowChild.isInFlowPositioned())
@@ -135,11 +132,19 @@ class BlockFormattingContext extends FormattingContext {
}
}

_placeOutOfFlowDescendants(container) {
ASSERT(container.isContainer());
let outOfFlowDescendants = Utils.collectOutOfFlowDescendants(container);
for (let outOfFlowBox of outOfFlowDescendants)
_layoutOutOfFlowDescendants(layoutContext) {
// 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._computeStaticPosition(outOfFlowBox);
layoutContext.layoutFormattingContext(outOfFlowBox.establishedFormattingContext());
this.computeHeight(outOfFlowBox);
this._computeOutOfFlowPosition(outOfFlowBox);
this._removeFromLayoutQueue(outOfFlowBox);
}
}

_computeOutOfFlowWidth(layoutBox) {
@@ -96,7 +96,7 @@ class FormattingContext {
_toAbsolutePosition(layoutBox) {
// We should never need to go beyond the root container.
let containingBlock = layoutBox.containingBlock();
ASSERT(containingBlock == this.rootContainer() || Utils.isDescendantOf(containingBlock, this.rootContainer()));
ASSERT(containingBlock == this.rootContainer() || containingBlock.isDescendantOf(this.rootContainer()));
let topLeft = layoutBox.rect().topLeft();
let ascendant = layoutBox.parent();
while (ascendant && ascendant != containingBlock) {
@@ -147,4 +147,39 @@ class FormattingContext {
ASSERT(this.m_displayToLayout.has(displayBox));
return this.m_displayToLayout.get(layout);
}

_outOfFlowDescendants() {
// FIXME: This is highly inefficient but will do for now.
// 1. Collect all the out-of-flow descendants first.
// 2. Check if they are all belong to this formatting context.
// - either the root container is the containing block.
// - or a descendant of the root container is the containing block
// and there is not other formatting context inbetween.
let allOutOfFlowBoxes = new Array();
let descendants = new Array();
for (let child = this.rootContainer().firstChild(); child; child = child.nextSibling())
descendants.push(child);
while (descendants.length) {
let descendant = descendants.pop();
if (descendant.isOutOfFlowPositioned())
allOutOfFlowBoxes.push(descendant);
if (!descendant.isContainer())
continue;
for (let child = descendant.lastChild(); child; child = child.previousSibling())
descendants.push(child);
}
let outOfFlowBoxes = new Array();
for (let outOfFlowBox of allOutOfFlowBoxes) {
let containingBlock = outOfFlowBox.containingBlock();
// Collect the out-of-flow descendant that belong to this formatting context.
if (containingBlock == this.rootContainer())
outOfFlowBoxes.push(outOfFlowBox);
else if (containingBlock.isDescendantOf(this.rootContainer())) {
if (!containingBlock.establishedFormattingContext() || !containingBlock.isPositioned())
outOfFlowBoxes.push(outOfFlowBox);
}
}
return outOfFlowBoxes;
}

}
@@ -72,6 +72,16 @@ Layout.Box = class Box {
return null;
}

nextInFlowOrFloatSibling() {
let nextInFlowSibling = this.nextSibling();
while (nextInFlowSibling) {
if (nextInFlowSibling.isInFlow() || nextInFlowSibling.isFloatingPositioned())
return nextInFlowSibling;
nextInFlowSibling = nextInFlowSibling.nextSibling();
}
return null;
}

previousSibling() {
return this.m_previousSibling;
}
@@ -250,6 +260,14 @@ Layout.Box = class Box {
return null;
}

isDescendantOf(container) {
ASSERT(container);
let ascendant = this.parent();
while (ascendant && ascendant != container)
ascendant = ascendant.parent();
return !!ascendant;
}

borderBox() {
return this.displayBox().borderBox();
}
@@ -55,6 +55,15 @@ Layout.Container = class Container extends Layout.Box {
return firstChild.nextInFlowSibling();
}

firstInFlowOrFloatChild() {
if (!this.hasChild())
return null;
let firstChild = this.firstChild();
if (firstChild.isInFlow() || firstChild.isFloatingPositioned())
return firstChild;
return firstChild.nextInFlowOrFloatSibling();
}

lastChild() {
return this.m_lastChild;
}
@@ -75,4 +84,29 @@ Layout.Container = class Container extends Layout.Box {
hasInFlowChild() {
return !!this.firstInFlowChild();
}

hasInFlowOrFloatChild() {
return !!this.firstInFlowOrFloatChild();
}

outOfFlowDescendants() {
if (!this.isPositioned())
return new Array();
let outOfFlowBoxes = new Array();
let descendants = new Array();
for (let child = this.firstChild(); child; child = child.nextSibling())
descendants.push(child);
while (descendants.length) {
let descendant = descendants.pop();
if (descendant.isOutOfFlowPositioned() && descendant.containingBlock() == this)
outOfFlowBoxes.push(descendant);
if (!descendant.isContainer())
continue;
for (let child = descendant.lastChild(); child; child = child.previousSibling())
descendants.push(child);
}
return outOfFlowBoxes;
}


}
@@ -479,31 +479,6 @@ class Utils {
return new LayoutRect(topLeft, box.rect().size());
}

static isDescendantOf(layoutBox, container) {
ASSERT(container);
let ascendant = layoutBox.parent();
while (ascendant && ascendant != container)
ascendant = ascendant.parent();
return !!ascendant;
}

static collectOutOfFlowDescendants(containtBlock) {
let outOfFlowBoxes = new Array();
let descendants = new Array();
for (let child = containtBlock.firstChild(); child; child = child.nextSibling())
descendants.push(child);
while (descendants.length) {
let descendant = descendants.pop();
if (descendant.isOutOfFlowPositioned() && descendant.containingBlock() == containtBlock)
outOfFlowBoxes.push(descendant);
if (!descendant.isContainer())
continue;
for (let child = descendant.lastChild(); child; child = child.previousSibling())
descendants.push(child);
}
return outOfFlowBoxes;
}

static nextBreakingOpportunity(textBox, currentPosition)
{
return window.nextBreakingOpportunity(textBox.content(), currentPosition);

0 comments on commit cece1ed

Please sign in to comment.