Bug 485275 - trunk displays svg transformed foreign object html differently then 1.9. r+sr=roc
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -977,19 +977,17 @@ nsCSSRendering::FindRootFrame(nsIFrame*
* + we paint the correct background on the |nsCanvasFrame|,
* |nsRootBoxFrame|, or |nsPageFrame|,
* + we don't paint the background on the root element, and
* + we don't paint the background on the BODY element in *some* cases,
* and for SGML-based HTML documents only.
*
* |FindBackground| returns true if a background should be painted, and
* the resulting style context to use for the background information
- * will be filled in to |aBackground|. It fills in a boolean indicating
- * whether the frame is the canvas frame, because PaintBackground must
- * propagate that frame's background color to the view manager.
+ * will be filled in to |aBackground|.
*/
const nsStyleBackground*
nsCSSRendering::FindRootFrameBackground(nsIFrame* aForFrame)
{
return FindRootFrame(aForFrame)->GetStyleBackground();
}
inline void
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -166,16 +166,18 @@ nsDisplayListBuilder::EnterPresShell(nsI
const nsRect& aDirtyRect) {
PresShellState* state = mPresShellStates.AppendElement();
if (!state)
return;
state->mPresShell = aReferenceFrame->PresContext()->PresShell();
state->mCaretFrame = nsnull;
state->mFirstFrameMarkedForDisplay = mFramesMarkedForDisplay.Length();
+ state->mPresShell->UpdateCanvasBackground();
+
if (!mBuildCaret)
return;
nsRefPtr<nsCaret> caret;
state->mPresShell->GetCaret(getter_AddRefs(caret));
state->mCaretFrame = caret->GetCaretFrame();
if (state->mCaretFrame) {
@@ -187,18 +189,17 @@ nsDisplayListBuilder::EnterPresShell(nsI
mFramesMarkedForDisplay.AppendElement(state->mCaretFrame);
MarkFrameForDisplay(state->mCaretFrame, nsnull);
}
}
}
void
nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame,
- const nsRect& aDirtyRect)
-{
+ const nsRect& aDirtyRect) {
if (CurrentPresShellState()->mPresShell != aReferenceFrame->PresContext()->PresShell()) {
// Must have not allocated a state for this presshell, presumably due
// to OOM.
return;
}
// Unmark and pop off the frames marked for display in this pres shell.
PRUint32 firstFrameForShell = CurrentPresShellState()->mFirstFrameMarkedForDisplay;
@@ -249,17 +250,17 @@ nsDisplayItem::OptimizeVisibility(nsDisp
NS_ASSERTION(f, "GetUnderlyingFrame() must return non-null for leaf items");
PRBool isMoving = aBuilder->IsMovingFrame(f);
if (IsOpaque(aBuilder)) {
nsRect opaqueArea = bounds;
if (isMoving) {
// The display list should include items for both the before and after
// states (see nsLayoutUtils::ComputeRepaintRegionForCopy. So the
- // only area we want to cover is the the area that was opaque in the
+ // only area we want to cover is the area that was opaque in the
// before state and in the after state.
opaqueArea.IntersectRect(bounds - aBuilder->GetMoveDelta(), bounds);
}
aVisibleRegion->SimpleSubtract(opaqueArea);
}
return PR_TRUE;
}
@@ -486,16 +487,40 @@ void nsDisplayList::SortByContentOrder(n
}
void nsDisplayList::Sort(nsDisplayListBuilder* aBuilder,
SortLEQ aCmp, void* aClosure) {
ExplodeAnonymousChildLists(aBuilder);
::Sort(this, Count(), aCmp, aClosure);
}
+void nsDisplaySolidColor::Paint(nsDisplayListBuilder* aBuilder,
+ nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
+ nsRect dirty;
+ dirty.IntersectRect(GetBounds(aBuilder), aDirtyRect);
+ aCtx->SetColor(mColor);
+ aCtx->FillRect(dirty);
+}
+
+// Even though we aren't supposed to, we need to override this because
+// we have no frame.
+PRBool
+nsDisplaySolidColor::OptimizeVisibility(nsDisplayListBuilder* aBuilder,
+ nsRegion* aVisibleRegion) {
+ // Do what nsDisplayItem::OptimizeVisibility would do but without a frame.
+ if (!aVisibleRegion->Intersects(mBounds))
+ return PR_FALSE;
+
+ if (IsOpaque(aBuilder)) {
+ aVisibleRegion->SimpleSubtract(mBounds);
+ }
+
+ return PR_TRUE;
+}
+
PRBool
nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder) {
// theme background overrides any other background
if (mIsThemed)
return PR_FALSE;
const nsStyleBackground* bg;
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -1003,16 +1003,55 @@ public:
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion);
NS_DISPLAY_DECL_NAME("Border")
};
/**
+ * A simple display item that just renders a solid color across a frame or
+ * specified bounds. Used in cases where we can't draw the frame tree but
+ * we want to draw something to avoid an ugly flash of white when
+ * navigating between pages. Also used as a bottom item to ensure that
+ * something is painted everywhere.
+ */
+class nsDisplaySolidColor : public nsDisplayItem {
+public:
+ nsDisplaySolidColor(const nsRect& aBounds, nscolor aColor)
+ : nsDisplayItem(nsnull), mBounds(aBounds), mColor(aColor) {
+ MOZ_COUNT_CTOR(nsDisplaySolidColor);
+ }
+#ifdef NS_BUILD_REFCNT_LOGGING
+ virtual ~nsDisplaySolidColor() {
+ MOZ_COUNT_DTOR(nsDisplaySolidColor);
+ }
+#endif
+
+ virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) { return mBounds; }
+
+ virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder) {
+ return (NS_GET_A(mColor) == 255);
+ }
+
+ virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder) { return PR_TRUE; }
+
+ virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
+ const nsRect& aDirtyRect);
+
+ virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder,
+ nsRegion* aVisibleRegion);
+
+ NS_DISPLAY_DECL_NAME("SolidColor")
+private:
+ nsRect mBounds;
+ nscolor mColor;
+};
+
+/**
* The standard display item to paint the CSS background of a frame.
*/
class nsDisplayBackground : public nsDisplayItem {
public:
nsDisplayBackground(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
mIsThemed = mFrame->IsThemed();
MOZ_COUNT_CTOR(nsDisplayBackground);
}
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -96,20 +96,20 @@ class nsWeakFrame;
class nsIScrollableFrame;
class gfxASurface;
class gfxContext;
class nsPIDOMEventTarget;
typedef short SelectionType;
typedef PRUint32 nsFrameState;
-// fa7f090d-b19a-4ef8-9552-82992a3b4a83
+// fa1bf801-9fb6-4d19-8d33-698e9961fc10
#define NS_IPRESSHELL_IID \
-{ 0xfa7f090d, 0xb19a, 0x4ef8, \
- { 0x95, 0x52, 0x82, 0x99, 0x2a, 0x3b, 0x4a, 0x83 } }
+{ 0xfa1bf801, 0x9fb6, 0x4d19, \
+ { 0x8d, 0x33, 0x69, 0x8e, 0x99, 0x61, 0xfc, 0x10 } }
// Constants for ScrollContentIntoView() function
#define NS_PRESSHELL_SCROLL_TOP 0
#define NS_PRESSHELL_SCROLL_BOTTOM 100
#define NS_PRESSHELL_SCROLL_LEFT 0
#define NS_PRESSHELL_SCROLL_RIGHT 100
#define NS_PRESSHELL_SCROLL_CENTER 50
#define NS_PRESSHELL_SCROLL_ANYWHERE -1
@@ -788,16 +788,21 @@ public:
* This color is composited on top of the user's default background
* color whenever we need to provide an "ultimate" background color.
* See PresShell::Paint, PresShell::PaintDefaultBackground, and
* nsDocShell::SetupNewViewer; bug 476557 and other bugs mentioned there.
*/
void SetCanvasBackground(nscolor aColor) { mCanvasBackgroundColor = aColor; }
nscolor GetCanvasBackground() { return mCanvasBackgroundColor; }
+ /* Use the current frame tree (if it exists) to update the background
+ * color of the most recent canvas.
+ */
+ virtual void UpdateCanvasBackground() = 0;
+
protected:
// IMPORTANT: The ownership implicit in the following member variables
// has been explicitly checked. If you add any members to this class,
// please make the ownership explicit (pinkerton, scc).
// these are the same Document and PresContext owned by the DocViewer.
// we must share ownership.
nsIDocument* mDocument; // [STRONG]
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -936,46 +936,16 @@ nsLayoutUtils::GetFrameForPoint(nsIFrame
nsDisplayItem::HitTestState hitTestState;
nsIFrame* result = list.HitTest(&builder, aPt, &hitTestState);
list.DeleteAll();
return result;
}
/**
- * A simple display item that just renders a solid color across the entire
- * visible area.
- */
-class nsDisplaySolidColor : public nsDisplayItem {
-public:
- nsDisplaySolidColor(nsIFrame* aFrame, nscolor aColor)
- : nsDisplayItem(aFrame), mColor(aColor) {
- MOZ_COUNT_CTOR(nsDisplaySolidColor);
- }
-#ifdef NS_BUILD_REFCNT_LOGGING
- virtual ~nsDisplaySolidColor() {
- MOZ_COUNT_DTOR(nsDisplaySolidColor);
- }
-#endif
-
- virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
- const nsRect& aDirtyRect);
- NS_DISPLAY_DECL_NAME("SolidColor")
-private:
- nscolor mColor;
-};
-
-void nsDisplaySolidColor::Paint(nsDisplayListBuilder* aBuilder,
- nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
-{
- aCtx->SetColor(mColor);
- aCtx->FillRect(aDirtyRect);
-}
-
-/**
* Remove all leaf display items that are not for descendants of
* aBuilder->GetReferenceFrame() from aList, and move all nsDisplayClip
* wrappers to their correct locations.
* @param aExtraPage the page we constructed aList for
* @param aY the Y-coordinate where aPage would be positioned relative
* to the main page (aBuilder->GetReferenceFrame()), considering only
* the content and ignoring page margins and dead space
* @param aList the list that is modified in-place
@@ -1102,17 +1072,19 @@ nsLayoutUtils::PaintFrame(nsIRenderingCo
NS_ENSURE_SUCCESS(rv, rv);
if (NS_GET_A(aBackground) > 0) {
// Fill the visible area with a background color. In the common case,
// the visible area is entirely covered by the background of the root
// document (at least!) so this will be removed by the optimizer. In some
// cases we might not have a root frame, so this will prevent garbage
// from being drawn.
- rv = list.AppendNewToBottom(new (&builder) nsDisplaySolidColor(aFrame, aBackground));
+ rv = list.AppendNewToBottom(new (&builder) nsDisplaySolidColor(
+ nsRect(builder.ToReferenceFrame(aFrame), aFrame->GetSize()),
+ aBackground));
NS_ENSURE_SUCCESS(rv, rv);
}
#ifdef DEBUG
if (gDumpPaintList) {
fprintf(stderr, "Painting --- before optimization (dirty %d,%d,%d,%d):\n",
dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
nsIFrameDebug::PrintDisplayList(&builder, list);
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -1125,16 +1125,18 @@ public:
#endif
#ifdef PR_LOGGING
static PRLogModuleInfo* gLog;
#endif
NS_IMETHOD DisableNonTestMouseEvents(PRBool aDisable);
+ virtual void UpdateCanvasBackground();
+
protected:
virtual ~PresShell();
void HandlePostedReflowCallbacks();
void CancelPostedReflowCallbacks();
void UnsuppressAndInvalidate();
@@ -5514,35 +5516,40 @@ PresShell::RenderSelection(nsISelection*
return nsnull;
}
}
return PaintRangePaintInfo(&rangeItems, aSelection, nsnull, area, aPoint,
aScreenRect);
}
+void PresShell::UpdateCanvasBackground()
+{
+ // If we have a frame tree and it has style information that
+ // specifies the background color of the canvas, update our local
+ // cache of that color.
+ nsIFrame* rootFrame = FrameConstructor()->GetRootElementStyleFrame();
+ if (rootFrame) {
+ const nsStyleBackground* bgStyle =
+ nsCSSRendering::FindRootFrameBackground(rootFrame);
+ mCanvasBackgroundColor = bgStyle->mBackgroundColor;
+ }
+}
+
NS_IMETHODIMP
PresShell::Paint(nsIView* aView,
nsIRenderingContext* aRenderingContext,
const nsRegion& aDirtyRegion)
{
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Paint);
NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell");
NS_ASSERTION(aView, "null view");
- // If we have a frame tree and it has style information that
- // specifies the background color of the canvas, update our local
- // cache of that color.
- nsIFrame* rootFrame = FrameConstructor()->GetRootElementStyleFrame();
- if (rootFrame) {
- const nsStyleBackground* bgStyle =
- nsCSSRendering::FindRootFrameBackground(rootFrame);
- mCanvasBackgroundColor = bgStyle->mBackgroundColor;
- }
+ UpdateCanvasBackground();
// Compute the backstop color for the view.
nscolor bgcolor;
nsIWidget* widget = aView->GetNearestWidget(nsnull);
if (widget && widget->GetTransparencyMode() != eTransparencyOpaque) {
// Within a transparent widget, so the backstop color must be
// totally transparent.
bgcolor = NS_RGBA(0,0,0,0);
--- a/layout/generic/nsFrameFrame.cpp
+++ b/layout/generic/nsFrameFrame.cpp
@@ -316,20 +316,51 @@ nsSubDocumentFrame::BuildDisplayList(nsD
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
if (!mInnerView)
return NS_OK;
nsIView* subdocView = mInnerView->GetFirstChild();
if (!subdocView)
return NS_OK;
+
+ // Get the PresShell so we can check if painting is suppressed
+ // on the subdocument. We use this roundabout way in case we
+ // don't have a frame tree.
+ if (!mFrameLoader)
+ return NS_OK;
+ nsCOMPtr<nsIDocShell> docShell;
+ mFrameLoader->GetDocShell(getter_AddRefs(docShell));
+ if (!docShell)
+ return NS_OK;
+ nsCOMPtr<nsIPresShell> presShell;
+ docShell->GetPresShell(getter_AddRefs(presShell));
+ if (!presShell)
+ return NS_OK;
+
+ PRBool suppressed = PR_TRUE;
+ presShell->IsPaintingSuppressed(&suppressed);
+
nsIFrame* f = static_cast<nsIFrame*>(subdocView->GetClientData());
- if (!f)
- return NS_OK;
-
+
+ if (!f || suppressed) {
+ // If we don't have a frame or painting of the PresShell is suppressed,
+ // try to draw the default background color. (Bug 485275)
+
+ // Get the bounds of subdocView relative to the reference frame.
+ nsRect shellBounds = subdocView->GetBounds() +
+ mInnerView->GetPosition() +
+ GetOffsetTo(aBuilder->ReferenceFrame());
+ rv = aLists.Content()->AppendNewToBottom(
+ new (aBuilder) nsDisplaySolidColor(
+ shellBounds,
+ presShell->GetCanvasBackground()));
+ return rv;
+ }
+
nsRect dirty = aDirtyRect - f->GetOffsetTo(this);
aBuilder->EnterPresShell(f, dirty);
// Clip children to the child root frame's rectangle
nsDisplayList childItems;
rv = f->BuildDisplayListForStackingContext(aBuilder, dirty, &childItems);
if (NS_SUCCEEDED(rv)) {