// 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. static uint8_t* create_circle_profile(float sigma, float circleR, int profileTextureWidth) { const int numSteps = profileTextureWidth; uint8_t* weights = new uint8_t[numSteps]; // The full kernel is 6 sigmas wide. int halfKernelSize = SkScalarCeilToInt(6.0f * sigma); // round up to next multiple of 2 and then divide by 2 halfKernelSize = ((halfKernelSize + 1) & ~1) >> 1; // Number of x steps at which to apply kernel in y to cover all the profile samples in x. int numYSteps = numSteps + 2 * halfKernelSize; SkAutoTArray<float> bulkAlloc(halfKernelSize + halfKernelSize + numYSteps); float* halfKernel = bulkAlloc.get(); float* summedKernel = bulkAlloc.get() + halfKernelSize; float* yEvals = bulkAlloc.get() + 2 * halfKernelSize; make_half_kernel_and_summed_table(halfKernel, summedKernel, halfKernelSize, sigma); float firstX = -halfKernelSize + 0.5f; apply_kernel_in_y(yEvals, numYSteps, firstX, circleR, halfKernelSize, summedKernel); for (int i = 0; i < numSteps - 1; ++i) { float evalX = i + 0.5f; weights[i] = eval_at(evalX, circleR, halfKernel, halfKernelSize, yEvals + i); } // Ensure the tail of the Gaussian goes to zero. weights[numSteps - 1] = 0; return weights; }
BOOST_FORCEINLINE result_type eval(const A0& a0,const A1& a1,const A2& a2, boost::mpl::int_<0> const&) const { return eval_at( boost::fusion::at_c<0>(a0) , boost::fusion::at_c<0>(a1) , boost::fusion::at_c<0>(a2) ); }
template<class N> BOOST_FORCEINLINE result_type eval(const A0& a0,const A1& a1,const A2& a2, N const&) const { return l_and( eval(a0,a1,a2, boost::mpl::int_<N::value-1>()) , eval_at ( boost::fusion::at_c<N::value>(a0) , boost::fusion::at_c<N::value>(a1) , boost::fusion::at_c<N::value>(a2) ) ); }
static uint8_t* create_profile(float halfWH, float sigma) { int kernelWH = SkScalarCeilToInt(6.0f*sigma); kernelWH = (kernelWH + 1) & ~1; // make it the next even number up SkAutoTArray<float> halfKernel(kernelWH*kernelWH/2); make_half_kernel(halfKernel.get(), kernelWH, sigma); float offset; int numSteps; compute_profile_offset_and_size(halfWH, sigma, &offset, &numSteps); uint8_t* weights = new uint8_t[numSteps]; for (int i = 0; i < numSteps; ++i) { weights[i] = eval_at(offset+i, halfWH, halfKernel.get(), kernelWH); } return weights; }