1*c8dee2aaSAndroid Build Coastguard Worker// Note, Skia has a different notion of a "radial" gradient. 2*c8dee2aaSAndroid Build Coastguard Worker// Skia has a twoPointConical gradient that is the same as the 3*c8dee2aaSAndroid Build Coastguard Worker// canvas's RadialGradient. 4*c8dee2aaSAndroid Build Coastguard Worker 5*c8dee2aaSAndroid Build Coastguard Workerfunction RadialCanvasGradient(x1, y1, r1, x2, y2, r2) { 6*c8dee2aaSAndroid Build Coastguard Worker this._shader = null; 7*c8dee2aaSAndroid Build Coastguard Worker this._colors = []; 8*c8dee2aaSAndroid Build Coastguard Worker this._pos = []; 9*c8dee2aaSAndroid Build Coastguard Worker 10*c8dee2aaSAndroid Build Coastguard Worker this.addColorStop = function(offset, color) { 11*c8dee2aaSAndroid Build Coastguard Worker if (offset < 0 || offset > 1 || !isFinite(offset)) { 12*c8dee2aaSAndroid Build Coastguard Worker throw 'offset must be between 0 and 1 inclusively'; 13*c8dee2aaSAndroid Build Coastguard Worker } 14*c8dee2aaSAndroid Build Coastguard Worker 15*c8dee2aaSAndroid Build Coastguard Worker color = parseColor(color); 16*c8dee2aaSAndroid Build Coastguard Worker // From the spec: If multiple stops are added at the same offset on a 17*c8dee2aaSAndroid Build Coastguard Worker // gradient, then they must be placed in the order added, with the first 18*c8dee2aaSAndroid Build Coastguard Worker // one closest to the start of the gradient, and each subsequent one 19*c8dee2aaSAndroid Build Coastguard Worker // infinitesimally further along towards the end point (in effect 20*c8dee2aaSAndroid Build Coastguard Worker // causing all but the first and last stop added at each point to be 21*c8dee2aaSAndroid Build Coastguard Worker // ignored). 22*c8dee2aaSAndroid Build Coastguard Worker // To implement that, if an offset is already in the list, 23*c8dee2aaSAndroid Build Coastguard Worker // we just overwrite its color (since the user can't remove Color stops 24*c8dee2aaSAndroid Build Coastguard Worker // after the fact). 25*c8dee2aaSAndroid Build Coastguard Worker var idx = this._pos.indexOf(offset); 26*c8dee2aaSAndroid Build Coastguard Worker if (idx !== -1) { 27*c8dee2aaSAndroid Build Coastguard Worker this._colors[idx] = color; 28*c8dee2aaSAndroid Build Coastguard Worker } else { 29*c8dee2aaSAndroid Build Coastguard Worker // insert it in sorted order 30*c8dee2aaSAndroid Build Coastguard Worker for (idx = 0; idx < this._pos.length; idx++) { 31*c8dee2aaSAndroid Build Coastguard Worker if (this._pos[idx] > offset) { 32*c8dee2aaSAndroid Build Coastguard Worker break; 33*c8dee2aaSAndroid Build Coastguard Worker } 34*c8dee2aaSAndroid Build Coastguard Worker } 35*c8dee2aaSAndroid Build Coastguard Worker this._pos .splice(idx, 0, offset); 36*c8dee2aaSAndroid Build Coastguard Worker this._colors.splice(idx, 0, color); 37*c8dee2aaSAndroid Build Coastguard Worker } 38*c8dee2aaSAndroid Build Coastguard Worker } 39*c8dee2aaSAndroid Build Coastguard Worker 40*c8dee2aaSAndroid Build Coastguard Worker this._copy = function() { 41*c8dee2aaSAndroid Build Coastguard Worker var rcg = new RadialCanvasGradient(x1, y1, r1, x2, y2, r2); 42*c8dee2aaSAndroid Build Coastguard Worker rcg._colors = this._colors.slice(); 43*c8dee2aaSAndroid Build Coastguard Worker rcg._pos = this._pos.slice(); 44*c8dee2aaSAndroid Build Coastguard Worker return rcg; 45*c8dee2aaSAndroid Build Coastguard Worker } 46*c8dee2aaSAndroid Build Coastguard Worker 47*c8dee2aaSAndroid Build Coastguard Worker this._dispose = function() { 48*c8dee2aaSAndroid Build Coastguard Worker if (this._shader) { 49*c8dee2aaSAndroid Build Coastguard Worker this._shader.delete(); 50*c8dee2aaSAndroid Build Coastguard Worker this._shader = null; 51*c8dee2aaSAndroid Build Coastguard Worker } 52*c8dee2aaSAndroid Build Coastguard Worker } 53*c8dee2aaSAndroid Build Coastguard Worker 54*c8dee2aaSAndroid Build Coastguard Worker this._getShader = function(currentTransform) { 55*c8dee2aaSAndroid Build Coastguard Worker // From the spec: "The points in the linear gradient must be transformed 56*c8dee2aaSAndroid Build Coastguard Worker // as described by the current transformation matrix when rendering." 57*c8dee2aaSAndroid Build Coastguard Worker var pts = [x1, y1, x2, y2]; 58*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Matrix.mapPoints(currentTransform, pts); 59*c8dee2aaSAndroid Build Coastguard Worker var sx1 = pts[0]; 60*c8dee2aaSAndroid Build Coastguard Worker var sy1 = pts[1]; 61*c8dee2aaSAndroid Build Coastguard Worker var sx2 = pts[2]; 62*c8dee2aaSAndroid Build Coastguard Worker var sy2 = pts[3]; 63*c8dee2aaSAndroid Build Coastguard Worker 64*c8dee2aaSAndroid Build Coastguard Worker var sx = currentTransform[0]; 65*c8dee2aaSAndroid Build Coastguard Worker var sy = currentTransform[4]; 66*c8dee2aaSAndroid Build Coastguard Worker var scaleFactor = (Math.abs(sx) + Math.abs(sy))/2; 67*c8dee2aaSAndroid Build Coastguard Worker 68*c8dee2aaSAndroid Build Coastguard Worker var sr1 = r1 * scaleFactor; 69*c8dee2aaSAndroid Build Coastguard Worker var sr2 = r2 * scaleFactor; 70*c8dee2aaSAndroid Build Coastguard Worker 71*c8dee2aaSAndroid Build Coastguard Worker this._dispose(); 72*c8dee2aaSAndroid Build Coastguard Worker this._shader = CanvasKit.Shader.MakeTwoPointConicalGradient( 73*c8dee2aaSAndroid Build Coastguard Worker [sx1, sy1], sr1, [sx2, sy2], sr2, this._colors, this._pos, 74*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.TileMode.Clamp); 75*c8dee2aaSAndroid Build Coastguard Worker return this._shader; 76*c8dee2aaSAndroid Build Coastguard Worker } 77*c8dee2aaSAndroid Build Coastguard Worker} 78