mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 940845 - Part 4: Add BlurRectangle to gfxAlphaBoxBlur and use it. r=roc
This commit is contained in:
parent
d0f9c81a1e
commit
cf7881aa40
@ -69,6 +69,10 @@ struct BaseSize {
|
||||
Sub operator/(T aScale) const {
|
||||
return Sub(width / aScale, height / aScale);
|
||||
}
|
||||
void Scale(T aXScale, T aYScale) {
|
||||
width *= aXScale;
|
||||
height *= aYScale;
|
||||
}
|
||||
|
||||
Sub operator*(const Sub& aSize) const {
|
||||
return Sub(width * aSize.width, height * aSize.height);
|
||||
|
@ -112,3 +112,35 @@ gfxIntSize gfxAlphaBoxBlur::CalculateBlurRadius(const gfxPoint& aStd)
|
||||
IntSize size = AlphaBoxBlur::CalculateBlurRadius(std);
|
||||
return gfxIntSize(size.width, size.height);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxAlphaBoxBlur::BlurRectangle(gfxContext *aDestinationCtx,
|
||||
const gfxRect& aRect,
|
||||
gfxCornerSizes* aCornerRadii,
|
||||
const gfxIntSize& aBlurRadius,
|
||||
const gfxRGBA& aShadowColor,
|
||||
const gfxRect& aDirtyRect,
|
||||
const gfxRect& aSkipRect)
|
||||
{
|
||||
// Create the temporary surface for blurring
|
||||
gfxAlphaBoxBlur blur;
|
||||
gfxContext *dest = blur.Init(aRect, gfxIntSize(), aBlurRadius, &aDirtyRect, &aSkipRect);
|
||||
|
||||
if (!dest) {
|
||||
return;
|
||||
}
|
||||
|
||||
gfxRect shadowGfxRect = aRect;
|
||||
shadowGfxRect.Round();
|
||||
|
||||
dest->NewPath();
|
||||
if (aCornerRadii) {
|
||||
dest->RoundedRectangle(shadowGfxRect, *aCornerRadii);
|
||||
} else {
|
||||
dest->Rectangle(shadowGfxRect);
|
||||
}
|
||||
dest->Fill();
|
||||
|
||||
aDestinationCtx->SetColor(aShadowColor);
|
||||
blur.Paint(aDestinationCtx);
|
||||
}
|
||||
|
@ -14,6 +14,9 @@
|
||||
class gfxContext;
|
||||
class gfxImageSurface;
|
||||
struct gfxRect;
|
||||
struct gfxRGBA;
|
||||
class gfxCornerSizes;
|
||||
class gfxMatrix;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
@ -99,6 +102,16 @@ public:
|
||||
*/
|
||||
static gfxIntSize CalculateBlurRadius(const gfxPoint& aStandardDeviation);
|
||||
|
||||
static void BlurRectangle(gfxContext *aDestinationCtx,
|
||||
const gfxRect& aRect,
|
||||
gfxCornerSizes* aCornerRadii,
|
||||
const gfxIntSize& aBlurRadius,
|
||||
const gfxRGBA& aShadowColor,
|
||||
const gfxRect& aDirtyRect,
|
||||
const gfxRect& aSkipRect);
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The context of the temporary alpha surface.
|
||||
|
@ -171,6 +171,12 @@ struct gfxCornerSizes {
|
||||
return sizes[index];
|
||||
}
|
||||
|
||||
void Scale(gfxFloat aXScale, gfxFloat aYScale)
|
||||
{
|
||||
for (int i = 0; i < NS_NUM_CORNERS; i++)
|
||||
sizes[i].Scale(aXScale, aYScale);
|
||||
}
|
||||
|
||||
const gfxSize TopLeft() const { return sizes[NS_CORNER_TOP_LEFT]; }
|
||||
gfxSize& TopLeft() { return sizes[NS_CORNER_TOP_LEFT]; }
|
||||
|
||||
|
@ -4822,6 +4822,22 @@ nsContextBoxBlur::BlurRectangle(gfxContext* aDestinationCtx,
|
||||
return;
|
||||
}
|
||||
|
||||
gfxRect shadowGfxRect =
|
||||
nsLayoutUtils::RectToGfxRect(aRect, aAppUnitsPerDevPixel);
|
||||
|
||||
if (aBlurRadius <= 0) {
|
||||
aDestinationCtx->SetColor(aShadowColor);
|
||||
aDestinationCtx->NewPath();
|
||||
if (aCornerRadii) {
|
||||
aDestinationCtx->RoundedRectangle(shadowGfxRect, *aCornerRadii);
|
||||
} else {
|
||||
aDestinationCtx->Rectangle(shadowGfxRect);
|
||||
}
|
||||
|
||||
aDestinationCtx->Fill();
|
||||
return;
|
||||
}
|
||||
|
||||
gfxFloat scaleX = 1;
|
||||
gfxFloat scaleY = 1;
|
||||
|
||||
@ -4830,61 +4846,31 @@ nsContextBoxBlur::BlurRectangle(gfxContext* aDestinationCtx,
|
||||
// and will sometimes get incorrect results (e.g. rotated blurs)
|
||||
gfxMatrix transform = aDestinationCtx->CurrentMatrix();
|
||||
// XXX: we could probably handle negative scales but for now it's easier just to fallback
|
||||
if (transform.HasNonAxisAlignedTransform() || transform.xx <= 0.0 || transform.yy <= 0.0) {
|
||||
transform = gfxMatrix();
|
||||
} else {
|
||||
if (!transform.HasNonAxisAlignedTransform() && transform.xx > 0.0 && transform.yy > 0.0) {
|
||||
scaleX = transform.xx;
|
||||
scaleY = transform.yy;
|
||||
}
|
||||
|
||||
gfxRect shadowGfxRect =
|
||||
nsLayoutUtils::RectToGfxRect(aRect, aAppUnitsPerDevPixel);
|
||||
gfxIntSize blurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel, scaleX, scaleY);
|
||||
|
||||
gfxAlphaBoxBlur blur;
|
||||
gfxContext *dest;
|
||||
bool preTransformed = false;
|
||||
if (blurRadius.width <= 0 && blurRadius.height <= 0) {
|
||||
dest = aDestinationCtx;
|
||||
} else {
|
||||
gfxRect dirtyRect =
|
||||
nsLayoutUtils::RectToGfxRect(aDirtyRect, aAppUnitsPerDevPixel);
|
||||
dirtyRect.RoundOut();
|
||||
|
||||
gfxRect rect = transform.TransformBounds(shadowGfxRect);
|
||||
|
||||
preTransformed = !transform.IsIdentity();
|
||||
|
||||
// Create the temporary surface for blurring
|
||||
dirtyRect = transform.TransformBounds(dirtyRect);
|
||||
gfxRect skipRect = transform.TransformBounds(aSkipRect);
|
||||
dest = blur.Init(rect, gfxIntSize(), blurRadius, &dirtyRect, &skipRect);
|
||||
|
||||
if (!dest) {
|
||||
return;
|
||||
}
|
||||
|
||||
dest->SetMatrix(transform);
|
||||
}
|
||||
|
||||
shadowGfxRect.Round();
|
||||
|
||||
aDestinationCtx->SetColor(aShadowColor);
|
||||
|
||||
dest->NewPath();
|
||||
if (aCornerRadii) {
|
||||
dest->RoundedRectangle(shadowGfxRect, *aCornerRadii);
|
||||
} else {
|
||||
dest->Rectangle(shadowGfxRect);
|
||||
}
|
||||
dest->Fill();
|
||||
|
||||
if (dest == aDestinationCtx)
|
||||
return;
|
||||
|
||||
if (preTransformed) {
|
||||
aDestinationCtx->IdentityMatrix();
|
||||
}
|
||||
|
||||
blur.Paint(aDestinationCtx);
|
||||
gfxIntSize blurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel, scaleX, scaleY);
|
||||
|
||||
gfxRect dirtyRect =
|
||||
nsLayoutUtils::RectToGfxRect(aDirtyRect, aAppUnitsPerDevPixel);
|
||||
dirtyRect.RoundOut();
|
||||
|
||||
shadowGfxRect = transform.TransformBounds(shadowGfxRect);
|
||||
dirtyRect = transform.TransformBounds(dirtyRect);
|
||||
gfxRect skipRect = transform.TransformBounds(aSkipRect);
|
||||
|
||||
if (aCornerRadii) {
|
||||
aCornerRadii->Scale(scaleX, scaleY);
|
||||
}
|
||||
|
||||
gfxAlphaBoxBlur::BlurRectangle(aDestinationCtx,
|
||||
shadowGfxRect,
|
||||
aCornerRadii,
|
||||
blurRadius,
|
||||
aShadowColor,
|
||||
dirtyRect,
|
||||
skipRect);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user