From d97d015ba976d96b1965d064f39be689075f9934 Mon Sep 17 00:00:00 2001 From: "roc+@cs.cmu.edu" Date: Mon, 11 Feb 2008 17:42:14 -0800 Subject: [PATCH] Bug 400813. Lines with font-size:0 content should not be treated as empty. r+sr=dbaron --- layout/generic/nsLineLayout.cpp | 33 +++++++++++++------ layout/generic/nsLineLayout.h | 1 + layout/generic/nsTextFrame.h | 12 +++++++ layout/generic/nsTextFrameThebes.cpp | 5 +-- layout/reftests/bugs/398144-1-ref.html | 3 +- layout/reftests/bugs/reftest.list | 2 +- .../line-breaking/non-breakable-1-ref.html | 1 + .../line-breaking/non-breakable-1.html | 1 + 8 files changed, 44 insertions(+), 14 deletions(-) diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index f68a00e7ac2..2a91c855602 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -395,6 +395,7 @@ nsLineLayout::NewPerSpanData(PerSpanData** aResult) psd->mLastFrame = nsnull; psd->mContainsFloat = PR_FALSE; psd->mZeroEffectiveSpanBox = PR_FALSE; + psd->mHasNonemptyContent = PR_FALSE; #ifdef DEBUG mSpansAllocated++; @@ -862,11 +863,14 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, pfd->mJustificationNumSpaces = mTextJustificationNumSpaces; pfd->mJustificationNumLetters = mTextJustificationNumLetters; - // XXX See if the frame is a placeholderFrame and if it is process - // the float. + // See if the frame is a placeholderFrame and if it is process + // the float. At the same time, check if the frame has any non-collapsed-away + // content. PRBool placedFloat = PR_FALSE; + PRBool hasNoncollapsedContent = PR_TRUE; if (frameType) { if (nsGkAtoms::placeholderFrame == frameType) { + hasNoncollapsedContent = PR_FALSE; pfd->SetFlag(PFD_SKIPWHENTRIMMINGWHITESPACE, PR_TRUE); nsIFrame* outOfFlowFrame = nsLayoutUtils::GetFloatFromPlaceholder(aFrame); if (outOfFlowFrame) { @@ -887,11 +891,12 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, else if (nsGkAtoms::textFrame == frameType) { // Note non-empty text-frames for inline frame compatibility hackery pfd->SetFlag(PFD_ISTEXTFRAME, PR_TRUE); - // XXX An empty text frame at the end of the line seems not - // to have zero width. - if (metrics.width) { + nsTextFrame* textFrame = static_cast(pfd->mFrame); + if (!textFrame->HasNoncollapsedCharacters()) { + hasNoncollapsedContent = PR_FALSE; + } else { pfd->SetFlag(PFD_ISNONEMPTYTEXTFRAME, PR_TRUE); - nsIContent* content = pfd->mFrame->GetContent(); + nsIContent* content = textFrame->GetContent(); const nsTextFragment* frag = content->GetText(); if (frag) { @@ -916,13 +921,21 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, } } } - else if (nsGkAtoms::letterFrame==frameType) { - pfd->SetFlag(PFD_ISLETTERFRAME, PR_TRUE); - } else if (nsGkAtoms::brFrame == frameType) { pfd->SetFlag(PFD_SKIPWHENTRIMMINGWHITESPACE, PR_TRUE); + } else { + if (nsGkAtoms::letterFrame==frameType) { + pfd->SetFlag(PFD_ISLETTERFRAME, PR_TRUE); + } + if (pfd->mSpan && + !pfd->mSpan->mHasNonemptyContent && pfd->mFrame->IsSelfEmpty()) { + hasNoncollapsedContent = PR_FALSE; + } } } + if (hasNoncollapsedContent) { + psd->mHasNonemptyContent = PR_TRUE; + } mSpaceManager->Translate(-tx, -ty); @@ -2059,7 +2072,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) } } if (applyMinLH) { - if ((psd->mX != psd->mLeftEdge) || preMode || foundLI) { + if (psd->mHasNonemptyContent || preMode || foundLI) { #ifdef NOISY_VERTICAL_ALIGN printf(" [span]==> adjusting min/maxY: currentValues: %d,%d", minY, maxY); #endif diff --git a/layout/generic/nsLineLayout.h b/layout/generic/nsLineLayout.h index 6b6855116a3..3b0352fdb80 100644 --- a/layout/generic/nsLineLayout.h +++ b/layout/generic/nsLineLayout.h @@ -468,6 +468,7 @@ protected: PRPackedBool mChangedFrameDirection; PRPackedBool mZeroEffectiveSpanBox; PRPackedBool mContainsFloat; + PRPackedBool mHasNonemptyContent; nscoord mLeftEdge; nscoord mX; diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index 419043807e6..ef5df3ffa9d 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -58,6 +58,10 @@ class nsTextPaintStyle; class PropertyProvider; +// This state bit is set on frames that have some non-collapsed characters after +// reflow +#define TEXT_HAS_NONCOLLAPSED_CHARACTERS 0x02000000 + class nsTextFrame : public nsFrame { public: friend class nsContinuingTextFrame; @@ -189,6 +193,14 @@ public: */ PRBool IsAtEndOfLine() const; + /** + * Call this only after reflow the frame. Returns true if non-collapsed + * characters are present. + */ + PRBool HasNoncollapsedCharacters() const { + return (GetStateBits() & TEXT_HAS_NONCOLLAPSED_CHARACTERS) != 0; + } + #ifdef ACCESSIBILITY NS_IMETHOD GetAccessible(nsIAccessible** aAccessible); #endif diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index cd9f50559d8..bfcca226ef7 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -145,7 +145,7 @@ #define TEXT_REFLOW_FLAGS \ (TEXT_FIRST_LETTER|TEXT_START_OF_LINE|TEXT_END_OF_LINE|TEXT_HYPHEN_BREAK| \ - TEXT_TRIMMED_TRAILING_WHITESPACE) + TEXT_TRIMMED_TRAILING_WHITESPACE|TEXT_HAS_NONCOLLAPSED_CHARACTERS) // Cache bits for IsEmpty(). // Set this bit if the textframe is known to be only collapsible whitespace. @@ -5513,6 +5513,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext, // frame to accumulate with trimmable width from this frame.) if (transformedCharsFit > 0) { lineLayout.SetTrimmableWidth(NSToCoordFloor(trimmableWidth)); + AddStateBits(TEXT_HAS_NONCOLLAPSED_CHARACTERS); } if (charsFit > 0 && charsFit == length && HasSoftHyphenBefore(frag, mTextRun, offset, end)) { @@ -5860,7 +5861,7 @@ nsIAtom* nsTextFrame::GetType() const { return nsGkAtoms::textFrame; -} +} /* virtual */ PRBool nsTextFrame::IsEmpty() diff --git a/layout/reftests/bugs/398144-1-ref.html b/layout/reftests/bugs/398144-1-ref.html index 41bd423a25c..b9e09bedd34 100644 --- a/layout/reftests/bugs/398144-1-ref.html +++ b/layout/reftests/bugs/398144-1-ref.html @@ -2,7 +2,8 @@
-
+
blank line
+ diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 9f006dc805e..dc376965949 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -613,7 +613,7 @@ skip-if(MOZ_WIDGET_TOOLKIT!="windows") == 391045.html 391045-ref.html # windows- == 400171-2b.html 400171-2-ref.html == 400171-2c.html 400171-2-ref.html == 400421-1.html 400421-1-ref.html -# == 400813-1.html 400813-1-ref.html +== 400813-1.html 400813-1-ref.html == 400826-1.html 400826-1-ref.html == 401946-1.xul about:blank == 402338-1.html 402338-1-ref.html diff --git a/layout/reftests/line-breaking/non-breakable-1-ref.html b/layout/reftests/line-breaking/non-breakable-1-ref.html index bfaf1528dc8..b8a1fb87b8a 100755 --- a/layout/reftests/line-breaking/non-breakable-1-ref.html +++ b/layout/reftests/line-breaking/non-breakable-1-ref.html @@ -1,3 +1,4 @@ + diff --git a/layout/reftests/line-breaking/non-breakable-1.html b/layout/reftests/line-breaking/non-breakable-1.html index f57b86a0152..3ee9222c687 100755 --- a/layout/reftests/line-breaking/non-breakable-1.html +++ b/layout/reftests/line-breaking/non-breakable-1.html @@ -1,3 +1,4 @@ +