Commits

Colin Copeland committed ed30e64

add basic board

  • Participants
  • Parent commits 49aebc4

Comments (0)

Files changed (5)

tic-tac-toe/example.html

-<script src="processing-0.8.js"></script>
-<canvas datasrc="example.pjs" width="200" height="200"></canvas>

tic-tac-toe/index.html

         <meta charset="utf-8" />
         <title>Tic Tac Toe</title>
         <link href="media/style.css" media="screen" rel="Stylesheet" type="text/css" /> 
-        <script src="media/processing-0.8.js" type="text/javascript" charset="utf-8" ></script>
         <script src="media/jquery-1.4.2.js" type="text/javascript" charset="utf-8" ></script>
-        <script type="text/javascript" charset="utf-8">
-            $(document).ready(function() {
-                // moo
-            })
-        </script>
+        <script src="media/game.js" type="text/javascript" charset="utf-8" ></script>
     </head>
     <body>
         <header>Tic Tac Toe</header>
-        <canvas width="800" height="600"></canvas>
+        <div id="coords"></div>
+        <canvas id='board' width="600" height="600"></canvas>
+        <ul>
+            <li><a href='https://developer.mozilla.org/en/Canvas_tutorial'>Canvas_tutorial</a></li>
+            <li><a href='http://developer.apple.com/mac/library/documentation/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/Canvas.html'>Apple's Using the Canvas</a></li>
+            <li><a href='http://billmill.org/static/canvastutorial/paddle.html'>Paddle</a></li>
+        </ul>
         <footer>Caktus Consulting Group, LLC</footer>
     </body>
 </html>

tic-tac-toe/media/game.js

+var line_size = 10;
+var box_size = 0;
+
+function setup_board(ctx) {
+    box_size = ctx.canvas.width/3.0;
+    console.log('box size', box_size);
+    console.log('line size', line_size);
+    ctx.clearRect(0, 0, ctx.canvas.height, ctx.canvas.width);
+    // border
+    ctx.fillRect(0, 0, line_size, ctx.canvas.height);
+    ctx.fillRect(0, 0, ctx.canvas.width, line_size);
+    ctx.fillRect(ctx.canvas.height - line_size, 0, line_size, ctx.canvas.height);
+    ctx.fillRect(0, ctx.canvas.width - line_size, ctx.canvas.width, line_size);
+    // dividers
+    ctx.fillRect(box_size, 0, line_size, ctx.canvas.height);
+    ctx.fillRect(box_size * 2, 0, line_size, ctx.canvas.height);
+    ctx.fillRect(0, box_size, ctx.canvas.width, line_size);
+    ctx.fillRect(0, box_size * 2, ctx.canvas.width, line_size);
+    // save?
+    ctx.save();
+}
+
+function draw(ctx, x, y) {
+    console.log('draw', ctx, x, y);
+    region_x = Math.floor(x / box_size);
+    region_y = Math.floor(y / box_size);
+    mark(ctx, region_x, region_y);
+}
+
+function mark(ctx, region_x, region_y) {
+    console.log('mark', region_x, region_y);
+    var x = region_x * box_size + line_size;
+    var y = region_y * box_size + line_size;
+    console.log('left/top', x, y);
+    ctx.fillStyle = "#00A308";
+    ctx.fillRect(x, y, box_size - line_size, box_size - line_size);
+    // ctx.save();
+}
+
+$(document).ready(function() {
+    var canvas = $('#board');
+    var ctx = canvas.get(0).getContext("2d");
+    canvas.click(function(e) {
+        draw(ctx, e.offsetX, e.offsetY);
+    });
+    canvas.mousemove(function(e) {
+        $('#coords').text(e.offsetX + ', ' + e.offsetY);
+    });
+    
+    // draw basic board
+    setup_board(ctx);
+});

tic-tac-toe/media/processing-0.8.js

