Skip to content

Commit 422c481

Browse files
committed
Bug 1791226 - Don't paint line-clamped lines. r=layout-reviewers,dshin
This matches the proposal in w3c/csswg-drafts#10816, and creates much better behavior. Differential Revision: https://phabricator.services.mozilla.com/D157578 UltraBlame original commit: c6ce92301ca11292a5dd25f07a80243592c94e5a
1 parent 84d035b commit 422c481

File tree

6 files changed

+83
-46
lines changed

6 files changed

+83
-46
lines changed

layout/generic/TextOverflow.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -810,15 +810,15 @@ bool TextOverflow::HasClippedTextOverflow(nsIFrame* aBlockFrame) {
810810

811811
bool TextOverflow::HasBlockEllipsis(nsIFrame* aBlockFrame) {
812812
nsBlockFrame* f = do_QueryFrame(aBlockFrame);
813-
return f && f->HasAnyStateBits(NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS);
813+
return f && f->HasLineClampEllipsis();
814814
}
815815

816816
static bool BlockCanHaveLineClampEllipsis(nsBlockFrame* aBlockFrame,
817817
bool aBeforeReflow) {
818818
if (aBeforeReflow) {
819819
return aBlockFrame->IsInLineClampContext();
820820
}
821-
return aBlockFrame->HasAnyStateBits(NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS);
821+
return aBlockFrame->HasLineClampEllipsis();
822822
}
823823

824824

layout/generic/nsBlockFrame.cpp

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,12 +1176,17 @@ static LogicalSize CalculateContainingBlockSizeForAbsolutes(
11761176

11771177

11781178
static const nsBlockFrame* GetAsLineClampDescendant(const nsIFrame* aFrame) {
1179-
if (const nsBlockFrame* block = do_QueryFrame(aFrame)) {
1180-
if (!block->HasAnyStateBits(NS_BLOCK_BFC)) {
1181-
return block;
1182-
}
1179+
const nsBlockFrame* block = do_QueryFrame(aFrame);
1180+
if (!block) {
1181+
return nullptr;
11831182
}
1184-
return nullptr;
1183+
if (block->HasAllStateBits(NS_FRAME_OUT_OF_FLOW)) {
1184+
return nullptr;
1185+
}
1186+
if (block->HasAllStateBits(NS_BLOCK_BFC)) {
1187+
return nullptr;
1188+
}
1189+
return block;
11851190
}
11861191

11871192
static nsBlockFrame* GetAsLineClampDescendant(nsIFrame* aFrame) {
@@ -1343,28 +1348,30 @@ class MOZ_RAII LineClampLineIterator {
13431348
};
13441349

13451350
static bool ClearLineClampEllipsis(nsBlockFrame* aFrame) {
1346-
if (!aFrame->HasAnyStateBits(NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS)) {
1351+
if (aFrame->HasLineClampEllipsis()) {
1352+
MOZ_ASSERT(!aFrame->HasLineClampEllipsisDescendant());
1353+
for (auto& line : aFrame->Lines()) {
1354+
if (line.HasLineClampEllipsis()) {
1355+
line.ClearHasLineClampEllipsis();
1356+
aFrame->SetHasLineClampEllipsis(false);
1357+
return true;
1358+
}
1359+
}
1360+
}
1361+
1362+
if (aFrame->HasLineClampEllipsisDescendant()) {
1363+
aFrame->SetHasLineClampEllipsisDescendant(false);
13471364
for (nsIFrame* f : aFrame->PrincipalChildList()) {
13481365
if (nsBlockFrame* child = GetAsLineClampDescendant(f)) {
13491366
if (ClearLineClampEllipsis(child)) {
13501367
return true;
13511368
}
13521369
}
13531370
}
1354-
return false;
1355-
}
1356-
1357-
aFrame->RemoveStateBits(NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS);
1358-
1359-
for (auto& line : aFrame->Lines()) {
1360-
if (line.HasLineClampEllipsis()) {
1361-
line.ClearHasLineClampEllipsis();
1362-
return true;
1363-
}
13641371
}
13651372

13661373

1367-
return true;
1374+
return false;
13681375
}
13691376

13701377
void nsBlockFrame::ClearLineClampEllipsis() { ::ClearLineClampEllipsis(this); }
@@ -2019,9 +2026,7 @@ nsReflowStatus nsBlockFrame::TrialReflow(nsPresContext* aPresContext,
20192026
}
20202027

20212028

2022-
if (aReflowInput.mStyleDisplay->mWebkitLineClamp) {
2023-
ClearLineClampEllipsis();
2024-
}
2029+
ClearLineClampEllipsis();
20252030

20262031
CheckFloats(state);
20272032

@@ -2052,7 +2057,7 @@ static nsLineBox* FindLineClampTarget(nsBlockFrame*& aFrame,
20522057
nsBlockFrame* aStopAtFrame,
20532058
StyleLineClamp aLineNumber) {
20542059
MOZ_ASSERT(aLineNumber > 0);
2055-
MOZ_ASSERT(!aFrame->HasAnyStateBits(NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS),
2060+
MOZ_ASSERT(!aFrame->HasLineClampEllipsis(),
20562061
"Should have been removed earlier in nsBlockReflow::Reflow");
20572062

20582063
nsLineBox* target = nullptr;
@@ -2114,11 +2119,16 @@ nscoord nsBlockFrame::ApplyLineClamp(nscoord aContentBlockEndEdge) {
21142119

21152120

21162121
line->SetHasLineClampEllipsis();
2117-
target->AddStateBits(NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS);
2122+
target->SetHasLineClampEllipsis(true);
21182123

21192124

21202125
nscoord edge = line->BEnd();
21212126
for (nsIFrame* f = target; f; f = f->GetParent()) {
2127+
MOZ_ASSERT(f->IsBlockFrameOrSubclass(),
2128+
"GetAsLineClampDescendant guarantees this");
2129+
if (f != target) {
2130+
static_cast<nsBlockFrame*>(f)->SetHasLineClampEllipsisDescendant(true);
2131+
}
21222132
if (f == this) {
21232133
break;
21242134
}
@@ -7637,7 +7647,7 @@ static void DisplayLine(nsDisplayListBuilder* aBuilder,
76377647
const bool aLineInLine, const nsDisplayListSet& aLists,
76387648
nsBlockFrame* aFrame, TextOverflow* aTextOverflow,
76397649
uint32_t aLineNumberForTextOverflow, int32_t aDepth,
7640-
int32_t& aDrawnLines) {
7650+
int32_t& aDrawnLines, bool& aFoundLineClamp) {
76417651
#ifdef DEBUG
76427652
if (nsBlockFrame::gLamePaintMetrics) {
76437653
aDrawnLines++;
@@ -7670,6 +7680,14 @@ static void DisplayLine(nsDisplayListBuilder* aBuilder,
76707680
kid = kid->GetNextSibling();
76717681
}
76727682

7683+
if (aFrame->HasLineClampEllipsisDescendant() && !aLineInLine) {
7684+
if (nsBlockFrame* f = GetAsLineClampDescendant(aLine->mFirstChild)) {
7685+
if (f->HasLineClampEllipsis() || f->HasLineClampEllipsisDescendant()) {
7686+
aFoundLineClamp = true;
7687+
}
7688+
}
7689+
}
7690+
76737691
if (aTextOverflow && aLineInLine) {
76747692
aTextOverflow->ProcessLine(collection, aLine.get(),
76757693
aLineNumberForTextOverflow);
@@ -7774,12 +7792,14 @@ void nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
77747792

77757793

77767794
nsLineBox* cursor =
7777-
(hasDescendantPlaceHolders || textOverflow.isSome() || backplateColor)
7795+
(hasDescendantPlaceHolders || textOverflow.isSome() || backplateColor ||
7796+
HasLineClampEllipsis() || HasLineClampEllipsisDescendant())
77787797
? nullptr
77797798
: GetFirstLineContaining(aBuilder->GetDirtyRect().y);
77807799
LineIterator line_end = LinesEnd();
77817800

77827801
TextOverflow* textOverflowPtr = textOverflow.ptrOr(nullptr);
7802+
bool foundClamp = false;
77837803

77847804
if (cursor) {
77857805
for (LineIterator line = mLines.begin(cursor); line != line_end; ++line) {
@@ -7794,7 +7814,8 @@ void nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
77947814

77957815
if (ShouldDescendIntoLine(lineArea)) {
77967816
DisplayLine(aBuilder, line, line->IsInline(), aLists, this, nullptr,
7797-
0, depth, drawnLines);
7817+
0, depth, drawnLines, foundClamp);
7818+
MOZ_ASSERT(!foundClamp);
77987819
}
77997820
}
78007821
}
@@ -7825,7 +7846,7 @@ void nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
78257846

78267847
if ((lineInLine && textOverflowPtr) || ShouldDescendIntoLine(lineArea)) {
78277848
DisplayLine(aBuilder, line, lineInLine, aLists, this, textOverflowPtr,
7828-
lineCount, depth, drawnLines);
7849+
lineCount, depth, drawnLines, foundClamp);
78297850
}
78307851

78317852
if (!lineInLine && !curBackplateArea.IsEmpty()) {
@@ -7856,6 +7877,10 @@ void nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
78567877
}
78577878
}
78587879
}
7880+
foundClamp = foundClamp || line->HasLineClampEllipsis();
7881+
if (foundClamp) {
7882+
break;
7883+
}
78597884
lineCount++;
78607885
}
78617886

layout/generic/nsBlockFrame.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,28 @@ class nsBlockFrame : public nsContainerFrame {
681681

682682

683683
bool MaybeHasFloats() const;
684+
685+
686+
687+
688+
689+
690+
bool HasLineClampEllipsis() const {
691+
return HasAnyStateBits(NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS);
692+
}
693+
694+
695+
696+
697+
bool HasLineClampEllipsisDescendant() const {
698+
return HasAnyStateBits(NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS_DESCENDANT);
699+
}
700+
void SetHasLineClampEllipsis(bool aValue) {
701+
AddOrRemoveStateBits(NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS, aValue);
702+
}
703+
void SetHasLineClampEllipsisDescendant(bool aValue) {
704+
AddOrRemoveStateBits(NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS_DESCENDANT, aValue);
705+
}
684706

685707
protected:
686708
nsBlockFrame* GetLineClampRoot() const;

layout/generic/nsFrameStateBits.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -563,33 +563,29 @@ FRAME_STATE_BIT(Block, 28, NS_BLOCK_HAS_MARKER)
563563
FRAME_STATE_BIT(Block, 29, NS_BLOCK_NEEDS_BIDI_RESOLUTION)
564564

565565

566+
FRAME_STATE_BIT(Block, 30, NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS)
567+
FRAME_STATE_BIT(Block, 31, NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS_DESCENDANT)
566568

567569

568570

569571

572+
FRAME_STATE_BIT(Block, 60, NS_BLOCK_LOOK_FOR_DIRTY_FRAMES)
570573

571-
FRAME_STATE_BIT(Block, 60, NS_BLOCK_HAS_LINE_CLAMP_ELLIPSIS)
572574

573575

574576

575577

576-
FRAME_STATE_BIT(Block, 61, NS_BLOCK_LOOK_FOR_DIRTY_FRAMES)
577578

578579

579580

580581

582+
FRAME_STATE_BIT(Block, 61, NS_BLOCK_INTRINSICS_INFLATED)
581583

582584

583585

584586

585587

586-
FRAME_STATE_BIT(Block, 62, NS_BLOCK_INTRINSICS_INFLATED)
587-
588-
589-
590-
591-
592-
FRAME_STATE_BIT(Block, 63, NS_BLOCK_HAS_FIRST_LETTER_CHILD)
588+
FRAME_STATE_BIT(Block, 62, NS_BLOCK_HAS_FIRST_LETTER_CHILD)
593589

594590

595591

testing/web-platform/tests/css/css-overflow/line-clamp/reference/webkit-line-clamp-040-ref.html

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,4 @@
1111
</style>
1212
<div class="clamp">Line 1
1313
Line 2…
14-
Line 3
15-
Line 4
16-
Line 5</div>
14+
</div>

testing/web-platform/tests/css/css-overflow/line-clamp/webkit-line-clamp-050.html

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,11 @@
1616
border: medium solid green;
1717
padding: 15px;
1818
}
19-
span {
20-
/* TODO: Remove once we don't paint clamped lines */
21-
color: transparent;
22-
}
2319
</style>
2420
<div class="clamp">
2521
Line1
26-
<div>Line2<br><span>Line3</span></div>
27-
<span>Line4</span>
22+
<div>Line2<br>Line3</div>
23+
Line4
2824
<div>Line5<br>Line6</div>
2925
Line7
3026
</div>

0 commit comments

Comments
 (0)