summaryrefslogtreecommitdiffstats
path: root/gfx/2d/Blur.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/2d/Blur.h198
1 files changed, 198 insertions, 0 deletions
diff --git a/gfx/2d/Blur.h b/gfx/2d/Blur.h
new file mode 100644
index 0000000000..e0f18c4c39
--- /dev/null
+++ b/gfx/2d/Blur.h
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 MOZILLA_GFX_BLUR_H_
+#define MOZILLA_GFX_BLUR_H_
+
+#include "mozilla/gfx/Rect.h"
+#include "mozilla/gfx/Point.h"
+#include "mozilla/CheckedInt.h"
+
+namespace mozilla {
+namespace gfx {
+
+#ifdef _MSC_VER
+# pragma warning(disable : 4251)
+#endif
+
+/**
+ * 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.
+ *
+ * This is a "service" class; the constructors set up all the information
+ * based on the values and compute the minimum size for an 8-bit alpha
+ * channel context.
+ * The callers are responsible for creating and managing the backing surface
+ * and passing the pointer to the data to the Blur() method. This class does
+ * not retain the pointer to the data outside of the Blur() call.
+ *
+ * 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.
+ */
+class GFX2D_API AlphaBoxBlur final {
+ public:
+ /** Constructs a box blur and computes the backing surface size.
+ *
+ * @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.
+ */
+ AlphaBoxBlur(const Rect& aRect, const IntSize& aSpreadRadius,
+ const IntSize& aBlurRadius, const Rect* aDirtyRect,
+ const Rect* aSkipRect);
+
+ AlphaBoxBlur(const Rect& aRect, int32_t aStride, float aSigmaX,
+ float aSigmaY);
+
+ AlphaBoxBlur();
+
+ void Init(const Rect& aRect, const IntSize& aSpreadRadius,
+ const IntSize& aBlurRadius, const Rect* aDirtyRect,
+ const Rect* aSkipRect);
+
+ ~AlphaBoxBlur();
+
+ /**
+ * Return the size, in pixels, of the 8-bit alpha surface we'd use.
+ */
+ IntSize GetSize() const;
+
+ /**
+ * Return the stride, in bytes, of the 8-bit alpha surface we'd use.
+ */
+ int32_t GetStride() const;
+
+ /**
+ * Returns the device-space rectangle the 8-bit alpha surface covers.
+ */
+ IntRect GetRect() const;
+
+ /**
+ * Return a pointer to a dirty rect, as passed in to the constructor, or
+ * nullptr if none was passed in.
+ */
+ Rect* GetDirtyRect();
+
+ /**
+ * Return the spread radius, in pixels.
+ */
+ IntSize GetSpreadRadius() const { return mSpreadRadius; }
+
+ /**
+ * Return the blur radius, in pixels.
+ */
+ IntSize GetBlurRadius() const { return mBlurRadius; }
+
+ /**
+ * Return the minimum buffer size that should be given to Blur() method. If
+ * zero, the class is not properly setup for blurring. Note that this
+ * includes the extra three bytes on top of the stride*width, where something
+ * like gfxImageSurface::GetDataSize() would report without it, even if it
+ * happens to have the extra bytes.
+ */
+ size_t GetSurfaceAllocationSize() const;
+
+ /**
+ * Perform the blur in-place on the surface backed by specified 8-bit
+ * alpha surface data. The size must be at least that returned by
+ * GetSurfaceAllocationSize() or bad things will happen.
+ */
+ void Blur(uint8_t* aData) const;
+
+ /**
+ * 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 AlphaBoxBlur's
+ * constructor, above.
+ */
+ static IntSize CalculateBlurRadius(const Point& aStandardDeviation);
+ static Float CalculateBlurSigma(int32_t aBlurRadius);
+
+ private:
+ void BoxBlur_C(uint8_t* aData, int32_t aLeftLobe, int32_t aRightLobe,
+ int32_t aTopLobe, int32_t aBottomLobe,
+ uint32_t* aIntegralImage, size_t aIntegralImageStride) const;
+ void BoxBlur_SSE2(uint8_t* aData, int32_t aLeftLobe, int32_t aRightLobe,
+ int32_t aTopLobe, int32_t aBottomLobe,
+ uint32_t* aIntegralImage,
+ size_t aIntegralImageStride) const;
+ void BoxBlur_NEON(uint8_t* aData, int32_t aLeftLobe, int32_t aRightLobe,
+ int32_t aTopLobe, int32_t aBottomLobe,
+ uint32_t* aIntegralImage,
+ size_t aIntegralImageStride) const;
+#ifdef _MIPS_ARCH_LOONGSON3A
+ void BoxBlur_LS3(uint8_t* aData, int32_t aLeftLobe, int32_t aRightLobe,
+ int32_t aTopLobe, int32_t aBottomLobe,
+ uint32_t* aIntegralImage, size_t aIntegralImageStride) const;
+#endif
+
+ static CheckedInt<int32_t> RoundUpToMultipleOf4(int32_t aVal);
+
+ /**
+ * A rect indicating the area where blurring is unnecessary, and the blur
+ * algorithm should skip over it.
+ *
+ * This is guaranteed to be 4-pixel aligned in the x axis.
+ */
+ IntRect mSkipRect;
+
+ /**
+ * The device-space rectangle the the backing 8-bit alpha surface covers.
+ */
+ IntRect mRect;
+
+ /**
+ * A copy of the dirty rect passed to the constructor. This will only be valid
+ * if mHasDirtyRect is true.
+ */
+ Rect mDirtyRect;
+
+ /**
+ * The spread radius, in pixels.
+ */
+ IntSize mSpreadRadius;
+
+ /**
+ * The blur radius, in pixels.
+ */
+ IntSize mBlurRadius;
+
+ /**
+ * The stride of the data passed to Blur()
+ */
+ int32_t mStride;
+
+ /**
+ * The minimum size of the buffer needed for the Blur() operation.
+ */
+ size_t mSurfaceAllocationSize;
+
+ /**
+ * Whether mDirtyRect contains valid data.
+ */
+ bool mHasDirtyRect;
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif /* MOZILLA_GFX_BLUR_H_ */