| Index: src/effects/gradients/SkTwoPointRadialGradient.cpp
|
| diff --git a/src/effects/gradients/SkTwoPointRadialGradient.cpp b/src/effects/gradients/SkTwoPointRadialGradient.cpp
|
| deleted file mode 100644
|
| index 44b73d6a3e256a78d77c4be7a26c0c41f24e8429..0000000000000000000000000000000000000000
|
| --- a/src/effects/gradients/SkTwoPointRadialGradient.cpp
|
| +++ /dev/null
|
| @@ -1,724 +0,0 @@
|
| -
|
| -/*
|
| - * Copyright 2012 Google Inc.
|
| - *
|
| - * Use of this source code is governed by a BSD-style license that can be
|
| - * found in the LICENSE file.
|
| - */
|
| -
|
| -#include "SkTwoPointRadialGradient.h"
|
| -
|
| -/* Two-point radial gradients are specified by two circles, each with a center
|
| - point and radius. The gradient can be considered to be a series of
|
| - concentric circles, with the color interpolated from the start circle
|
| - (at t=0) to the end circle (at t=1).
|
| -
|
| - For each point (x, y) in the span, we want to find the
|
| - interpolated circle that intersects that point. The center
|
| - of the desired circle (Cx, Cy) falls at some distance t
|
| - along the line segment between the start point (Sx, Sy) and
|
| - end point (Ex, Ey):
|
| -
|
| - Cx = (1 - t) * Sx + t * Ex (0 <= t <= 1)
|
| - Cy = (1 - t) * Sy + t * Ey
|
| -
|
| - The radius of the desired circle (r) is also a linear interpolation t
|
| - between the start and end radii (Sr and Er):
|
| -
|
| - r = (1 - t) * Sr + t * Er
|
| -
|
| - But
|
| -
|
| - (x - Cx)^2 + (y - Cy)^2 = r^2
|
| -
|
| - so
|
| -
|
| - (x - ((1 - t) * Sx + t * Ex))^2
|
| - + (y - ((1 - t) * Sy + t * Ey))^2
|
| - = ((1 - t) * Sr + t * Er)^2
|
| -
|
| - Solving for t yields
|
| -
|
| - [(Sx - Ex)^2 + (Sy - Ey)^2 - (Er - Sr)^2)] * t^2
|
| - + [2 * (Sx - Ex)(x - Sx) + 2 * (Sy - Ey)(y - Sy) - 2 * (Er - Sr) * Sr] * t
|
| - + [(x - Sx)^2 + (y - Sy)^2 - Sr^2] = 0
|
| -
|
| - To simplify, let Dx = Sx - Ex, Dy = Sy - Ey, Dr = Er - Sr, dx = x - Sx, dy = y - Sy
|
| -
|
| - [Dx^2 + Dy^2 - Dr^2)] * t^2
|
| - + 2 * [Dx * dx + Dy * dy - Dr * Sr] * t
|
| - + [dx^2 + dy^2 - Sr^2] = 0
|
| -
|
| - A quadratic in t. The two roots of the quadratic reflect the two
|
| - possible circles on which the point may fall. Solving for t yields
|
| - the gradient value to use.
|
| -
|
| - If a<0, the start circle is entirely contained in the
|
| - end circle, and one of the roots will be <0 or >1 (off the line
|
| - segment). If a>0, the start circle falls at least partially
|
| - outside the end circle (or vice versa), and the gradient
|
| - defines a "tube" where a point may be on one circle (on the
|
| - inside of the tube) or the other (outside of the tube). We choose
|
| - one arbitrarily.
|
| -
|
| - In order to keep the math to within the limits of fixed point,
|
| - we divide the entire quadratic by Dr^2, and replace
|
| - (x - Sx)/Dr with x' and (y - Sy)/Dr with y', giving
|
| -
|
| - [Dx^2 / Dr^2 + Dy^2 / Dr^2 - 1)] * t^2
|
| - + 2 * [x' * Dx / Dr + y' * Dy / Dr - Sr / Dr] * t
|
| - + [x'^2 + y'^2 - Sr^2/Dr^2] = 0
|
| -
|
| - (x' and y' are computed by appending the subtract and scale to the
|
| - fDstToIndex matrix in the constructor).
|
| -
|
| - Since the 'A' component of the quadratic is independent of x' and y', it
|
| - is precomputed in the constructor. Since the 'B' component is linear in
|
| - x' and y', if x and y are linear in the span, 'B' can be computed
|
| - incrementally with a simple delta (db below). If it is not (e.g.,
|
| - a perspective projection), it must be computed in the loop.
|
| -
|
| -*/
|
| -
|
| -namespace {
|
| -
|
| -inline SkFixed two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
|
| - SkScalar sr2d2, SkScalar foura,
|
| - SkScalar oneOverTwoA, bool posRoot) {
|
| - SkScalar c = SkScalarSquare(fx) + SkScalarSquare(fy) - sr2d2;
|
| - if (0 == foura) {
|
| - return SkScalarToFixed(SkScalarDiv(-c, b));
|
| - }
|
| -
|
| - SkScalar discrim = SkScalarSquare(b) - SkScalarMul(foura, c);
|
| - if (discrim < 0) {
|
| - discrim = -discrim;
|
| - }
|
| - SkScalar rootDiscrim = SkScalarSqrt(discrim);
|
| - SkScalar result;
|
| - if (posRoot) {
|
| - result = SkScalarMul(-b + rootDiscrim, oneOverTwoA);
|
| - } else {
|
| - result = SkScalarMul(-b - rootDiscrim, oneOverTwoA);
|
| - }
|
| - return SkScalarToFixed(result);
|
| -}
|
| -
|
| -typedef void (* TwoPointRadialShadeProc)(SkScalar fx, SkScalar dx,
|
| - SkScalar fy, SkScalar dy,
|
| - SkScalar b, SkScalar db,
|
| - SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
|
| - SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
|
| - int count);
|
| -
|
| -void shadeSpan_twopoint_clamp(SkScalar fx, SkScalar dx,
|
| - SkScalar fy, SkScalar dy,
|
| - SkScalar b, SkScalar db,
|
| - SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
|
| - SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
|
| - int count) {
|
| - for (; count > 0; --count) {
|
| - SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
|
| - fOneOverTwoA, posRoot);
|
| - SkFixed index = SkClampMax(t, 0xFFFF);
|
| - SkASSERT(index <= 0xFFFF);
|
| - *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift];
|
| - fx += dx;
|
| - fy += dy;
|
| - b += db;
|
| - }
|
| -}
|
| -void shadeSpan_twopoint_mirror(SkScalar fx, SkScalar dx,
|
| - SkScalar fy, SkScalar dy,
|
| - SkScalar b, SkScalar db,
|
| - SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
|
| - SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
|
| - int count) {
|
| - for (; count > 0; --count) {
|
| - SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
|
| - fOneOverTwoA, posRoot);
|
| - SkFixed index = mirror_tileproc(t);
|
| - SkASSERT(index <= 0xFFFF);
|
| - *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift];
|
| - fx += dx;
|
| - fy += dy;
|
| - b += db;
|
| - }
|
| -}
|
| -
|
| -void shadeSpan_twopoint_repeat(SkScalar fx, SkScalar dx,
|
| - SkScalar fy, SkScalar dy,
|
| - SkScalar b, SkScalar db,
|
| - SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
|
| - SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
|
| - int count) {
|
| - for (; count > 0; --count) {
|
| - SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
|
| - fOneOverTwoA, posRoot);
|
| - SkFixed index = repeat_tileproc(t);
|
| - SkASSERT(index <= 0xFFFF);
|
| - *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift];
|
| - fx += dx;
|
| - fy += dy;
|
| - b += db;
|
| - }
|
| -}
|
| -}
|
| -
|
| -/////////////////////////////////////////////////////////////////////
|
| -
|
| -static SkMatrix pts_to_unit(const SkPoint& start, SkScalar diffRadius) {
|
| - SkScalar inv = diffRadius ? SkScalarInvert(diffRadius) : 0;
|
| - SkMatrix matrix;
|
| - matrix.setTranslate(-start.fX, -start.fY);
|
| - matrix.postScale(inv, inv);
|
| - return matrix;
|
| -}
|
| -
|
| -SkTwoPointRadialGradient::SkTwoPointRadialGradient(const SkPoint& start, SkScalar startRadius,
|
| - const SkPoint& end, SkScalar endRadius,
|
| - const Descriptor& desc)
|
| - : SkGradientShaderBase(desc, pts_to_unit(start, endRadius - startRadius))
|
| - , fCenter1(start)
|
| - , fCenter2(end)
|
| - , fRadius1(startRadius)
|
| - , fRadius2(endRadius)
|
| -{
|
| - fDiff = fCenter1 - fCenter2;
|
| - fDiffRadius = fRadius2 - fRadius1;
|
| - // hack to avoid zero-divide for now
|
| - SkScalar inv = fDiffRadius ? SkScalarInvert(fDiffRadius) : 0;
|
| - fDiff.fX = SkScalarMul(fDiff.fX, inv);
|
| - fDiff.fY = SkScalarMul(fDiff.fY, inv);
|
| - fStartRadius = SkScalarMul(fRadius1, inv);
|
| - fSr2D2 = SkScalarSquare(fStartRadius);
|
| - fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SK_Scalar1;
|
| - fOneOverTwoA = fA ? SkScalarInvert(fA * 2) : 0;
|
| -}
|
| -
|
| -SkShader::BitmapType SkTwoPointRadialGradient::asABitmap(
|
| - SkBitmap* bitmap,
|
| - SkMatrix* matrix,
|
| - SkShader::TileMode* xy) const {
|
| - if (bitmap) {
|
| - this->getGradientTableBitmap(bitmap);
|
| - }
|
| - SkScalar diffL = 0; // just to avoid gcc warning
|
| - if (matrix) {
|
| - diffL = SkScalarSqrt(SkScalarSquare(fDiff.fX) +
|
| - SkScalarSquare(fDiff.fY));
|
| - }
|
| - if (matrix) {
|
| - if (diffL) {
|
| - SkScalar invDiffL = SkScalarInvert(diffL);
|
| - matrix->setSinCos(-SkScalarMul(invDiffL, fDiff.fY),
|
| - SkScalarMul(invDiffL, fDiff.fX));
|
| - } else {
|
| - matrix->reset();
|
| - }
|
| - matrix->preConcat(fPtsToUnit);
|
| - }
|
| - if (xy) {
|
| - xy[0] = fTileMode;
|
| - xy[1] = kClamp_TileMode;
|
| - }
|
| - return kTwoPointRadial_BitmapType;
|
| -}
|
| -
|
| -SkShader::GradientType SkTwoPointRadialGradient::asAGradient(
|
| - SkShader::GradientInfo* info) const {
|
| - if (info) {
|
| - commonAsAGradient(info);
|
| - info->fPoint[0] = fCenter1;
|
| - info->fPoint[1] = fCenter2;
|
| - info->fRadius[0] = fRadius1;
|
| - info->fRadius[1] = fRadius2;
|
| - }
|
| - return kRadial2_GradientType;
|
| -}
|
| -
|
| -size_t SkTwoPointRadialGradient::contextSize() const {
|
| - return sizeof(TwoPointRadialGradientContext);
|
| -}
|
| -
|
| -SkShader::Context* SkTwoPointRadialGradient::onCreateContext(const ContextRec& rec,
|
| - void* storage) const {
|
| - // For now, we might have divided by zero, so detect that.
|
| - if (0 == fDiffRadius) {
|
| - return NULL;
|
| - }
|
| - return SkNEW_PLACEMENT_ARGS(storage, TwoPointRadialGradientContext, (*this, rec));
|
| -}
|
| -
|
| -SkTwoPointRadialGradient::TwoPointRadialGradientContext::TwoPointRadialGradientContext(
|
| - const SkTwoPointRadialGradient& shader, const ContextRec& rec)
|
| - : INHERITED(shader, rec)
|
| -{
|
| - // we don't have a span16 proc
|
| - fFlags &= ~kHasSpan16_Flag;
|
| -}
|
| -
|
| -void SkTwoPointRadialGradient::TwoPointRadialGradientContext::shadeSpan(
|
| - int x, int y, SkPMColor* dstCParam, int count) {
|
| - SkASSERT(count > 0);
|
| -
|
| - const SkTwoPointRadialGradient& twoPointRadialGradient =
|
| - static_cast<const SkTwoPointRadialGradient&>(fShader);
|
| -
|
| - SkPMColor* SK_RESTRICT dstC = dstCParam;
|
| -
|
| - // Zero difference between radii: fill with transparent black.
|
| - if (twoPointRadialGradient.fDiffRadius == 0) {
|
| - sk_bzero(dstC, count * sizeof(*dstC));
|
| - return;
|
| - }
|
| - SkMatrix::MapXYProc dstProc = fDstToIndexProc;
|
| - TileProc proc = twoPointRadialGradient.fTileProc;
|
| - const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
|
| -
|
| - SkScalar foura = twoPointRadialGradient.fA * 4;
|
| - bool posRoot = twoPointRadialGradient.fDiffRadius < 0;
|
| - if (fDstToIndexClass != kPerspective_MatrixClass) {
|
| - SkPoint srcPt;
|
| - dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
|
| - SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
|
| - SkScalar dx, fx = srcPt.fX;
|
| - SkScalar dy, fy = srcPt.fY;
|
| -
|
| - if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
|
| - SkFixed fixedX, fixedY;
|
| - (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY);
|
| - dx = SkFixedToScalar(fixedX);
|
| - dy = SkFixedToScalar(fixedY);
|
| - } else {
|
| - SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
|
| - dx = fDstToIndex.getScaleX();
|
| - dy = fDstToIndex.getSkewY();
|
| - }
|
| - SkScalar b = (SkScalarMul(twoPointRadialGradient.fDiff.fX, fx) +
|
| - SkScalarMul(twoPointRadialGradient.fDiff.fY, fy) -
|
| - twoPointRadialGradient.fStartRadius) * 2;
|
| - SkScalar db = (SkScalarMul(twoPointRadialGradient.fDiff.fX, dx) +
|
| - SkScalarMul(twoPointRadialGradient.fDiff.fY, dy)) * 2;
|
| -
|
| - TwoPointRadialShadeProc shadeProc = shadeSpan_twopoint_repeat;
|
| - if (SkShader::kClamp_TileMode == twoPointRadialGradient.fTileMode) {
|
| - shadeProc = shadeSpan_twopoint_clamp;
|
| - } else if (SkShader::kMirror_TileMode == twoPointRadialGradient.fTileMode) {
|
| - shadeProc = shadeSpan_twopoint_mirror;
|
| - } else {
|
| - SkASSERT(SkShader::kRepeat_TileMode == twoPointRadialGradient.fTileMode);
|
| - }
|
| - (*shadeProc)(fx, dx, fy, dy, b, db,
|
| - twoPointRadialGradient.fSr2D2, foura,
|
| - twoPointRadialGradient.fOneOverTwoA, posRoot,
|
| - dstC, cache, count);
|
| - } else { // perspective case
|
| - SkScalar dstX = SkIntToScalar(x);
|
| - SkScalar dstY = SkIntToScalar(y);
|
| - for (; count > 0; --count) {
|
| - SkPoint srcPt;
|
| - dstProc(fDstToIndex, dstX, dstY, &srcPt);
|
| - SkScalar fx = srcPt.fX;
|
| - SkScalar fy = srcPt.fY;
|
| - SkScalar b = (SkScalarMul(twoPointRadialGradient.fDiff.fX, fx) +
|
| - SkScalarMul(twoPointRadialGradient.fDiff.fY, fy) -
|
| - twoPointRadialGradient.fStartRadius) * 2;
|
| - SkFixed t = two_point_radial(b, fx, fy, twoPointRadialGradient.fSr2D2, foura,
|
| - twoPointRadialGradient.fOneOverTwoA, posRoot);
|
| - SkFixed index = proc(t);
|
| - SkASSERT(index <= 0xFFFF);
|
| - *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift];
|
| - dstX += SK_Scalar1;
|
| - }
|
| - }
|
| -}
|
| -
|
| -#ifndef SK_IGNORE_TO_STRING
|
| -void SkTwoPointRadialGradient::toString(SkString* str) const {
|
| - str->append("SkTwoPointRadialGradient: (");
|
| -
|
| - str->append("center1: (");
|
| - str->appendScalar(fCenter1.fX);
|
| - str->append(", ");
|
| - str->appendScalar(fCenter1.fY);
|
| - str->append(") radius1: ");
|
| - str->appendScalar(fRadius1);
|
| - str->append(" ");
|
| -
|
| - str->append("center2: (");
|
| - str->appendScalar(fCenter2.fX);
|
| - str->append(", ");
|
| - str->appendScalar(fCenter2.fY);
|
| - str->append(") radius2: ");
|
| - str->appendScalar(fRadius2);
|
| - str->append(" ");
|
| -
|
| - this->INHERITED::toString(str);
|
| -
|
| - str->append(")");
|
| -}
|
| -#endif
|
| -
|
| -SkFlattenable* SkTwoPointRadialGradient::CreateProc(SkReadBuffer& buffer) {
|
| - DescriptorScope desc;
|
| - if (!desc.unflatten(buffer)) {
|
| - return NULL;
|
| - }
|
| - const SkPoint c1 = buffer.readPoint();
|
| - const SkPoint c2 = buffer.readPoint();
|
| - const SkScalar r1 = buffer.readScalar();
|
| - const SkScalar r2 = buffer.readScalar();
|
| - return SkGradientShader::CreateTwoPointRadial(c1, r1, c2, r2, desc.fColors, desc.fPos,
|
| - desc.fCount, desc.fTileMode, desc.fGradFlags,
|
| - desc.fLocalMatrix);
|
| -}
|
| -
|
| -void SkTwoPointRadialGradient::flatten(
|
| - SkWriteBuffer& buffer) const {
|
| - this->INHERITED::flatten(buffer);
|
| - buffer.writePoint(fCenter1);
|
| - buffer.writePoint(fCenter2);
|
| - buffer.writeScalar(fRadius1);
|
| - buffer.writeScalar(fRadius2);
|
| -}
|
| -
|
| -/////////////////////////////////////////////////////////////////////
|
| -
|
| -#if SK_SUPPORT_GPU
|
| -
|
| -#include "SkGr.h"
|
| -#include "gl/builders/GrGLProgramBuilder.h"
|
| -
|
| -// For brevity
|
| -typedef GrGLProgramDataManager::UniformHandle UniformHandle;
|
| -
|
| -class GrGLRadial2Gradient : public GrGLGradientEffect {
|
| -
|
| -public:
|
| -
|
| - GrGLRadial2Gradient(const GrProcessor&);
|
| - virtual ~GrGLRadial2Gradient() { }
|
| -
|
| - virtual void emitCode(GrGLFPBuilder*,
|
| - const GrFragmentProcessor&,
|
| - const char* outputColor,
|
| - const char* inputColor,
|
| - const TransformedCoordsArray&,
|
| - const TextureSamplerArray&) override;
|
| - void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
|
| -
|
| - static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
|
| -
|
| -protected:
|
| -
|
| - UniformHandle fParamUni;
|
| -
|
| - const char* fVSVaryingName;
|
| - const char* fFSVaryingName;
|
| -
|
| - bool fIsDegenerate;
|
| -
|
| - // @{
|
| - /// Values last uploaded as uniforms
|
| -
|
| - SkScalar fCachedCenter;
|
| - SkScalar fCachedRadius;
|
| - bool fCachedPosRoot;
|
| -
|
| - // @}
|
| -
|
| -private:
|
| -
|
| - typedef GrGLGradientEffect INHERITED;
|
| -
|
| -};
|
| -
|
| -/////////////////////////////////////////////////////////////////////
|
| -
|
| -class GrRadial2Gradient : public GrGradientEffect {
|
| -public:
|
| - static GrFragmentProcessor* Create(GrContext* ctx,
|
| - const SkTwoPointRadialGradient& shader,
|
| - const SkMatrix& matrix,
|
| - SkShader::TileMode tm) {
|
| - return SkNEW_ARGS(GrRadial2Gradient, (ctx, shader, matrix, tm));
|
| - }
|
| -
|
| - virtual ~GrRadial2Gradient() { }
|
| -
|
| - const char* name() const override { return "Two-Point Radial Gradient"; }
|
| -
|
| - virtual void getGLProcessorKey(const GrGLSLCaps& caps,
|
| - GrProcessorKeyBuilder* b) const override {
|
| - GrGLRadial2Gradient::GenKey(*this, caps, b);
|
| - }
|
| -
|
| - GrGLFragmentProcessor* createGLInstance() const override {
|
| - return SkNEW_ARGS(GrGLRadial2Gradient, (*this));
|
| - }
|
| -
|
| - // The radial gradient parameters can collapse to a linear (instead of quadratic) equation.
|
| - bool isDegenerate() const { return SK_Scalar1 == fCenterX1; }
|
| - SkScalar center() const { return fCenterX1; }
|
| - SkScalar radius() const { return fRadius0; }
|
| - bool isPosRoot() const { return SkToBool(fPosRoot); }
|
| -
|
| -private:
|
| - bool onIsEqual(const GrFragmentProcessor& sBase) const override {
|
| - const GrRadial2Gradient& s = sBase.cast<GrRadial2Gradient>();
|
| - return (INHERITED::onIsEqual(sBase) &&
|
| - this->fCenterX1 == s.fCenterX1 &&
|
| - this->fRadius0 == s.fRadius0 &&
|
| - this->fPosRoot == s.fPosRoot);
|
| - }
|
| -
|
| - GrRadial2Gradient(GrContext* ctx,
|
| - const SkTwoPointRadialGradient& shader,
|
| - const SkMatrix& matrix,
|
| - SkShader::TileMode tm)
|
| - : INHERITED(ctx, shader, matrix, tm)
|
| - , fCenterX1(shader.getCenterX1())
|
| - , fRadius0(shader.getStartRadius())
|
| - , fPosRoot(shader.getDiffRadius() < 0) {
|
| - this->initClassID<GrRadial2Gradient>();
|
| - // We pass the linear part of the quadratic as a varying.
|
| - // float b = 2.0 * (fCenterX1 * x - fRadius0 * z)
|
| - fBTransform = this->getCoordTransform();
|
| - SkMatrix& bMatrix = *fBTransform.accessMatrix();
|
| - bMatrix[SkMatrix::kMScaleX] = 2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMScaleX]) -
|
| - SkScalarMul(fRadius0, bMatrix[SkMatrix::kMPersp0]));
|
| - bMatrix[SkMatrix::kMSkewX] = 2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMSkewX]) -
|
| - SkScalarMul(fRadius0, bMatrix[SkMatrix::kMPersp1]));
|
| - bMatrix[SkMatrix::kMTransX] = 2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMTransX]) -
|
| - SkScalarMul(fRadius0, bMatrix[SkMatrix::kMPersp2]));
|
| - this->addCoordTransform(&fBTransform);
|
| - }
|
| -
|
| - GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
|
| -
|
| - // @{
|
| - // Cache of values - these can change arbitrarily, EXCEPT
|
| - // we shouldn't change between degenerate and non-degenerate?!
|
| -
|
| - GrCoordTransform fBTransform;
|
| - SkScalar fCenterX1;
|
| - SkScalar fRadius0;
|
| - SkBool8 fPosRoot;
|
| -
|
| - // @}
|
| -
|
| - typedef GrGradientEffect INHERITED;
|
| -};
|
| -
|
| -/////////////////////////////////////////////////////////////////////
|
| -
|
| -GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRadial2Gradient);
|
| -
|
| -GrFragmentProcessor* GrRadial2Gradient::TestCreate(SkRandom* random,
|
| - GrContext* context,
|
| - const GrDrawTargetCaps&,
|
| - GrTexture**) {
|
| - SkPoint center1 = {random->nextUScalar1(), random->nextUScalar1()};
|
| - SkScalar radius1 = random->nextUScalar1();
|
| - SkPoint center2;
|
| - SkScalar radius2;
|
| - do {
|
| - center2.set(random->nextUScalar1(), random->nextUScalar1());
|
| - radius2 = random->nextUScalar1 ();
|
| - // There is a bug in two point radial gradients with identical radii
|
| - } while (radius1 == radius2);
|
| -
|
| - SkColor colors[kMaxRandomGradientColors];
|
| - SkScalar stopsArray[kMaxRandomGradientColors];
|
| - SkScalar* stops = stopsArray;
|
| - SkShader::TileMode tm;
|
| - int colorCount = RandomGradientParams(random, colors, &stops, &tm);
|
| - SkAutoTUnref<SkShader> shader(SkGradientShader::CreateTwoPointRadial(center1, radius1,
|
| - center2, radius2,
|
| - colors, stops, colorCount,
|
| - tm));
|
| - SkPaint paint;
|
| - GrFragmentProcessor* fp;
|
| - GrColor paintColor;
|
| - SkAssertResult(shader->asFragmentProcessor(context, paint,
|
| - GrTest::TestMatrix(random), NULL,
|
| - &paintColor, &fp));
|
| - return fp;
|
| -}
|
| -
|
| -/////////////////////////////////////////////////////////////////////
|
| -
|
| -GrGLRadial2Gradient::GrGLRadial2Gradient(const GrProcessor& processor)
|
| - : fVSVaryingName(NULL)
|
| - , fFSVaryingName(NULL)
|
| - , fCachedCenter(SK_ScalarMax)
|
| - , fCachedRadius(-SK_ScalarMax)
|
| - , fCachedPosRoot(0) {
|
| -
|
| - const GrRadial2Gradient& data = processor.cast<GrRadial2Gradient>();
|
| - fIsDegenerate = data.isDegenerate();
|
| -}
|
| -
|
| -void GrGLRadial2Gradient::emitCode(GrGLFPBuilder* builder,
|
| - const GrFragmentProcessor& fp,
|
| - const char* outputColor,
|
| - const char* inputColor,
|
| - const TransformedCoordsArray& coords,
|
| - const TextureSamplerArray& samplers) {
|
| - const GrRadial2Gradient& ge = fp.cast<GrRadial2Gradient>();
|
| - this->emitUniforms(builder, ge);
|
| - fParamUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
|
| - kFloat_GrSLType, kDefault_GrSLPrecision,
|
| - "Radial2FSParams", 6);
|
| -
|
| - SkString cName("c");
|
| - SkString ac4Name("ac4");
|
| - SkString rootName("root");
|
| - SkString t;
|
| - SkString p0;
|
| - SkString p1;
|
| - SkString p2;
|
| - SkString p3;
|
| - SkString p4;
|
| - SkString p5;
|
| - builder->getUniformVariable(fParamUni).appendArrayAccess(0, &p0);
|
| - builder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1);
|
| - builder->getUniformVariable(fParamUni).appendArrayAccess(2, &p2);
|
| - builder->getUniformVariable(fParamUni).appendArrayAccess(3, &p3);
|
| - builder->getUniformVariable(fParamUni).appendArrayAccess(4, &p4);
|
| - builder->getUniformVariable(fParamUni).appendArrayAccess(5, &p5);
|
| -
|
| - GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
|
| - // We interpolate the linear component in coords[1].
|
| - SkASSERT(coords[0].getType() == coords[1].getType());
|
| - const char* coords2D;
|
| - SkString bVar;
|
| - if (kVec3f_GrSLType == coords[0].getType()) {
|
| - fsBuilder->codeAppendf("\tvec3 interpolants = vec3(%s.xy, %s.x) / %s.z;\n",
|
| - coords[0].c_str(), coords[1].c_str(), coords[0].c_str());
|
| - coords2D = "interpolants.xy";
|
| - bVar = "interpolants.z";
|
| - } else {
|
| - coords2D = coords[0].c_str();
|
| - bVar.printf("%s.x", coords[1].c_str());
|
| - }
|
| -
|
| - // c = (x^2)+(y^2) - params[4]
|
| - fsBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n",
|
| - cName.c_str(), coords2D, coords2D, p4.c_str());
|
| -
|
| - // If we aren't degenerate, emit some extra code, and accept a slightly
|
| - // more complex coord.
|
| - if (!fIsDegenerate) {
|
| -
|
| - // ac4 = 4.0 * params[0] * c
|
| - fsBuilder->codeAppendf("\tfloat %s = %s * 4.0 * %s;\n",
|
| - ac4Name.c_str(), p0.c_str(),
|
| - cName.c_str());
|
| -
|
| - // root = sqrt(b^2-4ac)
|
| - // (abs to avoid exception due to fp precision)
|
| - fsBuilder->codeAppendf("\tfloat %s = sqrt(abs(%s*%s - %s));\n",
|
| - rootName.c_str(), bVar.c_str(), bVar.c_str(),
|
| - ac4Name.c_str());
|
| -
|
| - // t is: (-b + params[5] * sqrt(b^2-4ac)) * params[1]
|
| - t.printf("(-%s + %s * %s) * %s", bVar.c_str(), p5.c_str(),
|
| - rootName.c_str(), p1.c_str());
|
| - } else {
|
| - // t is: -c/b
|
| - t.printf("-%s / %s", cName.c_str(), bVar.c_str());
|
| - }
|
| -
|
| - this->emitColor(builder, ge, t.c_str(), outputColor, inputColor, samplers);
|
| -}
|
| -
|
| -void GrGLRadial2Gradient::setData(const GrGLProgramDataManager& pdman,
|
| - const GrProcessor& processor) {
|
| - INHERITED::setData(pdman, processor);
|
| - const GrRadial2Gradient& data = processor.cast<GrRadial2Gradient>();
|
| - SkASSERT(data.isDegenerate() == fIsDegenerate);
|
| - SkScalar centerX1 = data.center();
|
| - SkScalar radius0 = data.radius();
|
| - if (fCachedCenter != centerX1 ||
|
| - fCachedRadius != radius0 ||
|
| - fCachedPosRoot != data.isPosRoot()) {
|
| -
|
| - SkScalar a = SkScalarMul(centerX1, centerX1) - SK_Scalar1;
|
| -
|
| - // When we're in the degenerate (linear) case, the second
|
| - // value will be INF but the program doesn't read it. (We
|
| - // use the same 6 uniforms even though we don't need them
|
| - // all in the linear case just to keep the code complexity
|
| - // down).
|
| - float values[6] = {
|
| - SkScalarToFloat(a),
|
| - 1 / (2.f * SkScalarToFloat(a)),
|
| - SkScalarToFloat(centerX1),
|
| - SkScalarToFloat(radius0),
|
| - SkScalarToFloat(SkScalarMul(radius0, radius0)),
|
| - data.isPosRoot() ? 1.f : -1.f
|
| - };
|
| -
|
| - pdman.set1fv(fParamUni, 6, values);
|
| - fCachedCenter = centerX1;
|
| - fCachedRadius = radius0;
|
| - fCachedPosRoot = data.isPosRoot();
|
| - }
|
| -}
|
| -
|
| -void GrGLRadial2Gradient::GenKey(const GrProcessor& processor,
|
| - const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
|
| - uint32_t* key = b->add32n(2);
|
| - key[0] = GenBaseGradientKey(processor);
|
| - key[1] = processor.cast<GrRadial2Gradient>().isDegenerate();
|
| -}
|
| -
|
| -/////////////////////////////////////////////////////////////////////
|
| -
|
| -bool SkTwoPointRadialGradient::asFragmentProcessor(GrContext* context, const SkPaint& paint,
|
| - const SkMatrix&,
|
| - const SkMatrix* localMatrix, GrColor* paintColor,
|
| - GrFragmentProcessor** fp) const {
|
| - SkASSERT(context);
|
| -
|
| - // invert the localM, translate to center1 (fPtsToUni), rotate so center2 is on x axis.
|
| - SkMatrix matrix;
|
| - if (!this->getLocalMatrix().invert(&matrix)) {
|
| - return false;
|
| - }
|
| - if (localMatrix) {
|
| - SkMatrix inv;
|
| - if (!localMatrix->invert(&inv)) {
|
| - return false;
|
| - }
|
| - matrix.postConcat(inv);
|
| - }
|
| - matrix.postConcat(fPtsToUnit);
|
| -
|
| - SkScalar diffLen = fDiff.length();
|
| - if (0 != diffLen) {
|
| - SkScalar invDiffLen = SkScalarInvert(diffLen);
|
| - SkMatrix rot;
|
| - rot.setSinCos(-SkScalarMul(invDiffLen, fDiff.fY),
|
| - SkScalarMul(invDiffLen, fDiff.fX));
|
| - matrix.postConcat(rot);
|
| - }
|
| -
|
| - *paintColor = SkColor2GrColorJustAlpha(paint.getColor());
|
| - *fp = GrRadial2Gradient::Create(context, *this, matrix, fTileMode);
|
| -
|
| - return true;
|
| -}
|
| -
|
| -#else
|
| -
|
| -bool SkTwoPointRadialGradient::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix&,
|
| - const SkMatrix*,
|
| - GrColor*, GrFragmentProcessor**) const {
|
| - SkDEBUGFAIL("Should not call in GPU-less build");
|
| - return false;
|
| -}
|
| -
|
| -#endif
|
|
|