1589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 2589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/* 3589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * Copyright 2012 Google Inc. 4589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * 5589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * Use of this source code is governed by a BSD-style license that can be 6589708bf7c706348b763e8277004cb160b202bdbrileya@google.com * found in the LICENSE file. 7589708bf7c706348b763e8277004cb160b202bdbrileya@google.com */ 8589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 99de5b514d38c5b36066bcdc14fba2f7e5196d372dandov#include "SkTwoPointRadialGradient.h" 10589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 11589708bf7c706348b763e8277004cb160b202bdbrileya@google.com/* Two-point radial gradients are specified by two circles, each with a center 12589708bf7c706348b763e8277004cb160b202bdbrileya@google.com point and radius. The gradient can be considered to be a series of 13589708bf7c706348b763e8277004cb160b202bdbrileya@google.com concentric circles, with the color interpolated from the start circle 14589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (at t=0) to the end circle (at t=1). 15589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 16589708bf7c706348b763e8277004cb160b202bdbrileya@google.com For each point (x, y) in the span, we want to find the 17589708bf7c706348b763e8277004cb160b202bdbrileya@google.com interpolated circle that intersects that point. The center 18589708bf7c706348b763e8277004cb160b202bdbrileya@google.com of the desired circle (Cx, Cy) falls at some distance t 19589708bf7c706348b763e8277004cb160b202bdbrileya@google.com along the line segment between the start point (Sx, Sy) and 20589708bf7c706348b763e8277004cb160b202bdbrileya@google.com end point (Ex, Ey): 21589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 22589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Cx = (1 - t) * Sx + t * Ex (0 <= t <= 1) 23589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Cy = (1 - t) * Sy + t * Ey 24589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 25589708bf7c706348b763e8277004cb160b202bdbrileya@google.com The radius of the desired circle (r) is also a linear interpolation t 26589708bf7c706348b763e8277004cb160b202bdbrileya@google.com between the start and end radii (Sr and Er): 27589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 28589708bf7c706348b763e8277004cb160b202bdbrileya@google.com r = (1 - t) * Sr + t * Er 29589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 30589708bf7c706348b763e8277004cb160b202bdbrileya@google.com But 31589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 32589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (x - Cx)^2 + (y - Cy)^2 = r^2 33589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 34589708bf7c706348b763e8277004cb160b202bdbrileya@google.com so 35589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 36589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (x - ((1 - t) * Sx + t * Ex))^2 37589708bf7c706348b763e8277004cb160b202bdbrileya@google.com + (y - ((1 - t) * Sy + t * Ey))^2 38589708bf7c706348b763e8277004cb160b202bdbrileya@google.com = ((1 - t) * Sr + t * Er)^2 39589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 40589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Solving for t yields 41589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 42589708bf7c706348b763e8277004cb160b202bdbrileya@google.com [(Sx - Ex)^2 + (Sy - Ey)^2 - (Er - Sr)^2)] * t^2 43589708bf7c706348b763e8277004cb160b202bdbrileya@google.com + [2 * (Sx - Ex)(x - Sx) + 2 * (Sy - Ey)(y - Sy) - 2 * (Er - Sr) * Sr] * t 44589708bf7c706348b763e8277004cb160b202bdbrileya@google.com + [(x - Sx)^2 + (y - Sy)^2 - Sr^2] = 0 45589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 46589708bf7c706348b763e8277004cb160b202bdbrileya@google.com To simplify, let Dx = Sx - Ex, Dy = Sy - Ey, Dr = Er - Sr, dx = x - Sx, dy = y - Sy 47589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 48589708bf7c706348b763e8277004cb160b202bdbrileya@google.com [Dx^2 + Dy^2 - Dr^2)] * t^2 49589708bf7c706348b763e8277004cb160b202bdbrileya@google.com + 2 * [Dx * dx + Dy * dy - Dr * Sr] * t 50589708bf7c706348b763e8277004cb160b202bdbrileya@google.com + [dx^2 + dy^2 - Sr^2] = 0 51589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 52589708bf7c706348b763e8277004cb160b202bdbrileya@google.com A quadratic in t. The two roots of the quadratic reflect the two 53589708bf7c706348b763e8277004cb160b202bdbrileya@google.com possible circles on which the point may fall. Solving for t yields 54589708bf7c706348b763e8277004cb160b202bdbrileya@google.com the gradient value to use. 55589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 56589708bf7c706348b763e8277004cb160b202bdbrileya@google.com If a<0, the start circle is entirely contained in the 57589708bf7c706348b763e8277004cb160b202bdbrileya@google.com end circle, and one of the roots will be <0 or >1 (off the line 58589708bf7c706348b763e8277004cb160b202bdbrileya@google.com segment). If a>0, the start circle falls at least partially 59589708bf7c706348b763e8277004cb160b202bdbrileya@google.com outside the end circle (or vice versa), and the gradient 60589708bf7c706348b763e8277004cb160b202bdbrileya@google.com defines a "tube" where a point may be on one circle (on the 61589708bf7c706348b763e8277004cb160b202bdbrileya@google.com inside of the tube) or the other (outside of the tube). We choose 62589708bf7c706348b763e8277004cb160b202bdbrileya@google.com one arbitrarily. 63589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 64589708bf7c706348b763e8277004cb160b202bdbrileya@google.com In order to keep the math to within the limits of fixed point, 65589708bf7c706348b763e8277004cb160b202bdbrileya@google.com we divide the entire quadratic by Dr^2, and replace 66589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (x - Sx)/Dr with x' and (y - Sy)/Dr with y', giving 67589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 68589708bf7c706348b763e8277004cb160b202bdbrileya@google.com [Dx^2 / Dr^2 + Dy^2 / Dr^2 - 1)] * t^2 69589708bf7c706348b763e8277004cb160b202bdbrileya@google.com + 2 * [x' * Dx / Dr + y' * Dy / Dr - Sr / Dr] * t 70589708bf7c706348b763e8277004cb160b202bdbrileya@google.com + [x'^2 + y'^2 - Sr^2/Dr^2] = 0 71589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 72589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (x' and y' are computed by appending the subtract and scale to the 73589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fDstToIndex matrix in the constructor). 74589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 75589708bf7c706348b763e8277004cb160b202bdbrileya@google.com Since the 'A' component of the quadratic is independent of x' and y', it 76589708bf7c706348b763e8277004cb160b202bdbrileya@google.com is precomputed in the constructor. Since the 'B' component is linear in 77589708bf7c706348b763e8277004cb160b202bdbrileya@google.com x' and y', if x and y are linear in the span, 'B' can be computed 78589708bf7c706348b763e8277004cb160b202bdbrileya@google.com incrementally with a simple delta (db below). If it is not (e.g., 79589708bf7c706348b763e8277004cb160b202bdbrileya@google.com a perspective projection), it must be computed in the loop. 80589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 81589708bf7c706348b763e8277004cb160b202bdbrileya@google.com*/ 82589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 83589708bf7c706348b763e8277004cb160b202bdbrileya@google.comnamespace { 84589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 85589708bf7c706348b763e8277004cb160b202bdbrileya@google.cominline SkFixed two_point_radial(SkScalar b, SkScalar fx, SkScalar fy, 86589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar sr2d2, SkScalar foura, 87589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar oneOverTwoA, bool posRoot) { 88589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar c = SkScalarSquare(fx) + SkScalarSquare(fy) - sr2d2; 89589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (0 == foura) { 90589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return SkScalarToFixed(SkScalarDiv(-c, b)); 91589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 92589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 93589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar discrim = SkScalarSquare(b) - SkScalarMul(foura, c); 94589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (discrim < 0) { 95589708bf7c706348b763e8277004cb160b202bdbrileya@google.com discrim = -discrim; 96589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 97589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar rootDiscrim = SkScalarSqrt(discrim); 98589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar result; 99589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (posRoot) { 100589708bf7c706348b763e8277004cb160b202bdbrileya@google.com result = SkScalarMul(-b + rootDiscrim, oneOverTwoA); 101589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 102589708bf7c706348b763e8277004cb160b202bdbrileya@google.com result = SkScalarMul(-b - rootDiscrim, oneOverTwoA); 103589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 104589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return SkScalarToFixed(result); 105589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 106589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 107589708bf7c706348b763e8277004cb160b202bdbrileya@google.comtypedef void (* TwoPointRadialShadeProc)(SkScalar fx, SkScalar dx, 108589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar fy, SkScalar dy, 109589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar b, SkScalar db, 110589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot, 111589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, 112589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count); 113589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 114589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan_twopoint_clamp(SkScalar fx, SkScalar dx, 115589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar fy, SkScalar dy, 116589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar b, SkScalar db, 117589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot, 118589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, 119589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count) { 120589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (; count > 0; --count) { 121589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura, 122589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fOneOverTwoA, posRoot); 123589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed index = SkClampMax(t, 0xFFFF); 124589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(index <= 0xFFFF); 125589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift]; 126589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 127589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy += dy; 128589708bf7c706348b763e8277004cb160b202bdbrileya@google.com b += db; 129589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 130589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 131589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan_twopoint_mirror(SkScalar fx, SkScalar dx, 132589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar fy, SkScalar dy, 133589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar b, SkScalar db, 134589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot, 135589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, 136589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count) { 137589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (; count > 0; --count) { 138589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura, 139589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fOneOverTwoA, posRoot); 140589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed index = mirror_tileproc(t); 141589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(index <= 0xFFFF); 142589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift]; 143589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 144589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy += dy; 145589708bf7c706348b763e8277004cb160b202bdbrileya@google.com b += db; 146589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 147589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 148589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 149589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid shadeSpan_twopoint_repeat(SkScalar fx, SkScalar dx, 150589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar fy, SkScalar dy, 151589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar b, SkScalar db, 152589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot, 153589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache, 154589708bf7c706348b763e8277004cb160b202bdbrileya@google.com int count) { 155589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (; count > 0; --count) { 156589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura, 157589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fOneOverTwoA, posRoot); 158589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed index = repeat_tileproc(t); 159589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(index <= 0xFFFF); 160589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift]; 161589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fx += dx; 162589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fy += dy; 163589708bf7c706348b763e8277004cb160b202bdbrileya@google.com b += db; 164589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 165589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 166589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 167589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 16898e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com///////////////////////////////////////////////////////////////////// 16998e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 170addf2edf3da20f053daa3897cfe2c52d7369a7b1reedSkTwoPointRadialGradient::SkTwoPointRadialGradient(const SkPoint& start, SkScalar startRadius, 171addf2edf3da20f053daa3897cfe2c52d7369a7b1reed const SkPoint& end, SkScalar endRadius, 172addf2edf3da20f053daa3897cfe2c52d7369a7b1reed const Descriptor& desc) 173addf2edf3da20f053daa3897cfe2c52d7369a7b1reed : SkGradientShaderBase(desc) 174addf2edf3da20f053daa3897cfe2c52d7369a7b1reed , fCenter1(start) 175addf2edf3da20f053daa3897cfe2c52d7369a7b1reed , fCenter2(end) 176addf2edf3da20f053daa3897cfe2c52d7369a7b1reed , fRadius1(startRadius) 177addf2edf3da20f053daa3897cfe2c52d7369a7b1reed , fRadius2(endRadius) 178addf2edf3da20f053daa3897cfe2c52d7369a7b1reed{ 179589708bf7c706348b763e8277004cb160b202bdbrileya@google.com init(); 180589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 181589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 182589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkShader::BitmapType SkTwoPointRadialGradient::asABitmap( 183589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkBitmap* bitmap, 184589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkMatrix* matrix, 185589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkShader::TileMode* xy) const { 186589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (bitmap) { 1871c6d64b78b24083ee9fd7411dac8a4a7e2d03a3crileya@google.com this->getGradientTableBitmap(bitmap); 188589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 189589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar diffL = 0; // just to avoid gcc warning 190589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (matrix) { 191589708bf7c706348b763e8277004cb160b202bdbrileya@google.com diffL = SkScalarSqrt(SkScalarSquare(fDiff.fX) + 192589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalarSquare(fDiff.fY)); 193589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 194589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (matrix) { 195589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (diffL) { 196589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar invDiffL = SkScalarInvert(diffL); 197589708bf7c706348b763e8277004cb160b202bdbrileya@google.com matrix->setSinCos(-SkScalarMul(invDiffL, fDiff.fY), 198589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalarMul(invDiffL, fDiff.fX)); 199589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 200589708bf7c706348b763e8277004cb160b202bdbrileya@google.com matrix->reset(); 201589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 202589708bf7c706348b763e8277004cb160b202bdbrileya@google.com matrix->preConcat(fPtsToUnit); 203589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 204589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (xy) { 205589708bf7c706348b763e8277004cb160b202bdbrileya@google.com xy[0] = fTileMode; 206589708bf7c706348b763e8277004cb160b202bdbrileya@google.com xy[1] = kClamp_TileMode; 207589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 208589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return kTwoPointRadial_BitmapType; 209589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 210589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 211589708bf7c706348b763e8277004cb160b202bdbrileya@google.comSkShader::GradientType SkTwoPointRadialGradient::asAGradient( 212589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkShader::GradientInfo* info) const { 213589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (info) { 214589708bf7c706348b763e8277004cb160b202bdbrileya@google.com commonAsAGradient(info); 215589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fPoint[0] = fCenter1; 216589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fPoint[1] = fCenter2; 217589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fRadius[0] = fRadius1; 218589708bf7c706348b763e8277004cb160b202bdbrileya@google.com info->fRadius[1] = fRadius2; 219589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 220589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return kRadial2_GradientType; 221589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 222589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 22387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgsize_t SkTwoPointRadialGradient::contextSize() const { 22487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return sizeof(TwoPointRadialGradientContext); 22587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 22687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 227ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgSkShader::Context* SkTwoPointRadialGradient::onCreateContext(const ContextRec& rec, 228ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org void* storage) const { 22987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // For now, we might have divided by zero, so detect that. 23087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (0 == fDiffRadius) { 23187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return NULL; 23287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } 233e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org return SkNEW_PLACEMENT_ARGS(storage, TwoPointRadialGradientContext, (*this, rec)); 23487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 23587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 23687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkTwoPointRadialGradient::TwoPointRadialGradientContext::TwoPointRadialGradientContext( 237e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org const SkTwoPointRadialGradient& shader, const ContextRec& rec) 238e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org : INHERITED(shader, rec) 23987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org{ 24087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // we don't have a span16 proc 24187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org fFlags &= ~kHasSpan16_Flag; 24287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 24387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 24487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkTwoPointRadialGradient::TwoPointRadialGradientContext::shadeSpan( 24587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org int x, int y, SkPMColor* dstCParam, int count) { 246589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(count > 0); 247589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 24887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkTwoPointRadialGradient& twoPointRadialGradient = 24987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org static_cast<const SkTwoPointRadialGradient&>(fShader); 25087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 251589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPMColor* SK_RESTRICT dstC = dstCParam; 252589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 253589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // Zero difference between radii: fill with transparent black. 25487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (twoPointRadialGradient.fDiffRadius == 0) { 255589708bf7c706348b763e8277004cb160b202bdbrileya@google.com sk_bzero(dstC, count * sizeof(*dstC)); 256589708bf7c706348b763e8277004cb160b202bdbrileya@google.com return; 257589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 258589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkMatrix::MapXYProc dstProc = fDstToIndexProc; 25987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org TileProc proc = twoPointRadialGradient.fTileProc; 26087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkPMColor* SK_RESTRICT cache = fCache->getCache32(); 261589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 26287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkScalar foura = twoPointRadialGradient.fA * 4; 26387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org bool posRoot = twoPointRadialGradient.fDiffRadius < 0; 264589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass != kPerspective_MatrixClass) { 265589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPoint srcPt; 266589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, 267589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 268589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dx, fx = srcPt.fX; 269589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dy, fy = srcPt.fY; 270589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 271589708bf7c706348b763e8277004cb160b202bdbrileya@google.com if (fDstToIndexClass == kFixedStepInX_MatrixClass) { 272589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed fixedX, fixedY; 273589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY); 274589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dx = SkFixedToScalar(fixedX); 275589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dy = SkFixedToScalar(fixedY); 276589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 277589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(fDstToIndexClass == kLinear_MatrixClass); 278589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dx = fDstToIndex.getScaleX(); 279589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dy = fDstToIndex.getSkewY(); 280589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 28187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkScalar b = (SkScalarMul(twoPointRadialGradient.fDiff.fX, fx) + 28287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkScalarMul(twoPointRadialGradient.fDiff.fY, fy) - 28387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org twoPointRadialGradient.fStartRadius) * 2; 28487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkScalar db = (SkScalarMul(twoPointRadialGradient.fDiff.fX, dx) + 28587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkScalarMul(twoPointRadialGradient.fDiff.fY, dy)) * 2; 286589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 287589708bf7c706348b763e8277004cb160b202bdbrileya@google.com TwoPointRadialShadeProc shadeProc = shadeSpan_twopoint_repeat; 28887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (SkShader::kClamp_TileMode == twoPointRadialGradient.fTileMode) { 289589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan_twopoint_clamp; 29087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else if (SkShader::kMirror_TileMode == twoPointRadialGradient.fTileMode) { 291589708bf7c706348b763e8277004cb160b202bdbrileya@google.com shadeProc = shadeSpan_twopoint_mirror; 292589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { 29387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(SkShader::kRepeat_TileMode == twoPointRadialGradient.fTileMode); 294589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 295589708bf7c706348b763e8277004cb160b202bdbrileya@google.com (*shadeProc)(fx, dx, fy, dy, b, db, 29687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org twoPointRadialGradient.fSr2D2, foura, 29787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org twoPointRadialGradient.fOneOverTwoA, posRoot, 298589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstC, cache, count); 299589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } else { // perspective case 300589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstX = SkIntToScalar(x); 301589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar dstY = SkIntToScalar(y); 302589708bf7c706348b763e8277004cb160b202bdbrileya@google.com for (; count > 0; --count) { 303589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkPoint srcPt; 304589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstProc(fDstToIndex, dstX, dstY, &srcPt); 305589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar fx = srcPt.fX; 306589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar fy = srcPt.fY; 30787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkScalar b = (SkScalarMul(twoPointRadialGradient.fDiff.fX, fx) + 30887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkScalarMul(twoPointRadialGradient.fDiff.fY, fy) - 30987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org twoPointRadialGradient.fStartRadius) * 2; 31087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkFixed t = two_point_radial(b, fx, fy, twoPointRadialGradient.fSr2D2, foura, 31187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org twoPointRadialGradient.fOneOverTwoA, posRoot); 312589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkFixed index = proc(t); 313589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkASSERT(index <= 0xFFFF); 314589708bf7c706348b763e8277004cb160b202bdbrileya@google.com *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift]; 315589708bf7c706348b763e8277004cb160b202bdbrileya@google.com dstX += SK_Scalar1; 316589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 317589708bf7c706348b763e8277004cb160b202bdbrileya@google.com } 318589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 319589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 3200f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 32176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkTwoPointRadialGradient::toString(SkString* str) const { 32276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("SkTwoPointRadialGradient: ("); 32376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 32476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("center1: ("); 32576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendScalar(fCenter1.fX); 32676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(", "); 32776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendScalar(fCenter1.fY); 32876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(") radius1: "); 32976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendScalar(fRadius1); 33076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(" "); 33176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 33276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("center2: ("); 33376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendScalar(fCenter2.fX); 33476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(", "); 33576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendScalar(fCenter2.fY); 33676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(") radius2: "); 33776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendScalar(fRadius2); 33876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(" "); 33976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 34076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com this->INHERITED::toString(str); 34176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 34276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(")"); 34376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com} 34476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif 34576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 3469fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 3479fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkTwoPointRadialGradient::SkTwoPointRadialGradient(SkReadBuffer& buffer) 348589708bf7c706348b763e8277004cb160b202bdbrileya@google.com : INHERITED(buffer), 349589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCenter1(buffer.readPoint()), 350589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fCenter2(buffer.readPoint()), 351589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fRadius1(buffer.readScalar()), 352589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fRadius2(buffer.readScalar()) { 353589708bf7c706348b763e8277004cb160b202bdbrileya@google.com init(); 354589708bf7c706348b763e8277004cb160b202bdbrileya@google.com}; 3559fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif 3569fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 3579fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkTwoPointRadialGradient::CreateProc(SkReadBuffer& buffer) { 3589fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed DescriptorScope desc; 3599fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (!desc.unflatten(buffer)) { 3609fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return NULL; 3619fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 3629fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const SkPoint c1 = buffer.readPoint(); 3639fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const SkPoint c2 = buffer.readPoint(); 3649fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const SkScalar r1 = buffer.readScalar(); 3659fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const SkScalar r2 = buffer.readScalar(); 3669fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return SkGradientShader::CreateTwoPointRadial(c1, r1, c2, r2, desc.fColors, desc.fPos, 3679fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed desc.fCount, desc.fTileMode, desc.fGradFlags, 3689fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed desc.fLocalMatrix); 3699fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 370589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 371589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid SkTwoPointRadialGradient::flatten( 3728b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org SkWriteBuffer& buffer) const { 373589708bf7c706348b763e8277004cb160b202bdbrileya@google.com this->INHERITED::flatten(buffer); 374589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.writePoint(fCenter1); 375589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.writePoint(fCenter2); 376589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.writeScalar(fRadius1); 377589708bf7c706348b763e8277004cb160b202bdbrileya@google.com buffer.writeScalar(fRadius2); 378589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 379589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 380589708bf7c706348b763e8277004cb160b202bdbrileya@google.comvoid SkTwoPointRadialGradient::init() { 381589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fDiff = fCenter1 - fCenter2; 382589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fDiffRadius = fRadius2 - fRadius1; 383589708bf7c706348b763e8277004cb160b202bdbrileya@google.com // hack to avoid zero-divide for now 384589708bf7c706348b763e8277004cb160b202bdbrileya@google.com SkScalar inv = fDiffRadius ? SkScalarInvert(fDiffRadius) : 0; 385589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fDiff.fX = SkScalarMul(fDiff.fX, inv); 386589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fDiff.fY = SkScalarMul(fDiff.fY, inv); 387589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fStartRadius = SkScalarMul(fRadius1, inv); 388589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fSr2D2 = SkScalarSquare(fStartRadius); 389589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SK_Scalar1; 390589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fOneOverTwoA = fA ? SkScalarInvert(fA * 2) : 0; 391589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 392589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fPtsToUnit.setTranslate(-fCenter1.fX, -fCenter1.fY); 393589708bf7c706348b763e8277004cb160b202bdbrileya@google.com fPtsToUnit.postScale(inv, inv); 394589708bf7c706348b763e8277004cb160b202bdbrileya@google.com} 395589708bf7c706348b763e8277004cb160b202bdbrileya@google.com 396d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com///////////////////////////////////////////////////////////////////// 397d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 398cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU 399cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 400b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h" 40130ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.h" 4029de5b514d38c5b36066bcdc14fba2f7e5196d372dandov#include "SkGr.h" 4032eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com 404d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com// For brevity 4057510b224e52b9518a8ddf7418db0e9c258f79539kkinnunentypedef GrGLProgramDataManager::UniformHandle UniformHandle; 406d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 4070707c29413a5a3cc1c2d14b8c65b3692af5c7411bsalomon@google.comclass GrGLRadial2Gradient : public GrGLGradientEffect { 408d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 409d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.compublic: 410d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 411b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrGLRadial2Gradient(const GrBackendProcessorFactory& factory, const GrProcessor&); 412d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com virtual ~GrGLRadial2Gradient() { } 413d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 41430ba436f04e61d4505fb854d5fc56079636e0788joshualitt virtual void emitCode(GrGLProgramBuilder*, 415b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor&, 416b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessorKey&, 417f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* outputColor, 418f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* inputColor, 41977af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray&, 420f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const TextureSamplerArray&) SK_OVERRIDE; 421b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE; 422d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 423b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static void GenKey(const GrProcessor&, const GrGLCaps& caps, GrProcessorKeyBuilder* b); 424d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 425d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.comprotected: 426d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 4275fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org UniformHandle fParamUni; 428d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 429d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com const char* fVSVaryingName; 430d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com const char* fFSVaryingName; 431d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 432d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com bool fIsDegenerate; 433d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 434d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com // @{ 435d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com /// Values last uploaded as uniforms 436d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 43781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fCachedCenter; 43881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fCachedRadius; 439d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com bool fCachedPosRoot; 440d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 441d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com // @} 442d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 443d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.comprivate: 444d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 4450707c29413a5a3cc1c2d14b8c65b3692af5c7411bsalomon@google.com typedef GrGLGradientEffect INHERITED; 446d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 447d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com}; 448d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 44998e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com///////////////////////////////////////////////////////////////////// 45098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 45198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.comclass GrRadial2Gradient : public GrGradientEffect { 45298e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.compublic: 453b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static GrFragmentProcessor* Create(GrContext* ctx, 454b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkTwoPointRadialGradient& shader, 455b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkMatrix& matrix, 456b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkShader::TileMode tm) { 45755fad7af61c21d502acb9891d631e8aa29e3628cbsalomon return SkNEW_ARGS(GrRadial2Gradient, (ctx, shader, matrix, tm)); 4580ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com } 45998e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 46098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com virtual ~GrRadial2Gradient() { } 46198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 46298e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com static const char* Name() { return "Two-Point Radial Gradient"; } 463b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE { 464b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return GrTBackendFragmentProcessorFactory<GrRadial2Gradient>::getInstance(); 46598e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com } 46698e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 46798e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com // The radial gradient parameters can collapse to a linear (instead of quadratic) equation. 46881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com bool isDegenerate() const { return SK_Scalar1 == fCenterX1; } 46981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar center() const { return fCenterX1; } 47081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar radius() const { return fRadius0; } 47198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com bool isPosRoot() const { return SkToBool(fPosRoot); } 47298e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 473b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrGLRadial2Gradient GLProcessor; 47498e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 47598e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.comprivate: 476b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual bool onIsEqual(const GrProcessor& sBase) const SK_OVERRIDE { 47749586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const GrRadial2Gradient& s = sBase.cast<GrRadial2Gradient>(); 47870db51fc09464fe8014516561c47aa6fb1a1ed2absalomon@google.com return (INHERITED::onIsEqual(sBase) && 47968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com this->fCenterX1 == s.fCenterX1 && 48068b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com this->fRadius0 == s.fRadius0 && 48168b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com this->fPosRoot == s.fPosRoot); 48268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com } 48368b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com 4840ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com GrRadial2Gradient(GrContext* ctx, 4850ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com const SkTwoPointRadialGradient& shader, 4860ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com const SkMatrix& matrix, 4870ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com SkShader::TileMode tm) 4880ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com : INHERITED(ctx, shader, matrix, tm) 4890ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com , fCenterX1(shader.getCenterX1()) 4900ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com , fRadius0(shader.getStartRadius()) 4915fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org , fPosRoot(shader.getDiffRadius() < 0) { 4925fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org // We pass the linear part of the quadratic as a varying. 4935fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org // float b = 2.0 * (fCenterX1 * x - fRadius0 * z) 4945fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org fBTransform = this->getCoordTransform(); 4955fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkMatrix& bMatrix = *fBTransform.accessMatrix(); 4965fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org bMatrix[SkMatrix::kMScaleX] = 2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMScaleX]) - 4975fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkScalarMul(fRadius0, bMatrix[SkMatrix::kMPersp0])); 4985fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org bMatrix[SkMatrix::kMSkewX] = 2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMSkewX]) - 4995fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkScalarMul(fRadius0, bMatrix[SkMatrix::kMPersp1])); 5005fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org bMatrix[SkMatrix::kMTransX] = 2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMTransX]) - 5015fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkScalarMul(fRadius0, bMatrix[SkMatrix::kMPersp2])); 5025fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org this->addCoordTransform(&fBTransform); 5035fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org } 5040ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com 505b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 50698e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 50798e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com // @{ 50898e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com // Cache of values - these can change arbitrarily, EXCEPT 50998e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com // we shouldn't change between degenerate and non-degenerate?! 51098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 5115fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org GrCoordTransform fBTransform; 5125fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkScalar fCenterX1; 5135fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkScalar fRadius0; 5145fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkBool8 fPosRoot; 51598e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 51698e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com // @} 51798e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 51898e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com typedef GrGradientEffect INHERITED; 51998e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com}; 52098e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 52198e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com///////////////////////////////////////////////////////////////////// 52298e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com 523b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRadial2Gradient); 524d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 525b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrRadial2Gradient::TestCreate(SkRandom* random, 526b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrContext* context, 527b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrDrawTargetCaps&, 528b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTexture**) { 529d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkPoint center1 = {random->nextUScalar1(), random->nextUScalar1()}; 530d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkScalar radius1 = random->nextUScalar1(); 531d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkPoint center2; 532d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkScalar radius2; 533d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com do { 534fb883bf80422c4763921b3d6e2a9ac81596e77bfbsalomon@google.com center2.set(random->nextUScalar1(), random->nextUScalar1()); 535d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com radius2 = random->nextUScalar1 (); 536e197cbf9a3e66bab926bc5e51962752dad5221a0bsalomon@google.com // There is a bug in two point radial gradients with identical radii 537d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com } while (radius1 == radius2); 538d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 539d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkColor colors[kMaxRandomGradientColors]; 540d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkScalar stopsArray[kMaxRandomGradientColors]; 541d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkScalar* stops = stopsArray; 542d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkShader::TileMode tm; 543d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com int colorCount = RandomGradientParams(random, colors, &stops, &tm); 544d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com SkAutoTUnref<SkShader> shader(SkGradientShader::CreateTwoPointRadial(center1, radius1, 545d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com center2, radius2, 546d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com colors, stops, colorCount, 547d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com tm)); 548e197cbf9a3e66bab926bc5e51962752dad5221a0bsalomon@google.com SkPaint paint; 549b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrFragmentProcessor* fp; 55083d081ae1d731b5039e99823620f5e287542ee39bsalomon GrColor paintColor; 551b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkAssertResult(shader->asFragmentProcessor(context, paint, NULL, &paintColor, &fp)); 552b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return fp; 553d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com} 554d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 555d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com///////////////////////////////////////////////////////////////////// 556d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 557b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGLRadial2Gradient::GrGLRadial2Gradient(const GrBackendProcessorFactory& factory, 558b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessor& processor) 559d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com : INHERITED(factory) 560d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com , fVSVaryingName(NULL) 561d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com , fFSVaryingName(NULL) 56281712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com , fCachedCenter(SK_ScalarMax) 56381712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com , fCachedRadius(-SK_ScalarMax) 564d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com , fCachedPosRoot(0) { 565d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 566b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrRadial2Gradient& data = processor.cast<GrRadial2Gradient>(); 567d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com fIsDegenerate = data.isDegenerate(); 568d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 569d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 57030ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLRadial2Gradient::emitCode(GrGLProgramBuilder* builder, 571b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor&, 572b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessorKey& key, 573f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* outputColor, 574f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const char* inputColor, 57577af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray& coords, 576f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com const TextureSamplerArray& samplers) { 57763e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon uint32_t baseKey = key.get32(0); 57863e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon this->emitUniforms(builder, baseKey); 57930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fParamUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, 5805fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org kFloat_GrSLType, "Radial2FSParams", 6); 5815fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org 5825fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkString cName("c"); 5835fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkString ac4Name("ac4"); 5845fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkString rootName("root"); 5855fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkString t; 5865fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkString p0; 5875fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkString p1; 5885fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkString p2; 5895fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkString p3; 5905fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkString p4; 5915fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkString p5; 5925fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org builder->getUniformVariable(fParamUni).appendArrayAccess(0, &p0); 5935fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org builder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1); 5945fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org builder->getUniformVariable(fParamUni).appendArrayAccess(2, &p2); 5955fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org builder->getUniformVariable(fParamUni).appendArrayAccess(3, &p3); 5965fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org builder->getUniformVariable(fParamUni).appendArrayAccess(4, &p4); 5975fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org builder->getUniformVariable(fParamUni).appendArrayAccess(5, &p5); 5985fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org 59930ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 6005fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org // We interpolate the linear component in coords[1]. 60123e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt SkASSERT(coords[0].getType() == coords[1].getType()); 6025fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org const char* coords2D; 6035fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org SkString bVar; 60423e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt if (kVec3f_GrSLType == coords[0].getType()) { 60530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\tvec3 interpolants = vec3(%s.xy, %s.x) / %s.z;\n", 6065fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org coords[0].c_str(), coords[1].c_str(), coords[0].c_str()); 6075fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org coords2D = "interpolants.xy"; 6085fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org bVar = "interpolants.z"; 6095fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org } else { 6105fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org coords2D = coords[0].c_str(); 6115fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org bVar.printf("%s.x", coords[1].c_str()); 612d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com } 613d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 6145fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org // c = (x^2)+(y^2) - params[4] 61530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n", 6165fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org cName.c_str(), coords2D, coords2D, p4.c_str()); 617d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 6185fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org // If we aren't degenerate, emit some extra code, and accept a slightly 6195fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org // more complex coord. 6205fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org if (!fIsDegenerate) { 621d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 6225fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org // ac4 = 4.0 * params[0] * c 62330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\tfloat %s = %s * 4.0 * %s;\n", 6245fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org ac4Name.c_str(), p0.c_str(), 6255fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org cName.c_str()); 6265fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org 6275fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org // root = sqrt(b^2-4ac) 6285fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org // (abs to avoid exception due to fp precision) 62930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\tfloat %s = sqrt(abs(%s*%s - %s));\n", 6305fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org rootName.c_str(), bVar.c_str(), bVar.c_str(), 6315fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org ac4Name.c_str()); 632d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 6335fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org // t is: (-b + params[5] * sqrt(b^2-4ac)) * params[1] 6345fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org t.printf("(-%s + %s * %s) * %s", bVar.c_str(), p5.c_str(), 6355fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org rootName.c_str(), p1.c_str()); 6365fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org } else { 6375fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org // t is: -c/b 6385fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org t.printf("-%s / %s", cName.c_str(), bVar.c_str()); 639f78df33efc72167f94da1b0476c9a86ba18a5f2cbsalomon@google.com } 6405fd7d5c20a15094da3fb6dc1d59955fd8f3217d7commit-bot@chromium.org 64163e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon this->emitColor(builder, t.c_str(), baseKey, outputColor, inputColor, samplers); 642d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 643d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 6447510b224e52b9518a8ddf7418db0e9c258f79539kkinnunenvoid GrGLRadial2Gradient::setData(const GrGLProgramDataManager& pdman, 645b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessor& processor) { 646b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt INHERITED::setData(pdman, processor); 647b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrRadial2Gradient& data = processor.cast<GrRadial2Gradient>(); 64896ae688f03f05a53c2ae6e66a431e180b90be9cdcommit-bot@chromium.org SkASSERT(data.isDegenerate() == fIsDegenerate); 64981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar centerX1 = data.center(); 65081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar radius0 = data.radius(); 651d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com if (fCachedCenter != centerX1 || 652d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com fCachedRadius != radius0 || 653d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com fCachedPosRoot != data.isPosRoot()) { 654d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 65581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar a = SkScalarMul(centerX1, centerX1) - SK_Scalar1; 656d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 657d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com // When we're in the degenerate (linear) case, the second 658d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com // value will be INF but the program doesn't read it. (We 659d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com // use the same 6 uniforms even though we don't need them 660d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com // all in the linear case just to keep the code complexity 661d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com // down). 662d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com float values[6] = { 66381712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalarToFloat(a), 66481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com 1 / (2.f * SkScalarToFloat(a)), 66581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalarToFloat(centerX1), 66681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalarToFloat(radius0), 66781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalarToFloat(SkScalarMul(radius0, radius0)), 668d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com data.isPosRoot() ? 1.f : -1.f 669d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com }; 670d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 6717510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set1fv(fParamUni, 6, values); 672d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com fCachedCenter = centerX1; 673d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com fCachedRadius = radius0; 674d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com fCachedPosRoot = data.isPosRoot(); 675d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com } 676d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 677d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 678b0a8a377f832c59cee939ad721e1f87d378b7142joshualittvoid GrGLRadial2Gradient::GenKey(const GrProcessor& processor, 679b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrGLCaps&, GrProcessorKeyBuilder* b) { 68063e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon uint32_t* key = b->add32n(2); 681b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt key[0] = GenBaseGradientKey(processor); 682b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt key[1] = processor.cast<GrRadial2Gradient>().isDegenerate(); 683d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 684d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 68598e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com///////////////////////////////////////////////////////////////////// 6861c6d64b78b24083ee9fd7411dac8a4a7e2d03a3crileya@google.com 687b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkTwoPointRadialGradient::asFragmentProcessor(GrContext* context, const SkPaint& paint, 688b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkMatrix* localMatrix, GrColor* paintColor, 689b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrFragmentProcessor** fp) const { 69049f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(context); 6919de5b514d38c5b36066bcdc14fba2f7e5196d372dandov 692f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com // invert the localM, translate to center1 (fPtsToUni), rotate so center2 is on x axis. 693dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com SkMatrix matrix; 694f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com if (!this->getLocalMatrix().invert(&matrix)) { 6959de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 69698e8b6de04e4c20451fbe3353645e3e384a76550rileya@google.com } 69796fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org if (localMatrix) { 69896fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org SkMatrix inv; 69996fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org if (!localMatrix->invert(&inv)) { 7009de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 70196fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org } 70296fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org matrix.postConcat(inv); 70396fb7489ba46909c3f81bb2d94755e7d4ccb5fadcommit-bot@chromium.org } 704f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com matrix.postConcat(fPtsToUnit); 70520c301bd1aa4578c6d0abb23ac2c72b5fbb436dbskia.committer@gmail.com 706f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com SkScalar diffLen = fDiff.length(); 707f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com if (0 != diffLen) { 708f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com SkScalar invDiffLen = SkScalarInvert(diffLen); 709f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com SkMatrix rot; 710f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com rot.setSinCos(-SkScalarMul(invDiffLen, fDiff.fY), 711f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com SkScalarMul(invDiffLen, fDiff.fX)); 712f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com matrix.postConcat(rot); 713dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com } 714dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com 71583d081ae1d731b5039e99823620f5e287542ee39bsalomon *paintColor = SkColor2GrColorJustAlpha(paint.getColor()); 716b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt *fp = GrRadial2Gradient::Create(context, *this, matrix, fTileMode); 7179de5b514d38c5b36066bcdc14fba2f7e5196d372dandov 7189de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return true; 719d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com} 720d7cc651b8da11d52ae90e910b948f5e2d15daaf9rileya@google.com 721cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else 722cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 723b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkTwoPointRadialGradient::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix*, 724b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrColor*, GrFragmentProcessor**) const { 725cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com SkDEBUGFAIL("Should not call in GPU-less build"); 7269de5b514d38c5b36066bcdc14fba2f7e5196d372dandov return false; 727cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com} 728cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 729cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif 730