text: /*
   * Copyright 2013 Google Inc.
   *
   * Use of this source code is governed by a BSD-style license that can be
   * found in the LICENSE file.
   */
  
  #ifndef SkGpuBlurUtils_DEFINED
  #define SkGpuBlurUtils_DEFINED
  
  #include "include/core/SkTypes.h"
  
  #if SK_SUPPORT_GPU
  #include "include/core/SkRefCnt.h"
  #include "include/private/gpu/ganesh/GrTypesPriv.h"
  
  class GrRecordingContext;
  namespace skgpu { namespace v1 { class SurfaceDrawContext; }}
  class GrSurfaceProxyView;
  class GrTexture;
  
  struct SkRect;
  
  namespace SkGpuBlurUtils {
  
  /** Maximum sigma before the implementation downscales the input image. */
  static constexpr float kMaxSigma = 4.f;
  
  #if SK_GPU_V1
  /**
   * Applies a 2D Gaussian blur to a given texture. The blurred result is returned
   * as a surfaceDrawContext in case the caller wishes to draw into the result.
   * The GrSurfaceOrigin of the result will watch the GrSurfaceOrigin of srcView. The output
   * color type, color space, and alpha type will be the same as the src.
   *
   * Note: one of sigmaX and sigmaY should be non-zero!
   * @param context         The GPU context
   * @param srcView         The source to be blurred.
   * @param srcColorType    The colorType of srcProxy
   * @param srcAlphaType    The alphaType of srcProxy
   * @param srcColorSpace   Color space of the source.
   * @param dstBounds       The destination bounds, relative to the source texture.
   * @param srcBounds       The source bounds, relative to the source texture's offset. No pixels
   *                        will be sampled outside of this rectangle.
   * @param sigmaX          The blur's standard deviation in X.
   * @param sigmaY          The blur's standard deviation in Y.
   * @param tileMode        The mode to handle samples outside bounds.
   * @param fit             backing fit for the returned render target context
   * @return                The surfaceDrawContext containing the blurred result.
   */
  std::unique_ptr<skgpu::v1::SurfaceDrawContext> GaussianBlur(
          GrRecordingContext*,
          GrSurfaceProxyView srcView,
          GrColorType srcColorType,
          SkAlphaType srcAlphaType,
          sk_sp<SkColorSpace> srcColorSpace,
          SkIRect dstBounds,
          SkIRect srcBounds,
          float sigmaX,
          float sigmaY,
          SkTileMode mode,
          SkBackingFit fit = SkBackingFit::kApprox);
  #endif // SK_GPU_V1
  
  static const int kBlurRRectMaxDivisions = 6;
  
  // This method computes all the parameters for drawing a partially occluded nine-patched
  // blurred rrect mask:
  //   rrectToDraw - the integerized rrect to draw in the mask
  //   widthHeight - how large to make the mask (rrectToDraw will be centered in this coord sys)
  //   rectXs, rectYs - the x & y coordinates of the covering geometry lattice
  //   texXs, texYs - the texture coordinate at each point in rectXs & rectYs
  // It returns true if 'devRRect' is nine-patchable
  bool ComputeBlurredRRectParams(const SkRRect& srcRRect,
                                 const SkRRect& devRRect,
                                 SkScalar sigma,
                                 SkScalar xformedSigma,
                                 SkRRect* rrectToDraw,
                                 SkISize* widthHeight,
                                 SkScalar rectXs[kBlurRRectMaxDivisions],
                                 SkScalar rectYs[kBlurRRectMaxDivisions],
                                 SkScalar texXs[kBlurRRectMaxDivisions],
                                 SkScalar texYs[kBlurRRectMaxDivisions]);
  
  int CreateIntegralTable(float sixSigma, SkBitmap* table);
  
  void Compute1DGaussianKernel(float* kernel, float sigma, int radius);
  
  void Compute1DLinearGaussianKernel(float* kernel, float* offset, float sigma, int radius);
  
  // Any sigmas smaller than this are effectively an identity blur so can skip convolution at a higher
  // level. The value was chosen because it corresponds roughly to a radius of 1/10px, and is slightly
  // greater than sqrt(1/2*sigma^2) for SK_ScalarNearlyZero.
  inline bool IsEffectivelyZeroSigma(float sigma) { return sigma <= 0.03f; }
  
  inline int SigmaRadius(float sigma) {
      return IsEffectivelyZeroSigma(sigma) ? 0 : static_cast<int>(ceilf(sigma * 3.0f));
  }
  
  inline int KernelWidth(int radius) { return 2 * radius + 1; }
  
  inline int LinearKernelWidth(int radius) { return radius + 1; }
  
  }  // namespace SkGpuBlurUtils
  
  #endif // SK_SUPPORT_GPU
  
  #endif
  