166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis// Copyright (c) 2013 The Chromium Authors. All rights reserved.
266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis// Use of this source code is governed by a BSD-style license that can be
366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis// found in the LICENSE file.
466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis'use strict';
666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisbase.require('base.gl_matrix');
866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisbase.exportTo('base', function() {
1066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var tmpVec2s = [];
1166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  for (var i = 0; i < 8; i++)
1266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    tmpVec2s[i] = vec2.create();
1366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
1466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var tmpVec2a = vec4.create();
1566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var tmpVec4a = vec4.create();
1666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var tmpVec4b = vec4.create();
1766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var tmpMat4 = mat4.create();
1866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var tmpMat4b = mat4.create();
1966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
2066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var p00 = vec2.createXY(0, 0);
2166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var p10 = vec2.createXY(1, 0);
2266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var p01 = vec2.createXY(0, 1);
2366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var p11 = vec2.createXY(1, 1);
2466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
2566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var lerpingVecA = vec2.create();
2666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var lerpingVecB = vec2.create();
2766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  function lerpVec2(out, a, b, amt) {
2866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vec2.scale(lerpingVecA, a, amt);
2966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vec2.scale(lerpingVecB, b, 1 - amt);
3066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vec2.add(out, lerpingVecA, lerpingVecB);
3166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vec2.normalize(out, out);
3266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return out;
3366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  }
3466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
3566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  /**
3666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * @constructor
3766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   */
3866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  function Quad() {
3966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    this.p1 = vec2.create();
4066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    this.p2 = vec2.create();
4166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    this.p3 = vec2.create();
4266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    this.p4 = vec2.create();
4366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  }
4466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
4566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Quad.FromXYWH = function(x, y, w, h) {
4666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var q = new Quad();
4766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vec2.set(q.p1, x, y);
4866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vec2.set(q.p2, x + w, y);
4966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vec2.set(q.p3, x + w, y + h);
5066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vec2.set(q.p4, x, y + h);
5166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return q;
5266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  }
5366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
5466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Quad.FromRect = function(r) {
5566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return new Quad.FromXYWH(
5666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        r.x, r.y,
5766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        r.width, r.height);
5866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  }
5966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
6066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Quad.From4Vecs = function(p1, p2, p3, p4) {
6166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var q = new Quad();
6266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vec2.set(q.p1, p1[0], p1[1]);
6366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vec2.set(q.p2, p2[0], p2[1]);
6466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vec2.set(q.p3, p3[0], p3[1]);
6566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vec2.set(q.p4, p4[0], p4[1]);
6666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return q;
6766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  }
6866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
6966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Quad.From8Array = function(arr) {
7066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    if (arr.length != 8)
7166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      throw new Error('Array must be 8 long');
7266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var q = new Quad();
7366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    q.p1[0] = arr[0];
7466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    q.p1[1] = arr[1];
7566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    q.p2[0] = arr[2];
7666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    q.p2[1] = arr[3];
7766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    q.p3[0] = arr[4];
7866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    q.p3[1] = arr[5];
7966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    q.p4[0] = arr[6];
8066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    q.p4[1] = arr[7];
8166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return q;
8266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  };
8366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
8466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Quad.prototype = {
8566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vecInside: function(vec) {
8666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return vecInTriangle2(vec, this.p1, this.p2, this.p3) ||
8766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          vecInTriangle2(vec, this.p1, this.p3, this.p4);
8866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
8966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
9066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    boundingRect: function() {
9166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var x0 = Math.min(this.p1[0], this.p2[0], this.p3[0], this.p4[0]);
9266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var y0 = Math.min(this.p1[1], this.p2[1], this.p3[1], this.p4[1]);
9366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
9466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var x1 = Math.max(this.p1[0], this.p2[0], this.p3[0], this.p4[0]);
9566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var y1 = Math.max(this.p1[1], this.p2[1], this.p3[1], this.p4[1]);
9666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
9766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return new base.Rect.FromXYWH(x0, y0, x1 - x0, y1 - y0);
9866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
9966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
10066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    clone: function() {
10166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var q = new Quad();
10266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.copy(q.p1, this.p1);
10366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.copy(q.p2, this.p2);
10466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.copy(q.p3, this.p3);
10566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.copy(q.p4, this.p4);
10666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return q;
10766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
10866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
10966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    scale: function(s) {
11066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var q = new Quad();
11166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.scaleFast(q, s);
11266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return q;
11366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
11466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
11566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    scaleFast: function(dstQuad, s) {
11666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.copy(dstQuad.p1, this.p1, s);
11766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.copy(dstQuad.p2, this.p2, s);
11866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.copy(dstQuad.p3, this.p3, s);
11966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.copy(dstQuad.p3, this.p3, s);
12066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
12166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
12266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    isRectangle: function() {
12366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      // Simple rectangle check. Note: will not handle out-of-order components.
12466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var bounds = this.boundingRect();
12566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return (
12666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          bounds.x == this.p1[0] &&
12766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          bounds.y == this.p1[1] &&
12866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          bounds.width == this.p2[0] - this.p1[0] &&
12966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          bounds.y == this.p2[1] &&
13066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          bounds.width == this.p3[0] - this.p1[0] &&
13166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          bounds.height == this.p3[1] - this.p2[1] &&
13266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          bounds.x == this.p4[0] &&
13366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          bounds.height == this.p4[1] - this.p2[1]
13466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      );
13566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
13666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
13766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    projectUnitRect: function(rect) {
13866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var q = new Quad();
13966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.projectUnitRectFast(q, rect);
14066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return q;
14166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
14266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
14366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    projectUnitRectFast: function(dstQuad, rect) {
14466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var v12 = tmpVec2s[0];
14566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var v14 = tmpVec2s[1];
14666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var v23 = tmpVec2s[2];
14766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var v43 = tmpVec2s[3];
14866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var l12, l14, l23, l43;
14966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
15066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.sub(v12, this.p2, this.p1);
15166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      l12 = vec2.length(v12);
15266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.scale(v12, v12, 1 / l12);
15366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
15466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.sub(v14, this.p4, this.p1);
15566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      l14 = vec2.length(v14);
15666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.scale(v14, v14, 1 / l14);
15766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
15866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.sub(v23, this.p3, this.p2);
15966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      l23 = vec2.length(v23);
16066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.scale(v23, v23, 1 / l23);
16166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
16266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.sub(v43, this.p3, this.p4);
16366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      l43 = vec2.length(v43);
16466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.scale(v43, v43, 1 / l43);
16566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
16666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var b12 = tmpVec2s[0];
16766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var b14 = tmpVec2s[1];
16866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var b23 = tmpVec2s[2];
16966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var b43 = tmpVec2s[3];
17066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      lerpVec2(b12, v12, v43, rect.y);
17166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      lerpVec2(b43, v12, v43, 1 - rect.bottom);
17266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      lerpVec2(b14, v14, v23, rect.x);
17366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      lerpVec2(b23, v14, v23, 1 - rect.right);
17466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
17566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.addTwoScaledUnitVectors(tmpVec2a,
17666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis                                   b12, l12 * rect.x,
17766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis                                   b14, l14 * rect.y);
17866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.add(dstQuad.p1, this.p1, tmpVec2a);
17966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
18066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.addTwoScaledUnitVectors(tmpVec2a,
18166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis                                   b12, l12 * -(1.0 - rect.right),
18266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis                                   b23, l23 * rect.y);
18366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.add(dstQuad.p2, this.p2, tmpVec2a);
18466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
18566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
18666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.addTwoScaledUnitVectors(tmpVec2a,
18766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis                                   b43, l43 * -(1.0 - rect.right),
18866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis                                   b23, l23 * -(1.0 - rect.bottom));
18966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.add(dstQuad.p3, this.p3, tmpVec2a);
19066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
19166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.addTwoScaledUnitVectors(tmpVec2a,
19266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis                                   b43, l43 * rect.left,
19366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis                                   b14, l14 * -(1.0 - rect.bottom));
19466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      vec2.add(dstQuad.p4, this.p4, tmpVec2a);
19566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
19666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
19766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    toString: function() {
19866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return 'Quad(' +
19966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          vec2.toString(this.p1) + ', ' +
20066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          vec2.toString(this.p2) + ', ' +
20166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          vec2.toString(this.p3) + ', ' +
20266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          vec2.toString(this.p4) + ')';
20366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    }
20466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  };
20566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
20666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  function sign(p1, p2, p3) {
20766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return (p1[0] - p3[0]) * (p2[1] - p3[1]) -
20866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        (p2[0] - p3[0]) * (p1[1] - p3[1]);
20966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  }
21066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
21166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  function vecInTriangle2(pt, p1, p2, p3) {
21266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var b1 = sign(pt, p1, p2) < 0.0;
21366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var b2 = sign(pt, p2, p3) < 0.0;
21466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var b3 = sign(pt, p3, p1) < 0.0;
21566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return ((b1 == b2) && (b2 == b3));
21666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  }
21766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
21866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  return {
21966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    vecInTriangle2: vecInTriangle2,
22066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    Quad: Quad
22166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  };
22266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis});
223