text: /*
   * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
   *  
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"), 
   * to deal in the Software without restriction, including without limitation 
   * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
   * and/or sell copies of the Software, and to permit persons to whom the 
   * Software is furnished to do so, subject to the following conditions:
   *  
   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.
   *  
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
   * DEALINGS IN THE SOFTWARE.
   * 
   */
  
  define(function (require, exports) {
      "use strict";
  
      var mathjs = require("mathjs"),
          _ = require("lodash");
  
      /**
       * Returns the number represented by the provided string, or null if there
       * is no such number.
       * 
       * @param {!string} value
       * @return {?number}
       */
      var parseNumber = function (value) {
          if (/^(\-|\+)?(\d+|\d*\.\d+|Infinity)$/.test(value)) {
              return Number(value);
          }
  
          return null;
      };
  
      /**
       * Return a string representation of a (finite) number, or some default
       * representation if the supplied value is not a finite number. If no
       * default is supplied, the empty string is used as a default representation.
       * 
       * @param {!number} value
       * @param {string=} defaultRep
       * @return {!string}
       */
      var formatNumber = function (value, defaultRep) {
          if (_.isFinite(value)) {
              return value.toString();
          } else {
              if (typeof defaultRep === "string") {
                  return defaultRep;
              } else {
                  return "";
              }
          }
      };
  
      /**
      * Convert a pixel dimension to a number.
      *
      * @param {string} pixelDimension
      * @return {?number}
      */
      var pixelDimensionToNumber = function (pixelDimension) {
          if (pixelDimension.substr(-2) === "px") {
              return parseNumber(pixelDimension.substring(0, pixelDimension.length - 2));
          }
              
          return null;
      };
  
      /**
       * Convert a number to one that can tbe represented as a fraction, rounded to 4 decimal places.
       *
       * @param {number} numerator 
       * @param {number} denominator
       * @return {number} Rounded to four decimal places
       */
      var normalize = function (numerator, denominator) {
          return mathjs.round(mathjs.round(numerator * denominator, 0) / denominator, 4);
      };
  
      /**
       * A small number used to account for rounding errors when
       *  determining whether a vector is scaled.
       *  
       * @private
       * @const
       * @type {number} 
       */
      var _EPSILON = 1 - 0.99999;
  
      /**
       * Indicates whether given vector is approximately of length one.
       *
       * @private
       * @param {number} a
       * @param {number} b
       * @return {boolean}
       */
      var _hasScale = function (a, b) {
          var scale = (a * a) + (b * b),
              diff = 1 - scale,
              dist = Math.abs(diff);
          
          return dist > _EPSILON;
      };
  
      /**
       * Indicates whether the given affine transformation describes just a rotation.
       *
       * @param {Array.<number>} transform
       * @return {boolean}
       */
      var isRotation = function (transform) {
          return transform.tx === 0 && transform.ty === 0 &&
              !_hasScale(transform.yx, transform.yy) &&
              !_hasScale(transform.xx, transform.xy);
      };
  
      /**
       * Clamp the value to the given range.
       * 
       * @param {number} value
       * @param {number} min
       * @param {number} max
       * @return {number}
       */
      var clamp = function (value, min, max) {
          return (value < min) ? min : (value > max ? max : value);
      };
  
      /**
       * Measure the planar distance between two points.
       *
       * @param {number} x1
       * @param {number} y1
       * @param {number} x2
       * @param {number} y2
       * @return {number}
       */
      var distance = function (x1, y1, x2, y2) {
          var xdiff = x2 - x1,
              ydiff = y2 - y1;
  
          return Math.sqrt((xdiff * xdiff) + (ydiff * ydiff));
      };
  
      exports.parseNumber = parseNumber;
      exports.formatNumber = formatNumber;
      exports.pixelDimensionToNumber = pixelDimensionToNumber;
      exports.normalize = normalize;
      exports.isRotation = isRotation;
      exports.clamp = clamp;
      exports.distance = distance;
  });
  