зеркало из https://github.com/mozilla/gecko-dev.git
Bug 458031. Take dirty rect into account to limit box-shadow computation. r+sr=roc
This commit is contained in:
Родитель
d483c98f06
Коммит
1976d96d55
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче