DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (b6d82b1a6b02)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
/* -*- 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.
   */
  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_ */