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