GrConvolutionEffect::GrConvolutionEffect(GrTexture* texture, Direction direction, int radius, float gaussianSigma, bool useBounds, float bounds[2]) : INHERITED(texture, direction, radius), fUseBounds(useBounds) { this->initClassID<GrConvolutionEffect>(); SkASSERT(radius <= kMaxKernelRadius); int width = this->width(); float sum = 0.0f; float denom = 1.0f / (2.0f * gaussianSigma * gaussianSigma); for (int i = 0; i < width; ++i) { float x = static_cast<float>(i - this->radius()); // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian // is dropped here, since we renormalize the kernel below. fKernel[i] = sk_float_exp(- x * x * denom); sum += fKernel[i]; } // Normalize the kernel float scale = 1.0f / sum; for (int i = 0; i < width; ++i) { fKernel[i] *= scale; } memcpy(fBounds, bounds, sizeof(fBounds)); }
static void fill_in_2D_gaussian_kernel(float* kernel, int width, int height, SkScalar sigmaX, SkScalar sigmaY) { SkASSERT(width * height <= MAX_KERNEL_SIZE); const float sigmaXDenom = 1.0f / (2.0f * SkScalarToFloat(SkScalarSquare(sigmaX))); const float sigmaYDenom = 1.0f / (2.0f * SkScalarToFloat(SkScalarSquare(sigmaY))); const int xRadius = width / 2; const int yRadius = height / 2; float sum = 0.0f; for (int x = 0; x < width; x++) { float xTerm = static_cast<float>(x - xRadius); xTerm = xTerm * xTerm * sigmaXDenom; for (int y = 0; y < height; y++) { float yTerm = static_cast<float>(y - yRadius); float xyTerm = sk_float_exp(-(xTerm + yTerm * yTerm * sigmaYDenom)); // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian // is dropped here, since we renormalize the kernel below. kernel[y * width + x] = xyTerm; sum += xyTerm; } } // Normalize the kernel float scale = 1.0f / sum; for (int i = 0; i < width * height; ++i) { kernel[i] *= scale; } }
bool FlingState::evaluateMatrix(SkMatrix* matrix) { if (!fActive) { return false; } const float t = getseconds() - fTime0; const float MIN_SPEED = 2; const float K0 = 5.0; const float K1 = 0.02; const float speed = fSpeed0 * (sk_float_exp(- K0 * t) - K1); if (speed <= MIN_SPEED) { fActive = false; return false; } float dist = (fSpeed0 - speed) / K0; // printf("---- time %g speed %g dist %g\n", t, speed, dist); float tx = fDirection.fX * dist; float ty = fDirection.fY * dist; if (DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER) { tx = sk_float_round2int(tx); ty = sk_float_round2int(ty); } matrix->setTranslate(tx, ty); // printf("---- evaluate (%g %g)\n", tx, ty); return true; }
// Static function to create a 2D convolution GrFragmentProcessor* GrMatrixConvolutionEffect::CreateGaussian(GrTexture* texture, const SkIRect& bounds, const SkISize& kernelSize, SkScalar gain, SkScalar bias, const SkIPoint& kernelOffset, GrTextureDomain::Mode tileMode, bool convolveAlpha, SkScalar sigmaX, SkScalar sigmaY) { float kernel[MAX_KERNEL_SIZE]; int width = kernelSize.width(); int height = kernelSize.height(); SkASSERT(width * height <= MAX_KERNEL_SIZE); float sum = 0.0f; float sigmaXDenom = 1.0f / (2.0f * SkScalarToFloat(SkScalarSquare(sigmaX))); float sigmaYDenom = 1.0f / (2.0f * SkScalarToFloat(SkScalarSquare(sigmaY))); int xRadius = width / 2; int yRadius = height / 2; for (int x = 0; x < width; x++) { float xTerm = static_cast<float>(x - xRadius); xTerm = xTerm * xTerm * sigmaXDenom; for (int y = 0; y < height; y++) { float yTerm = static_cast<float>(y - yRadius); float xyTerm = sk_float_exp(-(xTerm + yTerm * yTerm * sigmaYDenom)); // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian // is dropped here, since we renormalize the kernel below. kernel[y * width + x] = xyTerm; sum += xyTerm; } } // Normalize the kernel float scale = 1.0f / sum; for (int i = 0; i < width * height; ++i) { kernel[i] *= scale; } return new GrMatrixConvolutionEffect(texture, bounds, kernelSize, kernel, gain, bias, kernelOffset, tileMode, convolveAlpha); }