1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef MOZILLA_GFX_BLUR_H_ 8 #define MOZILLA_GFX_BLUR_H_ 9 10 #include "mozilla/gfx/Rect.h" 11 #include "mozilla/gfx/Point.h" 12 #include "mozilla/CheckedInt.h" 13 14 namespace mozilla { 15 namespace gfx { 16 17 #ifdef _MSC_VER 18 # pragma warning(disable : 4251) 19 #endif 20 21 /** 22 * Implementation of a triple box blur approximation of a Gaussian blur. 23 * 24 * A Gaussian blur is good for blurring because, when done independently 25 * in the horizontal and vertical directions, it matches the result that 26 * would be obtained using a different (rotated) set of axes. A triple 27 * box blur is a very close approximation of a Gaussian. 28 * 29 * This is a "service" class; the constructors set up all the information 30 * based on the values and compute the minimum size for an 8-bit alpha 31 * channel context. 32 * The callers are responsible for creating and managing the backing surface 33 * and passing the pointer to the data to the Blur() method. This class does 34 * not retain the pointer to the data outside of the Blur() call. 35 * 36 * A spread N makes each output pixel the maximum value of all source 37 * pixels within a square of side length 2N+1 centered on the output pixel. 38 */ 39 class GFX2D_API AlphaBoxBlur final { 40 public: 41 /** Constructs a box blur and computes the backing surface size. 42 * 43 * @param aRect The coordinates of the surface to create in device units. 44 * 45 * @param aBlurRadius The blur radius in pixels. This is the radius of the 46 * entire (triple) kernel function. Each individual box blur has radius 47 * approximately 1/3 this value, or diameter approximately 2/3 this value. 48 * This parameter should nearly always be computed using 49 * CalculateBlurRadius, below. 50 * 51 * @param aDirtyRect A pointer to a dirty rect, measured in device units, if 52 * available. This will be used for optimizing the blur operation. It is 53 * safe to pass nullptr here. 54 * 55 * @param aSkipRect A pointer to a rect, measured in device units, that 56 * represents an area where blurring is unnecessary and shouldn't be done 57 * for speed reasons. It is safe to pass nullptr here. 58 */ 59 AlphaBoxBlur(const Rect& aRect, const IntSize& aSpreadRadius, 60 const IntSize& aBlurRadius, const Rect* aDirtyRect, 61 const Rect* aSkipRect); 62 63 AlphaBoxBlur(const Rect& aRect, int32_t aStride, float aSigmaX, 64 float aSigmaY); 65 66 AlphaBoxBlur(); 67 68 void Init(const Rect& aRect, const IntSize& aSpreadRadius, 69 const IntSize& aBlurRadius, const Rect* aDirtyRect, 70 const Rect* aSkipRect); 71 72 ~AlphaBoxBlur(); 73 74 /** 75 * Return the size, in pixels, of the 8-bit alpha surface we'd use. 76 */ 77 IntSize GetSize() const; 78 79 /** 80 * Return the stride, in bytes, of the 8-bit alpha surface we'd use. 81 */ 82 int32_t GetStride() const; 83 84 /** 85 * Returns the device-space rectangle the 8-bit alpha surface covers. 86 */ 87 IntRect GetRect() const; 88 89 /** 90 * Return a pointer to a dirty rect, as passed in to the constructor, or 91 * nullptr if none was passed in. 92 */ 93 Rect* GetDirtyRect(); 94 95 /** 96 * Return the spread radius, in pixels. 97 */ GetSpreadRadius()98 IntSize GetSpreadRadius() const { return mSpreadRadius; } 99 100 /** 101 * Return the blur radius, in pixels. 102 */ GetBlurRadius()103 IntSize GetBlurRadius() const { return mBlurRadius; } 104 105 /** 106 * Return the minimum buffer size that should be given to Blur() method. If 107 * zero, the class is not properly setup for blurring. Note that this 108 * includes the extra three bytes on top of the stride*width, where something 109 * like gfxImageSurface::GetDataSize() would report without it, even if it 110 * happens to have the extra bytes. 111 */ 112 size_t GetSurfaceAllocationSize() const; 113 114 /** 115 * Perform the blur in-place on the surface backed by specified 8-bit 116 * alpha surface data. The size must be at least that returned by 117 * GetSurfaceAllocationSize() or bad things will happen. 118 */ 119 void Blur(uint8_t* aData) const; 120 121 /** 122 * Calculates a blur radius that, when used with box blur, approximates a 123 * Gaussian blur with the given standard deviation. The result of this 124 * function should be used as the aBlurRadius parameter to AlphaBoxBlur's 125 * constructor, above. 126 */ 127 static IntSize CalculateBlurRadius(const Point& aStandardDeviation); 128 static Float CalculateBlurSigma(int32_t aBlurRadius); 129 130 private: 131 void BoxBlur_C(uint8_t* aData, int32_t aLeftLobe, int32_t aRightLobe, 132 int32_t aTopLobe, int32_t aBottomLobe, 133 uint32_t* aIntegralImage, size_t aIntegralImageStride) const; 134 void BoxBlur_SSE2(uint8_t* aData, int32_t aLeftLobe, int32_t aRightLobe, 135 int32_t aTopLobe, int32_t aBottomLobe, 136 uint32_t* aIntegralImage, 137 size_t aIntegralImageStride) const; 138 void BoxBlur_NEON(uint8_t* aData, int32_t aLeftLobe, int32_t aRightLobe, 139 int32_t aTopLobe, int32_t aBottomLobe, 140 uint32_t* aIntegralImage, 141 size_t aIntegralImageStride) const; 142 #ifdef _MIPS_ARCH_LOONGSON3A 143 void BoxBlur_LS3(uint8_t* aData, int32_t aLeftLobe, int32_t aRightLobe, 144 int32_t aTopLobe, int32_t aBottomLobe, 145 uint32_t* aIntegralImage, size_t aIntegralImageStride) const; 146 #endif 147 148 static CheckedInt<int32_t> RoundUpToMultipleOf4(int32_t aVal); 149 150 /** 151 * A rect indicating the area where blurring is unnecessary, and the blur 152 * algorithm should skip over it. 153 * 154 * This is guaranteed to be 4-pixel aligned in the x axis. 155 */ 156 IntRect mSkipRect; 157 158 /** 159 * The device-space rectangle the the backing 8-bit alpha surface covers. 160 */ 161 IntRect mRect; 162 163 /** 164 * A copy of the dirty rect passed to the constructor. This will only be valid 165 * if mHasDirtyRect is true. 166 */ 167 Rect mDirtyRect; 168 169 /** 170 * The spread radius, in pixels. 171 */ 172 IntSize mSpreadRadius; 173 174 /** 175 * The blur radius, in pixels. 176 */ 177 IntSize mBlurRadius; 178 179 /** 180 * The stride of the data passed to Blur() 181 */ 182 int32_t mStride; 183 184 /** 185 * The minimum size of the buffer needed for the Blur() operation. 186 */ 187 size_t mSurfaceAllocationSize; 188 189 /** 190 * Whether mDirtyRect contains valid data. 191 */ 192 bool mHasDirtyRect; 193 }; 194 195 } // namespace gfx 196 } // namespace mozilla 197 198 #endif /* MOZILLA_GFX_BLUR_H_ */ 199