Bug 626536. Part 1. Refactor the background clip code so that it stores its state in a struct we can pass around. r=roc a=roc

This commit is contained in:
Timothy Nikkel 2011-01-18 13:43:47 -06:00
parent ba5c94807f
commit 9e965d401c

View File

@ -1541,19 +1541,30 @@ SetupDirtyRects(const nsRect& aBGClipArea, const nsRect& aCallerDirtyRect,
"second should be empty if first is");
}
struct BackgroundClipState {
nsRect mBGClipArea;
nsRect mDirtyRect;
gfxRect mDirtyRectGfx;
gfxCornerSizes mClippedRadii;
PRPackedBool mRadiiAreOuter;
// Whether we are being asked to draw with a caller provided background
// clipping area. If this is true we also disable rounded corners.
PRPackedBool mCustomClip;
};
static void
SetupBackgroundClip(gfxContext *aCtx, PRUint8 aBackgroundClip,
nsIFrame* aForFrame, const nsRect& aBorderArea,
const nsRect& aCallerDirtyRect, PRBool aHaveRoundedCorners,
const gfxCornerSizes& aBGRadii, nscoord aAppUnitsPerPixel,
gfxContextAutoSaveRestore* aAutoSR,
/* OUT: */
nsRect* aBGClipArea, nsRect* aDirtyRect,
gfxRect* aDirtyRectGfx)
GetBackgroundClip(gfxContext *aCtx, PRUint8 aBackgroundClip,
nsIFrame* aForFrame, const nsRect& aBorderArea,
const nsRect& aCallerDirtyRect, PRBool aHaveRoundedCorners,
const gfxCornerSizes& aBGRadii, nscoord aAppUnitsPerPixel,
/* out */ BackgroundClipState* aClipState)
{
*aBGClipArea = aBorderArea;
PRBool radiiAreOuter = PR_TRUE;
gfxCornerSizes clippedRadii = aBGRadii;
aClipState->mBGClipArea = aBorderArea;
aClipState->mCustomClip = PR_FALSE;
aClipState->mRadiiAreOuter = PR_TRUE;
aClipState->mClippedRadii = aBGRadii;
if (aBackgroundClip != NS_STYLE_BG_CLIP_BORDER) {
nsMargin border = aForFrame->GetUsedBorder();
if (aBackgroundClip != NS_STYLE_BG_CLIP_PADDING) {
@ -1562,7 +1573,7 @@ SetupBackgroundClip(gfxContext *aCtx, PRUint8 aBackgroundClip,
border += aForFrame->GetUsedPadding();
}
aForFrame->ApplySkipSides(border);
aBGClipArea->Deflate(border);
aClipState->mBGClipArea.Deflate(border);
if (aHaveRoundedCorners) {
gfxFloat borderSizes[4] = {
@ -1572,20 +1583,32 @@ SetupBackgroundClip(gfxContext *aCtx, PRUint8 aBackgroundClip,
gfxFloat(border.left / aAppUnitsPerPixel)
};
nsCSSBorderRenderer::ComputeInnerRadii(aBGRadii, borderSizes,
&clippedRadii);
radiiAreOuter = PR_FALSE;
&aClipState->mClippedRadii);
aClipState->mRadiiAreOuter = PR_FALSE;
}
}
SetupDirtyRects(*aBGClipArea, aCallerDirtyRect, aAppUnitsPerPixel,
aDirtyRect, aDirtyRectGfx);
SetupDirtyRects(aClipState->mBGClipArea, aCallerDirtyRect, aAppUnitsPerPixel,
&aClipState->mDirtyRect, &aClipState->mDirtyRectGfx);
}
if (aDirtyRectGfx->IsEmpty()) {
static void
SetupBackgroundClip(BackgroundClipState& aClipState, gfxContext *aCtx,
PRBool aHaveRoundedCorners, nscoord aAppUnitsPerPixel,
gfxContextAutoSaveRestore* aAutoSR)
{
if (aClipState.mDirtyRectGfx.IsEmpty()) {
// Our caller won't draw anything under this condition, so no need
// to set more up.
return;
}
if (aClipState.mCustomClip) {
// We don't support custom clips and rounded corners, arguably a bug, but
// table painting seems to depend on it.
return;
}
// If we have rounded corners, clip all subsequent drawing to the
// rounded rectangle defined by bgArea and bgRadii (we don't know
// whether the rounded corners intrude on the dirtyRect or not).
@ -1595,7 +1618,7 @@ SetupBackgroundClip(gfxContext *aCtx, PRUint8 aBackgroundClip,
if (aHaveRoundedCorners) {
gfxRect bgAreaGfx =
nsLayoutUtils::RectToGfxRect(*aBGClipArea, aAppUnitsPerPixel);
nsLayoutUtils::RectToGfxRect(aClipState.mBGClipArea, aAppUnitsPerPixel);
bgAreaGfx.Round();
bgAreaGfx.Condition();
@ -1604,13 +1627,13 @@ SetupBackgroundClip(gfxContext *aCtx, PRUint8 aBackgroundClip,
// http://hg.mozilla.org/mozilla-central/rev/50e934e4979b landed.
NS_WARNING("converted background area should not be empty");
// Make our caller not do anything.
aDirtyRectGfx->size.SizeTo(0.0, 0.0);
aClipState.mDirtyRectGfx.size.SizeTo(0.0, 0.0);
return;
}
aAutoSR->Reset(aCtx);
aCtx->NewPath();
aCtx->RoundedRectangle(bgAreaGfx, clippedRadii, radiiAreOuter);
aCtx->RoundedRectangle(bgAreaGfx, aClipState.mClippedRadii, aClipState.mRadiiAreOuter);
aCtx->Clip();
}
}
@ -2267,15 +2290,14 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
// intersection, but that breaks the table painter -- in particular,
// taking the intersection breaks reftests/bugs/403249-1[ab].)
const nsStyleBackground *bg = aBackgroundSC->GetStyleBackground();
nsRect bgClipArea, dirtyRect;
gfxRect dirtyRectGfx;
BackgroundClipState clipState;
PRUint8 currentBackgroundClip;
PRBool isSolidBorder;
gfxContextAutoSaveRestore autoSR;
if (aBGClipRect) {
bgClipArea = *aBGClipRect;
SetupDirtyRects(bgClipArea, aDirtyRect, appUnitsPerPixel,
&dirtyRect, &dirtyRectGfx);
clipState.mBGClipArea = *aBGClipRect;
clipState.mCustomClip = PR_TRUE;
SetupDirtyRects(clipState.mBGClipArea, aDirtyRect, appUnitsPerPixel,
&clipState.mDirtyRect, &clipState.mDirtyRectGfx);
} else {
// The background is rendered over the 'background-clip' area,
// which is normally equal to the border area but may be reduced
@ -2290,23 +2312,27 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
(aFlags & PAINTBG_WILL_PAINT_BORDER) && IsOpaqueBorder(aBorder);
if (isSolidBorder && currentBackgroundClip == NS_STYLE_BG_CLIP_BORDER)
currentBackgroundClip = NS_STYLE_BG_CLIP_PADDING;
SetupBackgroundClip(ctx, currentBackgroundClip, aForFrame,
aBorderArea, aDirtyRect, haveRoundedCorners,
bgRadii, appUnitsPerPixel, &autoSR,
&bgClipArea, &dirtyRect, &dirtyRectGfx);
GetBackgroundClip(ctx, currentBackgroundClip, aForFrame, aBorderArea,
aDirtyRect, haveRoundedCorners, bgRadii, appUnitsPerPixel,
&clipState);
}
// If we might be using a background color, go ahead and set it now.
if (drawBackgroundColor && !isCanvasFrame)
ctx->SetColor(gfxRGBA(bgColor));
gfxContextAutoSaveRestore autoSR;
// If there is no background image, draw a color. (If there is
// neither a background image nor a color, we wouldn't have gotten
// this far.)
if (!drawBackgroundImage) {
if (!dirtyRectGfx.IsEmpty() && !isCanvasFrame) {
if (!clipState.mDirtyRectGfx.IsEmpty() && !isCanvasFrame) {
SetupBackgroundClip(clipState, ctx, haveRoundedCorners, appUnitsPerPixel,
&autoSR);
ctx->NewPath();
ctx->Rectangle(dirtyRectGfx, PR_TRUE);
ctx->Rectangle(clipState.mDirtyRectGfx, PR_TRUE);
ctx->Fill();
}
return;
@ -2326,9 +2352,11 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
// The background color is rendered over the entire dirty area,
// even if the image isn't.
if (drawBackgroundColor && !isCanvasFrame) {
if (!dirtyRectGfx.IsEmpty()) {
if (!clipState.mDirtyRectGfx.IsEmpty()) {
SetupBackgroundClip(clipState, ctx, haveRoundedCorners, appUnitsPerPixel,
&autoSR);
ctx->NewPath();
ctx->Rectangle(dirtyRectGfx, PR_TRUE);
ctx->Rectangle(clipState.mDirtyRectGfx, PR_TRUE);
ctx->Fill();
}
}
@ -2342,19 +2370,21 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
newBackgroundClip = NS_STYLE_BG_CLIP_PADDING;
if (currentBackgroundClip != newBackgroundClip) {
currentBackgroundClip = newBackgroundClip;
SetupBackgroundClip(ctx, currentBackgroundClip, aForFrame,
aBorderArea, aDirtyRect, haveRoundedCorners,
bgRadii, appUnitsPerPixel, &autoSR,
&bgClipArea, &dirtyRect, &dirtyRectGfx);
GetBackgroundClip(ctx, currentBackgroundClip, aForFrame, aBorderArea,
aDirtyRect, haveRoundedCorners, bgRadii,
appUnitsPerPixel, &clipState);
SetupBackgroundClip(clipState, ctx, haveRoundedCorners,
appUnitsPerPixel, &autoSR);
}
}
if (!dirtyRectGfx.IsEmpty()) {
if (!clipState.mDirtyRectGfx.IsEmpty()) {
BackgroundLayerState state = PrepareBackgroundLayer(aPresContext, aForFrame,
aFlags, aBorderArea, bgClipArea, *bg, layer);
aFlags, aBorderArea, clipState.mBGClipArea, *bg, layer);
if (!state.mFillArea.IsEmpty()) {
state.mImageRenderer.Draw(aPresContext, aRenderingContext,
state.mDestArea, state.mFillArea,
state.mAnchor + aBorderArea.TopLeft(), dirtyRect);
state.mAnchor + aBorderArea.TopLeft(),
clipState.mDirtyRect);
}
}
}