From 94d689d854ed4a2cfbe7130e8b58b8f19963cfb7 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 26 Nov 2008 11:08:19 +1300 Subject: [PATCH 1/5] Bug 444375. Take TEXT_HAS_TRAILING_BREAK into account when computing min-width for text which has entirely collapsed away. r=smontagu --- layout/generic/nsTextFrameThebes.cpp | 26 +++++++++++++------------- layout/reftests/bugs/444375-1-ref.html | 15 +++++++++++++++ layout/reftests/bugs/444375-1.html | 16 ++++++++++++++++ layout/reftests/bugs/reftest.list | 1 + 4 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 layout/reftests/bugs/444375-1-ref.html create mode 100644 layout/reftests/bugs/444375-1.html diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 70376693067b..34b75d5af21b 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -5279,8 +5279,6 @@ nsTextFrame::AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext, gfxFloat tabWidth = -1; PRUint32 start = FindStartAfterSkippingWhitespace(&provider, aData, textStyle, &iter, flowEndInTextRun); - if (start >= flowEndInTextRun) - return; // XXX Should we consider hyphenation here? for (PRUint32 i = start, wordStart = start; i <= flowEndInTextRun; ++i) { @@ -5342,11 +5340,13 @@ nsTextFrame::AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext, } } - // Check if we have collapsible whitespace at the end - aData->skipWhitespace = - IsTrimmableSpace(provider.GetFragment(), - iter.ConvertSkippedToOriginal(flowEndInTextRun - 1), - textStyle); + if (start < flowEndInTextRun) { + // Check if we have collapsible whitespace at the end + aData->skipWhitespace = + IsTrimmableSpace(provider.GetFragment(), + iter.ConvertSkippedToOriginal(flowEndInTextRun - 1), + textStyle); + } } // XXX Need to do something here to avoid incremental reflow bugs due to @@ -5398,8 +5398,6 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsIRenderingContext *aRenderingContext, gfxFloat tabWidth = -1; PRUint32 start = FindStartAfterSkippingWhitespace(&provider, aData, textStyle, &iter, flowEndInTextRun); - if (start >= flowEndInTextRun) - return; // XXX Should we consider hyphenation here? // If newlines and tabs aren't preformatted, nothing to do inside @@ -5458,10 +5456,12 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsIRenderingContext *aRenderingContext, } // Check if we have collapsible whitespace at the end - aData->skipWhitespace = - IsTrimmableSpace(provider.GetFragment(), - iter.ConvertSkippedToOriginal(flowEndInTextRun - 1), - textStyle); + if (start < flowEndInTextRun) { + aData->skipWhitespace = + IsTrimmableSpace(provider.GetFragment(), + iter.ConvertSkippedToOriginal(flowEndInTextRun - 1), + textStyle); + } } // XXX Need to do something here to avoid incremental reflow bugs due to diff --git a/layout/reftests/bugs/444375-1-ref.html b/layout/reftests/bugs/444375-1-ref.html new file mode 100644 index 000000000000..4f326e4e70fc --- /dev/null +++ b/layout/reftests/bugs/444375-1-ref.html @@ -0,0 +1,15 @@ + + + + +
+
+ diff --git a/layout/reftests/bugs/444375-1.html b/layout/reftests/bugs/444375-1.html new file mode 100644 index 000000000000..119ffeea3971 --- /dev/null +++ b/layout/reftests/bugs/444375-1.html @@ -0,0 +1,16 @@ + + + + + +
+ + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 24333849270f..a0543f2a7ae9 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -915,6 +915,7 @@ random == 429849-1.html 429849-1-ref.html # bug 432288 fails == 441259-2.html 441259-2-ref.html # bug 441400 == 442542-1.html 442542-1-ref.html == 444015-1.html 444015-1-ref.html +== 444375-1.html 444375-1-ref.html == 444928-1.html 444928-1-ref.html == 444928-2.html 444928-2-ref.html != 444928-3.html 444928-3-notref.html From 7a907f23ca85030e4e3e053c146e3317098903af Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 26 Nov 2008 11:09:37 +1300 Subject: [PATCH 2/5] Bug 454959. When a document is in a floating view, floating-ness doesn't propagate across view manager boundaries. So use the display-root view as the place to invalidate from. r+sr=bzbarsky --- view/src/nsViewManager.cpp | 51 +++++--------------------------------- view/src/nsViewManager.h | 5 ---- 2 files changed, 6 insertions(+), 50 deletions(-) diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index 00aa3da8043d..da6bbc19682a 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -894,28 +894,12 @@ NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect, PRU return NS_OK; } - // if this is a floating view, it isn't covered by any widgets other than - // its children. In that case we walk up to its parent widget and use - // that as the root to update from. This also means we update areas that - // may be outside the parent view(s), which is necessary for floats. - if (view->GetFloating()) { - nsView* widgetParent = view; - - while (!widgetParent->HasWidget()) { - widgetParent->ConvertToParentCoords(&damagedRect.x, &damagedRect.y); - widgetParent = widgetParent->GetParent(); - } - - UpdateWidgetArea(widgetParent, nsRegion(damagedRect), nsnull); - } else { - // Propagate the update to the root widget of the root view manager, since - // iframes, for example, can overlap each other and be translucent. So we - // have to possibly invalidate our rect in each of the widgets we have - // lying about. - damagedRect.MoveBy(ComputeViewOffset(view)); - - UpdateWidgetArea(RootViewManager()->GetRootView(), nsRegion(damagedRect), nsnull); - } + nsView* displayRoot = GetDisplayRootFor(view); + // Propagate the update to the displayRoot, since iframes, for example, + // can overlap each other and be translucent. So we have to possibly + // invalidate our rect in each of the widgets we have lying about. + damagedRect.MoveBy(view->GetOffsetTo(displayRoot)); + UpdateWidgetArea(displayRoot, nsRegion(damagedRect), nsnull); RootViewManager()->IncrementUpdateCount(); @@ -2029,29 +2013,6 @@ NS_IMETHODIMP nsViewManager::ForceUpdate() return NS_OK; } -nsPoint nsViewManager::ComputeViewOffset(const nsView *aView) -{ - NS_PRECONDITION(aView, "Null view in ComputeViewOffset?"); - - nsPoint origin(0, 0); -#ifdef DEBUG - const nsView* rootView; - const nsView* origView = aView; -#endif - - while (aView) { -#ifdef DEBUG - rootView = aView; -#endif - origin += aView->GetPosition(); - aView = aView->GetParent(); - } - NS_ASSERTION(rootView == - origView->GetViewManager()->RootViewManager()->GetRootView(), - "Unexpected root view"); - return origin; -} - void nsViewManager::ViewToWidget(nsView *aView, nsView* aWidgetView, nsRect &aRect) const { while (aView != aWidgetView) { diff --git a/view/src/nsViewManager.h b/view/src/nsViewManager.h index 87d1671eeda8..09c6a7771d2b 100644 --- a/view/src/nsViewManager.h +++ b/view/src/nsViewManager.h @@ -416,11 +416,6 @@ public: // NOT in nsIViewManager, so private to the view module nsresult CreateRegion(nsIRegion* *result); - // return the sum of all view offsets from aView right up to the - // root of this view hierarchy (the view with no parent, which might - // not be in this view manager). - static nsPoint ComputeViewOffset(const nsView *aView); - PRBool IsRefreshEnabled() { return RootViewManager()->mRefreshEnabled; } nsIViewObserver* GetViewObserver() { return mObserver; } From b2b28bfe30a7ba4456ed00f50994c535fbe06e52 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 26 Nov 2008 11:12:06 +1300 Subject: [PATCH 3/5] Bug 454751. Use a fresh nsFrameConstructorState when we construct new frames in ReconstructDocElementHierarchyInternal, so internal state pointing to deleted frames is flushed out. r+sr=bzbarsky --- layout/base/crashtests/454751-1.xul | 20 +++++++++++++++++ layout/base/crashtests/crashtests.list | 1 + layout/base/nsCSSFrameConstructor.cpp | 31 ++++++++++++++++---------- 3 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 layout/base/crashtests/454751-1.xul diff --git a/layout/base/crashtests/454751-1.xul b/layout/base/crashtests/454751-1.xul new file mode 100644 index 000000000000..83ec7859953a --- /dev/null +++ b/layout/base/crashtests/454751-1.xul @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index 6e434124701c..cb87d683cb8e 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -125,6 +125,7 @@ load 429088-2.html load 432752-1.svg load 433450-1.html load 444925-1.xul +load 454751-1.xul load 455063-1.html load 455063-2.html load 455063-3.html diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 1b1d47d783ef..19e48f8378fb 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -7683,20 +7683,27 @@ nsCSSFrameConstructor::ReconstructDocElementHierarchyInternal() return rv; } } - - mInitialContainingBlock = nsnull; - mRootElementStyleFrame = nsnull; + } + } + + if (rootContent && NS_SUCCEEDED(rv)) { + mInitialContainingBlock = nsnull; + mRootElementStyleFrame = nsnull; - // Create the new document element hierarchy - nsIFrame* newChild; - rv = ConstructDocElementFrame(state, rootContent, - mDocElementContainingBlock, &newChild); + // We don't reuse the old frame constructor state because, + // for example, its mPopupItems may be stale + nsFrameConstructorState state(mPresShell, mFixedContainingBlock, + nsnull, nsnull, mTempFrameTreeState); - // newChild could be null even if |rv| is success, thanks to XBL. - if (NS_SUCCEEDED(rv) && newChild) { - rv = state.mFrameManager->InsertFrames(mDocElementContainingBlock, - nsnull, nsnull, newChild); - } + // Create the new document element hierarchy + nsIFrame* newChild; + rv = ConstructDocElementFrame(state, rootContent, + mDocElementContainingBlock, &newChild); + + // newChild could be null even if |rv| is success, thanks to XBL. + if (NS_SUCCEEDED(rv) && newChild) { + rv = state.mFrameManager->InsertFrames(mDocElementContainingBlock, + nsnull, nsnull, newChild); } } } From 57bec6006eae4ed6fb18926e54bd1941ea2a5fba Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 26 Nov 2008 11:15:41 +1300 Subject: [PATCH 4/5] Bug 460012. When recreating frames for a generated content node, reframe the nearest non-generated-content ancestor. r+sr=bzbarsky --- layout/base/nsCSSFrameConstructor.cpp | 7 +++++++ layout/base/nsLayoutUtils.cpp | 14 ++++++++++++++ layout/base/nsLayoutUtils.h | 6 ++++++ layout/generic/nsTextFrameThebes.cpp | 11 ++--------- layout/reftests/bugs/460012-1-ref.html | 6 ++++++ layout/reftests/bugs/460012-1.html | 16 ++++++++++++++++ layout/reftests/bugs/reftest.list | 1 + 7 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 layout/reftests/bugs/460012-1-ref.html create mode 100644 layout/reftests/bugs/460012-1.html diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 19e48f8378fb..408a139b6984 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -11092,6 +11092,13 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent) } } + if (frame) { + nsIFrame* nonGeneratedAncestor = nsLayoutUtils::GetNonGeneratedAncestor(frame); + if (nonGeneratedAncestor->GetContent() != aContent) { + return RecreateFramesForContent(nonGeneratedAncestor->GetContent()); + } + } + nsresult rv = NS_OK; if (frame && MaybeRecreateContainerForIBSplitterFrame(frame, &rv)) { diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 943a3f98fef6..4f8cac30524a 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1552,6 +1552,20 @@ nsLayoutUtils::FindNearestBlockAncestor(nsIFrame* aFrame) return nsnull; } +nsIFrame* +nsLayoutUtils::GetNonGeneratedAncestor(nsIFrame* aFrame) +{ + if (!(aFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT)) + return aFrame; + + nsFrameManager* frameManager = aFrame->PresContext()->FrameManager(); + nsIFrame* f = aFrame; + do { + f = GetParentOrPlaceholderFor(frameManager, f); + } while (f->GetStateBits() & NS_FRAME_GENERATED_CONTENT); + return f; +} + nsIFrame* nsLayoutUtils::GetParentOrPlaceholderFor(nsFrameManager* aFrameManager, nsIFrame* aFrame) diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index a776d6fea4fd..d653b3312d8b 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -622,6 +622,12 @@ public: */ static nsBlockFrame* FindNearestBlockAncestor(nsIFrame* aFrame); + /** + * Find the nearest ancestor that's not for generated content. Will return + * aFrame if aFrame is not for generated content. + */ + static nsIFrame* GetNonGeneratedAncestor(nsIFrame* aFrame); + /** * Cast aFrame to an nsBlockFrame* or return null if it's not * an nsBlockFrame. diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 34b75d5af21b..9233e62d5822 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -2995,13 +2995,6 @@ nsTextPaintStyle::InitCommonColors() mInitCommonColors = PR_TRUE; } -static nsIFrame* GetNonGeneratedAncestor(nsIFrame* f) { - while (f->GetStateBits() & NS_FRAME_GENERATED_CONTENT) { - f = nsLayoutUtils::GetParentOrPlaceholderFor(f->PresContext()->FrameManager(), f); - } - return f; -} - static nsIContent* FindElementAncestor(nsINode* aNode) { @@ -3029,7 +3022,7 @@ nsTextPaintStyle::InitSelectionColors() mInitSelectionColors = PR_TRUE; - nsIFrame* nonGeneratedAncestor = GetNonGeneratedAncestor(mFrame); + nsIFrame* nonGeneratedAncestor = nsLayoutUtils::GetNonGeneratedAncestor(mFrame); nsIContent* selectionContent = FindElementAncestor(nonGeneratedAncestor->GetContent()); if (selectionContent && @@ -4419,7 +4412,7 @@ nsTextFrame::PaintText(nsIRenderingContext* aRenderingContext, nsPoint aPt, } // Fork off to the (slower) paint-with-selection path if necessary. - if (GetNonGeneratedAncestor(this)->GetStateBits() & NS_FRAME_SELECTED_CONTENT) { + if (nsLayoutUtils::GetNonGeneratedAncestor(this)->GetStateBits() & NS_FRAME_SELECTED_CONTENT) { if (PaintTextWithSelection(ctx, framePt, textBaselinePt, dirtyRect, provider, textPaintStyle)) return; diff --git a/layout/reftests/bugs/460012-1-ref.html b/layout/reftests/bugs/460012-1-ref.html new file mode 100644 index 000000000000..59f913c00078 --- /dev/null +++ b/layout/reftests/bugs/460012-1-ref.html @@ -0,0 +1,6 @@ + + + +
Y
+ + diff --git a/layout/reftests/bugs/460012-1.html b/layout/reftests/bugs/460012-1.html new file mode 100644 index 000000000000..92d9e2c71faa --- /dev/null +++ b/layout/reftests/bugs/460012-1.html @@ -0,0 +1,16 @@ + + + + + + +
+ + + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index a0543f2a7ae9..b0979e03786e 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -964,6 +964,7 @@ fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 456147.xul 456147-ref.html # bug 456147 == 458487-4c.html 458487-4-ref.html == 458487-5a.html 458487-5-ref.html == 458487-5b.html 458487-5-ref.html +== 460012-1.html 460012-1-ref.html == 461266-1.html 461266-1-ref.html fails == 461512-1.html 461512-1-ref.html # Bug 461512 == 462844-1.html 462844-ref.html From 8d93852f4a8f6b058675773c9158c2c622546e3d Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 26 Nov 2008 11:19:34 +1300 Subject: [PATCH 5/5] Bug 463952. Expand destArea according to CSS background-repeat *before* intersecting with bgClipArea, instead of after. r+sr=dbaron --- layout/base/nsCSSRendering.cpp | 4 ++-- layout/reftests/bugs/463952-1-ref.html | 6 ++++++ layout/reftests/bugs/463952-1.html | 11 +++++++++++ layout/reftests/bugs/reftest.list | 1 + 4 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 layout/reftests/bugs/463952-1-ref.html create mode 100644 layout/reftests/bugs/463952-1.html diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 321f0571abe6..5a7ecca678e9 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -1518,8 +1518,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext, } nsRect destArea(imageTopLeft + aBorderArea.TopLeft(), imageSize); - nsRect fillArea; - fillArea.IntersectRect(destArea, bgClipArea); + nsRect fillArea = destArea; if (repeat & NS_STYLE_BG_REPEAT_X) { fillArea.x = bgClipArea.x; fillArea.width = bgClipArea.width; @@ -1528,6 +1527,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext, fillArea.y = bgClipArea.y; fillArea.height = bgClipArea.height; } + fillArea.IntersectRect(fillArea, bgClipArea); nsLayoutUtils::DrawImage(&aRenderingContext, image, destArea, fillArea, anchor + aBorderArea.TopLeft(), dirtyRect); diff --git a/layout/reftests/bugs/463952-1-ref.html b/layout/reftests/bugs/463952-1-ref.html new file mode 100644 index 000000000000..f90bb9bfc2d5 --- /dev/null +++ b/layout/reftests/bugs/463952-1-ref.html @@ -0,0 +1,6 @@ + + + +
+ + diff --git a/layout/reftests/bugs/463952-1.html b/layout/reftests/bugs/463952-1.html new file mode 100644 index 000000000000..5132674ad929 --- /dev/null +++ b/layout/reftests/bugs/463952-1.html @@ -0,0 +1,11 @@ + + + + + + +
+ +
+ + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index b0979e03786e..04640504e5df 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -973,4 +973,5 @@ fails == 461512-1.html 461512-1-ref.html # Bug 461512 == 462844-4.html 462844-ref.html == 463204-1.html 463204-1-ref.html == 463217-1.xul 463217-1-ref.xul +== 463952-1.html 463952-1-ref.html == 464811-1.html 464811-1-ref.html