/* * Copyright 2023 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "src/gpu/BlurUtils.h" #include "include/core/SkBitmap.h" #include "include/core/SkColorPriv.h" #include "include/core/SkImageInfo.h" #include "include/core/SkRRect.h" #include "include/core/SkRect.h" #include "include/core/SkScalar.h" #include "include/core/SkSize.h" #include "include/private/base/SkAssert.h" #include "include/private/base/SkFloatingPoint.h" #include "include/private/base/SkMath.h" #include "include/private/base/SkPoint_impl.h" #include "include/private/base/SkTemplates.h" #include "include/private/base/SkTo.h" #include "src/base/SkMathPriv.h" #include <algorithm> #include <cmath> #include <cstdint> #include <cstring> #include <memory> #include <vector> namespace skgpu { /////////////////////////////////////////////////////////////////////////////// // Rect Blur /////////////////////////////////////////////////////////////////////////////// // TODO: it seems like there should be some synergy with SkBlurMask::ComputeBlurProfile SkBitmap CreateIntegralTable(int width) { … } int ComputeIntegralTableWidth(float sixSigma) { … } /////////////////////////////////////////////////////////////////////////////// // Circle Blur /////////////////////////////////////////////////////////////////////////////// // Computes an unnormalized half kernel (right side). Returns the summation of all the half // kernel values. static float make_unnormalized_half_kernel(float* halfKernel, int halfKernelSize, float sigma) { … } // Create a Gaussian half-kernel (right side) and a summed area table given a sigma and number // of discrete steps. The half kernel is normalized to sum to 0.5. static void make_half_kernel_and_summed_table(float* halfKernel, float* summedHalfKernel, int halfKernelSize, float sigma) { … } // Applies the 1D half kernel vertically at points along the x axis to a circle centered at the // origin with radius circleR. static void apply_kernel_in_y(float* results, int numSteps, float firstX, float circleR, int halfKernelSize, const float* summedHalfKernelTable) { … } // Apply a Gaussian at point (evalX, 0) to a circle centered at the origin with radius circleR. // This relies on having a half kernel computed for the Gaussian and a table of applications of // the half kernel in y to columns at (evalX - halfKernel, evalX - halfKernel + 1, ..., evalX + // halfKernel) passed in as yKernelEvaluations. static uint8_t eval_at(float evalX, float circleR, const float* halfKernel, int halfKernelSize, const float* yKernelEvaluations) { … } // This function creates a profile of a blurred circle. It does this by computing a kernel for // half the Gaussian and a matching summed area table. The summed area table is used to compute // an array of vertical applications of the half kernel to the circle along the x axis. The // table of y evaluations has 2 * k + n entries where k is the size of the half kernel and n is // the size of the profile being computed. Then for each of the n profile entries we walk out k // steps in each horizontal direction multiplying the corresponding y evaluation by the half // kernel entry and sum these values to compute the profile entry. SkBitmap CreateCircleProfile(float sigma, float radius, int profileWidth) { … } SkBitmap CreateHalfPlaneProfile(int profileWidth) { … } /////////////////////////////////////////////////////////////////////////////// // RRect Blur /////////////////////////////////////////////////////////////////////////////// // Evaluate the vertical blur at the specified 'y' value given the location of the top of the // rrect. static uint8_t eval_V(float top, int y, const uint8_t* integral, int integralSize, float sixSigma) { … } // Apply a gaussian 'kernel' horizontally at the specified 'x', 'y' location. static uint8_t eval_H(int x, int y, const std::vector<float>& topVec, const float* kernel, int kernelSize, const uint8_t* integral, int integralSize, float sixSigma) { … } SkBitmap CreateRRectBlurMask(const SkRRect& rrectToDraw, const SkISize& dimensions, float sigma) { … } } // namespace skgpu