You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ft...@apache.org on 2015/09/17 17:29:01 UTC

[46/51] [abbrv] [partial] git commit: [flex-falcon] [refs/heads/JsToAs] - Added GCL extern.

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/bootstrap/webworkers.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/bootstrap/webworkers.js b/externs/GCL/externs/goog/bootstrap/webworkers.js
new file mode 100644
index 0000000..7799a0a
--- /dev/null
+++ b/externs/GCL/externs/goog/bootstrap/webworkers.js
@@ -0,0 +1,37 @@
+// Copyright 2010 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview A bootstrap for dynamically requiring Closure within an HTML5
+ * Web Worker context. To use this, first set CLOSURE_BASE_PATH to the directory
+ * containing base.js (relative to the main script), then use importScripts to
+ * load this file and base.js (in that order). After this you can use
+ * goog.require for further imports.
+ *
+ * @nocompile
+ */
+
+
+/**
+ * Imports a script using the Web Worker importScript API.
+ *
+ * @param {string} src The script source.
+ * @return {boolean} True if the script was imported, false otherwise.
+ */
+this.CLOSURE_IMPORT_SCRIPT = (function(global) {
+  return function(src) {
+    global['importScripts'](src);
+    return true;
+  };
+})(this);

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/color/alpha.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/color/alpha.js b/externs/GCL/externs/goog/color/alpha.js
new file mode 100644
index 0000000..4cd4781
--- /dev/null
+++ b/externs/GCL/externs/goog/color/alpha.js
@@ -0,0 +1,472 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Utilities related to alpha/transparent colors and alpha color
+ * conversion.
+ */
+
+goog.provide('goog.color.alpha');
+
+goog.require('goog.color');
+
+
+/**
+ * Parses an alpha color out of a string.
+ * @param {string} str Color in some format.
+ * @return {{hex: string, type: string}} 'hex' is a string containing
+ *     a hex representation of the color, and 'type' is a string
+ *     containing the type of color format passed in ('hex', 'rgb', 'named').
+ */
+goog.color.alpha.parse = function(str) {
+  var result = {};
+  str = String(str);
+
+  var maybeHex = goog.color.prependHashIfNecessaryHelper(str);
+  if (goog.color.alpha.isValidAlphaHexColor_(maybeHex)) {
+    result.hex = goog.color.alpha.normalizeAlphaHex_(maybeHex);
+    result.type = 'hex';
+    return result;
+  } else {
+    var rgba = goog.color.alpha.isValidRgbaColor_(str);
+    if (rgba.length) {
+      result.hex = goog.color.alpha.rgbaArrayToHex(rgba);
+      result.type = 'rgba';
+      return result;
+    } else {
+      var hsla = goog.color.alpha.isValidHslaColor_(str);
+      if (hsla.length) {
+        result.hex = goog.color.alpha.hslaArrayToHex(hsla);
+        result.type = 'hsla';
+        return result;
+      }
+    }
+  }
+  throw Error(str + ' is not a valid color string');
+};
+
+
+/**
+ * Converts a hex representation of a color to RGBA.
+ * @param {string} hexColor Color to convert.
+ * @return {string} string of the form 'rgba(R,G,B,A)' which can be used in
+ *    styles.
+ */
+goog.color.alpha.hexToRgbaStyle = function(hexColor) {
+  return goog.color.alpha.rgbaStyle_(goog.color.alpha.hexToRgba(hexColor));
+};
+
+
+/**
+ * Gets the hex color part of an alpha hex color. For example, from '#abcdef55'
+ * return '#abcdef'.
+ * @param {string} colorWithAlpha The alpha hex color to get the hex color from.
+ * @return {string} The hex color where the alpha part has been stripped off.
+ */
+goog.color.alpha.extractHexColor = function(colorWithAlpha) {
+  if (goog.color.alpha.isValidAlphaHexColor_(colorWithAlpha)) {
+    var fullColor = goog.color.prependHashIfNecessaryHelper(colorWithAlpha);
+    var normalizedColor = goog.color.alpha.normalizeAlphaHex_(fullColor);
+    return normalizedColor.substring(0, 7);
+  } else {
+    throw Error(colorWithAlpha + ' is not a valid 8-hex color string');
+  }
+};
+
+
+/**
+ * Gets the alpha color part of an alpha hex color. For example, from
+ * '#abcdef55' return '55'. The result is guaranteed to be two characters long.
+ * @param {string} colorWithAlpha The alpha hex color to get the hex color from.
+ * @return {string} The hex color where the alpha part has been stripped off.
+ */
+goog.color.alpha.extractAlpha = function(colorWithAlpha) {
+  if (goog.color.alpha.isValidAlphaHexColor_(colorWithAlpha)) {
+    var fullColor = goog.color.prependHashIfNecessaryHelper(colorWithAlpha);
+    var normalizedColor = goog.color.alpha.normalizeAlphaHex_(fullColor);
+    return normalizedColor.substring(7, 9);
+  } else {
+    throw Error(colorWithAlpha + ' is not a valid 8-hex color string');
+  }
+};
+
+
+/**
+ * Regular expression for extracting the digits in a hex color quadruplet.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.alpha.hexQuadrupletRe_ = /#(.)(.)(.)(.)/;
+
+
+/**
+ * Normalize a hex representation of an alpha color.
+ * @param {string} hexColor an alpha hex color string.
+ * @return {string} hex color in the format '#rrggbbaa' with all lowercase
+ *     literals.
+ * @private
+ */
+goog.color.alpha.normalizeAlphaHex_ = function(hexColor) {
+  if (!goog.color.alpha.isValidAlphaHexColor_(hexColor)) {
+    throw Error("'" + hexColor + "' is not a valid alpha hex color");
+  }
+  if (hexColor.length == 5) { // of the form #RGBA
+    hexColor = hexColor.replace(goog.color.alpha.hexQuadrupletRe_,
+        '#$1$1$2$2$3$3$4$4');
+  }
+  return hexColor.toLowerCase();
+};
+
+
+/**
+ * Converts an 8-hex representation of a color to RGBA.
+ * @param {string} hexColor Color to convert.
+ * @return {!Array<number>} array containing [r, g, b, a].
+ *     r, g, b are ints between 0
+ *     and 255, and a is a value between 0 and 1.
+ */
+goog.color.alpha.hexToRgba = function(hexColor) {
+  // TODO(user): Enhance code sharing with goog.color, for example by
+  //     adding a goog.color.genericHexToRgb method.
+  hexColor = goog.color.alpha.normalizeAlphaHex_(hexColor);
+  var r = parseInt(hexColor.substr(1, 2), 16);
+  var g = parseInt(hexColor.substr(3, 2), 16);
+  var b = parseInt(hexColor.substr(5, 2), 16);
+  var a = parseInt(hexColor.substr(7, 2), 16);
+
+  return [r, g, b, a / 255];
+};
+
+
+/**
+ * Converts a color from RGBA to hex representation.
+ * @param {number} r Amount of red, int between 0 and 255.
+ * @param {number} g Amount of green, int between 0 and 255.
+ * @param {number} b Amount of blue, int between 0 and 255.
+ * @param {number} a Amount of alpha, float between 0 and 1.
+ * @return {string} hex representation of the color.
+ */
+goog.color.alpha.rgbaToHex = function(r, g, b, a) {
+  var intAlpha = Math.floor(a * 255);
+  if (isNaN(intAlpha) || intAlpha < 0 || intAlpha > 255) {
+    // TODO(user): The CSS spec says the value should be clamped.
+    throw Error('"(' + r + ',' + g + ',' + b + ',' + a +
+        '") is not a valid RGBA color');
+  }
+  var hexA = goog.color.prependZeroIfNecessaryHelper(intAlpha.toString(16));
+  return goog.color.rgbToHex(r, g, b) + hexA;
+};
+
+
+/**
+ * Converts a color from HSLA to hex representation.
+ * @param {number} h Amount of hue, int between 0 and 360.
+ * @param {number} s Amount of saturation, int between 0 and 100.
+ * @param {number} l Amount of lightness, int between 0 and 100.
+ * @param {number} a Amount of alpha, float between 0 and 1.
+ * @return {string} hex representation of the color.
+ */
+goog.color.alpha.hslaToHex = function(h, s, l, a) {
+  var intAlpha = Math.floor(a * 255);
+  if (isNaN(intAlpha) || intAlpha < 0 || intAlpha > 255) {
+    // TODO(user): The CSS spec says the value should be clamped.
+    throw Error('"(' + h + ',' + s + ',' + l + ',' + a +
+        '") is not a valid HSLA color');
+  }
+  var hexA = goog.color.prependZeroIfNecessaryHelper(intAlpha.toString(16));
+  return goog.color.hslToHex(h, s / 100, l / 100) + hexA;
+};
+
+
+/**
+ * Converts a color from RGBA to hex representation.
+ * @param {Array<number>} rgba Array of [r, g, b, a], with r, g, b in [0, 255]
+ *     and a in [0, 1].
+ * @return {string} hex representation of the color.
+ */
+goog.color.alpha.rgbaArrayToHex = function(rgba) {
+  return goog.color.alpha.rgbaToHex(rgba[0], rgba[1], rgba[2], rgba[3]);
+};
+
+
+/**
+ * Converts a color from RGBA to an RGBA style string.
+ * @param {number} r Value of red, in [0, 255].
+ * @param {number} g Value of green, in [0, 255].
+ * @param {number} b Value of blue, in [0, 255].
+ * @param {number} a Value of alpha, in [0, 1].
+ * @return {string} An 'rgba(r,g,b,a)' string ready for use in a CSS rule.
+ */
+goog.color.alpha.rgbaToRgbaStyle = function(r, g, b, a) {
+  if (isNaN(r) || r < 0 || r > 255 ||
+      isNaN(g) || g < 0 || g > 255 ||
+      isNaN(b) || b < 0 || b > 255 ||
+      isNaN(a) || a < 0 || a > 1) {
+    throw Error('"(' + r + ',' + g + ',' + b + ',' + a +
+        ')" is not a valid RGBA color');
+  }
+  return goog.color.alpha.rgbaStyle_([r, g, b, a]);
+};
+
+
+/**
+ * Converts a color from RGBA to an RGBA style string.
+ * @param {(Array<number>|Float32Array)} rgba Array of [r, g, b, a],
+ *     with r, g, b in [0, 255] and a in [0, 1].
+ * @return {string} An 'rgba(r,g,b,a)' string ready for use in a CSS rule.
+ */
+goog.color.alpha.rgbaArrayToRgbaStyle = function(rgba) {
+  return goog.color.alpha.rgbaToRgbaStyle(rgba[0], rgba[1], rgba[2], rgba[3]);
+};
+
+
+/**
+ * Converts a color from HSLA to hex representation.
+ * @param {Array<number>} hsla Array of [h, s, l, a], where h is an integer in
+ *     [0, 360], s and l are integers in [0, 100], and a is in [0, 1].
+ * @return {string} hex representation of the color, such as '#af457eff'.
+ */
+goog.color.alpha.hslaArrayToHex = function(hsla) {
+  return goog.color.alpha.hslaToHex(hsla[0], hsla[1], hsla[2], hsla[3]);
+};
+
+
+/**
+ * Converts a color from HSLA to an RGBA style string.
+ * @param {Array<number>} hsla Array of [h, s, l, a], where h is and integer in
+ *     [0, 360], s and l are integers in [0, 100], and a is in [0, 1].
+ * @return {string} An 'rgba(r,g,b,a)' string ready for use in a CSS rule.
+ */
+goog.color.alpha.hslaArrayToRgbaStyle = function(hsla) {
+  return goog.color.alpha.hslaToRgbaStyle(hsla[0], hsla[1], hsla[2], hsla[3]);
+};
+
+
+/**
+ * Converts a color from HSLA to an RGBA style string.
+ * @param {number} h Amount of hue, int between 0 and 360.
+ * @param {number} s Amount of saturation, int between 0 and 100.
+ * @param {number} l Amount of lightness, int between 0 and 100.
+ * @param {number} a Amount of alpha, float between 0 and 1.
+ * @return {string} An 'rgba(r,g,b,a)' string ready for use in a CSS rule.
+ *     styles.
+ */
+goog.color.alpha.hslaToRgbaStyle = function(h, s, l, a) {
+  return goog.color.alpha.rgbaStyle_(goog.color.alpha.hslaToRgba(h, s, l, a));
+};
+
+
+/**
+ * Converts a color from HSLA color space to RGBA color space.
+ * @param {number} h Amount of hue, int between 0 and 360.
+ * @param {number} s Amount of saturation, int between 0 and 100.
+ * @param {number} l Amount of lightness, int between 0 and 100.
+ * @param {number} a Amount of alpha, float between 0 and 1.
+ * @return {!Array<number>} [r, g, b, a] values for the color, where r, g, b
+ *     are integers in [0, 255] and a is a float in [0, 1].
+ */
+goog.color.alpha.hslaToRgba = function(h, s, l, a) {
+  return goog.color.hslToRgb(h, s / 100, l / 100).concat(a);
+};
+
+
+/**
+ * Converts a color from RGBA color space to HSLA color space.
+ * Modified from {@link http://en.wikipedia.org/wiki/HLS_color_space}.
+ * @param {number} r Value of red, in [0, 255].
+ * @param {number} g Value of green, in [0, 255].
+ * @param {number} b Value of blue, in [0, 255].
+ * @param {number} a Value of alpha, in [0, 255].
+ * @return {!Array<number>} [h, s, l, a] values for the color, with h an int in
+ *     [0, 360] and s, l and a in [0, 1].
+ */
+goog.color.alpha.rgbaToHsla = function(r, g, b, a) {
+  return goog.color.rgbToHsl(r, g, b).concat(a);
+};
+
+
+/**
+ * Converts a color from RGBA color space to HSLA color space.
+ * @param {Array<number>} rgba [r, g, b, a] values for the color, each in
+ *     [0, 255].
+ * @return {!Array<number>} [h, s, l, a] values for the color, with h in
+ *     [0, 360] and s, l and a in [0, 1].
+ */
+goog.color.alpha.rgbaArrayToHsla = function(rgba) {
+  return goog.color.alpha.rgbaToHsla(rgba[0], rgba[1], rgba[2], rgba[3]);
+};
+
+
+/**
+ * Helper for isValidAlphaHexColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.alpha.validAlphaHexColorRe_ = /^#(?:[0-9a-f]{4}){1,2}$/i;
+
+
+/**
+ * Checks if a string is a valid alpha hex color.  We expect strings of the
+ * format #RRGGBBAA (ex: #1b3d5f5b) or #RGBA (ex: #3CAF == #33CCAAFF).
+ * @param {string} str String to check.
+ * @return {boolean} Whether the string is a valid alpha hex color.
+ * @private
+ */
+// TODO(user): Support percentages when goog.color also supports them.
+goog.color.alpha.isValidAlphaHexColor_ = function(str) {
+  return goog.color.alpha.validAlphaHexColorRe_.test(str);
+};
+
+
+/**
+ * Helper for isNormalizedAlphaHexColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.alpha.normalizedAlphaHexColorRe_ = /^#[0-9a-f]{8}$/;
+
+
+/**
+ * Checks if a string is a normalized alpha hex color.
+ * We expect strings of the format #RRGGBBAA (ex: #1b3d5f5b)
+ * using only lowercase letters.
+ * @param {string} str String to check.
+ * @return {boolean} Whether the string is a normalized hex color.
+ * @private
+ */
+goog.color.alpha.isNormalizedAlphaHexColor_ = function(str) {
+  return goog.color.alpha.normalizedAlphaHexColorRe_.test(str);
+};
+
+
+/**
+ * Regular expression for matching and capturing RGBA style strings. Helper for
+ * isValidRgbaColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.alpha.rgbaColorRe_ =
+    /^(?:rgba)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|1|0\.\d{0,10})\)$/i;
+
+
+/**
+ * Regular expression for matching and capturing HSLA style strings. Helper for
+ * isValidHslaColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.alpha.hslaColorRe_ =
+    /^(?:hsla)\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\%,\s?(0|[1-9]\d{0,2})\%,\s?(0|1|0\.\d{0,10})\)$/i;
+
+
+/**
+ * Checks if a string is a valid rgba color.  We expect strings of the format
+ * '(r, g, b, a)', or 'rgba(r, g, b, a)', where r, g, b are ints in [0, 255]
+ *     and a is a float in [0, 1].
+ * @param {string} str String to check.
+ * @return {!Array<number>} the integers [r, g, b, a] for valid colors or the
+ *     empty array for invalid colors.
+ * @private
+ */
+goog.color.alpha.isValidRgbaColor_ = function(str) {
+  // Each component is separate (rather than using a repeater) so we can
+  // capture the match. Also, we explicitly set each component to be either 0,
+  // or start with a non-zero, to prevent octal numbers from slipping through.
+  var regExpResultArray = str.match(goog.color.alpha.rgbaColorRe_);
+  if (regExpResultArray) {
+    var r = Number(regExpResultArray[1]);
+    var g = Number(regExpResultArray[2]);
+    var b = Number(regExpResultArray[3]);
+    var a = Number(regExpResultArray[4]);
+    if (r >= 0 && r <= 255 &&
+        g >= 0 && g <= 255 &&
+        b >= 0 && b <= 255 &&
+        a >= 0 && a <= 1) {
+      return [r, g, b, a];
+    }
+  }
+  return [];
+};
+
+
+/**
+ * Checks if a string is a valid hsla color.  We expect strings of the format
+ * 'hsla(h, s, l, a)', where s in an int in [0, 360], s and l are percentages
+ *     between 0 and 100 such as '50%' or '70%', and a is a float in [0, 1].
+ * @param {string} str String to check.
+ * @return {!Array<number>} the integers [h, s, l, a] for valid colors or the
+ *     empty array for invalid colors.
+ * @private
+ */
+goog.color.alpha.isValidHslaColor_ = function(str) {
+  // Each component is separate (rather than using a repeater) so we can
+  // capture the match. Also, we explicitly set each component to be either 0,
+  // or start with a non-zero, to prevent octal numbers from slipping through.
+  var regExpResultArray = str.match(goog.color.alpha.hslaColorRe_);
+  if (regExpResultArray) {
+    var h = Number(regExpResultArray[1]);
+    var s = Number(regExpResultArray[2]);
+    var l = Number(regExpResultArray[3]);
+    var a = Number(regExpResultArray[4]);
+    if (h >= 0 && h <= 360 &&
+        s >= 0 && s <= 100 &&
+        l >= 0 && l <= 100 &&
+        a >= 0 && a <= 1) {
+      return [h, s, l, a];
+    }
+  }
+  return [];
+};
+
+
+/**
+ * Takes an array of [r, g, b, a] and converts it into a string appropriate for
+ * CSS styles. The alpha channel value is rounded to 3 decimal places to make
+ * sure the produced string is not too long.
+ * @param {Array<number>} rgba [r, g, b, a] with r, g, b in [0, 255] and a
+ *     in [0, 1].
+ * @return {string} string of the form 'rgba(r,g,b,a)'.
+ * @private
+ */
+goog.color.alpha.rgbaStyle_ = function(rgba) {
+  var roundedRgba = rgba.slice(0);
+  roundedRgba[3] = Math.round(rgba[3] * 1000) / 1000;
+  return 'rgba(' + roundedRgba.join(',') + ')';
+};
+
+
+/**
+ * Converts from h,s,v,a values to a hex string
+ * @param {number} h Hue, in [0, 1].
+ * @param {number} s Saturation, in [0, 1].
+ * @param {number} v Value, in [0, 255].
+ * @param {number} a Alpha, in [0, 1].
+ * @return {string} hex representation of the color.
+ */
+goog.color.alpha.hsvaToHex = function(h, s, v, a) {
+  var alpha = Math.floor(a * 255);
+  return goog.color.hsvArrayToHex([h, s, v]) +
+         goog.color.prependZeroIfNecessaryHelper(alpha.toString(16));
+};
+
+
+/**
+ * Converts from an HSVA array to a hex string
+ * @param {Array<number>} hsva Array of [h, s, v, a] in
+ *     [[0, 1], [0, 1], [0, 255], [0, 1]].
+ * @return {string} hex representation of the color.
+ */
+goog.color.alpha.hsvaArrayToHex = function(hsva) {
+  return goog.color.alpha.hsvaToHex(hsva[0], hsva[1], hsva[2], hsva[3]);
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/color/color.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/color/color.js b/externs/GCL/externs/goog/color/color.js
new file mode 100644
index 0000000..8220532
--- /dev/null
+++ b/externs/GCL/externs/goog/color/color.js
@@ -0,0 +1,776 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Utilities related to color and color conversion.
+ */
+
+goog.provide('goog.color');
+goog.provide('goog.color.Hsl');
+goog.provide('goog.color.Hsv');
+goog.provide('goog.color.Rgb');
+
+goog.require('goog.color.names');
+goog.require('goog.math');
+
+
+/**
+ * RGB color representation. An array containing three elements [r, g, b],
+ * each an integer in [0, 255], representing the red, green, and blue components
+ * of the color respectively.
+ * @typedef {Array<number>}
+ */
+goog.color.Rgb;
+
+
+/**
+ * HSV color representation. An array containing three elements [h, s, v]:
+ * h (hue) must be an integer in [0, 360], cyclic.
+ * s (saturation) must be a number in [0, 1].
+ * v (value/brightness) must be an integer in [0, 255].
+ * @typedef {Array<number>}
+ */
+goog.color.Hsv;
+
+
+/**
+ * HSL color representation. An array containing three elements [h, s, l]:
+ * h (hue) must be an integer in [0, 360], cyclic.
+ * s (saturation) must be a number in [0, 1].
+ * l (lightness) must be a number in [0, 1].
+ * @typedef {Array<number>}
+ */
+goog.color.Hsl;
+
+
+/**
+ * Parses a color out of a string.
+ * @param {string} str Color in some format.
+ * @return {{hex: string, type: string}} 'hex' is a string containing a hex
+ *     representation of the color, 'type' is a string containing the type
+ *     of color format passed in ('hex', 'rgb', 'named').
+ */
+goog.color.parse = function(str) {
+  var result = {};
+  str = String(str);
+
+  var maybeHex = goog.color.prependHashIfNecessaryHelper(str);
+  if (goog.color.isValidHexColor_(maybeHex)) {
+    result.hex = goog.color.normalizeHex(maybeHex);
+    result.type = 'hex';
+    return result;
+  } else {
+    var rgb = goog.color.isValidRgbColor_(str);
+    if (rgb.length) {
+      result.hex = goog.color.rgbArrayToHex(rgb);
+      result.type = 'rgb';
+      return result;
+    } else if (goog.color.names) {
+      var hex = goog.color.names[str.toLowerCase()];
+      if (hex) {
+        result.hex = hex;
+        result.type = 'named';
+        return result;
+      }
+    }
+  }
+  throw Error(str + ' is not a valid color string');
+};
+
+
+/**
+ * Determines if the given string can be parsed as a color.
+ *     {@see goog.color.parse}.
+ * @param {string} str Potential color string.
+ * @return {boolean} True if str is in a format that can be parsed to a color.
+ */
+goog.color.isValidColor = function(str) {
+  var maybeHex = goog.color.prependHashIfNecessaryHelper(str);
+  return !!(goog.color.isValidHexColor_(maybeHex) ||
+            goog.color.isValidRgbColor_(str).length ||
+            goog.color.names && goog.color.names[str.toLowerCase()]);
+};
+
+
+/**
+ * Parses red, green, blue components out of a valid rgb color string.
+ * Throws Error if the color string is invalid.
+ * @param {string} str RGB representation of a color.
+ *    {@see goog.color.isValidRgbColor_}.
+ * @return {!goog.color.Rgb} rgb representation of the color.
+ */
+goog.color.parseRgb = function(str) {
+  var rgb = goog.color.isValidRgbColor_(str);
+  if (!rgb.length) {
+    throw Error(str + ' is not a valid RGB color');
+  }
+  return rgb;
+};
+
+
+/**
+ * Converts a hex representation of a color to RGB.
+ * @param {string} hexColor Color to convert.
+ * @return {string} string of the form 'rgb(R,G,B)' which can be used in
+ *    styles.
+ */
+goog.color.hexToRgbStyle = function(hexColor) {
+  return goog.color.rgbStyle_(goog.color.hexToRgb(hexColor));
+};
+
+
+/**
+ * Regular expression for extracting the digits in a hex color triplet.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.hexTripletRe_ = /#(.)(.)(.)/;
+
+
+/**
+ * Normalize an hex representation of a color
+ * @param {string} hexColor an hex color string.
+ * @return {string} hex color in the format '#rrggbb' with all lowercase
+ *     literals.
+ */
+goog.color.normalizeHex = function(hexColor) {
+  if (!goog.color.isValidHexColor_(hexColor)) {
+    throw Error("'" + hexColor + "' is not a valid hex color");
+  }
+  if (hexColor.length == 4) { // of the form #RGB
+    hexColor = hexColor.replace(goog.color.hexTripletRe_, '#$1$1$2$2$3$3');
+  }
+  return hexColor.toLowerCase();
+};
+
+
+/**
+ * Converts a hex representation of a color to RGB.
+ * @param {string} hexColor Color to convert.
+ * @return {!goog.color.Rgb} rgb representation of the color.
+ */
+goog.color.hexToRgb = function(hexColor) {
+  hexColor = goog.color.normalizeHex(hexColor);
+  var r = parseInt(hexColor.substr(1, 2), 16);
+  var g = parseInt(hexColor.substr(3, 2), 16);
+  var b = parseInt(hexColor.substr(5, 2), 16);
+
+  return [r, g, b];
+};
+
+
+/**
+ * Converts a color from RGB to hex representation.
+ * @param {number} r Amount of red, int between 0 and 255.
+ * @param {number} g Amount of green, int between 0 and 255.
+ * @param {number} b Amount of blue, int between 0 and 255.
+ * @return {string} hex representation of the color.
+ */
+goog.color.rgbToHex = function(r, g, b) {
+  r = Number(r);
+  g = Number(g);
+  b = Number(b);
+  if (isNaN(r) || r < 0 || r > 255 ||
+      isNaN(g) || g < 0 || g > 255 ||
+      isNaN(b) || b < 0 || b > 255) {
+    throw Error('"(' + r + ',' + g + ',' + b + '") is not a valid RGB color');
+  }
+  var hexR = goog.color.prependZeroIfNecessaryHelper(r.toString(16));
+  var hexG = goog.color.prependZeroIfNecessaryHelper(g.toString(16));
+  var hexB = goog.color.prependZeroIfNecessaryHelper(b.toString(16));
+  return '#' + hexR + hexG + hexB;
+};
+
+
+/**
+ * Converts a color from RGB to hex representation.
+ * @param {goog.color.Rgb} rgb rgb representation of the color.
+ * @return {string} hex representation of the color.
+ */
+goog.color.rgbArrayToHex = function(rgb) {
+  return goog.color.rgbToHex(rgb[0], rgb[1], rgb[2]);
+};
+
+
+/**
+ * Converts a color from RGB color space to HSL color space.
+ * Modified from {@link http://en.wikipedia.org/wiki/HLS_color_space}.
+ * @param {number} r Value of red, in [0, 255].
+ * @param {number} g Value of green, in [0, 255].
+ * @param {number} b Value of blue, in [0, 255].
+ * @return {!goog.color.Hsl} hsl representation of the color.
+ */
+goog.color.rgbToHsl = function(r, g, b) {
+  // First must normalize r, g, b to be between 0 and 1.
+  var normR = r / 255;
+  var normG = g / 255;
+  var normB = b / 255;
+  var max = Math.max(normR, normG, normB);
+  var min = Math.min(normR, normG, normB);
+  var h = 0;
+  var s = 0;
+
+  // Luminosity is the average of the max and min rgb color intensities.
+  var l = 0.5 * (max + min);
+
+  // The hue and saturation are dependent on which color intensity is the max.
+  // If max and min are equal, the color is gray and h and s should be 0.
+  if (max != min) {
+    if (max == normR) {
+      h = 60 * (normG - normB) / (max - min);
+    } else if (max == normG) {
+      h = 60 * (normB - normR) / (max - min) + 120;
+    } else if (max == normB) {
+      h = 60 * (normR - normG) / (max - min) + 240;
+    }
+
+    if (0 < l && l <= 0.5) {
+      s = (max - min) / (2 * l);
+    } else {
+      s = (max - min) / (2 - 2 * l);
+    }
+  }
+
+  // Make sure the hue falls between 0 and 360.
+  return [Math.round(h + 360) % 360, s, l];
+};
+
+
+/**
+ * Converts a color from RGB color space to HSL color space.
+ * @param {goog.color.Rgb} rgb rgb representation of the color.
+ * @return {!goog.color.Hsl} hsl representation of the color.
+ */
+goog.color.rgbArrayToHsl = function(rgb) {
+  return goog.color.rgbToHsl(rgb[0], rgb[1], rgb[2]);
+};
+
+
+/**
+ * Helper for hslToRgb.
+ * @param {number} v1 Helper variable 1.
+ * @param {number} v2 Helper variable 2.
+ * @param {number} vH Helper variable 3.
+ * @return {number} Appropriate RGB value, given the above.
+ * @private
+ */
+goog.color.hueToRgb_ = function(v1, v2, vH) {
+  if (vH < 0) {
+    vH += 1;
+  } else if (vH > 1) {
+    vH -= 1;
+  }
+  if ((6 * vH) < 1) {
+    return (v1 + (v2 - v1) * 6 * vH);
+  } else if (2 * vH < 1) {
+    return v2;
+  } else if (3 * vH < 2) {
+    return (v1 + (v2 - v1) * ((2 / 3) - vH) * 6);
+  }
+  return v1;
+};
+
+
+/**
+ * Converts a color from HSL color space to RGB color space.
+ * Modified from {@link http://www.easyrgb.com/math.html}
+ * @param {number} h Hue, in [0, 360].
+ * @param {number} s Saturation, in [0, 1].
+ * @param {number} l Luminosity, in [0, 1].
+ * @return {!goog.color.Rgb} rgb representation of the color.
+ */
+goog.color.hslToRgb = function(h, s, l) {
+  var r = 0;
+  var g = 0;
+  var b = 0;
+  var normH = h / 360; // normalize h to fall in [0, 1]
+
+  if (s == 0) {
+    r = g = b = l * 255;
+  } else {
+    var temp1 = 0;
+    var temp2 = 0;
+    if (l < 0.5) {
+      temp2 = l * (1 + s);
+    } else {
+      temp2 = l + s - (s * l);
+    }
+    temp1 = 2 * l - temp2;
+    r = 255 * goog.color.hueToRgb_(temp1, temp2, normH + (1 / 3));
+    g = 255 * goog.color.hueToRgb_(temp1, temp2, normH);
+    b = 255 * goog.color.hueToRgb_(temp1, temp2, normH - (1 / 3));
+  }
+
+  return [Math.round(r), Math.round(g), Math.round(b)];
+};
+
+
+/**
+ * Converts a color from HSL color space to RGB color space.
+ * @param {goog.color.Hsl} hsl hsl representation of the color.
+ * @return {!goog.color.Rgb} rgb representation of the color.
+ */
+goog.color.hslArrayToRgb = function(hsl) {
+  return goog.color.hslToRgb(hsl[0], hsl[1], hsl[2]);
+};
+
+
+/**
+ * Helper for isValidHexColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.validHexColorRe_ = /^#(?:[0-9a-f]{3}){1,2}$/i;
+
+
+/**
+ * Checks if a string is a valid hex color.  We expect strings of the format
+ * #RRGGBB (ex: #1b3d5f) or #RGB (ex: #3CA == #33CCAA).
+ * @param {string} str String to check.
+ * @return {boolean} Whether the string is a valid hex color.
+ * @private
+ */
+goog.color.isValidHexColor_ = function(str) {
+  return goog.color.validHexColorRe_.test(str);
+};
+
+
+/**
+ * Helper for isNormalizedHexColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.normalizedHexColorRe_ = /^#[0-9a-f]{6}$/;
+
+
+/**
+ * Checks if a string is a normalized hex color.
+ * We expect strings of the format #RRGGBB (ex: #1b3d5f)
+ * using only lowercase letters.
+ * @param {string} str String to check.
+ * @return {boolean} Whether the string is a normalized hex color.
+ * @private
+ */
+goog.color.isNormalizedHexColor_ = function(str) {
+  return goog.color.normalizedHexColorRe_.test(str);
+};
+
+
+/**
+ * Regular expression for matching and capturing RGB style strings. Helper for
+ * isValidRgbColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.rgbColorRe_ =
+    /^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i;
+
+
+/**
+ * Checks if a string is a valid rgb color.  We expect strings of the format
+ * '(r, g, b)', or 'rgb(r, g, b)', where each color component is an int in
+ * [0, 255].
+ * @param {string} str String to check.
+ * @return {!goog.color.Rgb} the rgb representation of the color if it is
+ *     a valid color, or the empty array otherwise.
+ * @private
+ */
+goog.color.isValidRgbColor_ = function(str) {
+  // Each component is separate (rather than using a repeater) so we can
+  // capture the match. Also, we explicitly set each component to be either 0,
+  // or start with a non-zero, to prevent octal numbers from slipping through.
+  var regExpResultArray = str.match(goog.color.rgbColorRe_);
+  if (regExpResultArray) {
+    var r = Number(regExpResultArray[1]);
+    var g = Number(regExpResultArray[2]);
+    var b = Number(regExpResultArray[3]);
+    if (r >= 0 && r <= 255 &&
+        g >= 0 && g <= 255 &&
+        b >= 0 && b <= 255) {
+      return [r, g, b];
+    }
+  }
+  return [];
+};
+
+
+/**
+ * Takes a hex value and prepends a zero if it's a single digit.
+ * Small helper method for use by goog.color and friends.
+ * @param {string} hex Hex value to prepend if single digit.
+ * @return {string} hex value prepended with zero if it was single digit,
+ *     otherwise the same value that was passed in.
+ */
+goog.color.prependZeroIfNecessaryHelper = function(hex) {
+  return hex.length == 1 ? '0' + hex : hex;
+};
+
+
+/**
+ * Takes a string a prepends a '#' sign if one doesn't exist.
+ * Small helper method for use by goog.color and friends.
+ * @param {string} str String to check.
+ * @return {string} The value passed in, prepended with a '#' if it didn't
+ *     already have one.
+ */
+goog.color.prependHashIfNecessaryHelper = function(str) {
+  return str.charAt(0) == '#' ? str : '#' + str;
+};
+
+
+/**
+ * Takes an array of [r, g, b] and converts it into a string appropriate for
+ * CSS styles.
+ * @param {goog.color.Rgb} rgb rgb representation of the color.
+ * @return {string} string of the form 'rgb(r,g,b)'.
+ * @private
+ */
+goog.color.rgbStyle_ = function(rgb) {
+  return 'rgb(' + rgb.join(',') + ')';
+};
+
+
+/**
+ * Converts an HSV triplet to an RGB array.  V is brightness because b is
+ *   reserved for blue in RGB.
+ * @param {number} h Hue value in [0, 360].
+ * @param {number} s Saturation value in [0, 1].
+ * @param {number} brightness brightness in [0, 255].
+ * @return {!goog.color.Rgb} rgb representation of the color.
+ */
+goog.color.hsvToRgb = function(h, s, brightness) {
+  var red = 0;
+  var green = 0;
+  var blue = 0;
+  if (s == 0) {
+    red = brightness;
+    green = brightness;
+    blue = brightness;
+  } else {
+    var sextant = Math.floor(h / 60);
+    var remainder = (h / 60) - sextant;
+    var val1 = brightness * (1 - s);
+    var val2 = brightness * (1 - (s * remainder));
+    var val3 = brightness * (1 - (s * (1 - remainder)));
+    switch (sextant) {
+      case 1:
+        red = val2;
+        green = brightness;
+        blue = val1;
+        break;
+      case 2:
+        red = val1;
+        green = brightness;
+        blue = val3;
+        break;
+      case 3:
+        red = val1;
+        green = val2;
+        blue = brightness;
+        break;
+      case 4:
+        red = val3;
+        green = val1;
+        blue = brightness;
+        break;
+      case 5:
+        red = brightness;
+        green = val1;
+        blue = val2;
+        break;
+      case 6:
+      case 0:
+        red = brightness;
+        green = val3;
+        blue = val1;
+        break;
+    }
+  }
+
+  return [Math.floor(red), Math.floor(green), Math.floor(blue)];
+};
+
+
+/**
+ * Converts from RGB values to an array of HSV values.
+ * @param {number} red Red value in [0, 255].
+ * @param {number} green Green value in [0, 255].
+ * @param {number} blue Blue value in [0, 255].
+ * @return {!goog.color.Hsv} hsv representation of the color.
+ */
+goog.color.rgbToHsv = function(red, green, blue) {
+
+  var max = Math.max(Math.max(red, green), blue);
+  var min = Math.min(Math.min(red, green), blue);
+  var hue;
+  var saturation;
+  var value = max;
+  if (min == max) {
+    hue = 0;
+    saturation = 0;
+  } else {
+    var delta = (max - min);
+    saturation = delta / max;
+
+    if (red == max) {
+      hue = (green - blue) / delta;
+    } else if (green == max) {
+      hue = 2 + ((blue - red) / delta);
+    } else {
+      hue = 4 + ((red - green) / delta);
+    }
+    hue *= 60;
+    if (hue < 0) {
+      hue += 360;
+    }
+    if (hue > 360) {
+      hue -= 360;
+    }
+  }
+
+  return [hue, saturation, value];
+};
+
+
+/**
+ * Converts from an array of RGB values to an array of HSV values.
+ * @param {goog.color.Rgb} rgb rgb representation of the color.
+ * @return {!goog.color.Hsv} hsv representation of the color.
+ */
+goog.color.rgbArrayToHsv = function(rgb) {
+  return goog.color.rgbToHsv(rgb[0], rgb[1], rgb[2]);
+};
+
+
+/**
+ * Converts an HSV triplet to an RGB array.
+ * @param {goog.color.Hsv} hsv hsv representation of the color.
+ * @return {!goog.color.Rgb} rgb representation of the color.
+ */
+goog.color.hsvArrayToRgb = function(hsv) {
+  return goog.color.hsvToRgb(hsv[0], hsv[1], hsv[2]);
+};
+
+
+/**
+ * Converts a hex representation of a color to HSL.
+ * @param {string} hex Color to convert.
+ * @return {!goog.color.Hsv} hsv representation of the color.
+ */
+goog.color.hexToHsl = function(hex) {
+  var rgb = goog.color.hexToRgb(hex);
+  return goog.color.rgbToHsl(rgb[0], rgb[1], rgb[2]);
+};
+
+
+/**
+ * Converts from h,s,l values to a hex string
+ * @param {number} h Hue, in [0, 360].
+ * @param {number} s Saturation, in [0, 1].
+ * @param {number} l Luminosity, in [0, 1].
+ * @return {string} hex representation of the color.
+ */
+goog.color.hslToHex = function(h, s, l) {
+  return goog.color.rgbArrayToHex(goog.color.hslToRgb(h, s, l));
+};
+
+
+/**
+ * Converts from an hsl array to a hex string
+ * @param {goog.color.Hsl} hsl hsl representation of the color.
+ * @return {string} hex representation of the color.
+ */
+goog.color.hslArrayToHex = function(hsl) {
+  return goog.color.rgbArrayToHex(goog.color.hslToRgb(hsl[0], hsl[1], hsl[2]));
+};
+
+
+/**
+ * Converts a hex representation of a color to HSV
+ * @param {string} hex Color to convert.
+ * @return {!goog.color.Hsv} hsv representation of the color.
+ */
+goog.color.hexToHsv = function(hex) {
+  return goog.color.rgbArrayToHsv(goog.color.hexToRgb(hex));
+};
+
+
+/**
+ * Converts from h,s,v values to a hex string
+ * @param {number} h Hue, in [0, 360].
+ * @param {number} s Saturation, in [0, 1].
+ * @param {number} v Value, in [0, 255].
+ * @return {string} hex representation of the color.
+ */
+goog.color.hsvToHex = function(h, s, v) {
+  return goog.color.rgbArrayToHex(goog.color.hsvToRgb(h, s, v));
+};
+
+
+/**
+ * Converts from an HSV array to a hex string
+ * @param {goog.color.Hsv} hsv hsv representation of the color.
+ * @return {string} hex representation of the color.
+ */
+goog.color.hsvArrayToHex = function(hsv) {
+  return goog.color.hsvToHex(hsv[0], hsv[1], hsv[2]);
+};
+
+
+/**
+ * Calculates the Euclidean distance between two color vectors on an HSL sphere.
+ * A demo of the sphere can be found at:
+ * http://en.wikipedia.org/wiki/HSL_color_space
+ * In short, a vector for color (H, S, L) in this system can be expressed as
+ * (S*L'*cos(2*PI*H), S*L'*sin(2*PI*H), L), where L' = abs(L - 0.5), and we
+ * simply calculate the 1-2 distance using these coordinates
+ * @param {goog.color.Hsl} hsl1 First color in hsl representation.
+ * @param {goog.color.Hsl} hsl2 Second color in hsl representation.
+ * @return {number} Distance between the two colors, in the range [0, 1].
+ */
+goog.color.hslDistance = function(hsl1, hsl2) {
+  var sl1, sl2;
+  if (hsl1[2] <= 0.5) {
+    sl1 = hsl1[1] * hsl1[2];
+  } else {
+    sl1 = hsl1[1] * (1.0 - hsl1[2]);
+  }
+
+  if (hsl2[2] <= 0.5) {
+    sl2 = hsl2[1] * hsl2[2];
+  } else {
+    sl2 = hsl2[1] * (1.0 - hsl2[2]);
+  }
+
+  var h1 = hsl1[0] / 360.0;
+  var h2 = hsl2[0] / 360.0;
+  var dh = (h1 - h2) * 2.0 * Math.PI;
+  return (hsl1[2] - hsl2[2]) * (hsl1[2] - hsl2[2]) +
+      sl1 * sl1 + sl2 * sl2 - 2 * sl1 * sl2 * Math.cos(dh);
+};
+
+
+/**
+ * Blend two colors together, using the specified factor to indicate the weight
+ * given to the first color
+ * @param {goog.color.Rgb} rgb1 First color represented in rgb.
+ * @param {goog.color.Rgb} rgb2 Second color represented in rgb.
+ * @param {number} factor The weight to be given to rgb1 over rgb2. Values
+ *     should be in the range [0, 1]. If less than 0, factor will be set to 0.
+ *     If greater than 1, factor will be set to 1.
+ * @return {!goog.color.Rgb} Combined color represented in rgb.
+ */
+goog.color.blend = function(rgb1, rgb2, factor) {
+  factor = goog.math.clamp(factor, 0, 1);
+
+  return [
+    Math.round(factor * rgb1[0] + (1.0 - factor) * rgb2[0]),
+    Math.round(factor * rgb1[1] + (1.0 - factor) * rgb2[1]),
+    Math.round(factor * rgb1[2] + (1.0 - factor) * rgb2[2])
+  ];
+};
+
+
+/**
+ * Adds black to the specified color, darkening it
+ * @param {goog.color.Rgb} rgb rgb representation of the color.
+ * @param {number} factor Number in the range [0, 1]. 0 will do nothing, while
+ *     1 will return black. If less than 0, factor will be set to 0. If greater
+ *     than 1, factor will be set to 1.
+ * @return {!goog.color.Rgb} Combined rgb color.
+ */
+goog.color.darken = function(rgb, factor) {
+  var black = [0, 0, 0];
+  return goog.color.blend(black, rgb, factor);
+};
+
+
+/**
+ * Adds white to the specified color, lightening it
+ * @param {goog.color.Rgb} rgb rgb representation of the color.
+ * @param {number} factor Number in the range [0, 1].  0 will do nothing, while
+ *     1 will return white. If less than 0, factor will be set to 0. If greater
+ *     than 1, factor will be set to 1.
+ * @return {!goog.color.Rgb} Combined rgb color.
+ */
+goog.color.lighten = function(rgb, factor) {
+  var white = [255, 255, 255];
+  return goog.color.blend(white, rgb, factor);
+};
+
+
+/**
+ * Find the "best" (highest-contrast) of the suggested colors for the prime
+ * color. Uses W3C formula for judging readability and visual accessibility:
+ * http://www.w3.org/TR/AERT#color-contrast
+ * @param {goog.color.Rgb} prime Color represented as a rgb array.
+ * @param {Array<goog.color.Rgb>} suggestions Array of colors,
+ *     each representing a rgb array.
+ * @return {!goog.color.Rgb} Highest-contrast color represented by an array..
+ */
+goog.color.highContrast = function(prime, suggestions) {
+  var suggestionsWithDiff = [];
+  for (var i = 0; i < suggestions.length; i++) {
+    suggestionsWithDiff.push({
+      color: suggestions[i],
+      diff: goog.color.yiqBrightnessDiff_(suggestions[i], prime) +
+          goog.color.colorDiff_(suggestions[i], prime)
+    });
+  }
+  suggestionsWithDiff.sort(function(a, b) {
+    return b.diff - a.diff;
+  });
+  return suggestionsWithDiff[0].color;
+};
+
+
+/**
+ * Calculate brightness of a color according to YIQ formula (brightness is Y).
+ * More info on YIQ here: http://en.wikipedia.org/wiki/YIQ. Helper method for
+ * goog.color.highContrast()
+ * @param {goog.color.Rgb} rgb Color represented by a rgb array.
+ * @return {number} brightness (Y).
+ * @private
+ */
+goog.color.yiqBrightness_ = function(rgb) {
+  return Math.round((rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000);
+};
+
+
+/**
+ * Calculate difference in brightness of two colors. Helper method for
+ * goog.color.highContrast()
+ * @param {goog.color.Rgb} rgb1 Color represented by a rgb array.
+ * @param {goog.color.Rgb} rgb2 Color represented by a rgb array.
+ * @return {number} Brightness difference.
+ * @private
+ */
+goog.color.yiqBrightnessDiff_ = function(rgb1, rgb2) {
+  return Math.abs(goog.color.yiqBrightness_(rgb1) -
+                  goog.color.yiqBrightness_(rgb2));
+};
+
+
+/**
+ * Calculate color difference between two colors. Helper method for
+ * goog.color.highContrast()
+ * @param {goog.color.Rgb} rgb1 Color represented by a rgb array.
+ * @param {goog.color.Rgb} rgb2 Color represented by a rgb array.
+ * @return {number} Color difference.
+ * @private
+ */
+goog.color.colorDiff_ = function(rgb1, rgb2) {
+  return Math.abs(rgb1[0] - rgb2[0]) + Math.abs(rgb1[1] - rgb2[1]) +
+      Math.abs(rgb1[2] - rgb2[2]);
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/color/names.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/color/names.js b/externs/GCL/externs/goog/color/names.js
new file mode 100644
index 0000000..c4b3ac8
--- /dev/null
+++ b/externs/GCL/externs/goog/color/names.js
@@ -0,0 +1,176 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Names of standard colors with their associated hex values.
+ */
+
+goog.provide('goog.color.names');
+
+
+/**
+ * A map that contains a lot of colors that are recognised by various browsers.
+ * This list is way larger than the minimal one dictated by W3C.
+ * The keys of this map are the lowercase "readable" names of the colors, while
+ * the values are the "hex" values.
+ */
+goog.color.names = {
+  'aliceblue': '#f0f8ff',
+  'antiquewhite': '#faebd7',
+  'aqua': '#00ffff',
+  'aquamarine': '#7fffd4',
+  'azure': '#f0ffff',
+  'beige': '#f5f5dc',
+  'bisque': '#ffe4c4',
+  'black': '#000000',
+  'blanchedalmond': '#ffebcd',
+  'blue': '#0000ff',
+  'blueviolet': '#8a2be2',
+  'brown': '#a52a2a',
+  'burlywood': '#deb887',
+  'cadetblue': '#5f9ea0',
+  'chartreuse': '#7fff00',
+  'chocolate': '#d2691e',
+  'coral': '#ff7f50',
+  'cornflowerblue': '#6495ed',
+  'cornsilk': '#fff8dc',
+  'crimson': '#dc143c',
+  'cyan': '#00ffff',
+  'darkblue': '#00008b',
+  'darkcyan': '#008b8b',
+  'darkgoldenrod': '#b8860b',
+  'darkgray': '#a9a9a9',
+  'darkgreen': '#006400',
+  'darkgrey': '#a9a9a9',
+  'darkkhaki': '#bdb76b',
+  'darkmagenta': '#8b008b',
+  'darkolivegreen': '#556b2f',
+  'darkorange': '#ff8c00',
+  'darkorchid': '#9932cc',
+  'darkred': '#8b0000',
+  'darksalmon': '#e9967a',
+  'darkseagreen': '#8fbc8f',
+  'darkslateblue': '#483d8b',
+  'darkslategray': '#2f4f4f',
+  'darkslategrey': '#2f4f4f',
+  'darkturquoise': '#00ced1',
+  'darkviolet': '#9400d3',
+  'deeppink': '#ff1493',
+  'deepskyblue': '#00bfff',
+  'dimgray': '#696969',
+  'dimgrey': '#696969',
+  'dodgerblue': '#1e90ff',
+  'firebrick': '#b22222',
+  'floralwhite': '#fffaf0',
+  'forestgreen': '#228b22',
+  'fuchsia': '#ff00ff',
+  'gainsboro': '#dcdcdc',
+  'ghostwhite': '#f8f8ff',
+  'gold': '#ffd700',
+  'goldenrod': '#daa520',
+  'gray': '#808080',
+  'green': '#008000',
+  'greenyellow': '#adff2f',
+  'grey': '#808080',
+  'honeydew': '#f0fff0',
+  'hotpink': '#ff69b4',
+  'indianred': '#cd5c5c',
+  'indigo': '#4b0082',
+  'ivory': '#fffff0',
+  'khaki': '#f0e68c',
+  'lavender': '#e6e6fa',
+  'lavenderblush': '#fff0f5',
+  'lawngreen': '#7cfc00',
+  'lemonchiffon': '#fffacd',
+  'lightblue': '#add8e6',
+  'lightcoral': '#f08080',
+  'lightcyan': '#e0ffff',
+  'lightgoldenrodyellow': '#fafad2',
+  'lightgray': '#d3d3d3',
+  'lightgreen': '#90ee90',
+  'lightgrey': '#d3d3d3',
+  'lightpink': '#ffb6c1',
+  'lightsalmon': '#ffa07a',
+  'lightseagreen': '#20b2aa',
+  'lightskyblue': '#87cefa',
+  'lightslategray': '#778899',
+  'lightslategrey': '#778899',
+  'lightsteelblue': '#b0c4de',
+  'lightyellow': '#ffffe0',
+  'lime': '#00ff00',
+  'limegreen': '#32cd32',
+  'linen': '#faf0e6',
+  'magenta': '#ff00ff',
+  'maroon': '#800000',
+  'mediumaquamarine': '#66cdaa',
+  'mediumblue': '#0000cd',
+  'mediumorchid': '#ba55d3',
+  'mediumpurple': '#9370db',
+  'mediumseagreen': '#3cb371',
+  'mediumslateblue': '#7b68ee',
+  'mediumspringgreen': '#00fa9a',
+  'mediumturquoise': '#48d1cc',
+  'mediumvioletred': '#c71585',
+  'midnightblue': '#191970',
+  'mintcream': '#f5fffa',
+  'mistyrose': '#ffe4e1',
+  'moccasin': '#ffe4b5',
+  'navajowhite': '#ffdead',
+  'navy': '#000080',
+  'oldlace': '#fdf5e6',
+  'olive': '#808000',
+  'olivedrab': '#6b8e23',
+  'orange': '#ffa500',
+  'orangered': '#ff4500',
+  'orchid': '#da70d6',
+  'palegoldenrod': '#eee8aa',
+  'palegreen': '#98fb98',
+  'paleturquoise': '#afeeee',
+  'palevioletred': '#db7093',
+  'papayawhip': '#ffefd5',
+  'peachpuff': '#ffdab9',
+  'peru': '#cd853f',
+  'pink': '#ffc0cb',
+  'plum': '#dda0dd',
+  'powderblue': '#b0e0e6',
+  'purple': '#800080',
+  'red': '#ff0000',
+  'rosybrown': '#bc8f8f',
+  'royalblue': '#4169e1',
+  'saddlebrown': '#8b4513',
+  'salmon': '#fa8072',
+  'sandybrown': '#f4a460',
+  'seagreen': '#2e8b57',
+  'seashell': '#fff5ee',
+  'sienna': '#a0522d',
+  'silver': '#c0c0c0',
+  'skyblue': '#87ceeb',
+  'slateblue': '#6a5acd',
+  'slategray': '#708090',
+  'slategrey': '#708090',
+  'snow': '#fffafa',
+  'springgreen': '#00ff7f',
+  'steelblue': '#4682b4',
+  'tan': '#d2b48c',
+  'teal': '#008080',
+  'thistle': '#d8bfd8',
+  'tomato': '#ff6347',
+  'turquoise': '#40e0d0',
+  'violet': '#ee82ee',
+  'wheat': '#f5deb3',
+  'white': '#ffffff',
+  'whitesmoke': '#f5f5f5',
+  'yellow': '#ffff00',
+  'yellowgreen': '#9acd32'
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/aes.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/aes.js b/externs/GCL/externs/goog/crypt/aes.js
new file mode 100644
index 0000000..d5a1674
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/aes.js
@@ -0,0 +1,1029 @@
+// Copyright 2012 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Implementation of AES in JavaScript.
+ * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
+ *
+ * @author nnaze@google.com (Nathan Naze) - port to Closure
+ */
+
+goog.provide('goog.crypt.Aes');
+
+goog.require('goog.asserts');
+goog.require('goog.crypt.BlockCipher');
+
+
+
+/**
+ * Implementation of AES in JavaScript.
+ * See http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
+ *
+ * WARNING: This is ECB mode only. If you are encrypting something
+ * longer than 16 bytes, or encrypting more than one value with the same key
+ * (so basically, always) you need to use this with a block cipher mode of
+ * operation.  See goog.crypt.Cbc.
+ *
+ * See http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation for more
+ * information.
+ *
+ * @constructor
+ * @implements {goog.crypt.BlockCipher}
+ * @param {!Array<number>} key The key as an array of integers in {0, 255}.
+ *     The key must have lengths of 16, 24, or 32 integers for 128-,
+ *     192-, or 256-bit encryption, respectively.
+ * @final
+ * @struct
+ */
+goog.crypt.Aes = function(key) {
+  goog.crypt.Aes.assertKeyArray_(key);
+
+  /**
+   * The AES key.
+   * @type {!Array<number>}
+   * @private
+   */
+  this.key_ = key;
+
+  /**
+   * Key length, in words.
+   * @type {number}
+   * @private
+   */
+  this.keyLength_ = this.key_.length / 4;
+
+  /**
+   * Number of rounds.  Based on key length per AES spec.
+   * @type {number}
+   * @private
+   */
+  this.numberOfRounds_ = this.keyLength_ + 6;
+
+  /**
+   * 4x4 byte array containing the current state.
+   * @type {!Array<!Array<number>>}
+   * @private
+   */
+  this.state_ = [[], [], [], []];
+
+  /**
+   * Scratch temporary array for calculation.
+   * @type {!Array<!Array<number>>}
+   * @private
+   */
+  this.temp_ = [[], [], [], []];
+
+  /**
+   * The key schedule.
+   * @type {!Array<!Array<number>>}
+   * @private
+   */
+  this.keySchedule_;
+
+  this.keyExpansion_();
+};
+
+
+/**
+ * @define {boolean} Whether to call test method stubs.  This can be enabled
+ *     for unit testing.
+ */
+goog.define('goog.crypt.Aes.ENABLE_TEST_MODE', false);
+
+
+/**
+ * @override
+ */
+goog.crypt.Aes.prototype.encrypt = function(input) {
+
+  if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+    this.testKeySchedule_(0, this.keySchedule_, 0);
+  }
+
+  this.copyInput_(input);
+  this.addRoundKey_(0);
+
+  for (var round = 1; round < this.numberOfRounds_; ++round) {
+    if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+      this.testKeySchedule_(round, this.keySchedule_, round);
+      this.testStartRound_(round, this.state_);
+    }
+
+    this.subBytes_(goog.crypt.Aes.SBOX_);
+    if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+      this.testAfterSubBytes_(round, this.state_);
+    }
+
+    this.shiftRows_();
+    if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+      this.testAfterShiftRows_(round, this.state_);
+    }
+
+    this.mixColumns_();
+    if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+      this.testAfterMixColumns_(round, this.state_);
+    }
+
+    this.addRoundKey_(round);
+  }
+
+  this.subBytes_(goog.crypt.Aes.SBOX_);
+  if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+    this.testAfterSubBytes_(round, this.state_);
+  }
+
+  this.shiftRows_();
+  if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+    this.testAfterShiftRows_(round, this.state_);
+  }
+
+  this.addRoundKey_(this.numberOfRounds_);
+
+  return this.generateOutput_();
+};
+
+
+/**
+ * @override
+ */
+goog.crypt.Aes.prototype.decrypt = function(input) {
+
+  if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+    this.testKeySchedule_(0, this.keySchedule_, this.numberOfRounds_);
+  }
+
+  this.copyInput_(input);
+  this.addRoundKey_(this.numberOfRounds_);
+
+  for (var round = 1; round < this.numberOfRounds_; ++round) {
+    if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+      this.testKeySchedule_(round, this.keySchedule_,
+                            this.numberOfRounds_ - round);
+      this.testStartRound_(round, this.state_);
+    }
+
+    this.invShiftRows_();
+    if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+      this.testAfterShiftRows_(round, this.state_);
+    }
+
+    this.subBytes_(goog.crypt.Aes.INV_SBOX_);
+    if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+      this.testAfterSubBytes_(round, this.state_);
+    }
+
+    this.addRoundKey_(this.numberOfRounds_ - round);
+    if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+      this.testAfterAddRoundKey_(round, this.state_);
+    }
+
+    this.invMixColumns_();
+  }
+
+  this.invShiftRows_();
+  if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+    this.testAfterShiftRows_(round, this.state_);
+  }
+
+  this.subBytes_(goog.crypt.Aes.INV_SBOX_);
+  if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+    this.testAfterSubBytes_(this.numberOfRounds_, this.state_);
+  }
+
+  if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+    this.testKeySchedule_(this.numberOfRounds_, this.keySchedule_, 0);
+  }
+
+  this.addRoundKey_(0);
+
+  return this.generateOutput_();
+};
+
+
+/**
+ * Block size, in words.  Fixed at 4 per AES spec.
+ * @type {number}
+ * @private
+ */
+goog.crypt.Aes.BLOCK_SIZE_ = 4;
+
+
+/**
+ * Asserts that the key's array of integers is in the correct format.
+ * @param {!Array<number>} arr AES key as array of integers.
+ * @private
+ */
+goog.crypt.Aes.assertKeyArray_ = function(arr) {
+  if (goog.asserts.ENABLE_ASSERTS) {
+    goog.asserts.assert(arr.length == 16 || arr.length == 24 ||
+                        arr.length == 32,
+                        'Key must have length 16, 24, or 32.');
+    for (var i = 0; i < arr.length; i++) {
+      goog.asserts.assertNumber(arr[i]);
+      goog.asserts.assert(arr[i] >= 0 && arr[i] <= 255);
+    }
+  }
+};
+
+
+/**
+ * Tests can populate this with a callback, and that callback will get called
+ * at the start of each round *in both functions encrypt() and decrypt()*.
+ * @param {number} roundNum Round number.
+ * @param {!Array<Array<number>>} Current state.
+ * @private
+ */
+goog.crypt.Aes.prototype.testStartRound_ = goog.nullFunction;
+
+
+/**
+ * Tests can populate this with a callback, and that callback will get called
+ * each round right after the SubBytes step gets executed *in both functions
+ * encrypt() and decrypt()*.
+ * @param {number} roundNum Round number.
+ * @param {!Array<Array<number>>} Current state.
+ * @private
+ */
+goog.crypt.Aes.prototype.testAfterSubBytes_ = goog.nullFunction;
+
+
+/**
+ * Tests can populate this with a callback, and that callback will get called
+ * each round right after the ShiftRows step gets executed *in both functions
+ * encrypt() and decrypt()*.
+ * @param {number} roundNum Round number.
+ * @param {!Array<Array<number>>} Current state.
+ * @private
+ */
+goog.crypt.Aes.prototype.testAfterShiftRows_ = goog.nullFunction;
+
+
+/**
+ * Tests can populate this with a callback, and that callback will get called
+ * each round right after the MixColumns step gets executed *but only in the
+ * decrypt() function*.
+ * @param {number} roundNum Round number.
+ * @param {!Array<Array<number>>} Current state.
+ * @private
+ */
+goog.crypt.Aes.prototype.testAfterMixColumns_ = goog.nullFunction;
+
+
+/**
+ * Tests can populate this with a callback, and that callback will get called
+ * each round right after the AddRoundKey step gets executed  encrypt().
+ * @param {number} roundNum Round number.
+ * @param {!Array<Array<number>>} Current state.
+ * @private
+ */
+goog.crypt.Aes.prototype.testAfterAddRoundKey_ = goog.nullFunction;
+
+
+/**
+ * Tests can populate this with a callback, and that callback will get called
+ * before each round on the round key.  *Gets called in both the encrypt() and
+ * decrypt() functions.*
+ * @param {number} roundNum Round number.
+ * @param {Array<!Array<number>>} Computed key schedule.
+ * @param {number} index The index into the key schedule to test. This is not
+ *     necessarily roundNum because the key schedule is used in reverse
+ *     in the case of decryption.
+ * @private
+ */
+goog.crypt.Aes.prototype.testKeySchedule_ = goog.nullFunction;
+
+
+/**
+ * Helper to copy input into the AES state matrix.
+ * @param {!Array<number>} input Byte array to copy into the state matrix.
+ * @private
+ */
+goog.crypt.Aes.prototype.copyInput_ = function(input) {
+  var v, p;
+
+  goog.asserts.assert(input.length == goog.crypt.Aes.BLOCK_SIZE_ * 4,
+                      'Expecting input of 4 times block size.');
+
+  for (var r = 0; r < goog.crypt.Aes.BLOCK_SIZE_; r++) {
+    for (var c = 0; c < 4; c++) {
+      p = c * 4 + r;
+      v = input[p];
+
+      goog.asserts.assert(
+          v <= 255 && v >= 0,
+          'Invalid input. Value %s at position %s is not a byte.', v, p);
+
+      this.state_[r][c] = v;
+    }
+  }
+};
+
+
+/**
+ * Helper to copy the state matrix into an output array.
+ * @return {!Array<number>} Output byte array.
+ * @private
+ */
+goog.crypt.Aes.prototype.generateOutput_ = function() {
+  var output = [];
+  for (var r = 0; r < goog.crypt.Aes.BLOCK_SIZE_; r++) {
+    for (var c = 0; c < 4; c++) {
+      output[c * 4 + r] = this.state_[r][c];
+    }
+  }
+  return output;
+};
+
+
+/**
+ * AES's AddRoundKey procedure. Add the current round key to the state.
+ * @param {number} round The current round.
+ * @private
+ */
+goog.crypt.Aes.prototype.addRoundKey_ = function(round) {
+  for (var r = 0; r < 4; r++) {
+    for (var c = 0; c < 4; c++) {
+      this.state_[r][c] ^= this.keySchedule_[round * 4 + c][r];
+    }
+  }
+};
+
+
+/**
+ * AES's SubBytes procedure. Substitute bytes from the precomputed SBox lookup
+ * into the state.
+ * @param {!Array<number>} box The SBox or invSBox.
+ * @private
+ */
+goog.crypt.Aes.prototype.subBytes_ = function(box) {
+  for (var r = 0; r < 4; r++) {
+    for (var c = 0; c < 4; c++) {
+      this.state_[r][c] = box[this.state_[r][c]];
+    }
+  }
+};
+
+
+/**
+ * AES's ShiftRows procedure. Shift the values in each row to the right. Each
+ * row is shifted one more slot than the one above it.
+ * @private
+ */
+goog.crypt.Aes.prototype.shiftRows_ = function() {
+  for (var r = 1; r < 4; r++) {
+    for (var c = 0; c < 4; c++) {
+      this.temp_[r][c] = this.state_[r][c];
+    }
+  }
+
+  for (var r = 1; r < 4; r++) {
+    for (var c = 0; c < 4; c++) {
+      this.state_[r][c] = this.temp_[r][(c + r) %
+          goog.crypt.Aes.BLOCK_SIZE_];
+    }
+  }
+};
+
+
+/**
+ * AES's InvShiftRows procedure. Shift the values in each row to the right.
+ * @private
+ */
+goog.crypt.Aes.prototype.invShiftRows_ = function() {
+  for (var r = 1; r < 4; r++) {
+    for (var c = 0; c < 4; c++) {
+      this.temp_[r][(c + r) % goog.crypt.Aes.BLOCK_SIZE_] =
+          this.state_[r][c];
+    }
+  }
+
+  for (var r = 1; r < 4; r++) {
+    for (var c = 0; c < 4; c++) {
+      this.state_[r][c] = this.temp_[r][c];
+    }
+  }
+};
+
+
+/**
+ * AES's MixColumns procedure. Mix the columns of the state using magic.
+ * @private
+ */
+goog.crypt.Aes.prototype.mixColumns_ = function() {
+  var s = this.state_;
+  var t = this.temp_[0];
+
+  for (var c = 0; c < 4; c++) {
+    t[0] = s[0][c];
+    t[1] = s[1][c];
+    t[2] = s[2][c];
+    t[3] = s[3][c];
+
+    s[0][c] = (goog.crypt.Aes.MULT_2_[t[0]] ^
+               goog.crypt.Aes.MULT_3_[t[1]] ^ t[2] ^ t[3]);
+    s[1][c] = (t[0] ^ goog.crypt.Aes.MULT_2_[t[1]] ^
+               goog.crypt.Aes.MULT_3_[t[2]] ^ t[3]);
+    s[2][c] = (t[0] ^ t[1] ^ goog.crypt.Aes.MULT_2_[t[2]] ^
+               goog.crypt.Aes.MULT_3_[t[3]]);
+    s[3][c] = (goog.crypt.Aes.MULT_3_[t[0]] ^ t[1] ^ t[2] ^
+               goog.crypt.Aes.MULT_2_[t[3]]);
+  }
+};
+
+
+/**
+ * AES's InvMixColumns procedure.
+ * @private
+ */
+goog.crypt.Aes.prototype.invMixColumns_ = function() {
+  var s = this.state_;
+  var t = this.temp_[0];
+
+  for (var c = 0; c < 4; c++) {
+    t[0] = s[0][c];
+    t[1] = s[1][c];
+    t[2] = s[2][c];
+    t[3] = s[3][c];
+
+    s[0][c] = (
+        goog.crypt.Aes.MULT_E_[t[0]] ^ goog.crypt.Aes.MULT_B_[t[1]] ^
+        goog.crypt.Aes.MULT_D_[t[2]] ^ goog.crypt.Aes.MULT_9_[t[3]]);
+
+    s[1][c] = (
+        goog.crypt.Aes.MULT_9_[t[0]] ^ goog.crypt.Aes.MULT_E_[t[1]] ^
+        goog.crypt.Aes.MULT_B_[t[2]] ^ goog.crypt.Aes.MULT_D_[t[3]]);
+
+    s[2][c] = (
+        goog.crypt.Aes.MULT_D_[t[0]] ^ goog.crypt.Aes.MULT_9_[t[1]] ^
+        goog.crypt.Aes.MULT_E_[t[2]] ^ goog.crypt.Aes.MULT_B_[t[3]]);
+
+    s[3][c] = (
+        goog.crypt.Aes.MULT_B_[t[0]] ^ goog.crypt.Aes.MULT_D_[t[1]] ^
+        goog.crypt.Aes.MULT_9_[t[2]] ^ goog.crypt.Aes.MULT_E_[t[3]]);
+  }
+};
+
+
+/**
+ * AES's KeyExpansion procedure. Create the key schedule from the initial key.
+ * @private
+ */
+goog.crypt.Aes.prototype.keyExpansion_ = function() {
+  this.keySchedule_ = new Array(goog.crypt.Aes.BLOCK_SIZE_ * (
+      this.numberOfRounds_ + 1));
+
+  for (var rowNum = 0; rowNum < this.keyLength_; rowNum++) {
+    this.keySchedule_[rowNum] = [
+      this.key_[4 * rowNum],
+      this.key_[4 * rowNum + 1],
+      this.key_[4 * rowNum + 2],
+      this.key_[4 * rowNum + 3]
+    ];
+  }
+
+  var temp = new Array(4);
+
+  for (var rowNum = this.keyLength_;
+       rowNum < (goog.crypt.Aes.BLOCK_SIZE_ * (this.numberOfRounds_ + 1));
+       rowNum++) {
+    temp[0] = this.keySchedule_[rowNum - 1][0];
+    temp[1] = this.keySchedule_[rowNum - 1][1];
+    temp[2] = this.keySchedule_[rowNum - 1][2];
+    temp[3] = this.keySchedule_[rowNum - 1][3];
+
+    if (rowNum % this.keyLength_ == 0) {
+      this.rotWord_(temp);
+      this.subWord_(temp);
+
+      temp[0] ^= goog.crypt.Aes.RCON_[rowNum / this.keyLength_][0];
+      temp[1] ^= goog.crypt.Aes.RCON_[rowNum / this.keyLength_][1];
+      temp[2] ^= goog.crypt.Aes.RCON_[rowNum / this.keyLength_][2];
+      temp[3] ^= goog.crypt.Aes.RCON_[rowNum / this.keyLength_][3];
+    } else if (this.keyLength_ > 6 && rowNum % this.keyLength_ == 4) {
+      this.subWord_(temp);
+    }
+
+    this.keySchedule_[rowNum] = new Array(4);
+    this.keySchedule_[rowNum][0] =
+        this.keySchedule_[rowNum - this.keyLength_][0] ^ temp[0];
+    this.keySchedule_[rowNum][1] =
+        this.keySchedule_[rowNum - this.keyLength_][1] ^ temp[1];
+    this.keySchedule_[rowNum][2] =
+        this.keySchedule_[rowNum - this.keyLength_][2] ^ temp[2];
+    this.keySchedule_[rowNum][3] =
+        this.keySchedule_[rowNum - this.keyLength_][3] ^ temp[3];
+  }
+};
+
+
+/**
+ * AES's SubWord procedure.
+ * @param {!Array<number>} w Bytes to find the SBox substitution for.
+ * @return {!Array<number>} The substituted bytes.
+ * @private
+ */
+goog.crypt.Aes.prototype.subWord_ = function(w) {
+  w[0] = goog.crypt.Aes.SBOX_[w[0]];
+  w[1] = goog.crypt.Aes.SBOX_[w[1]];
+  w[2] = goog.crypt.Aes.SBOX_[w[2]];
+  w[3] = goog.crypt.Aes.SBOX_[w[3]];
+
+  return w;
+};
+
+
+/**
+ * AES's RotWord procedure.
+ * @param {!Array<number>} w Array of bytes to rotate.
+ * @return {!Array<number>} The rotated bytes.
+ * @private
+ */
+goog.crypt.Aes.prototype.rotWord_ = function(w) {
+  var temp = w[0];
+
+  w[0] = w[1];
+  w[1] = w[2];
+  w[2] = w[3];
+  w[3] = temp;
+
+  return w;
+};
+
+
+/**
+ * Precomputed SBox lookup.
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.SBOX_ = [
+  0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe,
+  0xd7, 0xab, 0x76,
+
+  0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c,
+  0xa4, 0x72, 0xc0,
+
+  0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71,
+  0xd8, 0x31, 0x15,
+
+  0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb,
+  0x27, 0xb2, 0x75,
+
+  0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29,
+  0xe3, 0x2f, 0x84,
+
+  0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a,
+  0x4c, 0x58, 0xcf,
+
+  0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50,
+  0x3c, 0x9f, 0xa8,
+
+  0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10,
+  0xff, 0xf3, 0xd2,
+
+  0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64,
+  0x5d, 0x19, 0x73,
+
+  0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde,
+  0x5e, 0x0b, 0xdb,
+
+  0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91,
+  0x95, 0xe4, 0x79,
+
+  0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65,
+  0x7a, 0xae, 0x08,
+
+  0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b,
+  0xbd, 0x8b, 0x8a,
+
+  0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86,
+  0xc1, 0x1d, 0x9e,
+
+  0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce,
+  0x55, 0x28, 0xdf,
+
+  0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0,
+  0x54, 0xbb, 0x16
+];
+
+
+/**
+ * Precomputed InvSBox lookup.
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.INV_SBOX_ = [
+  0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81,
+  0xf3, 0xd7, 0xfb,
+
+  0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4,
+  0xde, 0xe9, 0xcb,
+
+  0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42,
+  0xfa, 0xc3, 0x4e,
+
+  0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d,
+  0x8b, 0xd1, 0x25,
+
+  0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d,
+  0x65, 0xb6, 0x92,
+
+  0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7,
+  0x8d, 0x9d, 0x84,
+
+  0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8,
+  0xb3, 0x45, 0x06,
+
+  0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01,
+  0x13, 0x8a, 0x6b,
+
+  0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0,
+  0xb4, 0xe6, 0x73,
+
+  0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c,
+  0x75, 0xdf, 0x6e,
+
+  0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa,
+  0x18, 0xbe, 0x1b,
+
+  0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78,
+  0xcd, 0x5a, 0xf4,
+
+  0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27,
+  0x80, 0xec, 0x5f,
+
+  0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93,
+  0xc9, 0x9c, 0xef,
+
+  0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83,
+  0x53, 0x99, 0x61,
+
+  0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55,
+  0x21, 0x0c, 0x7d
+];
+
+
+/**
+ * Precomputed RCon lookup.
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.RCON_ = [
+  [0x00, 0x00, 0x00, 0x00],
+  [0x01, 0x00, 0x00, 0x00],
+  [0x02, 0x00, 0x00, 0x00],
+  [0x04, 0x00, 0x00, 0x00],
+  [0x08, 0x00, 0x00, 0x00],
+  [0x10, 0x00, 0x00, 0x00],
+  [0x20, 0x00, 0x00, 0x00],
+  [0x40, 0x00, 0x00, 0x00],
+  [0x80, 0x00, 0x00, 0x00],
+  [0x1b, 0x00, 0x00, 0x00],
+  [0x36, 0x00, 0x00, 0x00]
+];
+
+
+/**
+ * Precomputed lookup of multiplication by 2 in GF(2^8)
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.MULT_2_ = [
+  0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16,
+  0x18, 0x1A, 0x1C, 0x1E,
+
+  0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, 0x30, 0x32, 0x34, 0x36,
+  0x38, 0x3A, 0x3C, 0x3E,
+
+  0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56,
+  0x58, 0x5A, 0x5C, 0x5E,
+
+  0x60, 0x62, 0x64, 0x66, 0x68, 0x6A, 0x6C, 0x6E, 0x70, 0x72, 0x74, 0x76,
+  0x78, 0x7A, 0x7C, 0x7E,
+
+  0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E, 0x90, 0x92, 0x94, 0x96,
+  0x98, 0x9A, 0x9C, 0x9E,
+
+  0xA0, 0xA2, 0xA4, 0xA6, 0xA8, 0xAA, 0xAC, 0xAE, 0xB0, 0xB2, 0xB4, 0xB6,
+  0xB8, 0xBA, 0xBC, 0xBE,
+
+  0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, 0xD0, 0xD2, 0xD4, 0xD6,
+  0xD8, 0xDA, 0xDC, 0xDE,
+
+  0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE, 0xF0, 0xF2, 0xF4, 0xF6,
+  0xF8, 0xFA, 0xFC, 0xFE,
+
+  0x1B, 0x19, 0x1F, 0x1D, 0x13, 0x11, 0x17, 0x15, 0x0B, 0x09, 0x0F, 0x0D,
+  0x03, 0x01, 0x07, 0x05,
+
+  0x3B, 0x39, 0x3F, 0x3D, 0x33, 0x31, 0x37, 0x35, 0x2B, 0x29, 0x2F, 0x2D,
+  0x23, 0x21, 0x27, 0x25,
+
+  0x5B, 0x59, 0x5F, 0x5D, 0x53, 0x51, 0x57, 0x55, 0x4B, 0x49, 0x4F, 0x4D,
+  0x43, 0x41, 0x47, 0x45,
+
+  0x7B, 0x79, 0x7F, 0x7D, 0x73, 0x71, 0x77, 0x75, 0x6B, 0x69, 0x6F, 0x6D,
+  0x63, 0x61, 0x67, 0x65,
+
+  0x9B, 0x99, 0x9F, 0x9D, 0x93, 0x91, 0x97, 0x95, 0x8B, 0x89, 0x8F, 0x8D,
+  0x83, 0x81, 0x87, 0x85,
+
+  0xBB, 0xB9, 0xBF, 0xBD, 0xB3, 0xB1, 0xB7, 0xB5, 0xAB, 0xA9, 0xAF, 0xAD,
+  0xA3, 0xA1, 0xA7, 0xA5,
+
+  0xDB, 0xD9, 0xDF, 0xDD, 0xD3, 0xD1, 0xD7, 0xD5, 0xCB, 0xC9, 0xCF, 0xCD,
+  0xC3, 0xC1, 0xC7, 0xC5,
+
+  0xFB, 0xF9, 0xFF, 0xFD, 0xF3, 0xF1, 0xF7, 0xF5, 0xEB, 0xE9, 0xEF, 0xED,
+  0xE3, 0xE1, 0xE7, 0xE5
+];
+
+
+/**
+ * Precomputed lookup of multiplication by 3 in GF(2^8)
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.MULT_3_ = [
+  0x00, 0x03, 0x06, 0x05, 0x0C, 0x0F, 0x0A, 0x09, 0x18, 0x1B, 0x1E, 0x1D,
+  0x14, 0x17, 0x12, 0x11,
+
+  0x30, 0x33, 0x36, 0x35, 0x3C, 0x3F, 0x3A, 0x39, 0x28, 0x2B, 0x2E, 0x2D,
+  0x24, 0x27, 0x22, 0x21,
+
+  0x60, 0x63, 0x66, 0x65, 0x6C, 0x6F, 0x6A, 0x69, 0x78, 0x7B, 0x7E, 0x7D,
+  0x74, 0x77, 0x72, 0x71,
+
+  0x50, 0x53, 0x56, 0x55, 0x5C, 0x5F, 0x5A, 0x59, 0x48, 0x4B, 0x4E, 0x4D,
+  0x44, 0x47, 0x42, 0x41,
+
+  0xC0, 0xC3, 0xC6, 0xC5, 0xCC, 0xCF, 0xCA, 0xC9, 0xD8, 0xDB, 0xDE, 0xDD,
+  0xD4, 0xD7, 0xD2, 0xD1,
+
+  0xF0, 0xF3, 0xF6, 0xF5, 0xFC, 0xFF, 0xFA, 0xF9, 0xE8, 0xEB, 0xEE, 0xED,
+  0xE4, 0xE7, 0xE2, 0xE1,
+
+  0xA0, 0xA3, 0xA6, 0xA5, 0xAC, 0xAF, 0xAA, 0xA9, 0xB8, 0xBB, 0xBE, 0xBD,
+  0xB4, 0xB7, 0xB2, 0xB1,
+
+  0x90, 0x93, 0x96, 0x95, 0x9C, 0x9F, 0x9A, 0x99, 0x88, 0x8B, 0x8E, 0x8D,
+  0x84, 0x87, 0x82, 0x81,
+
+  0x9B, 0x98, 0x9D, 0x9E, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86,
+  0x8F, 0x8C, 0x89, 0x8A,
+
+  0xAB, 0xA8, 0xAD, 0xAE, 0xA7, 0xA4, 0xA1, 0xA2, 0xB3, 0xB0, 0xB5, 0xB6,
+  0xBF, 0xBC, 0xB9, 0xBA,
+
+  0xFB, 0xF8, 0xFD, 0xFE, 0xF7, 0xF4, 0xF1, 0xF2, 0xE3, 0xE0, 0xE5, 0xE6,
+  0xEF, 0xEC, 0xE9, 0xEA,
+
+  0xCB, 0xC8, 0xCD, 0xCE, 0xC7, 0xC4, 0xC1, 0xC2, 0xD3, 0xD0, 0xD5, 0xD6,
+  0xDF, 0xDC, 0xD9, 0xDA,
+
+  0x5B, 0x58, 0x5D, 0x5E, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46,
+  0x4F, 0x4C, 0x49, 0x4A,
+
+  0x6B, 0x68, 0x6D, 0x6E, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76,
+  0x7F, 0x7C, 0x79, 0x7A,
+
+  0x3B, 0x38, 0x3D, 0x3E, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26,
+  0x2F, 0x2C, 0x29, 0x2A,
+
+  0x0B, 0x08, 0x0D, 0x0E, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16,
+  0x1F, 0x1C, 0x19, 0x1A
+];
+
+
+/**
+ * Precomputed lookup of multiplication by 9 in GF(2^8)
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.MULT_9_ = [
+  0x00, 0x09, 0x12, 0x1B, 0x24, 0x2D, 0x36, 0x3F, 0x48, 0x41, 0x5A, 0x53,
+  0x6C, 0x65, 0x7E, 0x77,
+
+  0x90, 0x99, 0x82, 0x8B, 0xB4, 0xBD, 0xA6, 0xAF, 0xD8, 0xD1, 0xCA, 0xC3,
+  0xFC, 0xF5, 0xEE, 0xE7,
+
+  0x3B, 0x32, 0x29, 0x20, 0x1F, 0x16, 0x0D, 0x04, 0x73, 0x7A, 0x61, 0x68,
+  0x57, 0x5E, 0x45, 0x4C,
+
+  0xAB, 0xA2, 0xB9, 0xB0, 0x8F, 0x86, 0x9D, 0x94, 0xE3, 0xEA, 0xF1, 0xF8,
+  0xC7, 0xCE, 0xD5, 0xDC,
+
+  0x76, 0x7F, 0x64, 0x6D, 0x52, 0x5B, 0x40, 0x49, 0x3E, 0x37, 0x2C, 0x25,
+  0x1A, 0x13, 0x08, 0x01,
+
+  0xE6, 0xEF, 0xF4, 0xFD, 0xC2, 0xCB, 0xD0, 0xD9, 0xAE, 0xA7, 0xBC, 0xB5,
+  0x8A, 0x83, 0x98, 0x91,
+
+  0x4D, 0x44, 0x5F, 0x56, 0x69, 0x60, 0x7B, 0x72, 0x05, 0x0C, 0x17, 0x1E,
+  0x21, 0x28, 0x33, 0x3A,
+
+  0xDD, 0xD4, 0xCF, 0xC6, 0xF9, 0xF0, 0xEB, 0xE2, 0x95, 0x9C, 0x87, 0x8E,
+  0xB1, 0xB8, 0xA3, 0xAA,
+
+  0xEC, 0xE5, 0xFE, 0xF7, 0xC8, 0xC1, 0xDA, 0xD3, 0xA4, 0xAD, 0xB6, 0xBF,
+  0x80, 0x89, 0x92, 0x9B,
+
+  0x7C, 0x75, 0x6E, 0x67, 0x58, 0x51, 0x4A, 0x43, 0x34, 0x3D, 0x26, 0x2F,
+  0x10, 0x19, 0x02, 0x0B,
+
+  0xD7, 0xDE, 0xC5, 0xCC, 0xF3, 0xFA, 0xE1, 0xE8, 0x9F, 0x96, 0x8D, 0x84,
+  0xBB, 0xB2, 0xA9, 0xA0,
+
+  0x47, 0x4E, 0x55, 0x5C, 0x63, 0x6A, 0x71, 0x78, 0x0F, 0x06, 0x1D, 0x14,
+  0x2B, 0x22, 0x39, 0x30,
+
+  0x9A, 0x93, 0x88, 0x81, 0xBE, 0xB7, 0xAC, 0xA5, 0xD2, 0xDB, 0xC0, 0xC9,
+  0xF6, 0xFF, 0xE4, 0xED,
+
+  0x0A, 0x03, 0x18, 0x11, 0x2E, 0x27, 0x3C, 0x35, 0x42, 0x4B, 0x50, 0x59,
+  0x66, 0x6F, 0x74, 0x7D,
+
+  0xA1, 0xA8, 0xB3, 0xBA, 0x85, 0x8C, 0x97, 0x9E, 0xE9, 0xE0, 0xFB, 0xF2,
+  0xCD, 0xC4, 0xDF, 0xD6,
+
+  0x31, 0x38, 0x23, 0x2A, 0x15, 0x1C, 0x07, 0x0E, 0x79, 0x70, 0x6B, 0x62,
+  0x5D, 0x54, 0x4F, 0x46
+];
+
+
+/**
+ * Precomputed lookup of multiplication by 11 in GF(2^8)
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.MULT_B_ = [
+  0x00, 0x0B, 0x16, 0x1D, 0x2C, 0x27, 0x3A, 0x31, 0x58, 0x53, 0x4E, 0x45,
+  0x74, 0x7F, 0x62, 0x69,
+
+  0xB0, 0xBB, 0xA6, 0xAD, 0x9C, 0x97, 0x8A, 0x81, 0xE8, 0xE3, 0xFE, 0xF5,
+  0xC4, 0xCF, 0xD2, 0xD9,
+
+  0x7B, 0x70, 0x6D, 0x66, 0x57, 0x5C, 0x41, 0x4A, 0x23, 0x28, 0x35, 0x3E,
+  0x0F, 0x04, 0x19, 0x12,
+
+  0xCB, 0xC0, 0xDD, 0xD6, 0xE7, 0xEC, 0xF1, 0xFA, 0x93, 0x98, 0x85, 0x8E,
+  0xBF, 0xB4, 0xA9, 0xA2,
+
+  0xF6, 0xFD, 0xE0, 0xEB, 0xDA, 0xD1, 0xCC, 0xC7, 0xAE, 0xA5, 0xB8, 0xB3,
+  0x82, 0x89, 0x94, 0x9F,
+
+  0x46, 0x4D, 0x50, 0x5B, 0x6A, 0x61, 0x7C, 0x77, 0x1E, 0x15, 0x08, 0x03,
+  0x32, 0x39, 0x24, 0x2F,
+
+  0x8D, 0x86, 0x9B, 0x90, 0xA1, 0xAA, 0xB7, 0xBC, 0xD5, 0xDE, 0xC3, 0xC8,
+  0xF9, 0xF2, 0xEF, 0xE4,
+
+  0x3D, 0x36, 0x2B, 0x20, 0x11, 0x1A, 0x07, 0x0C, 0x65, 0x6E, 0x73, 0x78,
+  0x49, 0x42, 0x5F, 0x54,
+
+  0xF7, 0xFC, 0xE1, 0xEA, 0xDB, 0xD0, 0xCD, 0xC6, 0xAF, 0xA4, 0xB9, 0xB2,
+  0x83, 0x88, 0x95, 0x9E,
+
+  0x47, 0x4C, 0x51, 0x5A, 0x6B, 0x60, 0x7D, 0x76, 0x1F, 0x14, 0x09, 0x02,
+  0x33, 0x38, 0x25, 0x2E,
+
+  0x8C, 0x87, 0x9A, 0x91, 0xA0, 0xAB, 0xB6, 0xBD, 0xD4, 0xDF, 0xC2, 0xC9,
+  0xF8, 0xF3, 0xEE, 0xE5,
+
+  0x3C, 0x37, 0x2A, 0x21, 0x10, 0x1B, 0x06, 0x0D, 0x64, 0x6F, 0x72, 0x79,
+  0x48, 0x43, 0x5E, 0x55,
+
+  0x01, 0x0A, 0x17, 0x1C, 0x2D, 0x26, 0x3B, 0x30, 0x59, 0x52, 0x4F, 0x44,
+  0x75, 0x7E, 0x63, 0x68,
+
+  0xB1, 0xBA, 0xA7, 0xAC, 0x9D, 0x96, 0x8B, 0x80, 0xE9, 0xE2, 0xFF, 0xF4,
+  0xC5, 0xCE, 0xD3, 0xD8,
+
+  0x7A, 0x71, 0x6C, 0x67, 0x56, 0x5D, 0x40, 0x4B, 0x22, 0x29, 0x34, 0x3F,
+  0x0E, 0x05, 0x18, 0x13,
+
+  0xCA, 0xC1, 0xDC, 0xD7, 0xE6, 0xED, 0xF0, 0xFB, 0x92, 0x99, 0x84, 0x8F,
+  0xBE, 0xB5, 0xA8, 0xA3
+];
+
+
+/**
+ * Precomputed lookup of multiplication by 13 in GF(2^8)
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.MULT_D_ = [
+  0x00, 0x0D, 0x1A, 0x17, 0x34, 0x39, 0x2E, 0x23, 0x68, 0x65, 0x72, 0x7F,
+  0x5C, 0x51, 0x46, 0x4B,
+
+  0xD0, 0xDD, 0xCA, 0xC7, 0xE4, 0xE9, 0xFE, 0xF3, 0xB8, 0xB5, 0xA2, 0xAF,
+  0x8C, 0x81, 0x96, 0x9B,
+
+  0xBB, 0xB6, 0xA1, 0xAC, 0x8F, 0x82, 0x95, 0x98, 0xD3, 0xDE, 0xC9, 0xC4,
+  0xE7, 0xEA, 0xFD, 0xF0,
+
+  0x6B, 0x66, 0x71, 0x7C, 0x5F, 0x52, 0x45, 0x48, 0x03, 0x0E, 0x19, 0x14,
+  0x37, 0x3A, 0x2D, 0x20,
+
+  0x6D, 0x60, 0x77, 0x7A, 0x59, 0x54, 0x43, 0x4E, 0x05, 0x08, 0x1F, 0x12,
+  0x31, 0x3C, 0x2B, 0x26,
+
+  0xBD, 0xB0, 0xA7, 0xAA, 0x89, 0x84, 0x93, 0x9E, 0xD5, 0xD8, 0xCF, 0xC2,
+  0xE1, 0xEC, 0xFB, 0xF6,
+
+  0xD6, 0xDB, 0xCC, 0xC1, 0xE2, 0xEF, 0xF8, 0xF5, 0xBE, 0xB3, 0xA4, 0xA9,
+  0x8A, 0x87, 0x90, 0x9D,
+
+  0x06, 0x0B, 0x1C, 0x11, 0x32, 0x3F, 0x28, 0x25, 0x6E, 0x63, 0x74, 0x79,
+  0x5A, 0x57, 0x40, 0x4D,
+
+  0xDA, 0xD7, 0xC0, 0xCD, 0xEE, 0xE3, 0xF4, 0xF9, 0xB2, 0xBF, 0xA8, 0xA5,
+  0x86, 0x8B, 0x9C, 0x91,
+
+  0x0A, 0x07, 0x10, 0x1D, 0x3E, 0x33, 0x24, 0x29, 0x62, 0x6F, 0x78, 0x75,
+  0x56, 0x5B, 0x4C, 0x41,
+
+  0x61, 0x6C, 0x7B, 0x76, 0x55, 0x58, 0x4F, 0x42, 0x09, 0x04, 0x13, 0x1E,
+  0x3D, 0x30, 0x27, 0x2A,
+
+  0xB1, 0xBC, 0xAB, 0xA6, 0x85, 0x88, 0x9F, 0x92, 0xD9, 0xD4, 0xC3, 0xCE,
+  0xED, 0xE0, 0xF7, 0xFA,
+
+  0xB7, 0xBA, 0xAD, 0xA0, 0x83, 0x8E, 0x99, 0x94, 0xDF, 0xD2, 0xC5, 0xC8,
+  0xEB, 0xE6, 0xF1, 0xFC,
+
+  0x67, 0x6A, 0x7D, 0x70, 0x53, 0x5E, 0x49, 0x44, 0x0F, 0x02, 0x15, 0x18,
+  0x3B, 0x36, 0x21, 0x2C,
+
+  0x0C, 0x01, 0x16, 0x1B, 0x38, 0x35, 0x22, 0x2F, 0x64, 0x69, 0x7E, 0x73,
+  0x50, 0x5D, 0x4A, 0x47,
+
+  0xDC, 0xD1, 0xC6, 0xCB, 0xE8, 0xE5, 0xF2, 0xFF, 0xB4, 0xB9, 0xAE, 0xA3,
+  0x80, 0x8D, 0x9A, 0x97
+];
+
+
+/**
+ * Precomputed lookup of multiplication by 14 in GF(2^8)
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.MULT_E_ = [
+  0x00, 0x0E, 0x1C, 0x12, 0x38, 0x36, 0x24, 0x2A, 0x70, 0x7E, 0x6C, 0x62,
+  0x48, 0x46, 0x54, 0x5A,
+
+  0xE0, 0xEE, 0xFC, 0xF2, 0xD8, 0xD6, 0xC4, 0xCA, 0x90, 0x9E, 0x8C, 0x82,
+  0xA8, 0xA6, 0xB4, 0xBA,
+
+  0xDB, 0xD5, 0xC7, 0xC9, 0xE3, 0xED, 0xFF, 0xF1, 0xAB, 0xA5, 0xB7, 0xB9,
+  0x93, 0x9D, 0x8F, 0x81,
+
+  0x3B, 0x35, 0x27, 0x29, 0x03, 0x0D, 0x1F, 0x11, 0x4B, 0x45, 0x57, 0x59,
+  0x73, 0x7D, 0x6F, 0x61,
+
+  0xAD, 0xA3, 0xB1, 0xBF, 0x95, 0x9B, 0x89, 0x87, 0xDD, 0xD3, 0xC1, 0xCF,
+  0xE5, 0xEB, 0xF9, 0xF7,
+
+  0x4D, 0x43, 0x51, 0x5F, 0x75, 0x7B, 0x69, 0x67, 0x3D, 0x33, 0x21, 0x2F,
+  0x05, 0x0B, 0x19, 0x17,
+
+  0x76, 0x78, 0x6A, 0x64, 0x4E, 0x40, 0x52, 0x5C, 0x06, 0x08, 0x1A, 0x14,
+  0x3E, 0x30, 0x22, 0x2C,
+
+  0x96, 0x98, 0x8A, 0x84, 0xAE, 0xA0, 0xB2, 0xBC, 0xE6, 0xE8, 0xFA, 0xF4,
+  0xDE, 0xD0, 0xC2, 0xCC,
+
+  0x41, 0x4F, 0x5D, 0x53, 0x79, 0x77, 0x65, 0x6B, 0x31, 0x3F, 0x2D, 0x23,
+  0x09, 0x07, 0x15, 0x1B,
+
+  0xA1, 0xAF, 0xBD, 0xB3, 0x99, 0x97, 0x85, 0x8B, 0xD1, 0xDF, 0xCD, 0xC3,
+  0xE9, 0xE7, 0xF5, 0xFB,
+
+  0x9A, 0x94, 0x86, 0x88, 0xA2, 0xAC, 0xBE, 0xB0, 0xEA, 0xE4, 0xF6, 0xF8,
+  0xD2, 0xDC, 0xCE, 0xC0,
+
+  0x7A, 0x74, 0x66, 0x68, 0x42, 0x4C, 0x5E, 0x50, 0x0A, 0x04, 0x16, 0x18,
+  0x32, 0x3C, 0x2E, 0x20,
+
+  0xEC, 0xE2, 0xF0, 0xFE, 0xD4, 0xDA, 0xC8, 0xC6, 0x9C, 0x92, 0x80, 0x8E,
+  0xA4, 0xAA, 0xB8, 0xB6,
+
+  0x0C, 0x02, 0x10, 0x1E, 0x34, 0x3A, 0x28, 0x26, 0x7C, 0x72, 0x60, 0x6E,
+  0x44, 0x4A, 0x58, 0x56,
+
+  0x37, 0x39, 0x2B, 0x25, 0x0F, 0x01, 0x13, 0x1D, 0x47, 0x49, 0x5B, 0x55,
+  0x7F, 0x71, 0x63, 0x6D,
+
+  0xD7, 0xD9, 0xCB, 0xC5, 0xEF, 0xE1, 0xF3, 0xFD, 0xA7, 0xA9, 0xBB, 0xB5,
+  0x9F, 0x91, 0x83, 0x8D
+];

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/arc4.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/arc4.js b/externs/GCL/externs/goog/crypt/arc4.js
new file mode 100644
index 0000000..73c6758
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/arc4.js
@@ -0,0 +1,164 @@
+// Copyright 2005 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview ARC4 streamcipher implementation.  A description of the
+ * algorithm can be found at:
+ * http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt.
+ *
+ * Usage:
+ * <code>
+ *   var arc4 = new goog.crypt.Arc4();
+ *   arc4.setKey(key);
+ *   arc4.discard(1536);
+ *   arc4.crypt(bytes);
+ * </code>
+ *
+ * Note: For converting between strings and byte arrays, goog.crypt.base64 may
+ * be useful.
+ *
+ */
+
+goog.provide('goog.crypt.Arc4');
+
+goog.require('goog.asserts');
+
+
+
+/**
+ * ARC4 streamcipher implementation.
+ * @constructor
+ * @final
+ * @struct
+ */
+goog.crypt.Arc4 = function() {
+  /**
+   * A permutation of all 256 possible bytes.
+   * @type {Array<number>}
+   * @private
+   */
+  this.state_ = [];
+
+  /**
+   * 8 bit index pointer into this.state_.
+   * @type {number}
+   * @private
+   */
+  this.index1_ = 0;
+
+  /**
+   * 8 bit index pointer into this.state_.
+   * @type {number}
+   * @private
+   */
+  this.index2_ = 0;
+};
+
+
+/**
+ * Initialize the cipher for use with new key.
+ * @param {Array<number>} key A byte array containing the key.
+ * @param {number=} opt_length Indicates # of bytes to take from the key.
+ */
+goog.crypt.Arc4.prototype.setKey = function(key, opt_length) {
+  goog.asserts.assertArray(key, 'Key parameter must be a byte array');
+
+  if (!opt_length) {
+    opt_length = key.length;
+  }
+
+  var state = this.state_;
+
+  for (var i = 0; i < 256; ++i) {
+    state[i] = i;
+  }
+
+  var j = 0;
+  for (var i = 0; i < 256; ++i) {
+    j = (j + state[i] + key[i % opt_length]) & 255;
+
+    var tmp = state[i];
+    state[i] = state[j];
+    state[j] = tmp;
+  }
+
+  this.index1_ = 0;
+  this.index2_ = 0;
+};
+
+
+/**
+ * Discards n bytes of the keystream.
+ * These days 1536 is considered a decent amount to drop to get the key state
+ * warmed-up enough for secure usage. This is not done in the constructor to
+ * preserve efficiency for use cases that do not need this.
+ * NOTE: Discard is identical to crypt without actually xoring any data. It's
+ * unfortunate to have this code duplicated, but this was done for performance
+ * reasons. Alternatives which were attempted:
+ * 1. Create a temp array of the correct length and pass it to crypt. This
+ *    works but needlessly allocates an array. But more importantly this
+ *    requires choosing an array type (Array or Uint8Array) in discard, and
+ *    choosing a different type than will be passed to crypt by the client
+ *    code hurts the javascript engines ability to optimize crypt (7x hit in
+ *    v8).
+ * 2. Make data option in crypt so discard can pass null, this has a huge
+ *    perf hit for crypt.
+ * @param {number} length Number of bytes to disregard from the stream.
+ */
+goog.crypt.Arc4.prototype.discard = function(length) {
+  var i = this.index1_;
+  var j = this.index2_;
+  var state = this.state_;
+
+  for (var n = 0; n < length; ++n) {
+    i = (i + 1) & 255;
+    j = (j + state[i]) & 255;
+
+    var tmp = state[i];
+    state[i] = state[j];
+    state[j] = tmp;
+  }
+
+  this.index1_ = i;
+  this.index2_ = j;
+};
+
+
+/**
+ * En- or decrypt (same operation for streamciphers like ARC4)
+ * @param {Array<number>|Uint8Array} data The data to be xor-ed in place.
+ * @param {number=} opt_length The number of bytes to crypt.
+ */
+goog.crypt.Arc4.prototype.crypt = function(data, opt_length) {
+  if (!opt_length) {
+    opt_length = data.length;
+  }
+  var i = this.index1_;
+  var j = this.index2_;
+  var state = this.state_;
+
+  for (var n = 0; n < opt_length; ++n) {
+    i = (i + 1) & 255;
+    j = (j + state[i]) & 255;
+
+    var tmp = state[i];
+    state[i] = state[j];
+    state[j] = tmp;
+
+    data[n] ^= state[(state[i] + state[j]) & 255];
+  }
+
+  this.index1_ = i;
+  this.index2_ = j;
+};