Bug 1665657 - Whitespace that will hang should not contribute to the min inline-size of a textframe. r=emilio

This affects a few of the examples in the text/white-space-2 reftest, but the changes look sensible;
more significantly from an interop point of view, there are specific web-platform reftests that are
currently failing, but will pass after the patch.

Differential Revision: https://phabricator.services.mozilla.com/D95811
This commit is contained in:
Jonathan Kew 2020-11-04 13:31:30 +00:00
Родитель 810bc229cc
Коммит 0e3cf9687e
8 изменённых файлов: 34 добавлений и 28 удалений

Просмотреть файл

@ -801,12 +801,13 @@ static bool IsTrimmableSpace(char aCh) {
} }
static bool IsTrimmableSpace(const nsTextFragment* aFrag, uint32_t aPos, static bool IsTrimmableSpace(const nsTextFragment* aFrag, uint32_t aPos,
const nsStyleText* aStyleText) { const nsStyleText* aStyleText,
bool aAllowHangingWS = false) {
NS_ASSERTION(aPos < aFrag->GetLength(), "No text for IsSpace!"); NS_ASSERTION(aPos < aFrag->GetLength(), "No text for IsSpace!");
switch (aFrag->CharAt(aPos)) { switch (aFrag->CharAt(aPos)) {
case ' ': case ' ':
return !aStyleText->WhiteSpaceIsSignificant() && return (!aStyleText->WhiteSpaceIsSignificant() || aAllowHangingWS) &&
!IsSpaceCombiningSequenceTail(aFrag, aPos + 1); !IsSpaceCombiningSequenceTail(aFrag, aPos + 1);
case '\n': case '\n':
return !aStyleText->NewlineIsSignificantStyle() && return !aStyleText->NewlineIsSignificantStyle() &&
@ -814,7 +815,7 @@ static bool IsTrimmableSpace(const nsTextFragment* aFrag, uint32_t aPos,
case '\t': case '\t':
case '\r': case '\r':
case '\f': case '\f':
return !aStyleText->WhiteSpaceIsSignificant(); return !aStyleText->WhiteSpaceIsSignificant() || aAllowHangingWS;
default: default:
return false; return false;
} }
@ -3049,11 +3050,13 @@ gfxSkipCharsIterator nsTextFrame::EnsureTextRun(
static uint32_t GetEndOfTrimmedText(const nsTextFragment* aFrag, static uint32_t GetEndOfTrimmedText(const nsTextFragment* aFrag,
const nsStyleText* aStyleText, const nsStyleText* aStyleText,
uint32_t aStart, uint32_t aEnd, uint32_t aStart, uint32_t aEnd,
gfxSkipCharsIterator* aIterator) { gfxSkipCharsIterator* aIterator,
bool aAllowHangingWS = false) {
aIterator->SetSkippedOffset(aEnd); aIterator->SetSkippedOffset(aEnd);
while (aIterator->GetSkippedOffset() > aStart) { while (aIterator->GetSkippedOffset() > aStart) {
aIterator->AdvanceSkipped(-1); aIterator->AdvanceSkipped(-1);
if (!IsTrimmableSpace(aFrag, aIterator->GetOriginalOffset(), aStyleText)) if (!IsTrimmableSpace(aFrag, aIterator->GetOriginalOffset(), aStyleText,
aAllowHangingWS))
return aIterator->GetSkippedOffset() + 1; return aIterator->GetSkippedOffset() + 1;
} }
return aStart; return aStart;
@ -8348,6 +8351,7 @@ void nsTextFrame::AddInlineMinISizeForFlow(gfxContext* aRenderingContext,
bool collapseWhitespace = !textStyle->WhiteSpaceIsSignificant(); bool collapseWhitespace = !textStyle->WhiteSpaceIsSignificant();
bool preformatNewlines = textStyle->NewlineIsSignificant(this); bool preformatNewlines = textStyle->NewlineIsSignificant(this);
bool preformatTabs = textStyle->WhiteSpaceIsSignificant(); bool preformatTabs = textStyle->WhiteSpaceIsSignificant();
bool whitespaceCanHang = textStyle->WhiteSpaceCanHangOrVisuallyCollapse();
gfxFloat tabWidth = -1; gfxFloat tabWidth = -1;
uint32_t start = FindStartAfterSkippingWhitespace(&provider, aData, textStyle, uint32_t start = FindStartAfterSkippingWhitespace(&provider, aData, textStyle,
&iter, flowEndInTextRun); &iter, flowEndInTextRun);
@ -8408,9 +8412,9 @@ void nsTextFrame::AddInlineMinISizeForFlow(gfxContext* aRenderingContext,
aData->mCurrentLine = NSCoordSaturatingAdd(aData->mCurrentLine, width); aData->mCurrentLine = NSCoordSaturatingAdd(aData->mCurrentLine, width);
aData->mAtStartOfLine = false; aData->mAtStartOfLine = false;
if (collapseWhitespace) { if (collapseWhitespace || whitespaceCanHang) {
uint32_t trimStart = uint32_t trimStart =
GetEndOfTrimmedText(frag, textStyle, wordStart, i, &iter); GetEndOfTrimmedText(frag, textStyle, wordStart, i, &iter, whitespaceCanHang);
if (trimStart == start) { if (trimStart == start) {
// This is *all* trimmable whitespace, so whatever trailingWhitespace // This is *all* trimmable whitespace, so whatever trailingWhitespace
// we saw previously is still trailing... // we saw previously is still trailing...
@ -9275,9 +9279,7 @@ void nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
bool isBreakSpaces = textStyle->mWhiteSpace == StyleWhiteSpace::BreakSpaces; bool isBreakSpaces = textStyle->mWhiteSpace == StyleWhiteSpace::BreakSpaces;
// allow whitespace to overflow the container // allow whitespace to overflow the container
bool whitespaceCanHang = !isBreakSpaces && bool whitespaceCanHang = textStyle->WhiteSpaceCanHangOrVisuallyCollapse();
textStyle->WhiteSpaceCanWrapStyle() &&
textStyle->WhiteSpaceIsSignificant();
gfxBreakPriority breakPriority = aLineLayout.LastOptionalBreakPriority(); gfxBreakPriority breakPriority = aLineLayout.LastOptionalBreakPriority();
gfxTextRun::SuppressBreak suppressBreak = gfxTextRun::eNoSuppressBreak; gfxTextRun::SuppressBreak suppressBreak = gfxTextRun::eNoSuppressBreak;
bool shouldSuppressLineBreak = ShouldSuppressLineBreak(); bool shouldSuppressLineBreak = ShouldSuppressLineBreak();

Просмотреть файл

@ -3,11 +3,14 @@
<head> <head>
<!-- Reference --> <!-- Reference -->
<style> <style>
div { border:1px solid black; } div { font:16px sans-serif; border:1px solid black; }
.container { float:left; width:20%; border-color:cyan; } .container { float:left; width:20%; border-color:cyan; }
p { width:0; } p { width:0; }
b { font-weight:normal; background-color:yellow; white-space:pre; } b { font-weight:normal; background-color:yellow; white-space:pre; }
.cell { display:table-cell; border:1px solid green; } .cell { display:table-cell; border:1px solid green; }
.hang { display:inline-block; width:0; overflow:visible; }
.hang span { display:inline; background-color:yellow; }
.clip { overflow: hidden; }
</style> </style>
</head> </head>
<body> <body>
@ -17,7 +20,7 @@ b { font-weight:normal; background-color:yellow; white-space:pre; }
Kitty</b></span> Kitty</b></span>
<p><span class="cell"><b>Hello Kitty</b></span> <p><span class="cell"><b>Hello Kitty</b></span>
<p><span class="cell"><b>Hello Kitty</b></span> <p><span class="cell"><b>Hello Kitty</b></span>
<p><span class="cell"><b>Hello <p><span class="cell"><b>Hello
Kitty</b></span> Kitty</b></span>
</div> </div>
@ -28,7 +31,7 @@ Kitty</b></span>
Kitty</b></span> Kitty</b></span>
<p><span class="cell"><b>Hello <p><span class="cell"><b>Hello
Kitty</b></span> Kitty</b></span>
<p><span class="cell"><b>Hello <p><span class="cell"><b>Hello
Kitty</b></span> Kitty</b></span>
</div> </div>
@ -37,7 +40,7 @@ Kitty</b></span>
Kitty</b></span> Kitty</b></span>
<p><span class="cell"><b>Hello Kitty</b></span> <p><span class="cell"><b>Hello Kitty</b></span>
<p><span class="cell"><b>Hello Kitty</b></span> <p><span class="cell"><b>Hello Kitty</b></span>
<p><span class="cell"><b>Hello <p><span class="cell clip"><b>Hello<span class="hang"><span> </span></span>
Kitty</b></span> Kitty</b></span>
</div> </div>
@ -46,18 +49,18 @@ Kitty</b></span>
Kitty</b></span> Kitty</b></span>
<p><span class="cell"><b>Hello Kitty</b></span> <p><span class="cell"><b>Hello Kitty</b></span>
<p><span class="cell"><b>Hello Kitty</b></span> <p><span class="cell"><b>Hello Kitty</b></span>
<p><span class="cell"><b>Hello <p><span class="cell"><b>Hello
Kitty</b></span> Kitty</b></span>
</div> </div>
<div class="container"> <div class="container">
<p><span class="cell"><b>Hello <p><span class="cell"><b>Hello<span class="hang"><span> </span></span>
Kitty</b></span> Kitty</b></span>
<p><span class="cell"><b>Hello <p><span class="cell"><b>Hello
Kitty</b></span> Kitty</b></span>
<p><span class="cell"><b>Hello <p><span class="cell"><b>Hello<span class="hang"><span> </span></span>
Kitty</b></span> Kitty</b></span>
<p><span class="cell"><b>Hello <p><span class="cell"><b>Hello
Kitty</b></span> Kitty</b></span>
</div> </div>

Просмотреть файл

@ -3,7 +3,7 @@
<head> <head>
<!-- Wrapping tests in table-cell to test min-width computation --> <!-- Wrapping tests in table-cell to test min-width computation -->
<style> <style>
div { border:1px solid black; } div { font:16px sans-serif; border:1px solid black; }
.container { float:left; width:20%; border-color:cyan; } .container { float:left; width:20%; border-color:cyan; }
p { width:0; } p { width:0; }
b { font-weight:normal; background-color:yellow; } b { font-weight:normal; background-color:yellow; }

Просмотреть файл

@ -963,6 +963,15 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText {
mWhiteSpace == mozilla::StyleWhiteSpace::PreSpace; mWhiteSpace == mozilla::StyleWhiteSpace::PreSpace;
} }
bool WhiteSpaceCanHangOrVisuallyCollapse() const {
// This was originally expressed in nsTextFrame in terms of:
// mWhiteSpace != StyleWhiteSpace::BreakSpaces &&
// WhiteSpaceCanWrapStyle() &&
// WhiteSpaceIsSignificant()
// which simplifies to:
return mWhiteSpace == mozilla::StyleWhiteSpace::PreWrap;
}
bool NewlineIsSignificantStyle() const { bool NewlineIsSignificantStyle() const {
return mWhiteSpace == mozilla::StyleWhiteSpace::Pre || return mWhiteSpace == mozilla::StyleWhiteSpace::Pre ||
mWhiteSpace == mozilla::StyleWhiteSpace::PreWrap || mWhiteSpace == mozilla::StyleWhiteSpace::PreWrap ||

Просмотреть файл

@ -1,2 +0,0 @@
[white-space-intrinsic-size-003.html]
expected: FAIL

Просмотреть файл

@ -1,2 +0,0 @@
[white-space-intrinsic-size-013.html]
expected: FAIL

Просмотреть файл

@ -1,2 +0,0 @@
[white-space-intrinsic-size-014.html]
expected: FAIL

Просмотреть файл

@ -1,2 +0,0 @@
[white-space-pre-wrap-trailing-spaces-003.html]
expected: FAIL