Changeset 230484 in webkit


Ignore:
Timestamp:
Apr 10, 2018 10:21:50 AM (6 years ago)
Author:
Alan Bujtas
Message:

[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.
Location:
trunk/Tools
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r230473 r230484  
     12018-04-10  Zalan Bujtas  <zalan@apple.com>
     2
     3        [LayoutReloaded] Add support for out-of-flow descendants in inline formatting context.
     4        https://bugs.webkit.org/show_bug.cgi?id=184454
     5
     6        Reviewed by Antti Koivisto.
     7
     8        When the containing block of an out-of-flow positioned element establishes an inline formatting context.
     9        This is mostly about moving out-of-flow logic from BlockFormattingContext to the base class.
     10
     11        * LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js:
     12        (BlockFormattingContext.prototype._adjustBottomWithFIXME):
     13        (BlockFormattingContext):
     14        (BlockFormattingContext.prototype._layoutOutOfFlowDescendants): Deleted.
     15        (BlockFormattingContext.prototype._computeOutOfFlowWidth): Deleted.
     16        (BlockFormattingContext.prototype._computeInFlowWidth): Deleted.
     17        (BlockFormattingContext.prototype._computeOutOfFlowHeight): Deleted.
     18        (BlockFormattingContext.prototype._computeOutOfFlowPosition): Deleted.
     19        (BlockFormattingContext.prototype._shrinkToFitWidth): Deleted.
     20        * LayoutReloaded/FormattingContext/FormattingContext.js:
     21        (FormattingContext.prototype._placeInFlowPositionedChildren):
     22        (FormattingContext.prototype._computeInFlowWidth):
     23        (FormattingContext.prototype._layoutOutOfFlowDescendants):
     24        (FormattingContext.prototype._computeOutOfFlowWidth):
     25        (FormattingContext.prototype._computeOutOfFlowHeight):
     26        (FormattingContext.prototype._computeOutOfFlowPosition):
     27        (FormattingContext.prototype._shrinkToFitWidth):
     28        * LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js:
     29        (InlineFormattingContext.prototype.layout):
     30        (InlineFormattingContext.prototype._handleInlineContainer):
     31        (InlineFormattingContext.prototype._handleInlineBlockContainer):
     32        (InlineFormattingContext.prototype._placeOutOfFlowDescendants): Deleted.
     33        * LayoutReloaded/test/index.html:
     34        * LayoutReloaded/test/inline-with-out-of-flow-descendant.html: Added.
     35
    1362018-04-09  Zan Dobersek  <zdobersek@igalia.com>
    237
  • trunk/Tools/LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js

    r230469 r230484  
    119119    }
    120120
    121     _layoutOutOfFlowDescendants() {
    122         // This lays out all the out-of-flow boxes that belong to this formatting context even if
    123         // the root container is not the containing block.
    124         let outOfFlowDescendants = this._outOfFlowDescendants();
    125         for (let outOfFlowBox of outOfFlowDescendants) {
    126             this._addToLayoutQueue(outOfFlowBox);
    127             this.computeWidth(outOfFlowBox);
    128             this.layoutState().layout(outOfFlowBox);
    129             this.computeHeight(outOfFlowBox);
    130             this._computeOutOfFlowPosition(outOfFlowBox);
    131             this._removeFromLayoutQueue(outOfFlowBox);
    132         }
    133     }
    134 
    135     _computeOutOfFlowWidth(layoutBox) {
    136         // 10.3.7 Absolutely positioned, non-replaced elements
    137 
    138         // 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the width is shrink-to-fit. Then solve for 'left'
    139         // 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if the 'direction' property of the element establishing
    140         //     the static-position containing block is 'ltr' set 'left' to the static position, otherwise set 'right' to the static position.
    141         //     Then solve for 'left' (if 'direction is 'rtl') or 'right' (if 'direction' is 'ltr').
    142         // 3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the width is shrink-to-fit . Then solve for 'right'
    143         // 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve for 'left'
    144         // 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve for 'width'
    145         // 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve for 'right'
    146         let width = Number.NaN;
    147         if (Utils.isWidthAuto(layoutBox) && Utils.isLeftAuto(layoutBox) && Utils.isRightAuto(layoutBox))
    148             width = this._shrinkToFitWidth(layoutBox);
    149         else if (Utils.isLeftAuto(layoutBox) && Utils.isWidthAuto(layoutBox) && !Utils.isRightAuto(layoutBox))
    150             width = this._shrinkToFitWidth(layoutBox); // 1
    151         else if (Utils.isLeftAuto(layoutBox) && Utils.isRightAuto(layoutBox) && !Utils.isWidthAuto(layoutBox))
    152             width = Utils.width(layoutBox); // 2
    153         else if (Utils.isWidthAuto(layoutBox) && Utils.isRightAuto(layoutBox) && !Utils.isLeftAuto(layoutBox))
    154             width = this._shrinkToFitWidth(layoutBox); // 3
    155         else if (Utils.isLeftAuto(layoutBox) && !Utils.isWidthAuto(layoutBox) && !Utils.isRightAuto(layoutBox))
    156             width = Utils.width(layoutBox); // 4
    157         else if (Utils.isWidthAuto(layoutBox) && !Utils.isLeftAuto(layoutBox) && !Utils.isRightAuto(layoutBox))
    158             width = Math.max(0, this.displayBox(layoutBox.containingBlock()).contentBox().width() - Utils.right(layoutBox) - Utils.left(layoutBox)); // 5
    159         else if (Utils.isRightAuto(layoutBox) && !Utils.isLeftAuto(layoutBox) && !Utils.isWidthAuto(layoutBox))
    160             width = Utils.width(layoutBox); // 6
    161         else
    162             ASSERT_NOT_REACHED();
    163         width += Utils.computedHorizontalBorderAndPadding(layoutBox.node());
    164         this.displayBox(layoutBox).setWidth(width);
    165     }
    166 
    167     _computeInFlowWidth(layoutBox) {
    168         if (Utils.isWidthAuto(layoutBox))
    169             return this.displayBox(layoutBox).setWidth(this._horizontalConstraint(layoutBox));
    170         return this.displayBox(layoutBox).setWidth(Utils.width(layoutBox) + Utils.computedHorizontalBorderAndPadding(layoutBox.node()));
    171     }
    172 
    173     _computeOutOfFlowHeight(layoutBox) {
    174         // 1. If all three of 'top', 'height', and 'bottom' are auto, set 'top' to the static position and apply rule number three below.
    175         // 2. If none of the three are 'auto': If both 'margin-top' and 'margin-bottom' are 'auto', solve the equation under
    176         //    the extra constraint that the two margins get equal values. If one of 'margin-top' or 'margin-bottom' is 'auto',
    177         //    solve the equation for that value. If the values are over-constrained, ignore the value for 'bottom' and solve for that value.
    178         // Otherwise, pick the one of the following six rules that applies.
    179 
    180         // 3. 'top' and 'height' are 'auto' and 'bottom' is not 'auto', then the height is based on the content per 10.6.7,
    181         //    set 'auto' values for 'margin-top' and 'margin-bottom' to 0, and solve for 'top'
    182         // 4. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then set 'top' to the static position, set 'auto' values
    183         //    for 'margin-top' and 'margin-bottom' to 0, and solve for 'bottom'
    184         // 5. 'height' and 'bottom' are 'auto' and 'top' is not 'auto', then the height is based on the content per 10.6.7,
    185         //    set 'auto' values for 'margin-top' and 'margin-bottom' to 0, and solve for 'bottom'
    186         // 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'
    187         // 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'
    188         // 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'
    189         let height = Number.NaN;
    190         if (Utils.isHeightAuto(layoutBox) && Utils.isBottomAuto(layoutBox) && Utils.isTopAuto(layoutBox))
    191             height = this._contentHeight(layoutBox); // 1
    192         else if (Utils.isTopAuto((layoutBox)) && Utils.isHeightAuto((layoutBox)) && !Utils.isBottomAuto((layoutBox)))
    193             height = this._contentHeight(layoutBox); // 3
    194         else if (Utils.isTopAuto((layoutBox)) && Utils.isBottomAuto((layoutBox)) && !Utils.isHeightAuto((layoutBox)))
    195             height = Utils.height(layoutBox); // 4
    196         else if (Utils.isHeightAuto((layoutBox)) && Utils.isBottomAuto((layoutBox)) && !Utils.isTopAuto((layoutBox)))
    197             height = this._contentHeight(layoutBox); // 5
    198         else if (Utils.isTopAuto((layoutBox)) && !Utils.isHeightAuto((layoutBox)) && !Utils.isBottomAuto((layoutBox)))
    199             height = Utils.height(layoutBox); // 6
    200         else if (Utils.isHeightAuto((layoutBox)) && !Utils.isTopAuto((layoutBox)) && !Utils.isBottomAuto((layoutBox)))
    201             height = Math.max(0, this.displayBox(layoutBox.containingBlock()).contentBox().height() - Utils.bottom(layoutBox) - Utils.top(layoutBox)); // 7
    202         else if (Utils.isBottomAuto((layoutBox)) && !Utils.isTopAuto((layoutBox)) && !Utils.isHeightAuto((layoutBox)))
    203             height = Utils.height(layoutBox); // 8
    204         else
    205             ASSERT_NOT_REACHED();
    206         height += Utils.computedVerticalBorderAndPadding(layoutBox.node());
    207         this.displayBox(layoutBox).setHeight(height);
    208     }
    209 
    210121    _computeInFlowHeight(layoutBox) {
    211122        if (Utils.isHeightAuto(layoutBox)) {
     
    265176        return bottom;
    266177    }
    267 
    268     _computeOutOfFlowPosition(layoutBox) {
    269         let displayBox = this.displayBox(layoutBox);
    270         let top = Number.NaN;
    271         let containerSize = this.displayBox(layoutBox.containingBlock()).contentBox().size();
    272         // Top/bottom
    273         if (Utils.isTopAuto(layoutBox) && Utils.isBottomAuto(layoutBox)) {
    274             ASSERT(Utils.isStaticallyPositioned(layoutBox));
    275             // Vertically statically positioned.
    276             // 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).
    277             let parent = layoutBox.parent();
    278             let parentDisplayBox = this.displayBox(parent);
    279             let previousInFlowSibling = layoutBox.previousInFlowSibling();
    280             let contentBottom = previousInFlowSibling ? this.displayBox(previousInFlowSibling).bottom() : parentDisplayBox.contentBox().top();
    281             top = contentBottom + this.marginTop(layoutBox);
    282             // Convert static position (in parent coordinate system) to absolute (in containing block coordindate system).
    283             if (parent != layoutBox.containingBlock()) {
    284                 ASSERT(displayBox.parent() == this.displayBox(layoutBox.containingBlock()));
    285                 top += Utils.mapPosition(parentDisplayBox.topLeft(), parentDisplayBox, displayBox.parent()).top();
    286             }
    287         } else if (!Utils.isTopAuto(layoutBox))
    288             top = Utils.top(layoutBox) + this.marginTop(layoutBox);
    289         else if (!Utils.isBottomAuto(layoutBox))
    290             top = containerSize.height() - Utils.bottom(layoutBox) - displayBox.height() - this.marginBottom(layoutBox);
    291         else
    292             ASSERT_NOT_REACHED();
    293         // Left/right
    294         let left = Number.NaN;
    295         if (Utils.isLeftAuto(layoutBox) && Utils.isRightAuto(layoutBox)) {
    296             ASSERT(Utils.isStaticallyPositioned(layoutBox));
    297             // Horizontally statically positioned.
    298             // 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).
    299             let parent = layoutBox.parent();
    300             let parentDisplayBox = this.displayBox(parent);
    301             left = parentDisplayBox.contentBox().left() + this.marginLeft(layoutBox);
    302             // Convert static position (in parent coordinate system) to absolute (in containing block coordindate system).
    303             if (parent != layoutBox.containingBlock()) {
    304                 ASSERT(displayBox.parent() == this.displayBox(layoutBox.containingBlock()));
    305                 left += Utils.mapPosition(parentDisplayBox.topLeft(), parentDisplayBox, displayBox.parent()).left();
    306             }
    307         } else if (!Utils.isLeftAuto(layoutBox))
    308             left = Utils.left(layoutBox) + this.marginLeft(layoutBox);
    309         else if (!Utils.isRightAuto(layoutBox))
    310             left = containerSize.width() - Utils.right(layoutBox) - displayBox.width() - this.marginRight(layoutBox);
    311         else
    312             ASSERT_NOT_REACHED();
    313         displayBox.setTopLeft(new LayoutPoint(top, left));
    314     }
    315 
    316     _shrinkToFitWidth(layoutBox) {
    317         // FIXME: this is naive.
    318         ASSERT(Utils.isWidthAuto(layoutBox));
    319         if (!layoutBox.isContainer() || !layoutBox.hasChild())
    320             return 0;
    321         let width = 0;
    322         for (let inFlowChild = layoutBox.firstInFlowChild(); inFlowChild; inFlowChild = inFlowChild.nextInFlowSibling()) {
    323             let widthCandidate = Utils.isWidthAuto(inFlowChild) ? this._shrinkToFitWidth(inFlowChild) : Utils.width(inFlowChild);
    324             width = Math.max(width, widthCandidate + Utils.computedHorizontalBorderAndPadding(inFlowChild.node()));
    325         }
    326         return width;
    327     }
    328178}
  • trunk/Tools/LayoutReloaded/FormattingContext/FormattingContext.js

    r230469 r230484  
    118118    }
    119119
     120    _placeInFlowPositionedChildren(container) {
     121        if (!container.isContainer())
     122            return;
     123        // If this layoutBox also establishes a formatting context, then positioning already has happend at the formatting context.
     124        if (container.establishesFormattingContext() && container != this.formattingRoot())
     125            return;
     126        ASSERT(container.isContainer());
     127        for (let inFlowChild = container.firstInFlowChild(); inFlowChild; inFlowChild = inFlowChild.nextInFlowSibling()) {
     128            if (!inFlowChild.isInFlowPositioned())
     129                continue;
     130            this._computeInFlowPositionedPosition(inFlowChild);
     131        }
     132    }
     133
    120134    _computeInFlowPositionedPosition(layoutBox) {
    121135        // Start with the original, static position.
     
    135149    }
    136150
    137     _placeInFlowPositionedChildren(container) {
    138         if (!container.isContainer())
    139             return;
    140         // If this layoutBox also establishes a formatting context, then positioning already has happend at the formatting context.
    141         if (container.establishesFormattingContext() && container != this.formattingRoot())
    142             return;
    143         ASSERT(container.isContainer());
    144         for (let inFlowChild = container.firstInFlowChild(); inFlowChild; inFlowChild = inFlowChild.nextInFlowSibling()) {
    145             if (!inFlowChild.isInFlowPositioned())
    146                 continue;
    147             this._computeInFlowPositionedPosition(inFlowChild);
    148         }
     151    _computeInFlowWidth(layoutBox) {
     152        if (Utils.isWidthAuto(layoutBox))
     153            return this.displayBox(layoutBox).setWidth(this._horizontalConstraint(layoutBox));
     154        return this.displayBox(layoutBox).setWidth(Utils.width(layoutBox) + Utils.computedHorizontalBorderAndPadding(layoutBox.node()));
     155    }
     156
     157    _layoutOutOfFlowDescendants() {
     158        // This lays out all the out-of-flow boxes that belong to this formatting context even if
     159        // the root container is not the containing block.
     160        let outOfFlowDescendants = this._outOfFlowDescendants();
     161        for (let outOfFlowBox of outOfFlowDescendants) {
     162            this._addToLayoutQueue(outOfFlowBox);
     163            this._computeOutOfFlowWidth(outOfFlowBox);
     164            this.layoutState().layout(outOfFlowBox);
     165            this._computeOutOfFlowHeight(outOfFlowBox);
     166            this._computeOutOfFlowPosition(outOfFlowBox);
     167            this._removeFromLayoutQueue(outOfFlowBox);
     168        }
     169    }
     170
     171    _computeOutOfFlowWidth(layoutBox) {
     172        // 10.3.7 Absolutely positioned, non-replaced elements
     173
     174        // 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the width is shrink-to-fit. Then solve for 'left'
     175        // 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if the 'direction' property of the element establishing
     176        //     the static-position containing block is 'ltr' set 'left' to the static position, otherwise set 'right' to the static position.
     177        //     Then solve for 'left' (if 'direction is 'rtl') or 'right' (if 'direction' is 'ltr').
     178        // 3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the width is shrink-to-fit . Then solve for 'right'
     179        // 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve for 'left'
     180        // 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve for 'width'
     181        // 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve for 'right'
     182        let width = Number.NaN;
     183        if (Utils.isWidthAuto(layoutBox) && Utils.isLeftAuto(layoutBox) && Utils.isRightAuto(layoutBox))
     184            width = this._shrinkToFitWidth(layoutBox);
     185        else if (Utils.isLeftAuto(layoutBox) && Utils.isWidthAuto(layoutBox) && !Utils.isRightAuto(layoutBox))
     186            width = this._shrinkToFitWidth(layoutBox); // 1
     187        else if (Utils.isLeftAuto(layoutBox) && Utils.isRightAuto(layoutBox) && !Utils.isWidthAuto(layoutBox))
     188            width = Utils.width(layoutBox); // 2
     189        else if (Utils.isWidthAuto(layoutBox) && Utils.isRightAuto(layoutBox) && !Utils.isLeftAuto(layoutBox))
     190            width = this._shrinkToFitWidth(layoutBox); // 3
     191        else if (Utils.isLeftAuto(layoutBox) && !Utils.isWidthAuto(layoutBox) && !Utils.isRightAuto(layoutBox))
     192            width = Utils.width(layoutBox); // 4
     193        else if (Utils.isWidthAuto(layoutBox) && !Utils.isLeftAuto(layoutBox) && !Utils.isRightAuto(layoutBox))
     194            width = Math.max(0, this.displayBox(layoutBox.containingBlock()).contentBox().width() - Utils.right(layoutBox) - Utils.left(layoutBox)); // 5
     195        else if (Utils.isRightAuto(layoutBox) && !Utils.isLeftAuto(layoutBox) && !Utils.isWidthAuto(layoutBox))
     196            width = Utils.width(layoutBox); // 6
     197        else
     198            ASSERT_NOT_REACHED();
     199        width += Utils.computedHorizontalBorderAndPadding(layoutBox.node());
     200        this.displayBox(layoutBox).setWidth(width);
     201    }
     202
     203    _computeOutOfFlowHeight(layoutBox) {
     204        // 1. If all three of 'top', 'height', and 'bottom' are auto, set 'top' to the static position and apply rule number three below.
     205        // 2. If none of the three are 'auto': If both 'margin-top' and 'margin-bottom' are 'auto', solve the equation under
     206        //    the extra constraint that the two margins get equal values. If one of 'margin-top' or 'margin-bottom' is 'auto',
     207        //    solve the equation for that value. If the values are over-constrained, ignore the value for 'bottom' and solve for that value.
     208        // Otherwise, pick the one of the following six rules that applies.
     209
     210        // 3. 'top' and 'height' are 'auto' and 'bottom' is not 'auto', then the height is based on the content per 10.6.7,
     211        //    set 'auto' values for 'margin-top' and 'margin-bottom' to 0, and solve for 'top'
     212        // 4. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then set 'top' to the static position, set 'auto' values
     213        //    for 'margin-top' and 'margin-bottom' to 0, and solve for 'bottom'
     214        // 5. 'height' and 'bottom' are 'auto' and 'top' is not 'auto', then the height is based on the content per 10.6.7,
     215        //    set 'auto' values for 'margin-top' and 'margin-bottom' to 0, and solve for 'bottom'
     216        // 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'
     217        // 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'
     218        // 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'
     219        let height = Number.NaN;
     220        if (Utils.isHeightAuto(layoutBox) && Utils.isBottomAuto(layoutBox) && Utils.isTopAuto(layoutBox))
     221            height = this._contentHeight(layoutBox); // 1
     222        else if (Utils.isTopAuto((layoutBox)) && Utils.isHeightAuto((layoutBox)) && !Utils.isBottomAuto((layoutBox)))
     223            height = this._contentHeight(layoutBox); // 3
     224        else if (Utils.isTopAuto((layoutBox)) && Utils.isBottomAuto((layoutBox)) && !Utils.isHeightAuto((layoutBox)))
     225            height = Utils.height(layoutBox); // 4
     226        else if (Utils.isHeightAuto((layoutBox)) && Utils.isBottomAuto((layoutBox)) && !Utils.isTopAuto((layoutBox)))
     227            height = this._contentHeight(layoutBox); // 5
     228        else if (Utils.isTopAuto((layoutBox)) && !Utils.isHeightAuto((layoutBox)) && !Utils.isBottomAuto((layoutBox)))
     229            height = Utils.height(layoutBox); // 6
     230        else if (Utils.isHeightAuto((layoutBox)) && !Utils.isTopAuto((layoutBox)) && !Utils.isBottomAuto((layoutBox)))
     231            height = Math.max(0, this.displayBox(layoutBox.containingBlock()).contentBox().height() - Utils.bottom(layoutBox) - Utils.top(layoutBox)); // 7
     232        else if (Utils.isBottomAuto((layoutBox)) && !Utils.isTopAuto((layoutBox)) && !Utils.isHeightAuto((layoutBox)))
     233            height = Utils.height(layoutBox); // 8
     234        else
     235            ASSERT_NOT_REACHED();
     236        height += Utils.computedVerticalBorderAndPadding(layoutBox.node());
     237        this.displayBox(layoutBox).setHeight(height);
     238    }
     239
     240    _computeOutOfFlowPosition(layoutBox) {
     241        let displayBox = this.displayBox(layoutBox);
     242        let top = Number.NaN;
     243        let containerSize = this.displayBox(layoutBox.containingBlock()).contentBox().size();
     244        // Top/bottom
     245        if (Utils.isTopAuto(layoutBox) && Utils.isBottomAuto(layoutBox)) {
     246            ASSERT(Utils.isStaticallyPositioned(layoutBox));
     247            // Vertically statically positioned.
     248            // 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).
     249            let parent = layoutBox.parent();
     250            let parentDisplayBox = this.displayBox(parent);
     251            let previousInFlowSibling = layoutBox.previousInFlowSibling();
     252            let contentBottom = previousInFlowSibling ? this.displayBox(previousInFlowSibling).bottom() : parentDisplayBox.contentBox().top();
     253            top = contentBottom + this.marginTop(layoutBox);
     254            // Convert static position (in parent coordinate system) to absolute (in containing block coordindate system).
     255            if (parent != layoutBox.containingBlock()) {
     256                ASSERT(displayBox.parent() == this.displayBox(layoutBox.containingBlock()));
     257                top += Utils.mapPosition(parentDisplayBox.topLeft(), parentDisplayBox, displayBox.parent()).top();
     258            }
     259        } else if (!Utils.isTopAuto(layoutBox))
     260            top = Utils.top(layoutBox) + this.marginTop(layoutBox);
     261        else if (!Utils.isBottomAuto(layoutBox))
     262            top = containerSize.height() - Utils.bottom(layoutBox) - displayBox.height() - this.marginBottom(layoutBox);
     263        else
     264            ASSERT_NOT_REACHED();
     265        // Left/right
     266        let left = Number.NaN;
     267        if (Utils.isLeftAuto(layoutBox) && Utils.isRightAuto(layoutBox)) {
     268            ASSERT(Utils.isStaticallyPositioned(layoutBox));
     269            // Horizontally statically positioned.
     270            // 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).
     271            let parent = layoutBox.parent();
     272            let parentDisplayBox = this.displayBox(parent);
     273            left = parentDisplayBox.contentBox().left() + this.marginLeft(layoutBox);
     274            // Convert static position (in parent coordinate system) to absolute (in containing block coordindate system).
     275            if (parent != layoutBox.containingBlock()) {
     276                ASSERT(displayBox.parent() == this.displayBox(layoutBox.containingBlock()));
     277                left += Utils.mapPosition(parentDisplayBox.topLeft(), parentDisplayBox, displayBox.parent()).left();
     278            }
     279        } else if (!Utils.isLeftAuto(layoutBox))
     280            left = Utils.left(layoutBox) + this.marginLeft(layoutBox);
     281        else if (!Utils.isRightAuto(layoutBox))
     282            left = containerSize.width() - Utils.right(layoutBox) - displayBox.width() - this.marginRight(layoutBox);
     283        else
     284            ASSERT_NOT_REACHED();
     285        displayBox.setTopLeft(new LayoutPoint(top, left));
     286    }
     287
     288    _shrinkToFitWidth(layoutBox) {
     289        // FIXME: this is naive and missing the actual preferred width computation.
     290        ASSERT(Utils.isWidthAuto(layoutBox));
     291        if (!layoutBox.isContainer() || !layoutBox.hasChild())
     292            return 0;
     293        let width = 0;
     294        for (let inFlowChild = layoutBox.firstInFlowChild(); inFlowChild; inFlowChild = inFlowChild.nextInFlowSibling()) {
     295            let widthCandidate = Utils.isWidthAuto(inFlowChild) ? this._shrinkToFitWidth(inFlowChild) : Utils.width(inFlowChild);
     296            width = Math.max(width, widthCandidate + Utils.computedHorizontalBorderAndPadding(inFlowChild.node()));
     297        }
     298        return width;
    149299    }
    150300
  • trunk/Tools/LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js

    r230469 r230484  
    5151        this._placeInFlowPositionedChildren(this.formattingRoot());
    5252        // And take care of out-of-flow boxes as the final step.
    53         this._placeOutOfFlowDescendants(this.formattingRoot());
     53        this._layoutOutOfFlowDescendants(this.formattingRoot());
    5454        this._commitLine();
    5555        ASSERT(!this.m_inlineContainerStack.length);
     
    7070        this._removeFromLayoutQueue(inlineContainer);
    7171        this._addToLayoutQueue(inlineContainer.nextInFlowOrFloatSibling());
    72         // Place the in- and out-of-flow positioned children.
     72        // Place inflow positioned children.
    7373        this._placeInFlowPositionedChildren(inlineContainer);
    74         this._placeOutOfFlowDescendants(inlineContainer);
    7574    }
    7675
     
    7877    _handleInlineBlockContainer(inlineBlockContainer) {
    7978        ASSERT(inlineBlockContainer.establishesFormattingContext());
     79        let displayBox = this.displayBox(inlineBlockContainer);
     80
     81        // TODO: auto width/height
    8082        this._adjustLineForInlineContainerStart(inlineBlockContainer);
    81         // TODO: auto width/height
    82         let displayBox = this.displayBox(inlineBlockContainer);
    8383        displayBox.setWidth(Utils.width(inlineBlockContainer) + Utils.computedHorizontalBorderAndPadding(inlineBlockContainer.node()));
     84        this.layoutState().layout(inlineBlockContainer);
    8485        displayBox.setHeight(Utils.height(inlineBlockContainer) + Utils.computedVerticalBorderAndPadding(inlineBlockContainer.node()));
    85         this.layoutState().layout(inlineBlockContainer);
     86        this._adjustLineForInlineContainerEnd(inlineBlockContainer);
     87
    8688        this._line().addInlineContainerBox(displayBox.size());
    87         this._adjustLineForInlineContainerEnd(inlineBlockContainer);
    8889        this._removeFromLayoutQueue(inlineBlockContainer);
    8990        this._addToLayoutQueue(inlineBlockContainer.nextInFlowOrFloatSibling());
     
    151152        let offset = this.marginRight(inlineContainer) + Utils.computedBorderAndPaddingRight(inlineContainer.node());
    152153        this._line().adjustWithOffset(offset);
    153     }
    154 
    155     _placeOutOfFlowDescendants(container) {
    156 
    157154    }
    158155
  • trunk/Tools/LayoutReloaded/test/index.html

    r230469 r230484  
    8181    "inline-with-padding-border-margin-offsets.html",
    8282    "inline-block-with-fixed-width-height.html",
    83     "inline-with-relative-positioning.html"
     83    "inline-with-relative-positioning.html",
     84    "inline-with-out-of-flow-descendant.html"
    8485];
    8586
Note: See TracChangeset for help on using the changeset viewer.