-/*
-
-    P R O C E S S I N G . J S - 0.8
-    a port of the Processing visualization language
-    
-    License       : MIT 
-    Developer     : John Resig: http://ejohn.org
-    Web Site      : http://processingjs.org  
-    Java Version  : http://processing.org
-    Github Repo.  : http://github.com/jeresig/processing-js
-    Bug Tracking  : http://processing-js.lighthouseapp.com
-    Mozilla POW!  : http://wiki.Mozilla.org/Education/Projects/ProcessingForTheWeb
-    Maintained by : Seneca: http://zenit.senecac.on.ca/wiki/index.php/Processing.js
-                    Hyper-Metrix: http://hyper-metrix.com/#Processing
-                    BuildingSky: http://weare.buildingsky.net/pages/processing-js
-  
- */
-
-(function() {
-
-  this.Processing = function Processing(aElement, aCode) {
-    // Get the DOM element if string was passed
-    if (typeof aElement === "string") {
-      aElement = document.getElementById(aElement);
-    }
-
-    // The problem: if the HTML canvas dimensions differ from the
-    // dimensions specified in the size() call in the sketch, for
-    // 3D sketches, browsers will either not render or render the
-    // scene incorrectly. To fix this, we need to adjust the attributes
-    // of the canvas width and height.
-    // this regex needs to be cleaned up a bit
-    var r = "" + aCode.match(/size\s*\((?:.+),(?:.+),\s*(OPENGL|P3D)\s*\)\s*;/);
-    var dimensions = r.match(/[0-9]+/g);
-
-    if (dimensions) {
-      var sketchWidth = parseInt(dimensions[0], 10);
-      var sketchHeight = parseInt(dimensions[1], 10);
-
-      // only adjust the attributes if they differ
-      if (aElement.width !== sketchWidth || aElement.height !== sketchHeight) {
-        aElement.setAttribute("width", sketchWidth);
-        aElement.setAttribute("height", sketchHeight);
-      }
-    }
-
-    // Build an Processing functions and env. vars into 'p'  
-    var p = Processing.build(aElement);
-
-    // Send aCode Processing syntax to be converted to JavaScript
-    if (aCode) {
-      p.init(aCode);
-    }
-
-    return p;
-  };
-
-  // Share lib space
-  Processing.lib = {};
-
-  // IE Unfriendly AJAX Method
-  var ajax = function(url) {
-    var AJAX = new window.XMLHttpRequest();
-    if (AJAX) {
-      AJAX.open("GET", url + "?t=" + new Date().getTime(), false);
-      AJAX.send(null);
-      return AJAX.responseText;
-    } else {
-      return false;
-    }
-  };
-
-  // Automatic Initialization Method
-  var init = function() {
-    var canvas = document.getElementsByTagName('canvas');
-
-    for (var i = 0, l = canvas.length; i < l; i++) {
-      // Get data-src instead of datasrc
-      var datasrc = canvas[i].getAttribute('data-src');
-      if (datasrc === null) {
-        // Temporary fallback for datasrc
-        datasrc = canvas[i].getAttribute('datasrc');
-      }
-      if (datasrc) {
-        // The problem: if the HTML canvas dimensions differ from the
-        // dimensions specified in the size() call in the sketch, for
-        // 3D sketches, browsers will either not render or render the
-        // scene incorrectly. To fix this, we need to adjust the attributes
-        // of the canvas width and height.
-        // Get the source, we'll need to find what the user has used in size()
-        var sketchSource = ajax(datasrc);
-        // get the dimensions
-        // this regex needs to be cleaned up a bit
-        var r = "" + sketchSource.match(/size\s*\((?:.+),(?:.+),\s*(OPENGL|P3D)\s*\)\s*;/);
-        var dimensions = r.match(/[0-9]+/g);
-
-        if (dimensions) {
-          var sketchWidth = parseInt(dimensions[0], 10);
-          var sketchHeight = parseInt(dimensions[1], 10);
-
-          // only adjust the attributes if they differ
-          if (canvas[i].width !== sketchWidth || canvas[i].height !== sketchHeight) {
-            canvas[i].setAttribute("width", sketchWidth);
-            canvas[i].setAttribute("height", sketchHeight);
-          }
-        }
-        Processing(canvas[i], sketchSource);
-      }
-    }
-  };
-
-  // Wrapper to easily deal with array names changes.
-  var newWebGLArray = function(data) {
-    return new WebGLFloatArray(data);
-  };
-
-  var createProgramObject = function(curContext, vetexShaderSource, fragmentShaderSource) {
-    var vertexShaderObject = curContext.createShader(curContext.VERTEX_SHADER);
-    curContext.shaderSource(vertexShaderObject, vetexShaderSource);
-    curContext.compileShader(vertexShaderObject);
-    if (!curContext.getShaderParameter(vertexShaderObject, curContext.COMPILE_STATUS)) {
-      throw curContext.getShaderInfoLog(vertexShaderObject);
-    }
-
-    var fragmentShaderObject = curContext.createShader(curContext.FRAGMENT_SHADER);
-    curContext.shaderSource(fragmentShaderObject, fragmentShaderSource);
-    curContext.compileShader(fragmentShaderObject);
-    if (!curContext.getShaderParameter(fragmentShaderObject, curContext.COMPILE_STATUS)) {
-      throw curContext.getShaderInfoLog(fragmentShaderObject);
-    }
-
-    var programObject = curContext.createProgram();
-    curContext.attachShader(programObject, vertexShaderObject);
-    curContext.attachShader(programObject, fragmentShaderObject);
-    curContext.linkProgram(programObject);
-    if (!curContext.getProgramParameter(programObject, curContext.LINK_STATUS)) {
-      throw "Error linking shaders.";
-    }
-
-    return programObject;
-  };
-
-  var programObject3D;
-  var programObject2D;
-
-  // Vertices are specified in a counter-clockwise order
-  // triangles are in this order: back, front, right, bottom, left, top
-  var boxVerts = [0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5,
-                     -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5,
-                     -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5,
-                      0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5,
-                      0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5,
-                     -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5,
-                     -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5,
-                     -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5,
-                     -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5];
-
-  var boxNorms = [0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1,
-                      0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,
-                      1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
-                      0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,
-                      -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,
-                      0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0];
-
-  var boxOutlineVerts = [0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5,
-                            -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5,
-                             0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5,
-                            -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
-                             0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5,
-                            -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5];
-
-  var boxBuffer;
-  var boxNormBuffer;
-  var boxOutlineBuffer;
-
-  var sphereBuffer;
-
-  var lineBuffer;
-
-  var pointBuffer;
-
-  // Vertex shader for points and lines
-  var vertexShaderSource2D = "attribute vec3 Vertex;" + "uniform vec4 color;" +
-
-  "uniform mat4 model;" + "uniform mat4 view;" + "uniform mat4 projection;" +
-
-  "void main(void) {" + "  gl_FrontColor = color;" + "  gl_Position = projection * view * model * vec4(Vertex, 1.0);" + "}";
-
-  var fragmentShaderSource2D = "void main(void){" + "  gl_FragColor = gl_Color;" + "}";
-
-  // Vertex shader for boxes and spheres
-  var vertexShaderSource3D = "attribute vec3 Vertex;" + "attribute vec3 Normal;" +
-
-  "uniform vec4 color;" +
-
-  "uniform bool usingMat;" + "uniform vec3 specular;" + "uniform vec3 mat_emissive;" + "uniform vec3 mat_ambient;" + "uniform vec3 mat_specular;" + "uniform float shininess;" +
-
-  "uniform mat4 model;" + "uniform mat4 view;" + "uniform mat4 projection;" + "uniform mat4 normalTransform;" +
-
-  "uniform int lightCount;" + "uniform vec3 falloff;" +
-
-  "struct Light {" + "  bool dummy;" + "   int type;" + "   vec3 color;" + "   vec3 position;" + "  vec3 direction;" + "  float angle;" + "  vec3 halfVector;" + "  float concentration;" + "};" + "uniform Light lights[8];" +
-
-  "void AmbientLight( inout vec3 totalAmbient, in vec3 ecPos, in Light light ) {" +
-  // Get the vector from the light to the vertex
-  // Get the distance from the current vector to the light position
-  "  float d = length( light.position - ecPos );" + "  float attenuation = 1.0 / ( falloff[0] + ( falloff[1] * d ) + ( falloff[2] * d * d ));" + "  totalAmbient += light.color * attenuation;" + "}" +
-
-  "void DirectionalLight( inout vec3 col, in vec3 ecPos, inout vec3 spec, in vec3 vertNormal, in Light light ) {" + "  float powerfactor = 0.0;" + "  float nDotVP = max(0.0, dot( vertNormal, light.position ));" + "  float nDotVH = max(0.0, dot( vertNormal, normalize( light.position-ecPos )));" +
-
-  "  if( nDotVP != 0.0 ){" + "    powerfactor = pow( nDotVH, shininess );" + "  }" +
-
-  "  col += light.color * nDotVP;" + "  spec += specular * powerfactor;" + "}" +
-
-  "void PointLight( inout vec3 col, inout vec3 spec, in vec3 vertNormal, in vec3 ecPos, in vec3 eye, in Light light ) {" + "  float powerfactor;" +
-
-  // Get the vector from the light to the vertex
-  "   vec3 VP = light.position - ecPos;" +
-
-  // Get the distance from the current vector to the light position
-  "  float d = length( VP ); " +
-
-  // Normalize the light ray so it can be used in the dot product operation.
-  "  VP = normalize( VP );" +
-
-  "  float attenuation = 1.0 / ( falloff[0] + ( falloff[1] * d ) + ( falloff[2] * d * d ));" +
-
-  "  float nDotVP = max( 0.0, dot( vertNormal, VP ));" + "  vec3 halfVector = normalize( VP + eye );" + "  float nDotHV = max( 0.0, dot( vertNormal, halfVector ));" +
-
-  "  if( nDotVP == 0.0) {" + "    powerfactor = 0.0;" + "  }" + "  else{" + "    powerfactor = pow( nDotHV, shininess );" + "  }" +
-
-  "  spec += specular * powerfactor * attenuation;" + "  col += light.color * nDotVP * attenuation;" + "}" +
-
-  /*
-  */
-  "void SpotLight( inout vec3 col, inout vec3 spec, in vec3 vertNormal, in vec3 ecPos, in vec3 eye, in Light light ) {" + "  float spotAttenuation;" + "  float powerfactor;" +
-
-  // calculate the vector from the current vertex to the light.
-  "  vec3 VP = light.position - ecPos; " + "  vec3 ldir = normalize( light.direction );" +
-
-  // get the distance from the spotlight and the vertex
-  "  float d = length( VP );" + "  VP = normalize( VP );" +
-
-  "  float attenuation = 1.0 / ( falloff[0] + ( falloff[1] * d ) + ( falloff[2] * d * d ) );" +
-
-  // dot product of the vector from vertex to light and light direction.
-  "  float spotDot = dot( VP, ldir );" +
-
-  // if the vertex falls inside the cone
-  "  if( spotDot < cos( light.angle ) ) {" + "    spotAttenuation = pow( spotDot, light.concentration );" + "  }" + "  else{" + "    spotAttenuation = 1.0;" + "  }" + "  attenuation *= spotAttenuation;" +
-
-  "  float nDotVP = max( 0.0, dot( vertNormal, VP ));" + "  vec3 halfVector = normalize( VP + eye );" + "  float nDotHV = max( 0.0, dot( vertNormal, halfVector ));" +
-
-  "  if( nDotVP == 0.0 ) {" + "    powerfactor = 0.0;" + "  }" + "  else {" + "    powerfactor = pow( nDotHV, shininess );" + "  }" +
-
-  "  spec += specular * powerfactor * attenuation;" + "  col += light.color * nDotVP * attenuation;" + "}" +
-
-  "void main(void) {" + "  vec3 finalAmbient = vec3( 0.0, 0.0, 0.0 );" + "  vec3 finalDiffuse = vec3( 0.0, 0.0, 0.0 );" + "  vec3 finalSpecular = vec3( 0.0, 0.0, 0.0 );" +
-
-  "  vec3 norm = vec3( normalTransform * vec4( Normal, 0.0 ) );" +
-
-  "  vec4 ecPos4 = view * model * vec4(Vertex,1.0);" + "  vec3 ecPos = (vec3(ecPos4))/ecPos4.w;" + "  vec3 eye = vec3( 0.0, 0.0, 1.0 );" +
-
-  // If there were no lights this draw call, just use the 
-  // assigned fill color of the shape and the specular value
-  "  if( lightCount == 0 ) {" + "    gl_FrontColor = color + vec4(mat_specular,1.0);" + "  }" + "  else {" + "    for( int i = 0; i < lightCount; i++ ) {" + "      if( lights[i].type == 0 ) {" + "        AmbientLight( finalAmbient, ecPos, lights[i] );" + "      }" + "      else if( lights[i].type == 1 ) {" + "        DirectionalLight( finalDiffuse,ecPos, finalSpecular, norm, lights[i] );" + "      }" + "      else if( lights[i].type == 2 ) {" + "        PointLight( finalDiffuse, finalSpecular, norm, ecPos, eye, lights[i] );" + "      }" + "      else if( lights[i].type == 3 ) {" + "        SpotLight( finalDiffuse, finalSpecular, norm, ecPos, eye, lights[i] );" + "      }" + "    }" +
-
-  "   if( usingMat == false ) {" + "    gl_FrontColor = vec4(  " + "      vec3(color) * finalAmbient +" + "      vec3(color) * finalDiffuse +" + "      vec3(color) * finalSpecular," + "      color[3] );" + "   }" + "   else{" + "     gl_FrontColor = vec4( " + "       mat_emissive + " + "       (vec3(color) * mat_ambient * finalAmbient) + " + "       (vec3(color) * finalDiffuse) + " + "       (mat_specular * finalSpecular), " + "       color[3] );" + "    }" + "  }" + "  gl_Position = projection * view * model * vec4( Vertex, 1.0 );" + "}";
-
-  var fragmentShaderSource3D = "void main(void){" + "  gl_FragColor = gl_Color;" + "}";
-
-  document.addEventListener('DOMContentLoaded', function() {
-    init();
-  },
-  false);
-
-  // Place-holder for debugging function
-  Processing.debug = function(e) {};
-
-  // Parse Processing (Java-like) syntax to JavaScript syntax with Regex
-  Processing.parse = function parse(aCode, p) {
-
-    // Force characters-as-bytes to work.
-    //aCode = aCode.replace(/('(.){1}')/g, "$1.charCodeAt(0)");
-    aCode = aCode.replace(/'.{1}'/g, function(all) {
-      return "(new Char(" + all + "))";
-    });
-
-    // Parse out @pjs directive, if any.
-    p.pjs = {
-      imageCache: {
-        pending: 0
-      }
-    }; // by default we have an empty imageCache, no more.
-    var dm = /\/\*\s*@pjs\s+((?:[^\*]|\*+[^\*\/])*)\*\//g.exec(aCode);
-    if (dm && dm.length === 2) {
-      var directives = dm.splice(1, 2)[0].replace('\n', '').replace('\r', '').split(';');
-
-      // We'll L/RTrim, and also remove any surrounding double quotes (e.g., just take string contents)
-      var clean = function(s) {
-        return s.replace(/^\s*\"?/, '').replace(/\"?\s*$/, '');
-      };
-
-      for (var i = 0, dl = directives.length; i < dl; i++) {
-        var pair = directives[i].split('=');
-        if (pair && pair.length === 2) {
-          var key = clean(pair[0]);
-          var value = clean(pair[1]);
-
-          // A few directives require work beyond storying key/value pairings
-          if (key === "preload") {
-            var list = value.split(',');
-            // All pre-loaded images will get put in imageCache, keyed on filename
-            for (var j = 0, ll = list.length; j < ll; j++) {
-              var imageName = clean(list[j]);
-              var img = new Image();
-              img.onload = (function() {
-                return function() {
-                  p.pjs.imageCache.pending--;
-                };
-              }());
-              p.pjs.imageCache.pending++;
-              p.pjs.imageCache[imageName] = img;
-              img.src = imageName;
-            }
-          } else if (key === "opaque") {
-            p.canvas.mozOpaque = value === "true";
-          } else {
-            p.pjs[key] = value;
-          }
-        }
-      }
-      aCode = aCode.replace(dm[0], '');
-    }
-
-    // Saves all strings into an array
-    // masks all strings into <STRING n>
-    // to be replaced with the array strings after parsing is finished
-    var strings = [];
-    aCode = aCode.replace(/(["'])(\\\1|.)*?(\1)/g, function(all) {
-      strings.push(all);
-      return "<STRING " + (strings.length - 1) + ">";
-    });
-
-    // Windows newlines cause problems: 
-    aCode = aCode.replace(/\r\n?/g, "\n");
-
-    // Remove end-of-line comments
-    aCode = aCode.replace(/\/\/.*\n/g, "\n");
-
-    // Weird parsing errors with %
-    aCode = aCode.replace(/([^\s])%([^\s])/g, "$1 % $2");
-
-    // Since frameRate() and frameRate are different things,
-    // we need to differentiate them somehow. So when we parse
-    // the Processing.js source, replace frameRate so it isn't
-    // confused with frameRate().
-    aCode = aCode.replace(/(\s*=\s*|\(*\s*)frameRate(\s*\)+?|\s*;)/, "$1p.FRAME_RATE$2");
-
-    // Simple convert a function-like thing to function
-    aCode = aCode.replace(/(?:static )?(\w+(?:\[\])* )(\w+)\s*(\([^\)]*\)\s*\{)/g, function(all, type, name, args) {
-      if (name === "if" || name === "for" || name === "while") {
-        return all;
-      } else {
-        return "processing." + name + " = function " + name + args;
-      }
-    });
-
-    // Attach import() to p{} bypassing JS command, allowing for extrernal library loading
-    //aCode = aCode.replace(/import \(|import\(/g, "p.Import(");
-    // Delete import statements, ie. import processing.video.*;
-    // https://processing-js.lighthouseapp.com/projects/41284/tickets/235-fix-parsing-of-java-import-statement
-    aCode = aCode.replace(/import\s+(.+);/g, "");
-
-    //replace  catch (IOException e) to catch (e)
-    aCode = aCode.replace(/catch\s*\(\W*\w*\s+(\w*)\W*\)/g, "catch ($1)");
-
-    //delete  the multiple catch block
-    var catchBlock = /(catch[^\}]*\})\W*catch[^\}]*\}/;
-
-    while (catchBlock.test(aCode)) {
-      aCode = aCode.replace(new RegExp(catchBlock), "$1");
-    }
-
-    Error.prototype.printStackTrace = function() {
-      this.toString();
-    };
-
-    // Force .length() to be .length
-    aCode = aCode.replace(/\.length\(\)/g, ".length");
-
-    // foo( int foo, float bar )
-    aCode = aCode.replace(/([\(,]\s*)(\w+)((?:\[\])+| )\s*(\w+\s*[\),])/g, "$1$4");
-    aCode = aCode.replace(/([\(,]\s*)(\w+)((?:\[\])+| )\s*(\w+\s*[\),])/g, "$1$4");
-
-    // float[] foo = new float[5];
-    aCode = aCode.replace(/new\s+(\w+)\s*((?:\[(?:[^\]]*)\])+)\s*(\{[^;]*\}\s*;)*/g, function(all, name, args, initVars) {
-      if (initVars) {
-        return initVars;
-      } else {
-        return "new ArrayList(" + args.replace(/\[\]/g, "[0]").slice(1, -1).split("][").join(", ") + ");";
-      }
-    });
-
-    // What does this do? This does the same thing as "Fix Array[] foo = {...} to [...]" below
-    aCode = aCode.replace(/(?:static )?\w+\[\]\s*(\w+)\[?\]?\s*=\s*\{.*?\};/g, function(all) {
-      return all.replace(/\{/g, "[").replace(/\}/g, "]");
-    });
-
-    // int|float foo;
-    var intFloat = /(\s*(?:int|float)\s+(?!\[\])*(?:\s*|[^\(;]*?,\s*))([a-zA-Z]\w*)\s*(,|;)/i;
-    while (intFloat.test(aCode)) {
-      aCode = (function() {
-        return aCode.replace(new RegExp(intFloat), function(all, type, name, sep) {
-          return type + " " + name + " = 0" + sep;
-        });
-      }());
-    }
-
-    // float foo = 5;
-    aCode = aCode.replace(/(?:static\s+)?(?:final\s+)?(\w+)((?:\[\s*\])+|\s)\s*(\w+)\[?\]?(\s*[=,;])/g, function(all, type, arr, name, sep) {
-      if (type === "return" || type === "else") {
-        return all;
-      } else {
-        return "var " + name + sep;
-      }
-    });
-
-    // Fix Array[] foo = {...} to [...]
-    aCode = aCode.replace(/\=\s*\{((.|\s)*?\};)/g, function(all, data) {
-      return "= [" + data.replace(/\{/g, "[").replace(/\}/g, "]");
-    });
-
-    // super() is a reserved word
-    aCode = aCode.replace(/super\(/g, "superMethod(");
-
-    // implements Int1, Int2 
-    aCode = aCode.replace(/implements\s+(\w+\s*(,\s*\w+\s*)*) \{/g, function(all, interfaces) {
-      var names = interfaces.replace(/\s+/g, "").split(",");
-      return "{ var __psj_interfaces = new ArrayList([\"" + names.join("\", \"") + "\"]);";
-    });
-
-    var classes = ["int", "float", "boolean", "String", "byte", "double", "long", "ArrayList"];
-
-    var classReplace = function(all, name, extend, vars, last) {
-      classes.push(name);
-
-      var staticVar = "";
-
-      vars = vars.replace(/final\s+var\s+(\w+\s*=\s*.*?;)/g, function(all, setting) {
-        staticVar += " " + name + "." + setting;
-        return "";
-      });
-
-
-      // Move arguments up from constructor and wrap contents with
-      // a with(this), and unwrap constructor
-      return "function " + name + "() {with(this){\n " + (extend ? "var __self=this;function superMethod(){extendClass(__self,arguments," + extend + ");}\n" : "") +
-      // Replace var foo = 0; with this.foo = 0;
-      // and force var foo; to become this.foo = null;
-      vars.replace(/\s*,\s*/g, ";\n  this.").replace(/\b(var |final |public )+\s*/g, "this.").replace(/\b(var |final |public )+\s*/g, "this.").replace(/this\.(\w+);/g, "this.$1 = null;") + (extend ? "extendClass(this, " + extend + ");\n" : "") + "<CLASS " + name + " " + staticVar + ">" + (typeof last === "string" ? last : name + "(");
-    };
-
-    var nextBrace = function(right) {
-      var rest = right,
-        position = 0,
-        leftCount = 1,
-        rightCount = 0;
-
-      while (leftCount !== rightCount) {
-        var nextLeft = rest.indexOf("{"),
-          nextRight = rest.indexOf("}");
-
-        if (nextLeft < nextRight && nextLeft !== -1) {
-          leftCount++;
-          rest = rest.slice(nextLeft + 1);
-          position += nextLeft + 1;
-        } else {
-          rightCount++;
-          rest = rest.slice(nextRight + 1);
-          position += nextRight + 1;
-        }
-      }
-
-      return right.slice(0, position - 1);
-    };
-
-    var matchClasses = /(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?\{\s*((?:.|\n)*?)\b\1\s*\(/g;
-    var matchNoCon = /(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?\{\s*((?:.|\n)*?)(processing)/g;
-
-    aCode = aCode.replace(matchClasses, classReplace);
-    aCode = aCode.replace(matchNoCon, classReplace);
-
-    var matchClass = /<CLASS (\w+) (.*?)>/,
-      m;
-
-    while ((m = aCode.match(matchClass))) {
-      var left = RegExp.leftContext,
-        allRest = RegExp.rightContext,
-        rest = nextBrace(allRest),
-        className = m[1],
-        staticVars = m[2] || "";
-
-      allRest = allRest.slice(rest.length + 1);
-
-      rest = (function() {
-        return rest.replace(new RegExp("\\b" + className + "\\(([^\\)]*?)\\)\\s*{", "g"), function(all, args) {
-          args = args.split(/,\s*?/);
-
-          if (args[0].match(/^\s*$/)) {
-            args.shift();
-          }
-
-          var fn = "if ( arguments.length === " + args.length + " ) {\n";
-
-          for (var i = 0; i < args.length; i++) {
-            fn += " var " + args[i] + " = arguments[" + i + "];\n";
-          }
-
-          return fn;
-        });
-      }());
-
-      // Fix class method names
-      // this.collide = function() { ... }
-      // and add closing } for with(this) ...
-      rest = (function() {
-        return rest.replace(/(?:public )?processing.\w+ = function (\w+)\((.*?)\)/g, function(all, name, args) {
-          return "ADDMETHOD(this, '" + name + "', function(" + args + ")";
-        });
-      }());
-
-      var matchMethod = /ADDMETHOD([\s\S]*?\{)/,
-        mc, methods = "";
-
-      while ((mc = rest.match(matchMethod))) {
-        var prev = RegExp.leftContext,
-          allNext = RegExp.rightContext,
-          next = nextBrace(allNext);
-
-        methods += "addMethod" + mc[1] + next + "});";
-
-        rest = prev + allNext.slice(next.length + 1);
-      }
-
-      rest = methods + rest;
-
-      aCode = left + rest + "\n}}" + staticVars + allRest;
-    }
-
-    // Do some tidying up, where necessary
-    aCode = aCode.replace(/processing.\w+ = function addMethod/g, "addMethod");
-
-
-    // Check if 3D context is invoked -- this is not the best way to do this.
-    if (aCode.match(/size\((?:.+),(?:.+),\s*(OPENGL|P3D)\s*\);/)) {
-      p.use3DContext = true;
-    }
-
-    // Handle (int) Casting
-    aCode = aCode.replace(/\(int\)/g, "0|");
-
-    // Remove Casting
-    aCode = aCode.replace(new RegExp("\\((" + classes.join("|") + ")(\\[\\])*\\)", "g"), "");
-
-    // Force numbers to exist //
-    //aCode = aCode.replace(/([^.])(\w+)\s*\+=/g, "$1$2 = ($2||0) +");
-    var toNumbers = function(str) {
-      var ret = [];
-
-      str.replace(/(..)/g, function(str) {
-        ret.push(parseInt(str, 16));
-      });
-
-      return ret;
-    };
-
-    // Convert #aaaaaa into color
-    aCode = aCode.replace(/#([a-f0-9]{6})/ig, function(m, hex) {
-      var num = toNumbers(hex);
-      return "defaultColor(" + num[0] + "," + num[1] + "," + num[2] + ")";
-    });
-
-    // Convert 3.0f to just 3.0
-    aCode = aCode.replace(/(\d+)f/g, "$1");
-
-    // replaces all masked strings from <STRING n> to the appropriate string contained in the strings array
-    for (var n = 0; n < strings.length; n++) {
-      aCode = (function() {
-        return aCode.replace(new RegExp("(.*)(<STRING " + n + ">)(.*)", "g"), function(all, quoteStart, match, quoteEnd) {
-          var returnString = all,
-            notString = true,
-            quoteType = "",
-            escape = false;
-
-          for (var x = 0; x < quoteStart.length; x++) {
-            if (notString) {
-              if (quoteStart.charAt(x) === "\"" || quoteStart.charAt(x) === "'") {
-                quoteType = quoteStart.charAt(x);
-                notString = false;
-              }
-            } else {
-              if (!escape) {
-                if (quoteStart.charAt(x) === "\\") {
-                  escape = true;
-                } else if (quoteStart.charAt(x) === quoteType) {
-                  notString = true;
-                  quoteType = "";
-                }
-              } else {
-                escape = false;
-              }
-            }
-          }
-
-          if (notString) { // Match is not inside a string
-            returnString = quoteStart + strings[n] + quoteEnd;
-          }
-
-          return returnString;
-        });
-      }());
-    }
-
-    return aCode;
-  };
-
-  function imageModeCorner(x, y, w, h, whAreSizes) {
-    return {
-      x: x,
-      y: y,
-      w: w,
-      h: h
-    };
-  }
-
-  function imageModeCorners(x, y, w, h, whAreSizes) {
-    return {
-      x: x,
-      y: y,
-      w: whAreSizes ? w : w - x,
-      h: whAreSizes ? h : h - y
-    };
-  }
-
-  function imageModeCenter(x, y, w, h, whAreSizes) {
-    return {
-      x: x - w / 2,
-      y: y - h / 2,
-      w: w,
-      h: h
-    };
-  }
-
-  // Attach Processing functions to 'p'
-  Processing.build = function buildProcessing(curElement) {
-    // Create the 'p' object
-    var p = {};
-    var curContext;
-    p.use3DContext = false; // default '2d' canvas context
-    p.canvas = curElement;
-
-    // Set Processing defaults / environment variables
-    p.name = 'Processing.js Instance';
-    p.PI = Math.PI;
-    p.TWO_PI = 2 * p.PI;
-    p.HALF_PI = p.PI / 2;
-    p.SINCOS_LENGTH = parseInt(360 / 0.5, 10);
-    p.MAX_FLOAT = 3.4028235e+38;
-    p.MIN_FLOAT = -3.4028235e+38;
-    p.MAX_INT = 2147483647;
-    p.MIN_INT = -2147483648;
-    p.CORNER = 0;
-    p.RADIUS = 1;
-    p.CENTER_RADIUS = 1;
-    p.CENTER = 2;
-    p.POLYGON = 2;
-    p.QUADS = 5;
-    p.TRIANGLES = 6;
-    p.POINTS = 7;
-    p.LINES = 8;
-    p.TRIANGLE_STRIP = 9;
-    p.TRIANGLE_FAN = 4;
-    p.QUAD_STRIP = 3;
-    p.CORNERS = 10;
-    p.CLOSE = true;
-    p.RGB = 1;
-    p.ARGB = 2;
-    p.HSB = 3;
-    p.ALPHA = 4;
-    p.CMYK = 5;
-    p.OPENGL = 'OPENGL';
-    p.P3D = 'P3D';
-    p.FRAME_RATE = 0;
-    p.focused = true;
-    p.ARROW = 'default';
-    p.CROSS = 'crosshair';
-    p.HAND = 'pointer';
-    p.MOVE = 'move';
-    p.TEXT = 'text';
-    p.WAIT = 'wait';
-    p.NOCURSOR = "url('data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='), auto";
-    p.ALPHA_MASK = 0xff000000;
-    p.RED_MASK = 0x00ff0000;
-    p.GREEN_MASK = 0x0000ff00;
-    p.BLUE_MASK = 0x000000ff;
-    p.REPLACE = 0;
-    p.BLEND = 1 << 0;
-    p.ADD = 1 << 1;
-    p.SUBTRACT = 1 << 2;
-    p.LIGHTEST = 1 << 3;
-    p.DARKEST = 1 << 4;
-    p.DIFFERENCE = 1 << 5;
-    p.EXCLUSION = 1 << 6;
-    p.MULTIPLY = 1 << 7;
-    p.SCREEN = 1 << 8;
-    p.OVERLAY = 1 << 9;
-    p.HARD_LIGHT = 1 << 10;
-    p.SOFT_LIGHT = 1 << 11;
-    p.DODGE = 1 << 12;
-    p.BURN = 1 << 13;
-    p.PRECISIONB = 15; // fixed point precision is limited to 15 bits!! 
-    p.PRECISIONF = 1 << p.PRECISIONB;
-    p.PREC_MAXVAL = p.PRECISIONF - 1;
-    p.PREC_ALPHA_SHIFT = 24 - p.PRECISIONB;
-    p.PREC_RED_SHIFT = 16 - p.PRECISIONB;
-    p.ROUND = 'round'; // Used by both cap and join.
-    p.SQUARE = 'butt'; // Used by cap.
-    p.PROJECT = 'square'; // Used by cap.
-    p.MITER = 'miter'; // Used by join.
-    p.BEVEL = 'bevel'; // Used by join.
-    p.CENTER = 88888880;
-    p.NORMAL_MODE_AUTO = 0;
-    p.NORMAL_MODE_SHAPE = 1;
-    p.NORMAL_MODE_VERTEX = 2;
-    p.MAX_LIGHTS = 8;
-
-    // Key Constants
-    // both key and keyCode will be equal to these values
-    p.BACKSPACE = 8;
-    p.TAB = 9;
-    p.ENTER = 10;
-    p.RETURN = 13;
-    p.ESC = 27;
-    p.DELETE = 127;
-
-    p.CODED = 0xffff;
-    // key will be CODED and keyCode will be this value
-    p.SHIFT = 16;
-    p.CONTROL = 17;
-    p.ALT = 18;
-    p.UP = 38;
-    p.RIGHT = 39;
-    p.DOWN = 40;
-    p.LEFT = 37;
-
-    var codedKeys = [p.SHIFT, p.CONTROL, p.ALT, p.UP, p.RIGHT, p.DOWN, p.LEFT];
-
-    // "Private" variables used to maintain state
-    var online = true,
-      doFill = true,
-      fillStyle = "rgba( 255, 255, 255, 1 )",
-      doStroke = true,
-      strokeStyle = "rgba( 204, 204, 204, 1 )",
-      lineWidth = 1,
-      loopStarted = false,
-      hasBackground = false,
-      doLoop = true,
-      looping = 0,
-      curRectMode = p.CORNER,
-      curEllipseMode = p.CENTER,
-      imageModeConvert = imageModeCorner,
-      normalX = 0,
-      normalY = 0,
-      normalZ = 0,
-      normalMode = p.NORMAL_MODE_AUTO,
-      inSetup = false,
-      inDraw = false,
-      curBackground = "rgba( 204, 204, 204, 1 )",
-      curFrameRate = 60,
-      curCursor = p.ARROW,
-      oldCursor = curElement.style.cursor,
-      curMsPerFrame = 1,
-      curShape = p.POLYGON,
-      curShapeCount = 0,
-      curvePoints = [],
-      curTightness = 0,
-      curveDetail = 20,
-      curveInited = false,
-      opacityRange = 255,
-      redRange = 255,
-      greenRange = 255,
-      blueRange = 255,
-      pathOpen = false,
-      mousePressed = false,
-      mouseDragging = false,
-      keyPressed = false,
-      curColorMode = p.RGB,
-      curTint = function() {},
-      curTextSize = 12,
-      curTextFont = "Arial",
-      getLoaded = false,
-      start = new Date().getTime(),
-      timeSinceLastFPS = start,
-      framesSinceLastFPS = 0,
-      lastTextPos = [0, 0, 0],
-      curveBasisMatrix, curveToBezierMatrix, curveDrawMatrix, bezierBasisInverse, bezierBasisMatrix;
-
-    // User can only have MAX_LIGHTS lights
-    var lightCount = 0;
-
-    //sphere stuff
-    var sphereDetailV = 0,
-      sphereDetailU = 0,
-      sphereX = [],
-      sphereY = [],
-      sphereZ = [],
-      sinLUT = new Array(p.SINCOS_LENGTH),
-      cosLUT = new Array(p.SINCOS_LENGTH),
-      sphereVerts, sphereNorms;
-
-    // Camera defaults and settings
-    var cam, cameraInv, forwardTransform, reverseTransform, modelView, modelViewInv, userMatrixStack, inverseCopy, projection, manipulatingCamera = false,
-      frustumMode = false,
-      cameraFOV = 60 * (Math.PI / 180),
-      cameraX = curElement.width / 2,
-      cameraY = curElement.height / 2,
-      cameraZ = cameraY / Math.tan(cameraFOV / 2),
-      cameraNear = cameraZ / 10,
-      cameraFar = cameraZ * 10,
-      cameraAspect = curElement.width / curElement.height;
-
-    var firstX, firstY, secondX, secondY, prevX, prevY;
-
-    // Stores states for pushStyle() and popStyle().
-    var styleArray = new Array(0);
-
-    // Glyph path storage for textFonts
-    p.glyphTable = {};
-
-    // Global vars for tracking mouse position
-    p.pmouseX = 0;
-    p.pmouseY = 0;
-    p.mouseX = 0;
-    p.mouseY = 0;
-    p.mouseButton = 0;
-    p.mouseDown = false;
-    p.mouseScroll = 0;
-
-    // Undefined event handlers to be replaced by user when needed
-    p.mouseClicked = undefined;
-    p.mouseDragged = undefined;
-    p.mouseMoved = undefined;
-    p.mousePressed = undefined;
-    p.mouseReleased = undefined;
-    p.mouseScrolled = undefined;
-    p.keyPressed = undefined;
-    p.keyReleased = undefined;
-    p.draw = undefined;
-    p.setup = undefined;
-
-    // The height/width of the canvas
-    p.width = curElement.width - 0;
-    p.height = curElement.height - 0;
-
-    // The current animation frame
-    p.frameCount = 0;
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Char handling
-    ////////////////////////////////////////////////////////////////////////////    
-    var charMap = {};
-
-    var Char = function Char(chr) {
-      if (typeof chr === 'string' && chr.length === 1) {
-        this.code = chr.charCodeAt(0);
-      } else {
-        this.code = NaN;
-      }
-
-      return (typeof charMap[this.code] === 'undefined') ? charMap[this.code] = this : charMap[this.code];
-    };
-
-    Char.prototype.toString = function() {
-      return String.fromCharCode(this.code);
-    };
-
-    Char.prototype.valueOf = function() {
-      return this.code;
-    };
-
-    ////////////////////////////////////////////////////////////////////////////
-    // PVector
-    ////////////////////////////////////////////////////////////////////////////
-    var PVector = function(x, y, z) {
-      this.x = x || 0;
-      this.y = y || 0;
-      this.z = z || 0;
-    },
-      createPVectorMethod = function(method) {
-      return function(v1, v2) {
-        var v = v1.get();
-        v[method](v2);
-        return v;
-      };
-    },
-      createSimplePVectorMethod = function(method) {
-      return function(v1, v2) {
-        return v1[method](v2);
-      };
-    },
-      simplePVMethods = "dist dot cross".split(" "),
-      method = simplePVMethods.length;
-
-    PVector.angleBetween = function(v1, v2) {
-      return Math.acos(v1.dot(v2) / (v1.mag() * v2.mag()));
-    };
-
-    // Common vector operations for PVector
-    PVector.prototype = {
-      set: function(v, y, z) {
-        if (arguments.length === 1) {
-          this.set(v.x || v[0], v.y || v[1], v.z || v[2]);
-        } else {
-          this.x = v;
-          this.y = y;
-          this.z = z;
-        }
-      },
-      get: function() {
-        return new PVector(this.x, this.y, this.z);
-      },
-      mag: function() {
-        return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
-      },
-      add: function(v, y, z) {
-        if (arguments.length === 3) {
-          this.x += v;
-          this.y += y;
-          this.z += z;
-        } else if (arguments.length === 1) {
-          this.x += v.x;
-          this.y += v.y;
-          this.z += v.z;
-        }
-      },
-      sub: function(v, y, z) {
-        if (arguments.length === 3) {
-          this.x -= v;
-          this.y -= y;
-          this.z -= z;
-        } else if (arguments.length === 1) {
-          this.x -= v.x;
-          this.y -= v.y;
-          this.z -= v.z;
-        }
-      },
-      mult: function(v) {
-        if (typeof v === 'number') {
-          this.x *= v;
-          this.y *= v;
-          this.z *= v;
-        } else if (typeof v === 'object') {
-          this.x *= v.x;
-          this.y *= v.y;
-          this.z *= v.z;
-        }
-      },
-      div: function(v) {
-        if (typeof v === 'number') {
-          this.x /= v;
-          this.y /= v;
-          this.z /= v;
-        } else if (typeof v === 'object') {
-          this.x /= v.x;
-          this.y /= v.y;
-          this.z /= v.z;
-        }
-      },
-      dist: function(v) {
-        var dx = this.x - v.x,
-          dy = this.y - v.y,
-          dz = this.z - v.z;
-        return Math.sqrt(dx * dx + dy * dy + dz * dz);
-      },
-      dot: function(v, y, z) {
-        var num;
-        if (arguments.length === 3) {
-          num = this.x * v + this.y * y + this.z * z;
-        } else if (arguments.length === 1) {
-          num = this.x * v.x + this.y * v.y + this.z * v.z;
-        }
-        return num;
-      },
-      cross: function(v) {
-        var
-        crossX = this.y * v.z - v.y * this.z,
-          crossY = this.z * v.x - v.z * this.x,
-          crossZ = this.x * v.y - v.x * this.y;
-        return new PVector(crossX, crossY, crossZ);
-      },
-      normalize: function() {
-        var m = this.mag();
-        if (m > 0) {
-          this.div(m);
-        }
-      },
-      limit: function(high) {
-        if (this.mag() > high) {
-          this.normalize();
-          this.mult(high);
-        }
-      },
-      heading2D: function() {
-        var angle = Math.atan2(-this.y, this.x);
-        return -angle;
-      },
-      toString: function() {
-        return "[" + this.x + ", " + this.y + ", " + this.z + "]";
-      },
-      array: function() {
-        return [this.x, this.y, this.z];
-      }
-    };
-
-    while (method--) {
-      PVector[simplePVMethods[method]] = createSimplePVectorMethod(simplePVMethods[method]);
-    }
-
-    for (method in PVector.prototype) {
-      if (PVector.prototype.hasOwnProperty(method) && !PVector.hasOwnProperty(method)) {
-        PVector[method] = createPVectorMethod(method);
-      }
-    }
-
-    p.PVector = PVector;
-
-    ////////////////////////////////////////////////////////////////////////////
-    // 2D Matrix
-    ////////////////////////////////////////////////////////////////////////////
-    /*
-      Helper function for printMatrix(). Finds the largest scalar
-      in the matrix, then number of digits left of the decimal.
-      Call from PMatrix2D and PMatrix3D's print() function.
-    */
-    var printMatrixHelper = function printMatrixHelper(elements) {
-      var big = 0;
-      for (var i = 0; i < elements.length; i++) {
-
-        if (i !== 0) {
-          big = Math.max(big, Math.abs(elements[i]));
-        } else {
-          big = Math.abs(elements[i]);
-        }
-      }
-
-      var digits = (big + "").indexOf(".");
-      if (digits === 0) {
-        digits = 1;
-      } else if (digits === -1) {
-        digits = (big + "").length;
-      }
-
-      return digits;
-    };
-
-    var PMatrix2D = function() {
-      if (arguments.length === 0) {
-        this.reset();
-      } else if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) {
-        this.set(arguments[0].array());
-      } else if (arguments.length === 6) {
-        this.set(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
-      }
-    };
-
-    PMatrix2D.prototype = {
-      set: function() {
-        if (arguments.length === 6) {
-          var a = arguments;
-          this.set([a[0], a[1], a[2],
-                                a[3], a[4], a[5]]);
-        } else if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) {
-          this.elements = arguments[0].array();
-        } else if (arguments.length === 1 && arguments[0] instanceof Array) {
-          this.elements = arguments[0].slice();
-        }
-      },
-      get: function() {
-        var outgoing = new PMatrix2D();
-        outgoing.set(this.elements);
-        return outgoing;
-      },
-      reset: function() {
-        this.set([1, 0, 0, 0, 1, 0]);
-      },
-      // Returns a copy of the element values.
-      array: function array() {
-        return this.elements.slice();
-      },
-      translate: function(tx, ty) {
-        this.elements[2] = tx * this.elements[0] + ty * this.elements[1] + this.elements[2];
-        this.elements[5] = tx * this.elements[3] + ty * this.elements[4] + this.elements[5];
-      },
-      // Does nothing in Processing.
-      transpose: function() {},
-      mult: function(source, target) {
-        var x, y;
-
-        if (source instanceof PVector) {
-          x = source.x;
-          y = source.y;
-          if (!target) {
-            target = new PVector();
-          }
-        } else if (source instanceof Array) {
-          x = source[0];
-          y = source[1];
-          if (!target) {
-            target = [];
-          }
-        }
-
-        if (target instanceof Array) {
-          target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2];
-          target[1] = this.elements[3] * x + this.elements[4] * y + this.elements[5];
-        } else if (target instanceof PVector) {
-          target.x = this.elements[0] * x + this.elements[1] * y + this.elements[2];
-          target.y = this.elements[3] * x + this.elements[4] * y + this.elements[5];
-          target.z = 0;
-        }
-        return target;
-      },
-      multX: function(x, y) {
-        return x * this.elements[0] + y * this.elements[1] + this.elements[2];
-      },
-      multY: function(x, y) {
-        return x * this.elements[3] + y * this.elements[4] + this.elements[5];
-      },
-      skewX: function(angle) {
-        this.apply(1, 0, 1, angle, 0, 0);
-      },
-      skewY: function(angle) {
-        this.apply(1, 0, 1, 0, angle, 0);
-      },
-      apply: function() {
-        if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) {
-          this.apply(arguments[0].array());
-        } else if (arguments.length === 6) {
-          var a = arguments;
-          this.apply([a[0], a[1], a[2],
-                                  a[3], a[4], a[5]]);
-        } else if (arguments.length === 1 && arguments[0] instanceof Array) {
-          var source = arguments[0];
-
-          var result = [0, 0, this.elements[2],
-                                    0, 0, this.elements[5]];
-          var e = 0;
-          for (var row = 0; row < 2; row++) {
-            for (var col = 0; col < 3; col++, e++) {
-              result[e] += this.elements[row * 3 + 0] * source[col + 0] + this.elements[row * 3 + 1] * source[col + 3];
-            }
-          }
-          this.elements = result.slice();
-        }
-      },
-      print: function() {
-        var digits = printMatrixHelper(this.elements);
-
-        var output = "";
-        output += p.nfs(this.elements[0], digits, 4) + " " + p.nfs(this.elements[1], digits, 4) + " " + p.nfs(this.elements[2], digits, 4) + "\n";
-        output += p.nfs(this.elements[3], digits, 4) + " " + p.nfs(this.elements[4], digits, 4) + " " + p.nfs(this.elements[5], digits, 4) + "\n\n";
-
-        p.println(output);
-      }
-    };
-
-    ////////////////////////////////////////////////////////////////////////////
-    // PMatrix3D
-    ////////////////////////////////////////////////////////////////////////////    
-    var PMatrix3D = function PMatrix3D() {
-      //When a matrix is created, it is set to an identity matrix
-      this.reset();
-    };
-
-    PMatrix3D.prototype = {
-      set: function() {
-        if (arguments.length === 16) {
-          var a = arguments;
-          this.set([a[0], a[1], a[2], a[3],
-                                a[4], a[5], a[6], a[7],
-                                a[8], a[9], a[10], a[11],
-                                a[12], a[13], a[14], a[15]]);
-        } else if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) {
-          this.elements = arguments[0].array();
-        } else if (arguments.length === 1 && arguments[0] instanceof Array) {
-          this.elements = arguments[0].slice();
-        }
-      },
-      get: function() {
-        var outgoing = new PMatrix3D();
-        outgoing.set(this.elements);
-        return outgoing;
-      },
-      reset: function() {
-        this.set([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
-      },
-      // Returns a copy of the element values.
-      array: function array() {
-        return this.elements.slice();
-      },
-      translate: function(tx, ty, tz) {
-        if (typeof tz === 'undefined') {
-          tx = 0;
-        }
-
-        this.elements[3] += tx * this.elements[0] + ty * this.elements[1] + tz * this.elements[2];
-        this.elements[7] += tx * this.elements[4] + ty * this.elements[5] + tz * this.elements[6];
-        this.elements[11] += tx * this.elements[8] + ty * this.elements[9] + tz * this.elements[10];
-        this.elements[15] += tx * this.elements[12] + ty * this.elements[13] + tz * this.elements[14];
-      },
-      transpose: function() {
-        var temp = this.elements.slice();
-        this.elements[0] = temp[0];
-        this.elements[1] = temp[4];
-        this.elements[2] = temp[8];
-        this.elements[3] = temp[12];
-        this.elements[4] = temp[1];
-        this.elements[5] = temp[5];
-        this.elements[6] = temp[9];
-        this.elements[7] = temp[13];
-        this.elements[8] = temp[2];
-        this.elements[9] = temp[6];
-        this.elements[10] = temp[10];
-        this.elements[11] = temp[14];
-        this.elements[12] = temp[3];
-        this.elements[13] = temp[7];
-        this.elements[14] = temp[11];
-        this.elements[15] = temp[15];
-      },
-      /*
-        You must either pass in two PVectors or two arrays,
-        don't mix between types. You may also omit a second
-        argument and simply read the result from the return.
-      */
-      mult: function(source, target) {
-        var x, y, z, w;
-        if (source instanceof PVector) {
-          x = source.x;
-          y = source.y;
-          z = source.z;
-          w = 1;
-          if (!target) {
-            target = new PVector();
-          }
-        } else if (source instanceof Array) {
-          x = source[0];
-          y = source[1];
-          z = source[2];
-          w = source[3] || 1;
-
-          if (!target || target.length !== 3 && target.length !== 4) {
-            target = [0, 0, 0];
-          }
-        }
-
-        if (target instanceof Array) {
-          if (target.length === 3) {
-            target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3];
-            target[1] = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7];
-            target[2] = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11];
-          } else if (target.length === 4) {
-            target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3] * w;
-            target[1] = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7] * w;
-            target[2] = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] * w;
-            target[3] = this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15] * w;
-          }
-        }
-        if (target instanceof PVector) {
-          target.x = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3];
-          target.y = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7];
-          target.z = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11];
-        }
-        return target;
-      },
-      preApply: function() {
-        if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) {
-          this.preApply(arguments[0].array());
-        } else if (arguments.length === 16) {
-          var a = arguments;
-          this.preApply([a[0], a[1], a[2], a[3],
-                                     a[4], a[5], a[6], a[7],
-                                     a[8], a[9], a[10], a[11],
-                                     a[12], a[13], a[14], a[15]]);
-        } else if (arguments.length === 1 && arguments[0] instanceof Array) {
-          var source = arguments[0];
-
-          var result = [0, 0, 0, 0,
-                                    0, 0, 0, 0,
-                                    0, 0, 0, 0,
-                                    0, 0, 0, 0];
-          var e = 0;
-          for (var row = 0; row < 4; row++) {
-            for (var col = 0; col < 4; col++, e++) {
-              result[e] += this.elements[col + 0] * source[row * 4 + 0] + this.elements[col + 4] * source[row * 4 + 1] + this.elements[col + 8] * source[row * 4 + 2] + this.elements[col + 12] * source[row * 4 + 3];
-            }
-          }
-          this.elements = result.slice();
-        }
-      },
-      apply: function() {
-        if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) {
-          this.apply(arguments[0].array());
-        } else if (arguments.length === 16) {
-          var a = arguments;
-          this.apply([a[0], a[1], a[2], a[3],
-                                  a[4], a[5], a[6], a[7],
-                                  a[8], a[9], a[10], a[11],
-                                  a[12], a[13], a[14], a[15]]);
-        } else if (arguments.length === 1 && arguments[0] instanceof Array) {
-          var source = arguments[0];
-
-          var result = [0, 0, 0, 0,
-                                    0, 0, 0, 0,
-                                    0, 0, 0, 0,
-                                    0, 0, 0, 0];
-          var e = 0;
-          for (var row = 0; row < 4; row++) {
-            for (var col = 0; col < 4; col++, e++) {
-              result[e] += this.elements[row * 4 + 0] * source[col + 0] + this.elements[row * 4 + 1] * source[col + 4] + this.elements[row * 4 + 2] * source[col + 8] + this.elements[row * 4 + 3] * source[col + 12];
-            }
-          }
-          this.elements = result.slice();
-        }
-      },
-      rotate: function(angle, v0, v1, v2) {
-        if (!v1) {
-          this.rotateZ(angle);
-        } else {
-          // TODO should make sure this vector is normalized
-          var c = p.cos(angle);
-          var s = p.sin(angle);
-          var t = 1.0 - c;
-
-          this.apply((t * v0 * v0) + c, (t * v0 * v1) - (s * v2), (t * v0 * v2) + (s * v1), 0, (t * v0 * v1) + (s * v2), (t * v1 * v1) + c, (t * v1 * v2) - (s * v0), 0, (t * v0 * v2) - (s * v1), (t * v1 * v2) + (s * v0), (t * v2 * v2) + c, 0, 0, 0, 0, 1);
-        }
-      },
-      invApply: function() {
-        if (typeof inverseCopy === "undefined") {
-          inverseCopy = new PMatrix3D();
-        }
-        var a = arguments;
-        inverseCopy.set(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);
-
-        if (!inverseCopy.invert()) {
-          return false;
-        }
-        this.preApply(inverseCopy);
-        return true;
-      },
-      rotateX: function(angle) {
-        var c = p.cos(angle);
-        var s = p.sin(angle);
-        this.apply([1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1]);
-      },
-
-      rotateY: function(angle) {
-        var c = p.cos(angle);
-        var s = p.sin(angle);
-        this.apply([c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1]);
-      },
-      rotateZ: function(angle) {
-        var c = Math.cos(angle);
-        var s = Math.sin(angle);
-        this.apply([c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
-      },
-      // Uniform scaling if only one value passed in
-      scale: function(sx, sy, sz) {
-        if (sx && !sy && !sz) {
-          sy = sz = sx;
-        } else if (sx && sy && !sz) {
-          sz = 1;
-        }
-
-        if (sx && sy && sz) {
-          this.elements[0] *= sx;
-          this.elements[1] *= sy;
-          this.elements[2] *= sz;
-          this.elements[4] *= sx;
-          this.elements[5] *= sy;
-          this.elements[6] *= sz;
-          this.elements[8] *= sx;
-          this.elements[9] *= sy;
-          this.elements[10] *= sz;
-          this.elements[12] *= sx;
-          this.elements[13] *= sy;
-          this.elements[14] *= sz;
-        }
-      },
-      skewX: function(angle) {
-        var t = p.tan(angle);
-        this.apply(1, t, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
-      },
-      skewY: function(angle) {
-        var t = Math.tan(angle);
-        this.apply(1, 0, 0, 0, t, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
-      },
-      multX: function(x, y, z, w) {
-        if (!z) {
-          return this.elements[0] * x + this.elements[1] * y + this.elements[3];
-        } else if (!w) {
-          return this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3];
-        } else {
-          return this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3] * w;
-        }
-      },
-      multY: function(x, y, z, w) {
-        if (!z) {
-          return this.elements[4] * x + this.elements[5] * y + this.elements[7];
-        } else if (!w) {
-          return this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7];
-        } else {
-          return this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7] * w;
-        }
-      },
-      multZ: function(x, y, z, w) {
-        if (!w) {
-          return this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11];
-        } else {
-          return this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] * w;
-        }
-      },
-      multW: function(x, y, z, w) {
-        if (!w) {
-          return this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15];
-        } else {
-          return this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15] * w;
-        }
-      },
-      invert: function() {
-        var kInv = [];
-        var fA0 = this.elements[0] * this.elements[5] - this.elements[1] * this.elements[4];
-        var fA1 = this.elements[0] * this.elements[6] - this.elements[2] * this.elements[4];
-        var fA2 = this.elements[0] * this.elements[7] - this.elements[3] * this.elements[4];
-        var fA3 = this.elements[1] * this.elements[6] - this.elements[2] * this.elements[5];
-        var fA4 = this.elements[1] * this.elements[7] - this.elements[3] * this.elements[5];
-        var fA5 = this.elements[2] * this.elements[7] - this.elements[3] * this.elements[6];
-        var fB0 = this.elements[8] * this.elements[13] - this.elements[9] * this.elements[12];
-        var fB1 = this.elements[8] * this.elements[14] - this.elements[10] * this.elements[12];
-        var fB2 = this.elements[8] * this.elements[15] - this.elements[11] * this.elements[12];
-        var fB3 = this.elements[9] * this.elements[14] - this.elements[10] * this.elements[13];
-        var fB4 = this.elements[9] * this.elements[15] - this.elements[11] * this.elements[13];
-        var fB5 = this.elements[10] * this.elements[15] - this.elements[11] * this.elements[14];
-
-        // Determinant
-        var fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0;
-
-        // Account for a very small value
-        // return false if not successful.
-        if (Math.abs(fDet) <= 1e-9) {
-          return false;
-        }
-
-        kInv[0] = +this.elements[5] * fB5 - this.elements[6] * fB4 + this.elements[7] * fB3;
-        kInv[4] = -this.elements[4] * fB5 + this.elements[6] * fB2 - this.elements[7] * fB1;
-        kInv[8] = +this.elements[4] * fB4 - this.elements[5] * fB2 + this.elements[7] * fB0;
-        kInv[12] = -this.elements[4] * fB3 + this.elements[5] * fB1 - this.elements[6] * fB0;
-        kInv[1] = -this.elements[1] * fB5 + this.elements[2] * fB4 - this.elements[3] * fB3;
-        kInv[5] = +this.elements[0] * fB5 - this.elements[2] * fB2 + this.elements[3] * fB1;
-        kInv[9] = -this.elements[0] * fB4 + this.elements[1] * fB2 - this.elements[3] * fB0;
-        kInv[13] = +this.elements[0] * fB3 - this.elements[1] * fB1 + this.elements[2] * fB0;
-        kInv[2] = +this.elements[13] * fA5 - this.elements[14] * fA4 + this.elements[15] * fA3;
-        kInv[6] = -this.elements[12] * fA5 + this.elements[14] * fA2 - this.elements[15] * fA1;
-        kInv[10] = +this.elements[12] * fA4 - this.elements[13] * fA2 + this.elements[15] * fA0;
-        kInv[14] = -this.elements[12] * fA3 + this.elements[13] * fA1 - this.elements[14] * fA0;
-        kInv[3] = -this.elements[9] * fA5 + this.elements[10] * fA4 - this.elements[11] * fA3;
-        kInv[7] = +this.elements[8] * fA5 - this.elements[10] * fA2 + this.elements[11] * fA1;
-        kInv[11] = -this.elements[8] * fA4 + this.elements[9] * fA2 - this.elements[11] * fA0;
-        kInv[15] = +this.elements[8] * fA3 - this.elements[9] * fA1 + this.elements[10] * fA0;
-
-        // Inverse using Determinant
-        var fInvDet = 1.0 / fDet;
-        kInv[0] *= fInvDet;
-        kInv[1] *= fInvDet;
-        kInv[2] *= fInvDet;
-        kInv[3] *= fInvDet;
-        kInv[4] *= fInvDet;
-        kInv[5] *= fInvDet;
-        kInv[6] *= fInvDet;
-        kInv[7] *= fInvDet;
-        kInv[8] *= fInvDet;
-        kInv[9] *= fInvDet;
-        kInv[10] *= fInvDet;
-        kInv[11] *= fInvDet;
-        kInv[12] *= fInvDet;
-        kInv[13] *= fInvDet;
-        kInv[14] *= fInvDet;
-        kInv[15] *= fInvDet;
-
-        this.elements = kInv.slice();
-        return true;
-      },
-      toString: function() {
-        var str = "";
-        for (var i = 0; i < 15; i++) {
-          str += this.elements[i] + ", ";
-        }
-        str += this.elements[15];
-        return str;
-      },
-      print: function() {
-        var digits = printMatrixHelper(this.elements);
-
-        var output = "";
-        output += p.nfs(this.elements[0], digits, 4) + " " + p.nfs(this.elements[1], digits, 4) + " " + p.nfs(this.elements[2], digits, 4) + " " + p.nfs(this.elements[3], digits, 4) + "\n";
-        output += p.nfs(this.elements[4], digits, 4) + " " + p.nfs(this.elements[5], digits, 4) + " " + p.nfs(this.elements[6], digits, 4) + " " + p.nfs(this.elements[7], digits, 4) + "\n";
-        output += p.nfs(this.elements[8], digits, 4) + " " + p.nfs(this.elements[9], digits, 4) + " " + p.nfs(this.elements[10], digits, 4) + " " + p.nfs(this.elements[11], digits, 4) + "\n";
-        output += p.nfs(this.elements[12], digits, 4) + " " + p.nfs(this.elements[13], digits, 4) + " " + p.nfs(this.elements[14], digits, 4) + " " + p.nfs(this.elements[15], digits, 4) + "\n\n";
-
-        p.println(output);
-      },
-      invTranslate: function(tx, ty, tz) {
-        this.preApply(1, 0, 0, -tx, 0, 1, 0, -ty, 0, 0, 1, -tz, 0, 0, 0, 1);
-      },
-      invRotateX: function(angle) {
-        var c = p.cos(-angle);
-        var s = p.sin(-angle);
-        this.preApply([1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1]);
-      },
-      invRotateY: function(angle) {
-        var c = p.cos(-angle);
-        var s = p.sin(-angle);
-        this.preApply([c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1]);
-      },
-      invRotateZ: function(angle) {
-        var c = p.cos(-angle);
-        var s = p.sin(-angle);
-        this.preApply([c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
-      },
-      invScale: function(x, y, z) {
-        this.preApply([1 / x, 0, 0, 0, 0, 1 / y, 0, 0, 0, 0, 1 / z, 0, 0, 0, 0, 1]);
-      }
-    };
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Matrix Stack
-    ////////////////////////////////////////////////////////////////////////////
-    var PMatrixStack = function PMatrixStack() {
-      this.matrixStack = [];
-    };
-
-    PMatrixStack.prototype.load = function load() {
-      var tmpMatrix;
-      if (p.use3DContext) {
-        tmpMatrix = new PMatrix3D();
-      } else {
-        tmpMatrix = new PMatrix2D();
-      }
-
-      if (arguments.length === 1) {
-        tmpMatrix.set(arguments[0]);
-      } else {
-        tmpMatrix.set(arguments);
-      }
-      this.matrixStack.push(tmpMatrix);
-    };
-
-    PMatrixStack.prototype.push = function push() {
-      this.matrixStack.push(this.peek());
-    };
-
-    PMatrixStack.prototype.pop = function pop() {
-      return this.matrixStack.pop();
-    };
-
-    PMatrixStack.prototype.peek = function peek() {
-      var tmpMatrix;
-      if (p.use3DContext) {
-        tmpMatrix = new PMatrix3D();
-      } else {
-        tmpMatrix = new PMatrix2D();
-      }
-
-      tmpMatrix.set(this.matrixStack[this.matrixStack.length - 1]);
-      return tmpMatrix;
-    };
-
-    PMatrixStack.prototype.mult = function mult(matrix) {
-      this.matrixStack[this.matrixStack.length - 1].apply(matrix);
-    };
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Array handling
-    ////////////////////////////////////////////////////////////////////////////    
-    p.split = function(str, delim) {
-      return str.split(delim);
-    };
-
-    p.splitTokens = function(str, tokens) {
-      if (arguments.length === 1) {
-        tokens = "\n\t\r\f ";
-      }
-
-      tokens = "[" + tokens + "]";
-
-      var ary = new Array(0);
-      var index = 0;
-      var pos = str.search(tokens);
-
-      while (pos >= 0) {
-        if (pos === 0) {
-          str = str.substring(1);
-        } else {
-          ary[index] = str.substring(0, pos);
-          index++;
-          str = str.substring(pos);
-        }
-        pos = str.search(tokens);
-      }
-
-      if (str.length > 0) {
-        ary[index] = str;
-      }
-
-      if (ary.length === 0) {
-        ary = undefined;
-      }
-
-      return ary;
-    };
-
-    p.append = function(array, element) {
-      array[array.length] = element;
-      return array;
-    };
-
-    p.concat = function(array1, array2) {
-      return array1.concat(array2);
-    };
-
-    p.sort = function(array, numElem) {
-      var ret = [];
-
-      // depending on the type used (int, float) or string
-      // we'll need to use a different compare function
-      if (array.length > 0) {
-        // copy since we need to return another array
-        var elemsToCopy = numElem > 0 ? numElem : array.length;
-        for (var i = 0; i < elemsToCopy; i++) {
-          ret.push(array[i]);
-        }
-        if (typeof array[0] === "string") {
-          ret.sort();
-        }
-        // int or float
-        else {
-          ret.sort(function(a, b) {
-            return a - b;
-          });
-        }
-
-        // copy on the rest of the elements that were not sorted in case the user
-        // only wanted a subset of an array to be sorted.
-        if (numElem > 0) {
-          for (var j = ret.length; j < array.length; j++) {
-            ret.push(array[j]);
-          }
-        }
-      }
-      return ret;
-    };
-
-    p.splice = function(array, value, index) {
-      if (array.length === 0 && value.length === 0) {
-        return array;
-      }
-
-      if (value instanceof Array) {
-        for (var i = 0, j = index; i < value.length; j++, i++) {
-          array.splice(j, 0, value[i]);
-        }
-      } else {
-        array.splice(index, 0, value);
-      }
-
-      return array;
-    };
-
-    p.subset = function(array, offset, length) {
-      if (arguments.length === 2) {
-        return p.subset(array, offset, array.length - offset);
-      } else if (arguments.length === 3) {
-        return array.slice(offset, offset + length);
-      }
-    };
-
-    p.join = function(array, seperator) {
-      return array.join(seperator);
-    };
-
-    p.shorten = function(ary) {
-      var newary = new Array(0);
-
-      // copy array into new array
-      var len = ary.length;
-      for (var i = 0; i < len; i++) {
-        newary[i] = ary[i];
-      }
-      newary.pop();
-
-      return newary;
-    };
-
-    p.expand = function(ary, newSize) {
-      var newary = new Array(0);
-
-      var len = ary.length;
-      for (var i = 0; i < len; i++) {
-        newary[i] = ary[i];
-      }
-
-      if (arguments.length === 1) {
-        // double size of array
-        newary.length *= 2;
-      } else if (arguments.length === 2) {
-        // size is newSize
-        newary.length = newSize;
-      }
-
-      return newary;
-    };
-
-    p.arrayCopy = function(src, srcPos, dest, destPos, length) {
-      if (arguments.length === 2) {
-        // recall itself and copy src to dest from start index 0 to 0 of src.length
-        p.arrayCopy(src, 0, srcPos, 0, src.length);
-      } else if (arguments.length === 3) {
-        // recall itself and copy src to dest from start index 0 to 0 of length
-        p.arrayCopy(src, 0, srcPos, 0, dest);
-      } else if (arguments.length === 5) {
-        // copy src to dest from index srcPos to index destPos of length recursivly on objects
-        for (var i = srcPos, j = destPos; i < length + srcPos; i++, j++) {
-          if (src[i] && typeof src[i] === "object") {
-            // src[i] is not null and is another object or array. go recursive
-            p.arrayCopy(src[i], 0, dest[j], 0, src[i].length);
-          } else {
-            // standard type, just copy
-            dest[j] = src[i];
-          }
-        }
-      }
-    };
-
-    p.ArrayList = function(size, size2, size3) {
-      var array = new Array(0 | size);
-
-      if (size2) {
-        for (var i = 0; i < size; i++) {
-          array[i] = [];
-
-          for (var j = 0; j < size2; j++) {
-            var a = array[i][j] = size3 ? new Array(size3) : 0;
-            for (var k = 0; k < size3; k++) {
-              a[k] = 0;
-            }
-          }
-        }
-      } else {
-        for (var l = 0; l < size; l++) {
-          array[l] = 0;
-        }
-      }
-
-      array.get = function(i) {
-        return this[i];
-      };
-      array.contains = function(item) {
-        return this.indexOf(item) !== -1;
-      };
-      array.add = function(item) {
-        return this.push(item);
-      };
-      array.size = function() {
-        return this.length;
-      };
-      array.clear = function() {
-        this.length = 0;
-      };
-      array.remove = function(i) {
-        return this.splice(i, 1)[0];
-      };
-      array.isEmpty = function() {
-        return !this.length;
-      };
-      array.clone = function() {
-        var a = new p.ArrayList(size);
-        for (var i = 0; i < size; i++) {
-          a[i] = this[i];
-        }
-        return a;
-      };
-
-      return array;
-    };
-
-    p.reverse = function(array) {
-      return array.reverse();
-    };
-
-
-    ////////////////////////////////////////////////////////////////////////////
-    // HashMap
-    ////////////////////////////////////////////////////////////////////////////
-    var virtHashCode = function virtHashCode(obj) {
-      if (obj.constructor === String) {
-        var hash = 0;
-        for (var i = 0; i < obj.length; ++i) {
-          hash = (hash * 31 + obj.charCodeAt(i)) & 0xFFFFFFFF;
-        }
-        return hash;
-      } else if (typeof(obj) !== "object") {
-        return obj & 0xFFFFFFFF;
-      } else if ("hashCode" in obj) {
-        return obj.hashCode.call(obj);
-      } else {
-        if (obj.$id === undefined) {
-          obj.$id = ((Math.floor(Math.random() * 0x10000) - 0x8000) << 16) | Math.floor(Math.random() * 0x10000);
-        }
-        return obj.$id;
-      }
-    };
-
-    var virtEquals = function virtEquals(obj, other) {
-      if (obj === null || other === null) {
-        return (obj === null) && (other === null);
-      } else if (obj.constructor === String) {
-        return obj === other;
-      } else if (typeof(obj) !== "object") {
-        return obj === other;
-      } else if ("equals" in obj) {
-        return obj.equals.call(obj, other);
-      } else {
-        return obj === other;
-      }
-    };
-
-    p.HashMap = function HashMap() {
-      if (arguments.length === 1 && arguments[0].constructor === HashMap) {
-        return arguments[0].clone();
-      }
-
-      var initialCapacity = arguments.length > 0 ? arguments[0] : 16;
-      var loadFactor = arguments.length > 1 ? arguments[1] : 0.75;
-
-      var buckets = new Array(initialCapacity);
-      var count = 0;
-      var hashMap = this;
-
-      function ensureLoad() {
-        if (count <= loadFactor * buckets.length) {
-          return;
-        }
-        var allEntries = [];
-        for (var i = 0; i < buckets.length; ++i) {
-          if (buckets[i] !== undefined) {
-            allEntries = allEntries.concat(buckets[i]);
-          }
-        }
-        buckets = new Array(buckets.length * 2);
-        for (var j = 0; j < allEntries.length; ++j) {
-          var index = virtHashCode(allEntries[j].key) % buckets.length;
-          var bucket = buckets[index];
-          if (bucket === undefined) {
-            buckets[index] = bucket = [];
-          }
-          bucket.push(allEntries[j]);
-        }
-      }
-
-      function Iterator(conversion, removeItem) {
-        var bucketIndex = 0;
-        var itemIndex = -1;
-        var endOfBuckets = false;
-
-        function findNext() {
-          while (!endOfBuckets) {
-            ++itemIndex;
-            if (bucketIndex >= buckets.length) {
-              endOfBuckets = true;
-            } else if (typeof(buckets[bucketIndex]) === 'undefined' || itemIndex >= buckets[bucketIndex].length) {
-              itemIndex = -1;
-              ++bucketIndex;
-            } else {
-              return;
-            }
-          }
-        }
-
-        this.hasNext = function() {
-          return !endOfBuckets;
-        };
-        this.next = function() {
-          var result = conversion(buckets[bucketIndex][itemIndex]);
-          findNext();
-          return result;
-        };
-        this.remove = function() {
-          removeItem(this.next());
-          --itemIndex;
-        };
-
-        findNext();
-      }
-
-      function Set(conversion, isIn, removeItem) {
-        this.clear = function() {
-          hashMap.clear();
-        };
-        this.contains = function(o) {
-          return isIn(o);
-        };
-        this.containsAll = function(o) {
-          var it = o.iterator();
-          while (it.hasNext()) {
-            if (!this.contains(it.next())) {
-              return false;
-            }
-          }