/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef GFX_BLUR_H #define GFX_BLUR_H #include "gfxTypes.h" #include "gfxRect.h" #include "nsSize.h" #include "gfxPoint.h" #include "mozilla/RefPtr.h" #include "mozilla/gfx/Blur.h" class gfxContext; namespace mozilla { namespace gfx { struct sRGBColor; struct RectCornerRadii; class SourceSurface; class DrawTarget; } // namespace gfx } // namespace mozilla /** * Implementation of a triple box blur approximation of a Gaussian blur. * * A Gaussian blur is good for blurring because, when done independently * in the horizontal and vertical directions, it matches the result that * would be obtained using a different (rotated) set of axes. A triple * box blur is a very close approximation of a Gaussian. * * Creates an 8-bit alpha channel context for callers to draw in, * spreads the contents of that context, blurs the contents, and applies * it as an alpha mask on a different existing context. * * A spread N makes each output pixel the maximum value of all source * pixels within a square of side length 2N+1 centered on the output pixel. * * A temporary surface is created in the Init function. The caller then draws * any desired content onto the context acquired through GetContext, and lastly * calls Paint to apply the blurred content as an alpha mask. */ class gfxAlphaBoxBlur final { typedef mozilla::gfx::sRGBColor sRGBColor; typedef mozilla::gfx::DrawTarget DrawTarget; typedef mozilla::gfx::RectCornerRadii RectCornerRadii; public: gfxAlphaBoxBlur() = default; ~gfxAlphaBoxBlur(); /** * Constructs a box blur and initializes the temporary surface. * * @param aDestinationCtx The destination to blur to. * * @param aRect The coordinates of the surface to create in device units. * * @param aBlurRadius The blur radius in pixels. This is the radius of * the entire (triple) kernel function. Each individual box blur has * radius approximately 1/3 this value, or diameter approximately 2/3 * this value. This parameter should nearly always be computed using * CalculateBlurRadius, below. * * @param aDirtyRect A pointer to a dirty rect, measured in device units, * if available. This will be used for optimizing the blur operation. It * is safe to pass nullptr here. * * @param aSkipRect A pointer to a rect, measured in device units, that * represents an area where blurring is unnecessary and shouldn't be done * for speed reasons. It is safe to pass nullptr here. * * @param aUseHardwareAccel Flag to state whether or not we can use hardware * acceleration to speed up this blur. */ mozilla::UniquePtr Init( gfxContext* aDestinationCtx, const gfxRect& aRect, const mozilla::gfx::IntSize& aSpreadRadius, const mozilla::gfx::IntSize& aBlurRadius, const gfxRect* aDirtyRect, const gfxRect* aSkipRect, bool aUseHardwareAccel = true); already_AddRefed InitDrawTarget( const mozilla::gfx::DrawTarget* aReferenceDT, const mozilla::gfx::Rect& aRect, const mozilla::gfx::IntSize& aSpreadRadius, const mozilla::gfx::IntSize& aBlurRadius, const mozilla::gfx::Rect* aDirtyRect = nullptr, const mozilla::gfx::Rect* aSkipRect = nullptr, bool aUseHardwareAccel = true); /** * Performs the blur and optionally colors the result if aShadowColor is not * null. */ already_AddRefed DoBlur( const mozilla::gfx::sRGBColor* aShadowColor = nullptr, mozilla::gfx::IntPoint* aOutTopLeft = nullptr); /** * Does the actual blurring/spreading and mask applying. Users of this * object must have drawn whatever they want to be blurred onto the internal * gfxContext returned by GetContext before calling this. * * @param aDestinationCtx The graphics context on which to apply the * blurred mask. */ void Paint(gfxContext* aDestinationCtx); /** * Calculates a blur radius that, when used with box blur, approximates * a Gaussian blur with the given standard deviation. The result of * this function should be used as the aBlurRadius parameter to Init, * above. */ static mozilla::gfx::IntSize CalculateBlurRadius( const gfxPoint& aStandardDeviation); /** * Blurs a coloured rectangle onto aDestinationCtx. This is equivalent * to calling Init(), drawing a rectangle onto the returned surface * and then calling Paint, but may let us optimize better in the * backend. * * @param aDestinationCtx The destination to blur to. * @param aRect The rectangle to blur in device pixels. * @param aCornerRadii Corner radii for aRect, if it is a rounded * rectangle. * @param aBlurRadius The standard deviation of the blur. * @param aShadowColor The color to draw the blurred shadow. * @param aDirtyRect An area in device pixels that is dirty and * needs to be redrawn. * @param aSkipRect An area in device pixels to avoid blurring * over, to prevent unnecessary work. */ static void BlurRectangle(gfxContext* aDestinationCtx, const gfxRect& aRect, const RectCornerRadii* aCornerRadii, const gfxPoint& aBlurStdDev, const sRGBColor& aShadowColor, const gfxRect& aDirtyRect, const gfxRect& aSkipRect); static void ShutdownBlurCache(); /*** * Blurs an inset box shadow according to a given path. * This is equivalent to calling Init(), drawing the inset path, * and calling paint. Do not call Init() if using this method. * * @param aDestinationCtx The destination to blur to. * @param aDestinationRect The destination rect in device pixels * @param aShadowClipRect The destiniation inner rect of the * inset path in device pixels. * @param aBlurRadius The standard deviation of the blur. * @param aShadowColor The color of the blur. * @param aInnerClipRadii Corner radii for the inside rect if it is a * rounded rect. * @param aSkipRect An area in device pixels we don't have to * paint in. */ void BlurInsetBox(gfxContext* aDestinationCtx, const mozilla::gfx::Rect& aDestinationRect, const mozilla::gfx::Rect& aShadowClipRect, const mozilla::gfx::IntSize& aBlurRadius, const mozilla::gfx::sRGBColor& aShadowColor, const RectCornerRadii* aInnerClipRadii, const mozilla::gfx::Rect& aSkipRect, const mozilla::gfx::Point& aShadowOffset); protected: already_AddRefed GetInsetBlur( const mozilla::gfx::Rect& aOuterRect, const mozilla::gfx::Rect& aWhitespaceRect, bool aIsDestRect, const mozilla::gfx::sRGBColor& aShadowColor, const mozilla::gfx::IntSize& aBlurRadius, const RectCornerRadii* aInnerClipRadii, DrawTarget* aDestDrawTarget, bool aMirrorCorners); /** * The DrawTarget of the temporary alpha surface. */ RefPtr mDrawTarget; /** * The temporary alpha surface. */ uint8_t* mData = nullptr; /** * The object that actually does the blurring for us. */ mozilla::gfx::AlphaBoxBlur mBlur; /** * Indicates using DrawTarget-accelerated blurs. */ bool mAccelerated = false; }; #endif /* GFX_BLUR_H */