aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/infrastructure/ace/www/processing.js
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/infrastructure/ace/www/processing.js')
-rw-r--r--trunk/infrastructure/ace/www/processing.js1714
1 files changed, 1714 insertions, 0 deletions
diff --git a/trunk/infrastructure/ace/www/processing.js b/trunk/infrastructure/ace/www/processing.js
new file mode 100644
index 0000000..988ef76
--- /dev/null
+++ b/trunk/infrastructure/ace/www/processing.js
@@ -0,0 +1,1714 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * 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.
+ */
+
+/*
+ * Processing.js - John Resig (http://ejohn.org/)
+ * MIT Licensed
+ * http://ejohn.org/blog/processingjs/
+ *
+ * This is a port of the Processing Visualization Language.
+ * More information: http://processing.org/
+ */
+
+(function(){
+
+this.Processing = function Processing( aElement, aCode )
+{
+ var p = buildProcessing( aElement );
+ p.init( aCode );
+ return p;
+};
+
+function log()
+{
+ try
+ {
+ console.log.apply( console, arguments );
+ }
+ catch(e)
+ {
+ try
+ {
+ opera.postError.apply( opera, arguments );
+ }
+ catch(e){}
+ }
+}
+
+function parse( aCode, p )
+{
+ // Angels weep at this parsing code :-(
+
+ // Remove end-of-line comments
+ aCode = aCode.replace(/\/\/ .*\n/g, "\n");
+
+ // Weird parsing errors with %
+ aCode = aCode.replace(/([^\s])%([^\s])/g, "$1 % $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;
+ }
+ });
+
+ // 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 (\w+)((?:\[([^\]]*)\])+)/g, function(all, name, args)
+ {
+ return "new ArrayList(" + args.slice(1,-1).split("][").join(", ") + ")";
+ });
+
+ aCode = aCode.replace(/(?:static )?\w+\[\]\s*(\w+)\[?\]?\s*=\s*{.*?};/g, function(all)
+ {
+ return all.replace(/{/g, "[").replace(/}/g, "]");
+ });
+
+ // int|float foo;
+ var intFloat = /(\n\s*(?:int|float)(?:\[\])?(?:\s*|[^\(]*?,\s*))([a-z]\w*)(;|,)/i;
+ while ( intFloat.test(aCode) )
+ {
+ aCode = aCode.replace(new RegExp(intFloat), function(all, type, name, sep)
+ {
+ return type + " " + name + " = 0" + sep;
+ });
+ }
+
+ // float foo = 5;
+ aCode = aCode.replace(/(?:static )?(\w+)((?:\[\])+| ) *(\w+)\[?\]?(\s*[=,;])/g, function(all, type, arr, name, sep)
+ {
+ if ( type == "return" )
+ 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, "]") + "]";
+ });
+
+ // static { ... } blocks
+ aCode = aCode.replace(/static\s*{((.|\n)*?)}/g, function(all, init)
+ {
+ // Convert the static definitons to variable assignments
+ //return init.replace(/\((.*?)\)/g, " = $1");
+ return init;
+ });
+
+ // super() is a reserved word
+ aCode = aCode.replace(/super\(/g, "superMethod(");
+
+ var classes = ["int", "float", "boolean", "string"];
+
+ function ClassReplace(all, name, extend, vars, last)
+ {
+ classes.push( name );
+
+ var static = "";
+
+ vars = vars.replace(/final\s+var\s+(\w+\s*=\s*.*?;)/g, function(all,set)
+ {
+ static += " " + name + "." + set;
+ 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?/g, ";\n this.")
+ .replace(/\b(var |final |public )+\s*/g, "this.")
+ .replace(/this.(\w+);/g, "this.$1 = null;") +
+ (extend ? "extendClass(this, " + extend + ");\n" : "") +
+ "<CLASS " + name + " " + static + ">" + (typeof last == "string" ? last : name + "(");
+ }
+
+ 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 = 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 = rest.replace(/(?:public )?Processing.\w+ = function (\w+)\((.*?)\)/g, function(all, name, args)
+ {
+ return "ADDMETHOD(this, '" + name + "', function(" + args + ")";
+ });
+
+ var matchMethod = /ADDMETHOD([\s\S]*?{)/, mc;
+ var 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");
+
+ function nextBrace( right )
+ {
+ var rest = right;
+ var position = 0;
+ var leftCount = 1, rightCount = 0;
+
+ while ( leftCount != rightCount )
+ {
+ var nextLeft = rest.indexOf("{");
+ var 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);
+ }
+
+ // Handle (int) Casting
+ aCode = aCode.replace(/\(int\)/g, "0|");
+
+ // Remove Casting
+ aCode = aCode.replace(new RegExp("\\((" + classes.join("|") + ")(\\[\\])?\\)", "g"), "");
+
+ // Convert 3.0f to just 3.0
+ aCode = aCode.replace(/(\d+)f/g, "$1");
+
+ // Force numbers to exist
+ //aCode = aCode.replace(/([^.])(\w+)\s*\+=/g, "$1$2 = ($2||0) +");
+
+ // Force characters-as-bytes to work
+ aCode = aCode.replace(/('[a-zA-Z0-9]')/g, "$1.charCodeAt(0)");
+
+ // Convert #aaaaaa into color
+ aCode = aCode.replace(/#([a-f0-9]{6})/ig, function(m, hex){
+ var num = toNumbers(hex);
+ return "color(" + num[0] + "," + num[1] + "," + num[2] + ")";
+ });
+
+ function toNumbers( str ){
+ var ret = [];
+ str.replace(/(..)/g, function(str){
+ ret.push( parseInt( str, 16 ) );
+ });
+ return ret;
+ }
+
+//log(aCode);
+
+ return aCode;
+}
+
+function buildProcessing( curElement ){
+
+ var p = {};
+
+ // init
+ p.PI = Math.PI;
+ p.TWO_PI = 2 * p.PI;
+ p.HALF_PI = p.PI / 2;
+ p.P3D = 3;
+ p.CORNER = 0;
+ p.CENTER = 1;
+ p.CENTER_RADIUS = 2;
+ p.RADIUS = 2;
+ p.POLYGON = 1;
+ p.TRIANGLES = 6;
+ p.POINTS = 7;
+ p.LINES = 8;
+ p.TRIANGLE_STRIP = 9;
+ p.CORNERS = 10;
+ p.CLOSE = true;
+ p.RGB = 1;
+ p.HSB = 2;
+
+ // "Private" variables used to maintain state
+ var curContext = curElement.getContext("2d");
+ var doFill = true;
+ var doStroke = true;
+ var loopStarted = false;
+ var hasBackground = false;
+ var doLoop = true;
+ var curRectMode = p.CORNER;
+ var curEllipseMode = p.CENTER;
+ var inSetup = false;
+ var inDraw = false;
+ var curBackground = "rgba(204,204,204,1)";
+ var curFrameRate = 1000;
+ var curShape = p.POLYGON;
+ var curShapeCount = 0;
+ var opacityRange = 255;
+ var redRange = 255;
+ var greenRange = 255;
+ var blueRange = 255;
+ var pathOpen = false;
+ var mousePressed = false;
+ var keyPressed = false;
+ var firstX, firstY, prevX, prevY;
+ var curColorMode = p.RGB;
+ var curTint = -1;
+ var curTextSize = 12;
+ var curTextFont = "Arial";
+ var getLoaded = false;
+ var start = (new Date).getTime();
+
+ // Global vars for tracking mouse position
+ p.pmouseX = 0;
+ p.pmouseY = 0;
+ p.mouseX = 0;
+ p.mouseY = 0;
+
+ // Will be replaced by the user, most likely
+ p.mouseDragged = undefined;
+ p.mouseMoved = undefined;
+ p.mousePressed = undefined;
+ p.mouseReleased = 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;
+
+ // In case I ever need to do HSV conversion:
+ // http://srufaculty.sru.edu/david.dailey/javascript/js/5rml.js
+ p.color = function color( aValue1, aValue2, aValue3, aValue4 )
+ {
+ var aColor = "";
+
+ if ( arguments.length == 3 )
+ {
+ aColor = p.color( aValue1, aValue2, aValue3, opacityRange );
+ }
+ else if ( arguments.length == 4 )
+ {
+ var a = aValue4 / opacityRange;
+ a = isNaN(a) ? 1 : a;
+
+ if ( curColorMode == p.HSB )
+ {
+ var rgb = HSBtoRGB(aValue1, aValue2, aValue3);
+ var r = rgb[0], g = rgb[1], b = rgb[2];
+ }
+ else
+ {
+ var r = getColor(aValue1, redRange);
+ var g = getColor(aValue2, greenRange);
+ var b = getColor(aValue3, blueRange);
+ }
+
+ aColor = "rgba(" + r + "," + g + "," + b + "," + a + ")";
+ }
+ else if ( typeof aValue1 == "string" )
+ {
+ aColor = aValue1;
+
+ if ( arguments.length == 2 )
+ {
+ var c = aColor.split(",");
+ c[3] = (aValue2 / opacityRange) + ")";
+ aColor = c.join(",");
+ }
+ }
+ else if ( arguments.length == 2 )
+ {
+ aColor = p.color( aValue1, aValue1, aValue1, aValue2 );
+ }
+ else if ( typeof aValue1 == "number" )
+ {
+ aColor = p.color( aValue1, aValue1, aValue1, opacityRange );
+ }
+ else
+ {
+ aColor = p.color( redRange, greenRange, blueRange, opacityRange );
+ }
+
+ // HSB conversion function from Mootools, MIT Licensed
+ function HSBtoRGB(h, s, b)
+ {
+ h = (h / redRange) * 100;
+ s = (s / greenRange) * 100;
+ b = (b / blueRange) * 100;
+ if (s == 0){
+ return [b, b, b];
+ } else {
+ var hue = h % 360;
+ var f = hue % 60;
+ var br = Math.round(b / 100 * 255);
+ var p = Math.round((b * (100 - s)) / 10000 * 255);
+ var q = Math.round((b * (6000 - s * f)) / 600000 * 255);
+ var t = Math.round((b * (6000 - s * (60 - f))) / 600000 * 255);
+ switch (Math.floor(hue / 60)){
+ case 0: return [br, t, p];
+ case 1: return [q, br, p];
+ case 2: return [p, br, t];
+ case 3: return [p, q, br];
+ case 4: return [t, p, br];
+ case 5: return [br, p, q];
+ }
+ }
+ }
+
+ function getColor( aValue, range )
+ {
+ return Math.round(255 * (aValue / range));
+ }
+
+ return aColor;
+ }
+
+ p.nf = function( num, pad )
+ {
+ var str = "" + num;
+ while ( pad - str.length )
+ str = "0" + str;
+ return str;
+ };
+
+ p.AniSprite = function( prefix, frames )
+ {
+ this.images = [];
+ this.pos = 0;
+
+ for ( var i = 0; i < frames; i++ )
+ {
+ this.images.push( prefix + p.nf( i, ("" + frames).length ) + ".gif" );
+ }
+
+ this.display = function( x, y )
+ {
+ p.image( this.images[ this.pos ], x, y );
+
+ if ( ++this.pos >= frames )
+ this.pos = 0;
+ };
+
+ this.getWidth = function()
+ {
+ return getImage(this.images[0]).width;
+ };
+
+ this.getHeight = function()
+ {
+ return getImage(this.images[0]).height;
+ };
+ };
+
+ function buildImageObject( obj )
+ {
+ var pixels = obj.data;
+ var data = p.createImage( obj.width, obj.height );
+
+ if ( data.__defineGetter__ && data.__lookupGetter__ && !data.__lookupGetter__("pixels") )
+ {
+ var pixelsDone;
+ data.__defineGetter__("pixels", function()
+ {
+ if ( pixelsDone )
+ return pixelsDone;
+
+ pixelsDone = [];
+
+ for ( var i = 0; i < pixels.length; i += 4 )
+ {
+ pixelsDone.push( p.color(pixels[i], pixels[i+1], pixels[i+2], pixels[i+3]) );
+ }
+
+ return pixelsDone;
+ });
+ }
+ else
+ {
+ data.pixels = [];
+
+ for ( var i = 0; i < pixels.length; i += 4 )
+ {
+ data.pixels.push( p.color(pixels[i], pixels[i+1], pixels[i+2], pixels[i+3]) );
+ }
+ }
+
+ return data;
+ }
+
+ p.createImage = function createImage( w, h, mode )
+ {
+ var data = {
+ width: w,
+ height: h,
+ pixels: new Array( w * h ),
+ get: function(x,y)
+ {
+ return this.pixels[w*y+x];
+ },
+ _mask: null,
+ mask: function(img)
+ {
+ this._mask = img;
+ },
+ loadPixels: function()
+ {
+ },
+ updatePixels: function()
+ {
+ }
+ };
+
+ return data;
+ }
+
+ p.createGraphics = function createGraphics( w, h )
+ {
+ var canvas = document.createElement("canvas");
+ var ret = buildProcessing( canvas );
+ ret.size( w, h );
+ ret.canvas = canvas;
+ return ret;
+ }
+
+ p.beginDraw = function beginDraw()
+ {
+
+ }
+
+ p.endDraw = function endDraw()
+ {
+
+ }
+
+ p.tint = function tint( rgb, a )
+ {
+ curTint = a;
+ }
+
+ function getImage( img ) {
+ if ( typeof img == "string" )
+ {
+ return document.getElementById(img);
+ }
+
+ if ( img.img || img.canvas )
+ {
+ return img.img || img.canvas;
+ }
+
+ img.data = [];
+
+ for ( var i = 0, l = img.pixels.length; i < l; i++ )
+ {
+ var c = (img.pixels[i] || "rgba(0,0,0,1)").slice(5,-1).split(",");
+ img.data.push( parseInt(c[0]), parseInt(c[1]), parseInt(c[2]), parseFloat(c[3]) * 100 );
+ }
+
+ var canvas = document.createElement("canvas")
+ canvas.width = img.width;
+ canvas.height = img.height;
+ var context = canvas.getContext("2d");
+ context.putImageData( img, 0, 0 );
+
+ img.canvas = canvas;
+
+ return canvas;
+ }
+
+ p.image = function image( img, x, y, w, h )
+ {
+ x = x || 0;
+ y = y || 0;
+
+ var obj = getImage(img);
+
+ if ( curTint >= 0 )
+ {
+ var oldAlpha = curContext.globalAlpha;
+ curContext.globalAlpha = curTint / opacityRange;
+ }
+
+ if ( arguments.length == 3 )
+ {
+ curContext.drawImage( obj, x, y );
+ }
+ else
+ {
+ curContext.drawImage( obj, x, y, w, h );
+ }
+
+ if ( curTint >= 0 )
+ {
+ curContext.globalAlpha = oldAlpha;
+ }
+
+ if ( img._mask )
+ {
+ var oldComposite = curContext.globalCompositeOperation;
+ curContext.globalCompositeOperation = "darker";
+ p.image( img._mask, x, y );
+ curContext.globalCompositeOperation = oldComposite;
+ }
+ }
+
+ p.exit = function exit()
+ {
+
+ }
+
+ p.save = function save( file )
+ {
+
+ }
+
+ p.loadImage = function loadImage( file )
+ {
+ var img = document.getElementById(file);
+ if ( !img )
+ return;
+
+ var h = img.height, w = img.width;
+
+ var canvas = document.createElement("canvas");
+ canvas.width = w;
+ canvas.height = h;
+ var context = canvas.getContext("2d");
+
+ context.drawImage( img, 0, 0 );
+ var data = buildImageObject( context.getImageData( 0, 0, w, h ) );
+ data.img = img;
+ return data;
+ }
+
+ p.loadFont = function loadFont( name )
+ {
+ return {
+ name: name,
+ width: function( str )
+ {
+ if ( curContext.mozMeasureText )
+ return curContext.mozMeasureText( typeof str == "number" ?
+ String.fromCharCode( str ) :
+ str) / curTextSize;
+ else
+ return 0;
+ }
+ };
+ }
+
+ p.textFont = function textFont( name, size )
+ {
+ curTextFont = name;
+ p.textSize( size );
+ }
+
+ p.textSize = function textSize( size )
+ {
+ if ( size )
+ {
+ curTextSize = size;
+ }
+ }
+
+ p.textAlign = function textAlign()
+ {
+
+ }
+
+ p.text = function text( str, x, y )
+ {
+ if ( str && curContext.mozDrawText )
+ {
+ curContext.save();
+ curContext.mozTextStyle = curTextSize + "px " + curTextFont.name;
+ curContext.translate(x, y);
+ curContext.mozDrawText( typeof str == "number" ?
+ String.fromCharCode( str ) :
+ str );
+ curContext.restore();
+ }
+ }
+
+ p.char = function char( key )
+ {
+ //return String.fromCharCode( key );
+ return key;
+ }
+
+ p.println = function println()
+ {
+
+ }
+
+ p.map = function map( value, istart, istop, ostart, ostop )
+ {
+ return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
+ };
+
+ String.prototype.replaceAll = function(re, replace)
+ {
+ return this.replace(new RegExp(re, "g"), replace);
+ };
+
+ p.Point = function Point( x, y )
+ {
+ this.x = x;
+ this.y = y;
+ this.copy = function()
+ {
+ return new Point( x, y );
+ }
+ }
+
+ p.Random = function()
+ {
+ var haveNextNextGaussian = false;
+ var nextNextGaussian;
+
+ this.nextGaussian = function()
+ {
+ if (haveNextNextGaussian) {
+ haveNextNextGaussian = false;
+
+ return nextNextGaussian;
+ } else {
+ var v1, v2, s;
+ do {
+ v1 = 2 * p.random(1) - 1; // between -1.0 and 1.0
+ v2 = 2 * p.random(1) - 1; // between -1.0 and 1.0
+ s = v1 * v1 + v2 * v2;
+ } while (s >= 1 || s == 0);
+ var multiplier = Math.sqrt(-2 * Math.log(s)/s);
+ nextNextGaussian = v2 * multiplier;
+ haveNextNextGaussian = true;
+
+ return v1 * multiplier;
+ }
+ };
+ }
+
+ p.ArrayList = function ArrayList( 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 i = 0; i < size; i++ )
+ {
+ array[i] = 0;
+ }
+ }
+
+ array.size = function()
+ {
+ return this.length;
+ };
+ array.get = function( i )
+ {
+ return this[ i ];
+ };
+ array.remove = function( i )
+ {
+ return this.splice( i, 1 );
+ };
+ array.add = function( item )
+ {
+ for ( var i = 0; this[ i ] != undefined; i++ ) {}
+ this[ i ] = item;
+ };
+ array.clone = function()
+ {
+ var a = new ArrayList( size );
+ for ( var i = 0; i < size; i++ )
+ {
+ a[ i ] = this[ i ];
+ }
+ return a;
+ };
+ array.isEmpty = function()
+ {
+ return !this.length;
+ };
+ array.clear = function()
+ {
+ this.length = 0;
+ };
+
+ return array;
+ }
+
+ p.colorMode = function colorMode( mode, range1, range2, range3, range4 )
+ {
+ curColorMode = mode;
+
+ if ( arguments.length >= 4 )
+ {
+ redRange = range1;
+ greenRange = range2;
+ blueRange = range3;
+ }
+
+ if ( arguments.length == 5 )
+ {
+ opacityRange = range4;
+ }
+
+ if ( arguments.length == 2 )
+ {
+ p.colorMode( mode, range1, range1, range1, range1 );
+ }
+ }
+
+ p.beginShape = function beginShape( type )
+ {
+ curShape = type;
+ curShapeCount = 0;
+ }
+
+ p.endShape = function endShape( close )
+ {
+ if ( curShapeCount != 0 )
+ {
+ curContext.lineTo( firstX, firstY );
+
+ if ( doFill )
+ curContext.fill();
+
+ if ( doStroke )
+ curContext.stroke();
+
+ curContext.closePath();
+ curShapeCount = 0;
+ pathOpen = false;
+ }
+
+ if ( pathOpen )
+ {
+ curContext.closePath();
+ }
+ }
+
+ p.vertex = function vertex( x, y, x2, y2, x3, y3 )
+ {
+ if ( curShapeCount == 0 && curShape != p.POINTS )
+ {
+ pathOpen = true;
+ curContext.beginPath();
+ curContext.moveTo( x, y );
+ }
+ else
+ {
+ if ( curShape == p.POINTS )
+ {
+ p.point( x, y );
+ }
+ else if ( arguments.length == 2 )
+ {
+ if ( curShape == p.TRIANGLE_STRIP && curShapeCount == 2 )
+ {
+ curContext.moveTo( prevX, prevY );
+ curContext.lineTo( firstX, firstY );
+ }
+
+ curContext.lineTo( x, y );
+ }
+ else if ( arguments.length == 4 )
+ {
+ if ( curShapeCount > 1 )
+ {
+ curContext.moveTo( prevX, prevY );
+ curContext.quadraticCurveTo( firstX, firstY, x, y );
+ curShapeCount = 1;
+ }
+ }
+ else if ( arguments.length == 6 )
+ {
+ curContext.bezierCurveTo( x, y, x2, y2, x3, y3 );
+ curShapeCount = -1;
+ }
+ }
+
+ prevX = firstX;
+ prevY = firstY;
+ firstX = x;
+ firstY = y;
+
+
+ curShapeCount++;
+
+ if ( curShape == p.LINES && curShapeCount == 2 ||
+ (curShape == p.TRIANGLES || curShape == p.TRIANGLE_STRIP) && curShapeCount == 3 )
+ {
+ p.endShape();
+ }
+
+ if ( curShape == p.TRIANGLE_STRIP && curShapeCount == 3 )
+ {
+ curShapeCount = 2;
+ }
+ }
+
+ p.curveTightness = function()
+ {
+
+ }
+
+ // Unimplmented - not really possible with the Canvas API
+ p.curveVertex = function( x, y, x2, y2 )
+ {
+ p.vertex( x, y, x2, y2 );
+ }
+
+ p.bezierVertex = p.vertex
+
+ p.rectMode = function rectMode( aRectMode )
+ {
+ curRectMode = aRectMode;
+ }
+
+ p.imageMode = function()
+ {
+
+ }
+
+ p.ellipseMode = function ellipseMode( aEllipseMode )
+ {
+ curEllipseMode = aEllipseMode;
+ }
+
+ p.dist = function dist( x1, y1, x2, y2 )
+ {
+ return Math.sqrt( Math.pow( x2 - x1, 2 ) + Math.pow( y2 - y1, 2 ) );
+ }
+
+ p.year = function year()
+ {
+ return (new Date).getYear() + 1900;
+ }
+
+ p.month = function month()
+ {
+ return (new Date).getMonth();
+ }
+
+ p.day = function day()
+ {
+ return (new Date).getDay();
+ }
+
+ p.hour = function hour()
+ {
+ return (new Date).getHours();
+ }
+
+ p.minute = function minute()
+ {
+ return (new Date).getMinutes();
+ }
+
+ p.second = function second()
+ {
+ return (new Date).getSeconds();
+ }
+
+ p.millis = function millis()
+ {
+ return (new Date).getTime() - start;
+ }
+
+ p.ortho = function ortho()
+ {
+
+ }
+
+ p.translate = function translate( x, y )
+ {
+ curContext.translate( x, y );
+ }
+
+ p.scale = function scale( x, y )
+ {
+ curContext.scale( x, y || x );
+ }
+
+ p.rotate = function rotate( aAngle )
+ {
+ curContext.rotate( aAngle );
+ }
+
+ p.pushMatrix = function pushMatrix()
+ {
+ curContext.save();
+ }
+
+ p.popMatrix = function popMatrix()
+ {
+ curContext.restore();
+ }
+
+ p.redraw = function redraw()
+ {
+ if ( hasBackground )
+ {
+ p.background();
+ }
+
+ inDraw = true;
+ p.pushMatrix();
+ p.draw();
+ p.popMatrix();
+ inDraw = false;
+ }
+
+ p.loop = function loop()
+ {
+ if ( loopStarted )
+ return;
+
+ var looping = setInterval(function()
+ {
+ try
+ {
+ p.redraw();
+ }
+ catch(e)
+ {
+ clearInterval( looping );
+ throw e;
+ }
+ }, 1000 / curFrameRate );
+
+ loopStarted = true;
+ }
+
+ p.frameRate = function frameRate( aRate )
+ {
+ curFrameRate = aRate;
+ }
+
+ p.background = function background( img )
+ {
+ if ( arguments.length )
+ {
+ if ( img && img.img )
+ {
+ curBackground = img;
+ }
+ else
+ {
+ curBackground = p.color.apply( this, arguments );
+ }
+ }
+
+
+ if ( curBackground.img )
+ {
+ p.image( curBackground, 0, 0 );
+ }
+ else
+ {
+ var oldFill = curContext.fillStyle;
+ curContext.fillStyle = curBackground + "";
+ curContext.fillRect( 0, 0, p.width, p.height );
+ curContext.fillStyle = oldFill;
+ }
+ }
+
+ p.sq = function sq( aNumber )
+ {
+ return aNumber * aNumber;
+ }
+
+ p.sqrt = function sqrt( aNumber )
+ {
+ return Math.sqrt( aNumber );
+ }
+
+ p.int = function int( aNumber )
+ {
+ return Math.floor( aNumber );
+ }
+
+ p.min = function min( aNumber, aNumber2 )
+ {
+ return Math.min( aNumber, aNumber2 );
+ }
+
+ p.max = function max( aNumber, aNumber2 )
+ {
+ return Math.max( aNumber, aNumber2 );
+ }
+
+ p.ceil = function ceil( aNumber )
+ {
+ return Math.ceil( aNumber );
+ }
+
+ p.floor = function floor( aNumber )
+ {
+ return Math.floor( aNumber );
+ }
+
+ p.float = function float( aNumber )
+ {
+ return typeof aNumber == "string" ?
+ p.float( aNumber.charCodeAt(0) ) :
+ parseFloat( aNumber );
+ }
+
+ p.byte = function byte( aNumber )
+ {
+ return aNumber || 0;
+ }
+
+ p.random = function random( aMin, aMax )
+ {
+ return arguments.length == 2 ?
+ aMin + (Math.random() * (aMax - aMin)) :
+ Math.random() * aMin;
+ }
+
+ // From: http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
+ p.noise = function( x, y, z )
+ {
+ return arguments.length >= 2 ?
+ PerlinNoise_2D( x, y ) :
+ PerlinNoise_2D( x, x );
+ }
+
+ function Noise(x, y)
+ {
+ var n = x + y * 57;
+ n = (n<<13) ^ n;
+ return Math.abs(1.0 - (((n * ((n * n * 15731) + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0));
+ }
+
+ function SmoothedNoise(x, y)
+ {
+ var corners = ( Noise(x-1, y-1)+Noise(x+1, y-1)+Noise(x-1, y+1)+Noise(x+1, y+1) ) / 16;
+ var sides = ( Noise(x-1, y) +Noise(x+1, y) +Noise(x, y-1) +Noise(x, y+1) ) / 8;
+ var center = Noise(x, y) / 4;
+ return corners + sides + center;
+ }
+
+ function InterpolatedNoise(x, y)
+ {
+ var integer_X = Math.floor(x);
+ var fractional_X = x - integer_X;
+
+ var integer_Y = Math.floor(y);
+ var fractional_Y = y - integer_Y;
+
+ var v1 = SmoothedNoise(integer_X, integer_Y);
+ var v2 = SmoothedNoise(integer_X + 1, integer_Y);
+ var v3 = SmoothedNoise(integer_X, integer_Y + 1);
+ var v4 = SmoothedNoise(integer_X + 1, integer_Y + 1);
+
+ var i1 = Interpolate(v1 , v2 , fractional_X);
+ var i2 = Interpolate(v3 , v4 , fractional_X);
+
+ return Interpolate(i1 , i2 , fractional_Y);
+ }
+
+ function PerlinNoise_2D(x, y)
+ {
+ var total = 0;
+ var p = 0.25;
+ var n = 3;
+
+ for ( var i = 0; i <= n; i++ )
+ {
+ var frequency = Math.pow(2, i);
+ var amplitude = Math.pow(p, i);
+
+ total = total + InterpolatedNoise(x * frequency, y * frequency) * amplitude;
+ }
+
+ return total;
+ }
+
+ function Interpolate(a, b, x)
+ {
+ var ft = x * p.PI;
+ var f = (1 - p.cos(ft)) * .5;
+ return a*(1-f) + b*f;
+ }
+
+ p.red = function( aColor )
+ {
+ return parseInt(aColor.slice(5));
+ }
+
+ p.green = function( aColor )
+ {
+ return parseInt(aColor.split(",")[1]);
+ }
+
+ p.blue = function( aColor )
+ {
+ return parseInt(aColor.split(",")[2]);
+ }
+
+ p.alpha = function( aColor )
+ {
+ return parseInt(aColor.split(",")[3]);
+ }
+
+ p.abs = function abs( aNumber )
+ {
+ return Math.abs( aNumber );
+ }
+
+ p.cos = function cos( aNumber )
+ {
+ return Math.cos( aNumber );
+ }
+
+ p.sin = function sin( aNumber )
+ {
+ return Math.sin( aNumber );
+ }
+
+ p.pow = function pow( aNumber, aExponent )
+ {
+ return Math.pow( aNumber, aExponent );
+ }
+
+ p.constrain = function constrain( aNumber, aMin, aMax )
+ {
+ return Math.min( Math.max( aNumber, aMin ), aMax );
+ }
+
+ p.sqrt = function sqrt( aNumber )
+ {
+ return Math.sqrt( aNumber );
+ }
+
+ p.atan2 = function atan2( aNumber, aNumber2 )
+ {
+ return Math.atan2( aNumber, aNumber2 );
+ }
+
+ p.radians = function radians( aAngle )
+ {
+ return ( aAngle / 180 ) * p.PI;
+ }
+
+ p.size = function size( aWidth, aHeight )
+ {
+ var fillStyle = curContext.fillStyle;
+ var strokeStyle = curContext.strokeStyle;
+
+ curElement.width = p.width = aWidth;
+ curElement.height = p.height = aHeight;
+
+ curContext.fillStyle = fillStyle;
+ curContext.strokeStyle = strokeStyle;
+ }
+
+ p.noStroke = function noStroke()
+ {
+ doStroke = false;
+ }
+
+ p.noFill = function noFill()
+ {
+ doFill = false;
+ }
+
+ p.smooth = function smooth()
+ {
+
+ }
+
+ p.noLoop = function noLoop()
+ {
+ doLoop = false;
+ }
+
+ p.fill = function fill()
+ {
+ doFill = true;
+ curContext.fillStyle = p.color.apply( this, arguments );
+ }
+
+ p.stroke = function stroke()
+ {
+ doStroke = true;
+ curContext.strokeStyle = p.color.apply( this, arguments );
+ }
+
+ p.strokeWeight = function strokeWeight( w )
+ {
+ curContext.lineWidth = w;
+ }
+
+ p.point = function point( x, y )
+ {
+ var oldFill = curContext.fillStyle;
+ curContext.fillStyle = curContext.strokeStyle;
+ curContext.fillRect( Math.round( x ), Math.round( y ), 1, 1 );
+ curContext.fillStyle = oldFill;
+ }
+
+ p.get = function get( x, y )
+ {
+ if ( arguments.length == 0 )
+ {
+ var c = p.createGraphics( p.width, p.height );
+ c.image( curContext, 0, 0 );
+ return c;
+ }
+
+ if ( !getLoaded )
+ {
+ getLoaded = buildImageObject( curContext.getImageData(0, 0, p.width, p.height) );
+ }
+
+ return getLoaded.get( x, y );
+ }
+
+ p.set = function set( x, y, color )
+ {
+ var oldFill = curContext.fillStyle;
+ curContext.fillStyle = color;
+ curContext.fillRect( Math.round( x ), Math.round( y ), 1, 1 );
+ curContext.fillStyle = oldFill;
+ }
+
+ p.arc = function arc( x, y, width, height, start, stop )
+ {
+ if ( width <= 0 )
+ return;
+
+ if ( curEllipseMode == p.CORNER )
+ {
+ x += width / 2;
+ y += height / 2;
+ }
+
+ curContext.beginPath();
+
+ curContext.moveTo( x, y );
+ curContext.arc( x, y, curEllipseMode == p.CENTER_RADIUS ? width : width/2, start, stop, false );
+
+ if ( doFill )
+ curContext.fill();
+
+ if ( doStroke )
+ curContext.stroke();
+
+ curContext.closePath();
+ }
+
+ p.line = function line( x1, y1, x2, y2 )
+ {
+ curContext.lineCap = "round";
+ curContext.beginPath();
+
+ curContext.moveTo( x1 || 0, y1 || 0 );
+ curContext.lineTo( x2 || 0, y2 || 0 );
+
+ curContext.stroke();
+
+ curContext.closePath();
+ }
+
+ p.bezier = function bezier( x1, y1, x2, y2, x3, y3, x4, y4 )
+ {
+ curContext.lineCap = "butt";
+ curContext.beginPath();
+
+ curContext.moveTo( x1, y1 );
+ curContext.bezierCurveTo( x2, y2, x3, y3, x4, y4 );
+
+ curContext.stroke();
+
+ curContext.closePath();
+ }
+
+ p.triangle = function triangle( x1, y1, x2, y2, x3, y3 )
+ {
+ p.beginShape();
+ p.vertex( x1, y1 );
+ p.vertex( x2, y2 );
+ p.vertex( x3, y3 );
+ p.endShape();
+ }
+
+ p.quad = function quad( x1, y1, x2, y2, x3, y3, x4, y4 )
+ {
+ p.beginShape();
+ p.vertex( x1, y1 );
+ p.vertex( x2, y2 );
+ p.vertex( x3, y3 );
+ p.vertex( x4, y4 );
+ p.endShape();
+ }
+
+ p.rect = function rect( x, y, width, height )
+ {
+ if ( width == 0 && height == 0 )
+ return;
+
+ curContext.beginPath();
+
+ var offsetStart = 0;
+ var offsetEnd = 0;
+
+ if ( curRectMode == p.CORNERS )
+ {
+ width -= x;
+ height -= y;
+ }
+
+ if ( curRectMode == p.RADIUS )
+ {
+ width *= 2;
+ height *= 2;
+ }
+
+ if ( curRectMode == p.CENTER || curRectMode == p.RADIUS )
+ {
+ x -= width / 2;
+ y -= height / 2;
+ }
+
+ curContext.rect(
+ Math.round( x ) - offsetStart,
+ Math.round( y ) - offsetStart,
+ Math.round( width ) + offsetEnd,
+ Math.round( height ) + offsetEnd
+ );
+
+ if ( doFill )
+ curContext.fill();
+
+ if ( doStroke )
+ curContext.stroke();
+
+ curContext.closePath();
+ }
+
+ p.ellipse = function ellipse( x, y, width, height )
+ {
+ x = x || 0;
+ y = y || 0;
+
+ if ( width <= 0 && height <= 0 )
+ return;
+
+ curContext.beginPath();
+
+ if ( curEllipseMode == p.RADIUS )
+ {
+ width *= 2;
+ height *= 2;
+ }
+
+ var offsetStart = 0;
+
+ // Shortcut for drawing a circle
+ if ( width == height )
+ curContext.arc( x - offsetStart, y - offsetStart, width / 2, 0, Math.PI * 2, false );
+
+ if ( doFill )
+ curContext.fill();
+
+ if ( doStroke )
+ curContext.stroke();
+
+ curContext.closePath();
+ }
+
+ p.link = function( href, target )
+ {
+ window.location = href;
+ }
+
+ p.loadPixels = function()
+ {
+ p.pixels = buildImageObject( curContext.getImageData(0, 0, p.width, p.height) ).pixels;
+ }
+
+ p.updatePixels = function()
+ {
+ var colors = /(\d+),(\d+),(\d+),(\d+)/;
+ var pixels = {};
+ var data = pixels.data = [];
+ pixels.width = p.width;
+ pixels.height = p.height;
+
+ var pos = 0;
+
+ for ( var i = 0, l = p.pixels.length; i < l; i++ ) {
+ var c = (p.pixels[i] || "rgba(0,0,0,1)").match(colors);
+ data[pos] = parseInt(c[1]);
+ data[pos+1] = parseInt(c[2]);
+ data[pos+2] = parseInt(c[3]);
+ data[pos+3] = parseFloat(c[4]) * 100;
+ pos += 4;
+ }
+
+ curContext.putImageData(pixels, 0, 0);
+ }
+
+ p.extendClass = function extendClass( obj, args, fn )
+ {
+ if ( arguments.length == 3 )
+ {
+ fn.apply( obj, args );
+ }
+ else
+ {
+ args.call( obj );
+ }
+ }
+
+ p.addMethod = function addMethod( object, name, fn )
+ {
+ if ( object[ name ] )
+ {
+ var args = fn.length;
+
+ var oldfn = object[ name ];
+ object[ name ] = function()
+ {
+ if ( arguments.length == args )
+ return fn.apply( this, arguments );
+ else
+ return oldfn.apply( this, arguments );
+ };
+ }
+ else
+ {
+ object[ name ] = fn;
+ }
+ }
+
+ p.init = function init(code){
+ p.stroke( 0 );
+ p.fill( 255 );
+
+ // Canvas has trouble rendering single pixel stuff on whole-pixel
+ // counts, so we slightly offset it (this is super lame).
+ curContext.translate( 0.5, 0.5 );
+
+ if ( code )
+ {
+ (function(Processing){with (p){
+ eval(parse(code, p));
+ }})(p);
+ }
+
+ if ( p.setup )
+ {
+ inSetup = true;
+ p.setup();
+ }
+
+ inSetup = false;
+
+ if ( p.draw )
+ {
+ if ( !doLoop )
+ {
+ p.redraw();
+ }
+ else
+ {
+ p.loop();
+ }
+ }
+
+ attach( curElement, "mousemove", function(e)
+ {
+ p.pmouseX = p.mouseX;
+ p.pmouseY = p.mouseY;
+ p.mouseX = e.clientX - curElement.offsetLeft;
+ p.mouseY = e.clientY - curElement.offsetTop;
+
+ if ( p.mouseMoved )
+ {
+ p.mouseMoved();
+ }
+
+ if ( mousePressed && p.mouseDragged )
+ {
+ p.mouseDragged();
+ }
+ });
+
+ attach( curElement, "mousedown", function(e)
+ {
+ mousePressed = true;
+
+ if ( typeof p.mousePressed == "function" )
+ {
+ p.mousePressed();
+ }
+ else
+ {
+ p.mousePressed = true;
+ }
+ });
+
+ attach( curElement, "mouseup", function(e)
+ {
+ mousePressed = false;
+
+ if ( typeof p.mousePressed != "function" )
+ {
+ p.mousePressed = false;
+ }
+
+ if ( p.mouseReleased )
+ {
+ p.mouseReleased();
+ }
+ });
+
+ attach( document, "keydown", function(e)
+ {
+ keyPressed = true;
+
+ p.key = e.keyCode + 32;
+
+ if ( e.shiftKey )
+ {
+ p.key = String.fromCharCode(p.key).toUpperCase().charCodeAt(0);
+ }
+
+ if ( typeof p.keyPressed == "function" )
+ {
+ p.keyPressed();
+ }
+ else
+ {
+ p.keyPressed = true;
+ }
+ });
+
+ attach( document, "keyup", function(e)
+ {
+ keyPressed = false;
+
+ if ( typeof p.keyPressed != "function" )
+ {
+ p.keyPressed = false;
+ }
+
+ if ( p.keyReleased )
+ {
+ p.keyReleased();
+ }
+ });
+
+ function attach(elem, type, fn)
+ {
+ if ( elem.addEventListener )
+ elem.addEventListener( type, fn, false );
+ else
+ elem.attachEvent( "on" + type, fn );
+ }
+ };
+
+ return p;
+}
+
+})();