Blur.h (6218B)
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/gfx/Types.h" 13 14 class SkSurface; 15 16 namespace mozilla { 17 namespace gfx { 18 19 class DrawTargetSkia; 20 21 #ifdef _MSC_VER 22 # pragma warning(disable : 4251) 23 #endif 24 25 /** 26 * Implementation of a Gaussian blur. 27 * 28 * A Gaussian blur is good for blurring because, when done independently 29 * in the horizontal and vertical directions, it matches the result that 30 * would be obtained using a different (rotated) set of axes. 31 * 32 * This is a "service" class; the constructors set up all the information 33 * based on the values. 34 * The callers are responsible for creating and managing the backing surface 35 * and passing the pointer to the data to the Blur() method. This class does 36 * not retain the pointer to the data outside of the Blur() call. 37 * 38 * A spread N makes each output pixel the maximum value of all source 39 * pixels within a square of side length 2N+1 centered on the output pixel. 40 */ 41 class GFX2D_API GaussianBlur final { 42 public: 43 /** Constructs a Gaussian blur and computes the backing surface size. 44 * 45 * @param aRect The coordinates of the surface to create in device units. 46 * 47 * @param aSigma The blur sigma. 48 * 49 * @param aDirtyRect A pointer to a dirty rect, measured in device units, if 50 * available. This will be used for optimizing the blur operation. It is 51 * safe to pass nullptr here. 52 * 53 * @param aSkipRect A pointer to a rect, measured in device units, that 54 * represents an area where blurring is unnecessary and shouldn't be done 55 * for speed reasons. It is safe to pass nullptr here. 56 * 57 * @param aFormat The format of the surface's data. 58 * 59 * @param aClamp Whether clamping at border pixels is required. 60 */ 61 GaussianBlur(const Rect& aRect, const IntSize& aSpreadRadius, 62 const Point& aSigma, const Rect* aDirtyRect, 63 const Rect* aSkipRect, SurfaceFormat aFormat = SurfaceFormat::A8, 64 bool aClamp = false); 65 66 explicit GaussianBlur(const Point& aSigma, bool aClamp = false); 67 68 GaussianBlur(); 69 70 void Init(const Rect& aRect, const IntSize& aSpreadRadius, 71 const Point& aBlurSigma, const Rect* aDirtyRect, 72 const Rect* aSkipRect, SurfaceFormat aFormat = SurfaceFormat::A8, 73 bool aClamp = false); 74 75 ~GaussianBlur(); 76 77 /** 78 * Return the size, in pixels, of the surface we'd use. 79 */ 80 IntSize GetSize() const; 81 82 /** 83 * Return the format of the blur data. 84 */ 85 SurfaceFormat GetFormat() const; 86 87 /** 88 * Return the stride, in bytes, of the surface we'd use. 89 */ 90 int32_t GetStride() const; 91 92 /** 93 * Returns the device-space rectangle the surface covers. 94 */ 95 IntRect GetRect() const; 96 97 /** 98 * Return a pointer to a dirty rect, as passed in to the constructor, or 99 * nullptr if none was passed in. 100 */ 101 Rect* GetDirtyRect(); 102 103 /** 104 * Return the spread radius, in pixels. 105 */ 106 IntSize GetSpreadRadius() const { return mSpreadRadius; } 107 108 /** 109 * Return the blur sigma. 110 */ 111 Point GetBlurSigma() const { return mBlurSigma; } 112 113 /** 114 * Return the blur radius, in pixels. 115 */ 116 IntSize GetBlurRadius() const { return mBlurRadius; } 117 118 /** 119 * Return the skip rect. 120 */ 121 IntRect GetSkipRect() const { return mSkipRect; } 122 123 /** 124 * Return the minimum buffer size that should be given to Blur() method. If 125 * zero, the class is not properly setup for blurring. Note that this 126 * includes the extra three bytes on top of the stride*width, where something 127 * like gfxImageSurface::GetDataSize() would report without it, even if it 128 * happens to have the extra bytes. 129 */ 130 size_t GetSurfaceAllocationSize() const; 131 132 /** 133 * Perform the blur in-place on the surface backed by specified surface data. 134 * The size must be at least that returned by GetSurfaceAllocationSize() or 135 * bad things will happen. 136 */ 137 void Blur(uint8_t* aData, int32_t aStride, const IntSize& aSize, 138 SurfaceFormat aFormat = SurfaceFormat::UNKNOWN) const; 139 140 /** 141 * Calculates a blur radius that, when used with box blur, approximates a 142 * Gaussian blur with the given standard deviation. The result of this 143 * function should be used as the aBlurRadius parameter to GaussianBlur's 144 * constructor, above. 145 */ 146 static IntSize CalculateBlurRadius(const Point& aStandardDeviation); 147 static Float CalculateBlurSigma(int32_t aBlurRadius); 148 149 private: 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 backing 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 sigma (standard deviation). 176 */ 177 Point mBlurSigma; 178 179 /** 180 * The blur radius, in pixels. 181 */ 182 IntSize mBlurRadius; 183 184 /** 185 * The format of the data passed to Blur() 186 */ 187 SurfaceFormat mFormat = SurfaceFormat::UNKNOWN; 188 189 /** 190 * Whether clamping at border pixels is required. 191 */ 192 bool mClamp = false; 193 194 /** 195 * The stride of the data passed to Blur() 196 */ 197 int32_t mStride = 0; 198 199 /** 200 * The minimum size of the buffer needed for the Blur() operation. 201 */ 202 size_t mSurfaceAllocationSize = 0; 203 204 /** 205 * Whether mDirtyRect contains valid data. 206 */ 207 bool mHasDirtyRect = false; 208 209 bool Spread(uint8_t* aData, int32_t aStride, const IntSize& aSize, 210 SurfaceFormat aFormat) const; 211 212 friend class DrawTargetSkia; 213 214 bool BlurSkSurface(SkSurface* aSurface) const; 215 }; 216 217 } // namespace gfx 218 } // namespace mozilla 219 220 #endif /* MOZILLA_GFX_BLUR_H_ */