From fba54c049673c7acb8f487892b07a1704f63274e Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Mon, 6 Apr 2009 22:00:29 +0100 Subject: [PATCH] Bug 486933 - image-rendering does not work on body or root CSS background images. r+sr=roc --- layout/base/nsCSSRendering.cpp | 101 ++++++++++-------- layout/base/nsCSSRendering.h | 7 +- layout/base/nsLayoutUtils.cpp | 7 +- .../image/background-image-zoom-1-ref.html | 21 ++++ .../image/background-image-zoom-1.html | 22 ++++ layout/reftests/image/reftest.list | 3 +- 6 files changed, 110 insertions(+), 51 deletions(-) create mode 100644 layout/reftests/image/background-image-zoom-1-ref.html create mode 100644 layout/reftests/image/background-image-zoom-1.html diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 0d46a9a491b..82559ef554b 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -904,6 +904,59 @@ nsCSSRendering::FindNonTransparentBackground(nsStyleContext* aContext, } + +// Returns true if aFrame is a canvas frame. +// We need to treat the viewport as canvas because, even though +// it does not actually paint a background, we need to get the right +// background style so we correctly detect transparent documents. +PRBool +nsCSSRendering::IsCanvasFrame(nsIFrame *aFrame) +{ + nsIAtom* frameType = aFrame->GetType(); + return frameType == nsGkAtoms::canvasFrame || + frameType == nsGkAtoms::rootFrame || + frameType == nsGkAtoms::pageFrame || + frameType == nsGkAtoms::pageContentFrame || + frameType == nsGkAtoms::viewportFrame; +} + +nsIFrame* +nsCSSRendering::FindRootFrame(nsIFrame *aForFrame) +{ + const nsStyleBackground* result = aForFrame->GetStyleBackground(); + + // Check if we need to do propagation from BODY rather than HTML. + if (result->IsTransparent()) { + nsIContent* content = aForFrame->GetContent(); + // The root element content can't be null. We wouldn't know what + // frame to create for aFrame. + // Use |GetOwnerDoc| so it works during destruction. + nsIDocument* document = content->GetOwnerDoc(); + nsCOMPtr htmlDoc = do_QueryInterface(document); + if (htmlDoc) { + nsIContent* bodyContent = htmlDoc->GetBodyContentExternal(); + // We need to null check the body node (bug 118829) since + // there are cases, thanks to the fix for bug 5569, where we + // will reflow a document with no body. In particular, if a + // SCRIPT element in the head blocks the parser and then has a + // SCRIPT that does "document.location.href = 'foo'", then + // nsParser::Terminate will call |DidBuildModel| methods + // through to the content sink, which will call |StartLayout| + // and thus |InitialReflow| on the pres shell. See bug 119351 + // for the ugly details. + if (bodyContent) { + nsIFrame *bodyFrame = aForFrame->PresContext()->GetPresShell()-> + GetPrimaryFrameFor(bodyContent); + if (bodyFrame) { + return bodyFrame; + } + } + } + } + + return aForFrame; +} + /** * |FindBackground| finds the correct style data to use to paint the * background. It is responsible for handling the following two @@ -933,56 +986,10 @@ nsCSSRendering::FindNonTransparentBackground(nsStyleContext* aContext, * whether the frame is the canvas frame, because PaintBackground must * propagate that frame's background color to the view manager. */ - -// Returns true if aFrame is a canvas frame. -// We need to treat the viewport as canvas because, even though -// it does not actually paint a background, we need to get the right -// background style so we correctly detect transparent documents. -PRBool -nsCSSRendering::IsCanvasFrame(nsIFrame *aFrame) -{ - nsIAtom* frameType = aFrame->GetType(); - return frameType == nsGkAtoms::canvasFrame || - frameType == nsGkAtoms::rootFrame || - frameType == nsGkAtoms::pageFrame || - frameType == nsGkAtoms::pageContentFrame || - frameType == nsGkAtoms::viewportFrame; -} - const nsStyleBackground* nsCSSRendering::FindRootFrameBackground(nsIFrame* aForFrame) { - const nsStyleBackground* result = aForFrame->GetStyleBackground(); - - // Check if we need to do propagation from BODY rather than HTML. - if (result->IsTransparent()) { - nsIContent* content = aForFrame->GetContent(); - // The root element content can't be null. We wouldn't know what - // frame to create for aForFrame. - // Use |GetOwnerDoc| so it works during destruction. - nsIDocument* document = content->GetOwnerDoc(); - nsCOMPtr htmlDoc = do_QueryInterface(document); - if (htmlDoc) { - nsIContent* bodyContent = htmlDoc->GetBodyContentExternal(); - // We need to null check the body node (bug 118829) since - // there are cases, thanks to the fix for bug 5569, where we - // will reflow a document with no body. In particular, if a - // SCRIPT element in the head blocks the parser and then has a - // SCRIPT that does "document.location.href = 'foo'", then - // nsParser::Terminate will call |DidBuildModel| methods - // through to the content sink, which will call |StartLayout| - // and thus |InitialReflow| on the pres shell. See bug 119351 - // for the ugly details. - if (bodyContent) { - nsIFrame *bodyFrame = aForFrame->PresContext()->GetPresShell()-> - GetPrimaryFrameFor(bodyContent); - if (bodyFrame) - result = bodyFrame->GetStyleBackground(); - } - } - } - - return result; + return FindRootFrame(aForFrame)->GetStyleBackground(); } inline void diff --git a/layout/base/nsCSSRendering.h b/layout/base/nsCSSRendering.h index 998c4473840..38310eb0c07 100644 --- a/layout/base/nsCSSRendering.h +++ b/layout/base/nsCSSRendering.h @@ -119,7 +119,12 @@ struct nsCSSRendering { nscolor aColor); /** - * @return PR_TRUE if |aForFrame| is a canvas frame, in the CSS sense. + * Gets the root frame for the frame + */ + static nsIFrame* FindRootFrame(nsIFrame* aForFrame); + + /** + * @return PR_TRUE if |aFrame| is a canvas frame, in the CSS sense. */ static PRBool IsCanvasFrame(nsIFrame* aFrame); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 0fbef073e60..5e9f8715886 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -2669,10 +2669,13 @@ nsLayoutUtils::GetClosestLayer(nsIFrame* aFrame) } gfxPattern::GraphicsFilter -nsLayoutUtils::GetGraphicsFilterForFrame(nsIFrame* aFrame) +nsLayoutUtils::GetGraphicsFilterForFrame(nsIFrame* aForFrame) { #ifdef MOZ_SVG - switch (aFrame->GetStyleSVG()->mImageRendering) { + nsIFrame *frame = nsCSSRendering::IsCanvasFrame(aForFrame) ? + nsCSSRendering::FindRootFrame(aForFrame) : aForFrame; + + switch (frame->GetStyleSVG()->mImageRendering) { case NS_STYLE_IMAGE_RENDERING_OPTIMIZESPEED: return gfxPattern::FILTER_FAST; case NS_STYLE_IMAGE_RENDERING_OPTIMIZEQUALITY: diff --git a/layout/reftests/image/background-image-zoom-1-ref.html b/layout/reftests/image/background-image-zoom-1-ref.html new file mode 100644 index 00000000000..944262e17df --- /dev/null +++ b/layout/reftests/image/background-image-zoom-1-ref.html @@ -0,0 +1,21 @@ + + + + +reference background-image-rendering: -moz-crisp-edges + + + + + diff --git a/layout/reftests/image/background-image-zoom-1.html b/layout/reftests/image/background-image-zoom-1.html new file mode 100644 index 00000000000..4b93bfb029c --- /dev/null +++ b/layout/reftests/image/background-image-zoom-1.html @@ -0,0 +1,22 @@ + + + + +test background-image-rendering: -moz-crisp-edges + + + + + diff --git a/layout/reftests/image/reftest.list b/layout/reftests/image/reftest.list index 55fa5dde510..ae5111e5d7d 100644 --- a/layout/reftests/image/reftest.list +++ b/layout/reftests/image/reftest.list @@ -1 +1,2 @@ -== image-zoom-1.html image-zoom-1-ref.html \ No newline at end of file +== background-image-zoom-1.html background-image-zoom-1-ref.html +== image-zoom-1.html image-zoom-1-ref.html