Diff
Modified: trunk/LayoutTests/ChangeLog (237730 => 237731)
--- trunk/LayoutTests/ChangeLog 2018-11-02 14:21:56 UTC (rev 237730)
+++ trunk/LayoutTests/ChangeLog 2018-11-02 14:23:54 UTC (rev 237731)
@@ -1,3 +1,14 @@
+2018-11-02 Zalan Bujtas <za...@apple.com>
+
+ [LFC][IFC] Add support for intrinsic width calculation
+ https://bugs.webkit.org/show_bug.cgi?id=191144
+
+ Reviewed by Antti Koivisto.
+
+ * fast/inline/simple-shrink-to-fit-inline-block-expected.txt: Added.
+ * fast/inline/simple-shrink-to-fit-inline-block.html: Added.
+ * platform/ios/TestExpectations:
+
2018-11-01 Philippe Normand <pnorm...@igalia.com>
[Apache] Self-signed SSL certificate RSA key is considered too weak
Added: trunk/LayoutTests/fast/inline/simple-shrink-to-fit-inline-block-expected.txt (0 => 237731)
--- trunk/LayoutTests/fast/inline/simple-shrink-to-fit-inline-block-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/inline/simple-shrink-to-fit-inline-block-expected.txt 2018-11-02 14:23:54 UTC (rev 237731)
@@ -0,0 +1,13 @@
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {DIV} at (0,0) size 300x102
+ RenderText {#text} at (0,1) size 86x18
+ text run at (0,1) width 86: "first line with"
+ RenderBlock {DIV} at (85,0) size 77x102 [border: (1px solid #FF0000)]
+ RenderText {#text} at (1,1) size 74x18
+ text run at (1,1) width 74: "shrink to fit"
+ RenderText {#text} at (161,1) size 48x18
+ text run at (161,1) width 48: "content"
Added: trunk/LayoutTests/fast/inline/simple-shrink-to-fit-inline-block.html (0 => 237731)
--- trunk/LayoutTests/fast/inline/simple-shrink-to-fit-inline-block.html (rev 0)
+++ trunk/LayoutTests/fast/inline/simple-shrink-to-fit-inline-block.html 2018-11-02 14:23:54 UTC (rev 237731)
@@ -0,0 +1,14 @@
+<style>
+#main {
+ width: 300px;
+}
+
+#inline-b {
+ border: 1px solid red;
+ display: inline-block;
+ height: 100px;
+}
+
+</style>
+
+<div id=main>first line with<div id=inline-b>shrink to fit</div>content</div>
Modified: trunk/LayoutTests/platform/ios/TestExpectations (237730 => 237731)
--- trunk/LayoutTests/platform/ios/TestExpectations 2018-11-02 14:21:56 UTC (rev 237730)
+++ trunk/LayoutTests/platform/ios/TestExpectations 2018-11-02 14:23:54 UTC (rev 237731)
@@ -3114,6 +3114,7 @@
fast/inline/simple-intruding-floats2.html [ Failure ]
fast/inline/simple-intruding-floats3.html [ Failure ]
fast/inline/simple-inline-block.html [ Failure ]
+fast/inline/simple-shrink-to-fit-inline-block.html [ Failure ]
# Datalist
webkit.org/b/186714 fast/forms/datalist/datalist-textinput-keydown.html [ Skip ]
Modified: trunk/Source/WebCore/ChangeLog (237730 => 237731)
--- trunk/Source/WebCore/ChangeLog 2018-11-02 14:21:56 UTC (rev 237730)
+++ trunk/Source/WebCore/ChangeLog 2018-11-02 14:23:54 UTC (rev 237731)
@@ -1,5 +1,28 @@
2018-11-02 Zalan Bujtas <za...@apple.com>
+ [LFC][IFC] Add support for intrinsic width calculation
+ https://bugs.webkit.org/show_bug.cgi?id=191144
+
+ Reviewed by Antti Koivisto.
+
+ This is the inline formatting version of the shrink-to-fit computation. It generates inline runs
+ and uses InlineLineBreaker to compute min/max width. This is very similar to ::layout.
+
+ Test: fast/inline/simple-shrink-to-fit-inline-block.html
+
+ * layout/inlineformatting/InlineFormattingContext.cpp:
+ (WebCore::Layout::InlineFormattingContext::layout const):
+ (WebCore::Layout::InlineFormattingContext::computeWidthAndMargin const):
+ (WebCore::Layout::InlineFormattingContext::computeHeightAndMargin const):
+ (WebCore::Layout::InlineFormattingContext::layoutFormattingContextRoot const):
+ (WebCore::Layout::InlineFormattingContext::computeWidthAndHeightForReplacedInlineBox const):
+ (WebCore::Layout::InlineFormattingContext::collectInlineContent const):
+ (WebCore::Layout::InlineFormattingContext::instrinsicWidthConstraints const):
+ (WebCore::Layout::InlineFormattingContext::computeWidthAndHeightForInlineBox const): Deleted.
+ * layout/inlineformatting/InlineFormattingContext.h:
+
+2018-11-02 Zalan Bujtas <za...@apple.com>
+
[LFC][BFC] BlockFormattingContext::instrinsicWidthConstraints logic should look similar to ::layout
https://bugs.webkit.org/show_bug.cgi?id=191181
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (237730 => 237731)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2018-11-02 14:21:56 UTC (rev 237730)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2018-11-02 14:23:54 UTC (rev 237731)
@@ -60,43 +60,22 @@
auto& inlineFormattingState = downcast<InlineFormattingState>(formattingState());
InlineRunProvider inlineRunProvider(inlineFormattingState);
- auto& formattingRoot = downcast<Container>(root());
- auto* layoutBox = formattingRoot.firstInFlowOrFloatingChild();
- // Casually walk through the block's descendants and place the inline boxes one after the other as much as we can (yeah, I am looking at you floats).
- while (layoutBox) {
- if (layoutBox->establishesFormattingContext()) {
- layoutFormattingContextRoot(*layoutBox);
- // Formatting context roots take care of their entire subtree. Continue with next sibling.
- inlineRunProvider.append(*layoutBox);
- layoutBox = layoutBox->nextInFlowOrFloatingSibling();
+ collectInlineContent(inlineRunProvider);
+ // Compute width/height for non-text content.
+ for (auto& inlineRun : inlineRunProvider.runs()) {
+ if (inlineRun.isText())
continue;
- }
- if (is<Container>(layoutBox)) {
- ASSERT(is<InlineContainer>(layoutBox));
- layoutBox = downcast<Container>(*layoutBox).firstInFlowOrFloatingChild();
+ auto& layoutBox = inlineRun.inlineItem().layoutBox();
+ if (layoutBox.establishesFormattingContext()) {
+ layoutFormattingContextRoot(layoutBox);
continue;
}
-
- inlineRunProvider.append(*layoutBox);
- computeWidthAndHeightForInlineBox(*layoutBox);
-
- for (; layoutBox; layoutBox = layoutBox->parent()) {
- if (layoutBox == &formattingRoot) {
- layoutBox = nullptr;
- break;
- }
- if (auto* nextSibling = layoutBox->nextInFlowOrFloatingSibling()) {
- layoutBox = nextSibling;
- break;
- }
- }
- ASSERT(!layoutBox || layoutBox->isDescendantOf(formattingRoot));
+ computeWidthAndHeightForReplacedInlineBox(layoutBox);
}
layoutInlineContent(inlineRunProvider);
-
LOG_WITH_STREAM(FormattingContextLayout, stream << "[End] -> inline formatting context -> formatting root(" << &root() << ")");
}
@@ -204,81 +183,69 @@
line.close(Line::LastLine::Yes);
}
-void InlineFormattingContext::layoutFormattingContextRoot(const Box& layoutBox) const
+void InlineFormattingContext::computeWidthAndMargin(const Box& layoutBox) const
{
auto& layoutState = this->layoutState();
- ASSERT(layoutBox.isFloatingPositioned() || layoutBox.isInlineBlockBox());
+ WidthAndMargin widthAndMargin;
+ if (layoutBox.isFloatingPositioned())
+ widthAndMargin = Geometry::floatingWidthAndMargin(layoutState, layoutBox);
+ else if (layoutBox.isInlineBlockBox())
+ widthAndMargin = Geometry::inlineBlockWidthAndMargin(layoutState, layoutBox);
+ else if (layoutBox.replaced())
+ widthAndMargin = Geometry::inlineReplacedWidthAndMargin(layoutState, layoutBox);
+ else
+ ASSERT_NOT_REACHED();
+
auto& displayBox = layoutState.displayBoxForLayoutBox(layoutBox);
+ displayBox.setContentBoxWidth(widthAndMargin.width);
+ displayBox.setHorizontalMargin(widthAndMargin.margin);
+ displayBox.setHorizontalNonComputedMargin(widthAndMargin.nonComputedMargin);
+}
- auto computeWidthAndMargin = [&]() {
- WidthAndMargin widthAndMargin;
+void InlineFormattingContext::computeHeightAndMargin(const Box& layoutBox) const
+{
+ auto& layoutState = this->layoutState();
- if (layoutBox.isFloatingPositioned())
- widthAndMargin = Geometry::floatingWidthAndMargin(layoutState, layoutBox);
- else if (layoutBox.isInlineBlockBox())
- widthAndMargin = Geometry::inlineBlockWidthAndMargin(layoutState, layoutBox);
- else
- ASSERT_NOT_REACHED();
+ HeightAndMargin heightAndMargin;
+ if (layoutBox.isFloatingPositioned())
+ heightAndMargin = Geometry::floatingHeightAndMargin(layoutState, layoutBox);
+ else if (layoutBox.isInlineBlockBox())
+ heightAndMargin = Geometry::inlineBlockHeightAndMargin(layoutState, layoutBox);
+ else if (layoutBox.replaced())
+ heightAndMargin = Geometry::inlineReplacedHeightAndMargin(layoutState, layoutBox);
+ else
+ ASSERT_NOT_REACHED();
- displayBox.setContentBoxWidth(widthAndMargin.width);
- displayBox.setHorizontalMargin(widthAndMargin.margin);
- displayBox.setHorizontalNonComputedMargin(widthAndMargin.nonComputedMargin);
- };
+ auto& displayBox = layoutState.displayBoxForLayoutBox(layoutBox);
+ displayBox.setContentBoxHeight(heightAndMargin.height);
+ displayBox.setVerticalNonCollapsedMargin(heightAndMargin.margin);
+ displayBox.setVerticalMargin(heightAndMargin.collapsedMargin.value_or(heightAndMargin.margin));
+}
- auto computeHeightAndMargin = [&]() {
- HeightAndMargin heightAndMargin;
+void InlineFormattingContext::layoutFormattingContextRoot(const Box& layoutBox) const
+{
+ ASSERT(layoutBox.isFloatingPositioned() || layoutBox.isInlineBlockBox());
- if (layoutBox.isFloatingPositioned())
- heightAndMargin = Geometry::floatingHeightAndMargin(layoutState, layoutBox);
- else if (layoutBox.isInlineBlockBox())
- heightAndMargin = Geometry::inlineBlockHeightAndMargin(layoutState, layoutBox);
- else
- ASSERT_NOT_REACHED();
-
- displayBox.setContentBoxHeight(heightAndMargin.height);
- displayBox.setVerticalNonCollapsedMargin(heightAndMargin.margin);
- displayBox.setVerticalMargin(heightAndMargin.collapsedMargin.value_or(heightAndMargin.margin));
- };
-
- layoutState.createFormattingStateForFormattingRootIfNeeded(layoutBox);
+ auto& layoutState = this->layoutState();
+ auto& formattingState = layoutState.createFormattingStateForFormattingRootIfNeeded(layoutBox);
computeBorderAndPadding(layoutBox);
- computeWidthAndMargin();
-
+ computeWidthAndMargin(layoutBox);
// Swich over to the new formatting context (the one that the root creates).
- layoutState.establishedFormattingState(layoutBox).formattingContext(layoutBox)->layout();
-
+ formattingState.formattingContext(layoutBox)->layout();
// Come back and finalize the root's height and margin.
- computeHeightAndMargin();
+ computeHeightAndMargin(layoutBox);
}
-void InlineFormattingContext::computeWidthAndHeightForInlineBox(const Box& layoutBox) const
+void InlineFormattingContext::computeWidthAndHeightForReplacedInlineBox(const Box& layoutBox) const
{
ASSERT(!layoutBox.isContainer());
ASSERT(!layoutBox.establishesFormattingContext());
+ ASSERT(layoutBox.replaced());
- if (is<InlineBox>(layoutBox) && downcast<InlineBox>(layoutBox).hasTextContent()) {
- // Text content width is computed during text run generation. -It does not make any sense to measure unprocessed text here, since it will likely be
- // split up (or concatenated).
- return;
- }
-
- auto& layoutState = this->layoutState();
- // This is pretty much only for replaced inline boxes atm.
- ASSERT(layoutBox.replaced());
computeBorderAndPadding(layoutBox);
-
- auto widthAndMargin = Geometry::inlineReplacedWidthAndMargin(layoutState, layoutBox);
- auto heightAndMargin = Geometry::inlineReplacedHeightAndMargin(layoutState, layoutBox);
-
- auto& displayBox = layoutState.displayBoxForLayoutBox(layoutBox);
- displayBox.setContentBoxWidth(widthAndMargin.width);
- displayBox.setHorizontalMargin(widthAndMargin.margin);
- displayBox.setHorizontalNonComputedMargin(widthAndMargin.nonComputedMargin);
-
- displayBox.setContentBoxHeight(heightAndMargin.height);
- displayBox.setVerticalNonCollapsedMargin(heightAndMargin.margin);
- displayBox.setVerticalMargin(heightAndMargin.collapsedMargin.value_or(heightAndMargin.margin));
+ computeWidthAndMargin(layoutBox);
+ computeHeightAndMargin(layoutBox);
}
void InlineFormattingContext::computeFloatPosition(const FloatingContext& floatingContext, Line& line, const Box& floatBox) const
@@ -301,9 +268,79 @@
{
}
+void InlineFormattingContext::collectInlineContent(InlineRunProvider& inlineRunProvider) const
+{
+ if (!is<Container>(root()))
+ return;
+
+ auto& formattingRoot = downcast<Container>(root());
+ auto* layoutBox = formattingRoot.firstInFlowOrFloatingChild();
+
+ while (layoutBox) {
+ ASSERT(layoutBox->isDescendantOf(formattingRoot));
+
+ if (layoutBox->establishesFormattingContext()) {
+ inlineRunProvider.append(*layoutBox);
+ layoutBox = layoutBox->nextInFlowOrFloatingSibling();
+ continue;
+ }
+
+ if (is<Container>(layoutBox)) {
+ layoutBox = downcast<Container>(*layoutBox).firstInFlowOrFloatingChild();
+ continue;
+ }
+
+ inlineRunProvider.append(*layoutBox);
+
+ while (true) {
+ if (auto* nextSibling = layoutBox->nextInFlowOrFloatingSibling()) {
+ layoutBox = nextSibling;
+ break;
+ }
+
+ layoutBox = layoutBox->parent();
+
+ if (layoutBox == &formattingRoot)
+ return;
+ }
+ }
+}
+
FormattingContext::InstrinsicWidthConstraints InlineFormattingContext::instrinsicWidthConstraints() const
{
- return { };
+ auto& formattingStateForRoot = layoutState().formattingStateForBox(root());
+ if (auto instrinsicWidthConstraints = formattingStateForRoot.instrinsicWidthConstraints(root()))
+ return *instrinsicWidthConstraints;
+
+ auto& inlineFormattingState = downcast<InlineFormattingState>(formattingState());
+ InlineRunProvider inlineRunProvider(inlineFormattingState);
+ collectInlineContent(inlineRunProvider);
+
+ // Compute width for non-text content.
+ for (auto& inlineRun : inlineRunProvider.runs()) {
+ if (inlineRun.isText())
+ continue;
+
+ computeWidthAndMargin(inlineRun.inlineItem().layoutBox());
+ }
+
+ auto maximumLineWidth = [&](auto availableWidth) {
+ LayoutUnit maxContentLogicalRight;
+ InlineLineBreaker lineBreaker(layoutState(), inlineFormattingState.inlineContent(), inlineRunProvider.runs());
+ LayoutUnit lineLogicalRight;
+ while (auto run = lineBreaker.nextRun(lineLogicalRight, availableWidth, !lineLogicalRight)) {
+ if (run->position == InlineLineBreaker::Run::Position::LineBegin)
+ lineLogicalRight = 0;
+ lineLogicalRight += run->width;
+
+ maxContentLogicalRight = std::max(maxContentLogicalRight, lineLogicalRight);
+ }
+ return maxContentLogicalRight;
+ };
+
+ auto instrinsicWidthConstraints = FormattingContext::InstrinsicWidthConstraints { maximumLineWidth(0), maximumLineWidth(LayoutUnit::max()) };
+ formattingStateForRoot.setInstrinsicWidthConstraints(root(), instrinsicWidthConstraints);
+ return instrinsicWidthConstraints;
}
}
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h (237730 => 237731)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2018-11-02 14:21:56 UTC (rev 237730)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2018-11-02 14:23:54 UTC (rev 237731)
@@ -106,11 +106,14 @@
void initializeNewLine(Line&) const;
void layoutFormattingContextRoot(const Box&) const;
- void computeWidthAndHeightForInlineBox(const Box&) const;
+ void computeWidthAndHeightForReplacedInlineBox(const Box&) const;
+ void computeHeightAndMargin(const Box&) const;
+ void computeWidthAndMargin(const Box&) const;
void computeFloatPosition(const FloatingContext&, Line&, const Box&) const;
void computeStaticPosition(const Box&) const override;
void computeInFlowPositionedPosition(const Box&) const override;
+ void collectInlineContent(InlineRunProvider&) const;
InstrinsicWidthConstraints instrinsicWidthConstraints() const override;
};
Modified: trunk/Tools/ChangeLog (237730 => 237731)
--- trunk/Tools/ChangeLog 2018-11-02 14:21:56 UTC (rev 237730)
+++ trunk/Tools/ChangeLog 2018-11-02 14:23:54 UTC (rev 237731)
@@ -1,3 +1,12 @@
+2018-11-02 Zalan Bujtas <za...@apple.com>
+
+ [LFC][IFC] Add support for intrinsic width calculation
+ https://bugs.webkit.org/show_bug.cgi?id=191144
+
+ Reviewed by Antti Koivisto.
+
+ * LayoutReloaded/misc/LFC-passing-tests.txt:
+
2018-11-01 Philippe Normand <pnorm...@igalia.com>
[Apache] Self-signed SSL certificate RSA key is considered too weak
Modified: trunk/Tools/LayoutReloaded/misc/LFC-passing-tests.txt (237730 => 237731)
--- trunk/Tools/LayoutReloaded/misc/LFC-passing-tests.txt 2018-11-02 14:21:56 UTC (rev 237730)
+++ trunk/Tools/LayoutReloaded/misc/LFC-passing-tests.txt 2018-11-02 14:23:54 UTC (rev 237731)
@@ -68,3 +68,4 @@
fast/inline/simple-intruding-floats2.html
fast/inline/simple-intruding-floats3.html
fast/inline/simple-inline-block.html
+fast/inline/simple-shrink-to-fit-inline-block.html