Bug 1260031 - Not force break before a block when calculating intrinsic width if the current line is empty and the block cannot intersect floats. r=dbaron
MozReview-Commit-ID: 9rNUDK5t5jg
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -778,29 +778,36 @@ nsBlockFrame::GetPrefISize(nsRenderingCo
IndentBy(stdout, gNoiseIndent);
printf("line (%s%s)\n",
line->IsBlock() ? "block" : "inline",
line->IsEmpty() ? ", empty" : "");
}
AutoNoisyIndenter lineindent(gNoisyIntrinsic);
#endif
if (line->IsBlock()) {
- data.ForceBreak();
+ if (!data.mLineIsEmpty || BlockCanIntersectFloats(line->mFirstChild)) {
+ data.ForceBreak();
+ }
data.mCurrentLine = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
line->mFirstChild, nsLayoutUtils::PREF_ISIZE);
data.ForceBreak();
} else {
if (!curFrame->GetPrevContinuation() &&
line == curFrame->begin_lines()) {
// Only add text-indent if it has no percentages; using a
// percentage basis of 0 unconditionally would give strange
// behavior for calc(10%-3px).
const nsStyleCoord &indent = StyleText()->mTextIndent;
- if (indent.ConvertsToLength())
- data.mCurrentLine += nsRuleNode::ComputeCoordPercentCalc(indent, 0);
+ if (indent.ConvertsToLength()) {
+ nscoord length = indent.ToLength();
+ if (length != 0) {
+ data.mCurrentLine += length;
+ data.mLineIsEmpty = false;
+ }
+ }
}
// XXX Bug NNNNNN Should probably handle percentage text-indent.
data.mLine = &line;
data.SetLineContainer(curFrame);
nsIFrame *kid = line->mFirstChild;
for (int32_t i = 0, i_end = line->GetChildCount(); i != i_end;
++i, kid = kid->GetNextSibling()) {
--- a/layout/generic/nsFirstLetterFrame.cpp
+++ b/layout/generic/nsFirstLetterFrame.cpp
@@ -120,16 +120,17 @@ nsFirstLetterFrame::AddInlineMinISize(ns
// Needed for non-floating first-letter frames and for the continuations
// following the first-letter that we also use nsFirstLetterFrame for.
/* virtual */ void
nsFirstLetterFrame::AddInlinePrefISize(nsRenderingContext *aRenderingContext,
nsIFrame::InlinePrefISizeData *aData)
{
DoInlineIntrinsicISize(aRenderingContext, aData, nsLayoutUtils::PREF_ISIZE);
+ aData->mLineIsEmpty = false;
}
// Needed for floating first-letter frames.
/* virtual */ nscoord
nsFirstLetterFrame::GetMinISize(nsRenderingContext *aRenderingContext)
{
return nsLayoutUtils::MinISizeFromInline(this, aRenderingContext);
}
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -4438,16 +4438,17 @@ nsIFrame::InlineMinISizeData::DefaultAdd
}
void
nsIFrame::InlinePrefISizeData::DefaultAddInlinePrefISize(nscoord aISize)
{
mCurrentLine = NSCoordSaturatingAdd(mCurrentLine, aISize);
mTrailingWhitespace = 0;
mSkipWhitespace = false;
+ mLineIsEmpty = false;
}
void
nsIFrame::InlineMinISizeData::ForceBreak()
{
mCurrentLine -= mTrailingWhitespace;
mPrevLines = std::max(mPrevLines, mCurrentLine);
mCurrentLine = mTrailingWhitespace = 0;
@@ -4527,16 +4528,17 @@ nsIFrame::InlinePrefISizeData::ForceBrea
mFloats.Clear();
}
mCurrentLine =
NSCoordSaturatingSubtract(mCurrentLine, mTrailingWhitespace, nscoord_MAX);
mPrevLines = std::max(mPrevLines, mCurrentLine);
mCurrentLine = mTrailingWhitespace = 0;
mSkipWhitespace = true;
+ mLineIsEmpty = true;
}
static void
AddCoord(const nsStyleCoord& aStyle,
nsIFrame* aFrame,
nscoord* aCoord, float* aPercent,
bool aClampNegativeToZero)
{
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1823,20 +1823,27 @@ public:
// Whether we're currently at the start of the line. If we are, we
// can't break (for example, between the text-indent and the first
// word).
bool mAtStartOfLine;
};
struct InlinePrefISizeData : public InlineIntrinsicISizeData {
+ InlinePrefISizeData()
+ : mLineIsEmpty(true)
+ {}
+
void ForceBreak();
// The default implementation for nsIFrame::AddInlinePrefISize.
void DefaultAddInlinePrefISize(nscoord aISize);
+
+ // True if the current line contains nothing other than placeholders.
+ bool mLineIsEmpty;
};
/**
* Add the intrinsic minimum width of a frame in a way suitable for
* use in inline layout to an |InlineIntrinsicISizeData| object that
* represents the intrinsic width information of all the previous
* frames in the inline layout region.
*
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -268,16 +268,17 @@ nsInlineFrame::AddInlineMinISize(nsRende
DoInlineIntrinsicISize(aRenderingContext, aData, nsLayoutUtils::MIN_ISIZE);
}
/* virtual */ void
nsInlineFrame::AddInlinePrefISize(nsRenderingContext *aRenderingContext,
nsIFrame::InlinePrefISizeData *aData)
{
DoInlineIntrinsicISize(aRenderingContext, aData, nsLayoutUtils::PREF_ISIZE);
+ aData->mLineIsEmpty = false;
}
/* virtual */
LogicalSize
nsInlineFrame::ComputeSize(nsRenderingContext *aRenderingContext,
WritingMode aWM,
const LogicalSize& aCBSize,
nscoord aAvailableISize,
--- a/layout/generic/nsRubyFrame.cpp
+++ b/layout/generic/nsRubyFrame.cpp
@@ -82,16 +82,17 @@ nsRubyFrame::AddInlinePrefISize(nsRender
nsIFrame::InlinePrefISizeData *aData)
{
for (nsIFrame* frame = this; frame; frame = frame->GetNextInFlow()) {
for (RubySegmentEnumerator e(static_cast<nsRubyFrame*>(frame));
!e.AtEnd(); e.Next()) {
e.GetBaseContainer()->AddInlinePrefISize(aRenderingContext, aData);
}
}
+ aData->mLineIsEmpty = false;
}
/* virtual */ void
nsRubyFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus)
{
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -8342,16 +8342,17 @@ nsTextFrame::AddInlinePrefISizeForFlow(n
const nsTextFragment* frag = mContent->GetText();
PropertyProvider provider(textRun, textStyle, frag, this,
iter, INT32_MAX, nullptr, 0, aTextRunType);
// text-combine-upright frame is constantly 1em on inline-axis.
if (StyleContext()->IsTextCombined()) {
aData->mCurrentLine += provider.GetFontMetrics()->EmHeight();
aData->mTrailingWhitespace = 0;
+ aData->mLineIsEmpty = false;
return;
}
bool collapseWhitespace = !textStyle->WhiteSpaceIsSignificant();
bool preformatNewlines = textStyle->NewlineIsSignificant(this);
bool preformatTabs = textStyle->TabIsSignificant();
gfxFloat tabWidth = -1;
uint32_t start =
@@ -8379,16 +8380,17 @@ nsTextFrame::AddInlinePrefISizeForFlow(n
}
}
if (i > lineStart) {
nscoord width = NSToCoordCeilClamped(
textRun->GetAdvanceWidth(Range(lineStart, i), &provider));
width = std::max(0, width);
aData->mCurrentLine = NSCoordSaturatingAdd(aData->mCurrentLine, width);
+ aData->mLineIsEmpty = false;
if (collapseWhitespace) {
uint32_t trimStart = GetEndOfTrimmedText(frag, textStyle, lineStart, i, &iter);
if (trimStart == start) {
// This is *all* trimmable whitespace, so whatever trailingWhitespace
// we saw previously is still trailing...
aData->mTrailingWhitespace += width;
} else {
@@ -8405,16 +8407,17 @@ nsTextFrame::AddInlinePrefISizeForFlow(n
if (preformattedTab) {
PropertyProvider::Spacing spacing;
provider.GetSpacing(Range(i, i + 1), &spacing);
aData->mCurrentLine += nscoord(spacing.mBefore);
gfxFloat afterTab =
AdvanceToNextTab(aData->mCurrentLine, this,
textRun, &tabWidth);
aData->mCurrentLine = nscoord(afterTab + spacing.mAfter);
+ aData->mLineIsEmpty = false;
lineStart = i + 1;
} else if (preformattedNewline) {
aData->ForceBreak();
lineStart = i;
}
}
// Check if we have collapsible whitespace at the end
new file mode 100644
--- /dev/null
+++ b/layout/reftests/floats/1260031-1-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Bug 1260031 - Intrinsic width with float</title>
+ <style>
+ #left {
+ display: inline-block;
+ width: 50px;
+ height: 50px;
+ background: green;
+ }
+ #right {
+ display: inline-block;
+ width: 50px;
+ height: 50px;
+ background: blue;
+ }
+ </style>
+</head>
+<body>
+ <div id="test">
+ <div id="wrapper">
+ <div id="left"></div><div id="right"></div>
+ </div>
+ </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/floats/1260031-1.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Bug 1260031 - Intrinsic width with float</title>
+ <style>
+ #wrapper {
+ background: red;
+ width: -moz-fit-content;
+ width: fit-content;
+ }
+ #left {
+ float: left;
+ width: 50px;
+ height: 50px;
+ background: green;
+ }
+ #right {
+ width: 50px;
+ height: 50px;
+ background: blue;
+ }
+ </style>
+</head>
+<body>
+ <div id="test">
+ <div id="wrapper">
+ <div id="left"></div>
+ <div id="right"></div>
+ </div>
+ </div>
+ <script>
+ document.getElementById("right").style = location.search.slice(1);
+ </script>
+</body>
+</html>
--- a/layout/reftests/floats/reftest.list
+++ b/layout/reftests/floats/reftest.list
@@ -16,16 +16,19 @@ fails == 345369-2.html 345369-2-ref.html
== 345369-4.html 345369-4-ref.html
== 345369-5.html 345369-5-ref.html
== 429974-1.html 429974-1-ref.html
== 478834-1.html 478834-1-ref.html
== 546048-1.html 546048-1-ref.html
== 775350-1.html 775350-1-ref.html
== 1114329.html 1114329-ref.html
== 1236745-1.html 1236745-1-ref.html
+== 1260031-1.html?display:table 1260031-1-ref.html
+== 1260031-1.html?display:table-cell 1260031-1-ref.html
+== 1260031-1.html?overflow:hidden 1260031-1-ref.html
== float-in-rtl-1a.html float-in-rtl-1-ref.html
fuzzy-if(skiaContent,1,27000) == float-in-rtl-1b.html float-in-rtl-1-ref.html
fuzzy-if(skiaContent,1,27000) == float-in-rtl-1c.html float-in-rtl-1-ref.html
fuzzy-if(skiaContent,1,27000) == float-in-rtl-1d.html float-in-rtl-1-ref.html
== float-in-rtl-2a.html float-in-rtl-2-ref.html
fuzzy-if(skiaContent,1,12000) == float-in-rtl-2b.html float-in-rtl-2-ref.html
fuzzy-if(skiaContent,1,12000) == float-in-rtl-2c.html float-in-rtl-2-ref.html
fuzzy-if(skiaContent,1,12000) == float-in-rtl-2d.html float-in-rtl-2-ref.html