Bug 458031. Take dirty rect into account to limit box-shadow computation. r+sr=roc

This commit is contained in:
Michael Ventnor 2008-12-03 10:16:22 +13:00
Родитель d483c98f06
Коммит 1976d96d55
7 изменённых файлов: 52 добавлений и 14 удалений

Просмотреть файл

@ -1054,7 +1054,8 @@ void
nsCSSRendering::PaintBoxShadow(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
const nsPoint& aForFramePt)
const nsPoint& aForFramePt,
const nsRect& aDirtyRect)
{
nsMargin borderValues;
PRIntn sidesToSkip;
@ -1076,6 +1077,8 @@ nsCSSRendering::PaintBoxShadow(nsPresContext* aPresContext,
twipsPerPixel, &borderRadii);
gfxRect frameGfxRect = RectToGfxRect(frameRect, twipsPerPixel);
gfxRect dirtyGfxRect = RectToGfxRect(aDirtyRect, twipsPerPixel);
for (PRUint32 i = styleBorder->mBoxShadow->Length(); i > 0; --i) {
nsCSSShadowItem* shadowItem = styleBorder->mBoxShadow->ShadowAt(i - 1);
gfxRect shadowRect(frameRect.x, frameRect.y, frameRect.width, frameRect.height);
@ -1097,9 +1100,9 @@ nsCSSRendering::PaintBoxShadow(nsPresContext* aPresContext,
nsRefPtr<gfxContext> shadowContext;
nsContextBoxBlur blurringArea;
// shadowRect has already been converted to device pixels, pass 1 as the appunits/pixel value
// shadowRect is already in device pixels, pass 1 as the appunits/pixel value
blurRadius /= twipsPerPixel;
shadowContext = blurringArea.Init(shadowRect, blurRadius, 1, renderContext);
shadowContext = blurringArea.Init(shadowRect, blurRadius, 1, renderContext, dirtyGfxRect);
if (!shadowContext)
continue;
@ -2540,7 +2543,8 @@ GetTextDecorationRectInternal(const gfxPoint& aPt,
gfxContext*
nsContextBoxBlur::Init(const gfxRect& aRect, nscoord aBlurRadius,
PRInt32 aAppUnitsPerDevPixel,
gfxContext* aDestinationCtx)
gfxContext* aDestinationCtx,
const gfxRect& aDirtyRect)
{
mDestinationCtx = aDestinationCtx;
@ -2561,9 +2565,24 @@ nsContextBoxBlur::Init(const gfxRect& aRect, nscoord aBlurRadius,
return mContext;
}
gfxRect dirtyRect = aDirtyRect;
dirtyRect.ScaleInverse(aAppUnitsPerDevPixel);
gfxRect rectWithBlur = rect;
rectWithBlur.Outset(blurRadius);
// Determine the area of the shadow we need.
mRequiredShadowArea = dirtyRect.Intersect(rectWithBlur);
mDestinationCtx = aDestinationCtx;
mContext = blur.Init(rect, gfxIntSize(blurRadius, blurRadius));
// XXX the temporary surface will be the mRequiredShadowArea inflated by
// blurRadius in each direction so that the required shadow pixels are computed
// correctly. We could actually use a smaller temporary surface by observing
// that where the temporary surface is outside the rectWithBlur, the pixel
// values are guaranteed to be fully transparent, so we could intersect the
// inflated mRequiredShadowArea with rectWithBlur to compute the temporary
// surface area. But we're not doing that right now because it's more complex to do.
mContext = blur.Init(mRequiredShadowArea, gfxIntSize(blurRadius, blurRadius));
return mContext;
}
@ -2573,7 +2592,12 @@ nsContextBoxBlur::DoPaint()
if (mContext == mDestinationCtx)
return;
mDestinationCtx->Save();
mDestinationCtx->NewPath();
mDestinationCtx->Rectangle(mRequiredShadowArea);
mDestinationCtx->Clip();
blur.Paint(mDestinationCtx);
mDestinationCtx->Restore();
}
gfxContext*
@ -2581,3 +2605,4 @@ nsContextBoxBlur::GetContext()
{
return mContext;
}

Просмотреть файл

@ -64,7 +64,8 @@ struct nsCSSRendering {
static void PaintBoxShadow(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
const nsPoint& aForFramePt);
const nsPoint& aForFramePt,
const nsRect& aDirtyRect);
/**
* Render the border for an element using css rendering rules
@ -288,6 +289,9 @@ public:
* set the color on this context before
* calling Init().
*
* @param aDirtyRect The absolute dirty rect in app units. Used to
* optimize the temporary surface size and speed up blur.
*
* @return A blank 8-bit alpha-channel-only graphics context to
* draw on, or null on error. Must not be freed. The
* context has a device offset applied to it given by
@ -302,7 +306,8 @@ public:
* directly on it instead of any temporary surface created in this class.
*/
gfxContext* Init(const gfxRect& aRect, nscoord aBlurRadius,
PRInt32 aAppUnitsPerDevPixel, gfxContext* aDestinationCtx);
PRInt32 aAppUnitsPerDevPixel, gfxContext* aDestinationCtx,
const gfxRect& aDirtyRect);
/**
* Does the actual blurring and mask applying. Users of this object *must*
@ -323,6 +328,8 @@ protected:
nsRefPtr<gfxContext> mContext;
gfxContext* mDestinationCtx;
gfxRect mRequiredShadowArea;
};
#endif /* nsCSSRendering_h___ */

Просмотреть файл

@ -651,7 +651,7 @@ nsDisplayBoxShadow::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
nsCSSRendering::PaintBoxShadow(mFrame->PresContext(), *aCtx,
mFrame, offset);
mFrame, offset, aDirtyRect);
}
nsRect

