diff --git a/app/src/processing/mode/javascript/BasicServer.java b/app/src/processing/mode/javascript/BasicServer.java
index 35e0a74df..d2e4dfb89 100644
--- a/app/src/processing/mode/javascript/BasicServer.java
+++ b/app/src/processing/mode/javascript/BasicServer.java
@@ -363,7 +363,9 @@ implements HttpConstants, Runnable
try {
handleClient();
} catch (Exception e) {
- e.printStackTrace();
+ // TODO check why this is raised instead of
+ // sending 404 for favicon.ico, etc. ..
+ //e.printStackTrace();
}
}
socket = null;
diff --git a/javascript/examples/HTML5/Audio/AudioApis/AudioApis.pde b/javascript/examples/HTML5/Audio/AudioApis/AudioApis.pde
new file mode 100644
index 000000000..303a8577f
--- /dev/null
+++ b/javascript/examples/HTML5/Audio/AudioApis/AudioApis.pde
@@ -0,0 +1,65 @@
+/**
+ * This example shows how to render a waveform from an audio file.
+ *
+ * Currently Firefox and Chrome only.
+ */
+
+int[] audioBytes;
+boolean noAudioDataApi;
+
+void setup ()
+{
+ size( 800, 200 );
+
+ sketchStarted( this );
+}
+
+void draw ()
+{
+ background( 100 );
+
+ if ( noAudioDataApi )
+ {
+ background( 100, 0, 0 );
+ fill( 255, 0, 0 );
+ text( "Your browser does not support the AudioData API. Try FF 4+ or recent Chrome", 20, 40 );
+ }
+ else if ( audioBytes != null )
+ {
+ noFill();
+ stroke( 255 );
+ beginShape();
+ for ( int i = 0; i < audioBytes.length; i++ )
+ {
+ vertex( map( i, 0, audioBytes.length, 0, width ), map( audioBytes[i], -1, 1, height, 0 ) );
+ }
+ endShape();
+ }
+}
+
+void audioDataApiNotAvailable ()
+{
+ noAudioDataApi = true;
+}
+
+void audioMetaData ( int sampleRate, int channels, int bufferLength )
+{
+}
+
+void audioData ( int[] buffer )
+{
+ if ( audioBytes == null )
+ audioBytes = buffer;
+ else
+ {
+ int[] tmp = new int[ audioBytes.length + buffer.length ];
+
+ for ( int i = 0; i < audioBytes.length; i++ )
+ tmp[i] = audioBytes[i];
+
+ for ( int i = 0; i < buffer.length; i++ )
+ tmp[audioBytes.length+i] = buffer[i];
+
+ audioBytes = tmp;
+ }
+}
diff --git a/javascript/examples/HTML5/Audio/AudioApis/audio.js b/javascript/examples/HTML5/Audio/AudioApis/audio.js
new file mode 100644
index 000000000..87c2b6bdd
--- /dev/null
+++ b/javascript/examples/HTML5/Audio/AudioApis/audio.js
@@ -0,0 +1,84 @@
+
+var sketchStarted = function ( sketch )
+{
+ if ( navigator.userAgent.match(/Firefox/i) )
+ AudioDataFF.load( ["BD.wav","BD.mp3"], sketch );
+ else if ( navigator.userAgent.match(/Chrome/i) )
+ AudioDataWebKit.load( "BD.wav", sketch );
+ else
+ sketch.audioDataApiNotAvailable();
+}
+
+// https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AudioBuffer-section
+// http://www.html5rocks.com/en/tutorials/webaudio/intro/
+// http://chromium.googlecode.com/svn/trunk/samples/audio/index.html
+var AudioDataWebKit = {
+ context : (function(){
+ if ('webkitAudioContext' in window)
+ return new webkitAudioContext();
+ })(),
+ buffers : [],
+ listener : null,
+ load : function ( url, listener ) {
+ this.listener = listener;
+ if ( !( url instanceof Array ) ) {
+ url = [url];
+ }
+ for ( u in url ) {
+ var request = new XMLHttpRequest();
+ request.open('GET', url[u], true);
+ request.responseType = 'arraybuffer';
+ request.onload = (function(ad){ return function() {
+ ad.context.decodeAudioData( request.response, function(buffer) {
+ ad.buffers.push( buffer );
+ ad.listener.audioMetaData( buffer.sampleRate, buffer.numberOfChannels, buffer.length );
+ ad.listener.audioData( buffer.getChannelData(0) );
+ }, onError);
+ }})(this);
+ var onError = function (err) {
+ console.log( err );
+ }
+ request.send();
+ }
+ }
+};
+
+// https://wiki.mozilla.org/Audio_Data_API
+var AudioDataFF = {
+ audioElement : null,
+ listener : null,
+ load : function ( url, listener ) {
+ this.listener = listener;
+ if ( this.audioElement == null ) {
+ this.audioElement = document.createElement( "audio" );
+ this.audioElement.addEventListener('loadedmetadata', (function(ad){ return function ( ev ) {
+ ad.audioMetaData( ev, this );
+ }})(this), false);
+ this.audioElement.addEventListener('MozAudioAvailable', (function(ad){return function(ev){
+ ad.audioAvailable( ev, this );
+ }})(this), false);
+ if ( !( url instanceof Array ) ) {
+ url = [ url ];
+ }
+ for ( u in url ) {
+ var src = document.createElement( "source" );
+ src.setAttribute( "src", url[u] );
+ this.audioElement.appendChild( src );
+ }
+ document.body.appendChild( this.audioElement );
+ }
+ },
+ audioAvailable : function ( ev ) {
+ this.listener.audioData( ev.frameBuffer );
+ },
+ audioMetaData : function ( ev ) {
+ if ( this.audioElement ) {
+ this.audioElement.volume = 0;
+ this.audioElement.play();
+ this.listener.audioMetaData(
+ this.audioElement.mozSampleRate,
+ this.audioElement.mozChannels,
+ this.audioElement.mozFrameBufferLength );
+ }
+ }
+};
diff --git a/javascript/examples/HTML5/Audio/AudioApis/data/BD.mp3 b/javascript/examples/HTML5/Audio/AudioApis/data/BD.mp3
new file mode 100644
index 000000000..9d1aa49fe
Binary files /dev/null and b/javascript/examples/HTML5/Audio/AudioApis/data/BD.mp3 differ
diff --git a/javascript/examples/HTML5/Audio/AudioApis/data/BD.wav b/javascript/examples/HTML5/Audio/AudioApis/data/BD.wav
new file mode 100644
index 000000000..c8ac8535b
Binary files /dev/null and b/javascript/examples/HTML5/Audio/AudioApis/data/BD.wav differ
diff --git a/javascript/examples/HTML5/Audio/AudioApis/sketch.properties b/javascript/examples/HTML5/Audio/AudioApis/sketch.properties
new file mode 100644
index 000000000..6d28cd598
--- /dev/null
+++ b/javascript/examples/HTML5/Audio/AudioApis/sketch.properties
@@ -0,0 +1 @@
+mode=JavaScript
diff --git a/javascript/examples/HTML5/Audio/AudioApis/web-export/AudioApis.pde b/javascript/examples/HTML5/Audio/AudioApis/web-export/AudioApis.pde
new file mode 100644
index 000000000..3a957f14a
--- /dev/null
+++ b/javascript/examples/HTML5/Audio/AudioApis/web-export/AudioApis.pde
@@ -0,0 +1,66 @@
+/**
+ * This example shows how to render a waveform from an audio file.
+ *
+ * Currently Firefox and Chrome only.
+ */
+
+int[] audioBytes;
+boolean noAudioDataApi;
+
+void setup ()
+{
+ size( 800, 200 );
+
+ sketchStarted( this );
+}
+
+void draw ()
+{
+ background( 100 );
+
+ if ( noAudioDataApi )
+ {
+ background( 100, 0, 0 );
+ fill( 255, 0, 0 );
+ text( "Your browser does not support the AudioData API. Try FF 4+ or recent Chrome", 20, 40 );
+ }
+ else if ( audioBytes != null )
+ {
+ noFill();
+ stroke( 255 );
+ beginShape();
+ for ( int i = 0; i < audioBytes.length; i++ )
+ {
+ vertex( map( i, 0, audioBytes.length, 0, width ), map( audioBytes[i], -1, 1, height, 0 ) );
+ }
+ endShape();
+ }
+}
+
+void audioDataApiNotAvailable ()
+{
+ noAudioDataApi = true;
+}
+
+void audioMetaData ( int sampleRate, int channels, int bufferLength )
+{
+}
+
+void audioData ( int[] buffer )
+{
+ if ( audioBytes == null )
+ audioBytes = buffer;
+ else
+ {
+ int[] tmp = new int[ audioBytes.length + buffer.length ];
+
+ for ( int i = 0; i < audioBytes.length; i++ )
+ tmp[i] = audioBytes[i];
+
+ for ( int i = 0; i < buffer.length; i++ )
+ tmp[audioBytes.length+i] = buffer[i];
+
+ audioBytes = tmp;
+ }
+}
+
diff --git a/javascript/examples/HTML5/Audio/AudioApis/web-export/BD.mp3 b/javascript/examples/HTML5/Audio/AudioApis/web-export/BD.mp3
new file mode 100644
index 000000000..9d1aa49fe
Binary files /dev/null and b/javascript/examples/HTML5/Audio/AudioApis/web-export/BD.mp3 differ
diff --git a/javascript/examples/HTML5/Audio/AudioApis/web-export/BD.wav b/javascript/examples/HTML5/Audio/AudioApis/web-export/BD.wav
new file mode 100644
index 000000000..c8ac8535b
Binary files /dev/null and b/javascript/examples/HTML5/Audio/AudioApis/web-export/BD.wav differ
diff --git a/javascript/examples/HTML5/Audio/AudioApis/web-export/audio.js b/javascript/examples/HTML5/Audio/AudioApis/web-export/audio.js
new file mode 100644
index 000000000..87c2b6bdd
--- /dev/null
+++ b/javascript/examples/HTML5/Audio/AudioApis/web-export/audio.js
@@ -0,0 +1,84 @@
+
+var sketchStarted = function ( sketch )
+{
+ if ( navigator.userAgent.match(/Firefox/i) )
+ AudioDataFF.load( ["BD.wav","BD.mp3"], sketch );
+ else if ( navigator.userAgent.match(/Chrome/i) )
+ AudioDataWebKit.load( "BD.wav", sketch );
+ else
+ sketch.audioDataApiNotAvailable();
+}
+
+// https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AudioBuffer-section
+// http://www.html5rocks.com/en/tutorials/webaudio/intro/
+// http://chromium.googlecode.com/svn/trunk/samples/audio/index.html
+var AudioDataWebKit = {
+ context : (function(){
+ if ('webkitAudioContext' in window)
+ return new webkitAudioContext();
+ })(),
+ buffers : [],
+ listener : null,
+ load : function ( url, listener ) {
+ this.listener = listener;
+ if ( !( url instanceof Array ) ) {
+ url = [url];
+ }
+ for ( u in url ) {
+ var request = new XMLHttpRequest();
+ request.open('GET', url[u], true);
+ request.responseType = 'arraybuffer';
+ request.onload = (function(ad){ return function() {
+ ad.context.decodeAudioData( request.response, function(buffer) {
+ ad.buffers.push( buffer );
+ ad.listener.audioMetaData( buffer.sampleRate, buffer.numberOfChannels, buffer.length );
+ ad.listener.audioData( buffer.getChannelData(0) );
+ }, onError);
+ }})(this);
+ var onError = function (err) {
+ console.log( err );
+ }
+ request.send();
+ }
+ }
+};
+
+// https://wiki.mozilla.org/Audio_Data_API
+var AudioDataFF = {
+ audioElement : null,
+ listener : null,
+ load : function ( url, listener ) {
+ this.listener = listener;
+ if ( this.audioElement == null ) {
+ this.audioElement = document.createElement( "audio" );
+ this.audioElement.addEventListener('loadedmetadata', (function(ad){ return function ( ev ) {
+ ad.audioMetaData( ev, this );
+ }})(this), false);
+ this.audioElement.addEventListener('MozAudioAvailable', (function(ad){return function(ev){
+ ad.audioAvailable( ev, this );
+ }})(this), false);
+ if ( !( url instanceof Array ) ) {
+ url = [ url ];
+ }
+ for ( u in url ) {
+ var src = document.createElement( "source" );
+ src.setAttribute( "src", url[u] );
+ this.audioElement.appendChild( src );
+ }
+ document.body.appendChild( this.audioElement );
+ }
+ },
+ audioAvailable : function ( ev ) {
+ this.listener.audioData( ev.frameBuffer );
+ },
+ audioMetaData : function ( ev ) {
+ if ( this.audioElement ) {
+ this.audioElement.volume = 0;
+ this.audioElement.play();
+ this.listener.audioMetaData(
+ this.audioElement.mozSampleRate,
+ this.audioElement.mozChannels,
+ this.audioElement.mozFrameBufferLength );
+ }
+ }
+};
diff --git a/javascript/examples/HTML5/Audio/AudioApis/web-export/processing.js b/javascript/examples/HTML5/Audio/AudioApis/web-export/processing.js
new file mode 100644
index 000000000..45c550fdd
--- /dev/null
+++ b/javascript/examples/HTML5/Audio/AudioApis/web-export/processing.js
@@ -0,0 +1,9994 @@
+/***
+
+ P R O C E S S I N G . J S - 1.3.6
+ a port of the Processing visualization language
+
+ Processing.js is licensed under the MIT License, see LICENSE.
+ For a list of copyright holders, please refer to AUTHORS.
+
+ http://processingjs.org
+
+***/
+
+(function(window, document, Math, undef) {
+ var nop = function() {};
+ var debug = function() {
+ if ("console" in window) return function(msg) {
+ window.console.log("Processing.js: " + msg)
+ };
+ return nop()
+ }();
+ var ajax = function(url) {
+ var xhr = new XMLHttpRequest;
+ xhr.open("GET", url, false);
+ if (xhr.overrideMimeType) xhr.overrideMimeType("text/plain");
+ xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT");
+ xhr.send(null);
+ if (xhr.status !== 200 && xhr.status !== 0) throw "XMLHttpRequest failed, status code " + xhr.status;
+ return xhr.responseText
+ };
+ var isDOMPresent = "document" in this && !("fake" in this.document);
+ document.head = document.head || document.getElementsByTagName("head")[0];
+
+ function setupTypedArray(name, fallback) {
+ if (name in window) return window[name];
+ if (typeof window[fallback] === "function") return window[fallback];
+ return function(obj) {
+ if (obj instanceof Array) return obj;
+ if (typeof obj === "number") {
+ var arr = [];
+ arr.length = obj;
+ return arr
+ }
+ }
+ }
+ var Float32Array = setupTypedArray("Float32Array", "WebGLFloatArray"),
+ Int32Array = setupTypedArray("Int32Array", "WebGLIntArray"),
+ Uint16Array = setupTypedArray("Uint16Array", "WebGLUnsignedShortArray"),
+ Uint8Array = setupTypedArray("Uint8Array", "WebGLUnsignedByteArray");
+ var PConstants = {
+ X: 0,
+ Y: 1,
+ Z: 2,
+ R: 3,
+ G: 4,
+ B: 5,
+ A: 6,
+ U: 7,
+ V: 8,
+ NX: 9,
+ NY: 10,
+ NZ: 11,
+ EDGE: 12,
+ SR: 13,
+ SG: 14,
+ SB: 15,
+ SA: 16,
+ SW: 17,
+ TX: 18,
+ TY: 19,
+ TZ: 20,
+ VX: 21,
+ VY: 22,
+ VZ: 23,
+ VW: 24,
+ AR: 25,
+ AG: 26,
+ AB: 27,
+ DR: 3,
+ DG: 4,
+ DB: 5,
+ DA: 6,
+ SPR: 28,
+ SPG: 29,
+ SPB: 30,
+ SHINE: 31,
+ ER: 32,
+ EG: 33,
+ EB: 34,
+ BEEN_LIT: 35,
+ VERTEX_FIELD_COUNT: 36,
+ P2D: 1,
+ JAVA2D: 1,
+ WEBGL: 2,
+ P3D: 2,
+ OPENGL: 2,
+ PDF: 0,
+ DXF: 0,
+ OTHER: 0,
+ WINDOWS: 1,
+ MAXOSX: 2,
+ LINUX: 3,
+ EPSILON: 1.0E-4,
+ MAX_FLOAT: 3.4028235E38,
+ MIN_FLOAT: -3.4028235E38,
+ MAX_INT: 2147483647,
+ MIN_INT: -2147483648,
+ PI: Math.PI,
+ TWO_PI: 2 * Math.PI,
+ HALF_PI: Math.PI / 2,
+ THIRD_PI: Math.PI / 3,
+ QUARTER_PI: Math.PI / 4,
+ DEG_TO_RAD: Math.PI / 180,
+ RAD_TO_DEG: 180 / Math.PI,
+ WHITESPACE: " \t\n\r\u000c\u00a0",
+ RGB: 1,
+ ARGB: 2,
+ HSB: 3,
+ ALPHA: 4,
+ CMYK: 5,
+ TIFF: 0,
+ TARGA: 1,
+ JPEG: 2,
+ GIF: 3,
+ BLUR: 11,
+ GRAY: 12,
+ INVERT: 13,
+ OPAQUE: 14,
+ POSTERIZE: 15,
+ THRESHOLD: 16,
+ ERODE: 17,
+ DILATE: 18,
+ REPLACE: 0,
+ BLEND: 1 << 0,
+ ADD: 1 << 1,
+ SUBTRACT: 1 << 2,
+ LIGHTEST: 1 << 3,
+ DARKEST: 1 << 4,
+ DIFFERENCE: 1 << 5,
+ EXCLUSION: 1 << 6,
+ MULTIPLY: 1 << 7,
+ SCREEN: 1 << 8,
+ OVERLAY: 1 << 9,
+ HARD_LIGHT: 1 << 10,
+ SOFT_LIGHT: 1 << 11,
+ DODGE: 1 << 12,
+ BURN: 1 << 13,
+ ALPHA_MASK: 4278190080,
+ RED_MASK: 16711680,
+ GREEN_MASK: 65280,
+ BLUE_MASK: 255,
+ CUSTOM: 0,
+ ORTHOGRAPHIC: 2,
+ PERSPECTIVE: 3,
+ POINT: 2,
+ POINTS: 2,
+ LINE: 4,
+ LINES: 4,
+ TRIANGLE: 8,
+ TRIANGLES: 9,
+ TRIANGLE_STRIP: 10,
+ TRIANGLE_FAN: 11,
+ QUAD: 16,
+ QUADS: 16,
+ QUAD_STRIP: 17,
+ POLYGON: 20,
+ PATH: 21,
+ RECT: 30,
+ ELLIPSE: 31,
+ ARC: 32,
+ SPHERE: 40,
+ BOX: 41,
+ GROUP: 0,
+ PRIMITIVE: 1,
+ GEOMETRY: 3,
+ VERTEX: 0,
+ BEZIER_VERTEX: 1,
+ CURVE_VERTEX: 2,
+ BREAK: 3,
+ CLOSESHAPE: 4,
+ OPEN: 1,
+ CLOSE: 2,
+ CORNER: 0,
+ CORNERS: 1,
+ RADIUS: 2,
+ CENTER_RADIUS: 2,
+ CENTER: 3,
+ DIAMETER: 3,
+ CENTER_DIAMETER: 3,
+ BASELINE: 0,
+ TOP: 101,
+ BOTTOM: 102,
+ NORMAL: 1,
+ NORMALIZED: 1,
+ IMAGE: 2,
+ MODEL: 4,
+ SHAPE: 5,
+ SQUARE: "butt",
+ ROUND: "round",
+ PROJECT: "square",
+ MITER: "miter",
+ BEVEL: "bevel",
+ AMBIENT: 0,
+ DIRECTIONAL: 1,
+ SPOT: 3,
+ BACKSPACE: 8,
+ TAB: 9,
+ ENTER: 10,
+ RETURN: 13,
+ ESC: 27,
+ DELETE: 127,
+ CODED: 65535,
+ SHIFT: 16,
+ CONTROL: 17,
+ ALT: 18,
+ CAPSLK: 20,
+ PGUP: 33,
+ PGDN: 34,
+ END: 35,
+ HOME: 36,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40,
+ F1: 112,
+ F2: 113,
+ F3: 114,
+ F4: 115,
+ F5: 116,
+ F6: 117,
+ F7: 118,
+ F8: 119,
+ F9: 120,
+ F10: 121,
+ F11: 122,
+ F12: 123,
+ NUMLK: 144,
+ META: 157,
+ INSERT: 155,
+ ARROW: "default",
+ CROSS: "crosshair",
+ HAND: "pointer",
+ MOVE: "move",
+ TEXT: "text",
+ WAIT: "wait",
+ NOCURSOR: "url('data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='), auto",
+ DISABLE_OPENGL_2X_SMOOTH: 1,
+ ENABLE_OPENGL_2X_SMOOTH: -1,
+ ENABLE_OPENGL_4X_SMOOTH: 2,
+ ENABLE_NATIVE_FONTS: 3,
+ DISABLE_DEPTH_TEST: 4,
+ ENABLE_DEPTH_TEST: -4,
+ ENABLE_DEPTH_SORT: 5,
+ DISABLE_DEPTH_SORT: -5,
+ DISABLE_OPENGL_ERROR_REPORT: 6,
+ ENABLE_OPENGL_ERROR_REPORT: -6,
+ ENABLE_ACCURATE_TEXTURES: 7,
+ DISABLE_ACCURATE_TEXTURES: -7,
+ HINT_COUNT: 10,
+ SINCOS_LENGTH: 720,
+ PRECISIONB: 15,
+ PRECISIONF: 1 << 15,
+ PREC_MAXVAL: (1 << 15) - 1,
+ PREC_ALPHA_SHIFT: 24 - 15,
+ PREC_RED_SHIFT: 16 - 15,
+ NORMAL_MODE_AUTO: 0,
+ NORMAL_MODE_SHAPE: 1,
+ NORMAL_MODE_VERTEX: 2,
+ MAX_LIGHTS: 8
+ };
+
+ function virtHashCode(obj) {
+ if (typeof obj === "string") {
+ var hash = 0;
+ for (var i = 0; i < obj.length; ++i) hash = hash * 31 + obj.charCodeAt(i) & 4294967295;
+ return hash
+ }
+ if (typeof obj !== "object") return obj & 4294967295;
+ if (obj.hashCode instanceof Function) return obj.hashCode();
+ if (obj.$id === undef) obj.$id = Math.floor(Math.random() * 65536) - 32768 << 16 | Math.floor(Math.random() * 65536);
+ return obj.$id
+ }
+ function virtEquals(obj, other) {
+ if (obj === null || other === null) return obj === null && other === null;
+ if (typeof obj === "string") return obj === other;
+ if (typeof obj !== "object") return obj === other;
+ if (obj.equals instanceof Function) return obj.equals(other);
+ return obj === other
+ }
+ var ObjectIterator = function(obj) {
+ if (obj.iterator instanceof Function) return obj.iterator();
+ if (obj instanceof Array) {
+ var index = -1;
+ this.hasNext = function() {
+ return ++index < obj.length
+ };
+ this.next = function() {
+ return obj[index]
+ }
+ } else throw "Unable to iterate: " + obj;
+ };
+ var ArrayList = function() {
+ function Iterator(array) {
+ var index = 0;
+ this.hasNext = function() {
+ return index < array.length
+ };
+ this.next = function() {
+ return array[index++]
+ };
+ this.remove = function() {
+ array.splice(index, 1)
+ }
+ }
+ function ArrayList() {
+ var array;
+ if (arguments.length === 0) array = [];
+ else if (arguments.length > 0 && typeof arguments[0] !== "number") array = arguments[0].toArray();
+ else {
+ array = [];
+ array.length = 0 | arguments[0]
+ }
+ this.get = function(i) {
+ return array[i]
+ };
+ this.contains = function(item) {
+ return this.indexOf(item) > -1
+ };
+ this.indexOf = function(item) {
+ for (var i = 0, len = array.length; i < len; ++i) if (virtEquals(item, array[i])) return i;
+ return -1
+ };
+ this.add = function() {
+ if (arguments.length === 1) array.push(arguments[0]);
+ else if (arguments.length === 2) {
+ var arg0 = arguments[0];
+ if (typeof arg0 === "number") if (arg0 >= 0 && arg0 <= array.length) array.splice(arg0, 0, arguments[1]);
+ else throw arg0 + " is not a valid index";
+ else throw typeof arg0 + " is not a number";
+ } else throw "Please use the proper number of parameters.";
+ };
+ this.addAll = function(arg1, arg2) {
+ var it;
+ if (typeof arg1 === "number") {
+ if (arg1 < 0 || arg1 > array.length) throw "Index out of bounds for addAll: " + arg1 + " greater or equal than " + array.length;
+ it = new ObjectIterator(arg2);
+ while (it.hasNext()) array.splice(arg1++, 0, it.next())
+ } else {
+ it = new ObjectIterator(arg1);
+ while (it.hasNext()) array.push(it.next())
+ }
+ };
+ this.set = function() {
+ if (arguments.length === 2) {
+ var arg0 = arguments[0];
+ if (typeof arg0 === "number") if (arg0 >= 0 && arg0 < array.length) array.splice(arg0, 1, arguments[1]);
+ else throw arg0 + " is not a valid index.";
+ else throw typeof arg0 + " is not a number";
+ } else throw "Please use the proper number of parameters.";
+ };
+ this.size = function() {
+ return array.length
+ };
+ this.clear = function() {
+ array.length = 0
+ };
+ this.remove = function(item) {
+ if (typeof item === "number") return array.splice(item, 1)[0];
+ item = this.indexOf(item);
+ if (item > -1) {
+ array.splice(item, 1);
+ return true
+ }
+ return false
+ };
+ this.isEmpty = function() {
+ return !array.length
+ };
+ this.clone = function() {
+ return new ArrayList(this)
+ };
+ this.toArray = function() {
+ return array.slice(0)
+ };
+ this.iterator = function() {
+ return new Iterator(array)
+ }
+ }
+ return ArrayList
+ }();
+ var HashMap = function() {
+ function HashMap() {
+ if (arguments.length === 1 && arguments[0] instanceof HashMap) return arguments[0].clone();
+ var initialCapacity = arguments.length > 0 ? arguments[0] : 16;
+ var loadFactor = arguments.length > 1 ? arguments[1] : 0.75;
+ var buckets = [];
+ buckets.length = initialCapacity;
+ var count = 0;
+ var hashMap = this;
+
+ function getBucketIndex(key) {
+ var index = virtHashCode(key) % buckets.length;
+ return index < 0 ? buckets.length + index : index
+ }
+ function ensureLoad() {
+ if (count <= loadFactor * buckets.length) return;
+ var allEntries = [];
+ for (var i = 0; i < buckets.length; ++i) if (buckets[i] !== undef) allEntries = allEntries.concat(buckets[i]);
+ var newBucketsLength = buckets.length * 2;
+ buckets = [];
+ buckets.length = newBucketsLength;
+ for (var j = 0; j < allEntries.length; ++j) {
+ var index = getBucketIndex(allEntries[j].key);
+ var bucket = buckets[index];
+ if (bucket === undef) 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 (buckets[bucketIndex] === undef || 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;
+ return true
+ };
+ this.isEmpty = function() {
+ return hashMap.isEmpty()
+ };
+ this.iterator = function() {
+ return new Iterator(conversion, removeItem)
+ };
+ this.remove = function(o) {
+ if (this.contains(o)) {
+ removeItem(o);
+ return true
+ }
+ return false
+ };
+ this.removeAll = function(c) {
+ var it = c.iterator();
+ var changed = false;
+ while (it.hasNext()) {
+ var item = it.next();
+ if (this.contains(item)) {
+ removeItem(item);
+ changed = true
+ }
+ }
+ return true
+ };
+ this.retainAll = function(c) {
+ var it = this.iterator();
+ var toRemove = [];
+ while (it.hasNext()) {
+ var entry = it.next();
+ if (!c.contains(entry)) toRemove.push(entry)
+ }
+ for (var i = 0; i < toRemove.length; ++i) removeItem(toRemove[i]);
+ return toRemove.length > 0
+ };
+ this.size = function() {
+ return hashMap.size()
+ };
+ this.toArray = function() {
+ var result = [];
+ var it = this.iterator();
+ while (it.hasNext()) result.push(it.next());
+ return result
+ }
+ }
+ function Entry(pair) {
+ this._isIn = function(map) {
+ return map === hashMap && pair.removed === undef
+ };
+ this.equals = function(o) {
+ return virtEquals(pair.key, o.getKey())
+ };
+ this.getKey = function() {
+ return pair.key
+ };
+ this.getValue = function() {
+ return pair.value
+ };
+ this.hashCode = function(o) {
+ return virtHashCode(pair.key)
+ };
+ this.setValue = function(value) {
+ var old = pair.value;
+ pair.value = value;
+ return old
+ }
+ }
+ this.clear = function() {
+ count = 0;
+ buckets = [];
+ buckets.length = initialCapacity
+ };
+ this.clone = function() {
+ var map = new HashMap;
+ map.putAll(this);
+ return map
+ };
+ this.containsKey = function(key) {
+ var index = getBucketIndex(key);
+ var bucket = buckets[index];
+ if (bucket === undef) return false;
+ for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) return true;
+ return false
+ };
+ this.containsValue = function(value) {
+ for (var i = 0; i < buckets.length; ++i) {
+ var bucket = buckets[i];
+ if (bucket === undef) continue;
+ for (var j = 0; j < bucket.length; ++j) if (virtEquals(bucket[j].value, value)) return true
+ }
+ return false
+ };
+ this.entrySet = function() {
+ return new Set(function(pair) {
+ return new Entry(pair)
+ },
+
+
+ function(pair) {
+ return pair instanceof Entry && pair._isIn(hashMap)
+ },
+
+
+ function(pair) {
+ return hashMap.remove(pair.getKey())
+ })
+ };
+ this.get = function(key) {
+ var index = getBucketIndex(key);
+ var bucket = buckets[index];
+ if (bucket === undef) return null;
+ for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) return bucket[i].value;
+ return null
+ };
+ this.isEmpty = function() {
+ return count === 0
+ };
+ this.keySet = function() {
+ return new Set(function(pair) {
+ return pair.key
+ },
+
+
+ function(key) {
+ return hashMap.containsKey(key)
+ },
+
+
+ function(key) {
+ return hashMap.remove(key)
+ })
+ };
+ this.values = function() {
+ return new Set(function(pair) {
+ return pair.value
+ },
+
+
+ function(value) {
+ return hashMap.containsValue(value)
+ },
+
+ function(value) {
+ return hashMap.removeByValue(value)
+ })
+ };
+ this.put = function(key, value) {
+ var index = getBucketIndex(key);
+ var bucket = buckets[index];
+ if (bucket === undef) {
+ ++count;
+ buckets[index] = [{
+ key: key,
+ value: value
+ }];
+ ensureLoad();
+ return null
+ }
+ for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) {
+ var previous = bucket[i].value;
+ bucket[i].value = value;
+ return previous
+ }++count;
+ bucket.push({
+ key: key,
+ value: value
+ });
+ ensureLoad();
+ return null
+ };
+ this.putAll = function(m) {
+ var it = m.entrySet().iterator();
+ while (it.hasNext()) {
+ var entry = it.next();
+ this.put(entry.getKey(), entry.getValue())
+ }
+ };
+ this.remove = function(key) {
+ var index = getBucketIndex(key);
+ var bucket = buckets[index];
+ if (bucket === undef) return null;
+ for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) {
+ --count;
+ var previous = bucket[i].value;
+ bucket[i].removed = true;
+ if (bucket.length > 1) bucket.splice(i, 1);
+ else buckets[index] = undef;
+ return previous
+ }
+ return null
+ };
+ this.removeByValue = function(value) {
+ var bucket, i, ilen, pair;
+ for (bucket in buckets) if (buckets.hasOwnProperty(bucket)) for (i = 0, ilen = buckets[bucket].length; i < ilen; i++) {
+ pair = buckets[bucket][i];
+ if (pair.value === value) {
+ buckets[bucket].splice(i, 1);
+ return true
+ }
+ }
+ return false
+ };
+ this.size = function() {
+ return count
+ }
+ }
+ return HashMap
+ }();
+ var PVector = function() {
+ function PVector(x, y, z) {
+ this.x = x || 0;
+ this.y = y || 0;
+ this.z = z || 0
+ }
+ PVector.dist = function(v1, v2) {
+ return v1.dist(v2)
+ };
+ PVector.dot = function(v1, v2) {
+ return v1.dot(v2)
+ };
+ PVector.cross = function(v1, v2) {
+ return v1.cross(v2)
+ };
+ PVector.angleBetween = function(v1, v2) {
+ return Math.acos(v1.dot(v2) / (v1.mag() * v2.mag()))
+ };
+ PVector.prototype = {
+ set: function(v, y, z) {
+ if (arguments.length === 1) this.set(v.x || v[0] || 0, v.y || v[1] || 0, v.z || v[2] || 0);
+ else {
+ this.x = v;
+ this.y = y;
+ this.z = z
+ }
+ },
+ get: function() {
+ return new PVector(this.x, this.y, this.z)
+ },
+ mag: function() {
+ var x = this.x,
+ y = this.y,
+ z = this.z;
+ return Math.sqrt(x * x + y * y + z * z)
+ },
+ add: function(v, y, z) {
+ if (arguments.length === 1) {
+ this.x += v.x;
+ this.y += v.y;
+ this.z += v.z
+ } else {
+ this.x += v;
+ this.y += y;
+ this.z += z
+ }
+ },
+ sub: function(v, y, z) {
+ if (arguments.length === 1) {
+ this.x -= v.x;
+ this.y -= v.y;
+ this.z -= v.z
+ } else {
+ this.x -= v;
+ this.y -= y;
+ this.z -= z
+ }
+ },
+ mult: function(v) {
+ if (typeof v === "number") {
+ this.x *= v;
+ this.y *= v;
+ this.z *= v
+ } else {
+ 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 {
+ 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) {
+ if (arguments.length === 1) return this.x * v.x + this.y * v.y + this.z * v.z;
+ return this.x * v + this.y * y + this.z * z
+ },
+ cross: function(v) {
+ var x = this.x,
+ y = this.y,
+ z = this.z;
+ return new PVector(y * v.z - v.y * z, z * v.x - v.z * x, x * v.y - v.x * y)
+ },
+ 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() {
+ return -Math.atan2(-this.y, this.x)
+ },
+ toString: function() {
+ return "[" + this.x + ", " + this.y + ", " + this.z + "]"
+ },
+ array: function() {
+ return [this.x, this.y, this.z]
+ }
+ };
+
+ function createPVectorMethod(method) {
+ return function(v1, v2) {
+ var v = v1.get();
+ v[method](v2);
+ return v
+ }
+ }
+ for (var method in PVector.prototype) if (PVector.prototype.hasOwnProperty(method) && !PVector.hasOwnProperty(method)) PVector[method] = createPVectorMethod(method);
+ return PVector
+ }();
+
+ function DefaultScope() {}
+ DefaultScope.prototype = PConstants;
+ var defaultScope = new DefaultScope;
+ defaultScope.ArrayList = ArrayList;
+ defaultScope.HashMap = HashMap;
+ defaultScope.PVector = PVector;
+ defaultScope.ObjectIterator = ObjectIterator;
+ defaultScope.PConstants = PConstants;
+ defaultScope.defineProperty = function(obj, name, desc) {
+ if ("defineProperty" in Object) Object.defineProperty(obj, name, desc);
+ else {
+ if (desc.hasOwnProperty("get")) obj.__defineGetter__(name, desc.get);
+ if (desc.hasOwnProperty("set")) obj.__defineSetter__(name, desc.set)
+ }
+ };
+
+ function extendClass(subClass, baseClass) {
+ function extendGetterSetter(propertyName) {
+ defaultScope.defineProperty(subClass, propertyName, {
+ get: function() {
+ return baseClass[propertyName]
+ },
+ set: function(v) {
+ baseClass[propertyName] = v
+ },
+ enumerable: true
+ })
+ }
+ var properties = [];
+ for (var propertyName in baseClass) if (typeof baseClass[propertyName] === "function") {
+ if (!subClass.hasOwnProperty(propertyName)) subClass[propertyName] = baseClass[propertyName]
+ } else if (propertyName.charAt(0) !== "$" && !(propertyName in subClass)) properties.push(propertyName);
+ while (properties.length > 0) extendGetterSetter(properties.shift())
+ }
+ defaultScope.extendClassChain = function(base) {
+ var path = [base];
+ for (var self = base.$upcast; self; self = self.$upcast) {
+ extendClass(self, base);
+ path.push(self);
+ base = self
+ }
+ while (path.length > 0) path.pop().$self = base
+ };
+ defaultScope.extendStaticMembers = function(derived, base) {
+ extendClass(derived, base)
+ };
+ defaultScope.extendInterfaceMembers = function(derived, base) {
+ extendClass(derived, base)
+ };
+ defaultScope.addMethod = function(object, name, fn, superAccessor) {
+ if (object[name]) {
+ var args = fn.length,
+ oldfn = object[name];
+ object[name] = function() {
+ if (arguments.length === args) return fn.apply(this, arguments);
+ return oldfn.apply(this, arguments)
+ }
+ } else object[name] = fn
+ };
+ defaultScope.createJavaArray = function(type, bounds) {
+ var result = null;
+ if (typeof bounds[0] === "number") {
+ var itemsCount = 0 | bounds[0];
+ if (bounds.length <= 1) {
+ result = [];
+ result.length = itemsCount;
+ for (var i = 0; i < itemsCount; ++i) result[i] = 0
+ } else {
+ result = [];
+ var newBounds = bounds.slice(1);
+ for (var j = 0; j < itemsCount; ++j) result.push(defaultScope.createJavaArray(type, newBounds))
+ }
+ }
+ return result
+ };
+ var colors = {
+ aliceblue: "#f0f8ff",
+ antiquewhite: "#faebd7",
+ aqua: "#00ffff",
+ aquamarine: "#7fffd4",
+ azure: "#f0ffff",
+ beige: "#f5f5dc",
+ bisque: "#ffe4c4",
+ black: "#000000",
+ blanchedalmond: "#ffebcd",
+ blue: "#0000ff",
+ blueviolet: "#8a2be2",
+ brown: "#a52a2a",
+ burlywood: "#deb887",
+ cadetblue: "#5f9ea0",
+ chartreuse: "#7fff00",
+ chocolate: "#d2691e",
+ coral: "#ff7f50",
+ cornflowerblue: "#6495ed",
+ cornsilk: "#fff8dc",
+ crimson: "#dc143c",
+ cyan: "#00ffff",
+ darkblue: "#00008b",
+ darkcyan: "#008b8b",
+ darkgoldenrod: "#b8860b",
+ darkgray: "#a9a9a9",
+ darkgreen: "#006400",
+ darkkhaki: "#bdb76b",
+ darkmagenta: "#8b008b",
+ darkolivegreen: "#556b2f",
+ darkorange: "#ff8c00",
+ darkorchid: "#9932cc",
+ darkred: "#8b0000",
+ darksalmon: "#e9967a",
+ darkseagreen: "#8fbc8f",
+ darkslateblue: "#483d8b",
+ darkslategray: "#2f4f4f",
+ darkturquoise: "#00ced1",
+ darkviolet: "#9400d3",
+ deeppink: "#ff1493",
+ deepskyblue: "#00bfff",
+ dimgray: "#696969",
+ dodgerblue: "#1e90ff",
+ firebrick: "#b22222",
+ floralwhite: "#fffaf0",
+ forestgreen: "#228b22",
+ fuchsia: "#ff00ff",
+ gainsboro: "#dcdcdc",
+ ghostwhite: "#f8f8ff",
+ gold: "#ffd700",
+ goldenrod: "#daa520",
+ gray: "#808080",
+ green: "#008000",
+ greenyellow: "#adff2f",
+ honeydew: "#f0fff0",
+ hotpink: "#ff69b4",
+ indianred: "#cd5c5c",
+ indigo: "#4b0082",
+ ivory: "#fffff0",
+ khaki: "#f0e68c",
+ lavender: "#e6e6fa",
+ lavenderblush: "#fff0f5",
+ lawngreen: "#7cfc00",
+ lemonchiffon: "#fffacd",
+ lightblue: "#add8e6",
+ lightcoral: "#f08080",
+ lightcyan: "#e0ffff",
+ lightgoldenrodyellow: "#fafad2",
+ lightgrey: "#d3d3d3",
+ lightgreen: "#90ee90",
+ lightpink: "#ffb6c1",
+ lightsalmon: "#ffa07a",
+ lightseagreen: "#20b2aa",
+ lightskyblue: "#87cefa",
+ lightslategray: "#778899",
+ lightsteelblue: "#b0c4de",
+ lightyellow: "#ffffe0",
+ lime: "#00ff00",
+ limegreen: "#32cd32",
+ linen: "#faf0e6",
+ magenta: "#ff00ff",
+ maroon: "#800000",
+ mediumaquamarine: "#66cdaa",
+ mediumblue: "#0000cd",
+ mediumorchid: "#ba55d3",
+ mediumpurple: "#9370d8",
+ mediumseagreen: "#3cb371",
+ mediumslateblue: "#7b68ee",
+ mediumspringgreen: "#00fa9a",
+ mediumturquoise: "#48d1cc",
+ mediumvioletred: "#c71585",
+ midnightblue: "#191970",
+ mintcream: "#f5fffa",
+ mistyrose: "#ffe4e1",
+ moccasin: "#ffe4b5",
+ navajowhite: "#ffdead",
+ navy: "#000080",
+ oldlace: "#fdf5e6",
+ olive: "#808000",
+ olivedrab: "#6b8e23",
+ orange: "#ffa500",
+ orangered: "#ff4500",
+ orchid: "#da70d6",
+ palegoldenrod: "#eee8aa",
+ palegreen: "#98fb98",
+ paleturquoise: "#afeeee",
+ palevioletred: "#d87093",
+ papayawhip: "#ffefd5",
+ peachpuff: "#ffdab9",
+ peru: "#cd853f",
+ pink: "#ffc0cb",
+ plum: "#dda0dd",
+ powderblue: "#b0e0e6",
+ purple: "#800080",
+ red: "#ff0000",
+ rosybrown: "#bc8f8f",
+ royalblue: "#4169e1",
+ saddlebrown: "#8b4513",
+ salmon: "#fa8072",
+ sandybrown: "#f4a460",
+ seagreen: "#2e8b57",
+ seashell: "#fff5ee",
+ sienna: "#a0522d",
+ silver: "#c0c0c0",
+ skyblue: "#87ceeb",
+ slateblue: "#6a5acd",
+ slategray: "#708090",
+ snow: "#fffafa",
+ springgreen: "#00ff7f",
+ steelblue: "#4682b4",
+ tan: "#d2b48c",
+ teal: "#008080",
+ thistle: "#d8bfd8",
+ tomato: "#ff6347",
+ turquoise: "#40e0d0",
+ violet: "#ee82ee",
+ wheat: "#f5deb3",
+ white: "#ffffff",
+ whitesmoke: "#f5f5f5",
+ yellow: "#ffff00",
+ yellowgreen: "#9acd32"
+ };
+ (function(Processing) {
+ var unsupportedP5 = ("open() createOutput() createInput() BufferedReader selectFolder() " + "dataPath() createWriter() selectOutput() beginRecord() " + "saveStream() endRecord() selectInput() saveBytes() createReader() " + "beginRaw() endRaw() PrintWriter delay()").split(" "),
+ count = unsupportedP5.length,
+ prettyName, p5Name;
+
+ function createUnsupportedFunc(n) {
+ return function() {
+ throw "Processing.js does not support " + n + ".";
+ }
+ }
+ while (count--) {
+ prettyName = unsupportedP5[count];
+ p5Name = prettyName.replace("()", "");
+ Processing[p5Name] = createUnsupportedFunc(prettyName)
+ }
+ })(defaultScope);
+ defaultScope.defineProperty(defaultScope, "screenWidth", {
+ get: function() {
+ return window.innerWidth
+ }
+ });
+ defaultScope.defineProperty(defaultScope, "screenHeight", {
+ get: function() {
+ return window.innerHeight
+ }
+ });
+ var processingInstances = [];
+ var processingInstanceIds = {};
+ var removeInstance = function(id) {
+ processingInstances.splice(processingInstanceIds[id], 1);
+ delete processingInstanceIds[id]
+ };
+ var addInstance = function(processing) {
+ if (processing.externals.canvas.id === undef || !processing.externals.canvas.id.length) processing.externals.canvas.id = "__processing" + processingInstances.length;
+ processingInstanceIds[processing.externals.canvas.id] = processingInstances.length;
+ processingInstances.push(processing)
+ };
+
+ function computeFontMetrics(pfont) {
+ var emQuad = 250,
+ correctionFactor = pfont.size / emQuad,
+ canvas = document.createElement("canvas");
+ canvas.width = 2 * emQuad;
+ canvas.height = 2 * emQuad;
+ canvas.style.opacity = 0;
+ var cfmFont = pfont.getCSSDefinition(emQuad + "px", "normal"),
+ ctx = canvas.getContext("2d");
+ ctx.font = cfmFont;
+ pfont.context2d = ctx;
+ var protrusions = "dbflkhyjqpg";
+ canvas.width = ctx.measureText(protrusions).width;
+ ctx.font = cfmFont;
+ var leadDiv = document.createElement("div");
+ leadDiv.style.position = "absolute";
+ leadDiv.style.opacity = 0;
+ leadDiv.style.fontFamily = '"' + pfont.name + '"';
+ leadDiv.style.fontSize = emQuad + "px";
+ leadDiv.innerHTML = protrusions + "
" + protrusions;
+ document.body.appendChild(leadDiv);
+ var w = canvas.width,
+ h = canvas.height,
+ baseline = h / 2;
+ ctx.fillStyle = "white";
+ ctx.fillRect(0, 0, w, h);
+ ctx.fillStyle = "black";
+ ctx.fillText(protrusions, 0, baseline);
+ var pixelData = ctx.getImageData(0, 0, w, h).data;
+ var i = 0,
+ w4 = w * 4,
+ len = pixelData.length;
+ while (++i < len && pixelData[i] === 255) nop();
+ var ascent = Math.round(i / w4);
+ i = len - 1;
+ while (--i > 0 && pixelData[i] === 255) nop();
+ var descent = Math.round(i / w4);
+ pfont.ascent = correctionFactor * (baseline - ascent);
+ pfont.descent = correctionFactor * (descent - baseline);
+ if (document.defaultView.getComputedStyle) {
+ var leadDivHeight = document.defaultView.getComputedStyle(leadDiv, null).getPropertyValue("height");
+ leadDivHeight = correctionFactor * leadDivHeight.replace("px", "");
+ if (leadDivHeight >= pfont.size * 2) pfont.leading = Math.round(leadDivHeight / 2)
+ }
+ document.body.removeChild(leadDiv)
+ }
+ function PFont(name, size) {
+ if (name === undef) name = "";
+ this.name = name;
+ if (size === undef) size = 0;
+ this.size = size;
+ this.glyph = false;
+ this.ascent = 0;
+ this.descent = 0;
+ this.leading = 1.2 * size;
+ var illegalIndicator = name.indexOf(" Italic Bold");
+ if (illegalIndicator !== -1) name = name.substring(0, illegalIndicator);
+ this.style = "normal";
+ var italicsIndicator = name.indexOf(" Italic");
+ if (italicsIndicator !== -1) {
+ name = name.substring(0, italicsIndicator);
+ this.style = "italic"
+ }
+ this.weight = "normal";
+ var boldIndicator = name.indexOf(" Bold");
+ if (boldIndicator !== -1) {
+ name = name.substring(0, boldIndicator);
+ this.weight = "bold"
+ }
+ this.family = "sans-serif";
+ if (name !== undef) switch (name) {
+ case "sans-serif":
+ case "serif":
+ case "monospace":
+ case "fantasy":
+ case "cursive":
+ this.family = name;
+ break;
+ default:
+ this.family = '"' + name + '", sans-serif';
+ break
+ }
+ this.context2d = null;
+ computeFontMetrics(this);
+ this.css = this.getCSSDefinition();
+ this.context2d.font = this.css
+ }
+ PFont.prototype.getCSSDefinition = function(fontSize, lineHeight) {
+ if (fontSize === undef) fontSize = this.size + "px";
+ if (lineHeight === undef) lineHeight = this.leading + "px";
+ var components = [this.style, "normal", this.weight, fontSize + "/" + lineHeight, this.family];
+ return components.join(" ")
+ };
+ PFont.prototype.measureTextWidth = function(string) {
+ return this.context2d.measureText(string).width
+ };
+ PFont.PFontCache = {};
+ PFont.get = function(fontName, fontSize) {
+ var cache = PFont.PFontCache;
+ var idx = fontName + "/" + fontSize;
+ if (!cache[idx]) cache[idx] = new PFont(fontName, fontSize);
+ return cache[idx]
+ };
+ PFont.list = function() {
+ return ["sans-serif", "serif", "monospace", "fantasy", "cursive"]
+ };
+ PFont.preloading = {
+ template: {},
+ initialized: false,
+ initialize: function() {
+ var generateTinyFont = function() {
+ var encoded = "#E3KAI2wAgT1MvMg7Eo3VmNtYX7ABi3CxnbHlm" + "7Abw3kaGVhZ7ACs3OGhoZWE7A53CRobXR47AY3" + "AGbG9jYQ7G03Bm1heH7ABC3CBuYW1l7Ae3AgcG" + "9zd7AI3AE#B3AQ2kgTY18PPPUACwAg3ALSRoo3" + "#yld0xg32QAB77#E777773B#E3C#I#Q77773E#" + "Q7777777772CMAIw7AB77732B#M#Q3wAB#g3B#" + "E#E2BB//82BB////w#B7#gAEg3E77x2B32B#E#" + "Q#MTcBAQ32gAe#M#QQJ#E32M#QQJ#I#g32Q77#";
+ var expand = function(input) {
+ return "AAAAAAAA".substr(~~input ? 7 - input : 6)
+ };
+ return encoded.replace(/[#237]/g, expand)
+ };
+ var fontface = document.createElement("style");
+ fontface.setAttribute("type", "text/css");
+ fontface.innerHTML = "@font-face {\n" + ' font-family: "PjsEmptyFont";' + "\n" + " src: url('data:application/x-font-ttf;base64," + generateTinyFont() + "')\n" + " format('truetype');\n" + "}";
+ document.head.appendChild(fontface);
+ var element = document.createElement("span");
+ element.style.cssText = 'position: absolute; top: 0; left: 0; opacity: 0; font-family: "PjsEmptyFont", fantasy;';
+ element.innerHTML = "AAAAAAAA";
+ document.body.appendChild(element);
+ this.template = element;
+ this.initialized = true
+ },
+ getElementWidth: function(element) {
+ return document.defaultView.getComputedStyle(element, "").getPropertyValue("width")
+ },
+ timeAttempted: 0,
+ pending: function(intervallength) {
+ if (!this.initialized) this.initialize();
+ var element, computedWidthFont, computedWidthRef = this.getElementWidth(this.template);
+ for (var i = 0; i < this.fontList.length; i++) {
+ element = this.fontList[i];
+ computedWidthFont = this.getElementWidth(element);
+ if (this.timeAttempted < 4E3 && computedWidthFont === computedWidthRef) {
+ this.timeAttempted += intervallength;
+ return true
+ } else {
+ document.body.removeChild(element);
+ this.fontList.splice(i--, 1);
+ this.timeAttempted = 0
+ }
+ }
+ if (this.fontList.length === 0) return false;
+ return true
+ },
+ fontList: [],
+ addedList: {},
+ add: function(fontSrc) {
+ if (!this.initialized) this.initialize();
+ var fontName = typeof fontSrc === "object" ? fontSrc.fontFace : fontSrc,
+ fontUrl = typeof fontSrc === "object" ? fontSrc.url : fontSrc;
+ if (this.addedList[fontName]) return;
+ var style = document.createElement("style");
+ style.setAttribute("type", "text/css");
+ style.innerHTML = "@font-face{\n font-family: '" + fontName + "';\n src: url('" + fontUrl + "');\n}\n";
+ document.head.appendChild(style);
+ this.addedList[fontName] = true;
+ var element = document.createElement("span");
+ element.style.cssText = "position: absolute; top: 0; left: 0; opacity: 0;";
+ element.style.fontFamily = '"' + fontName + '", "PjsEmptyFont", fantasy';
+ element.innerHTML = "AAAAAAAA";
+ document.body.appendChild(element);
+ this.fontList.push(element)
+ }
+ };
+ defaultScope.PFont = PFont;
+ var Processing = this.Processing = function(aCanvas, aCode) {
+ if (! (this instanceof Processing)) throw "called Processing constructor as if it were a function: missing 'new'.";
+ var curElement, pgraphicsMode = aCanvas === undef && aCode === undef;
+ if (pgraphicsMode) curElement = document.createElement("canvas");
+ else curElement = typeof aCanvas === "string" ? document.getElementById(aCanvas) : aCanvas;
+ if (! (curElement instanceof HTMLCanvasElement)) throw "called Processing constructor without passing canvas element reference or id.";
+
+ function unimplemented(s) {
+ Processing.debug("Unimplemented - " + s)
+ }
+ var p = this;
+ p.externals = {
+ canvas: curElement,
+ context: undef,
+ sketch: undef
+ };
+ p.name = "Processing.js Instance";
+ p.use3DContext = false;
+ p.focused = false;
+ p.breakShape = false;
+ p.glyphTable = {};
+ p.pmouseX = 0;
+ p.pmouseY = 0;
+ p.mouseX = 0;
+ p.mouseY = 0;
+ p.mouseButton = 0;
+ p.mouseScroll = 0;
+ p.mouseClicked = undef;
+ p.mouseDragged = undef;
+ p.mouseMoved = undef;
+ p.mousePressed = undef;
+ p.mouseReleased = undef;
+ p.mouseScrolled = undef;
+ p.mouseOver = undef;
+ p.mouseOut = undef;
+ p.touchStart = undef;
+ p.touchEnd = undef;
+ p.touchMove = undef;
+ p.touchCancel = undef;
+ p.key = undef;
+ p.keyCode = undef;
+ p.keyPressed = nop;
+ p.keyReleased = nop;
+ p.keyTyped = nop;
+ p.draw = undef;
+ p.setup = undef;
+ p.__mousePressed = false;
+ p.__keyPressed = false;
+ p.__frameRate = 60;
+ p.frameCount = 0;
+ p.width = 100;
+ p.height = 100;
+ var curContext, curSketch, drawing, online = true,
+ doFill = true,
+ fillStyle = [1, 1, 1, 1],
+ currentFillColor = 4294967295,
+ isFillDirty = true,
+ doStroke = true,
+ strokeStyle = [0, 0, 0, 1],
+ currentStrokeColor = 4278190080,
+ isStrokeDirty = true,
+ lineWidth = 1,
+ loopStarted = false,
+ renderSmooth = false,
+ doLoop = true,
+ looping = 0,
+ curRectMode = 0,
+ curEllipseMode = 3,
+ normalX = 0,
+ normalY = 0,
+ normalZ = 0,
+ normalMode = 0,
+ curFrameRate = 60,
+ curMsPerFrame = 1E3 / curFrameRate,
+ curCursor = 'default',
+ oldCursor = curElement.style.cursor,
+ curShape = 20,
+ curShapeCount = 0,
+ curvePoints = [],
+ curTightness = 0,
+ curveDet = 20,
+ curveInited = false,
+ backgroundObj = -3355444,
+ bezDetail = 20,
+ colorModeA = 255,
+ colorModeX = 255,
+ colorModeY = 255,
+ colorModeZ = 255,
+ pathOpen = false,
+ mouseDragging = false,
+ pmouseXLastFrame = 0,
+ pmouseYLastFrame = 0,
+ curColorMode = 1,
+ curTint = null,
+ curTint3d = null,
+ getLoaded = false,
+ start = Date.now(),
+ timeSinceLastFPS = start,
+ framesSinceLastFPS = 0,
+ textcanvas, curveBasisMatrix, curveToBezierMatrix, curveDrawMatrix, bezierDrawMatrix, bezierBasisInverse, bezierBasisMatrix, curContextCache = {
+ attributes: {},
+ locations: {}
+ },
+ programObject3D, programObject2D, programObjectUnlitShape, boxBuffer, boxNormBuffer, boxOutlineBuffer, rectBuffer, rectNormBuffer, sphereBuffer, lineBuffer, fillBuffer, fillColorBuffer, strokeColorBuffer, pointBuffer, shapeTexVBO, canTex, textTex, curTexture = {
+ width: 0,
+ height: 0
+ },
+ curTextureMode = 2,
+ usingTexture = false,
+ textBuffer, textureBuffer, indexBuffer, horizontalTextAlignment = 37,
+ verticalTextAlignment = 0,
+ textMode = 4,
+ curFontName = "Arial",
+ curTextSize = 12,
+ curTextAscent = 9,
+ curTextDescent = 2,
+ curTextLeading = 14,
+ curTextFont = PFont.get(curFontName, curTextSize),
+ originalContext, proxyContext = null,
+ isContextReplaced = false,
+ setPixelsCached, maxPixelsCached = 1E3,
+ pressedKeysMap = [],
+ lastPressedKeyCode = null,
+ codedKeys = [16, 17, 18, 20, 33, 34, 35, 36, 37, 38, 39, 40, 144, 155, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 157];
+ var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop;
+ if (document.defaultView && document.defaultView.getComputedStyle) {
+ stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(curElement, null)["paddingLeft"], 10) || 0;
+ stylePaddingTop = parseInt(document.defaultView.getComputedStyle(curElement, null)["paddingTop"], 10) || 0;
+ styleBorderLeft = parseInt(document.defaultView.getComputedStyle(curElement, null)["borderLeftWidth"], 10) || 0;
+ styleBorderTop = parseInt(document.defaultView.getComputedStyle(curElement, null)["borderTopWidth"], 10) || 0
+ }
+ var lightCount = 0;
+ var sphereDetailV = 0,
+ sphereDetailU = 0,
+ sphereX = [],
+ sphereY = [],
+ sphereZ = [],
+ sinLUT = new Float32Array(720),
+ cosLUT = new Float32Array(720),
+ sphereVerts, sphereNorms;
+ var cam, cameraInv, modelView, modelViewInv, userMatrixStack, userReverseMatrixStack, inverseCopy, projection, manipulatingCamera = false,
+ frustumMode = false,
+ cameraFOV = 60 * (Math.PI / 180),
+ cameraX = p.width / 2,
+ cameraY = p.height / 2,
+ cameraZ = cameraY / Math.tan(cameraFOV / 2),
+ cameraNear = cameraZ / 10,
+ cameraFar = cameraZ * 10,
+ cameraAspect = p.width / p.height;
+ var vertArray = [],
+ curveVertArray = [],
+ curveVertCount = 0,
+ isCurve = false,
+ isBezier = false,
+ firstVert = true;
+ var curShapeMode = 0;
+ var styleArray = [];
+ var boxVerts = new Float32Array([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 boxOutlineVerts = new Float32Array([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 = new Float32Array([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 rectVerts = new Float32Array([0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0]);
+ var rectNorms = new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]);
+ var vShaderSrcUnlitShape = "varying vec4 frontColor;" + "attribute vec3 aVertex;" + "attribute vec4 aColor;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform float pointSize;" + "void main(void) {" + " frontColor = aColor;" + " gl_PointSize = pointSize;" + " gl_Position = uProjection * uView * vec4(aVertex, 1.0);" + "}";
+ var fShaderSrcUnlitShape = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 frontColor;" + "void main(void){" + " gl_FragColor = frontColor;" + "}";
+ var vertexShaderSource2D = "varying vec4 frontColor;" + "attribute vec3 Vertex;" + "attribute vec2 aTextureCoord;" + "uniform vec4 color;" + "uniform mat4 model;" + "uniform mat4 view;" + "uniform mat4 projection;" + "uniform float pointSize;" + "varying vec2 vTextureCoord;" + "void main(void) {" + " gl_PointSize = pointSize;" + " frontColor = color;" + " gl_Position = projection * view * model * vec4(Vertex, 1.0);" + " vTextureCoord = aTextureCoord;" + "}";
+ var fragmentShaderSource2D = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 frontColor;" + "varying vec2 vTextureCoord;" + "uniform sampler2D uSampler;" + "uniform int picktype;" + "void main(void){" + " if(picktype == 0){" + " gl_FragColor = frontColor;" + " }" + " else if(picktype == 1){" + " float alpha = texture2D(uSampler, vTextureCoord).a;" + " gl_FragColor = vec4(frontColor.rgb*alpha, alpha);\n" + " }" + "}";
+ var webglMaxTempsWorkaround = /Windows/.test(navigator.userAgent);
+ var vertexShaderSource3D = "varying vec4 frontColor;" + "attribute vec3 Vertex;" + "attribute vec3 Normal;" + "attribute vec4 aColor;" + "attribute vec2 aTexture;" + "varying vec2 vTexture;" + "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 {" + " int type;" + " vec3 color;" + " vec3 position;" + " vec3 direction;" + " float angle;" + " vec3 halfVector;" + " float concentration;" + "};" + "uniform Light lights0;" + "uniform Light lights1;" + "uniform Light lights2;" + "uniform Light lights3;" + "uniform Light lights4;" + "uniform Light lights5;" + "uniform Light lights6;" + "uniform Light lights7;" + "Light getLight(int index){" + " if(index == 0) return lights0;" + " if(index == 1) return lights1;" + " if(index == 2) return lights2;" + " if(index == 3) return lights3;" + " if(index == 4) return lights4;" + " if(index == 5) return lights5;" + " if(index == 6) return lights6;" + " return lights7;" + "}" + "void AmbientLight( inout vec3 totalAmbient, in vec3 ecPos, in Light light ) {" + " 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, inout vec3 spec, in vec3 vertNormal, in vec3 ecPos, in Light light ) {" + " float powerfactor = 0.0;" + " float nDotVP = max(0.0, dot( vertNormal, normalize(-light.position) ));" + " float nDotVH = max(0.0, dot( vertNormal, normalize(-light.position-normalize(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 Light light ) {" + " float powerfactor;" + " vec3 VP = light.position - ecPos;" + " float d = length( VP ); " + " 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 - normalize(ecPos) );" + " 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 Light light ) {" + " float spotAttenuation;" + " float powerfactor;" + " vec3 VP = light.position - ecPos; " + " vec3 ldir = normalize( -light.direction );" + " float d = length( VP );" + " VP = normalize( VP );" + " float attenuation = 1.0 / ( falloff[0] + ( falloff[1] * d ) + ( falloff[2] * d * d ) );" + " float spotDot = dot( VP, ldir );" + (webglMaxTempsWorkaround ? " spotAttenuation = 1.0; " : " if( spotDot > cos( light.angle ) ) {" + " spotAttenuation = pow( spotDot, light.concentration );" + " }" + " else{" + " spotAttenuation = 0.0;" + " }" + " attenuation *= spotAttenuation;" + "") + " float nDotVP = max( 0.0, dot( vertNormal, VP ));" + " vec3 halfVector = normalize( VP - normalize(ecPos) );" + " 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 );" + " vec4 col = color;" + " if(color[0] == -1.0){" + " col = aColor;" + " }" + " vec3 norm = normalize(vec3( normalTransform * vec4( Normal, 0.0 ) ));" + " vec4 ecPos4 = view * model * vec4(Vertex,1.0);" + " vec3 ecPos = (vec3(ecPos4))/ecPos4.w;" + " if( lightCount == 0 ) {" + " frontColor = col + vec4(mat_specular,1.0);" + " }" + " else {" + " for( int i = 0; i < 8; i++ ) {" + " Light l = getLight(i);" + " if( i >= lightCount ){" + " break;" + " }" + " if( l.type == 0 ) {" + " AmbientLight( finalAmbient, ecPos, l );" + " }" + " else if( l.type == 1 ) {" + " DirectionalLight( finalDiffuse, finalSpecular, norm, ecPos, l );" + " }" + " else if( l.type == 2 ) {" + " PointLight( finalDiffuse, finalSpecular, norm, ecPos, l );" + " }" + " else {" + " SpotLight( finalDiffuse, finalSpecular, norm, ecPos, l );" + " }" + " }" + " if( usingMat == false ) {" + " frontColor = vec4(" + " vec3(col) * finalAmbient +" + " vec3(col) * finalDiffuse +" + " vec3(col) * finalSpecular," + " col[3] );" + " }" + " else{" + " frontColor = vec4( " + " mat_emissive + " + " (vec3(col) * mat_ambient * finalAmbient) + " + " (vec3(col) * finalDiffuse) + " + " (mat_specular * finalSpecular), " + " col[3] );" + " }" + " }" + " vTexture.xy = aTexture.xy;" + " gl_Position = projection * view * model * vec4( Vertex, 1.0 );" + "}";
+ var fragmentShaderSource3D = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 frontColor;" + "uniform sampler2D sampler;" + "uniform bool usingTexture;" + "varying vec2 vTexture;" + "void main(void){" + " if(usingTexture){" + " gl_FragColor = vec4(texture2D(sampler, vTexture.xy)) * frontColor;" + " }" + " else{" + " gl_FragColor = frontColor;" + " }" + "}";
+
+ function uniformf(cacheId, programObj, varName, varValue) {
+ var varLocation = curContextCache.locations[cacheId];
+ if (varLocation === undef) {
+ varLocation = curContext.getUniformLocation(programObj, varName);
+ curContextCache.locations[cacheId] = varLocation
+ }
+ if (varLocation !== null) if (varValue.length === 4) curContext.uniform4fv(varLocation, varValue);
+ else if (varValue.length === 3) curContext.uniform3fv(varLocation, varValue);
+ else if (varValue.length === 2) curContext.uniform2fv(varLocation, varValue);
+ else curContext.uniform1f(varLocation, varValue)
+ }
+ function uniformi(cacheId, programObj, varName, varValue) {
+ var varLocation = curContextCache.locations[cacheId];
+ if (varLocation === undef) {
+ varLocation = curContext.getUniformLocation(programObj, varName);
+ curContextCache.locations[cacheId] = varLocation
+ }
+ if (varLocation !== null) if (varValue.length === 4) curContext.uniform4iv(varLocation, varValue);
+ else if (varValue.length === 3) curContext.uniform3iv(varLocation, varValue);
+ else if (varValue.length === 2) curContext.uniform2iv(varLocation, varValue);
+ else curContext.uniform1i(varLocation, varValue)
+ }
+ function uniformMatrix(cacheId, programObj, varName, transpose, matrix) {
+ var varLocation = curContextCache.locations[cacheId];
+ if (varLocation === undef) {
+ varLocation = curContext.getUniformLocation(programObj, varName);
+ curContextCache.locations[cacheId] = varLocation
+ }
+ if (varLocation !== -1) if (matrix.length === 16) curContext.uniformMatrix4fv(varLocation, transpose, matrix);
+ else if (matrix.length === 9) curContext.uniformMatrix3fv(varLocation, transpose, matrix);
+ else curContext.uniformMatrix2fv(varLocation, transpose, matrix)
+ }
+ function vertexAttribPointer(cacheId, programObj, varName, size, VBO) {
+ var varLocation = curContextCache.attributes[cacheId];
+ if (varLocation === undef) {
+ varLocation = curContext.getAttribLocation(programObj, varName);
+ curContextCache.attributes[cacheId] = varLocation
+ }
+ if (varLocation !== -1) {
+ curContext.bindBuffer(curContext.ARRAY_BUFFER, VBO);
+ curContext.vertexAttribPointer(varLocation, size, curContext.FLOAT, false, 0, 0);
+ curContext.enableVertexAttribArray(varLocation)
+ }
+ }
+ function disableVertexAttribPointer(cacheId, programObj, varName) {
+ var varLocation = curContextCache.attributes[cacheId];
+ if (varLocation === undef) {
+ varLocation = curContext.getAttribLocation(programObj, varName);
+ curContextCache.attributes[cacheId] = varLocation
+ }
+ if (varLocation !== -1) curContext.disableVertexAttribArray(varLocation)
+ }
+ 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 imageModeCorner = function(x, y, w, h, whAreSizes) {
+ return {
+ x: x,
+ y: y,
+ w: w,
+ h: h
+ }
+ };
+ var imageModeConvert = imageModeCorner;
+ var imageModeCorners = function(x, y, w, h, whAreSizes) {
+ return {
+ x: x,
+ y: y,
+ w: whAreSizes ? w : w - x,
+ h: whAreSizes ? h : h - y
+ }
+ };
+ var imageModeCenter = function(x, y, w, h, whAreSizes) {
+ return {
+ x: x - w / 2,
+ y: y - h / 2,
+ w: w,
+ h: h
+ }
+ };
+ var DrawingShared = function() {};
+ var Drawing2D = function() {};
+ var Drawing3D = function() {};
+ var DrawingPre = function() {};
+ Drawing2D.prototype = new DrawingShared;
+ Drawing2D.prototype.constructor = Drawing2D;
+ Drawing3D.prototype = new DrawingShared;
+ Drawing3D.prototype.constructor = Drawing3D;
+ DrawingPre.prototype = new DrawingShared;
+ DrawingPre.prototype.constructor = DrawingPre;
+ DrawingShared.prototype.a3DOnlyFunction = nop;
+ var charMap = {};
+ var Char = p.Character = function(chr) {
+ if (typeof chr === "string" && chr.length === 1) this.code = chr.charCodeAt(0);
+ else if (typeof chr === "number") this.code = chr;
+ else if (chr instanceof Char) this.code = chr;
+ else this.code = NaN;
+ return charMap[this.code] === undef ? charMap[this.code] = this : charMap[this.code]
+ };
+ Char.prototype.toString = function() {
+ return String.fromCharCode(this.code)
+ };
+ Char.prototype.valueOf = function() {
+ return this.code
+ };
+ var PShape = p.PShape = function(family) {
+ this.family = family || 0;
+ this.visible = true;
+ this.style = true;
+ this.children = [];
+ this.nameTable = [];
+ this.params = [];
+ this.name = "";
+ this.image = null;
+ this.matrix = null;
+ this.kind = null;
+ this.close = null;
+ this.width = null;
+ this.height = null;
+ this.parent = null
+ };
+ PShape.prototype = {
+ isVisible: function() {
+ return this.visible
+ },
+ setVisible: function(visible) {
+ this.visible = visible
+ },
+ disableStyle: function() {
+ this.style = false;
+ for (var i = 0, j = this.children.length; i < j; i++) this.children[i].disableStyle()
+ },
+ enableStyle: function() {
+ this.style = true;
+ for (var i = 0, j = this.children.length; i < j; i++) this.children[i].enableStyle()
+ },
+ getFamily: function() {
+ return this.family
+ },
+ getWidth: function() {
+ return this.width
+ },
+ getHeight: function() {
+ return this.height
+ },
+ setName: function(name) {
+ this.name = name
+ },
+ getName: function() {
+ return this.name
+ },
+ draw: function() {
+ if (this.visible) {
+ this.pre();
+ this.drawImpl();
+ this.post()
+ }
+ },
+ drawImpl: function() {
+ if (this.family === 0) this.drawGroup();
+ else if (this.family === 1) this.drawPrimitive();
+ else if (this.family === 3) this.drawGeometry();
+ else if (this.family === 21) this.drawPath()
+ },
+ drawPath: function() {
+ var i, j;
+ if (this.vertices.length === 0) return;
+ p.beginShape();
+ if (this.vertexCodes.length === 0) if (this.vertices[0].length === 2) for (i = 0, j = this.vertices.length; i < j; i++) p.vertex(this.vertices[i][0], this.vertices[i][1]);
+ else for (i = 0, j = this.vertices.length; i < j; i++) p.vertex(this.vertices[i][0], this.vertices[i][1], this.vertices[i][2]);
+ else {
+ var index = 0;
+ if (this.vertices[0].length === 2) for (i = 0, j = this.vertexCodes.length; i < j; i++) if (this.vertexCodes[i] === 0) {
+ p.vertex(this.vertices[index][0], this.vertices[index][1]);
+ if (this.vertices[index]["moveTo"] === true) vertArray[vertArray.length - 1]["moveTo"] = true;
+ else if (this.vertices[index]["moveTo"] === false) vertArray[vertArray.length - 1]["moveTo"] = false;
+ p.breakShape = false;
+ index++
+ } else if (this.vertexCodes[i] === 1) {
+ p.bezierVertex(this.vertices[index + 0][0], this.vertices[index + 0][1], this.vertices[index + 1][0], this.vertices[index + 1][1], this.vertices[index + 2][0], this.vertices[index + 2][1]);
+ index += 3
+ } else if (this.vertexCodes[i] === 2) {
+ p.curveVertex(this.vertices[index][0], this.vertices[index][1]);
+ index++
+ } else {
+ if (this.vertexCodes[i] === 3) p.breakShape = true
+ } else for (i = 0, j = this.vertexCodes.length; i < j; i++) if (this.vertexCodes[i] === 0) {
+ p.vertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index][2]);
+ if (this.vertices[index]["moveTo"] === true) vertArray[vertArray.length - 1]["moveTo"] = true;
+ else if (this.vertices[index]["moveTo"] === false) vertArray[vertArray.length - 1]["moveTo"] = false;
+ p.breakShape = false
+ } else if (this.vertexCodes[i] === 1) {
+ p.bezierVertex(this.vertices[index + 0][0], this.vertices[index + 0][1], this.vertices[index + 0][2], this.vertices[index + 1][0], this.vertices[index + 1][1], this.vertices[index + 1][2], this.vertices[index + 2][0], this.vertices[index + 2][1], this.vertices[index + 2][2]);
+ index += 3
+ } else if (this.vertexCodes[i] === 2) {
+ p.curveVertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index][2]);
+ index++
+ } else if (this.vertexCodes[i] === 3) p.breakShape = true
+ }
+ p.endShape(this.close ? 2 : 1)
+ },
+ drawGeometry: function() {
+ var i, j;
+ p.beginShape(this.kind);
+ if (this.style) for (i = 0, j = this.vertices.length; i < j; i++) p.vertex(this.vertices[i]);
+ else for (i = 0, j = this.vertices.length; i < j; i++) {
+ var vert = this.vertices[i];
+ if (vert[2] === 0) p.vertex(vert[0], vert[1]);
+ else p.vertex(vert[0], vert[1], vert[2])
+ }
+ p.endShape()
+ },
+ drawGroup: function() {
+ for (var i = 0, j = this.children.length; i < j; i++) this.children[i].draw()
+ },
+ drawPrimitive: function() {
+ if (this.kind === 2) p.point(this.params[0], this.params[1]);
+ else if (this.kind === 4) if (this.params.length === 4) p.line(this.params[0], this.params[1], this.params[2], this.params[3]);
+ else p.line(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]);
+ else if (this.kind === 8) p.triangle(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]);
+ else if (this.kind === 16) p.quad(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5], this.params[6], this.params[7]);
+ else if (this.kind === 30) if (this.image !== null) {
+ p.imageMode(0);
+ p.image(this.image, this.params[0], this.params[1], this.params[2], this.params[3])
+ } else {
+ p.rectMode(0);
+ p.rect(this.params[0], this.params[1], this.params[2], this.params[3])
+ } else if (this.kind === 31) {
+ p.ellipseMode(0);
+ p.ellipse(this.params[0], this.params[1], this.params[2], this.params[3])
+ } else if (this.kind === 32) {
+ p.ellipseMode(0);
+ p.arc(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5])
+ } else if (this.kind === 41) if (this.params.length === 1) p.box(this.params[0]);
+ else p.box(this.params[0], this.params[1], this.params[2]);
+ else if (this.kind === 40) p.sphere(this.params[0])
+ },
+ pre: function() {
+ if (this.matrix) {
+ p.pushMatrix();
+ curContext.transform(this.matrix.elements[0], this.matrix.elements[3], this.matrix.elements[1], this.matrix.elements[4], this.matrix.elements[2], this.matrix.elements[5])
+ }
+ if (this.style) {
+ p.pushStyle();
+ this.styles()
+ }
+ },
+ post: function() {
+ if (this.matrix) p.popMatrix();
+ if (this.style) p.popStyle()
+ },
+ styles: function() {
+ if (this.stroke) {
+ p.stroke(this.strokeColor);
+ p.strokeWeight(this.strokeWeight);
+ p.strokeCap(this.strokeCap);
+ p.strokeJoin(this.strokeJoin)
+ } else p.noStroke();
+ if (this.fill) p.fill(this.fillColor);
+ else p.noFill()
+ },
+ getChild: function(child) {
+ var i, j;
+ if (typeof child === "number") return this.children[child];
+ var found;
+ if (child === "" || this.name === child) return this;
+ if (this.nameTable.length > 0) {
+ for (i = 0, j = this.nameTable.length; i < j || found; i++) if (this.nameTable[i].getName === child) {
+ found = this.nameTable[i];
+ break
+ }
+ if (found) return found
+ }
+ for (i = 0, j = this.children.length; i < j; i++) {
+ found = this.children[i].getChild(child);
+ if (found) return found
+ }
+ return null
+ },
+ getChildCount: function() {
+ return this.children.length
+ },
+ addChild: function(child) {
+ this.children.push(child);
+ child.parent = this;
+ if (child.getName() !== null) this.addName(child.getName(), child)
+ },
+ addName: function(name, shape) {
+ if (this.parent !== null) this.parent.addName(name, shape);
+ else this.nameTable.push([name, shape])
+ },
+ translate: function() {
+ if (arguments.length === 2) {
+ this.checkMatrix(2);
+ this.matrix.translate(arguments[0], arguments[1])
+ } else {
+ this.checkMatrix(3);
+ this.matrix.translate(arguments[0], arguments[1], 0)
+ }
+ },
+ checkMatrix: function(dimensions) {
+ if (this.matrix === null) if (dimensions === 2) this.matrix = new p.PMatrix2D;
+ else this.matrix = new p.PMatrix3D;
+ else if (dimensions === 3 && this.matrix instanceof p.PMatrix2D) this.matrix = new p.PMatrix3D
+ },
+ rotateX: function(angle) {
+ this.rotate(angle, 1, 0, 0)
+ },
+ rotateY: function(angle) {
+ this.rotate(angle, 0, 1, 0)
+ },
+ rotateZ: function(angle) {
+ this.rotate(angle, 0, 0, 1)
+ },
+ rotate: function() {
+ if (arguments.length === 1) {
+ this.checkMatrix(2);
+ this.matrix.rotate(arguments[0])
+ } else {
+ this.checkMatrix(3);
+ this.matrix.rotate(arguments[0], arguments[1], arguments[2], arguments[3])
+ }
+ },
+ scale: function() {
+ if (arguments.length === 2) {
+ this.checkMatrix(2);
+ this.matrix.scale(arguments[0], arguments[1])
+ } else if (arguments.length === 3) {
+ this.checkMatrix(2);
+ this.matrix.scale(arguments[0], arguments[1], arguments[2])
+ } else {
+ this.checkMatrix(2);
+ this.matrix.scale(arguments[0])
+ }
+ },
+ resetMatrix: function() {
+ this.checkMatrix(2);
+ this.matrix.reset()
+ },
+ applyMatrix: function(matrix) {
+ if (arguments.length === 1) this.applyMatrix(matrix.elements[0], matrix.elements[1], 0, matrix.elements[2], matrix.elements[3], matrix.elements[4], 0, matrix.elements[5], 0, 0, 1, 0, 0, 0, 0, 1);
+ else if (arguments.length === 6) {
+ this.checkMatrix(2);
+ this.matrix.apply(arguments[0], arguments[1], arguments[2], 0, arguments[3], arguments[4], arguments[5], 0, 0, 0, 1, 0, 0, 0, 0, 1)
+ } else if (arguments.length === 16) {
+ this.checkMatrix(3);
+ this.matrix.apply(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11], arguments[12], arguments[13], arguments[14], arguments[15])
+ }
+ }
+ };
+ var PShapeSVG = p.PShapeSVG = function() {
+ p.PShape.call(this);
+ if (arguments.length === 1) {
+ this.element = arguments[0];
+ this.vertexCodes = [];
+ this.vertices = [];
+ this.opacity = 1;
+ this.stroke = false;
+ this.strokeColor = 4278190080;
+ this.strokeWeight = 1;
+ this.strokeCap = 'butt';
+ this.strokeJoin = 'miter';
+ this.strokeGradient = null;
+ this.strokeGradientPaint = null;
+ this.strokeName = null;
+ this.strokeOpacity = 1;
+ this.fill = true;
+ this.fillColor = 4278190080;
+ this.fillGradient = null;
+ this.fillGradientPaint = null;
+ this.fillName = null;
+ this.fillOpacity = 1;
+ if (this.element.getName() !== "svg") throw "root is not