180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2012 Google Inc. 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTwoPointConicalGradient.h" 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int valid_divide(float numer, float denom, float* ratio) { 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(ratio); 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (0 == denom) { 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 0; 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *ratio = numer / denom; 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 1; 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Return the number of distinct real roots, and write them into roots[] in 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// ascending order 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int find_quad_roots(float A, float B, float C, float roots[2]) { 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(roots); 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (A == 0) { 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return valid_divide(-C, B, roots); 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float R = B*B - 4*A*C; 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (R < 0) { 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 0; 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru R = sk_float_sqrt(R); 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 1 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float Q = B; 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (Q < 0) { 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Q -= R; 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Q += R; 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // on 10.6 this was much slower than the above branch :( 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float Q = B + copysignf(R, B); 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Q *= -0.5f; 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (0 == Q) { 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru roots[0] = 0; 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 1; 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float r0 = Q / A; 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float r1 = C / Q; 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru roots[0] = r0 < r1 ? r0 : r1; 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru roots[1] = r0 > r1 ? r0 : r1; 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 2; 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic float lerp(float x, float dx, float t) { 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return x + t * dx; 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic float sqr(float x) { return x * x; } 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid TwoPtRadial::init(const SkPoint& center0, SkScalar rad0, 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPoint& center1, SkScalar rad1) { 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCenterX = SkScalarToFloat(center0.fX); 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCenterY = SkScalarToFloat(center0.fY); 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fDCenterX = SkScalarToFloat(center1.fX) - fCenterX; 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fDCenterY = SkScalarToFloat(center1.fY) - fCenterY; 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRadius = SkScalarToFloat(rad0); 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fDRadius = SkScalarToFloat(rad1) - fRadius; 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius); 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRadius2 = sqr(fRadius); 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRDR = fRadius * fDRadius; 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid TwoPtRadial::setup(SkScalar fx, SkScalar fy, SkScalar dfx, SkScalar dfy) { 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRelX = SkScalarToFloat(fx) - fCenterX; 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRelY = SkScalarToFloat(fy) - fCenterY; 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fIncX = SkScalarToFloat(dfx); 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fIncY = SkScalarToFloat(dfy); 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fB = -2 * (fDCenterX * fRelX + fDCenterY * fRelY + fRDR); 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fDB = -2 * (fDCenterX * fIncX + fDCenterY * fIncY); 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkFixed TwoPtRadial::nextT() { 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float roots[2]; 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float C = sqr(fRelX) + sqr(fRelY) - fRadius2; 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int countRoots = find_quad_roots(fA, fB, C, roots); 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRelX += fIncX; 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRelY += fIncY; 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fB += fDB; 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (0 == countRoots) { 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return kDontDrawT; 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Prefer the bigger t value if both give a radius(t) > 0 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // find_quad_roots returns the values sorted, so we start with the last 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float t = roots[countRoots - 1]; 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float r = lerp(fRadius, fDRadius, t); 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (r <= 0) { 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru t = roots[0]; // might be the same as roots[countRoots-1] 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru r = lerp(fRadius, fDRadius, t); 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (r <= 0) { 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return kDontDrawT; 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkFloatToFixed(t); 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 115096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergertypedef void (*TwoPointConicalProc)(TwoPtRadial* rec, SkPMColor* dstC, 116096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger const SkPMColor* cache, int toggle, int count); 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, 119096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger const SkPMColor* SK_RESTRICT cache, int toggle, 120096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger int count) { 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (; count > 0; --count) { 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkFixed t = rec->nextT(); 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (TwoPtRadial::DontDrawT(t)) { 12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dstC++ = 0; 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkFixed index = SkClampMax(t, 0xFFFF); 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(index <= 0xFFFF); 128096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *dstC++ = cache[toggle + 129096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger (index >> SkGradientShaderBase::kCache32Shift)]; 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 131096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger toggle = next_dither_toggle(toggle); 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, 136096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger const SkPMColor* SK_RESTRICT cache, int toggle, 137096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger int count) { 13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (; count > 0; --count) { 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkFixed t = rec->nextT(); 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (TwoPtRadial::DontDrawT(t)) { 14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dstC++ = 0; 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkFixed index = repeat_tileproc(t); 14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(index <= 0xFFFF); 145096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *dstC++ = cache[toggle + 146096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger (index >> SkGradientShaderBase::kCache32Shift)]; 14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 148096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger toggle = next_dither_toggle(toggle); 14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, 153096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger const SkPMColor* SK_RESTRICT cache, int toggle, 154096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger int count) { 15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (; count > 0; --count) { 15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkFixed t = rec->nextT(); 15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (TwoPtRadial::DontDrawT(t)) { 15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dstC++ = 0; 15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkFixed index = mirror_tileproc(t); 16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(index <= 0xFFFF); 162096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger *dstC++ = cache[toggle + 163096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger (index >> SkGradientShaderBase::kCache32Shift)]; 16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 165096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger toggle = next_dither_toggle(toggle); 16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkTwoPointConicalGradient::init() { 17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRec.init(fCenter1, fRadius1, fCenter2, fRadius2); 17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPtsToUnit.reset(); 17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////// 17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkTwoPointConicalGradient::SkTwoPointConicalGradient( 177779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger const SkPoint& start, SkScalar startRadius, 178779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger const SkPoint& end, SkScalar endRadius, 179779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger const Descriptor& desc) 180779bf8a99dc7f03e5c43b26d4b85d7920ce89aeeDerek Sollenberger : SkGradientShaderBase(desc), 18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCenter1(start), 18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCenter2(end), 18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRadius1(startRadius), 18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRadius2(endRadius) { 18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // this is degenerate, and should be caught by our caller 18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(fCenter1 != fCenter2 || fRadius1 != fRadius2); 18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->init(); 18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 190096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerbool SkTwoPointConicalGradient::isOpaque() const { 191096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // Because areas outside the cone are left untouched, we cannot treat the 192096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger // shader as opaque even if the gradient itself is opaque. 193e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // TODO(junov): Compute whether the cone fills the plane crbug.com/222380 194096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger return false; 195096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger} 196096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam, 19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int count) { 199096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger int toggle = init_dither_toggle(x, y); 200096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(count > 0); 20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPMColor* SK_RESTRICT dstC = dstCParam; 20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkMatrix::MapXYProc dstProc = fDstToIndexProc; 20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPMColor* SK_RESTRICT cache = this->getCache32(); 20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 209096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger TwoPointConicalProc shadeProc = twopoint_repeat; 21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (SkShader::kClamp_TileMode == fTileMode) { 21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru shadeProc = twopoint_clamp; 21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else if (SkShader::kMirror_TileMode == fTileMode) { 21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru shadeProc = twopoint_mirror; 21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(SkShader::kRepeat_TileMode == fTileMode); 21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fDstToIndexClass != kPerspective_MatrixClass) { 21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint srcPt; 22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, 22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar dx, fx = srcPt.fX; 22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar dy, fy = srcPt.fY; 22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fDstToIndexClass == kFixedStepInX_MatrixClass) { 22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkFixed fixedX, fixedY; 22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY); 22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dx = SkFixedToScalar(fixedX); 22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dy = SkFixedToScalar(fixedY); 23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(fDstToIndexClass == kLinear_MatrixClass); 23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dx = fDstToIndex.getScaleX(); 23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dy = fDstToIndex.getSkewY(); 23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRec.setup(fx, fy, dx, dy); 237096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger (*shadeProc)(&fRec, dstC, cache, toggle, count); 23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { // perspective case 239910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger SkScalar dstX = SkIntToScalar(x) + SK_ScalarHalf; 240910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger SkScalar dstY = SkIntToScalar(y) + SK_ScalarHalf; 24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (; count > 0; --count) { 24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint srcPt; 24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dstProc(fDstToIndex, dstX, dstY, &srcPt); 24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRec.setup(srcPt.fX, srcPt.fY, 0, 0); 245096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger (*shadeProc)(&fRec, dstC, cache, toggle, 1); 246910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 247910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger dstX += SK_Scalar1; 248096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger toggle = next_dither_toggle(toggle); 249910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger dstC += 1; 25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkTwoPointConicalGradient::setContext(const SkBitmap& device, 25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPaint& paint, 25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkMatrix& matrix) { 25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!this->INHERITED::setContext(device, paint, matrix)) { 25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // we don't have a span16 proc 26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fFlags &= ~kHasSpan16_Flag; 26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // in general, we might discard based on computed-radius, so clear 26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // this flag (todo: sometimes we can detect that we never discard...) 26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fFlags &= ~kOpaqueAlpha_Flag; 26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkShader::BitmapType SkTwoPointConicalGradient::asABitmap( 27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBitmap* bitmap, SkMatrix* matrix, SkShader::TileMode* xy) const { 27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint diff = fCenter2 - fCenter1; 27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar diffLen = 0; 27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (bitmap) { 27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->getGradientTableBitmap(bitmap); 27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (matrix) { 28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru diffLen = diff.length(); 28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (matrix) { 28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (diffLen) { 28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar invDiffLen = SkScalarInvert(diffLen); 28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // rotate to align circle centers with the x-axis 28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru matrix->setSinCos(-SkScalarMul(invDiffLen, diff.fY), 28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalarMul(invDiffLen, diff.fX)); 28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru matrix->reset(); 29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru matrix->preTranslate(-fCenter1.fX, -fCenter1.fY); 29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (xy) { 29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru xy[0] = fTileMode; 29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru xy[1] = kClamp_TileMode; 29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return kTwoPointConical_BitmapType; 29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkShader::GradientType SkTwoPointConicalGradient::asAGradient( 30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GradientInfo* info) const { 30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (info) { 30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru commonAsAGradient(info); 30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru info->fPoint[0] = fCenter1; 30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru info->fPoint[1] = fCenter2; 30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru info->fRadius[0] = fRadius1; 30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru info->fRadius[1] = fRadius2; 30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return kConical_GradientType; 31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkTwoPointConicalGradient::SkTwoPointConicalGradient( 31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkFlattenableReadBuffer& buffer) 31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru : INHERITED(buffer), 31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCenter1(buffer.readPoint()), 31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCenter2(buffer.readPoint()), 31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRadius1(buffer.readScalar()), 31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRadius2(buffer.readScalar()) { 31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->init(); 32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkTwoPointConicalGradient::flatten( 32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkFlattenableWriteBuffer& buffer) const { 32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->INHERITED::flatten(buffer); 32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru buffer.writePoint(fCenter1); 32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru buffer.writePoint(fCenter2); 32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru buffer.writeScalar(fRadius1); 32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru buffer.writeScalar(fRadius2); 32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////// 33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if SK_SUPPORT_GPU 33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 335363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "GrTBackendEffectFactory.h" 336363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// For brevity 33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutypedef GrGLUniformManager::UniformHandle UniformHandle; 33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 340363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerclass GrGLConical2Gradient : public GrGLGradientEffect { 34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic: 34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 343e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger GrGLConical2Gradient(const GrBackendEffectFactory& factory, const GrDrawEffect&); 34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru virtual ~GrGLConical2Gradient() { } 34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 346363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger virtual void emitCode(GrGLShaderBuilder*, 347e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger const GrDrawEffect&, 348363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger EffectKey, 349363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger const char* outputColor, 350363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger const char* inputColor, 3510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const TransformedCoordsArray&, 352363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger const TextureSamplerArray&) SK_OVERRIDE; 353e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; 35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 355e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps); 35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprotected: 35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3590a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger UniformHandle fParamUni; 36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const char* fVSVaryingName; 36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const char* fFSVaryingName; 36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool fIsDegenerate; 36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // @{ 36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /// Values last uploaded as uniforms 36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 369363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar fCachedCenter; 370363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar fCachedRadius; 371363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar fCachedDiffRadius; 37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // @} 37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate: 37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 377363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger typedef GrGLGradientEffect INHERITED; 37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////// 38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass GrConical2Gradient : public GrGradientEffect { 38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic: 38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 386d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger static GrEffectRef* Create(GrContext* ctx, 387d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger const SkTwoPointConicalGradient& shader, 388d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger const SkMatrix& matrix, 389d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger SkShader::TileMode tm) { 390d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger AutoEffectUnref effect(SkNEW_ARGS(GrConical2Gradient, (ctx, shader, matrix, tm))); 391d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return CreateEffectRef(effect); 392d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger } 39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru virtual ~GrConical2Gradient() { } 39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static const char* Name() { return "Two-Point Conical Gradient"; } 397363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 398363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger return GrTBackendEffectFactory<GrConical2Gradient>::getInstance(); 39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // The radial gradient parameters can collapse to a linear (instead of quadratic) equation. 40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool isDegenerate() const { return SkScalarAbs(fDiffRadius) == SkScalarAbs(fCenterX1); } 403363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar center() const { return fCenterX1; } 404363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar diffRadius() const { return fDiffRadius; } 405363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar radius() const { return fRadius0; } 40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 407363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger typedef GrGLConical2Gradient GLEffect; 40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate: 410d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE { 411d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger const GrConical2Gradient& s = CastEffect<GrConical2Gradient>(sBase); 412d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return (INHERITED::onIsEqual(sBase) && 413d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger this->fCenterX1 == s.fCenterX1 && 414d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger this->fRadius0 == s.fRadius0 && 415d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger this->fDiffRadius == s.fDiffRadius); 416d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger } 417d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 418d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger GrConical2Gradient(GrContext* ctx, 419d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger const SkTwoPointConicalGradient& shader, 420d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger const SkMatrix& matrix, 421d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger SkShader::TileMode tm) 422d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger : INHERITED(ctx, shader, matrix, tm) 423d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger , fCenterX1(shader.getCenterX1()) 424d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger , fRadius0(shader.getStartRadius()) 4250a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger , fDiffRadius(shader.getDiffRadius()) { 4260a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // We pass the linear part of the quadratic as a varying. 4270a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z) 4280a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger fBTransform = this->getCoordTransform(); 4290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkMatrix& bMatrix = *fBTransform.accessMatrix(); 4300a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkScalar r0dr = SkScalarMul(fRadius0, fDiffRadius); 4310a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger bMatrix[SkMatrix::kMScaleX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMScaleX]) + 4320a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp0])); 4330a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger bMatrix[SkMatrix::kMSkewX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMSkewX]) + 4340a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp1])); 4350a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger bMatrix[SkMatrix::kMTransX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMTransX]) + 4360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp2])); 4370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger this->addCoordTransform(&fBTransform); 4380a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 439d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 440363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger GR_DECLARE_EFFECT_TEST; 44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // @{ 44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Cache of values - these can change arbitrarily, EXCEPT 44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // we shouldn't change between degenerate and non-degenerate?! 44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4460a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger GrCoordTransform fBTransform; 4470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkScalar fCenterX1; 4480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkScalar fRadius0; 4490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkScalar fDiffRadius; 45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // @} 45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru typedef GrGradientEffect INHERITED; 45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 456363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerGR_DEFINE_EFFECT_TEST(GrConical2Gradient); 45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4580a657bbc2c6fc9daf699942e023050536d5ec95fDerek SollenbergerGrEffectRef* GrConical2Gradient::TestCreate(SkRandom* random, 459d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger GrContext* context, 4607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const GrDrawTargetCaps&, 461d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger GrTexture**) { 46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint center1 = {random->nextUScalar1(), random->nextUScalar1()}; 46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar radius1 = random->nextUScalar1(); 46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint center2; 46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar radius2; 46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru do { 467363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger center2.set(random->nextUScalar1(), random->nextUScalar1()); 46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru radius2 = random->nextUScalar1 (); 46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // If the circles are identical the factory will give us an empty shader. 47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } while (radius1 == radius2 && center1 == center2); 47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkColor colors[kMaxRandomGradientColors]; 47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar stopsArray[kMaxRandomGradientColors]; 47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar* stops = stopsArray; 47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkShader::TileMode tm; 47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int colorCount = RandomGradientParams(random, colors, &stops, &tm); 47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoTUnref<SkShader> shader(SkGradientShader::CreateTwoPointConical(center1, radius1, 47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru center2, radius2, 47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru colors, stops, colorCount, 48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru tm)); 481d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger SkPaint paint; 482d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return shader->asNewEffect(context, paint); 48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////// 48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 488d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrGLConical2Gradient::GrGLConical2Gradient(const GrBackendEffectFactory& factory, 489e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger const GrDrawEffect& drawEffect) 49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru : INHERITED(factory) 49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru , fVSVaryingName(NULL) 49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru , fFSVaryingName(NULL) 493363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger , fCachedCenter(SK_ScalarMax) 494363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger , fCachedRadius(-SK_ScalarMax) 495363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger , fCachedDiffRadius(-SK_ScalarMax) { 49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 497e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger const GrConical2Gradient& data = drawEffect.castEffect<GrConical2Gradient>(); 49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fIsDegenerate = data.isDegenerate(); 49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 501363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder, 502e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger const GrDrawEffect&, 503363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger EffectKey key, 504363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger const char* outputColor, 505363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger const char* inputColor, 5060a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const TransformedCoordsArray& coords, 507363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger const TextureSamplerArray& samplers) { 5080a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger this->emitUniforms(builder, key); 5090a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger fParamUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility, 5100a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger kFloat_GrSLType, "Conical2FSParams", 6); 5110a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5120a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString cName("c"); 5130a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString ac4Name("ac4"); 5140a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString dName("d"); 5150a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString qName("q"); 5160a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString r0Name("r0"); 5170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString r1Name("r1"); 5180a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString tName("t"); 5190a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString p0; // 4a 5200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString p1; // 1/a 5210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString p2; // distance between centers 5220a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString p3; // start radius 5230a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString p4; // start radius squared 5240a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString p5; // difference in radii (r1 - r0) 5250a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5260a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->getUniformVariable(fParamUni).appendArrayAccess(0, &p0); 5270a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1); 5280a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->getUniformVariable(fParamUni).appendArrayAccess(2, &p2); 5290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->getUniformVariable(fParamUni).appendArrayAccess(3, &p3); 5300a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->getUniformVariable(fParamUni).appendArrayAccess(4, &p4); 5310a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->getUniformVariable(fParamUni).appendArrayAccess(5, &p5); 5320a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5330a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // We interpolate the linear component in coords[1]. 5340a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(coords[0].type() == coords[1].type()); 5350a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const char* coords2D; 5360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkString bVar; 5370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (kVec3f_GrSLType == coords[0].type()) { 5380a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\tvec3 interpolants = vec3(%s.xy, %s.x) / %s.z;\n", 5390a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger coords[0].c_str(), coords[1].c_str(), coords[0].c_str()); 5400a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger coords2D = "interpolants.xy"; 5410a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger bVar = "interpolants.z"; 5420a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } else { 5430a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger coords2D = coords[0].c_str(); 5440a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger bVar.printf("%s.x", coords[1].c_str()); 54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // output will default to transparent black (we simply won't write anything 5480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // else to it if invalid, instead of discarding or returning prematurely) 5490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor); 5500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // c = (x^2)+(y^2) - params[4] 5520a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\tfloat %s = dot(%s, %s) - %s;\n", 5530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger cName.c_str(), coords2D, coords2D, p4.c_str()); 5540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5550a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Non-degenerate case (quadratic) 5560a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (!fIsDegenerate) { 5570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5580a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // ac4 = params[0] * c 5590a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\tfloat %s = %s * %s;\n", ac4Name.c_str(), p0.c_str(), 5600a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger cName.c_str()); 5610a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5620a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // d = b^2 - ac4 5630a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\tfloat %s = %s * %s - %s;\n", dName.c_str(), 5640a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger bVar.c_str(), bVar.c_str(), ac4Name.c_str()); 5650a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // only proceed if discriminant is >= 0 5670a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\tif (%s >= 0.0) {\n", dName.c_str()); 5680a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // intermediate value we'll use to compute the roots 5700a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // q = -0.5 * (b +/- sqrt(d)) 5710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\t\tfloat %s = -0.5 * (%s + (%s < 0.0 ? -1.0 : 1.0)" 5720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger " * sqrt(%s));\n", qName.c_str(), bVar.c_str(), 5730a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger bVar.c_str(), dName.c_str()); 5740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // compute both roots 5760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // r0 = q * params[1] 5770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\t\tfloat %s = %s * %s;\n", r0Name.c_str(), 5780a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger qName.c_str(), p1.c_str()); 5790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // r1 = c / q 5800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\t\tfloat %s = %s / %s;\n", r1Name.c_str(), 5810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger cName.c_str(), qName.c_str()); 5820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Note: If there are two roots that both generate radius(t) > 0, the 5840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Canvas spec says to choose the larger t. 5850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5860a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // so we'll look at the larger one first: 5870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\t\tfloat %s = max(%s, %s);\n", tName.c_str(), 5880a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger r0Name.c_str(), r1Name.c_str()); 5890a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5900a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // if r(t) > 0, then we're done; t will be our x coordinate 5910a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\t\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), 5920a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger p5.c_str(), p3.c_str()); 5930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppend("\t\t"); 5950a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers); 5960a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 5970a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // otherwise, if r(t) for the larger root was <= 0, try the other root 5980a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppend("\t\t} else {\n"); 5990a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\t\t\t%s = min(%s, %s);\n", tName.c_str(), 6000a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger r0Name.c_str(), r1Name.c_str()); 6010a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 6020a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // if r(t) > 0 for the smaller root, then t will be our x coordinate 6030a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\t\t\tif (%s * %s + %s > 0.0) {\n", 6040a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger tName.c_str(), p5.c_str(), p3.c_str()); 6050a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 6060a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppend("\t\t\t"); 6070a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers); 6080a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 6090a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // end if (r(t) > 0) for smaller root 6100a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppend("\t\t\t}\n"); 6110a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // end if (r(t) > 0), else, for larger root 6120a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppend("\t\t}\n"); 6130a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // end if (discriminant >= 0) 6140a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppend("\t}\n"); 6150a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } else { 61680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // linear case: t = -c/b 6180a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(), 6190a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger cName.c_str(), bVar.c_str()); 62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // if r(t) > 0, then t will be the x coordinate 6220a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), 6230a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger p5.c_str(), p3.c_str()); 6240a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppend("\t"); 6250a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers); 6260a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder->fsCodeAppend("\t}\n"); 62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 630e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergervoid GrGLConical2Gradient::setData(const GrGLUniformManager& uman, 631e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger const GrDrawEffect& drawEffect) { 632e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger INHERITED::setData(uman, drawEffect); 633e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger const GrConical2Gradient& data = drawEffect.castEffect<GrConical2Gradient>(); 6340a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(data.isDegenerate() == fIsDegenerate); 635363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar centerX1 = data.center(); 636363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar radius0 = data.radius(); 637363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar diffRadius = data.diffRadius(); 63880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 63980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fCachedCenter != centerX1 || 64080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCachedRadius != radius0 || 64180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCachedDiffRadius != diffRadius) { 64280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 643363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalar a = SkScalarMul(centerX1, centerX1) - diffRadius * diffRadius; 64480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 64580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // When we're in the degenerate (linear) case, the second 64680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // value will be INF but the program doesn't read it. (We 64780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // use the same 6 uniforms even though we don't need them 64880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // all in the linear case just to keep the code complexity 64980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // down). 65080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float values[6] = { 651363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalarToFloat(a * 4), 652363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 1.f / (SkScalarToFloat(a)), 653363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalarToFloat(centerX1), 654363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalarToFloat(radius0), 655363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalarToFloat(SkScalarMul(radius0, radius0)), 656363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalarToFloat(diffRadius) 65780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru }; 65880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 659910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger uman.set1fv(fParamUni, 6, values); 66080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCachedCenter = centerX1; 66180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCachedRadius = radius0; 66280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fCachedDiffRadius = diffRadius; 66380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 66480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 66580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 666e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek SollenbergerGrGLEffect::EffectKey GrGLConical2Gradient::GenKey(const GrDrawEffect& drawEffect, 667e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger const GrGLCaps&) { 668363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger enum { 6690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger kIsDegenerate = 1 << kBaseKeyBitCnt, 670363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger }; 671363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 6720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger EffectKey key = GenBaseGradientKey(drawEffect); 673e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (drawEffect.castEffect<GrConical2Gradient>().isDegenerate()) { 674363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger key |= kIsDegenerate; 675363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger } 676363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger return key; 67780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 67880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 67980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////// 68080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 681d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrEffectRef* SkTwoPointConicalGradient::asNewEffect(GrContext* context, const SkPaint&) const { 682d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger SkASSERT(NULL != context); 683363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkASSERT(fPtsToUnit.isIdentity()); 684363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger // invert the localM, translate to center1, rotate so center2 is on x axis. 68580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkMatrix matrix; 686363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger if (!this->getLocalMatrix().invert(&matrix)) { 687d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return NULL; 688363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger } 689363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger matrix.postTranslate(-fCenter1.fX, -fCenter1.fY); 690363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 69180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint diff = fCenter2 - fCenter1; 69280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar diffLen = diff.length(); 69380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (0 != diffLen) { 69480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar invDiffLen = SkScalarInvert(diffLen); 695363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkMatrix rot; 696363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger rot.setSinCos(-SkScalarMul(invDiffLen, diff.fY), 697363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkScalarMul(invDiffLen, diff.fX)); 698363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger matrix.postConcat(rot); 69980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 70080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 701d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return GrConical2Gradient::Create(context, *this, matrix, fTileMode); 70280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 70380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 70480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 70580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 706d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrEffectRef* SkTwoPointConicalGradient::asNewEffect(GrContext*, const SkPaint&) const { 70780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDEBUGFAIL("Should not call in GPU-less build"); 708d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return NULL; 70980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 71080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 71180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 712d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 713d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#ifdef SK_DEVELOPER 714d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergervoid SkTwoPointConicalGradient::toString(SkString* str) const { 715d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->append("SkTwoPointConicalGradient: ("); 716d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 717d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->append("center1: ("); 718d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->appendScalar(fCenter1.fX); 719d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->append(", "); 720d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->appendScalar(fCenter1.fY); 721d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->append(") radius1: "); 722d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->appendScalar(fRadius1); 723d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->append(" "); 724d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 725d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->append("center2: ("); 726d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->appendScalar(fCenter2.fX); 727d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->append(", "); 728d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->appendScalar(fCenter2.fY); 729d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->append(") radius2: "); 730d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->appendScalar(fRadius2); 731d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->append(" "); 732d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 733d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger this->INHERITED::toString(str); 734d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 735d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger str->append(")"); 736d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger} 737d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#endif 738