michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=8 sts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef MOZILLA_GFX_BLUR_H_ michael@0: #define MOZILLA_GFX_BLUR_H_ michael@0: michael@0: #include "mozilla/gfx/Rect.h" michael@0: #include "mozilla/gfx/Point.h" michael@0: #include "mozilla/CheckedInt.h" michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: michael@0: #ifdef _MSC_VER michael@0: #pragma warning( disable : 4251 ) michael@0: #endif michael@0: michael@0: /** michael@0: * Implementation of a triple box blur approximation of a Gaussian blur. michael@0: * michael@0: * A Gaussian blur is good for blurring because, when done independently michael@0: * in the horizontal and vertical directions, it matches the result that michael@0: * would be obtained using a different (rotated) set of axes. A triple michael@0: * box blur is a very close approximation of a Gaussian. michael@0: * michael@0: * This is a "service" class; the constructors set up all the information michael@0: * based on the values and compute the minimum size for an 8-bit alpha michael@0: * channel context. michael@0: * The callers are responsible for creating and managing the backing surface michael@0: * and passing the pointer to the data to the Blur() method. This class does michael@0: * not retain the pointer to the data outside of the Blur() call. michael@0: * michael@0: * A spread N makes each output pixel the maximum value of all source michael@0: * pixels within a square of side length 2N+1 centered on the output pixel. michael@0: */ michael@0: class GFX2D_API AlphaBoxBlur michael@0: { michael@0: public: michael@0: michael@0: /** Constructs a box blur and computes the backing surface size. michael@0: * michael@0: * @param aRect The coordinates of the surface to create in device units. michael@0: * michael@0: * @param aBlurRadius The blur radius in pixels. This is the radius of the michael@0: * entire (triple) kernel function. Each individual box blur has radius michael@0: * approximately 1/3 this value, or diameter approximately 2/3 this value. michael@0: * This parameter should nearly always be computed using CalculateBlurRadius, michael@0: * below. michael@0: * michael@0: * @param aDirtyRect A pointer to a dirty rect, measured in device units, if michael@0: * available. This will be used for optimizing the blur operation. It is michael@0: * safe to pass nullptr here. michael@0: * michael@0: * @param aSkipRect A pointer to a rect, measured in device units, that michael@0: * represents an area where blurring is unnecessary and shouldn't be done for michael@0: * speed reasons. It is safe to pass nullptr here. michael@0: */ michael@0: AlphaBoxBlur(const Rect& aRect, michael@0: const IntSize& aSpreadRadius, michael@0: const IntSize& aBlurRadius, michael@0: const Rect* aDirtyRect, michael@0: const Rect* aSkipRect); michael@0: michael@0: AlphaBoxBlur(const Rect& aRect, michael@0: int32_t aStride, michael@0: float aSigmaX, michael@0: float aSigmaY); michael@0: michael@0: ~AlphaBoxBlur(); michael@0: michael@0: /** michael@0: * Return the size, in pixels, of the 8-bit alpha surface we'd use. michael@0: */ michael@0: IntSize GetSize(); michael@0: michael@0: /** michael@0: * Return the stride, in bytes, of the 8-bit alpha surface we'd use. michael@0: */ michael@0: int32_t GetStride(); michael@0: michael@0: /** michael@0: * Returns the device-space rectangle the 8-bit alpha surface covers. michael@0: */ michael@0: IntRect GetRect(); michael@0: michael@0: /** michael@0: * Return a pointer to a dirty rect, as passed in to the constructor, or nullptr michael@0: * if none was passed in. michael@0: */ michael@0: Rect* GetDirtyRect(); michael@0: michael@0: /** michael@0: * Return the minimum buffer size that should be given to Blur() method. If michael@0: * zero, the class is not properly setup for blurring. Note that this michael@0: * includes the extra three bytes on top of the stride*width, where something michael@0: * like gfxImageSurface::GetDataSize() would report without it, even if it michael@0: * happens to have the extra bytes. michael@0: */ michael@0: size_t GetSurfaceAllocationSize() const; michael@0: michael@0: /** michael@0: * Perform the blur in-place on the surface backed by specified 8-bit michael@0: * alpha surface data. The size must be at least that returned by michael@0: * GetSurfaceAllocationSize() or bad things will happen. michael@0: */ michael@0: void Blur(uint8_t* aData); michael@0: michael@0: /** michael@0: * Calculates a blur radius that, when used with box blur, approximates a michael@0: * Gaussian blur with the given standard deviation. The result of this michael@0: * function should be used as the aBlurRadius parameter to AlphaBoxBlur's michael@0: * constructor, above. michael@0: */ michael@0: static IntSize CalculateBlurRadius(const Point& aStandardDeviation); michael@0: michael@0: private: michael@0: michael@0: void BoxBlur_C(uint8_t* aData, michael@0: int32_t aLeftLobe, int32_t aRightLobe, int32_t aTopLobe, michael@0: int32_t aBottomLobe, uint32_t *aIntegralImage, size_t aIntegralImageStride); michael@0: void BoxBlur_SSE2(uint8_t* aData, michael@0: int32_t aLeftLobe, int32_t aRightLobe, int32_t aTopLobe, michael@0: int32_t aBottomLobe, uint32_t *aIntegralImage, size_t aIntegralImageStride); michael@0: michael@0: static CheckedInt RoundUpToMultipleOf4(int32_t aVal); michael@0: michael@0: /** michael@0: * A rect indicating the area where blurring is unnecessary, and the blur michael@0: * algorithm should skip over it. michael@0: */ michael@0: IntRect mSkipRect; michael@0: michael@0: /** michael@0: * The device-space rectangle the the backing 8-bit alpha surface covers. michael@0: */ michael@0: IntRect mRect; michael@0: michael@0: /** michael@0: * A copy of the dirty rect passed to the constructor. This will only be valid if michael@0: * mHasDirtyRect is true. michael@0: */ michael@0: Rect mDirtyRect; michael@0: michael@0: /** michael@0: * The spread radius, in pixels. michael@0: */ michael@0: IntSize mSpreadRadius; michael@0: michael@0: /** michael@0: * The blur radius, in pixels. michael@0: */ michael@0: IntSize mBlurRadius; michael@0: michael@0: /** michael@0: * The stride of the data passed to Blur() michael@0: */ michael@0: int32_t mStride; michael@0: michael@0: /** michael@0: * The minimum size of the buffer needed for the Blur() operation. michael@0: */ michael@0: size_t mSurfaceAllocationSize; michael@0: michael@0: /** michael@0: * Whether mDirtyRect contains valid data. michael@0: */ michael@0: bool mHasDirtyRect; michael@0: }; michael@0: michael@0: } michael@0: } michael@0: michael@0: #endif /* MOZILLA_GFX_BLUR_H_ */