16c432337818ff15e553c957d466a67e54684f97brileya@google.com/* 26c432337818ff15e553c957d466a67e54684f97brileya@google.com * Copyright 2012 Google Inc. 36c432337818ff15e553c957d466a67e54684f97brileya@google.com * 46c432337818ff15e553c957d466a67e54684f97brileya@google.com * Use of this source code is governed by a BSD-style license that can be 56c432337818ff15e553c957d466a67e54684f97brileya@google.com * found in the LICENSE file. 66c432337818ff15e553c957d466a67e54684f97brileya@google.com */ 76c432337818ff15e553c957d466a67e54684f97brileya@google.com 86c432337818ff15e553c957d466a67e54684f97brileya@google.com#include "SkTwoPointConicalGradient.h" 96c432337818ff15e553c957d466a67e54684f97brileya@google.com 106c432337818ff15e553c957d466a67e54684f97brileya@google.comstatic int valid_divide(float numer, float denom, float* ratio) { 116c432337818ff15e553c957d466a67e54684f97brileya@google.com SkASSERT(ratio); 126c432337818ff15e553c957d466a67e54684f97brileya@google.com if (0 == denom) { 136c432337818ff15e553c957d466a67e54684f97brileya@google.com return 0; 146c432337818ff15e553c957d466a67e54684f97brileya@google.com } 156c432337818ff15e553c957d466a67e54684f97brileya@google.com *ratio = numer / denom; 166c432337818ff15e553c957d466a67e54684f97brileya@google.com return 1; 176c432337818ff15e553c957d466a67e54684f97brileya@google.com} 186c432337818ff15e553c957d466a67e54684f97brileya@google.com 196c432337818ff15e553c957d466a67e54684f97brileya@google.com// Return the number of distinct real roots, and write them into roots[] in 206c432337818ff15e553c957d466a67e54684f97brileya@google.com// ascending order 216c432337818ff15e553c957d466a67e54684f97brileya@google.comstatic int find_quad_roots(float A, float B, float C, float roots[2]) { 226c432337818ff15e553c957d466a67e54684f97brileya@google.com SkASSERT(roots); 23935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 246c432337818ff15e553c957d466a67e54684f97brileya@google.com if (A == 0) { 256c432337818ff15e553c957d466a67e54684f97brileya@google.com return valid_divide(-C, B, roots); 266c432337818ff15e553c957d466a67e54684f97brileya@google.com } 27935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 286c432337818ff15e553c957d466a67e54684f97brileya@google.com float R = B*B - 4*A*C; 296c432337818ff15e553c957d466a67e54684f97brileya@google.com if (R < 0) { 306c432337818ff15e553c957d466a67e54684f97brileya@google.com return 0; 316c432337818ff15e553c957d466a67e54684f97brileya@google.com } 326c432337818ff15e553c957d466a67e54684f97brileya@google.com R = sk_float_sqrt(R); 336c432337818ff15e553c957d466a67e54684f97brileya@google.com 346c432337818ff15e553c957d466a67e54684f97brileya@google.com#if 1 356c432337818ff15e553c957d466a67e54684f97brileya@google.com float Q = B; 366c432337818ff15e553c957d466a67e54684f97brileya@google.com if (Q < 0) { 376c432337818ff15e553c957d466a67e54684f97brileya@google.com Q -= R; 386c432337818ff15e553c957d466a67e54684f97brileya@google.com } else { 396c432337818ff15e553c957d466a67e54684f97brileya@google.com Q += R; 406c432337818ff15e553c957d466a67e54684f97brileya@google.com } 416c432337818ff15e553c957d466a67e54684f97brileya@google.com#else 426c432337818ff15e553c957d466a67e54684f97brileya@google.com // on 10.6 this was much slower than the above branch :( 436c432337818ff15e553c957d466a67e54684f97brileya@google.com float Q = B + copysignf(R, B); 446c432337818ff15e553c957d466a67e54684f97brileya@google.com#endif 456c432337818ff15e553c957d466a67e54684f97brileya@google.com Q *= -0.5f; 466c432337818ff15e553c957d466a67e54684f97brileya@google.com if (0 == Q) { 476c432337818ff15e553c957d466a67e54684f97brileya@google.com roots[0] = 0; 486c432337818ff15e553c957d466a67e54684f97brileya@google.com return 1; 496c432337818ff15e553c957d466a67e54684f97brileya@google.com } 506c432337818ff15e553c957d466a67e54684f97brileya@google.com 516c432337818ff15e553c957d466a67e54684f97brileya@google.com float r0 = Q / A; 526c432337818ff15e553c957d466a67e54684f97brileya@google.com float r1 = C / Q; 536c432337818ff15e553c957d466a67e54684f97brileya@google.com roots[0] = r0 < r1 ? r0 : r1; 546c432337818ff15e553c957d466a67e54684f97brileya@google.com roots[1] = r0 > r1 ? r0 : r1; 556c432337818ff15e553c957d466a67e54684f97brileya@google.com return 2; 566c432337818ff15e553c957d466a67e54684f97brileya@google.com} 576c432337818ff15e553c957d466a67e54684f97brileya@google.com 586c432337818ff15e553c957d466a67e54684f97brileya@google.comstatic float lerp(float x, float dx, float t) { 596c432337818ff15e553c957d466a67e54684f97brileya@google.com return x + t * dx; 606c432337818ff15e553c957d466a67e54684f97brileya@google.com} 616c432337818ff15e553c957d466a67e54684f97brileya@google.com 626c432337818ff15e553c957d466a67e54684f97brileya@google.comstatic float sqr(float x) { return x * x; } 636c432337818ff15e553c957d466a67e54684f97brileya@google.com 646c432337818ff15e553c957d466a67e54684f97brileya@google.comvoid TwoPtRadial::init(const SkPoint& center0, SkScalar rad0, 656c432337818ff15e553c957d466a67e54684f97brileya@google.com const SkPoint& center1, SkScalar rad1) { 666c432337818ff15e553c957d466a67e54684f97brileya@google.com fCenterX = SkScalarToFloat(center0.fX); 676c432337818ff15e553c957d466a67e54684f97brileya@google.com fCenterY = SkScalarToFloat(center0.fY); 686c432337818ff15e553c957d466a67e54684f97brileya@google.com fDCenterX = SkScalarToFloat(center1.fX) - fCenterX; 696c432337818ff15e553c957d466a67e54684f97brileya@google.com fDCenterY = SkScalarToFloat(center1.fY) - fCenterY; 706c432337818ff15e553c957d466a67e54684f97brileya@google.com fRadius = SkScalarToFloat(rad0); 716c432337818ff15e553c957d466a67e54684f97brileya@google.com fDRadius = SkScalarToFloat(rad1) - fRadius; 726c432337818ff15e553c957d466a67e54684f97brileya@google.com 736c432337818ff15e553c957d466a67e54684f97brileya@google.com fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius); 746c432337818ff15e553c957d466a67e54684f97brileya@google.com fRadius2 = sqr(fRadius); 756c432337818ff15e553c957d466a67e54684f97brileya@google.com fRDR = fRadius * fDRadius; 766c432337818ff15e553c957d466a67e54684f97brileya@google.com} 776c432337818ff15e553c957d466a67e54684f97brileya@google.com 786c432337818ff15e553c957d466a67e54684f97brileya@google.comvoid TwoPtRadial::setup(SkScalar fx, SkScalar fy, SkScalar dfx, SkScalar dfy) { 796c432337818ff15e553c957d466a67e54684f97brileya@google.com fRelX = SkScalarToFloat(fx) - fCenterX; 806c432337818ff15e553c957d466a67e54684f97brileya@google.com fRelY = SkScalarToFloat(fy) - fCenterY; 816c432337818ff15e553c957d466a67e54684f97brileya@google.com fIncX = SkScalarToFloat(dfx); 826c432337818ff15e553c957d466a67e54684f97brileya@google.com fIncY = SkScalarToFloat(dfy); 836c432337818ff15e553c957d466a67e54684f97brileya@google.com fB = -2 * (fDCenterX * fRelX + fDCenterY * fRelY + fRDR); 846c432337818ff15e553c957d466a67e54684f97brileya@google.com fDB = -2 * (fDCenterX * fIncX + fDCenterY * fIncY); 856c432337818ff15e553c957d466a67e54684f97brileya@google.com} 866c432337818ff15e553c957d466a67e54684f97brileya@google.com 876c432337818ff15e553c957d466a67e54684f97brileya@google.comSkFixed TwoPtRadial::nextT() { 886c432337818ff15e553c957d466a67e54684f97brileya@google.com float roots[2]; 89935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 906c432337818ff15e553c957d466a67e54684f97brileya@google.com float C = sqr(fRelX) + sqr(fRelY) - fRadius2; 916c432337818ff15e553c957d466a67e54684f97brileya@google.com int countRoots = find_quad_roots(fA, fB, C, roots); 926c432337818ff15e553c957d466a67e54684f97brileya@google.com 936c432337818ff15e553c957d466a67e54684f97brileya@google.com fRelX += fIncX; 946c432337818ff15e553c957d466a67e54684f97brileya@google.com fRelY += fIncY; 956c432337818ff15e553c957d466a67e54684f97brileya@google.com fB += fDB; 966c432337818ff15e553c957d466a67e54684f97brileya@google.com 976c432337818ff15e553c957d466a67e54684f97brileya@google.com if (0 == countRoots) { 986c432337818ff15e553c957d466a67e54684f97brileya@google.com return kDontDrawT; 996c432337818ff15e553c957d466a67e54684f97brileya@google.com } 1006c432337818ff15e553c957d466a67e54684f97brileya@google.com 1016c432337818ff15e553c957d466a67e54684f97brileya@google.com // Prefer the bigger t value if both give a radius(t) > 0 1026c432337818ff15e553c957d466a67e54684f97brileya@google.com // find_quad_roots returns the values sorted, so we start with the last 1036c432337818ff15e553c957d466a67e54684f97brileya@google.com float t = roots[countRoots - 1]; 1046c432337818ff15e553c957d466a67e54684f97brileya@google.com float r = lerp(fRadius, fDRadius, t); 1056c432337818ff15e553c957d466a67e54684f97brileya@google.com if (r <= 0) { 1066c432337818ff15e553c957d466a67e54684f97brileya@google.com t = roots[0]; // might be the same as roots[countRoots-1] 1076c432337818ff15e553c957d466a67e54684f97brileya@google.com r = lerp(fRadius, fDRadius, t); 1086c432337818ff15e553c957d466a67e54684f97brileya@google.com if (r <= 0) { 1096c432337818ff15e553c957d466a67e54684f97brileya@google.com return kDontDrawT; 1106c432337818ff15e553c957d466a67e54684f97brileya@google.com } 1116c432337818ff15e553c957d466a67e54684f97brileya@google.com } 1126c432337818ff15e553c957d466a67e54684f97brileya@google.com return SkFloatToFixed(t); 1136c432337818ff15e553c957d466a67e54684f97brileya@google.com} 1146c432337818ff15e553c957d466a67e54684f97brileya@google.com 115b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.comtypedef void (*TwoPointConicalProc)(TwoPtRadial* rec, SkPMColor* dstC, 116b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com const SkPMColor* cache, int toggle, int count); 1176c432337818ff15e553c957d466a67e54684f97brileya@google.com 1186c432337818ff15e553c957d466a67e54684f97brileya@google.comstatic void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, 119b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com const SkPMColor* SK_RESTRICT cache, int toggle, 120b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com int count) { 1216c432337818ff15e553c957d466a67e54684f97brileya@google.com for (; count > 0; --count) { 1226c432337818ff15e553c957d466a67e54684f97brileya@google.com SkFixed t = rec->nextT(); 1236c432337818ff15e553c957d466a67e54684f97brileya@google.com if (TwoPtRadial::DontDrawT(t)) { 1246c432337818ff15e553c957d466a67e54684f97brileya@google.com *dstC++ = 0; 1256c432337818ff15e553c957d466a67e54684f97brileya@google.com } else { 1266c432337818ff15e553c957d466a67e54684f97brileya@google.com SkFixed index = SkClampMax(t, 0xFFFF); 1276c432337818ff15e553c957d466a67e54684f97brileya@google.com SkASSERT(index <= 0xFFFF); 128b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com *dstC++ = cache[toggle + 129b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com (index >> SkGradientShaderBase::kCache32Shift)]; 1306c432337818ff15e553c957d466a67e54684f97brileya@google.com } 131b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com toggle = next_dither_toggle(toggle); 1326c432337818ff15e553c957d466a67e54684f97brileya@google.com } 1336c432337818ff15e553c957d466a67e54684f97brileya@google.com} 1346c432337818ff15e553c957d466a67e54684f97brileya@google.com 1356c432337818ff15e553c957d466a67e54684f97brileya@google.comstatic void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, 136b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com const SkPMColor* SK_RESTRICT cache, int toggle, 137b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com int count) { 1386c432337818ff15e553c957d466a67e54684f97brileya@google.com for (; count > 0; --count) { 1396c432337818ff15e553c957d466a67e54684f97brileya@google.com SkFixed t = rec->nextT(); 1406c432337818ff15e553c957d466a67e54684f97brileya@google.com if (TwoPtRadial::DontDrawT(t)) { 1416c432337818ff15e553c957d466a67e54684f97brileya@google.com *dstC++ = 0; 1426c432337818ff15e553c957d466a67e54684f97brileya@google.com } else { 1436c432337818ff15e553c957d466a67e54684f97brileya@google.com SkFixed index = repeat_tileproc(t); 1446c432337818ff15e553c957d466a67e54684f97brileya@google.com SkASSERT(index <= 0xFFFF); 145b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com *dstC++ = cache[toggle + 146b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com (index >> SkGradientShaderBase::kCache32Shift)]; 1476c432337818ff15e553c957d466a67e54684f97brileya@google.com } 148b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com toggle = next_dither_toggle(toggle); 1496c432337818ff15e553c957d466a67e54684f97brileya@google.com } 1506c432337818ff15e553c957d466a67e54684f97brileya@google.com} 1516c432337818ff15e553c957d466a67e54684f97brileya@google.com 1526c432337818ff15e553c957d466a67e54684f97brileya@google.comstatic void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, 153b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com const SkPMColor* SK_RESTRICT cache, int toggle, 154b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com int count) { 1556c432337818ff15e553c957d466a67e54684f97brileya@google.com for (; count > 0; --count) { 1566c432337818ff15e553c957d466a67e54684f97brileya@google.com SkFixed t = rec->nextT(); 1576c432337818ff15e553c957d466a67e54684f97brileya@google.com if (TwoPtRadial::DontDrawT(t)) { 1586c432337818ff15e553c957d466a67e54684f97brileya@google.com *dstC++ = 0; 1596c432337818ff15e553c957d466a67e54684f97brileya@google.com } else { 1606c432337818ff15e553c957d466a67e54684f97brileya@google.com SkFixed index = mirror_tileproc(t); 1616c432337818ff15e553c957d466a67e54684f97brileya@google.com SkASSERT(index <= 0xFFFF); 162b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com *dstC++ = cache[toggle + 163b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com (index >> SkGradientShaderBase::kCache32Shift)]; 1646c432337818ff15e553c957d466a67e54684f97brileya@google.com } 165b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com toggle = next_dither_toggle(toggle); 1666c432337818ff15e553c957d466a67e54684f97brileya@google.com } 1676c432337818ff15e553c957d466a67e54684f97brileya@google.com} 1686c432337818ff15e553c957d466a67e54684f97brileya@google.com 1696c432337818ff15e553c957d466a67e54684f97brileya@google.comvoid SkTwoPointConicalGradient::init() { 1706c432337818ff15e553c957d466a67e54684f97brileya@google.com fRec.init(fCenter1, fRadius1, fCenter2, fRadius2); 1716c432337818ff15e553c957d466a67e54684f97brileya@google.com fPtsToUnit.reset(); 1726c432337818ff15e553c957d466a67e54684f97brileya@google.com} 1736c432337818ff15e553c957d466a67e54684f97brileya@google.com 174eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com///////////////////////////////////////////////////////////////////// 175eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 1766c432337818ff15e553c957d466a67e54684f97brileya@google.comSkTwoPointConicalGradient::SkTwoPointConicalGradient( 1772d5eaf20bb39e7f90e0294eccf2a598135c7b570reed@google.com const SkPoint& start, SkScalar startRadius, 1782d5eaf20bb39e7f90e0294eccf2a598135c7b570reed@google.com const SkPoint& end, SkScalar endRadius, 1792d5eaf20bb39e7f90e0294eccf2a598135c7b570reed@google.com const Descriptor& desc) 18052d6fb7020e41328b86785a5ea12d42f44f36b8creed@google.com : SkGradientShaderBase(desc), 1816c432337818ff15e553c957d466a67e54684f97brileya@google.com fCenter1(start), 1826c432337818ff15e553c957d466a67e54684f97brileya@google.com fCenter2(end), 1836c432337818ff15e553c957d466a67e54684f97brileya@google.com fRadius1(startRadius), 1846c432337818ff15e553c957d466a67e54684f97brileya@google.com fRadius2(endRadius) { 1856c432337818ff15e553c957d466a67e54684f97brileya@google.com // this is degenerate, and should be caught by our caller 1866c432337818ff15e553c957d466a67e54684f97brileya@google.com SkASSERT(fCenter1 != fCenter2 || fRadius1 != fRadius2); 1876c432337818ff15e553c957d466a67e54684f97brileya@google.com this->init(); 1886c432337818ff15e553c957d466a67e54684f97brileya@google.com} 1896c432337818ff15e553c957d466a67e54684f97brileya@google.com 190f999f59dac04f742f6c45c2c029d563538e97620commit-bot@chromium.orgbool SkTwoPointConicalGradient::isOpaque() const { 191e3199a12d2e9a33609d9fd25b8d3a09265d055cfrobertphillips@google.com // Because areas outside the cone are left untouched, we cannot treat the 192e3199a12d2e9a33609d9fd25b8d3a09265d055cfrobertphillips@google.com // shader as opaque even if the gradient itself is opaque. 193e3199a12d2e9a33609d9fd25b8d3a09265d055cfrobertphillips@google.com // TODO(junov): Compute whether the cone fills the plane crbug.com/222380 194e3199a12d2e9a33609d9fd25b8d3a09265d055cfrobertphillips@google.com return false; 195f999f59dac04f742f6c45c2c029d563538e97620commit-bot@chromium.org} 196f999f59dac04f742f6c45c2c029d563538e97620commit-bot@chromium.org 1976c432337818ff15e553c957d466a67e54684f97brileya@google.comvoid SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam, 1986c432337818ff15e553c957d466a67e54684f97brileya@google.com int count) { 199b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com int toggle = init_dither_toggle(x, y); 200b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com 2016c432337818ff15e553c957d466a67e54684f97brileya@google.com SkASSERT(count > 0); 202935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 2036c432337818ff15e553c957d466a67e54684f97brileya@google.com SkPMColor* SK_RESTRICT dstC = dstCParam; 204935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 2056c432337818ff15e553c957d466a67e54684f97brileya@google.com SkMatrix::MapXYProc dstProc = fDstToIndexProc; 2069b2cc2b61fa225ce9f0295d5c62140334bb74d17bsalomon@google.com 2076c432337818ff15e553c957d466a67e54684f97brileya@google.com const SkPMColor* SK_RESTRICT cache = this->getCache32(); 2086c432337818ff15e553c957d466a67e54684f97brileya@google.com 209b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com TwoPointConicalProc shadeProc = twopoint_repeat; 2106c432337818ff15e553c957d466a67e54684f97brileya@google.com if (SkShader::kClamp_TileMode == fTileMode) { 2116c432337818ff15e553c957d466a67e54684f97brileya@google.com shadeProc = twopoint_clamp; 2126c432337818ff15e553c957d466a67e54684f97brileya@google.com } else if (SkShader::kMirror_TileMode == fTileMode) { 2136c432337818ff15e553c957d466a67e54684f97brileya@google.com shadeProc = twopoint_mirror; 2146c432337818ff15e553c957d466a67e54684f97brileya@google.com } else { 2156c432337818ff15e553c957d466a67e54684f97brileya@google.com SkASSERT(SkShader::kRepeat_TileMode == fTileMode); 2166c432337818ff15e553c957d466a67e54684f97brileya@google.com } 217935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 2186c432337818ff15e553c957d466a67e54684f97brileya@google.com if (fDstToIndexClass != kPerspective_MatrixClass) { 2196c432337818ff15e553c957d466a67e54684f97brileya@google.com SkPoint srcPt; 2206c432337818ff15e553c957d466a67e54684f97brileya@google.com dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, 2216c432337818ff15e553c957d466a67e54684f97brileya@google.com SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 2226c432337818ff15e553c957d466a67e54684f97brileya@google.com SkScalar dx, fx = srcPt.fX; 2236c432337818ff15e553c957d466a67e54684f97brileya@google.com SkScalar dy, fy = srcPt.fY; 224935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 2256c432337818ff15e553c957d466a67e54684f97brileya@google.com if (fDstToIndexClass == kFixedStepInX_MatrixClass) { 2266c432337818ff15e553c957d466a67e54684f97brileya@google.com SkFixed fixedX, fixedY; 2276c432337818ff15e553c957d466a67e54684f97brileya@google.com (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY); 2286c432337818ff15e553c957d466a67e54684f97brileya@google.com dx = SkFixedToScalar(fixedX); 2296c432337818ff15e553c957d466a67e54684f97brileya@google.com dy = SkFixedToScalar(fixedY); 2306c432337818ff15e553c957d466a67e54684f97brileya@google.com } else { 2316c432337818ff15e553c957d466a67e54684f97brileya@google.com SkASSERT(fDstToIndexClass == kLinear_MatrixClass); 2326c432337818ff15e553c957d466a67e54684f97brileya@google.com dx = fDstToIndex.getScaleX(); 2336c432337818ff15e553c957d466a67e54684f97brileya@google.com dy = fDstToIndex.getSkewY(); 2346c432337818ff15e553c957d466a67e54684f97brileya@google.com } 2356c432337818ff15e553c957d466a67e54684f97brileya@google.com 2366c432337818ff15e553c957d466a67e54684f97brileya@google.com fRec.setup(fx, fy, dx, dy); 237b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com (*shadeProc)(&fRec, dstC, cache, toggle, count); 2386c432337818ff15e553c957d466a67e54684f97brileya@google.com } else { // perspective case 239b941e5c71e30ef9150a9dff80de5e393d68dde07mike@reedtribe.org SkScalar dstX = SkIntToScalar(x) + SK_ScalarHalf; 240b941e5c71e30ef9150a9dff80de5e393d68dde07mike@reedtribe.org SkScalar dstY = SkIntToScalar(y) + SK_ScalarHalf; 2416c432337818ff15e553c957d466a67e54684f97brileya@google.com for (; count > 0; --count) { 2426c432337818ff15e553c957d466a67e54684f97brileya@google.com SkPoint srcPt; 2436c432337818ff15e553c957d466a67e54684f97brileya@google.com dstProc(fDstToIndex, dstX, dstY, &srcPt); 2446c432337818ff15e553c957d466a67e54684f97brileya@google.com fRec.setup(srcPt.fX, srcPt.fY, 0, 0); 245b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com (*shadeProc)(&fRec, dstC, cache, toggle, 1); 246b941e5c71e30ef9150a9dff80de5e393d68dde07mike@reedtribe.org 247b941e5c71e30ef9150a9dff80de5e393d68dde07mike@reedtribe.org dstX += SK_Scalar1; 248b0f31cddaad4252e3d5f841b2010c7d1d026e5a2reed@google.com toggle = next_dither_toggle(toggle); 249b941e5c71e30ef9150a9dff80de5e393d68dde07mike@reedtribe.org dstC += 1; 2506c432337818ff15e553c957d466a67e54684f97brileya@google.com } 2516c432337818ff15e553c957d466a67e54684f97brileya@google.com } 2526c432337818ff15e553c957d466a67e54684f97brileya@google.com} 2536c432337818ff15e553c957d466a67e54684f97brileya@google.com 2546c432337818ff15e553c957d466a67e54684f97brileya@google.combool SkTwoPointConicalGradient::setContext(const SkBitmap& device, 2556c432337818ff15e553c957d466a67e54684f97brileya@google.com const SkPaint& paint, 2566c432337818ff15e553c957d466a67e54684f97brileya@google.com const SkMatrix& matrix) { 2576c432337818ff15e553c957d466a67e54684f97brileya@google.com if (!this->INHERITED::setContext(device, paint, matrix)) { 2586c432337818ff15e553c957d466a67e54684f97brileya@google.com return false; 2596c432337818ff15e553c957d466a67e54684f97brileya@google.com } 260935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 2616c432337818ff15e553c957d466a67e54684f97brileya@google.com // we don't have a span16 proc 2626c432337818ff15e553c957d466a67e54684f97brileya@google.com fFlags &= ~kHasSpan16_Flag; 263935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 2646c432337818ff15e553c957d466a67e54684f97brileya@google.com // in general, we might discard based on computed-radius, so clear 2656c432337818ff15e553c957d466a67e54684f97brileya@google.com // this flag (todo: sometimes we can detect that we never discard...) 2666c432337818ff15e553c957d466a67e54684f97brileya@google.com fFlags &= ~kOpaqueAlpha_Flag; 2676c432337818ff15e553c957d466a67e54684f97brileya@google.com 2686c432337818ff15e553c957d466a67e54684f97brileya@google.com return true; 2696c432337818ff15e553c957d466a67e54684f97brileya@google.com} 2706c432337818ff15e553c957d466a67e54684f97brileya@google.com 2716c432337818ff15e553c957d466a67e54684f97brileya@google.comSkShader::BitmapType SkTwoPointConicalGradient::asABitmap( 2726c432337818ff15e553c957d466a67e54684f97brileya@google.com SkBitmap* bitmap, SkMatrix* matrix, SkShader::TileMode* xy) const { 2736c432337818ff15e553c957d466a67e54684f97brileya@google.com SkPoint diff = fCenter2 - fCenter1; 2746c432337818ff15e553c957d466a67e54684f97brileya@google.com SkScalar diffLen = 0; 2756c432337818ff15e553c957d466a67e54684f97brileya@google.com 2766c432337818ff15e553c957d466a67e54684f97brileya@google.com if (bitmap) { 27724a508e688b595f3381afc9a0e9d069e483fa360rileya@google.com this->getGradientTableBitmap(bitmap); 2786c432337818ff15e553c957d466a67e54684f97brileya@google.com } 2796c432337818ff15e553c957d466a67e54684f97brileya@google.com if (matrix) { 2806c432337818ff15e553c957d466a67e54684f97brileya@google.com diffLen = diff.length(); 2816c432337818ff15e553c957d466a67e54684f97brileya@google.com } 2826c432337818ff15e553c957d466a67e54684f97brileya@google.com if (matrix) { 2836c432337818ff15e553c957d466a67e54684f97brileya@google.com if (diffLen) { 2846c432337818ff15e553c957d466a67e54684f97brileya@google.com SkScalar invDiffLen = SkScalarInvert(diffLen); 2856c432337818ff15e553c957d466a67e54684f97brileya@google.com // rotate to align circle centers with the x-axis 2866c432337818ff15e553c957d466a67e54684f97brileya@google.com matrix->setSinCos(-SkScalarMul(invDiffLen, diff.fY), 2876c432337818ff15e553c957d466a67e54684f97brileya@google.com SkScalarMul(invDiffLen, diff.fX)); 2886c432337818ff15e553c957d466a67e54684f97brileya@google.com } else { 2896c432337818ff15e553c957d466a67e54684f97brileya@google.com matrix->reset(); 2906c432337818ff15e553c957d466a67e54684f97brileya@google.com } 2916c432337818ff15e553c957d466a67e54684f97brileya@google.com matrix->preTranslate(-fCenter1.fX, -fCenter1.fY); 2926c432337818ff15e553c957d466a67e54684f97brileya@google.com } 2936c432337818ff15e553c957d466a67e54684f97brileya@google.com if (xy) { 2946c432337818ff15e553c957d466a67e54684f97brileya@google.com xy[0] = fTileMode; 2956c432337818ff15e553c957d466a67e54684f97brileya@google.com xy[1] = kClamp_TileMode; 2966c432337818ff15e553c957d466a67e54684f97brileya@google.com } 2976c432337818ff15e553c957d466a67e54684f97brileya@google.com return kTwoPointConical_BitmapType; 2986c432337818ff15e553c957d466a67e54684f97brileya@google.com} 2996c432337818ff15e553c957d466a67e54684f97brileya@google.com 3006c432337818ff15e553c957d466a67e54684f97brileya@google.comSkShader::GradientType SkTwoPointConicalGradient::asAGradient( 3016c432337818ff15e553c957d466a67e54684f97brileya@google.com GradientInfo* info) const { 3026c432337818ff15e553c957d466a67e54684f97brileya@google.com if (info) { 3036c432337818ff15e553c957d466a67e54684f97brileya@google.com commonAsAGradient(info); 3046c432337818ff15e553c957d466a67e54684f97brileya@google.com info->fPoint[0] = fCenter1; 3056c432337818ff15e553c957d466a67e54684f97brileya@google.com info->fPoint[1] = fCenter2; 3066c432337818ff15e553c957d466a67e54684f97brileya@google.com info->fRadius[0] = fRadius1; 3076c432337818ff15e553c957d466a67e54684f97brileya@google.com info->fRadius[1] = fRadius2; 3086c432337818ff15e553c957d466a67e54684f97brileya@google.com } 3096c432337818ff15e553c957d466a67e54684f97brileya@google.com return kConical_GradientType; 3106c432337818ff15e553c957d466a67e54684f97brileya@google.com} 3116c432337818ff15e553c957d466a67e54684f97brileya@google.com 3126c432337818ff15e553c957d466a67e54684f97brileya@google.comSkTwoPointConicalGradient::SkTwoPointConicalGradient( 3136c432337818ff15e553c957d466a67e54684f97brileya@google.com SkFlattenableReadBuffer& buffer) 3146c432337818ff15e553c957d466a67e54684f97brileya@google.com : INHERITED(buffer), 3156c432337818ff15e553c957d466a67e54684f97brileya@google.com fCenter1(buffer.readPoint()), 3166c432337818ff15e553c957d466a67e54684f97brileya@google.com fCenter2(buffer.readPoint()), 3176c432337818ff15e553c957d466a67e54684f97brileya@google.com fRadius1(buffer.readScalar()), 3186c432337818ff15e553c957d466a67e54684f97brileya@google.com fRadius2(buffer.readScalar()) { 3196c432337818ff15e553c957d466a67e54684f97brileya@google.com this->init(); 3206c432337818ff15e553c957d466a67e54684f97brileya@google.com}; 3216c432337818ff15e553c957d466a67e54684f97brileya@google.com 3226c432337818ff15e553c957d466a67e54684f97brileya@google.comvoid SkTwoPointConicalGradient::flatten( 3236c432337818ff15e553c957d466a67e54684f97brileya@google.com SkFlattenableWriteBuffer& buffer) const { 3246c432337818ff15e553c957d466a67e54684f97brileya@google.com this->INHERITED::flatten(buffer); 3256c432337818ff15e553c957d466a67e54684f97brileya@google.com buffer.writePoint(fCenter1); 3266c432337818ff15e553c957d466a67e54684f97brileya@google.com buffer.writePoint(fCenter2); 3276c432337818ff15e553c957d466a67e54684f97brileya@google.com buffer.writeScalar(fRadius1); 3286c432337818ff15e553c957d466a67e54684f97brileya@google.com buffer.writeScalar(fRadius2); 3296c432337818ff15e553c957d466a67e54684f97brileya@google.com} 3306c432337818ff15e553c957d466a67e54684f97brileya@google.com 3315cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com///////////////////////////////////////////////////////////////////// 3325cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 3333515569a78b58fbb57f20ec909fffde8f945c19cbsalomon@google.com#if SK_SUPPORT_GPU 3343515569a78b58fbb57f20ec909fffde8f945c19cbsalomon@google.com 3358780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com#include "GrTBackendEffectFactory.h" 3368780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com 3375cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com// For brevity 3385cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.comtypedef GrGLUniformManager::UniformHandle UniformHandle; 3395cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 340f30e9eedfba04f5dd131efed491e3a6afd7a3119bsalomon@google.comclass GrGLConical2Gradient : public GrGLGradientEffect { 3415cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.compublic: 3425cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 3438bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com GrGLConical2Gradient(const GrBackendEffectFactory& factory, const GrDrawEffect&); 3445cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com virtual ~GrGLConical2Gradient() { } 3455cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 3468780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com virtual void emitCode(GrGLShaderBuilder*, 3478bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrDrawEffect&, 3488780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com EffectKey, 3498780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com const char* outputColor, 3508780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com const char* inputColor, 3510a42d756187a602db0d7455bf08fe9b1ced08854bsalomon@google.com const TransformedCoordsArray&, 3528780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com const TextureSamplerArray&) SK_OVERRIDE; 3538bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; 3545cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 3558bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps); 3565cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 3575cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.comprotected: 3585cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 359ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org UniformHandle fParamUni; 3605cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 3615cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com const char* fVSVaryingName; 3625cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com const char* fFSVaryingName; 3635cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 3645cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com bool fIsDegenerate; 3655cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 3665cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com // @{ 3675cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com /// Values last uploaded as uniforms 3685cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 3693a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalar fCachedCenter; 3703a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalar fCachedRadius; 3713a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalar fCachedDiffRadius; 3725cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 3735cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com // @} 3745cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 3755cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.comprivate: 3765cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 377f30e9eedfba04f5dd131efed491e3a6afd7a3119bsalomon@google.com typedef GrGLGradientEffect INHERITED; 3785cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 3795cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com}; 3805cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 381eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com///////////////////////////////////////////////////////////////////// 382eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 383eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.comclass GrConical2Gradient : public GrGradientEffect { 384eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.compublic: 385eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 38638b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com static GrEffectRef* Create(GrContext* ctx, 38738b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com const SkTwoPointConicalGradient& shader, 38838b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com const SkMatrix& matrix, 38938b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com SkShader::TileMode tm) { 390ba8399f132a172950b49dec019e910ff681928f6bsalomon@google.com AutoEffectUnref effect(SkNEW_ARGS(GrConical2Gradient, (ctx, shader, matrix, tm))); 39186e2faff92b4e897e1e38e8728f098a5d9d22034bsalomon@google.com return CreateEffectRef(effect); 39238b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com } 393eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 394eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com virtual ~GrConical2Gradient() { } 395eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 396eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com static const char* Name() { return "Two-Point Conical Gradient"; } 3971f64de790a624dc250d3da0789b3ada6251facb7bsalomon@google.com virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 3981f64de790a624dc250d3da0789b3ada6251facb7bsalomon@google.com return GrTBackendEffectFactory<GrConical2Gradient>::getInstance(); 399eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com } 400eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 401eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com // The radial gradient parameters can collapse to a linear (instead of quadratic) equation. 402eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com bool isDegenerate() const { return SkScalarAbs(fDiffRadius) == SkScalarAbs(fCenterX1); } 4033a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalar center() const { return fCenterX1; } 4043a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalar diffRadius() const { return fDiffRadius; } 4053a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalar radius() const { return fRadius0; } 406eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 407ca5e87e973b87209b5ffa298b8bc6ce0c512a204bsalomon@google.com typedef GrGLConical2Gradient GLEffect; 408eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 409eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.comprivate: 4106a2cef0e27af0600fe1afcc0fcda2f3011371be9bsalomon@google.com virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE { 411ba8399f132a172950b49dec019e910ff681928f6bsalomon@google.com const GrConical2Gradient& s = CastEffect<GrConical2Gradient>(sBase); 412c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com return (INHERITED::onIsEqual(sBase) && 413c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com this->fCenterX1 == s.fCenterX1 && 414c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com this->fRadius0 == s.fRadius0 && 415c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com this->fDiffRadius == s.fDiffRadius); 416c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com } 417c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com 41838b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com GrConical2Gradient(GrContext* ctx, 41938b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com const SkTwoPointConicalGradient& shader, 42038b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com const SkMatrix& matrix, 42138b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com SkShader::TileMode tm) 42238b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com : INHERITED(ctx, shader, matrix, tm) 42338b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com , fCenterX1(shader.getCenterX1()) 42438b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com , fRadius0(shader.getStartRadius()) 425ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org , fDiffRadius(shader.getDiffRadius()) { 426ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // We pass the linear part of the quadratic as a varying. 427ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z) 428ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org fBTransform = this->getCoordTransform(); 429ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkMatrix& bMatrix = *fBTransform.accessMatrix(); 430ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkScalar r0dr = SkScalarMul(fRadius0, fDiffRadius); 431ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org bMatrix[SkMatrix::kMScaleX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMScaleX]) + 432ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp0])); 433ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org bMatrix[SkMatrix::kMSkewX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMSkewX]) + 434ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp1])); 435ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org bMatrix[SkMatrix::kMTransX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMTransX]) + 436ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp2])); 437ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org this->addCoordTransform(&fBTransform); 438ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org } 43938b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com 4407e0b48a766909be86a2923d909b85c111de4d237bsalomon@google.com GR_DECLARE_EFFECT_TEST; 441eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 442eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com // @{ 443eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com // Cache of values - these can change arbitrarily, EXCEPT 444eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com // we shouldn't change between degenerate and non-degenerate?! 445eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 446ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org GrCoordTransform fBTransform; 447ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkScalar fCenterX1; 448ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkScalar fRadius0; 449ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkScalar fDiffRadius; 450eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 451eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com // @} 452eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 453eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com typedef GrGradientEffect INHERITED; 454eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com}; 455eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 4567e0b48a766909be86a2923d909b85c111de4d237bsalomon@google.comGR_DEFINE_EFFECT_TEST(GrConical2Gradient); 45778ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com 458680372190ee596c7485dcf2974c824fcf6a355dccommit-bot@chromium.orgGrEffectRef* GrConical2Gradient::TestCreate(SkRandom* random, 45938b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com GrContext* context, 460516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com const GrDrawTargetCaps&, 46138b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com GrTexture**) { 46278ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com SkPoint center1 = {random->nextUScalar1(), random->nextUScalar1()}; 46378ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com SkScalar radius1 = random->nextUScalar1(); 46478ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com SkPoint center2; 46578ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com SkScalar radius2; 46678ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com do { 4678ab9c69d0b75ef66106bf255c853740d72f65776bsalomon@google.com center2.set(random->nextUScalar1(), random->nextUScalar1()); 46878ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com radius2 = random->nextUScalar1 (); 46978ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com // If the circles are identical the factory will give us an empty shader. 47078ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com } while (radius1 == radius2 && center1 == center2); 471935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 47278ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com SkColor colors[kMaxRandomGradientColors]; 47378ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com SkScalar stopsArray[kMaxRandomGradientColors]; 47478ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com SkScalar* stops = stopsArray; 47578ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com SkShader::TileMode tm; 47678ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com int colorCount = RandomGradientParams(random, colors, &stops, &tm); 47778ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com SkAutoTUnref<SkShader> shader(SkGradientShader::CreateTwoPointConical(center1, radius1, 47878ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com center2, radius2, 47978ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com colors, stops, colorCount, 48078ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com tm)); 48105614588d877c5112445a5a0478619b187c2dbc4bsalomon@google.com SkPaint paint; 48205614588d877c5112445a5a0478619b187c2dbc4bsalomon@google.com return shader->asNewEffect(context, paint); 48378ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com} 48478ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com 48578ab92aa5c32b094205df9565e492d56ddce13cbbsalomon@google.com 486eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com///////////////////////////////////////////////////////////////////// 487eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com 488ba8399f132a172950b49dec019e910ff681928f6bsalomon@google.comGrGLConical2Gradient::GrGLConical2Gradient(const GrBackendEffectFactory& factory, 4898bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrDrawEffect& drawEffect) 4905cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com : INHERITED(factory) 4915cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com , fVSVaryingName(NULL) 4925cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com , fFSVaryingName(NULL) 4933a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com , fCachedCenter(SK_ScalarMax) 4943a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com , fCachedRadius(-SK_ScalarMax) 4953a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com , fCachedDiffRadius(-SK_ScalarMax) { 4965cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 4978bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrConical2Gradient& data = drawEffect.castEffect<GrConical2Gradient>(); 4985cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com fIsDegenerate = data.isDegenerate(); 4995cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com} 5005cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 5018780f037626b5196962a39ab76afd51f094a7765bsalomon@google.comvoid GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder, 5028bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrDrawEffect&, 503d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com EffectKey key, 5048780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com const char* outputColor, 5058780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com const char* inputColor, 5060a42d756187a602db0d7455bf08fe9b1ced08854bsalomon@google.com const TransformedCoordsArray& coords, 5078780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com const TextureSamplerArray& samplers) { 508f813e7169d80b7ba2ecd4b2994391202d977db35bsalomon@google.com this->emitUniforms(builder, key); 509ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org fParamUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility, 510ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org kFloat_GrSLType, "Conical2FSParams", 6); 511ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 512ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString cName("c"); 513ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString ac4Name("ac4"); 514ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString dName("d"); 515ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString qName("q"); 516ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString r0Name("r0"); 517ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString r1Name("r1"); 518ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString tName("t"); 519ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString p0; // 4a 520ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString p1; // 1/a 521ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString p2; // distance between centers 522ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString p3; // start radius 523ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString p4; // start radius squared 524ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString p5; // difference in radii (r1 - r0) 525ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 526ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->getUniformVariable(fParamUni).appendArrayAccess(0, &p0); 527ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1); 528ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->getUniformVariable(fParamUni).appendArrayAccess(2, &p2); 529ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->getUniformVariable(fParamUni).appendArrayAccess(3, &p3); 530ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->getUniformVariable(fParamUni).appendArrayAccess(4, &p4); 531ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->getUniformVariable(fParamUni).appendArrayAccess(5, &p5); 532ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 533ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // We interpolate the linear component in coords[1]. 534ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkASSERT(coords[0].type() == coords[1].type()); 535ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org const char* coords2D; 536ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org SkString bVar; 537ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org if (kVec3f_GrSLType == coords[0].type()) { 538ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\tvec3 interpolants = vec3(%s.xy, %s.x) / %s.z;\n", 539ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org coords[0].c_str(), coords[1].c_str(), coords[0].c_str()); 540ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org coords2D = "interpolants.xy"; 541ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org bVar = "interpolants.z"; 542ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org } else { 543ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org coords2D = coords[0].c_str(); 544ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org bVar.printf("%s.x", coords[1].c_str()); 5455cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com } 5465cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 547ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // output will default to transparent black (we simply won't write anything 548ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // else to it if invalid, instead of discarding or returning prematurely) 549ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor); 550ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 551ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // c = (x^2)+(y^2) - params[4] 552ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\tfloat %s = dot(%s, %s) - %s;\n", 553ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org cName.c_str(), coords2D, coords2D, p4.c_str()); 554ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 555ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // Non-degenerate case (quadratic) 556ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org if (!fIsDegenerate) { 557ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 558ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // ac4 = params[0] * c 559ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\tfloat %s = %s * %s;\n", ac4Name.c_str(), p0.c_str(), 560ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org cName.c_str()); 561ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 562ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // d = b^2 - ac4 563ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\tfloat %s = %s * %s - %s;\n", dName.c_str(), 564ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org bVar.c_str(), bVar.c_str(), ac4Name.c_str()); 565ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 566ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // only proceed if discriminant is >= 0 567ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\tif (%s >= 0.0) {\n", dName.c_str()); 568ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 569ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // intermediate value we'll use to compute the roots 570ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // q = -0.5 * (b +/- sqrt(d)) 571ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\t\tfloat %s = -0.5 * (%s + (%s < 0.0 ? -1.0 : 1.0)" 572ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org " * sqrt(%s));\n", qName.c_str(), bVar.c_str(), 573ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org bVar.c_str(), dName.c_str()); 574ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 575ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // compute both roots 576ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // r0 = q * params[1] 577ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\t\tfloat %s = %s * %s;\n", r0Name.c_str(), 578ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org qName.c_str(), p1.c_str()); 579ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // r1 = c / q 580ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\t\tfloat %s = %s / %s;\n", r1Name.c_str(), 581ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org cName.c_str(), qName.c_str()); 582ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 583ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // Note: If there are two roots that both generate radius(t) > 0, the 584ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // Canvas spec says to choose the larger t. 585ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 586ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // so we'll look at the larger one first: 587ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\t\tfloat %s = max(%s, %s);\n", tName.c_str(), 588ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org r0Name.c_str(), r1Name.c_str()); 589ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 590ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // if r(t) > 0, then we're done; t will be our x coordinate 591ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\t\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), 592ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org p5.c_str(), p3.c_str()); 593ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 594ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppend("\t\t"); 595ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers); 596ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 597ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // otherwise, if r(t) for the larger root was <= 0, try the other root 598ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppend("\t\t} else {\n"); 599ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\t\t\t%s = min(%s, %s);\n", tName.c_str(), 600ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org r0Name.c_str(), r1Name.c_str()); 601ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 602ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // if r(t) > 0 for the smaller root, then t will be our x coordinate 603ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\t\t\tif (%s * %s + %s > 0.0) {\n", 604ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org tName.c_str(), p5.c_str(), p3.c_str()); 605ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 606ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppend("\t\t\t"); 607ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers); 608ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org 609ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // end if (r(t) > 0) for smaller root 610ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppend("\t\t\t}\n"); 611ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // end if (r(t) > 0), else, for larger root 612ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppend("\t\t}\n"); 613ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // end if (discriminant >= 0) 614ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppend("\t}\n"); 615ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org } else { 6165cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 617ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // linear case: t = -c/b 618ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(), 619ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org cName.c_str(), bVar.c_str()); 6205cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 621ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org // if r(t) > 0, then t will be the x coordinate 622ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), 623ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org p5.c_str(), p3.c_str()); 624ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppend("\t"); 625ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers); 626ccebafa609c7f2b789cb329ef293ccbece6ee34acommit-bot@chromium.org builder->fsCodeAppend("\t}\n"); 6275cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com } 6285cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com} 6295cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 6308bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.comvoid GrGLConical2Gradient::setData(const GrGLUniformManager& uman, 6318bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrDrawEffect& drawEffect) { 6328bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com INHERITED::setData(uman, drawEffect); 6338bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrConical2Gradient& data = drawEffect.castEffect<GrConical2Gradient>(); 634c0b28fb2217fefe54708b591b5aa202a5615f551commit-bot@chromium.org SkASSERT(data.isDegenerate() == fIsDegenerate); 6353a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalar centerX1 = data.center(); 6363a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalar radius0 = data.radius(); 6373a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalar diffRadius = data.diffRadius(); 6385cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 6395cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com if (fCachedCenter != centerX1 || 6405cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com fCachedRadius != radius0 || 6415cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com fCachedDiffRadius != diffRadius) { 6425cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 6433a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalar a = SkScalarMul(centerX1, centerX1) - diffRadius * diffRadius; 6445cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 6455cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com // When we're in the degenerate (linear) case, the second 6465cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com // value will be INF but the program doesn't read it. (We 6475cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com // use the same 6 uniforms even though we don't need them 6485cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com // all in the linear case just to keep the code complexity 6495cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com // down). 6505cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com float values[6] = { 6513a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalarToFloat(a * 4), 6523a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com 1.f / (SkScalarToFloat(a)), 6533a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalarToFloat(centerX1), 6543a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalarToFloat(radius0), 6553a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalarToFloat(SkScalarMul(radius0, radius0)), 6563a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com SkScalarToFloat(diffRadius) 6575cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com }; 6585cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 65922fedc5d469a05bf11cc6d798529f07899402ecacommit-bot@chromium.org uman.set1fv(fParamUni, 6, values); 6605cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com fCachedCenter = centerX1; 6615cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com fCachedRadius = radius0; 6625cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com fCachedDiffRadius = diffRadius; 6635cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com } 6645cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com} 6655cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 6668bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.comGrGLEffect::EffectKey GrGLConical2Gradient::GenKey(const GrDrawEffect& drawEffect, 6678bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrGLCaps&) { 668d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com enum { 669f813e7169d80b7ba2ecd4b2994391202d977db35bsalomon@google.com kIsDegenerate = 1 << kBaseKeyBitCnt, 670d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com }; 671d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com 672f813e7169d80b7ba2ecd4b2994391202d977db35bsalomon@google.com EffectKey key = GenBaseGradientKey(drawEffect); 6738bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com if (drawEffect.castEffect<GrConical2Gradient>().isDegenerate()) { 674d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com key |= kIsDegenerate; 675d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com } 676d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com return key; 6775cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com} 6785cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 679eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com///////////////////////////////////////////////////////////////////// 6805cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 68138b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.comGrEffectRef* SkTwoPointConicalGradient::asNewEffect(GrContext* context, const SkPaint&) const { 682f40b3ce485ed2e115920f5d9f7898da18d6ba7cebsalomon@google.com SkASSERT(NULL != context); 683b6fb9ce9ba1cc23ecb656cfeb76b8e1fe9792adcbsalomon@google.com SkASSERT(fPtsToUnit.isIdentity()); 684b6fb9ce9ba1cc23ecb656cfeb76b8e1fe9792adcbsalomon@google.com // invert the localM, translate to center1, rotate so center2 is on x axis. 68507d48f7919dea4b366b76b1f40319141051eb816bsalomon@google.com SkMatrix matrix; 686b6fb9ce9ba1cc23ecb656cfeb76b8e1fe9792adcbsalomon@google.com if (!this->getLocalMatrix().invert(&matrix)) { 687f03531dacf0572e4d2c544c8b3a56178ad2a7d36humper@google.com return NULL; 688b6fb9ce9ba1cc23ecb656cfeb76b8e1fe9792adcbsalomon@google.com } 689b6fb9ce9ba1cc23ecb656cfeb76b8e1fe9792adcbsalomon@google.com matrix.postTranslate(-fCenter1.fX, -fCenter1.fY); 690b6fb9ce9ba1cc23ecb656cfeb76b8e1fe9792adcbsalomon@google.com 691eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com SkPoint diff = fCenter2 - fCenter1; 692eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com SkScalar diffLen = diff.length(); 693eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com if (0 != diffLen) { 694eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com SkScalar invDiffLen = SkScalarInvert(diffLen); 695b6fb9ce9ba1cc23ecb656cfeb76b8e1fe9792adcbsalomon@google.com SkMatrix rot; 696b6fb9ce9ba1cc23ecb656cfeb76b8e1fe9792adcbsalomon@google.com rot.setSinCos(-SkScalarMul(invDiffLen, diff.fY), 697b6fb9ce9ba1cc23ecb656cfeb76b8e1fe9792adcbsalomon@google.com SkScalarMul(invDiffLen, diff.fX)); 698b6fb9ce9ba1cc23ecb656cfeb76b8e1fe9792adcbsalomon@google.com matrix.postConcat(rot); 699eec72870460a4d1c624307d8ff5aaddbbe0dd25drileya@google.com } 70007d48f7919dea4b366b76b1f40319141051eb816bsalomon@google.com 70138b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com return GrConical2Gradient::Create(context, *this, matrix, fTileMode); 7025cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com} 7035cf85cab5c294cf70d0d3b52f383de3f9daa4697rileya@google.com 7043515569a78b58fbb57f20ec909fffde8f945c19cbsalomon@google.com#else 7053515569a78b58fbb57f20ec909fffde8f945c19cbsalomon@google.com 70659d9bca234df359715bcfc1d2046315c94c3e23dbsalomon@google.comGrEffectRef* SkTwoPointConicalGradient::asNewEffect(GrContext*, const SkPaint&) const { 7073515569a78b58fbb57f20ec909fffde8f945c19cbsalomon@google.com SkDEBUGFAIL("Should not call in GPU-less build"); 70805614588d877c5112445a5a0478619b187c2dbc4bsalomon@google.com return NULL; 7093515569a78b58fbb57f20ec909fffde8f945c19cbsalomon@google.com} 7103515569a78b58fbb57f20ec909fffde8f945c19cbsalomon@google.com 711069700aef2be72c711e7f665e2250c41a83bd6datwiz@google.com#endif 712bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 713bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com#ifdef SK_DEVELOPER 714bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.comvoid SkTwoPointConicalGradient::toString(SkString* str) const { 715bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append("SkTwoPointConicalGradient: ("); 716bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 717bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append("center1: ("); 718bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->appendScalar(fCenter1.fX); 719bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append(", "); 720bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->appendScalar(fCenter1.fY); 721bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append(") radius1: "); 722bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->appendScalar(fRadius1); 723bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append(" "); 724bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 725bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append("center2: ("); 726bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->appendScalar(fCenter2.fX); 727bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append(", "); 728bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->appendScalar(fCenter2.fY); 729bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append(") radius2: "); 730bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->appendScalar(fRadius2); 731bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append(" "); 732bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 733bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com this->INHERITED::toString(str); 734bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 735bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append(")"); 736bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com} 737bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com#endif 738