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