Просмотреть файл

@ -202,10 +202,12 @@ nsDisplayTextShadow::Paint(nsDisplayListBuilder* aBuilder,
gfxRect shadowRect = gfxRect(pt.x, pt.y, innerWidthInAppUnits, mFrame->GetSize().height);
gfxContext* thebesCtx = aCtx->ThebesContext();
gfxRect dirtyRect(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
nsContextBoxBlur contextBoxBlur;
gfxContext* shadowCtx = contextBoxBlur.Init(shadowRect, mBlurRadius,
mFrame->PresContext()->AppUnitsPerDevPixel(),
thebesCtx);
thebesCtx, dirtyRect);
if (!shadowCtx)
return;

Просмотреть файл

@ -4150,7 +4150,7 @@ nsTextFrame::PaintOneShadow(PRUint32 aOffset, PRUint32 aLength,
nsContextBoxBlur contextBoxBlur;
gfxContext* shadowContext = contextBoxBlur.Init(shadowRect, blurRadius,
PresContext()->AppUnitsPerDevPixel(),
aCtx);
aCtx, aDirtyRect);
if (!shadowContext)
return;

Просмотреть файл

@ -387,7 +387,8 @@ nsTextBoxFrame::PaintTitle(nsIRenderingContext& aRenderingContext,
PaintOneShadow(aRenderingContext.ThebesContext(),
textRect,
textStyle->mTextShadow->ShadowAt(i - 1),
GetStyleColor()->mColor);
GetStyleColor()->mColor,
aDirtyRect);
}
}
@ -563,7 +564,8 @@ nsTextBoxFrame::DrawText(nsIRenderingContext& aRenderingContext,
void nsTextBoxFrame::PaintOneShadow(gfxContext* aCtx,
const nsRect& aTextRect,
nsCSSShadowItem* aShadowDetails,
const nscolor& aForegroundColor) {
const nscolor& aForegroundColor,
const nsRect& aDirtyRect) {
nsPoint shadowOffset(aShadowDetails->mXOffset,
aShadowDetails->mYOffset);
nscoord blurRadius = PR_MAX(aShadowDetails->mRadius, 0);
@ -572,11 +574,12 @@ void nsTextBoxFrame::PaintOneShadow(gfxContext* aCtx,
shadowRect.MoveBy(shadowOffset);
gfxRect shadowRectGFX(shadowRect.x, shadowRect.y, shadowRect.width, shadowRect.height);
gfxRect dirtyRectGFX(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
nsContextBoxBlur contextBoxBlur;
gfxContext* shadowContext = contextBoxBlur.Init(shadowRectGFX, blurRadius,
PresContext()->AppUnitsPerDevPixel(),
aCtx);
aCtx, dirtyRectGFX);
if (!shadowContext)
return;

Просмотреть файл

@ -134,7 +134,8 @@ private:
void PaintOneShadow(gfxContext * aCtx,
const nsRect& aTextRect,
nsCSSShadowItem* aShadowDetails,
const nscolor& aForegroundColor);
const nscolor& aForegroundColor,
const nsRect& aDirtyRect);
CroppingStyle mCropType;