diff options
Diffstat (limited to 'src/effects')
-rw-r--r-- | src/effects/gradients/SkGradientShader.cpp | 26 | ||||
-rw-r--r-- | src/effects/gradients/SkTwoPointRadialGradient.cpp | 724 | ||||
-rw-r--r-- | src/effects/gradients/SkTwoPointRadialGradient.h | 64 |
3 files changed, 0 insertions, 814 deletions
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp index eaa7e46f76..52731b395f 100644 --- a/src/effects/gradients/SkGradientShader.cpp +++ b/src/effects/gradients/SkGradientShader.cpp @@ -8,7 +8,6 @@ #include "SkGradientShaderPriv.h" #include "SkLinearGradient.h" #include "SkRadialGradient.h" -#include "SkTwoPointRadialGradient.h" #include "SkTwoPointConicalGradient.h" #include "SkSweepGradient.h" @@ -802,30 +801,6 @@ SkShader* SkGradientShader::CreateRadial(const SkPoint& center, SkScalar radius, return SkNEW_ARGS(SkRadialGradient, (center, radius, desc)); } -SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start, - SkScalar startRadius, - const SkPoint& end, - SkScalar endRadius, - const SkColor colors[], - const SkScalar pos[], - int colorCount, - SkShader::TileMode mode, - uint32_t flags, - const SkMatrix* localMatrix) { - if (startRadius < 0 || endRadius < 0) { - return NULL; - } - if (!valid_grad(colors, pos, colorCount, mode)) { - return NULL; - } - EXPAND_1_COLOR(colorCount); - - SkGradientShaderBase::Descriptor desc; - desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix); - return SkNEW_ARGS(SkTwoPointRadialGradient, - (start, startRadius, end, endRadius, desc)); -} - SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start, SkScalar startRadius, const SkPoint& end, @@ -897,7 +872,6 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLinearGradient) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRadialGradient) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSweepGradient) - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointRadialGradient) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointConicalGradient) SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END diff --git a/src/effects/gradients/SkTwoPointRadialGradient.cpp b/src/effects/gradients/SkTwoPointRadialGradient.cpp deleted file mode 100644 index 44b73d6a3e..0000000000 --- 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 diff --git a/src/effects/gradients/SkTwoPointRadialGradient.h b/src/effects/gradients/SkTwoPointRadialGradient.h deleted file mode 100644 index 7da85d6d88..0000000000 --- a/src/effects/gradients/SkTwoPointRadialGradient.h +++ /dev/null @@ -1,64 +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. - */ - - #ifndef SkTwoPointRadialGradient_DEFINED - #define SkTwoPointRadialGradient_DEFINED - - #include "SkGradientShaderPriv.h" - -class SkTwoPointRadialGradient : public SkGradientShaderBase { -public: - SkTwoPointRadialGradient(const SkPoint& start, SkScalar startRadius, - const SkPoint& end, SkScalar endRadius, - const Descriptor&); - - virtual BitmapType asABitmap(SkBitmap* bitmap, - SkMatrix* matrix, - TileMode* xy) const override; - GradientType asAGradient(GradientInfo* info) const override; - virtual bool asFragmentProcessor(GrContext* context, const SkPaint&, const SkMatrix& viewM, - const SkMatrix*, GrColor*, - GrFragmentProcessor**) const override; - - size_t contextSize() const override; - - class TwoPointRadialGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { - public: - TwoPointRadialGradientContext(const SkTwoPointRadialGradient&, const ContextRec&); - - void shadeSpan(int x, int y, SkPMColor dstC[], int count) override; - - private: - typedef SkGradientShaderBase::GradientShaderBaseContext INHERITED; - }; - - SkScalar getCenterX1() const { return fDiff.length(); } - SkScalar getStartRadius() const { return fStartRadius; } - SkScalar getDiffRadius() const { return fDiffRadius; } - - SK_TO_STRING_OVERRIDE() - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTwoPointRadialGradient) - -protected: - SkTwoPointRadialGradient(SkReadBuffer& buffer); - void flatten(SkWriteBuffer& buffer) const override; - Context* onCreateContext(const ContextRec&, void* storage) const override; - -private: - const SkPoint fCenter1; - const SkPoint fCenter2; - const SkScalar fRadius1; - const SkScalar fRadius2; - SkPoint fDiff; - SkScalar fStartRadius, fDiffRadius, fSr2D2, fA, fOneOverTwoA; - - friend class SkGradientShader; - typedef SkGradientShaderBase INHERITED; -}; - -#endif |