Bug 1042423 - Part 1: Clean up GetBackgroundClip and make it public. r=roc

This commit is contained in:
Matt Woodrow 2014-07-23 17:20:39 +12:00
Родитель 3d909148b5
Коммит 1b1819d095
2 изменённых файлов: 105 добавлений и 112 удалений

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

@ -431,19 +431,30 @@ MakeBevelColor(mozilla::css::Side whichSide, uint8_t style,
static bool
GetRadii(nsIFrame* aForFrame, const nsStyleBorder& aBorder,
const nsRect& aOrigBorderArea, const nsRect& aBorderArea,
gfxCornerSizes* aBgRadii)
nscoord aRadii[8])
{
nscoord radii[8];
bool haveRoundedCorners;
nsSize sz = aBorderArea.Size();
nsSize frameSize = aForFrame->GetSize();
if (&aBorder == aForFrame->StyleBorder() &&
frameSize == aOrigBorderArea.Size()) {
haveRoundedCorners = aForFrame->GetBorderRadii(sz, sz, Sides(), radii);
haveRoundedCorners = aForFrame->GetBorderRadii(sz, sz, Sides(), aRadii);
} else {
haveRoundedCorners =
nsIFrame::ComputeBorderRadii(aBorder.mBorderRadius, frameSize, sz, Sides(), radii);
nsIFrame::ComputeBorderRadii(aBorder.mBorderRadius, frameSize, sz, Sides(), aRadii);
}
return haveRoundedCorners;
}
static bool
GetRadii(nsIFrame* aForFrame, const nsStyleBorder& aBorder,
const nsRect& aOrigBorderArea, const nsRect& aBorderArea,
gfxCornerSizes* aBgRadii)
{
nscoord radii[8];
bool haveRoundedCorners = GetRadii(aForFrame, aBorder, aOrigBorderArea, aBorderArea, radii);
if (haveRoundedCorners) {
auto d2a = aForFrame->PresContext()->AppUnitsPerDevPixel();
nsCSSRendering::ComputePixelRadii(radii, d2a, aBgRadii);
@ -1695,35 +1706,39 @@ SetupDirtyRects(const nsRect& aBGClipArea, const nsRect& aCallerDirtyRect,
"second should be empty if first is");
}
struct BackgroundClipState {
nsRect mBGClipArea; // Affected by mClippedRadii
nsRect mAdditionalBGClipArea; // Not affected by mClippedRadii
nsRect mDirtyRect;
gfxRect mDirtyRectGfx;
gfxCornerSizes mClippedRadii;
bool mHasAdditionalBGClipArea;
// Whether we are being asked to draw with a caller provided background
// clipping area. If this is true we also disable rounded corners.
bool mCustomClip;
};
static void
GetBackgroundClip(gfxContext *aCtx, uint8_t aBackgroundClip,
uint8_t aBackgroundAttachment,
nsIFrame* aForFrame, const nsRect& aBorderArea,
const nsRect& aCallerDirtyRect, bool aHaveRoundedCorners,
const gfxCornerSizes& aBGRadii, nscoord aAppUnitsPerPixel,
/* out */ BackgroundClipState* aClipState)
/* static */ void
nsCSSRendering::GetBackgroundClip(const nsStyleBackground::Layer& aLayer,
nsIFrame* aForFrame, const nsStyleBorder& aBorder,
const nsRect& aBorderArea, const nsRect& aCallerDirtyRect,
bool aWillPaintBorder, nscoord aAppUnitsPerPixel,
/* out */ BackgroundClipState* aClipState)
{
// Compute the outermost boundary of the area that might be painted.
// Same coordinate space as aBorderArea.
nsRect clipBorderArea =
::BoxDecorationRectForBorder(aForFrame, aBorderArea, &aBorder);
bool haveRoundedCorners = GetRadii(aForFrame, aBorder, aBorderArea,
clipBorderArea, aClipState->mRadii);
uint8_t backgroundClip = aLayer.mClip;
bool isSolidBorder =
aWillPaintBorder && IsOpaqueBorder(aBorder);
if (isSolidBorder && backgroundClip == NS_STYLE_BG_CLIP_BORDER) {
// If we have rounded corners, we need to inflate the background
// drawing area a bit to avoid seams between the border and
// background.
backgroundClip = haveRoundedCorners ?
NS_STYLE_BG_CLIP_MOZ_ALMOST_PADDING : NS_STYLE_BG_CLIP_PADDING;
}
aClipState->mBGClipArea = aBorderArea;
aClipState->mHasAdditionalBGClipArea = false;
aClipState->mCustomClip = false;
aClipState->mClippedRadii = aBGRadii;
if (aForFrame->GetType() == nsGkAtoms::scrollFrame &&
NS_STYLE_BG_ATTACHMENT_LOCAL == aBackgroundAttachment) {
NS_STYLE_BG_ATTACHMENT_LOCAL == aLayer.mAttachment) {
// As of this writing, this is still in discussion in the CSS Working Group
// http://lists.w3.org/Archives/Public/www-style/2013Jul/0250.html
@ -1731,7 +1746,7 @@ GetBackgroundClip(gfxContext *aCtx, uint8_t aBackgroundClip,
// but the background is also clipped at a non-scrolling 'padding-box'
// like the content. (See below.)
// Therefore, only 'content-box' makes a difference here.
if (aBackgroundClip == NS_STYLE_BG_CLIP_CONTENT) {
if (backgroundClip == NS_STYLE_BG_CLIP_CONTENT) {
nsIScrollableFrame* scrollableFrame = do_QueryFrame(aForFrame);
// Clip at a rectangle attached to the scrolled content.
aClipState->mHasAdditionalBGClipArea = true;
@ -1751,12 +1766,12 @@ GetBackgroundClip(gfxContext *aCtx, uint8_t aBackgroundClip,
// Also clip at a non-scrolling, rounded-corner 'padding-box',
// same as the scrolled content because of the 'overflow' property.
aBackgroundClip = NS_STYLE_BG_CLIP_PADDING;
backgroundClip = NS_STYLE_BG_CLIP_PADDING;
}
if (aBackgroundClip != NS_STYLE_BG_CLIP_BORDER) {
if (backgroundClip != NS_STYLE_BG_CLIP_BORDER) {
nsMargin border = aForFrame->GetUsedBorder();
if (aBackgroundClip == NS_STYLE_BG_CLIP_MOZ_ALMOST_PADDING) {
if (backgroundClip == NS_STYLE_BG_CLIP_MOZ_ALMOST_PADDING) {
// Reduce |border| by 1px (device pixels) on all sides, if
// possible, so that we don't get antialiasing seams between the
// background and border.
@ -1764,27 +1779,29 @@ GetBackgroundClip(gfxContext *aCtx, uint8_t aBackgroundClip,
border.right = std::max(0, border.right - aAppUnitsPerPixel);
border.bottom = std::max(0, border.bottom - aAppUnitsPerPixel);
border.left = std::max(0, border.left - aAppUnitsPerPixel);
} else if (aBackgroundClip != NS_STYLE_BG_CLIP_PADDING) {
NS_ASSERTION(aBackgroundClip == NS_STYLE_BG_CLIP_CONTENT,
} else if (backgroundClip != NS_STYLE_BG_CLIP_PADDING) {
NS_ASSERTION(backgroundClip == NS_STYLE_BG_CLIP_CONTENT,
"unexpected background-clip");
border += aForFrame->GetUsedPadding();
}
border.ApplySkipSides(aForFrame->GetSkipSides());
aClipState->mBGClipArea.Deflate(border);
if (aHaveRoundedCorners) {
gfxFloat borderSizes[4] = {
gfxFloat(border.top / aAppUnitsPerPixel),
gfxFloat(border.right / aAppUnitsPerPixel),
gfxFloat(border.bottom / aAppUnitsPerPixel),
gfxFloat(border.left / aAppUnitsPerPixel)
};
nsCSSBorderRenderer::ComputeInnerRadii(aBGRadii, borderSizes,
&aClipState->mClippedRadii);
if (haveRoundedCorners) {
nsIFrame::InsetBorderRadii(aClipState->mRadii, border);
}
}
if (!aHaveRoundedCorners && aClipState->mHasAdditionalBGClipArea) {
if (haveRoundedCorners) {
auto d2a = aForFrame->PresContext()->AppUnitsPerDevPixel();
nsCSSRendering::ComputePixelRadii(aClipState->mRadii, d2a, &aClipState->mClippedRadii);
aClipState->mHasRoundedCorners = true;
} else {
aClipState->mHasRoundedCorners = false;
}
if (!haveRoundedCorners && aClipState->mHasAdditionalBGClipArea) {
// Do the intersection here to account for the fast path(?) below.
aClipState->mBGClipArea =
aClipState->mBGClipArea.Intersect(aClipState->mAdditionalBGClipArea);
@ -1796,8 +1813,8 @@ GetBackgroundClip(gfxContext *aCtx, uint8_t aBackgroundClip,
}
static void
SetupBackgroundClip(BackgroundClipState& aClipState, gfxContext *aCtx,
bool aHaveRoundedCorners, nscoord aAppUnitsPerPixel,
SetupBackgroundClip(nsCSSRendering::BackgroundClipState& aClipState,
gfxContext *aCtx, nscoord aAppUnitsPerPixel,
gfxContextAutoSaveRestore* aAutoSR)
{
if (aClipState.mDirtyRectGfx.IsEmpty()) {
@ -1831,7 +1848,7 @@ SetupBackgroundClip(BackgroundClipState& aClipState, gfxContext *aCtx,
aCtx->Clip();
}
if (aHaveRoundedCorners) {
if (aClipState.mHasRoundedCorners) {
gfxRect bgAreaGfx =
nsLayoutUtils::RectToGfxRect(aClipState.mBGClipArea, aAppUnitsPerPixel);
bgAreaGfx.Round();
@ -1854,8 +1871,8 @@ SetupBackgroundClip(BackgroundClipState& aClipState, gfxContext *aCtx,
}
static void
DrawBackgroundColor(BackgroundClipState& aClipState, gfxContext *aCtx,
bool aHaveRoundedCorners, nscoord aAppUnitsPerPixel)
DrawBackgroundColor(nsCSSRendering::BackgroundClipState& aClipState,
gfxContext *aCtx, nscoord aAppUnitsPerPixel)
{
if (aClipState.mDirtyRectGfx.IsEmpty()) {
// Our caller won't draw anything under this condition, so no need
@ -1865,7 +1882,7 @@ DrawBackgroundColor(BackgroundClipState& aClipState, gfxContext *aCtx,
// We don't support custom clips and rounded corners, arguably a bug, but
// table painting seems to depend on it.
if (!aHaveRoundedCorners || aClipState.mCustomClip) {
if (!aClipState.mHasRoundedCorners || aClipState.mCustomClip) {
aCtx->NewPath();
aCtx->Rectangle(aClipState.mDirtyRectGfx, true);
aCtx->Fill();
@ -2693,9 +2710,6 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
::BoxDecorationRectForBackground(aForFrame, aBorderArea, &aBorder);
nsRect clipBorderArea =
::BoxDecorationRectForBorder(aForFrame, aBorderArea, &aBorder);
gfxCornerSizes bgRadii;
bool haveRoundedCorners =
::GetRadii(aForFrame, aBorder, aBorderArea, clipBorderArea, &bgRadii);
// The 'bgClipArea' (used only by the image tiling logic, far below)
// is the caller-provided aBGClipRect if any, or else the area
@ -2706,36 +2720,15 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
gfxContext* ctx = aRenderingContext.ThebesContext();
nscoord appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
BackgroundClipState clipState;
uint8_t currentBackgroundClip;
bool isSolidBorder;
if (aBGClipRect) {
clipState.mBGClipArea = *aBGClipRect;
clipState.mCustomClip = 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
// to the padding area by CSS. Also, if the border is solid, we
// don't need to draw outside the padding area. In either case,
// if the borders are rounded, make sure we use the same inner
// radii as the border code will.
// The background-color is drawn based on the bottom
// background-clip.
currentBackgroundClip = bg->BottomLayer().mClip;
isSolidBorder =
(aFlags & PAINTBG_WILL_PAINT_BORDER) && IsOpaqueBorder(aBorder);
if (isSolidBorder && currentBackgroundClip == NS_STYLE_BG_CLIP_BORDER) {
// If we have rounded corners, we need to inflate the background
// drawing area a bit to avoid seams between the border and
// background.
currentBackgroundClip = haveRoundedCorners ?
NS_STYLE_BG_CLIP_MOZ_ALMOST_PADDING : NS_STYLE_BG_CLIP_PADDING;
}
GetBackgroundClip(ctx, currentBackgroundClip, bg->BottomLayer().mAttachment,
aForFrame, clipBorderArea,
aDirtyRect, haveRoundedCorners, bgRadii, appUnitsPerPixel,
GetBackgroundClip(bg->BottomLayer(),
aForFrame, aBorder, aBorderArea,
aDirtyRect, (aFlags & PAINTBG_WILL_PAINT_BORDER), appUnitsPerPixel,
&clipState);
}
@ -2752,7 +2745,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
// this far.)
if (!drawBackgroundImage) {
if (!isCanvasFrame) {
DrawBackgroundColor(clipState, ctx, haveRoundedCorners, appUnitsPerPixel);
DrawBackgroundColor(clipState, ctx, appUnitsPerPixel);
}
return;
}
@ -2783,34 +2776,29 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
// The background color is rendered over the entire dirty area,
// even if the image isn't.
if (drawBackgroundColor && !isCanvasFrame) {
DrawBackgroundColor(clipState, ctx, haveRoundedCorners, appUnitsPerPixel);
DrawBackgroundColor(clipState, ctx, appUnitsPerPixel);
}
if (drawBackgroundImage) {
bool clipSet = false;
uint8_t currentBackgroundClip = NS_STYLE_BG_CLIP_BORDER;
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT_WITH_RANGE(i, bg, bg->mImageCount - 1,
nLayers + (bg->mImageCount -
startLayer - 1)) {
const nsStyleBackground::Layer &layer = bg->mLayers[i];
if (!aBGClipRect) {
uint8_t newBackgroundClip = layer.mClip;
if (isSolidBorder && newBackgroundClip == NS_STYLE_BG_CLIP_BORDER) {
newBackgroundClip = haveRoundedCorners ?
NS_STYLE_BG_CLIP_MOZ_ALMOST_PADDING : NS_STYLE_BG_CLIP_PADDING;
}
if (currentBackgroundClip != newBackgroundClip || !clipSet) {
currentBackgroundClip = newBackgroundClip;
if (currentBackgroundClip != layer.mClip || !clipSet) {
currentBackgroundClip = layer.mClip;
// If clipSet is false that means this is the bottom layer and we
// already called GetBackgroundClip above and it stored its results
// in clipState.
if (clipSet) {
autoSR.Restore(); // reset the previous one
GetBackgroundClip(ctx, currentBackgroundClip, layer.mAttachment, aForFrame,
clipBorderArea, aDirtyRect, haveRoundedCorners,
bgRadii, appUnitsPerPixel, &clipState);
GetBackgroundClip(layer, aForFrame,
aBorder, aBorderArea, aDirtyRect, (aFlags & PAINTBG_WILL_PAINT_BORDER),
appUnitsPerPixel, &clipState);
}
SetupBackgroundClip(clipState, ctx, haveRoundedCorners,
appUnitsPerPixel, &autoSR);
SetupBackgroundClip(clipState, ctx, appUnitsPerPixel, &autoSR);
clipSet = true;
if (!clipBorderArea.IsEqualEdges(aBorderArea)) {
// We're drawing the background for the joined continuation boxes
@ -2891,14 +2879,6 @@ nsCSSRendering::PaintBackgroundColorWithSC(gfxRGBA aColor,
return;
}
// Compute the outermost boundary of the area that might be painted.
// Same coordinate space as aBorderArea.
nsRect clipBorderArea =
::BoxDecorationRectForBorder(aForFrame, aBorderArea, &aBorder);
gfxCornerSizes bgRadii;
bool haveRoundedCorners =
::GetRadii(aForFrame, aBorder, aBorderArea, clipBorderArea, &bgRadii);
// The background is rendered over the 'background-clip' area,
// which is normally equal to the border area but may be reduced
// to the padding area by CSS. Also, if the border is solid, we
@ -2910,27 +2890,17 @@ nsCSSRendering::PaintBackgroundColorWithSC(gfxRGBA aColor,
gfxContext* ctx = aRenderingContext.ThebesContext();
nscoord appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
const nsStyleBackground *bg = aBackgroundSC->StyleBackground();
uint8_t currentBackgroundClip = bg->BottomLayer().mClip;
bool isSolidBorder =
(aFlags & PAINTBG_WILL_PAINT_BORDER) && IsOpaqueBorder(aBorder);
if (isSolidBorder && currentBackgroundClip == NS_STYLE_BG_CLIP_BORDER) {
// If we have rounded corners, we need to inflate the background
// drawing area a bit to avoid seams between the border and
// background.
currentBackgroundClip = haveRoundedCorners ?
NS_STYLE_BG_CLIP_MOZ_ALMOST_PADDING : NS_STYLE_BG_CLIP_PADDING;
}
BackgroundClipState clipState;
GetBackgroundClip(ctx, currentBackgroundClip, bg->BottomLayer().mAttachment,
aForFrame, clipBorderArea,
aDirtyRect, haveRoundedCorners, bgRadii, appUnitsPerPixel,
GetBackgroundClip(bg->BottomLayer(),
aForFrame, aBorder, aBorderArea,
aDirtyRect, (aFlags & PAINTBG_WILL_PAINT_BORDER), appUnitsPerPixel,
&clipState);
ctx->SetColor(aColor);
gfxContextAutoSaveRestore autoSR;
DrawBackgroundColor(clipState, ctx, haveRoundedCorners, appUnitsPerPixel);
DrawBackgroundColor(clipState, ctx, appUnitsPerPixel);
}
static inline bool

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

@ -473,6 +473,29 @@ struct nsCSSRendering {
const nsRect& aBGClipRect,
const nsStyleBackground::Layer& aLayer);
struct BackgroundClipState {
nsRect mBGClipArea; // Affected by mClippedRadii
nsRect mAdditionalBGClipArea; // Not affected by mClippedRadii
nsRect mDirtyRect;
gfxRect mDirtyRectGfx;
nscoord mRadii[8];
gfxCornerSizes mClippedRadii;
bool mHasRoundedCorners;
bool mHasAdditionalBGClipArea;
// Whether we are being asked to draw with a caller provided background
// clipping area. If this is true we also disable rounded corners.
bool mCustomClip;
};
static void
GetBackgroundClip(const nsStyleBackground::Layer& aLayer,
nsIFrame* aForFrame, const nsStyleBorder& aBorder, const nsRect& aBorderArea,
const nsRect& aCallerDirtyRect, bool aWillPaintBorder,
nscoord aAppUnitsPerPixel,
/* out */ BackgroundClipState* aClipState);
/**
* Render the background for an element using css rendering rules
* for backgrounds.