Skip to content

Commit

Permalink
[LFC][TFC] Add support for percentage min/max-width
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=213436

Reviewed by Antti Koivisto.

Source/WebCore:

1. The table generates a principal block container box called the table wrapper box that contains the table box itself and any caption boxes.
2. The table wrapper box establishes a block formatting context, and the table box establishes a table formatting context.
3. The computed values of properties 'position', 'float', 'margin-*', 'top', 'right', 'bottom', and 'left' on
   the table element are used on the table wrapper box and not the table box; all other values of non-inheritable
   properties are used on the table box and not the table wrapper box.
4. In a block formatting context, each box's left outer edge touches the left edge of the containing block.
   This is true even in the presence of floats, unless the box establishes a new block formatting context (in which case the
   box itself may become narrower due to the floats)

Now consider the following case:
<div style="display: block; width: 500px;">
    <div style="float: left; width: 100px;"></div>
    <div style="display: table; width: 10%;"></div>
</div>
1. We create a table wrapper box to wrap the "display: table" block level box (#1).
2. The table wrapper box's width property is set to auto (#3).
3. Since it establishes a new block formatting context, the available horizontal space gets shrunk by the float (#4)
4. The table wrapper box's used width computes to 500px - 100px -> 400px;

Now we are inside the BFC established by the table wrapper box and try to resolve the table's width -> %10.
According to the normal BFC rules, it should compute to 10% of the containing block's logical width: 400px -> 40px.
However in practice it computes to 50px (10% of 500px).

Similar setup with non-table content would resolve the inner block level box's width to 40px;
<div style="display: block; width: 500px">
    <div style="float: left; width: 100px;"></div>
    <div style="display: block; overflow: hidden;">
        <div style="display: block; width: 10%"></div>
    </div>
</div>
This needs clarification.

Test: fast/layoutformattingcontext/float-avoider-available-horizontal-space3.html

* layout/FormattingContext.h:
(WebCore::Layout::FormattingContext::isTableWrapperBlockFormattingContext const):
* layout/blockformatting/BlockFormattingContext.cpp:
(WebCore::Layout::BlockFormattingContext::layoutInFlowContent):
* layout/blockformatting/tablewrapper/TableWrapperBlockFormattingContext.cpp:
(WebCore::Layout::TableWrapperBlockFormattingContext::computeWidthAndMarginForTableBox):
* layout/blockformatting/tablewrapper/TableWrapperBlockFormattingContext.h:

LayoutTests:

* fast/layoutformattingcontext/float-avoider-available-horizontal-space3-expected.html: Added.
* fast/layoutformattingcontext/float-avoider-available-horizontal-space3.html: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@263327 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
zalan@apple.com committed Jun 21, 2020
1 parent 0bfe795 commit d42669f
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 4 deletions.
10 changes: 10 additions & 0 deletions LayoutTests/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
2020-06-21 Zalan Bujtas <zalan@apple.com>

[LFC][TFC] Add support for percentage min/max-width
https://bugs.webkit.org/show_bug.cgi?id=213436

Reviewed by Antti Koivisto.

* fast/layoutformattingcontext/float-avoider-available-horizontal-space3-expected.html: Added.
* fast/layoutformattingcontext/float-avoider-available-horizontal-space3.html: Added.

2020-06-20 Zalan Bujtas <zalan@apple.com>

[LFC][TFC][Quirk] Table height needs quirk handling
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html> <!-- webkit-test-runner [ internal:LayoutFormattingContextEnabled=true internal:LayoutFormattingContextIntegrationEnabled=false ] -->
<style>
.first {
height: 60px;
width: 50px;
background-color: green;
}

.second {
height: 40px;
width: 50px;
position: relative;
top: -60px;
left: 50px;
background-color: blue;
}

.third {
height: 20px;
width: 20px;
position: relative;
top: -60px;
left: 50px;
background-color: blue;
}
</style>
<div class=first></div>
<div class=second></div>
<div class=third></div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html><!-- webkit-test-runner [ internal:LayoutFormattingContextEnabled=true internal:LayoutFormattingContextIntegrationEnabled=false ] -->
<style>
.container {
width: 100px;
height: 20px;
}

.floatBox {
float: left;
width: 50px;
height: 20px;
background-color: green;
}

.table {
display: table;
height: 20px;
background-color: blue;
}
</style>
<div class=container>
<div class=floatBox></div>
<div class=table style="width: 50%"></div>
</div>
<div class=container>
<div class=floatBox></div>
<div class=table style="min-width: 50%; width: 10%"></div>
</div>
<div class=container>
<div class=floatBox></div>
<div class=table style="max-width: 20%; width: 50%"></div>
</div>
49 changes: 49 additions & 0 deletions Source/WebCore/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,52 @@
2020-06-21 Zalan Bujtas <zalan@apple.com>

[LFC][TFC] Add support for percentage min/max-width
https://bugs.webkit.org/show_bug.cgi?id=213436

Reviewed by Antti Koivisto.

1. The table generates a principal block container box called the table wrapper box that contains the table box itself and any caption boxes.
2. The table wrapper box establishes a block formatting context, and the table box establishes a table formatting context.
3. The computed values of properties 'position', 'float', 'margin-*', 'top', 'right', 'bottom', and 'left' on
the table element are used on the table wrapper box and not the table box; all other values of non-inheritable
properties are used on the table box and not the table wrapper box.
4. In a block formatting context, each box's left outer edge touches the left edge of the containing block.
This is true even in the presence of floats, unless the box establishes a new block formatting context (in which case the
box itself may become narrower due to the floats)

Now consider the following case:
<div style="display: block; width: 500px;">
<div style="float: left; width: 100px;"></div>
<div style="display: table; width: 10%;"></div>
</div>
1. We create a table wrapper box to wrap the "display: table" block level box (#1).
2. The table wrapper box's width property is set to auto (#3).
3. Since it establishes a new block formatting context, the available horizontal space gets shrunk by the float (#4)
4. The table wrapper box's used width computes to 500px - 100px -> 400px;

Now we are inside the BFC established by the table wrapper box and try to resolve the table's width -> %10.
According to the normal BFC rules, it should compute to 10% of the containing block's logical width: 400px -> 40px.
However in practice it computes to 50px (10% of 500px).

Similar setup with non-table content would resolve the inner block level box's width to 40px;
<div style="display: block; width: 500px">
<div style="float: left; width: 100px;"></div>
<div style="display: block; overflow: hidden;">
<div style="display: block; width: 10%"></div>
</div>
</div>
This needs clarification.

Test: fast/layoutformattingcontext/float-avoider-available-horizontal-space3.html

* layout/FormattingContext.h:
(WebCore::Layout::FormattingContext::isTableWrapperBlockFormattingContext const):
* layout/blockformatting/BlockFormattingContext.cpp:
(WebCore::Layout::BlockFormattingContext::layoutInFlowContent):
* layout/blockformatting/tablewrapper/TableWrapperBlockFormattingContext.cpp:
(WebCore::Layout::TableWrapperBlockFormattingContext::computeWidthAndMarginForTableBox):
* layout/blockformatting/tablewrapper/TableWrapperBlockFormattingContext.h:

2020-06-20 Jer Noble <jer.noble@apple.com>

RecoveryOS: PAL::getAVPlayerLayerClass() will crash when AVFoundation is missing
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/layout/FormattingContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class FormattingContext {
bool isBlockFormattingContext() const { return root().establishesBlockFormattingContext(); }
bool isInlineFormattingContext() const { return root().establishesInlineFormattingContext(); }
bool isTableFormattingContext() const { return root().establishesTableFormattingContext(); }
bool isTableWrapperBlockFormattingContext() const { return isBlockFormattingContext() && root().isTableWrapperBox(); }

enum class EscapeReason {
NeedsGeometryFromEstablishedFormattingContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "LayoutInitialContainingBlock.h"
#include "LayoutState.h"
#include "Logging.h"
#include "TableWrapperBlockFormattingContext.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/text/TextStream.h>

Expand Down Expand Up @@ -123,7 +124,10 @@ void BlockFormattingContext::layoutInFlowContent(InvalidationState& invalidation
precomputeVerticalPositionForBoxAndAncestors(containerBox, { constraints, containingBlockConstraints });
}
// Layout the inflow descendants of this formatting context root.
LayoutContext::createFormattingContext(containerBox, layoutState())->layoutInFlowContent(invalidationState, geometry().constraintsForInFlowContent(containerBox));
auto formattingContext = LayoutContext::createFormattingContext(containerBox, layoutState());
if (containerBox.isTableWrapperBox())
downcast<TableWrapperBlockFormattingContext>(*formattingContext).setHorizontalConstraintsIgnoringFloats(containingBlockConstraints.horizontal);
formattingContext->layoutInFlowContent(invalidationState, geometry().constraintsForInFlowContent(containerBox));
}
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,36 @@ void TableWrapperBlockFormattingContext::computeWidthAndMarginForTableBox(const
}

auto availableHorizontalSpace = horizontalConstraints.logicalWidth;
// 1. The table generates a principal block container box called the table wrapper box that contains the table box itself and any caption boxes.
// 2. The table wrapper box establishes a block formatting context, and the table box establishes a table formatting context.
// 3. The computed values of properties 'position', 'float', 'margin-*', 'top', 'right', 'bottom', and 'left' on
// the table element are used on the table wrapper box and not the table box; all other values of non-inheritable
// properties are used on the table box and not the table wrapper box.
// 4. In a block formatting context, each box's left outer edge touches the left edge of the containing block.
// This is true even in the presence of floats, unless the box establishes a new block formatting context (in which case the
// box itself may become narrower due to the floats)
//
// Now consider the following case:
// <div style="display: block; width: 500px;">
// <div style="float: left; width: 100px;"></div>
// <div style="display: table; width: 10%;"></div>
// </div>
// </div>
// 1. We create a table wrapper box to wrap the "display: table" block level box (#1).
// 2. The table wrapper box's width property is set to auto (#3).
// 3. Since it establishes a new block formatting context, the available horizontal space gets shrunk by the float (#4)
// 4. The table wrapper box's used width computes to 500px - 100px -> 400px;
//
// Now we are inside the BFC established by the table wrapper box and try to resolve the table's width -> %10.
// According to the normal BFC rules, it should compute to 10% of the containing block's logical width: 400px -> 40px.
// However in practice it computes to 50px (10% of 500px).
// Similar setup with non-table content would resolve the inner block level box's width to 40px;
// This needs clarification in the spec.
auto horizontalConstraintForResolvingWidth = m_horizontalConstraintsIgnoringFloats.logicalWidth;
auto geometry = this->geometry();
auto computedWidth = geometry.computedWidth(tableBox, availableHorizontalSpace);
auto computedMaxWidth = geometry.computedMaxWidth(tableBox, availableHorizontalSpace);
auto computedMinWidth = geometry.computedMinWidth(tableBox, availableHorizontalSpace);
auto computedWidth = geometry.computedWidth(tableBox, horizontalConstraintForResolvingWidth);
auto computedMaxWidth = geometry.computedMaxWidth(tableBox, horizontalConstraintForResolvingWidth);
auto computedMinWidth = geometry.computedMinWidth(tableBox, horizontalConstraintForResolvingWidth);
// Use the generic shrink-to-fit-width logic as the initial width for the table.
auto usedWidth = std::min(std::max(intrinsicWidthConstraints.minimum, availableHorizontalSpace), intrinsicWidthConstraints.maximum);
if (computedWidth || computedMinWidth || computedMaxWidth) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class TableWrapperBlockFormattingContext final : public BlockFormattingContext {

void layoutInFlowContent(InvalidationState&, const ConstraintsForInFlowContent&) final;

void setHorizontalConstraintsIgnoringFloats(const HorizontalConstraints& horizontalConstraints) { m_horizontalConstraintsIgnoringFloats = horizontalConstraints; }

private:
class Quirks : public BlockFormattingContext::Quirks {
public:
Expand All @@ -56,6 +58,9 @@ class TableWrapperBlockFormattingContext final : public BlockFormattingContext {
void computeBorderAndPaddingForTableBox(const ContainerBox&, const HorizontalConstraints&);
void computeWidthAndMarginForTableBox(const ContainerBox&, const HorizontalConstraints&);
void computeHeightAndMarginForTableBox(const ContainerBox&, const ConstraintsForInFlowContent&);

private:
HorizontalConstraints m_horizontalConstraintsIgnoringFloats;
};

inline TableWrapperBlockFormattingContext::Quirks::Quirks(const TableWrapperBlockFormattingContext& formattingContext)
Expand All @@ -66,4 +71,6 @@ inline TableWrapperBlockFormattingContext::Quirks::Quirks(const TableWrapperBloc
}
}

SPECIALIZE_TYPE_TRAITS_LAYOUT_FORMATTING_CONTEXT(TableWrapperBlockFormattingContext, isTableWrapperBlockFormattingContext())

#endif

0 comments on commit d42669f

Please sign in to comment.