mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-21 06:37:30 +09:00
Issue #2364 - Re-factor AlphaBoxBlur
Only blur one quadrant of a box-shadow and mirror it to the other quadrants. This applies only if the corners are symmetrical (square corners or equal corner radii) otherwise we'll fall back to the old method.
This commit is contained in:
parent
8d42309580
commit
8d30faf95f
6 changed files with 556 additions and 351 deletions
|
|
@ -335,10 +335,26 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect,
|
||||||
const IntSize& aBlurRadius,
|
const IntSize& aBlurRadius,
|
||||||
const Rect* aDirtyRect,
|
const Rect* aDirtyRect,
|
||||||
const Rect* aSkipRect)
|
const Rect* aSkipRect)
|
||||||
: mSpreadRadius(aSpreadRadius),
|
: mSurfaceAllocationSize(0)
|
||||||
mBlurRadius(aBlurRadius),
|
|
||||||
mSurfaceAllocationSize(0)
|
|
||||||
{
|
{
|
||||||
|
Init(aRect, aSpreadRadius, aBlurRadius, aDirtyRect, aSkipRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
AlphaBoxBlur::AlphaBoxBlur()
|
||||||
|
: mSurfaceAllocationSize(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AlphaBoxBlur::Init(const Rect& aRect,
|
||||||
|
const IntSize& aSpreadRadius,
|
||||||
|
const IntSize& aBlurRadius,
|
||||||
|
const Rect* aDirtyRect,
|
||||||
|
const Rect* aSkipRect)
|
||||||
|
{
|
||||||
|
mSpreadRadius = aSpreadRadius;
|
||||||
|
mBlurRadius = aBlurRadius;
|
||||||
|
|
||||||
Rect rect(aRect);
|
Rect rect(aRect);
|
||||||
rect.Inflate(Size(aBlurRadius + aSpreadRadius));
|
rect.Inflate(Size(aBlurRadius + aSpreadRadius));
|
||||||
rect.RoundOut();
|
rect.RoundOut();
|
||||||
|
|
@ -355,8 +371,7 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect,
|
||||||
mHasDirtyRect = false;
|
mHasDirtyRect = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRect = IntRect(int32_t(rect.x), int32_t(rect.y),
|
mRect = TruncatedToInt(rect);
|
||||||
int32_t(rect.width), int32_t(rect.height));
|
|
||||||
if (mRect.IsEmpty()) {
|
if (mRect.IsEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -366,11 +381,8 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect,
|
||||||
// blurring/spreading we need to do. We convert it to IntRect to avoid
|
// blurring/spreading we need to do. We convert it to IntRect to avoid
|
||||||
// expensive int<->float conversions if we were to use Rect instead.
|
// expensive int<->float conversions if we were to use Rect instead.
|
||||||
Rect skipRect = *aSkipRect;
|
Rect skipRect = *aSkipRect;
|
||||||
skipRect.RoundIn();
|
|
||||||
skipRect.Deflate(Size(aBlurRadius + aSpreadRadius));
|
skipRect.Deflate(Size(aBlurRadius + aSpreadRadius));
|
||||||
mSkipRect = IntRect(int32_t(skipRect.x), int32_t(skipRect.y),
|
mSkipRect = RoundedIn(skipRect);
|
||||||
int32_t(skipRect.width), int32_t(skipRect.height));
|
|
||||||
|
|
||||||
mSkipRect = mSkipRect.Intersect(mRect);
|
mSkipRect = mSkipRect.Intersect(mRect);
|
||||||
if (mSkipRect.IsEqualInterior(mRect))
|
if (mSkipRect.IsEqualInterior(mRect))
|
||||||
return;
|
return;
|
||||||
|
|
@ -397,8 +409,7 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect,
|
||||||
int32_t aStride,
|
int32_t aStride,
|
||||||
float aSigmaX,
|
float aSigmaX,
|
||||||
float aSigmaY)
|
float aSigmaY)
|
||||||
: mRect(int32_t(aRect.x), int32_t(aRect.y),
|
: mRect(TruncatedToInt(aRect)),
|
||||||
int32_t(aRect.width), int32_t(aRect.height)),
|
|
||||||
mSpreadRadius(),
|
mSpreadRadius(),
|
||||||
mBlurRadius(CalculateBlurRadius(Point(aSigmaX, aSigmaY))),
|
mBlurRadius(CalculateBlurRadius(Point(aSigmaX, aSigmaY))),
|
||||||
mStride(aStride),
|
mStride(aStride),
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,14 @@ public:
|
||||||
float aSigmaX,
|
float aSigmaX,
|
||||||
float aSigmaY);
|
float aSigmaY);
|
||||||
|
|
||||||
|
AlphaBoxBlur();
|
||||||
|
|
||||||
|
void Init(const Rect& aRect,
|
||||||
|
const IntSize& aSpreadRadius,
|
||||||
|
const IntSize& aBlurRadius,
|
||||||
|
const Rect* aDirtyRect,
|
||||||
|
const Rect* aSkipRect);
|
||||||
|
|
||||||
~AlphaBoxBlur();
|
~AlphaBoxBlur();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -224,6 +224,15 @@ struct RectCornerRadii {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AreRadiiSame() const {
|
||||||
|
for (size_t i = 1; i < RectCorner::Count; i++) {
|
||||||
|
if (radii[i] != radii[0]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Scale(Float aXScale, Float aYScale) {
|
void Scale(Float aXScale, Float aYScale) {
|
||||||
for (int i = 0; i < RectCorner::Count; i++) {
|
for (int i = 0; i < RectCorner::Count; i++) {
|
||||||
radii[i].Scale(aXScale, aYScale);
|
radii[i].Scale(aXScale, aYScale);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -10,14 +10,13 @@
|
||||||
#include "nsSize.h"
|
#include "nsSize.h"
|
||||||
#include "gfxPoint.h"
|
#include "gfxPoint.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/gfx/Blur.h"
|
||||||
|
|
||||||
class gfxContext;
|
class gfxContext;
|
||||||
struct gfxRect;
|
struct gfxRect;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
class AlphaBoxBlur;
|
|
||||||
struct Color;
|
struct Color;
|
||||||
struct RectCornerRadii;
|
struct RectCornerRadii;
|
||||||
class SourceSurface;
|
class SourceSurface;
|
||||||
|
|
@ -73,21 +72,19 @@ public:
|
||||||
* represents an area where blurring is unnecessary and shouldn't be done
|
* represents an area where blurring is unnecessary and shouldn't be done
|
||||||
* for speed reasons. It is safe to pass nullptr here.
|
* for speed reasons. It is safe to pass nullptr here.
|
||||||
*/
|
*/
|
||||||
gfxContext* Init(const gfxRect& aRect,
|
already_AddRefed<gfxContext>
|
||||||
const mozilla::gfx::IntSize& aSpreadRadius,
|
Init(const gfxRect& aRect,
|
||||||
const mozilla::gfx::IntSize& aBlurRadius,
|
const mozilla::gfx::IntSize& aSpreadRadius,
|
||||||
const gfxRect* aDirtyRect,
|
const mozilla::gfx::IntSize& aBlurRadius,
|
||||||
const gfxRect* aSkipRect);
|
const gfxRect* aDirtyRect,
|
||||||
|
const gfxRect* aSkipRect);
|
||||||
|
|
||||||
/**
|
already_AddRefed<DrawTarget>
|
||||||
* Returns the context that should be drawn to supply the alpha mask to be
|
InitDrawTarget(const mozilla::gfx::Rect& aRect,
|
||||||
* blurred. If the returned surface is null, then there was an error in
|
const mozilla::gfx::IntSize& aSpreadRadius,
|
||||||
* its creation.
|
const mozilla::gfx::IntSize& aBlurRadius,
|
||||||
*/
|
const mozilla::gfx::Rect* aDirtyRect = nullptr,
|
||||||
gfxContext* GetContext()
|
const mozilla::gfx::Rect* aSkipRect = nullptr);
|
||||||
{
|
|
||||||
return mContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<mozilla::gfx::SourceSurface>
|
already_AddRefed<mozilla::gfx::SourceSurface>
|
||||||
DoBlur(DrawTarget* aDT, mozilla::gfx::IntPoint* aTopLeft);
|
DoBlur(DrawTarget* aDT, mozilla::gfx::IntPoint* aTopLeft);
|
||||||
|
|
@ -129,7 +126,7 @@ public:
|
||||||
*/
|
*/
|
||||||
static void BlurRectangle(gfxContext *aDestinationCtx,
|
static void BlurRectangle(gfxContext *aDestinationCtx,
|
||||||
const gfxRect& aRect,
|
const gfxRect& aRect,
|
||||||
RectCornerRadii* aCornerRadii,
|
const RectCornerRadii* aCornerRadii,
|
||||||
const gfxPoint& aBlurStdDev,
|
const gfxPoint& aBlurStdDev,
|
||||||
const Color& aShadowColor,
|
const Color& aShadowColor,
|
||||||
const gfxRect& aDirtyRect,
|
const gfxRect& aDirtyRect,
|
||||||
|
|
@ -154,41 +151,34 @@ public:
|
||||||
* @param aSKipRect An area in device pixels we don't have to paint in.
|
* @param aSKipRect An area in device pixels we don't have to paint in.
|
||||||
*/
|
*/
|
||||||
void BlurInsetBox(gfxContext* aDestinationCtx,
|
void BlurInsetBox(gfxContext* aDestinationCtx,
|
||||||
const mozilla::gfx::Rect aDestinationRect,
|
const mozilla::gfx::Rect& aDestinationRect,
|
||||||
const mozilla::gfx::Rect aShadowClipRect,
|
const mozilla::gfx::Rect& aShadowClipRect,
|
||||||
const mozilla::gfx::IntSize aBlurRadius,
|
const mozilla::gfx::IntSize& aBlurRadius,
|
||||||
const mozilla::gfx::IntSize aSpreadRadius,
|
|
||||||
const mozilla::gfx::Color& aShadowColor,
|
const mozilla::gfx::Color& aShadowColor,
|
||||||
const bool aHasBorderRadius,
|
const RectCornerRadii* aInnerClipRadii,
|
||||||
const RectCornerRadii& aInnerClipRadii,
|
const mozilla::gfx::Rect& aSkipRect,
|
||||||
const mozilla::gfx::Rect aSkipRect,
|
const mozilla::gfx::Point& aShadowOffset);
|
||||||
const mozilla::gfx::Point aShadowOffset);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
already_AddRefed<mozilla::gfx::SourceSurface>
|
already_AddRefed<mozilla::gfx::SourceSurface>
|
||||||
GetInsetBlur(const mozilla::gfx::Rect aOuterRect,
|
GetInsetBlur(const mozilla::gfx::Rect& aOuterRect,
|
||||||
const mozilla::gfx::Rect aWhitespaceRect,
|
const mozilla::gfx::Rect& aWhitespaceRect,
|
||||||
const bool aIsDestRect,
|
bool aIsDestRect,
|
||||||
const mozilla::gfx::Color& aShadowColor,
|
const mozilla::gfx::Color& aShadowColor,
|
||||||
const mozilla::gfx::IntSize& aBlurRadius,
|
const mozilla::gfx::IntSize& aBlurRadius,
|
||||||
const bool aHasBorderRadius,
|
const RectCornerRadii* aInnerClipRadii,
|
||||||
const RectCornerRadii& aInnerClipRadii,
|
DrawTarget* aDestDrawTarget,
|
||||||
DrawTarget* aDestDrawTarget);
|
bool aMirrorCorners);
|
||||||
|
|
||||||
/**
|
|
||||||
* The context of the temporary alpha surface.
|
|
||||||
*/
|
|
||||||
RefPtr<gfxContext> mContext;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The temporary alpha surface.
|
* The temporary alpha surface.
|
||||||
*/
|
*/
|
||||||
mozilla::UniquePtr<unsigned char[]> mData;
|
uint8_t* mData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The object that actually does the blurring for us.
|
* The object that actually does the blurring for us.
|
||||||
*/
|
*/
|
||||||
mozilla::UniquePtr<mozilla::gfx::AlphaBoxBlur> mBlur;
|
mozilla::gfx::AlphaBoxBlur mBlur;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* GFX_BLUR_H */
|
#endif /* GFX_BLUR_H */
|
||||||
|
|
|
||||||
|
|
@ -1631,7 +1631,6 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
|
||||||
// transparent in the shadow, so drawing them changes nothing.
|
// transparent in the shadow, so drawing them changes nothing.
|
||||||
gfxContext* renderContext = aRenderingContext.ThebesContext();
|
gfxContext* renderContext = aRenderingContext.ThebesContext();
|
||||||
DrawTarget* drawTarget = renderContext->GetDrawTarget();
|
DrawTarget* drawTarget = renderContext->GetDrawTarget();
|
||||||
nsContextBoxBlur blurringArea;
|
|
||||||
|
|
||||||
// Clip the context to the area of the frame's padding rect, so no part of the
|
// Clip the context to the area of the frame's padding rect, so no part of the
|
||||||
// shadow is painted outside. Also cut out anything beyond where the inset shadow
|
// shadow is painted outside. Also cut out anything beyond where the inset shadow
|
||||||
|
|
@ -6243,9 +6242,8 @@ nsContextBoxBlur::InsetBoxBlur(gfxContext* aDestinationCtx,
|
||||||
|
|
||||||
mAlphaBoxBlur.BlurInsetBox(aDestinationCtx, transformedDestRect,
|
mAlphaBoxBlur.BlurInsetBox(aDestinationCtx, transformedDestRect,
|
||||||
transformedShadowClipRect,
|
transformedShadowClipRect,
|
||||||
blurRadius, spreadRadius,
|
blurRadius, aShadowColor,
|
||||||
aShadowColor, aHasBorderRadius,
|
aHasBorderRadius ? &aInnerClipRectRadii : nullptr,
|
||||||
aInnerClipRectRadii, transformedSkipRect,
|
transformedSkipRect, aShadowOffset);
|
||||||
aShadowOffset);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue