Line data Source code
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
40 : {
41 : public:
42 :
43 : /** Constructs a box blur and computes the backing surface size.
44 : *
45 : * @param aRect The coordinates of the surface to create in device units.
46 : *
47 : * @param aBlurRadius The blur radius in pixels. This is the radius of the
48 : * entire (triple) kernel function. Each individual box blur has radius
49 : * approximately 1/3 this value, or diameter approximately 2/3 this value.
50 : * This parameter should nearly always be computed using CalculateBlurRadius,
51 : * below.
52 : *
53 : * @param aDirtyRect A pointer to a dirty rect, measured in device units, if
54 : * available. This will be used for optimizing the blur operation. It is
55 : * safe to pass nullptr here.
56 : *
57 : * @param aSkipRect A pointer to a rect, measured in device units, that
58 : * represents an area where blurring is unnecessary and shouldn't be done for
59 : * speed reasons. It is safe to pass nullptr here.
60 : */
61 : AlphaBoxBlur(const Rect& aRect,
62 : const IntSize& aSpreadRadius,
63 : const IntSize& aBlurRadius,
64 : const Rect* aDirtyRect,
65 : const Rect* aSkipRect);
66 :
67 : AlphaBoxBlur(const Rect& aRect,
68 : int32_t aStride,
69 : float aSigmaX,
70 : float aSigmaY);
71 :
72 : AlphaBoxBlur();
73 :
74 : void Init(const Rect& aRect,
75 : const IntSize& aSpreadRadius,
76 : const IntSize& aBlurRadius,
77 : const Rect* aDirtyRect,
78 : const Rect* aSkipRect);
79 :
80 : ~AlphaBoxBlur();
81 :
82 : /**
83 : * Return the size, in pixels, of the 8-bit alpha surface we'd use.
84 : */
85 : IntSize GetSize();
86 :
87 : /**
88 : * Return the stride, in bytes, of the 8-bit alpha surface we'd use.
89 : */
90 : int32_t GetStride();
91 :
92 : /**
93 : * Returns the device-space rectangle the 8-bit alpha surface covers.
94 : */
95 : IntRect GetRect();
96 :
97 : /**
98 : * Return a pointer to a dirty rect, as passed in to the constructor, or nullptr
99 : * 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 radius, in pixels.
110 : */
111 0 : IntSize GetBlurRadius() const { return mBlurRadius; }
112 :
113 : /**
114 : * Return the minimum buffer size that should be given to Blur() method. If
115 : * zero, the class is not properly setup for blurring. Note that this
116 : * includes the extra three bytes on top of the stride*width, where something
117 : * like gfxImageSurface::GetDataSize() would report without it, even if it
118 : * happens to have the extra bytes.
119 : */
120 : size_t GetSurfaceAllocationSize() const;
121 :
122 : /**
123 : * Perform the blur in-place on the surface backed by specified 8-bit
124 : * alpha surface data. The size must be at least that returned by
125 : * GetSurfaceAllocationSize() or bad things will happen.
126 : */
127 : void Blur(uint8_t* aData);
128 :
129 : /**
130 : * Calculates a blur radius that, when used with box blur, approximates a
131 : * Gaussian blur with the given standard deviation. The result of this
132 : * function should be used as the aBlurRadius parameter to AlphaBoxBlur's
133 : * constructor, above.
134 : */
135 : static IntSize CalculateBlurRadius(const Point& aStandardDeviation);
136 : static Float CalculateBlurSigma(int32_t aBlurRadius);
137 :
138 : private:
139 :
140 : void BoxBlur_C(uint8_t* aData,
141 : int32_t aLeftLobe, int32_t aRightLobe, int32_t aTopLobe,
142 : int32_t aBottomLobe, uint32_t *aIntegralImage, size_t aIntegralImageStride);
143 : void BoxBlur_SSE2(uint8_t* aData,
144 : int32_t aLeftLobe, int32_t aRightLobe, int32_t aTopLobe,
145 : int32_t aBottomLobe, uint32_t *aIntegralImage, size_t aIntegralImageStride);
146 : #ifdef BUILD_ARM_NEON
147 : void BoxBlur_NEON(uint8_t* aData,
148 : int32_t aLeftLobe, int32_t aRightLobe, int32_t aTopLobe,
149 : int32_t aBottomLobe, uint32_t *aIntegralImage, size_t aIntegralImageStride);
150 : #endif
151 : #ifdef _MIPS_ARCH_LOONGSON3A
152 : void BoxBlur_LS3(uint8_t* aData,
153 : int32_t aLeftLobe, int32_t aRightLobe, int32_t aTopLobe,
154 : int32_t aBottomLobe, uint32_t *aIntegralImage, size_t aIntegralImageStride);
155 : #endif
156 :
157 : static CheckedInt<int32_t> RoundUpToMultipleOf4(int32_t aVal);
158 :
159 : /**
160 : * A rect indicating the area where blurring is unnecessary, and the blur
161 : * algorithm should skip over it.
162 : */
163 : IntRect mSkipRect;
164 :
165 : /**
166 : * The device-space rectangle the the backing 8-bit alpha surface covers.
167 : */
168 : IntRect mRect;
169 :
170 : /**
171 : * A copy of the dirty rect passed to the constructor. This will only be valid if
172 : * mHasDirtyRect is true.
173 : */
174 : Rect mDirtyRect;
175 :
176 : /**
177 : * The spread radius, in pixels.
178 : */
179 : IntSize mSpreadRadius;
180 :
181 : /**
182 : * The blur radius, in pixels.
183 : */
184 : IntSize mBlurRadius;
185 :
186 : /**
187 : * The stride of the data passed to Blur()
188 : */
189 : int32_t mStride;
190 :
191 : /**
192 : * The minimum size of the buffer needed for the Blur() operation.
193 : */
194 : size_t mSurfaceAllocationSize;
195 :
196 : /**
197 : * Whether mDirtyRect contains valid data.
198 : */
199 : bool mHasDirtyRect;
200 : };
201 :
202 : } // namespace gfx
203 : } // namespace mozilla
204 :
205 : #endif /* MOZILLA_GFX_BLUR_H_ */
|