1function interp(A, B, t) {
2    return A + (B - A) * t;
3}
4
5function interp_cubic_coords(x1, x2, x3, x4, t)
6{
7    var ab = interp(x1, x2, t);
8    var bc = interp(x2, x3, t);
9    var cd = interp(x3, x4, t);
10    var abc = interp(ab, bc, t);
11    var bcd = interp(bc, cd, t);
12    var abcd = interp(abc, bcd, t);
13    return abcd;
14}
15
16// FIXME : only works for path with single cubic
17function path_partial(value, path) {
18    assert(isArray(path));
19    var out = [];
20    for (var cIndex = 0; cIndex < path.length; ++cIndex) {
21        out[cIndex] = {};
22        var curveKey = Object.keys(path[cIndex])[0];
23        var curve = path[cIndex][curveKey];
24        var outArray;
25        switch (curveKey) {
26            case "cubic":
27                var x1 = curve[0], y1 = curve[1], x2 = curve[2], y2 = curve[3];
28                var x3 = curve[4], y3 = curve[5], x4 = curve[6], y4 = curve[7];
29                var t1 = 0, t2 = value;
30                var ax = interp_cubic_coords(x1, x2, x3, x4, t1);
31                var ay = interp_cubic_coords(y1, y2, y3, y4, t1);
32                var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3);
33                var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3);
34                var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3);
35                var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3);
36                var dx = interp_cubic_coords(x1, x2, x3, x4, t2);
37                var dy = interp_cubic_coords(y1, y2, y3, y4, t2);
38                var mx = ex * 27 - ax * 8 - dx;
39                var my = ey * 27 - ay * 8 - dy;
40                var nx = fx * 27 - ax - dx * 8;
41                var ny = fy * 27 - ay - dy * 8;
42                var bx = (mx * 2 - nx) / 18;
43                var by = (my * 2 - ny) / 18;
44                var cx = (nx * 2 - mx) / 18;
45                var cy = (ny * 2 - my) / 18;
46                outArray = [
47                    ax, ay, bx, by, cx, cy, dx, dy
48                ];
49                break;
50            default:
51                assert(0);  // unimplemented
52        }
53        out[cIndex][curveKey] = outArray;
54    }
55    return out;
56}
57
58function interp_paths(value, paths) {
59    assert(isArray(paths));
60    assert(paths.length == 2);
61    var curves0 = paths[0];
62    assert(isArray(curves0));
63    var curves1 = paths[1];
64    assert(isArray(curves1));
65    assert(curves0.length == curves1.length);
66    var out = [];
67    for (var cIndex = 0; cIndex < curves0.length; ++cIndex) {
68        out[cIndex] = {};
69        var curve0Key = Object.keys(curves0[cIndex])[0];
70        var curve1Key = Object.keys(curves1[cIndex])[0];
71        assert(curve0Key == curve1Key);
72        var curve0 = curves0[cIndex][curve0Key];
73        var curve1 = curves1[cIndex][curve1Key];
74        assert(isArray(curve0));
75        assert(isArray(curve1));
76        assert(curve0.length == curve1.length);
77        var outArray = [];
78        for (var i = 0; i < curve1.length; ++i) {
79            outArray[i] = curve0[i] + (curve1[i] - curve0[i]) * value;
80        }
81        out[cIndex][curve0Key] = outArray;
82    }
83    return out;
84}
85