diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 9555564c4fed..ff98238d21a7 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -87,81 +87,6 @@ using namespace mozilla; -/** - * This is a small wrapper class to encapsulate image drawing that can draw an - * nsStyleImage image, which may internally be a real image, a sub image, or a - * CSS gradient. - * - * @note Always call the member functions in the order of PrepareImage(), - * ComputeSize(), and Draw(). - */ -class ImageRenderer { -public: - enum { - FLAG_SYNC_DECODE_IMAGES = 0x01 - }; - ImageRenderer(nsIFrame* aForFrame, const nsStyleImage* aImage, PRUint32 aFlags); - ~ImageRenderer(); - /** - * Populates member variables to get ready for rendering. - * @return true iff the image is ready, and there is at least a pixel to - * draw. - */ - bool PrepareImage(); - /** - * @return the image size in appunits when rendered, after accounting for the - * background positioning area, background-size, and the image's intrinsic - * dimensions (if any). - */ - nsSize ComputeSize(const nsStyleBackground::Size& aLayerSize, - const nsSize& aBgPositioningArea); - /** - * Draws the image to the target rendering context. - * @see nsLayoutUtils::DrawImage() for other parameters - */ - void Draw(nsPresContext* aPresContext, - nsRenderingContext& aRenderingContext, - const nsRect& aDest, - const nsRect& aFill, - const nsPoint& aAnchor, - const nsRect& aDirty); - -private: - /* - * Compute the "unscaled" dimensions of the image in aUnscaled{Width,Height} - * and aRatio. Whether the image has a height and width are indicated by - * aHaveWidth and aHaveHeight. If the image doesn't have a ratio, aRatio will - * be (0, 0). - */ - void ComputeUnscaledDimensions(const nsSize& aBgPositioningArea, - nscoord& aUnscaledWidth, bool& aHaveWidth, - nscoord& aUnscaledHeight, bool& aHaveHeight, - nsSize& aRatio); - - /* - * Using the previously-computed unscaled width and height (if each are - * valid, as indicated by aHaveWidth/aHaveHeight), compute the size at which - * the image should actually render. - */ - nsSize - ComputeDrawnSize(const nsStyleBackground::Size& aLayerSize, - const nsSize& aBgPositioningArea, - nscoord aUnscaledWidth, bool aHaveWidth, - nscoord aUnscaledHeight, bool aHaveHeight, - const nsSize& aIntrinsicRatio); - - nsIFrame* mForFrame; - const nsStyleImage* mImage; - nsStyleImageType mType; - nsCOMPtr mImageContainer; - nsRefPtr mGradientData; - nsIFrame* mPaintServerFrame; - nsLayoutUtils::SurfaceFromElementResult mImageElementSurface; - bool mIsReady; - nsSize mSize; // unscaled size of the image, in app units - PRUint32 mFlags; -}; - // To avoid storing this data on nsInlineFrame (bloat) and to avoid // recalculating this for each frame in a continuation (perf), hold // a cache of various coordinate information that we need in order @@ -1692,12 +1617,12 @@ DrawBackgroundColor(BackgroundClipState& aClipState, gfxContext *aCtx, aCtx->Restore(); } -static nscolor -DetermineBackgroundColorInternal(nsPresContext* aPresContext, - nsStyleContext* aStyleContext, - nsIFrame* aFrame, - bool& aDrawBackgroundImage, - bool& aDrawBackgroundColor) +nscolor +nsCSSRendering::DetermineBackgroundColor(nsPresContext* aPresContext, + nsStyleContext* aStyleContext, + nsIFrame* aFrame, + bool& aDrawBackgroundImage, + bool& aDrawBackgroundColor) { aDrawBackgroundImage = true; aDrawBackgroundColor = true; @@ -1729,20 +1654,6 @@ DetermineBackgroundColorInternal(nsPresContext* aPresContext, return bgColor; } -nscolor -nsCSSRendering::DetermineBackgroundColor(nsPresContext* aPresContext, - nsStyleContext* aStyleContext, - nsIFrame* aFrame) -{ - bool drawBackgroundImage; - bool drawBackgroundColor; - return DetermineBackgroundColorInternal(aPresContext, - aStyleContext, - aFrame, - drawBackgroundImage, - drawBackgroundColor); -} - static gfxFloat ConvertGradientValueToPixels(const nsStyleCoord& aCoord, gfxFloat aFillLength, @@ -2226,51 +2137,6 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext, } } -/** - * A struct representing all the information needed to paint a background - * image to some target, taking into account all CSS background-* properties. - * See PrepareBackgroundLayer. - */ -struct BackgroundLayerState { - /** - * @param aFlags some combination of nsCSSRendering::PAINTBG_* flags - */ - BackgroundLayerState(nsIFrame* aForFrame, const nsStyleImage* aImage, PRUint32 aFlags) - : mImageRenderer(aForFrame, aImage, aFlags) {} - - /** - * The ImageRenderer that will be used to draw the background. - */ - ImageRenderer mImageRenderer; - /** - * A rectangle that one copy of the image tile is mapped onto. Same - * coordinate system as aBorderArea/aBGClipRect passed into - * PrepareBackgroundLayer. - */ - nsRect mDestArea; - /** - * The actual rectangle that should be filled with (complete or partial) - * image tiles. Same coordinate system as aBorderArea/aBGClipRect passed into - * PrepareBackgroundLayer. - */ - nsRect mFillArea; - /** - * The anchor point that should be snapped to a pixel corner. Same - * coordinate system as aBorderArea/aBGClipRect passed into - * PrepareBackgroundLayer. - */ - nsPoint mAnchor; -}; - -static BackgroundLayerState -PrepareBackgroundLayer(nsPresContext* aPresContext, - nsIFrame* aForFrame, - PRUint32 aFlags, - const nsRect& aBorderArea, - const nsRect& aBGClipRect, - const nsStyleBackground& aBackground, - const nsStyleBackground::Layer& aLayer); - void nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, @@ -2318,11 +2184,11 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext, bool drawBackgroundImage; bool drawBackgroundColor; - nscolor bgColor = DetermineBackgroundColorInternal(aPresContext, - aBackgroundSC, - aForFrame, - drawBackgroundImage, - drawBackgroundColor); + nscolor bgColor = DetermineBackgroundColor(aPresContext, + aBackgroundSC, + aForFrame, + drawBackgroundImage, + drawBackgroundColor); // At this point, drawBackgroundImage and drawBackgroundColor are // true if and only if we are actually supposed to paint an image or @@ -2452,7 +2318,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext, } } if (!clipState.mDirtyRectGfx.IsEmpty()) { - BackgroundLayerState state = PrepareBackgroundLayer(aPresContext, aForFrame, + nsBackgroundLayerState state = PrepareBackgroundLayer(aPresContext, aForFrame, aFlags, aBorderArea, clipState.mBGClipArea, *bg, layer); if (!state.mFillArea.IsEmpty()) { state.mImageRenderer.Draw(aPresContext, aRenderingContext, @@ -2476,14 +2342,14 @@ IsTransformed(nsIFrame* aForFrame, nsIFrame* aTopFrame) return false; } -static BackgroundLayerState -PrepareBackgroundLayer(nsPresContext* aPresContext, - nsIFrame* aForFrame, - PRUint32 aFlags, - const nsRect& aBorderArea, - const nsRect& aBGClipRect, - const nsStyleBackground& aBackground, - const nsStyleBackground::Layer& aLayer) +nsBackgroundLayerState +nsCSSRendering::PrepareBackgroundLayer(nsPresContext* aPresContext, + nsIFrame* aForFrame, + PRUint32 aFlags, + const nsRect& aBorderArea, + const nsRect& aBGClipRect, + const nsStyleBackground& aBackground, + const nsStyleBackground::Layer& aLayer) { /* * The background properties we need to keep in mind when drawing background @@ -2542,10 +2408,10 @@ PrepareBackgroundLayer(nsPresContext* aPresContext, PRUint32 irFlags = 0; if (aFlags & nsCSSRendering::PAINTBG_SYNC_DECODE_IMAGES) { - irFlags |= ImageRenderer::FLAG_SYNC_DECODE_IMAGES; + irFlags |= nsImageRenderer::FLAG_SYNC_DECODE_IMAGES; } - BackgroundLayerState state(aForFrame, &aLayer.mImage, irFlags); + nsBackgroundLayerState state(aForFrame, &aLayer.mImage, irFlags); if (!state.mImageRenderer.PrepareImage()) { // There's no image or it's not ready to be painted. return state; @@ -2695,7 +2561,7 @@ nsCSSRendering::GetBackgroundLayerRect(nsPresContext* aPresContext, const nsStyleBackground& aBackground, const nsStyleBackground::Layer& aLayer) { - BackgroundLayerState state = + nsBackgroundLayerState state = PrepareBackgroundLayer(aPresContext, aForFrame, 0, aBorderArea, aBorderArea, aBackground, aLayer); return state.mFillArea; @@ -3790,9 +3656,9 @@ nsCSSRendering::GetTextDecorationRectInternal(const gfxPoint& aPt, // ------------------ // ImageRenderer // ------------------ -ImageRenderer::ImageRenderer(nsIFrame* aForFrame, - const nsStyleImage* aImage, - PRUint32 aFlags) +nsImageRenderer::nsImageRenderer(nsIFrame* aForFrame, + const nsStyleImage* aImage, + PRUint32 aFlags) : mForFrame(aForFrame) , mImage(aImage) , mType(aImage->GetType()) @@ -3805,12 +3671,12 @@ ImageRenderer::ImageRenderer(nsIFrame* aForFrame, { } -ImageRenderer::~ImageRenderer() +nsImageRenderer::~nsImageRenderer() { } bool -ImageRenderer::PrepareImage() +nsImageRenderer::PrepareImage() { if (mImage->IsEmpty() || !mImage->IsComplete()) { // Make sure the image is actually decoding @@ -3930,10 +3796,10 @@ ComputeContainCoverSizeFromRatio(const nsSize& aBgPositioningArea, } void -ImageRenderer::ComputeUnscaledDimensions(const nsSize& aBgPositioningArea, - nscoord& aUnscaledWidth, bool& aHaveWidth, - nscoord& aUnscaledHeight, bool& aHaveHeight, - nsSize& aRatio) +nsImageRenderer::ComputeUnscaledDimensions(const nsSize& aBgPositioningArea, + nscoord& aUnscaledWidth, bool& aHaveWidth, + nscoord& aUnscaledHeight, bool& aHaveHeight, + nsSize& aRatio) { NS_ASSERTION(mIsReady, "Ensure PrepareImage() has returned true " "before calling me"); @@ -4003,11 +3869,11 @@ ImageRenderer::ComputeUnscaledDimensions(const nsSize& aBgPositioningArea, } nsSize -ImageRenderer::ComputeDrawnSize(const nsStyleBackground::Size& aLayerSize, - const nsSize& aBgPositioningArea, - nscoord aUnscaledWidth, bool aHaveWidth, - nscoord aUnscaledHeight, bool aHaveHeight, - const nsSize& aIntrinsicRatio) +nsImageRenderer::ComputeDrawnSize(const nsStyleBackground::Size& aLayerSize, + const nsSize& aBgPositioningArea, + nscoord aUnscaledWidth, bool aHaveWidth, + nscoord aUnscaledHeight, bool aHaveHeight, + const nsSize& aIntrinsicRatio) { NS_ABORT_IF_FALSE(aIntrinsicRatio.width >= 0, "image ratio with nonsense width"); @@ -4171,8 +4037,8 @@ ImageRenderer::ComputeDrawnSize(const nsStyleBackground::Size& aLayerSize, * width will be 4px, while in the second case the returned width will be 8px. */ nsSize -ImageRenderer::ComputeSize(const nsStyleBackground::Size& aLayerSize, - const nsSize& aBgPositioningArea) +nsImageRenderer::ComputeSize(const nsStyleBackground::Size& aLayerSize, + const nsSize& aBgPositioningArea) { bool haveWidth, haveHeight; nsSize ratio; @@ -4191,12 +4057,12 @@ ImageRenderer::ComputeSize(const nsStyleBackground::Size& aLayerSize, } void -ImageRenderer::Draw(nsPresContext* aPresContext, - nsRenderingContext& aRenderingContext, - const nsRect& aDest, - const nsRect& aFill, - const nsPoint& aAnchor, - const nsRect& aDirty) +nsImageRenderer::Draw(nsPresContext* aPresContext, + nsRenderingContext& aRenderingContext, + const nsRect& aDest, + const nsRect& aFill, + const nsPoint& aAnchor, + const nsRect& aDirty) { if (!mIsReady) { NS_NOTREACHED("Ensure PrepareImage() has returned true before calling me"); @@ -4248,6 +4114,31 @@ ImageRenderer::Draw(nsPresContext* aPresContext, } } +bool +nsImageRenderer::IsRasterImage() +{ + if (mType != eStyleImageType_Image) + return false; + nsCOMPtr img; + nsresult rv = mImage->GetImageData()->GetImage(getter_AddRefs(img)); + if (NS_FAILED(rv) || !img) + return false; + return img->GetType() == imgIContainer::TYPE_RASTER; +} + +already_AddRefed +nsImageRenderer::GetContainer() +{ + nsCOMPtr img; + nsresult rv = mImage->GetImageData()->GetImage(getter_AddRefs(img)); + if (NS_FAILED(rv) || !img) + return nsnull; + nsRefPtr container; + rv = img->GetImageContainer(getter_AddRefs(container)); + NS_ENSURE_SUCCESS(rv, nsnull); + return container.forget(); +} + #define MAX_BLUR_RADIUS 300 #define MAX_SPREAD_RADIUS 50 diff --git a/layout/base/nsCSSRendering.h b/layout/base/nsCSSRendering.h index 150ecd5b1582..672ac63fdbf1 100644 --- a/layout/base/nsCSSRendering.h +++ b/layout/base/nsCSSRendering.h @@ -44,12 +44,129 @@ #include "gfxBlur.h" #include "gfxContext.h" #include "gfxImageSurface.h" +#include "nsLayoutUtils.h" struct nsPoint; class nsStyleContext; class nsPresContext; class nsRenderingContext; +/** + * This is a small wrapper class to encapsulate image drawing that can draw an + * nsStyleImage image, which may internally be a real image, a sub image, or a + * CSS gradient. + * + * @note Always call the member functions in the order of PrepareImage(), + * ComputeSize(), and Draw(). + */ +class nsImageRenderer { +public: + typedef mozilla::layers::ImageContainer ImageContainer; + + enum { + FLAG_SYNC_DECODE_IMAGES = 0x01 + }; + nsImageRenderer(nsIFrame* aForFrame, const nsStyleImage* aImage, PRUint32 aFlags); + ~nsImageRenderer(); + /** + * Populates member variables to get ready for rendering. + * @return true iff the image is ready, and there is at least a pixel to + * draw. + */ + bool PrepareImage(); + /** + * @return the image size in appunits when rendered, after accounting for the + * background positioning area, background-size, and the image's intrinsic + * dimensions (if any). + */ + nsSize ComputeSize(const nsStyleBackground::Size& aLayerSize, + const nsSize& aBgPositioningArea); + /** + * Draws the image to the target rendering context. + * @see nsLayoutUtils::DrawImage() for other parameters + */ + void Draw(nsPresContext* aPresContext, + nsRenderingContext& aRenderingContext, + const nsRect& aDest, + const nsRect& aFill, + const nsPoint& aAnchor, + const nsRect& aDirty); + + + bool IsRasterImage(); + already_AddRefed GetContainer(); +private: + /* + * Compute the "unscaled" dimensions of the image in aUnscaled{Width,Height} + * and aRatio. Whether the image has a height and width are indicated by + * aHaveWidth and aHaveHeight. If the image doesn't have a ratio, aRatio will + * be (0, 0). + */ + void ComputeUnscaledDimensions(const nsSize& aBgPositioningArea, + nscoord& aUnscaledWidth, bool& aHaveWidth, + nscoord& aUnscaledHeight, bool& aHaveHeight, + nsSize& aRatio); + + /* + * Using the previously-computed unscaled width and height (if each are + * valid, as indicated by aHaveWidth/aHaveHeight), compute the size at which + * the image should actually render. + */ + nsSize + ComputeDrawnSize(const nsStyleBackground::Size& aLayerSize, + const nsSize& aBgPositioningArea, + nscoord aUnscaledWidth, bool aHaveWidth, + nscoord aUnscaledHeight, bool aHaveHeight, + const nsSize& aIntrinsicRatio); + + nsIFrame* mForFrame; + const nsStyleImage* mImage; + nsStyleImageType mType; + nsCOMPtr mImageContainer; + nsRefPtr mGradientData; + nsIFrame* mPaintServerFrame; + nsLayoutUtils::SurfaceFromElementResult mImageElementSurface; + bool mIsReady; + nsSize mSize; // unscaled size of the image, in app units + PRUint32 mFlags; +}; + +/** + * A struct representing all the information needed to paint a background + * image to some target, taking into account all CSS background-* properties. + * See PrepareBackgroundLayer. + */ +struct nsBackgroundLayerState { + /** + * @param aFlags some combination of nsCSSRendering::PAINTBG_* flags + */ + nsBackgroundLayerState(nsIFrame* aForFrame, const nsStyleImage* aImage, PRUint32 aFlags) + : mImageRenderer(aForFrame, aImage, aFlags) {} + + /** + * The nsImageRenderer that will be used to draw the background. + */ + nsImageRenderer mImageRenderer; + /** + * A rectangle that one copy of the image tile is mapped onto. Same + * coordinate system as aBorderArea/aBGClipRect passed into + * PrepareBackgroundLayer. + */ + nsRect mDestArea; + /** + * The actual rectangle that should be filled with (complete or partial) + * image tiles. Same coordinate system as aBorderArea/aBGClipRect passed into + * PrepareBackgroundLayer. + */ + nsRect mFillArea; + /** + * The anchor point that should be snapped to a pixel corner. Same + * coordinate system as aBorderArea/aBGClipRect passed into + * PrepareBackgroundLayer. + */ + nsPoint mAnchor; +}; + struct nsCSSRendering { /** * Initialize any static variables used by nsCSSRendering. @@ -211,7 +328,18 @@ struct nsCSSRendering { static nscolor DetermineBackgroundColor(nsPresContext* aPresContext, nsStyleContext* aStyleContext, - nsIFrame* aFrame); + nsIFrame* aFrame, + bool& aDrawBackgroundImage, + bool& aDrawBackgroundColor); + + static nsBackgroundLayerState + PrepareBackgroundLayer(nsPresContext* aPresContext, + nsIFrame* aForFrame, + PRUint32 aFlags, + const nsRect& aBorderArea, + const nsRect& aBGClipRect, + const nsStyleBackground& aBackground, + const nsStyleBackground::Layer& aLayer); /** * Render the background for an element using css rendering rules diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index e5245790c18f..469e01180742 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -5036,9 +5036,14 @@ void PresShell::UpdateCanvasBackground() // style frame but we don't have access to the canvasframe here. It isn't // a problem because only a few frames can return something other than true // and none of them would be a canvas frame or root element style frame. + bool drawBackgroundImage; + bool drawBackgroundColor; + mCanvasBackgroundColor = nsCSSRendering::DetermineBackgroundColor(mPresContext, bgStyle, - rootStyleFrame); + rootStyleFrame, + drawBackgroundImage, + drawBackgroundColor); if (GetPresContext()->IsRootContentDocument() && !IsTransparentContainerElement(mPresContext)) { mCanvasBackgroundColor =