diff --git a/9781430244646.jpg b/9781430244646.jpg new file mode 100644 index 0000000..8fe359d Binary files /dev/null and b/9781430244646.jpg differ diff --git a/CodeToAccompany9781430244646/.DS_Store b/CodeToAccompany9781430244646/.DS_Store new file mode 100644 index 0000000..f95bbc6 Binary files /dev/null and b/CodeToAccompany9781430244646/.DS_Store differ diff --git a/CodeToAccompany9781430244646/README.txt b/CodeToAccompany9781430244646/README.txt new file mode 100644 index 0000000..9242ce5 --- /dev/null +++ b/CodeToAccompany9781430244646/README.txt @@ -0,0 +1,20 @@ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 + +This source code is provided "as is" for educational purposes only. +Any express or implied warranties, including, but not limited to, the +implied warraties of mechanibility and fitness for a particular purpose +are disclaimed. In no event shall the copyright owner be liable for any +direct, indirect, incidental, special, exemplary, or consequential damages +(including but not limited to, procurement of substitute goods or services; +loss of use, data, or profits; or business interruption) however caused +and on any theory of liability, whether in contract, strict liability, or +tort (including negligence or otherwise) arising in any way out of the use +of this code, even if advised of the possibility of such damage. diff --git a/CodeToAccompany9781430244646/ch02/.DS_Store b/CodeToAccompany9781430244646/ch02/.DS_Store new file mode 100644 index 0000000..875af24 Binary files /dev/null and b/CodeToAccompany9781430244646/ch02/.DS_Store differ diff --git a/CodeToAccompany9781430244646/ch02/algorithmic_face/algorithmic_face.pde b/CodeToAccompany9781430244646/ch02/algorithmic_face/algorithmic_face.pde new file mode 100644 index 0000000..7b94c17 --- /dev/null +++ b/CodeToAccompany9781430244646/ch02/algorithmic_face/algorithmic_face.pde @@ -0,0 +1,105 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ +// algorithmic_face.pde, chapter 2 +// Algorithmic approach to drawing a face. + +// Simple Algorithmic Face +size(600, 800); +background(0); +stroke(255); +noFill(); +// draw ellipses from top left corner +ellipseMode(CORNER); + +// BEGIN DECLARE/INITIALIZE VARIABLES +// HEAD +float headHeight = 600; +float headWidth = headHeight*5/7; +float head_x = (width-headWidth)/2; +float head_y = (height-headHeight)/2; + +// EYES +float eyeWidth = headWidth/5; +float eyeHeight = eyeWidth/2; +float irisDiam = eyeHeight; +float pupilDiam = irisDiam/3; +float eye_y = head_y+headHeight/2-eyeHeight/2; +// left +float leftEye_x = head_x+eyeWidth; +float leftIris_x = leftEye_x + eyeWidth/2-irisDiam/2; +float leftPupil_x = leftEye_x + eyeWidth/2-pupilDiam/2; +// right +float rightEye_x = head_x+eyeWidth*3; +float rightIris_x = rightEye_x + eyeWidth/2-irisDiam/2; +float rightPupil_x = rightEye_x + eyeWidth/2-pupilDiam/2; + +//EYEBROWS +float eyeBrowWidth = eyeWidth*1.25; +float eyeBrowHeight = eyeHeight/4; +float eyeBrow_y = eye_y - eyeHeight - eyeBrowHeight/2; +// left +float leftEyeBrow_x = leftEye_x - (eyeBrowWidth-eyeWidth); +// right +float rightEyeBrow_x = rightEye_x; + +// NOSE +float nose_x = head_x+eyeWidth*2; +float nose_y = head_y + headHeight - headHeight/4; + +// MOUTH +float mouthWidth = eyeWidth*1.5; +float mouthHeight = headHeight/12; +float mouth_x = leftIris_x+irisDiam/2+eyeWidth/4; +float mouth_y = nose_y + mouthHeight; + +// EARS +float earWidth = eyeHeight*1.5; +float earHeight = headHeight/4; +float ear_y = eyeBrow_y; +// left +float leftEar_x = head_x-earWidth/2; +// right +float rightEar_x = head_x+headWidth-earWidth/2; + +// BEGIN DRAWING +// Draw head +ellipse(head_x, head_y, headWidth, headHeight); +// left eye +ellipse(leftEye_x, eye_y, eyeWidth, eyeHeight); +// Draw left iris +ellipse(leftIris_x, eye_y, irisDiam, irisDiam); +// Draw left pupil +ellipse(leftPupil_x, eye_y+eyeHeight/2-pupilDiam/2, pupilDiam, pupilDiam); +// Draw right eye +ellipse(rightEye_x, eye_y, eyeWidth, eyeHeight); +// Draw right iris +ellipse(rightIris_x, eye_y, irisDiam, irisDiam); +// Draw right pupil +ellipse(rightPupil_x, eye_y+eyeHeight/2-pupilDiam/2, pupilDiam, pupilDiam); +// Draw left eyebrow +rect(leftEyeBrow_x, eyeBrow_y, eyeBrowWidth, eyeBrowHeight); +// Draw right eyebrow +rect(rightEyeBrow_x, eyeBrow_y, eyeBrowWidth, eyeBrowHeight); +// Draw nose +triangle(nose_x, nose_y, nose_x+eyeWidth, nose_y, nose_x + eyeWidth/2, nose_y-eyeWidth); +// Draw Mouth - top lip +arc(mouth_x, mouth_y-mouthHeight/2, mouthWidth, mouthHeight, PI, TWO_PI); +// Draw Mouth - bottom lip +arc(mouth_x, mouth_y-mouthHeight/2, mouthWidth, mouthHeight, 0, PI); +// Draw Mouth – crease +line(mouth_x, mouth_y, mouth_x+mouthWidth, mouth_y); +// Draw left ear +arc(leftEar_x, ear_y, earWidth, earHeight, PI/2.3, PI*1.55); +// Draw right ear +arc(rightEar_x, ear_y, earWidth, earHeight, -PI/1.8, PI/1.8); + diff --git a/CodeToAccompany9781430244646/ch02/arcs_example/.DS_Store b/CodeToAccompany9781430244646/ch02/arcs_example/.DS_Store new file mode 100644 index 0000000..7fdec46 Binary files /dev/null and b/CodeToAccompany9781430244646/ch02/arcs_example/.DS_Store differ diff --git a/CodeToAccompany9781430244646/ch02/arcs_example/arcs_example.pde b/CodeToAccompany9781430244646/ch02/arcs_example/arcs_example.pde new file mode 100644 index 0000000..6195a36 --- /dev/null +++ b/CodeToAccompany9781430244646/ch02/arcs_example/arcs_example.pde @@ -0,0 +1,43 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ +// arcs_example.pde, chapter 2 +// Creates a page of randomized arcs. + +PFont font; + +void setup() { + size(1000, 1000); + background(255); + fill(0); + font = createFont("ArialMT-48.vlw", 20); + textFont(font, 18); + int cols = 4; + int rows = 4; + + float cellW = width/cols; + float cellH = height/rows; + + + for (int i=0; i= 9 && !document.doctype) throw "The doctype directive is missing. The recommended doctype in Internet Explorer is the HTML5 doctype: "; + 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(a) { + var array; + if (a instanceof ArrayList) array = a.toArray(); + else { + array = []; + if (typeof a === "number") array.length = a > 0 ? a : 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.lastIndexOf = function(item) { + for (var i = array.length - 1; i >= 0; --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.removeAll = function(c) { + var i, x, item, newList = new ArrayList; + newList.addAll(this); + this.clear(); + for (i = 0, x = 0; i < newList.size(); i++) { + item = newList.get(i); + if (!c.contains(item)) this.add(x++, item) + } + if (this.size() < newList.size()) 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; + var currentItem; + + 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() { + currentItem = conversion(buckets[bucketIndex][itemIndex]); + findNext(); + return currentItem + }; + this.remove = function() { + if (currentItem !== undef) { + removeItem(currentItem); + --itemIndex; + findNext() + } + }; + 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 overloadBaseClassFunction(object, name, basefn) { + if (!object.hasOwnProperty(name) || typeof object[name] !== "function") { + object[name] = basefn; + return + } + var fn = object[name]; + if ("$overloads" in fn) { + fn.$defaultOverload = basefn; + return + } + if (! ("$overloads" in basefn) && fn.length === basefn.length) return; + var overloads, defaultOverload; + if ("$overloads" in basefn) { + overloads = basefn.$overloads.slice(0); + overloads[fn.length] = fn; + defaultOverload = basefn.$defaultOverload + } else { + overloads = []; + overloads[basefn.length] = basefn; + overloads[fn.length] = fn; + defaultOverload = fn + } + var hubfn = function() { + var fn = hubfn.$overloads[arguments.length] || ("$methodArgsIndex" in hubfn && arguments.length > hubfn.$methodArgsIndex ? hubfn.$overloads[hubfn.$methodArgsIndex] : null) || hubfn.$defaultOverload; + return fn.apply(this, arguments) + }; + hubfn.$overloads = overloads; + if ("$methodArgsIndex" in basefn) hubfn.$methodArgsIndex = basefn.$methodArgsIndex; + hubfn.$defaultOverload = defaultOverload; + hubfn.name = name; + object[name] = hubfn + } + 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") overloadBaseClassFunction(subClass, propertyName, baseClass[propertyName]); + else if (propertyName.charAt(0) !== "$" && !(propertyName in subClass)) properties.push(propertyName); + while (properties.length > 0) extendGetterSetter(properties.shift()); + subClass.$super = baseClass + } + 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, hasMethodArgs) { + var existingfn = object[name]; + if (existingfn || hasMethodArgs) { + var args = fn.length; + if ("$overloads" in existingfn) existingfn.$overloads[args] = fn; + else { + var hubfn = function() { + var fn = hubfn.$overloads[arguments.length] || ("$methodArgsIndex" in hubfn && arguments.length > hubfn.$methodArgsIndex ? hubfn.$overloads[hubfn.$methodArgsIndex] : null) || hubfn.$defaultOverload; + return fn.apply(this, arguments) + }; + var overloads = []; + if (existingfn) overloads[existingfn.length] = existingfn; + overloads[args] = fn; + hubfn.$overloads = overloads; + hubfn.$defaultOverload = existingfn || fn; + if (hasMethodArgs) hubfn.$methodArgsIndex = args; + hubfn.name = name; + object[name] = hubfn + } + } else object[name] = fn + }; + + function isNumericalJavaType(type) { + if (typeof type !== "string") return false; + return ["byte", "int", "char", "color", "float", "long", "double"].indexOf(type) !== -1 + } + defaultScope.createJavaArray = function(type, bounds) { + var result = null, + defaultValue = null; + if (typeof type === "string") if (type === "boolean") defaultValue = false; + else if (isNumericalJavaType(type)) defaultValue = 0; + 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] = defaultValue + } 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 + } + }); + defaultScope.defineProperty(defaultScope, "online", { + get: function() { + return true + } + }); + 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; + 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); + if (pfont.caching) return ctx + } + 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 = computeFontMetrics(this); + this.css = this.getCSSDefinition(); + if (this.context2d) this.context2d.font = this.css + } + PFont.prototype.caching = true; + 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.prototype.measureTextWidthFallback = function(string) { + var canvas = document.createElement("canvas"), + ctx = canvas.getContext("2d"); + ctx.font = this.css; + return ctx.measureText(string).width + }; + PFont.PFontCache = { + length: 0 + }; + PFont.get = function(fontName, fontSize) { + fontSize = (fontSize * 10 + 0.5 | 0) / 10; + var cache = PFont.PFontCache, + idx = fontName + "/" + fontSize; + if (!cache[idx]) { + cache[idx] = new PFont(fontName, fontSize); + cache.length++; + if (cache.length === 50) { + PFont.prototype.measureTextWidth = PFont.prototype.measureTextWidthFallback; + PFont.prototype.caching = false; + var entry; + for (entry in cache) if (entry !== "length") cache[entry].context2d = null; + return new PFont(fontName, fontSize) + } + if (cache.length === 400) { + PFont.PFontCache = {}; + PFont.get = PFont.getFallback; + return new PFont(fontName, fontSize) + } + } + return cache[idx] + }; + PFont.getFallback = function(fontName, fontSize) { + return new PFont(fontName, fontSize) + }; + 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 vertexShaderSrcUnlitShape = "varying vec4 vFrontColor;" + "attribute vec3 aVertex;" + "attribute vec4 aColor;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform float uPointSize;" + "void main(void) {" + " vFrontColor = aColor;" + " gl_PointSize = uPointSize;" + " gl_Position = uProjection * uView * vec4(aVertex, 1.0);" + "}"; + var fragmentShaderSrcUnlitShape = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 vFrontColor;" + "uniform bool uSmooth;" + "void main(void){" + " if(uSmooth == true){" + " float dist = distance(gl_PointCoord, vec2(0.5));" + " if(dist > 0.5){" + " discard;" + " }" + " }" + " gl_FragColor = vFrontColor;" + "}"; + var vertexShaderSrc2D = "varying vec4 vFrontColor;" + "attribute vec3 aVertex;" + "attribute vec2 aTextureCoord;" + "uniform vec4 uColor;" + "uniform mat4 uModel;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform float uPointSize;" + "varying vec2 vTextureCoord;" + "void main(void) {" + " gl_PointSize = uPointSize;" + " vFrontColor = uColor;" + " gl_Position = uProjection * uView * uModel * vec4(aVertex, 1.0);" + " vTextureCoord = aTextureCoord;" + "}"; + var fragmentShaderSrc2D = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 vFrontColor;" + "varying vec2 vTextureCoord;" + "uniform sampler2D uSampler;" + "uniform int uIsDrawingText;" + "uniform bool uSmooth;" + "void main(void){" + " if(uSmooth == true){" + " float dist = distance(gl_PointCoord, vec2(0.5));" + " if(dist > 0.5){" + " discard;" + " }" + " }" + " if(uIsDrawingText == 1){" + " float alpha = texture2D(uSampler, vTextureCoord).a;" + " gl_FragColor = vec4(vFrontColor.rgb * alpha, alpha);" + " }" + " else{" + " gl_FragColor = vFrontColor;" + " }" + "}"; + var webglMaxTempsWorkaround = /Windows/.test(navigator.userAgent); + var vertexShaderSrc3D = "varying vec4 vFrontColor;" + "attribute vec3 aVertex;" + "attribute vec3 aNormal;" + "attribute vec4 aColor;" + "attribute vec2 aTexture;" + "varying vec2 vTexture;" + "uniform vec4 uColor;" + "uniform bool uUsingMat;" + "uniform vec3 uSpecular;" + "uniform vec3 uMaterialEmissive;" + "uniform vec3 uMaterialAmbient;" + "uniform vec3 uMaterialSpecular;" + "uniform float uShininess;" + "uniform mat4 uModel;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform mat4 uNormalTransform;" + "uniform int uLightCount;" + "uniform vec3 uFalloff;" + "struct Light {" + " int type;" + " vec3 color;" + " vec3 position;" + " vec3 direction;" + " float angle;" + " vec3 halfVector;" + " float concentration;" + "};" + "uniform Light uLights0;" + "uniform Light uLights1;" + "uniform Light uLights2;" + "uniform Light uLights3;" + "uniform Light uLights4;" + "uniform Light uLights5;" + "uniform Light uLights6;" + "uniform Light uLights7;" + "Light getLight(int index){" + " if(index == 0) return uLights0;" + " if(index == 1) return uLights1;" + " if(index == 2) return uLights2;" + " if(index == 3) return uLights3;" + " if(index == 4) return uLights4;" + " if(index == 5) return uLights5;" + " if(index == 6) return uLights6;" + " return uLights7;" + "}" + "void AmbientLight( inout vec3 totalAmbient, in vec3 ecPos, in Light light ) {" + " float d = length( light.position - ecPos );" + " float attenuation = 1.0 / ( uFalloff[0] + ( uFalloff[1] * d ) + ( uFalloff[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, uShininess );" + " }" + " col += light.color * nDotVP;" + " spec += uSpecular * 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 / ( uFalloff[0] + ( uFalloff[1] * d ) + ( uFalloff[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, uShininess );" + " }" + " spec += uSpecular * 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 = 0.0;" + " vec3 VP = light.position - ecPos;" + " vec3 ldir = normalize( -light.direction );" + " float d = length( VP );" + " VP = normalize( VP );" + " float attenuation = 1.0 / ( uFalloff[0] + ( uFalloff[1] * d ) + ( uFalloff[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 = pow( nDotHV, uShininess );" + " }" + " spec += uSpecular * powerFactor * attenuation;" + " col += light.color * nDotVP * attenuation;" + "}" + "void main(void) {" + " vec3 finalAmbient = vec3( 0.0 );" + " vec3 finalDiffuse = vec3( 0.0 );" + " vec3 finalSpecular = vec3( 0.0 );" + " vec4 col = uColor;" + " if ( uColor[0] == -1.0 ){" + " col = aColor;" + " }" + " vec3 norm = normalize(vec3( uNormalTransform * vec4( aNormal, 0.0 ) ));" + " vec4 ecPos4 = uView * uModel * vec4(aVertex, 1.0);" + " vec3 ecPos = (vec3(ecPos4))/ecPos4.w;" + " if( uLightCount == 0 ) {" + " vFrontColor = col + vec4(uMaterialSpecular, 1.0);" + " }" + " else {" + " for( int i = 0; i < 8; i++ ) {" + " Light l = getLight(i);" + " if( i >= uLightCount ){" + " 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( uUsingMat == false ) {" + " vFrontColor = vec4(" + " vec3( col ) * finalAmbient +" + " vec3( col ) * finalDiffuse +" + " vec3( col ) * finalSpecular," + " col[3] );" + " }" + " else{" + " vFrontColor = vec4( " + " uMaterialEmissive + " + " (vec3(col) * uMaterialAmbient * finalAmbient ) + " + " (vec3(col) * finalDiffuse) + " + " (uMaterialSpecular * finalSpecular), " + " col[3] );" + " }" + " }" + " vTexture.xy = aTexture.xy;" + " gl_Position = uProjection * uView * uModel * vec4( aVertex, 1.0 );" + "}"; + var fragmentShaderSrc3D = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 vFrontColor;" + "uniform sampler2D uSampler;" + "uniform bool uUsingTexture;" + "varying vec2 vTexture;" + "void main(void){" + " if( uUsingTexture ){" + " gl_FragColor = vec4(texture2D(uSampler, vTexture.xy)) * vFrontColor;" + " }" + " else{" + " gl_FragColor = vFrontColor;" + " }" + "}"; + + 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(renderContext) { + renderContext = renderContext || p; + if (this.visible) { + this.pre(renderContext); + this.drawImpl(renderContext); + this.post(renderContext) + } + }, + drawImpl: function(renderContext) { + if (this.family === 0) this.drawGroup(renderContext); + else if (this.family === 1) this.drawPrimitive(renderContext); + else if (this.family === 3) this.drawGeometry(renderContext); + else if (this.family === 21) this.drawPath(renderContext) + }, + drawPath: function(renderContext) { + var i, j; + if (this.vertices.length === 0) return; + renderContext.beginShape(); + if (this.vertexCodes.length === 0) if (this.vertices[0].length === 2) for (i = 0, j = this.vertices.length; i < j; i++) renderContext.vertex(this.vertices[i][0], this.vertices[i][1]); + else for (i = 0, j = this.vertices.length; i < j; i++) renderContext.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) { + renderContext.vertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index]["moveTo"]); + renderContext.breakShape = false; + index++ + } else if (this.vertexCodes[i] === 1) { + renderContext.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) { + renderContext.curveVertex(this.vertices[index][0], this.vertices[index][1]); + index++ + } else { + if (this.vertexCodes[i] === 3) renderContext.breakShape = true + } else for (i = 0, j = this.vertexCodes.length; i < j; i++) if (this.vertexCodes[i] === 0) { + renderContext.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; + renderContext.breakShape = false + } else if (this.vertexCodes[i] === 1) { + renderContext.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) { + renderContext.curveVertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index][2]); + index++ + } else if (this.vertexCodes[i] === 3) renderContext.breakShape = true + } + renderContext.endShape(this.close ? 2 : 1) + }, + drawGeometry: function(renderContext) { + var i, j; + renderContext.beginShape(this.kind); + if (this.style) for (i = 0, j = this.vertices.length; i < j; i++) renderContext.vertex(this.vertices[i]); + else for (i = 0, j = this.vertices.length; i < j; i++) { + var vert = this.vertices[i]; + if (vert[2] === 0) renderContext.vertex(vert[0], vert[1]); + else renderContext.vertex(vert[0], vert[1], vert[2]) + } + renderContext.endShape() + }, + drawGroup: function(renderContext) { + for (var i = 0, j = this.children.length; i < j; i++) this.children[i].draw(renderContext) + }, + drawPrimitive: function(renderContext) { + if (this.kind === 2) renderContext.point(this.params[0], this.params[1]); + else if (this.kind === 4) if (this.params.length === 4) renderContext.line(this.params[0], this.params[1], this.params[2], this.params[3]); + else renderContext.line(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]); + else if (this.kind === 8) renderContext.triangle(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]); + else if (this.kind === 16) renderContext.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) { + var imMode = imageModeConvert; + renderContext.imageMode(0); + renderContext.image(this.image, this.params[0], this.params[1], this.params[2], this.params[3]); + imageModeConvert = imMode + } else { + var rcMode = curRectMode; + renderContext.rectMode(0); + renderContext.rect(this.params[0], this.params[1], this.params[2], this.params[3]); + curRectMode = rcMode + } else if (this.kind === 31) { + var elMode = curEllipseMode; + renderContext.ellipseMode(0); + renderContext.ellipse(this.params[0], this.params[1], this.params[2], this.params[3]); + curEllipseMode = elMode + } else if (this.kind === 32) { + var eMode = curEllipseMode; + renderContext.ellipseMode(0); + renderContext.arc(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]); + curEllipseMode = eMode + } else if (this.kind === 41) if (this.params.length === 1) renderContext.box(this.params[0]); + else renderContext.box(this.params[0], this.params[1], this.params[2]); + else if (this.kind === 40) renderContext.sphere(this.params[0]) + }, + pre: function(renderContext) { + if (this.matrix) { + renderContext.pushMatrix(); + renderContext.transform(this.matrix) + } + if (this.style) { + renderContext.pushStyle(); + this.styles(renderContext) + } + }, + post: function(renderContext) { + if (this.matrix) renderContext.popMatrix(); + if (this.style) renderContext.popStyle() + }, + styles: function(renderContext) { + if (this.stroke) { + renderContext.stroke(this.strokeColor); + renderContext.strokeWeight(this.strokeWeight); + renderContext.strokeCap(this.strokeCap); + renderContext.strokeJoin(this.strokeJoin) + } else renderContext.noStroke(); + if (this.fill) renderContext.fill(this.fillColor); + else renderContext.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 , it's <" + this.element.getName() + ">"; + } else if (arguments.length === 2) if (typeof arguments[1] === "string") { + if (arguments[1].indexOf(".svg") > -1) { + this.element = new p.XMLElement(p, arguments[1]); + this.vertexCodes = []; + this.vertices = []; + this.opacity = 1; + this.stroke = false; + this.strokeColor = 4278190080; + this.strokeWeight = 1; + this.strokeCap = 'butt'; + this.strokeJoin = 'miter'; + this.strokeGradient = ""; + this.strokeGradientPaint = ""; + this.strokeName = ""; + this.strokeOpacity = 1; + this.fill = true; + this.fillColor = 4278190080; + this.fillGradient = null; + this.fillGradientPaint = null; + this.fillOpacity = 1 + } + } else if (arguments[0]) { + this.element = arguments[1]; + this.vertexCodes = arguments[0].vertexCodes.slice(); + this.vertices = arguments[0].vertices.slice(); + this.stroke = arguments[0].stroke; + this.strokeColor = arguments[0].strokeColor; + this.strokeWeight = arguments[0].strokeWeight; + this.strokeCap = arguments[0].strokeCap; + this.strokeJoin = arguments[0].strokeJoin; + this.strokeGradient = arguments[0].strokeGradient; + this.strokeGradientPaint = arguments[0].strokeGradientPaint; + this.strokeName = arguments[0].strokeName; + this.fill = arguments[0].fill; + this.fillColor = arguments[0].fillColor; + this.fillGradient = arguments[0].fillGradient; + this.fillGradientPaint = arguments[0].fillGradientPaint; + this.fillName = arguments[0].fillName; + this.strokeOpacity = arguments[0].strokeOpacity; + this.fillOpacity = arguments[0].fillOpacity; + this.opacity = arguments[0].opacity + } + this.name = this.element.getStringAttribute("id"); + var displayStr = this.element.getStringAttribute("display", "inline"); + this.visible = displayStr !== "none"; + var str = this.element.getAttribute("transform"); + if (str) this.matrix = this.parseMatrix(str); + var viewBoxStr = this.element.getStringAttribute("viewBox"); + if (viewBoxStr !== null) { + var viewBox = viewBoxStr.split(" "); + this.width = viewBox[2]; + this.height = viewBox[3] + } + var unitWidth = this.element.getStringAttribute("width"); + var unitHeight = this.element.getStringAttribute("height"); + if (unitWidth !== null) { + this.width = this.parseUnitSize(unitWidth); + this.height = this.parseUnitSize(unitHeight) + } else if (this.width === 0 || this.height === 0) { + this.width = 1; + this.height = 1; + throw "The width and/or height is not " + "readable in the tag of this file."; + } + this.parseColors(this.element); + this.parseChildren(this.element) + }; + PShapeSVG.prototype = new PShape; + PShapeSVG.prototype.parseMatrix = function() { + function getCoords(s) { + var m = []; + s.replace(/\((.*?)\)/, function() { + return function(all, params) { + m = params.replace(/,+/g, " ").split(/\s+/) + } + }()); + return m + } + return function(str) { + this.checkMatrix(2); + var pieces = []; + str.replace(/\s*(\w+)\((.*?)\)/g, function(all) { + pieces.push(p.trim(all)) + }); + if (pieces.length === 0) return null; + for (var i = 0, j = pieces.length; i < j; i++) { + var m = getCoords(pieces[i]); + if (pieces[i].indexOf("matrix") !== -1) this.matrix.set(m[0], m[2], m[4], m[1], m[3], m[5]); + else if (pieces[i].indexOf("translate") !== -1) { + var tx = m[0]; + var ty = m.length === 2 ? m[1] : 0; + this.matrix.translate(tx, ty) + } else if (pieces[i].indexOf("scale") !== -1) { + var sx = m[0]; + var sy = m.length === 2 ? m[1] : m[0]; + this.matrix.scale(sx, sy) + } else if (pieces[i].indexOf("rotate") !== -1) { + var angle = m[0]; + if (m.length === 1) this.matrix.rotate(p.radians(angle)); + else if (m.length === 3) { + this.matrix.translate(m[1], m[2]); + this.matrix.rotate(p.radians(m[0])); + this.matrix.translate(-m[1], -m[2]) + } + } else if (pieces[i].indexOf("skewX") !== -1) this.matrix.skewX(parseFloat(m[0])); + else if (pieces[i].indexOf("skewY") !== -1) this.matrix.skewY(m[0]); + else if (pieces[i].indexOf("shearX") !== -1) this.matrix.shearX(m[0]); + else if (pieces[i].indexOf("shearY") !== -1) this.matrix.shearY(m[0]) + } + return this.matrix + } + }(); + PShapeSVG.prototype.parseChildren = function(element) { + var newelement = element.getChildren(); + var children = new p.PShape; + for (var i = 0, j = newelement.length; i < j; i++) { + var kid = this.parseChild(newelement[i]); + if (kid) children.addChild(kid) + } + this.children.push(children) + }; + PShapeSVG.prototype.getName = function() { + return this.name + }; + PShapeSVG.prototype.parseChild = function(elem) { + var name = elem.getName(); + var shape; + if (name === "g") shape = new PShapeSVG(this, elem); + else if (name === "defs") shape = new PShapeSVG(this, elem); + else if (name === "line") { + shape = new PShapeSVG(this, elem); + shape.parseLine() + } else if (name === "circle") { + shape = new PShapeSVG(this, elem); + shape.parseEllipse(true) + } else if (name === "ellipse") { + shape = new PShapeSVG(this, elem); + shape.parseEllipse(false) + } else if (name === "rect") { + shape = new PShapeSVG(this, elem); + shape.parseRect() + } else if (name === "polygon") { + shape = new PShapeSVG(this, elem); + shape.parsePoly(true) + } else if (name === "polyline") { + shape = new PShapeSVG(this, elem); + shape.parsePoly(false) + } else if (name === "path") { + shape = new PShapeSVG(this, elem); + shape.parsePath() + } else if (name === "radialGradient") unimplemented("PShapeSVG.prototype.parseChild, name = radialGradient"); + else if (name === "linearGradient") unimplemented("PShapeSVG.prototype.parseChild, name = linearGradient"); + else if (name === "text") unimplemented("PShapeSVG.prototype.parseChild, name = text"); + else if (name === "filter") unimplemented("PShapeSVG.prototype.parseChild, name = filter"); + else if (name === "mask") unimplemented("PShapeSVG.prototype.parseChild, name = mask"); + else nop(); + return shape + }; + PShapeSVG.prototype.parsePath = function() { + this.family = 21; + this.kind = 0; + var pathDataChars = []; + var c; + var pathData = p.trim(this.element.getStringAttribute("d").replace(/[\s,]+/g, " ")); + if (pathData === null) return; + pathData = p.__toCharArray(pathData); + var cx = 0, + cy = 0, + ctrlX = 0, + ctrlY = 0, + ctrlX1 = 0, + ctrlX2 = 0, + ctrlY1 = 0, + ctrlY2 = 0, + endX = 0, + endY = 0, + ppx = 0, + ppy = 0, + px = 0, + py = 0, + i = 0, + valOf = 0; + var str = ""; + var tmpArray = []; + var flag = false; + var lastInstruction; + var command; + var j, k; + while (i < pathData.length) { + valOf = pathData[i].valueOf(); + if (valOf >= 65 && valOf <= 90 || valOf >= 97 && valOf <= 122) { + j = i; + i++; + if (i < pathData.length) { + tmpArray = []; + valOf = pathData[i].valueOf(); + while (! (valOf >= 65 && valOf <= 90 || valOf >= 97 && valOf <= 100 || valOf >= 102 && valOf <= 122) && flag === false) { + if (valOf === 32) { + if (str !== "") { + tmpArray.push(parseFloat(str)); + str = "" + } + i++ + } else if (valOf === 45) if (pathData[i - 1].valueOf() === 101) { + str += pathData[i].toString(); + i++ + } else { + if (str !== "") tmpArray.push(parseFloat(str)); + str = pathData[i].toString(); + i++ + } else { + str += pathData[i].toString(); + i++ + } + if (i === pathData.length) flag = true; + else valOf = pathData[i].valueOf() + } + } + if (str !== "") { + tmpArray.push(parseFloat(str)); + str = "" + } + command = pathData[j]; + valOf = command.valueOf(); + if (valOf === 77) { + if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) { + cx = tmpArray[0]; + cy = tmpArray[1]; + this.parsePathMoveto(cx, cy); + if (tmpArray.length > 2) for (j = 2, k = tmpArray.length; j < k; j += 2) { + cx = tmpArray[j]; + cy = tmpArray[j + 1]; + this.parsePathLineto(cx, cy) + } + } + } else if (valOf === 109) { + if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) { + cx += tmpArray[0]; + cy += tmpArray[1]; + this.parsePathMoveto(cx, cy); + if (tmpArray.length > 2) for (j = 2, k = tmpArray.length; j < k; j += 2) { + cx += tmpArray[j]; + cy += tmpArray[j + 1]; + this.parsePathLineto(cx, cy) + } + } + } else if (valOf === 76) { + if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) { + cx = tmpArray[j]; + cy = tmpArray[j + 1]; + this.parsePathLineto(cx, cy) + } + } else if (valOf === 108) { + if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) { + cx += tmpArray[j]; + cy += tmpArray[j + 1]; + this.parsePathLineto(cx, cy) + } + } else if (valOf === 72) for (j = 0, k = tmpArray.length; j < k; j++) { + cx = tmpArray[j]; + this.parsePathLineto(cx, cy) + } else if (valOf === 104) for (j = 0, k = tmpArray.length; j < k; j++) { + cx += tmpArray[j]; + this.parsePathLineto(cx, cy) + } else if (valOf === 86) for (j = 0, k = tmpArray.length; j < k; j++) { + cy = tmpArray[j]; + this.parsePathLineto(cx, cy) + } else if (valOf === 118) for (j = 0, k = tmpArray.length; j < k; j++) { + cy += tmpArray[j]; + this.parsePathLineto(cx, cy) + } else if (valOf === 67) { + if (tmpArray.length >= 6 && tmpArray.length % 6 === 0) for (j = 0, k = tmpArray.length; j < k; j += 6) { + ctrlX1 = tmpArray[j]; + ctrlY1 = tmpArray[j + 1]; + ctrlX2 = tmpArray[j + 2]; + ctrlY2 = tmpArray[j + 3]; + endX = tmpArray[j + 4]; + endY = tmpArray[j + 5]; + this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 99) { + if (tmpArray.length >= 6 && tmpArray.length % 6 === 0) for (j = 0, k = tmpArray.length; j < k; j += 6) { + ctrlX1 = cx + tmpArray[j]; + ctrlY1 = cy + tmpArray[j + 1]; + ctrlX2 = cx + tmpArray[j + 2]; + ctrlY2 = cy + tmpArray[j + 3]; + endX = cx + tmpArray[j + 4]; + endY = cy + tmpArray[j + 5]; + this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 83) { + if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) { + if (lastInstruction.toLowerCase() === "c" || lastInstruction.toLowerCase() === "s") { + ppx = this.vertices[this.vertices.length - 2][0]; + ppy = this.vertices[this.vertices.length - 2][1]; + px = this.vertices[this.vertices.length - 1][0]; + py = this.vertices[this.vertices.length - 1][1]; + ctrlX1 = px + (px - ppx); + ctrlY1 = py + (py - ppy) + } else { + ctrlX1 = this.vertices[this.vertices.length - 1][0]; + ctrlY1 = this.vertices[this.vertices.length - 1][1] + } + ctrlX2 = tmpArray[j]; + ctrlY2 = tmpArray[j + 1]; + endX = tmpArray[j + 2]; + endY = tmpArray[j + 3]; + this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 115) { + if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) { + if (lastInstruction.toLowerCase() === "c" || lastInstruction.toLowerCase() === "s") { + ppx = this.vertices[this.vertices.length - 2][0]; + ppy = this.vertices[this.vertices.length - 2][1]; + px = this.vertices[this.vertices.length - 1][0]; + py = this.vertices[this.vertices.length - 1][1]; + ctrlX1 = px + (px - ppx); + ctrlY1 = py + (py - ppy) + } else { + ctrlX1 = this.vertices[this.vertices.length - 1][0]; + ctrlY1 = this.vertices[this.vertices.length - 1][1] + } + ctrlX2 = cx + tmpArray[j]; + ctrlY2 = cy + tmpArray[j + 1]; + endX = cx + tmpArray[j + 2]; + endY = cy + tmpArray[j + 3]; + this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 81) { + if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) { + ctrlX = tmpArray[j]; + ctrlY = tmpArray[j + 1]; + endX = tmpArray[j + 2]; + endY = tmpArray[j + 3]; + this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 113) { + if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) { + ctrlX = cx + tmpArray[j]; + ctrlY = cy + tmpArray[j + 1]; + endX = cx + tmpArray[j + 2]; + endY = cy + tmpArray[j + 3]; + this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 84) { + if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) { + if (lastInstruction.toLowerCase() === "q" || lastInstruction.toLowerCase() === "t") { + ppx = this.vertices[this.vertices.length - 2][0]; + ppy = this.vertices[this.vertices.length - 2][1]; + px = this.vertices[this.vertices.length - 1][0]; + py = this.vertices[this.vertices.length - 1][1]; + ctrlX = px + (px - ppx); + ctrlY = py + (py - ppy) + } else { + ctrlX = cx; + ctrlY = cy + } + endX = tmpArray[j]; + endY = tmpArray[j + 1]; + this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 116) { + if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) { + if (lastInstruction.toLowerCase() === "q" || lastInstruction.toLowerCase() === "t") { + ppx = this.vertices[this.vertices.length - 2][0]; + ppy = this.vertices[this.vertices.length - 2][1]; + px = this.vertices[this.vertices.length - 1][0]; + py = this.vertices[this.vertices.length - 1][1]; + ctrlX = px + (px - ppx); + ctrlY = py + (py - ppy) + } else { + ctrlX = cx; + ctrlY = cy + } + endX = cx + tmpArray[j]; + endY = cy + tmpArray[j + 1]; + this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 90 || valOf === 122) this.close = true; + lastInstruction = command.toString() + } else i++ + } + }; + PShapeSVG.prototype.parsePathQuadto = function(x1, y1, cx, cy, x2, y2) { + if (this.vertices.length > 0) { + this.parsePathCode(1); + this.parsePathVertex(x1 + (cx - x1) * 2 / 3, y1 + (cy - y1) * 2 / 3); + this.parsePathVertex(x2 + (cx - x2) * 2 / 3, y2 + (cy - y2) * 2 / 3); + this.parsePathVertex(x2, y2) + } else throw "Path must start with M/m"; + }; + PShapeSVG.prototype.parsePathCurveto = function(x1, y1, x2, y2, x3, y3) { + if (this.vertices.length > 0) { + this.parsePathCode(1); + this.parsePathVertex(x1, y1); + this.parsePathVertex(x2, y2); + this.parsePathVertex(x3, y3) + } else throw "Path must start with M/m"; + }; + PShapeSVG.prototype.parsePathLineto = function(px, py) { + if (this.vertices.length > 0) { + this.parsePathCode(0); + this.parsePathVertex(px, py); + this.vertices[this.vertices.length - 1]["moveTo"] = false + } else throw "Path must start with M/m"; + }; + PShapeSVG.prototype.parsePathMoveto = function(px, py) { + if (this.vertices.length > 0) this.parsePathCode(3); + this.parsePathCode(0); + this.parsePathVertex(px, py); + this.vertices[this.vertices.length - 1]["moveTo"] = true + }; + PShapeSVG.prototype.parsePathVertex = function(x, y) { + var verts = []; + verts[0] = x; + verts[1] = y; + this.vertices.push(verts) + }; + PShapeSVG.prototype.parsePathCode = function(what) { + this.vertexCodes.push(what) + }; + PShapeSVG.prototype.parsePoly = function(val) { + this.family = 21; + this.close = val; + var pointsAttr = p.trim(this.element.getStringAttribute("points").replace(/[,\s]+/g, " ")); + if (pointsAttr !== null) { + var pointsBuffer = pointsAttr.split(" "); + if (pointsBuffer.length % 2 === 0) for (var i = 0, j = pointsBuffer.length; i < j; i++) { + var verts = []; + verts[0] = pointsBuffer[i]; + verts[1] = pointsBuffer[++i]; + this.vertices.push(verts) + } else throw "Error parsing polygon points: odd number of coordinates provided"; + } + }; + PShapeSVG.prototype.parseRect = function() { + this.kind = 30; + this.family = 1; + this.params = []; + this.params[0] = this.element.getFloatAttribute("x"); + this.params[1] = this.element.getFloatAttribute("y"); + this.params[2] = this.element.getFloatAttribute("width"); + this.params[3] = this.element.getFloatAttribute("height"); + if (this.params[2] < 0 || this.params[3] < 0) throw "svg error: negative width or height found while parsing "; + }; + PShapeSVG.prototype.parseEllipse = function(val) { + this.kind = 31; + this.family = 1; + this.params = []; + this.params[0] = this.element.getFloatAttribute("cx") | 0; + this.params[1] = this.element.getFloatAttribute("cy") | 0; + var rx, ry; + if (val) { + rx = ry = this.element.getFloatAttribute("r"); + if (rx < 0) throw "svg error: negative radius found while parsing "; + } else { + rx = this.element.getFloatAttribute("rx"); + ry = this.element.getFloatAttribute("ry"); + if (rx < 0 || ry < 0) throw "svg error: negative x-axis radius or y-axis radius found while parsing "; + } + this.params[0] -= rx; + this.params[1] -= ry; + this.params[2] = rx * 2; + this.params[3] = ry * 2 + }; + PShapeSVG.prototype.parseLine = function() { + this.kind = 4; + this.family = 1; + this.params = []; + this.params[0] = this.element.getFloatAttribute("x1"); + this.params[1] = this.element.getFloatAttribute("y1"); + this.params[2] = this.element.getFloatAttribute("x2"); + this.params[3] = this.element.getFloatAttribute("y2") + }; + PShapeSVG.prototype.parseColors = function(element) { + if (element.hasAttribute("opacity")) this.setOpacity(element.getAttribute("opacity")); + if (element.hasAttribute("stroke")) this.setStroke(element.getAttribute("stroke")); + if (element.hasAttribute("stroke-width")) this.setStrokeWeight(element.getAttribute("stroke-width")); + if (element.hasAttribute("stroke-linejoin")) this.setStrokeJoin(element.getAttribute("stroke-linejoin")); + if (element.hasAttribute("stroke-linecap")) this.setStrokeCap(element.getStringAttribute("stroke-linecap")); + if (element.hasAttribute("fill")) this.setFill(element.getStringAttribute("fill")); + if (element.hasAttribute("style")) { + var styleText = element.getStringAttribute("style"); + var styleTokens = styleText.toString().split(";"); + for (var i = 0, j = styleTokens.length; i < j; i++) { + var tokens = p.trim(styleTokens[i].split(":")); + if (tokens[0] === "fill") this.setFill(tokens[1]); + else if (tokens[0] === "fill-opacity") this.setFillOpacity(tokens[1]); + else if (tokens[0] === "stroke") this.setStroke(tokens[1]); + else if (tokens[0] === "stroke-width") this.setStrokeWeight(tokens[1]); + else if (tokens[0] === "stroke-linecap") this.setStrokeCap(tokens[1]); + else if (tokens[0] === "stroke-linejoin") this.setStrokeJoin(tokens[1]); + else if (tokens[0] === "stroke-opacity") this.setStrokeOpacity(tokens[1]); + else if (tokens[0] === "opacity") this.setOpacity(tokens[1]) + } + } + }; + PShapeSVG.prototype.setFillOpacity = function(opacityText) { + this.fillOpacity = parseFloat(opacityText); + this.fillColor = this.fillOpacity * 255 << 24 | this.fillColor & 16777215 + }; + PShapeSVG.prototype.setFill = function(fillText) { + var opacityMask = this.fillColor & 4278190080; + if (fillText === "none") this.fill = false; + else if (fillText.indexOf("#") === 0) { + this.fill = true; + if (fillText.length === 4) fillText = fillText.replace(/#(.)(.)(.)/, "#$1$1$2$2$3$3"); + this.fillColor = opacityMask | parseInt(fillText.substring(1), 16) & 16777215 + } else if (fillText.indexOf("rgb") === 0) { + this.fill = true; + this.fillColor = opacityMask | this.parseRGB(fillText) + } else if (fillText.indexOf("url(#") === 0) this.fillName = fillText.substring(5, fillText.length - 1); + else if (colors[fillText]) { + this.fill = true; + this.fillColor = opacityMask | parseInt(colors[fillText].substring(1), 16) & 16777215 + } + }; + PShapeSVG.prototype.setOpacity = function(opacity) { + this.strokeColor = parseFloat(opacity) * 255 << 24 | this.strokeColor & 16777215; + this.fillColor = parseFloat(opacity) * 255 << 24 | this.fillColor & 16777215 + }; + PShapeSVG.prototype.setStroke = function(strokeText) { + var opacityMask = this.strokeColor & 4278190080; + if (strokeText === "none") this.stroke = false; + else if (strokeText.charAt(0) === "#") { + this.stroke = true; + if (strokeText.length === 4) strokeText = strokeText.replace(/#(.)(.)(.)/, "#$1$1$2$2$3$3"); + this.strokeColor = opacityMask | parseInt(strokeText.substring(1), 16) & 16777215 + } else if (strokeText.indexOf("rgb") === 0) { + this.stroke = true; + this.strokeColor = opacityMask | this.parseRGB(strokeText) + } else if (strokeText.indexOf("url(#") === 0) this.strokeName = strokeText.substring(5, strokeText.length - 1); + else if (colors[strokeText]) { + this.stroke = true; + this.strokeColor = opacityMask | parseInt(colors[strokeText].substring(1), 16) & 16777215 + } + }; + PShapeSVG.prototype.setStrokeWeight = function(weight) { + this.strokeWeight = this.parseUnitSize(weight) + }; + PShapeSVG.prototype.setStrokeJoin = function(linejoin) { + if (linejoin === "miter") this.strokeJoin = 'miter'; + else if (linejoin === "round") this.strokeJoin = 'round'; + else if (linejoin === "bevel") this.strokeJoin = 'bevel' + }; + PShapeSVG.prototype.setStrokeCap = function(linecap) { + if (linecap === "butt") this.strokeCap = 'butt'; + else if (linecap === "round") this.strokeCap = 'round'; + else if (linecap === "square") this.strokeCap = 'square' + }; + PShapeSVG.prototype.setStrokeOpacity = function(opacityText) { + this.strokeOpacity = parseFloat(opacityText); + this.strokeColor = this.strokeOpacity * 255 << 24 | this.strokeColor & 16777215 + }; + PShapeSVG.prototype.parseRGB = function(color) { + var sub = color.substring(color.indexOf("(") + 1, color.indexOf(")")); + var values = sub.split(", "); + return values[0] << 16 | values[1] << 8 | values[2] + }; + PShapeSVG.prototype.parseUnitSize = function(text) { + var len = text.length - 2; + if (len < 0) return text; + if (text.indexOf("pt") === len) return parseFloat(text.substring(0, len)) * 1.25; + if (text.indexOf("pc") === len) return parseFloat(text.substring(0, len)) * 15; + if (text.indexOf("mm") === len) return parseFloat(text.substring(0, len)) * 3.543307; + if (text.indexOf("cm") === len) return parseFloat(text.substring(0, len)) * 35.43307; + if (text.indexOf("in") === len) return parseFloat(text.substring(0, len)) * 90; + if (text.indexOf("px") === len) return parseFloat(text.substring(0, len)); + return parseFloat(text) + }; + p.shape = function(shape, x, y, width, height) { + if (arguments.length >= 1 && arguments[0] !== null) if (shape.isVisible()) { + p.pushMatrix(); + if (curShapeMode === 3) if (arguments.length === 5) { + p.translate(x - width / 2, y - height / 2); + p.scale(width / shape.getWidth(), height / shape.getHeight()) + } else if (arguments.length === 3) p.translate(x - shape.getWidth() / 2, -shape.getHeight() / 2); + else p.translate(-shape.getWidth() / 2, -shape.getHeight() / 2); + else if (curShapeMode === 0) if (arguments.length === 5) { + p.translate(x, y); + p.scale(width / shape.getWidth(), height / shape.getHeight()) + } else { + if (arguments.length === 3) p.translate(x, y) + } else if (curShapeMode === 1) if (arguments.length === 5) { + width -= x; + height -= y; + p.translate(x, y); + p.scale(width / shape.getWidth(), height / shape.getHeight()) + } else if (arguments.length === 3) p.translate(x, y); + shape.draw(p); + if (arguments.length === 1 && curShapeMode === 3 || arguments.length > 1) p.popMatrix() + } + }; + p.shapeMode = function(mode) { + curShapeMode = mode + }; + p.loadShape = function(filename) { + if (arguments.length === 1) if (filename.indexOf(".svg") > -1) return new PShapeSVG(null, filename); + return null + }; + var XMLAttribute = function(fname, n, nameSpace, v, t) { + this.fullName = fname || ""; + this.name = n || ""; + this.namespace = nameSpace || ""; + this.value = v; + this.type = t + }; + XMLAttribute.prototype = { + getName: function() { + return this.name + }, + getFullName: function() { + return this.fullName + }, + getNamespace: function() { + return this.namespace + }, + getValue: function() { + return this.value + }, + getType: function() { + return this.type + }, + setValue: function(newval) { + this.value = newval + } + }; + var XMLElement = p.XMLElement = function(selector, uri, sysid, line) { + this.attributes = []; + this.children = []; + this.fullName = null; + this.name = null; + this.namespace = ""; + this.content = null; + this.parent = null; + this.lineNr = ""; + this.systemID = ""; + this.type = "ELEMENT"; + if (selector) if (typeof selector === "string") if (uri === undef && selector.indexOf("<") > -1) this.parse(selector); + else { + this.fullName = selector; + this.namespace = uri; + this.systemId = sysid; + this.lineNr = line + } else this.parse(uri) + }; + XMLElement.prototype = { + parse: function(textstring) { + var xmlDoc; + try { + var extension = textstring.substring(textstring.length - 4); + if (extension === ".xml" || extension === ".svg") textstring = ajax(textstring); + xmlDoc = (new DOMParser).parseFromString(textstring, "text/xml"); + var elements = xmlDoc.documentElement; + if (elements) this.parseChildrenRecursive(null, elements); + else throw "Error loading document"; + return this + } catch(e) { + throw e; + } + }, + parseChildrenRecursive: function(parent, elementpath) { + var xmlelement, xmlattribute, tmpattrib, l, m, child; + if (!parent) { + this.fullName = elementpath.localName; + this.name = elementpath.nodeName; + xmlelement = this + } else { + xmlelement = new XMLElement(elementpath.nodeName); + xmlelement.parent = parent + } + if (elementpath.nodeType === 3 && elementpath.textContent !== "") return this.createPCDataElement(elementpath.textContent); + if (elementpath.nodeType === 4) return this.createCDataElement(elementpath.textContent); + if (elementpath.attributes) for (l = 0, m = elementpath.attributes.length; l < m; l++) { + tmpattrib = elementpath.attributes[l]; + xmlattribute = new XMLAttribute(tmpattrib.getname, tmpattrib.nodeName, tmpattrib.namespaceURI, tmpattrib.nodeValue, tmpattrib.nodeType); + xmlelement.attributes.push(xmlattribute) + } + if (elementpath.childNodes) for (l = 0, m = elementpath.childNodes.length; l < m; l++) { + var node = elementpath.childNodes[l]; + child = xmlelement.parseChildrenRecursive(xmlelement, node); + if (child !== null) xmlelement.children.push(child) + } + return xmlelement + }, + createElement: function(fullname, namespaceuri, sysid, line) { + if (sysid === undef) return new XMLElement(fullname, namespaceuri); + return new XMLElement(fullname, namespaceuri, sysid, line) + }, + createPCDataElement: function(content, isCDATA) { + if (content.replace(/^\s+$/g, "") === "") return null; + var pcdata = new XMLElement; + pcdata.type = "TEXT"; + pcdata.content = content; + return pcdata + }, + createCDataElement: function(content) { + var cdata = this.createPCDataElement(content); + if (cdata === null) return null; + cdata.type = "CDATA"; + var htmlentities = { + "<": "<", + ">": ">", + "'": "'", + '"': """ + }, + entity; + for (entity in htmlentities) if (!Object.hasOwnProperty(htmlentities, entity)) content = content.replace(new RegExp(entity, "g"), htmlentities[entity]); + cdata.cdata = content; + return cdata + }, + hasAttribute: function() { + if (arguments.length === 1) return this.getAttribute(arguments[0]) !== null; + if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]) !== null + }, + equals: function(other) { + if (! (other instanceof XMLElement)) return false; + var i, j; + if (this.fullName !== other.fullName) return false; + if (this.attributes.length !== other.getAttributeCount()) return false; + if (this.attributes.length !== other.attributes.length) return false; + var attr_name, attr_ns, attr_value, attr_type, attr_other; + for (i = 0, j = this.attributes.length; i < j; i++) { + attr_name = this.attributes[i].getName(); + attr_ns = this.attributes[i].getNamespace(); + attr_other = other.findAttribute(attr_name, attr_ns); + if (attr_other === null) return false; + if (this.attributes[i].getValue() !== attr_other.getValue()) return false; + if (this.attributes[i].getType() !== attr_other.getType()) return false + } + if (this.children.length !== other.getChildCount()) return false; + if (this.children.length > 0) { + var child1, child2; + for (i = 0, j = this.children.length; i < j; i++) { + child1 = this.getChild(i); + child2 = other.getChild(i); + if (!child1.equals(child2)) return false + } + return true + } + return this.content === other.content + }, + getContent: function() { + if (this.type === "TEXT" || this.type === "CDATA") return this.content; + var children = this.children; + if (children.length === 1 && (children[0].type === "TEXT" || children[0].type === "CDATA")) return children[0].content; + return null + }, + getAttribute: function() { + var attribute; + if (arguments.length === 2) { + attribute = this.findAttribute(arguments[0]); + if (attribute) return attribute.getValue(); + return arguments[1] + } else if (arguments.length === 1) { + attribute = this.findAttribute(arguments[0]); + if (attribute) return attribute.getValue(); + return null + } else if (arguments.length === 3) { + attribute = this.findAttribute(arguments[0], arguments[1]); + if (attribute) return attribute.getValue(); + return arguments[2] + } + }, + getStringAttribute: function() { + if (arguments.length === 1) return this.getAttribute(arguments[0]); + if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]); + return this.getAttribute(arguments[0], arguments[1], arguments[2]) + }, + getString: function(attributeName) { + return this.getStringAttribute(attributeName) + }, + getFloatAttribute: function() { + if (arguments.length === 1) return parseFloat(this.getAttribute(arguments[0], 0)); + if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]); + return this.getAttribute(arguments[0], arguments[1], arguments[2]) + }, + getFloat: function(attributeName) { + return this.getFloatAttribute(attributeName) + }, + getIntAttribute: function() { + if (arguments.length === 1) return this.getAttribute(arguments[0], 0); + if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]); + return this.getAttribute(arguments[0], arguments[1], arguments[2]) + }, + getInt: function(attributeName) { + return this.getIntAttribute(attributeName) + }, + hasChildren: function() { + return this.children.length > 0 + }, + addChild: function(child) { + if (child !== null) { + child.parent = this; + this.children.push(child) + } + }, + insertChild: function(child, index) { + if (child) { + if (child.getLocalName() === null && !this.hasChildren()) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild.getLocalName() === null) { + lastChild.setContent(lastChild.getContent() + child.getContent()); + return + } + } + child.parent = this; + this.children.splice(index, 0, child) + } + }, + getChild: function(selector) { + if (typeof selector === "number") return this.children[selector]; + if (selector.indexOf("/") !== -1) return this.getChildRecursive(selector.split("/"), 0); + var kid, kidName; + for (var i = 0, j = this.getChildCount(); i < j; i++) { + kid = this.getChild(i); + kidName = kid.getName(); + if (kidName !== null && kidName === selector) return kid + } + return null + }, + getChildren: function() { + if (arguments.length === 1) { + if (typeof arguments[0] === "number") return this.getChild(arguments[0]); + if (arguments[0].indexOf("/") !== -1) return this.getChildrenRecursive(arguments[0].split("/"), 0); + var matches = []; + var kid, kidName; + for (var i = 0, j = this.getChildCount(); i < j; i++) { + kid = this.getChild(i); + kidName = kid.getName(); + if (kidName !== null && kidName === arguments[0]) matches.push(kid) + } + return matches + } + return this.children + }, + getChildCount: function() { + return this.children.length + }, + getChildRecursive: function(items, offset) { + if (offset === items.length) return this; + var kid, kidName, matchName = items[offset]; + for (var i = 0, j = this.getChildCount(); i < j; i++) { + kid = this.getChild(i); + kidName = kid.getName(); + if (kidName !== null && kidName === matchName) return kid.getChildRecursive(items, offset + 1) + } + return null + }, + getChildrenRecursive: function(items, offset) { + if (offset === items.length - 1) return this.getChildren(items[offset]); + var matches = this.getChildren(items[offset]); + var kidMatches = []; + for (var i = 0; i < matches.length; i++) kidMatches = kidMatches.concat(matches[i].getChildrenRecursive(items, offset + 1)); + return kidMatches + }, + isLeaf: function() { + return !this.hasChildren() + }, + listChildren: function() { + var arr = []; + for (var i = 0, j = this.children.length; i < j; i++) arr.push(this.getChild(i).getName()); + return arr + }, + removeAttribute: function(name, namespace) { + this.namespace = namespace || ""; + for (var i = 0, j = this.attributes.length; i < j; i++) if (this.attributes[i].getName() === name && this.attributes[i].getNamespace() === this.namespace) { + this.attributes.splice(i, 1); + break + } + }, + removeChild: function(child) { + if (child) for (var i = 0, j = this.children.length; i < j; i++) if (this.children[i].equals(child)) { + this.children.splice(i, 1); + break + } + }, + removeChildAtIndex: function(index) { + if (this.children.length > index) this.children.splice(index, 1) + }, + findAttribute: function(name, namespace) { + this.namespace = namespace || ""; + for (var i = 0, j = this.attributes.length; i < j; i++) if (this.attributes[i].getName() === name && this.attributes[i].getNamespace() === this.namespace) return this.attributes[i]; + return null + }, + setAttribute: function() { + var attr; + if (arguments.length === 3) { + var index = arguments[0].indexOf(":"); + var name = arguments[0].substring(index + 1); + attr = this.findAttribute(name, arguments[1]); + if (attr) attr.setValue(arguments[2]); + else { + attr = new XMLAttribute(arguments[0], name, arguments[1], arguments[2], "CDATA"); + this.attributes.push(attr) + } + } else { + attr = this.findAttribute(arguments[0]); + if (attr) attr.setValue(arguments[1]); + else { + attr = new XMLAttribute(arguments[0], arguments[0], null, arguments[1], "CDATA"); + this.attributes.push(attr) + } + } + }, + setString: function(attribute, value) { + this.setAttribute(attribute, value) + }, + setInt: function(attribute, value) { + this.setAttribute(attribute, value) + }, + setFloat: function(attribute, value) { + this.setAttribute(attribute, value) + }, + setContent: function(content) { + if (this.children.length > 0) Processing.debug("Tried to set content for XMLElement with children"); + this.content = content + }, + setName: function() { + if (arguments.length === 1) { + this.name = arguments[0]; + this.fullName = arguments[0]; + this.namespace = null + } else { + var index = arguments[0].indexOf(":"); + if (arguments[1] === null || index < 0) this.name = arguments[0]; + else this.name = arguments[0].substring(index + 1); + this.fullName = arguments[0]; + this.namespace = arguments[1] + } + }, + getName: function() { + return this.fullName + }, + getLocalName: function() { + return this.name + }, + getAttributeCount: function() { + return this.attributes.length + }, + toString: function() { + if (this.type === "TEXT") return this.content; + if (this.type === "CDATA") return this.cdata; + var tagstring = this.fullName; + var xmlstring = "<" + tagstring; + var a, c; + for (a = 0; a < this.attributes.length; a++) { + var attr = this.attributes[a]; + xmlstring += " " + attr.getName() + "=" + '"' + attr.getValue() + '"' + } + if (this.children.length === 0) if (this.content === "") xmlstring += "/>"; + else xmlstring += ">" + this.content + ""; + else { + xmlstring += ">"; + for (c = 0; c < this.children.length; c++) xmlstring += this.children[c].toString(); + xmlstring += "" + } + return xmlstring + } + }; + XMLElement.parse = function(xmlstring) { + var element = new XMLElement; + element.parse(xmlstring); + return element + }; + var XML = p.XML = p.XMLElement; + p.loadXML = function(uri) { + return new XML(p, uri) + }; + var printMatrixHelper = function(elements) { + var big = 0; + for (var i = 0; i < elements.length; i++) if (i !== 0) big = Math.max(big, Math.abs(elements[i])); + else big = Math.abs(elements[i]); + var digits = (big + "").indexOf("."); + if (digits === 0) digits = 1; + else if (digits === -1) digits = (big + "").length; + return digits + }; + var PMatrix2D = p.PMatrix2D = function() { + if (arguments.length === 0) this.reset(); + else if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) this.set(arguments[0].array()); + else if (arguments.length === 6) this.set(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]) + }; + PMatrix2D.prototype = { + set: function() { + if (arguments.length === 6) { + var a = arguments; + this.set([a[0], a[1], a[2], a[3], a[4], a[5]]) + } else if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) this.elements = arguments[0].array(); + else if (arguments.length === 1 && arguments[0] instanceof Array) this.elements = arguments[0].slice() + }, + get: function() { + var outgoing = new PMatrix2D; + outgoing.set(this.elements); + return outgoing + }, + reset: function() { + this.set([1, 0, 0, 0, 1, 0]) + }, + array: function array() { + return this.elements.slice() + }, + translate: function(tx, ty) { + this.elements[2] = tx * this.elements[0] + ty * this.elements[1] + this.elements[2]; + this.elements[5] = tx * this.elements[3] + ty * this.elements[4] + this.elements[5] + }, + invTranslate: function(tx, ty) { + this.translate(-tx, -ty) + }, + transpose: function() {}, + mult: function(source, target) { + var x, y; + if (source instanceof + PVector) { + x = source.x; + y = source.y; + if (!target) target = new PVector + } else if (source instanceof Array) { + x = source[0]; + y = source[1]; + if (!target) target = [] + } + if (target instanceof Array) { + target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2]; + target[1] = this.elements[3] * x + this.elements[4] * y + this.elements[5] + } else if (target instanceof PVector) { + target.x = this.elements[0] * x + this.elements[1] * y + this.elements[2]; + target.y = this.elements[3] * x + this.elements[4] * y + this.elements[5]; + target.z = 0 + } + return target + }, + multX: function(x, y) { + return x * this.elements[0] + y * this.elements[1] + this.elements[2] + }, + multY: function(x, y) { + return x * this.elements[3] + y * this.elements[4] + this.elements[5] + }, + skewX: function(angle) { + this.apply(1, 0, 1, angle, 0, 0) + }, + skewY: function(angle) { + this.apply(1, 0, 1, 0, angle, 0) + }, + shearX: function(angle) { + this.apply(1, 0, 1, Math.tan(angle), 0, 0) + }, + shearY: function(angle) { + this.apply(1, 0, 1, 0, Math.tan(angle), 0) + }, + determinant: function() { + return this.elements[0] * this.elements[4] - this.elements[1] * this.elements[3] + }, + invert: function() { + var d = this.determinant(); + if (Math.abs(d) > -2147483648) { + var old00 = this.elements[0]; + var old01 = this.elements[1]; + var old02 = this.elements[2]; + var old10 = this.elements[3]; + var old11 = this.elements[4]; + var old12 = this.elements[5]; + this.elements[0] = old11 / d; + this.elements[3] = -old10 / d; + this.elements[1] = -old01 / d; + this.elements[4] = old00 / d; + this.elements[2] = (old01 * old12 - old11 * old02) / d; + this.elements[5] = (old10 * old02 - old00 * old12) / d; + return true + } + return false + }, + scale: function(sx, sy) { + if (sx && !sy) sy = sx; + if (sx && sy) { + this.elements[0] *= sx; + this.elements[1] *= sy; + this.elements[3] *= sx; + this.elements[4] *= sy + } + }, + invScale: function(sx, sy) { + if (sx && !sy) sy = sx; + this.scale(1 / sx, 1 / sy) + }, + apply: function() { + var source; + if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) source = arguments[0].array(); + else if (arguments.length === 6) source = Array.prototype.slice.call(arguments); + else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0]; + var result = [0, 0, this.elements[2], 0, 0, this.elements[5]]; + var e = 0; + for (var row = 0; row < 2; row++) for (var col = 0; col < 3; col++, e++) result[e] += this.elements[row * 3 + 0] * source[col + 0] + this.elements[row * 3 + 1] * source[col + 3]; + this.elements = result.slice() + }, + preApply: function() { + var source; + if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) source = arguments[0].array(); + else if (arguments.length === 6) source = Array.prototype.slice.call(arguments); + else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0]; + var result = [0, 0, source[2], 0, 0, source[5]]; + result[2] = source[2] + this.elements[2] * source[0] + this.elements[5] * source[1]; + result[5] = source[5] + this.elements[2] * source[3] + this.elements[5] * source[4]; + result[0] = this.elements[0] * source[0] + this.elements[3] * source[1]; + result[3] = this.elements[0] * source[3] + this.elements[3] * source[4]; + result[1] = this.elements[1] * source[0] + this.elements[4] * source[1]; + result[4] = this.elements[1] * source[3] + this.elements[4] * source[4]; + this.elements = result.slice() + }, + rotate: function(angle) { + var c = Math.cos(angle); + var s = Math.sin(angle); + var temp1 = this.elements[0]; + var temp2 = this.elements[1]; + this.elements[0] = c * temp1 + s * temp2; + this.elements[1] = -s * temp1 + c * temp2; + temp1 = this.elements[3]; + temp2 = this.elements[4]; + this.elements[3] = c * temp1 + s * temp2; + this.elements[4] = -s * temp1 + c * temp2 + }, + rotateZ: function(angle) { + this.rotate(angle) + }, + invRotateZ: function(angle) { + this.rotateZ(angle - Math.PI) + }, + print: function() { + var digits = printMatrixHelper(this.elements); + var output = "" + p.nfs(this.elements[0], digits, 4) + " " + p.nfs(this.elements[1], digits, 4) + " " + p.nfs(this.elements[2], digits, 4) + "\n" + p.nfs(this.elements[3], digits, 4) + " " + p.nfs(this.elements[4], digits, 4) + " " + p.nfs(this.elements[5], digits, 4) + "\n\n"; + p.println(output) + } + }; + var PMatrix3D = p.PMatrix3D = function() { + this.reset() + }; + PMatrix3D.prototype = { + set: function() { + if (arguments.length === 16) this.elements = Array.prototype.slice.call(arguments); + else if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) this.elements = arguments[0].array(); + else if (arguments.length === 1 && arguments[0] instanceof Array) this.elements = arguments[0].slice() + }, + get: function() { + var outgoing = new PMatrix3D; + outgoing.set(this.elements); + return outgoing + }, + reset: function() { + this.elements = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] + }, + array: function array() { + return this.elements.slice() + }, + translate: function(tx, ty, tz) { + if (tz === undef) tz = 0; + this.elements[3] += tx * this.elements[0] + ty * this.elements[1] + tz * this.elements[2]; + this.elements[7] += tx * this.elements[4] + ty * this.elements[5] + tz * this.elements[6]; + this.elements[11] += tx * this.elements[8] + ty * this.elements[9] + tz * this.elements[10]; + this.elements[15] += tx * this.elements[12] + ty * this.elements[13] + tz * this.elements[14] + }, + transpose: function() { + var temp = this.elements[4]; + this.elements[4] = this.elements[1]; + this.elements[1] = temp; + temp = this.elements[8]; + this.elements[8] = this.elements[2]; + this.elements[2] = temp; + temp = this.elements[6]; + this.elements[6] = this.elements[9]; + this.elements[9] = temp; + temp = this.elements[3]; + this.elements[3] = this.elements[12]; + this.elements[12] = temp; + temp = this.elements[7]; + this.elements[7] = this.elements[13]; + this.elements[13] = temp; + temp = this.elements[11]; + this.elements[11] = this.elements[14]; + this.elements[14] = temp + }, + mult: function(source, target) { + var x, y, z, w; + if (source instanceof + PVector) { + x = source.x; + y = source.y; + z = source.z; + w = 1; + if (!target) target = new PVector + } else if (source instanceof Array) { + x = source[0]; + y = source[1]; + z = source[2]; + w = source[3] || 1; + if (!target || target.length !== 3 && target.length !== 4) target = [0, 0, 0] + } + if (target instanceof Array) if (target.length === 3) { + target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3]; + target[1] = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7]; + target[2] = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] + } else if (target.length === 4) { + target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3] * w; + target[1] = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7] * w; + target[2] = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] * w; + target[3] = this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15] * w + } + if (target instanceof PVector) { + target.x = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3]; + target.y = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7]; + target.z = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] + } + return target + }, + preApply: function() { + var source; + if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) source = arguments[0].array(); + else if (arguments.length === 16) source = Array.prototype.slice.call(arguments); + else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0]; + var result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + var e = 0; + for (var row = 0; row < 4; row++) for (var col = 0; col < 4; col++, e++) result[e] += this.elements[col + 0] * source[row * 4 + 0] + this.elements[col + 4] * source[row * 4 + 1] + this.elements[col + 8] * source[row * 4 + 2] + this.elements[col + 12] * source[row * 4 + 3]; + this.elements = result.slice() + }, + apply: function() { + var source; + if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) source = arguments[0].array(); + else if (arguments.length === 16) source = Array.prototype.slice.call(arguments); + else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0]; + var result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + var e = 0; + for (var row = 0; row < 4; row++) for (var col = 0; col < 4; col++, e++) result[e] += this.elements[row * 4 + 0] * source[col + 0] + this.elements[row * 4 + 1] * source[col + 4] + this.elements[row * 4 + 2] * source[col + 8] + this.elements[row * 4 + 3] * source[col + 12]; + this.elements = result.slice() + }, + rotate: function(angle, v0, v1, v2) { + if (!v1) this.rotateZ(angle); + else { + var c = p.cos(angle); + var s = p.sin(angle); + var t = 1 - c; + this.apply(t * v0 * v0 + c, t * v0 * v1 - s * v2, t * v0 * v2 + s * v1, 0, t * v0 * v1 + s * v2, t * v1 * v1 + c, t * v1 * v2 - s * v0, 0, t * v0 * v2 - s * v1, t * v1 * v2 + s * v0, t * v2 * v2 + c, 0, 0, 0, 0, 1) + } + }, + invApply: function() { + if (inverseCopy === undef) inverseCopy = new PMatrix3D; + var a = arguments; + inverseCopy.set(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]); + if (!inverseCopy.invert()) return false; + this.preApply(inverseCopy); + return true + }, + rotateX: function(angle) { + var c = p.cos(angle); + var s = p.sin(angle); + this.apply([1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1]) + }, + rotateY: function(angle) { + var c = p.cos(angle); + var s = p.sin(angle); + this.apply([c, + 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1]) + }, + rotateZ: function(angle) { + var c = Math.cos(angle); + var s = Math.sin(angle); + this.apply([c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]) + }, + scale: function(sx, sy, sz) { + if (sx && !sy && !sz) sy = sz = sx; + else if (sx && sy && !sz) sz = 1; + if (sx && sy && sz) { + this.elements[0] *= sx; + this.elements[1] *= sy; + this.elements[2] *= sz; + this.elements[4] *= sx; + this.elements[5] *= sy; + this.elements[6] *= sz; + this.elements[8] *= sx; + this.elements[9] *= sy; + this.elements[10] *= sz; + this.elements[12] *= sx; + this.elements[13] *= sy; + this.elements[14] *= sz + } + }, + skewX: function(angle) { + var t = Math.tan(angle); + this.apply(1, t, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) + }, + skewY: function(angle) { + var t = Math.tan(angle); + this.apply(1, 0, 0, 0, t, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) + }, + shearX: function(angle) { + var t = Math.tan(angle); + this.apply(1, t, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) + }, + shearY: function(angle) { + var t = Math.tan(angle); + this.apply(1, 0, 0, 0, t, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) + }, + multX: function(x, y, z, w) { + if (!z) return this.elements[0] * x + this.elements[1] * y + this.elements[3]; + if (!w) return this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3]; + return this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3] * w + }, + multY: function(x, y, z, w) { + if (!z) return this.elements[4] * x + this.elements[5] * y + this.elements[7]; + if (!w) return this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7]; + return this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7] * w + }, + multZ: function(x, y, z, w) { + if (!w) return this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11]; + return this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] * w + }, + multW: function(x, y, z, w) { + if (!w) return this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15]; + return this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15] * w + }, + invert: function() { + var fA0 = this.elements[0] * this.elements[5] - this.elements[1] * this.elements[4]; + var fA1 = this.elements[0] * this.elements[6] - this.elements[2] * this.elements[4]; + var fA2 = this.elements[0] * this.elements[7] - this.elements[3] * this.elements[4]; + var fA3 = this.elements[1] * this.elements[6] - this.elements[2] * this.elements[5]; + var fA4 = this.elements[1] * this.elements[7] - this.elements[3] * this.elements[5]; + var fA5 = this.elements[2] * this.elements[7] - this.elements[3] * this.elements[6]; + var fB0 = this.elements[8] * this.elements[13] - this.elements[9] * this.elements[12]; + var fB1 = this.elements[8] * this.elements[14] - this.elements[10] * this.elements[12]; + var fB2 = this.elements[8] * this.elements[15] - this.elements[11] * this.elements[12]; + var fB3 = this.elements[9] * this.elements[14] - this.elements[10] * this.elements[13]; + var fB4 = this.elements[9] * this.elements[15] - this.elements[11] * this.elements[13]; + var fB5 = this.elements[10] * this.elements[15] - this.elements[11] * this.elements[14]; + var fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0; + if (Math.abs(fDet) <= 1.0E-9) return false; + var kInv = []; + kInv[0] = +this.elements[5] * fB5 - this.elements[6] * fB4 + this.elements[7] * fB3; + kInv[4] = -this.elements[4] * fB5 + this.elements[6] * fB2 - this.elements[7] * fB1; + kInv[8] = +this.elements[4] * fB4 - this.elements[5] * fB2 + this.elements[7] * fB0; + kInv[12] = -this.elements[4] * fB3 + this.elements[5] * fB1 - this.elements[6] * fB0; + kInv[1] = -this.elements[1] * fB5 + this.elements[2] * fB4 - this.elements[3] * fB3; + kInv[5] = +this.elements[0] * fB5 - this.elements[2] * fB2 + this.elements[3] * fB1; + kInv[9] = -this.elements[0] * fB4 + this.elements[1] * fB2 - this.elements[3] * fB0; + kInv[13] = +this.elements[0] * fB3 - this.elements[1] * fB1 + this.elements[2] * fB0; + kInv[2] = +this.elements[13] * fA5 - this.elements[14] * fA4 + this.elements[15] * fA3; + kInv[6] = -this.elements[12] * fA5 + this.elements[14] * fA2 - this.elements[15] * fA1; + kInv[10] = +this.elements[12] * fA4 - this.elements[13] * fA2 + this.elements[15] * fA0; + kInv[14] = -this.elements[12] * fA3 + this.elements[13] * fA1 - this.elements[14] * fA0; + kInv[3] = -this.elements[9] * fA5 + this.elements[10] * fA4 - this.elements[11] * fA3; + kInv[7] = +this.elements[8] * fA5 - this.elements[10] * fA2 + this.elements[11] * fA1; + kInv[11] = -this.elements[8] * fA4 + this.elements[9] * fA2 - this.elements[11] * fA0; + kInv[15] = +this.elements[8] * fA3 - this.elements[9] * fA1 + this.elements[10] * fA0; + var fInvDet = 1 / fDet; + kInv[0] *= fInvDet; + kInv[1] *= fInvDet; + kInv[2] *= fInvDet; + kInv[3] *= fInvDet; + kInv[4] *= fInvDet; + kInv[5] *= fInvDet; + kInv[6] *= fInvDet; + kInv[7] *= fInvDet; + kInv[8] *= fInvDet; + kInv[9] *= fInvDet; + kInv[10] *= fInvDet; + kInv[11] *= fInvDet; + kInv[12] *= fInvDet; + kInv[13] *= fInvDet; + kInv[14] *= fInvDet; + kInv[15] *= fInvDet; + this.elements = kInv.slice(); + return true + }, + toString: function() { + var str = ""; + for (var i = 0; i < 15; i++) str += this.elements[i] + ", "; + str += this.elements[15]; + return str + }, + print: function() { + var digits = printMatrixHelper(this.elements); + var output = "" + p.nfs(this.elements[0], digits, 4) + " " + p.nfs(this.elements[1], digits, 4) + " " + p.nfs(this.elements[2], digits, 4) + " " + p.nfs(this.elements[3], digits, 4) + "\n" + p.nfs(this.elements[4], digits, 4) + " " + p.nfs(this.elements[5], digits, 4) + " " + p.nfs(this.elements[6], digits, 4) + " " + p.nfs(this.elements[7], digits, 4) + "\n" + p.nfs(this.elements[8], digits, 4) + " " + p.nfs(this.elements[9], digits, 4) + " " + p.nfs(this.elements[10], digits, 4) + " " + p.nfs(this.elements[11], digits, 4) + "\n" + p.nfs(this.elements[12], digits, 4) + " " + p.nfs(this.elements[13], digits, 4) + " " + p.nfs(this.elements[14], digits, 4) + " " + p.nfs(this.elements[15], digits, 4) + "\n\n"; + p.println(output) + }, + invTranslate: function(tx, ty, tz) { + this.preApply(1, 0, 0, -tx, 0, 1, 0, -ty, 0, 0, 1, -tz, 0, 0, 0, 1) + }, + invRotateX: function(angle) { + var c = Math.cos(-angle); + var s = Math.sin(-angle); + this.preApply([1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1]) + }, + invRotateY: function(angle) { + var c = Math.cos(-angle); + var s = Math.sin(-angle); + this.preApply([c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1]) + }, + invRotateZ: function(angle) { + var c = Math.cos(-angle); + var s = Math.sin(-angle); + this.preApply([c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]) + }, + invScale: function(x, y, z) { + this.preApply([1 / x, 0, 0, 0, 0, 1 / y, 0, 0, 0, 0, 1 / z, 0, 0, 0, 0, 1]) + } + }; + var PMatrixStack = p.PMatrixStack = function() { + this.matrixStack = [] + }; + PMatrixStack.prototype.load = function() { + var tmpMatrix = drawing.$newPMatrix(); + if (arguments.length === 1) tmpMatrix.set(arguments[0]); + else tmpMatrix.set(arguments); + this.matrixStack.push(tmpMatrix) + }; + Drawing2D.prototype.$newPMatrix = function() { + return new PMatrix2D + }; + Drawing3D.prototype.$newPMatrix = function() { + return new PMatrix3D + }; + PMatrixStack.prototype.push = function() { + this.matrixStack.push(this.peek()) + }; + PMatrixStack.prototype.pop = function() { + return this.matrixStack.pop() + }; + PMatrixStack.prototype.peek = function() { + var tmpMatrix = drawing.$newPMatrix(); + tmpMatrix.set(this.matrixStack[this.matrixStack.length - 1]); + return tmpMatrix + }; + PMatrixStack.prototype.mult = function(matrix) { + this.matrixStack[this.matrixStack.length - 1].apply(matrix) + }; + p.split = function(str, delim) { + return str.split(delim) + }; + p.splitTokens = function(str, tokens) { + if (tokens === undef) return str.split(/\s+/g); + var chars = tokens.split(/()/g), + buffer = "", + len = str.length, + i, c, tokenized = []; + for (i = 0; i < len; i++) { + c = str[i]; + if (chars.indexOf(c) > -1) { + if (buffer !== "") tokenized.push(buffer); + buffer = "" + } else buffer += c + } + if (buffer !== "") tokenized.push(buffer); + return tokenized + }; + p.append = function(array, element) { + array[array.length] = element; + return array + }; + p.concat = function(array1, array2) { + return array1.concat(array2) + }; + p.sort = function(array, numElem) { + var ret = []; + if (array.length > 0) { + var elemsToCopy = numElem > 0 ? numElem : array.length; + for (var i = 0; i < elemsToCopy; i++) ret.push(array[i]); + if (typeof array[0] === "string") ret.sort(); + else ret.sort(function(a, b) { + return a - b + }); + if (numElem > 0) for (var j = ret.length; j < array.length; j++) ret.push(array[j]) + } + return ret + }; + p.splice = function(array, value, index) { + if (value.length === 0) return array; + if (value instanceof Array) for (var i = 0, j = index; i < value.length; j++, i++) array.splice(j, 0, value[i]); + else array.splice(index, 0, value); + return array + }; + p.subset = function(array, offset, length) { + var end = length !== undef ? offset + length : array.length; + return array.slice(offset, end) + }; + p.join = function(array, seperator) { + return array.join(seperator) + }; + p.shorten = function(ary) { + var newary = []; + var len = ary.length; + for (var i = 0; i < len; i++) newary[i] = ary[i]; + newary.pop(); + return newary + }; + p.expand = function(ary, targetSize) { + var temp = ary.slice(0), + newSize = targetSize || ary.length * 2; + temp.length = newSize; + return temp + }; + p.arrayCopy = function() { + var src, srcPos = 0, + dest, destPos = 0, + length; + if (arguments.length === 2) { + src = arguments[0]; + dest = arguments[1]; + length = src.length + } else if (arguments.length === 3) { + src = arguments[0]; + dest = arguments[1]; + length = arguments[2] + } else if (arguments.length === 5) { + src = arguments[0]; + srcPos = arguments[1]; + dest = arguments[2]; + destPos = arguments[3]; + length = arguments[4] + } + for (var i = srcPos, j = destPos; i < length + srcPos; i++, j++) if (dest[j] !== undef) dest[j] = src[i]; + else throw "array index out of bounds exception"; + }; + p.reverse = function(array) { + return array.reverse() + }; + p.mix = function(a, b, f) { + return a + ((b - a) * f >> 8) + }; + p.peg = function(n) { + return n < 0 ? 0 : n > 255 ? 255 : n + }; + p.modes = function() { + var ALPHA_MASK = 4278190080, + RED_MASK = 16711680, + GREEN_MASK = 65280, + BLUE_MASK = 255, + min = Math.min, + max = Math.max; + + function applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) { + var a = min(((c1 & 4278190080) >>> 24) + f, 255) << 24; + var r = ar + ((cr - ar) * f >> 8); + r = (r < 0 ? 0 : r > 255 ? 255 : r) << 16; + var g = ag + ((cg - ag) * f >> 8); + g = (g < 0 ? 0 : g > 255 ? 255 : g) << 8; + var b = ab + ((cb - ab) * f >> 8); + b = b < 0 ? 0 : b > 255 ? 255 : b; + return a | r | g | b + } + return { + replace: function(c1, c2) { + return c2 + }, + blend: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = c1 & RED_MASK, + ag = c1 & GREEN_MASK, + ab = c1 & BLUE_MASK, + br = c2 & RED_MASK, + bg = c2 & GREEN_MASK, + bb = c2 & BLUE_MASK; + return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | ar + ((br - ar) * f >> 8) & RED_MASK | ag + ((bg - ag) * f >> 8) & GREEN_MASK | ab + ((bb - ab) * f >> 8) & BLUE_MASK + }, + add: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24; + return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | min((c1 & RED_MASK) + ((c2 & RED_MASK) >> 8) * f, RED_MASK) & RED_MASK | min((c1 & GREEN_MASK) + ((c2 & GREEN_MASK) >> 8) * f, GREEN_MASK) & GREEN_MASK | min((c1 & BLUE_MASK) + ((c2 & BLUE_MASK) * f >> 8), BLUE_MASK) + }, + subtract: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24; + return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | max((c1 & RED_MASK) - ((c2 & RED_MASK) >> 8) * f, GREEN_MASK) & RED_MASK | max((c1 & GREEN_MASK) - ((c2 & GREEN_MASK) >> 8) * f, BLUE_MASK) & GREEN_MASK | max((c1 & BLUE_MASK) - ((c2 & BLUE_MASK) * f >> 8), 0) + }, + lightest: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24; + return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | max(c1 & RED_MASK, ((c2 & RED_MASK) >> 8) * f) & RED_MASK | max(c1 & GREEN_MASK, ((c2 & GREEN_MASK) >> 8) * f) & GREEN_MASK | max(c1 & BLUE_MASK, (c2 & BLUE_MASK) * f >> 8) + }, + darkest: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = c1 & RED_MASK, + ag = c1 & GREEN_MASK, + ab = c1 & BLUE_MASK, + br = min(c1 & RED_MASK, ((c2 & RED_MASK) >> 8) * f), + bg = min(c1 & GREEN_MASK, ((c2 & GREEN_MASK) >> 8) * f), + bb = min(c1 & BLUE_MASK, (c2 & BLUE_MASK) * f >> 8); + return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | ar + ((br - ar) * f >> 8) & RED_MASK | ag + ((bg - ag) * f >> 8) & GREEN_MASK | ab + ((bb - ab) * f >> 8) & BLUE_MASK + }, + difference: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = ar > br ? ar - br : br - ar, + cg = ag > bg ? ag - bg : bg - ag, + cb = ab > bb ? ab - bb : bb - ab; + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + exclusion: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = ar + br - (ar * br >> 7), + cg = ag + bg - (ag * bg >> 7), + cb = ab + bb - (ab * bb >> 7); + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + multiply: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = ar * br >> 8, + cg = ag * bg >> 8, + cb = ab * bb >> 8; + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + screen: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = 255 - ((255 - ar) * (255 - br) >> 8), + cg = 255 - ((255 - ag) * (255 - bg) >> 8), + cb = 255 - ((255 - ab) * (255 - bb) >> 8); + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + hard_light: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = br < 128 ? ar * br >> 7 : 255 - ((255 - ar) * (255 - br) >> 7), + cg = bg < 128 ? ag * bg >> 7 : 255 - ((255 - ag) * (255 - bg) >> 7), + cb = bb < 128 ? ab * bb >> 7 : 255 - ((255 - ab) * (255 - bb) >> 7); + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + soft_light: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = (ar * br >> 7) + (ar * ar >> 8) - (ar * ar * br >> 15), + cg = (ag * bg >> 7) + (ag * ag >> 8) - (ag * ag * bg >> 15), + cb = (ab * bb >> 7) + (ab * ab >> 8) - (ab * ab * bb >> 15); + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + overlay: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = ar < 128 ? ar * br >> 7 : 255 - ((255 - ar) * (255 - br) >> 7), + cg = ag < 128 ? ag * bg >> 7 : 255 - ((255 - ag) * (255 - bg) >> 7), + cb = ab < 128 ? ab * bb >> 7 : 255 - ((255 - ab) * (255 - bb) >> 7); + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + dodge: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK; + var cr = 255; + if (br !== 255) { + cr = (ar << 8) / (255 - br); + cr = cr < 0 ? 0 : cr > 255 ? 255 : cr + } + var cg = 255; + if (bg !== 255) { + cg = (ag << 8) / (255 - bg); + cg = cg < 0 ? 0 : cg > 255 ? 255 : cg + } + var cb = 255; + if (bb !== 255) { + cb = (ab << 8) / (255 - bb); + cb = cb < 0 ? 0 : cb > 255 ? 255 : cb + } + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + burn: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK; + var cr = 0; + if (br !== 0) { + cr = (255 - ar << 8) / br; + cr = 255 - (cr < 0 ? 0 : cr > 255 ? 255 : cr) + } + var cg = 0; + if (bg !== 0) { + cg = (255 - ag << 8) / bg; + cg = 255 - (cg < 0 ? 0 : cg > 255 ? 255 : cg) + } + var cb = 0; + if (bb !== 0) { + cb = (255 - ab << 8) / bb; + cb = 255 - (cb < 0 ? 0 : cb > 255 ? 255 : cb) + } + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + } + } + }(); + + function color$4(aValue1, aValue2, aValue3, aValue4) { + var r, g, b, a; + if (curColorMode === 3) { + var rgb = p.color.toRGB(aValue1, aValue2, aValue3); + r = rgb[0]; + g = rgb[1]; + b = rgb[2] + } else { + r = Math.round(255 * (aValue1 / colorModeX)); + g = Math.round(255 * (aValue2 / colorModeY)); + b = Math.round(255 * (aValue3 / colorModeZ)) + } + a = Math.round(255 * (aValue4 / colorModeA)); + r = r < 0 ? 0 : r; + g = g < 0 ? 0 : g; + b = b < 0 ? 0 : b; + a = a < 0 ? 0 : a; + r = r > 255 ? 255 : r; + g = g > 255 ? 255 : g; + b = b > 255 ? 255 : b; + a = a > 255 ? 255 : a; + return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255 + } + function color$2(aValue1, aValue2) { + var a; + if (aValue1 & 4278190080) { + a = Math.round(255 * (aValue2 / colorModeA)); + a = a > 255 ? 255 : a; + a = a < 0 ? 0 : a; + return aValue1 - (aValue1 & 4278190080) + (a << 24 & 4278190080) + } + if (curColorMode === 1) return color$4(aValue1, aValue1, aValue1, aValue2); + if (curColorMode === 3) return color$4(0, 0, aValue1 / colorModeX * colorModeZ, aValue2) + } + function color$1(aValue1) { + if (aValue1 <= colorModeX && aValue1 >= 0) { + if (curColorMode === 1) return color$4(aValue1, aValue1, aValue1, colorModeA); + if (curColorMode === 3) return color$4(0, 0, aValue1 / colorModeX * colorModeZ, colorModeA) + } + if (aValue1) { + if (aValue1 > 2147483647) aValue1 -= 4294967296; + return aValue1 + } + } + p.color = function(aValue1, aValue2, aValue3, aValue4) { + if (aValue1 !== undef && aValue2 !== undef && aValue3 !== undef && aValue4 !== undef) return color$4(aValue1, aValue2, aValue3, aValue4); + if (aValue1 !== undef && aValue2 !== undef && aValue3 !== undef) return color$4(aValue1, aValue2, aValue3, colorModeA); + if (aValue1 !== undef && aValue2 !== undef) return color$2(aValue1, aValue2); + if (typeof aValue1 === "number") return color$1(aValue1); + return color$4(colorModeX, colorModeY, colorModeZ, colorModeA) + }; + p.color.toString = function(colorInt) { + return "rgba(" + ((colorInt >> 16) & 255) + "," + ((colorInt >> 8) & 255) + "," + (colorInt & 255) + "," + ((colorInt >> 24) & 255) / 255 + ")" + }; + p.color.toInt = function(r, g, b, a) { + return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255 + }; + p.color.toArray = function(colorInt) { + return [(colorInt >> 16) & 255, (colorInt >> 8) & 255, colorInt & 255, (colorInt >> 24) & 255] + }; + p.color.toGLArray = function(colorInt) { + return [((colorInt & 16711680) >>> 16) / 255, ((colorInt >> 8) & 255) / 255, (colorInt & 255) / 255, ((colorInt >> 24) & 255) / 255] + }; + p.color.toRGB = function(h, s, b) { + h = h > colorModeX ? colorModeX : h; + s = s > colorModeY ? colorModeY : s; + b = b > colorModeZ ? colorModeZ : b; + h = h / colorModeX * 360; + s = s / colorModeY * 100; + b = b / colorModeZ * 100; + var br = Math.round(b / 100 * 255); + if (s === 0) return [br, br, br]; + var hue = h % 360; + var f = hue % 60; + var p = Math.round(b * (100 - s) / 1E4 * 255); + var q = Math.round(b * (6E3 - s * f) / 6E5 * 255); + var t = Math.round(b * (6E3 - s * (60 - f)) / 6E5 * 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 colorToHSB(colorInt) { + var red, green, blue; + red = ((colorInt >> 16) & 255) / 255; + green = ((colorInt >> 8) & 255) / 255; + blue = (colorInt & 255) / 255; + var max = p.max(p.max(red, green), blue), + min = p.min(p.min(red, green), blue), + hue, saturation; + if (min === max) return [0, 0, max * colorModeZ]; + saturation = (max - min) / max; + if (red === max) hue = (green - blue) / (max - min); + else if (green === max) hue = 2 + (blue - red) / (max - min); + else hue = 4 + (red - green) / (max - min); + hue /= 6; + if (hue < 0) hue += 1; + else if (hue > 1) hue -= 1; + return [hue * colorModeX, saturation * colorModeY, max * colorModeZ] + } + p.brightness = function(colInt) { + return colorToHSB(colInt)[2] + }; + p.saturation = function(colInt) { + return colorToHSB(colInt)[1] + }; + p.hue = function(colInt) { + return colorToHSB(colInt)[0] + }; + p.red = function(aColor) { + return ((aColor >> 16) & 255) / 255 * colorModeX + }; + p.green = function(aColor) { + return ((aColor & 65280) >>> 8) / 255 * colorModeY + }; + p.blue = function(aColor) { + return (aColor & 255) / 255 * colorModeZ + }; + p.alpha = function(aColor) { + return ((aColor >> 24) & 255) / 255 * colorModeA + }; + p.lerpColor = function(c1, c2, amt) { + var r, g, b, a, r1, g1, b1, a1, r2, g2, b2, a2; + var hsb1, hsb2, rgb, h, s; + var colorBits1 = p.color(c1); + var colorBits2 = p.color(c2); + if (curColorMode === 3) { + hsb1 = colorToHSB(colorBits1); + a1 = ((colorBits1 >> 24) & 255) / colorModeA; + hsb2 = colorToHSB(colorBits2); + a2 = ((colorBits2 & 4278190080) >>> 24) / colorModeA; + h = p.lerp(hsb1[0], hsb2[0], amt); + s = p.lerp(hsb1[1], hsb2[1], amt); + b = p.lerp(hsb1[2], hsb2[2], amt); + rgb = p.color.toRGB(h, s, b); + a = p.lerp(a1, a2, amt) * colorModeA; + return a << 24 & 4278190080 | (rgb[0] & 255) << 16 | (rgb[1] & 255) << 8 | rgb[2] & 255 + } + r1 = (colorBits1 >> 16) & 255; + g1 = (colorBits1 >> 8) & 255; + b1 = colorBits1 & 255; + a1 = ((colorBits1 >> 24) & 255) / colorModeA; + r2 = (colorBits2 & 16711680) >>> 16; + g2 = (colorBits2 >> 8) & 255; + b2 = colorBits2 & 255; + a2 = ((colorBits2 >> 24) & 255) / colorModeA; + r = p.lerp(r1, r2, amt) | 0; + g = p.lerp(g1, g2, amt) | 0; + b = p.lerp(b1, b2, amt) | 0; + a = p.lerp(a1, a2, amt) * colorModeA; + return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255 + }; + p.colorMode = function() { + curColorMode = arguments[0]; + if (arguments.length > 1) { + colorModeX = arguments[1]; + colorModeY = arguments[2] || arguments[1]; + colorModeZ = arguments[3] || arguments[1]; + colorModeA = arguments[4] || arguments[1] + } + }; + p.blendColor = function(c1, c2, mode) { + if (mode === 0) return p.modes.replace(c1, c2); + else if (mode === 1) return p.modes.blend(c1, c2); + else if (mode === 2) return p.modes.add(c1, c2); + else if (mode === 4) return p.modes.subtract(c1, c2); + else if (mode === 8) return p.modes.lightest(c1, c2); + else if (mode === 16) return p.modes.darkest(c1, c2); + else if (mode === 32) return p.modes.difference(c1, c2); + else if (mode === 64) return p.modes.exclusion(c1, c2); + else if (mode === 128) return p.modes.multiply(c1, c2); + else if (mode === 256) return p.modes.screen(c1, c2); + else if (mode === 1024) return p.modes.hard_light(c1, c2); + else if (mode === 2048) return p.modes.soft_light(c1, c2); + else if (mode === 512) return p.modes.overlay(c1, c2); + else if (mode === 4096) return p.modes.dodge(c1, c2); + else if (mode === 8192) return p.modes.burn(c1, c2) + }; + + function saveContext() { + curContext.save() + } + function restoreContext() { + curContext.restore(); + isStrokeDirty = true; + isFillDirty = true + } + p.printMatrix = function() { + modelView.print() + }; + Drawing2D.prototype.translate = function(x, y) { + modelView.translate(x, y); + modelViewInv.invTranslate(x, y); + curContext.translate(x, y) + }; + Drawing3D.prototype.translate = function(x, y, z) { + modelView.translate(x, y, z); + modelViewInv.invTranslate(x, y, z) + }; + Drawing2D.prototype.scale = function(x, y) { + modelView.scale(x, y); + modelViewInv.invScale(x, y); + curContext.scale(x, y || x) + }; + Drawing3D.prototype.scale = function(x, y, z) { + modelView.scale(x, y, z); + modelViewInv.invScale(x, y, z) + }; + Drawing2D.prototype.transform = function(pmatrix) { + var e = pmatrix.array(); + curContext.transform(e[0], e[3], e[1], e[4], e[2], e[5]) + }; + Drawing3D.prototype.transformm = function(pmatrix3d) { + throw "p.transform is currently not supported in 3D mode"; + }; + Drawing2D.prototype.pushMatrix = function() { + userMatrixStack.load(modelView); + userReverseMatrixStack.load(modelViewInv); + saveContext() + }; + Drawing3D.prototype.pushMatrix = function() { + userMatrixStack.load(modelView); + userReverseMatrixStack.load(modelViewInv) + }; + Drawing2D.prototype.popMatrix = function() { + modelView.set(userMatrixStack.pop()); + modelViewInv.set(userReverseMatrixStack.pop()); + restoreContext() + }; + Drawing3D.prototype.popMatrix = function() { + modelView.set(userMatrixStack.pop()); + modelViewInv.set(userReverseMatrixStack.pop()) + }; + Drawing2D.prototype.resetMatrix = function() { + modelView.reset(); + modelViewInv.reset(); + curContext.setTransform(1, 0, 0, 1, 0, 0) + }; + Drawing3D.prototype.resetMatrix = function() { + modelView.reset(); + modelViewInv.reset() + }; + DrawingShared.prototype.applyMatrix = function() { + var a = arguments; + modelView.apply(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]); + modelViewInv.invApply(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]) + }; + Drawing2D.prototype.applyMatrix = function() { + var a = arguments; + for (var cnt = a.length; cnt < 16; cnt++) a[cnt] = 0; + a[10] = a[15] = 1; + DrawingShared.prototype.applyMatrix.apply(this, a) + }; + p.rotateX = function(angleInRadians) { + modelView.rotateX(angleInRadians); + modelViewInv.invRotateX(angleInRadians) + }; + Drawing2D.prototype.rotateZ = function() { + throw "rotateZ() is not supported in 2D mode. Use rotate(float) instead."; + }; + Drawing3D.prototype.rotateZ = function(angleInRadians) { + modelView.rotateZ(angleInRadians); + modelViewInv.invRotateZ(angleInRadians) + }; + p.rotateY = function(angleInRadians) { + modelView.rotateY(angleInRadians); + modelViewInv.invRotateY(angleInRadians) + }; + Drawing2D.prototype.rotate = function(angleInRadians) { + modelView.rotateZ(angleInRadians); + modelViewInv.invRotateZ(angleInRadians); + curContext.rotate(angleInRadians) + }; + Drawing3D.prototype.rotate = function(angleInRadians) { + p.rotateZ(angleInRadians) + }; + Drawing2D.prototype.shearX = function(angleInRadians) { + modelView.shearX(angleInRadians); + curContext.transform(1, 0, angleInRadians, 1, 0, 0) + }; + Drawing3D.prototype.shearX = function(angleInRadians) { + modelView.shearX(angleInRadians) + }; + Drawing2D.prototype.shearY = function(angleInRadians) { + modelView.shearY(angleInRadians); + curContext.transform(1, angleInRadians, 0, 1, 0, 0) + }; + Drawing3D.prototype.shearY = function(angleInRadians) { + modelView.shearY(angleInRadians) + }; + p.pushStyle = function() { + saveContext(); + p.pushMatrix(); + var newState = { + "doFill": doFill, + "currentFillColor": currentFillColor, + "doStroke": doStroke, + "currentStrokeColor": currentStrokeColor, + "curTint": curTint, + "curRectMode": curRectMode, + "curColorMode": curColorMode, + "colorModeX": colorModeX, + "colorModeZ": colorModeZ, + "colorModeY": colorModeY, + "colorModeA": colorModeA, + "curTextFont": curTextFont, + "horizontalTextAlignment": horizontalTextAlignment, + "verticalTextAlignment": verticalTextAlignment, + "textMode": textMode, + "curFontName": curFontName, + "curTextSize": curTextSize, + "curTextAscent": curTextAscent, + "curTextDescent": curTextDescent, + "curTextLeading": curTextLeading + }; + styleArray.push(newState) + }; + p.popStyle = function() { + var oldState = styleArray.pop(); + if (oldState) { + restoreContext(); + p.popMatrix(); + doFill = oldState.doFill; + currentFillColor = oldState.currentFillColor; + doStroke = oldState.doStroke; + currentStrokeColor = oldState.currentStrokeColor; + curTint = oldState.curTint; + curRectMode = oldState.curRectMode; + curColorMode = oldState.curColorMode; + colorModeX = oldState.colorModeX; + colorModeZ = oldState.colorModeZ; + colorModeY = oldState.colorModeY; + colorModeA = oldState.colorModeA; + curTextFont = oldState.curTextFont; + curFontName = oldState.curFontName; + curTextSize = oldState.curTextSize; + horizontalTextAlignment = oldState.horizontalTextAlignment; + verticalTextAlignment = oldState.verticalTextAlignment; + textMode = oldState.textMode; + curTextAscent = oldState.curTextAscent; + curTextDescent = oldState.curTextDescent; + curTextLeading = oldState.curTextLeading + } else throw "Too many popStyle() without enough pushStyle()"; + }; + p.year = function() { + return (new Date).getFullYear() + }; + p.month = function() { + return (new Date).getMonth() + 1 + }; + p.day = function() { + return (new Date).getDate() + }; + p.hour = function() { + return (new Date).getHours() + }; + p.minute = function() { + return (new Date).getMinutes() + }; + p.second = function() { + return (new Date).getSeconds() + }; + p.millis = function() { + return Date.now() - start + }; + + function redrawHelper() { + var sec = (Date.now() - timeSinceLastFPS) / 1E3; + framesSinceLastFPS++; + var fps = framesSinceLastFPS / sec; + if (sec > 0.5) { + timeSinceLastFPS = Date.now(); + framesSinceLastFPS = 0; + p.__frameRate = fps + } + p.frameCount++ + } + Drawing2D.prototype.redraw = function() { + redrawHelper(); + curContext.lineWidth = lineWidth; + var pmouseXLastEvent = p.pmouseX, + pmouseYLastEvent = p.pmouseY; + p.pmouseX = pmouseXLastFrame; + p.pmouseY = pmouseYLastFrame; + saveContext(); + p.draw(); + restoreContext(); + pmouseXLastFrame = p.mouseX; + pmouseYLastFrame = p.mouseY; + p.pmouseX = pmouseXLastEvent; + p.pmouseY = pmouseYLastEvent + }; + Drawing3D.prototype.redraw = function() { + redrawHelper(); + var pmouseXLastEvent = p.pmouseX, + pmouseYLastEvent = p.pmouseY; + p.pmouseX = pmouseXLastFrame; + p.pmouseY = pmouseYLastFrame; + curContext.clear(curContext.DEPTH_BUFFER_BIT); + curContextCache = { + attributes: {}, + locations: {} + }; + p.noLights(); + p.lightFalloff(1, 0, 0); + p.shininess(1); + p.ambient(255, 255, 255); + p.specular(0, 0, 0); + p.emissive(0, 0, 0); + p.camera(); + p.draw(); + pmouseXLastFrame = p.mouseX; + pmouseYLastFrame = p.mouseY; + p.pmouseX = pmouseXLastEvent; + p.pmouseY = pmouseYLastEvent + }; + p.noLoop = function() { + doLoop = false; + loopStarted = false; + clearInterval(looping); + curSketch.onPause() + }; + p.loop = function() { + if (loopStarted) return; + timeSinceLastFPS = Date.now(); + framesSinceLastFPS = 0; + looping = window.setInterval(function() { + try { + curSketch.onFrameStart(); + p.redraw(); + curSketch.onFrameEnd() + } catch(e_loop) { + window.clearInterval(looping); + throw e_loop; + } + }, + curMsPerFrame); + doLoop = true; + loopStarted = true; + curSketch.onLoop() + }; + p.frameRate = function(aRate) { + curFrameRate = aRate; + curMsPerFrame = 1E3 / curFrameRate; + if (doLoop) { + p.noLoop(); + p.loop() + } + }; + var eventHandlers = []; + + function attachEventHandler(elem, type, fn) { + if (elem.addEventListener) elem.addEventListener(type, fn, false); + else elem.attachEvent("on" + type, fn); + eventHandlers.push({ + elem: elem, + type: type, + fn: fn + }) + } + function detachEventHandler(eventHandler) { + var elem = eventHandler.elem, + type = eventHandler.type, + fn = eventHandler.fn; + if (elem.removeEventListener) elem.removeEventListener(type, fn, false); + else if (elem.detachEvent) elem.detachEvent("on" + type, fn) + } + p.exit = function() { + window.clearInterval(looping); + removeInstance(p.externals.canvas.id); + delete curElement.onmousedown; + for (var lib in Processing.lib) if (Processing.lib.hasOwnProperty(lib)) if (Processing.lib[lib].hasOwnProperty("detach")) Processing.lib[lib].detach(p); + var i = eventHandlers.length; + while (i--) detachEventHandler(eventHandlers[i]); + curSketch.onExit() + }; + p.cursor = function() { + if (arguments.length > 1 || arguments.length === 1 && arguments[0] instanceof p.PImage) { + var image = arguments[0], + x, y; + if (arguments.length >= 3) { + x = arguments[1]; + y = arguments[2]; + if (x < 0 || y < 0 || y >= image.height || x >= image.width) throw "x and y must be non-negative and less than the dimensions of the image"; + } else { + x = image.width >>> 1; + y = image.height >>> 1 + } + var imageDataURL = image.toDataURL(); + var style = 'url("' + imageDataURL + '") ' + x + " " + y + ", default"; + curCursor = curElement.style.cursor = style + } else if (arguments.length === 1) { + var mode = arguments[0]; + curCursor = curElement.style.cursor = mode + } else curCursor = curElement.style.cursor = oldCursor + }; + p.noCursor = function() { + curCursor = curElement.style.cursor = PConstants.NOCURSOR + }; + p.link = function(href, target) { + if (target !== undef) window.open(href, target); + else window.location = href + }; + p.beginDraw = nop; + p.endDraw = nop; + Drawing2D.prototype.toImageData = function(x, y, w, h) { + x = x !== undef ? x : 0; + y = y !== undef ? y : 0; + w = w !== undef ? w : p.width; + h = h !== undef ? h : p.height; + return curContext.getImageData(x, y, w, h) + }; + Drawing3D.prototype.toImageData = function(x, y, w, h) { + x = x !== undef ? x : 0; + y = y !== undef ? y : 0; + w = w !== undef ? w : p.width; + h = h !== undef ? h : p.height; + var c = document.createElement("canvas"), + ctx = c.getContext("2d"), + obj = ctx.createImageData(w, h), + uBuff = new Uint8Array(w * h * 4); + curContext.readPixels(x, y, w, h, curContext.RGBA, curContext.UNSIGNED_BYTE, uBuff); + for (var i = 0, ul = uBuff.length, obj_data = obj.data; i < ul; i++) obj_data[i] = uBuff[(h - 1 - Math.floor(i / 4 / w)) * w * 4 + i % (w * 4)]; + return obj + }; + p.status = function(text) { + window.status = text + }; + p.binary = function(num, numBits) { + var bit; + if (numBits > 0) bit = numBits; + else if (num instanceof Char) { + bit = 16; + num |= 0 + } else { + bit = 32; + while (bit > 1 && !(num >>> bit - 1 & 1)) bit-- + } + var result = ""; + while (bit > 0) result += num >>> --bit & 1 ? "1" : "0"; + return result + }; + p.unbinary = function(binaryString) { + var i = binaryString.length - 1, + mask = 1, + result = 0; + while (i >= 0) { + var ch = binaryString[i--]; + if (ch !== "0" && ch !== "1") throw "the value passed into unbinary was not an 8 bit binary number"; + if (ch === "1") result += mask; + mask <<= 1 + } + return result + }; + + function nfCoreScalar(value, plus, minus, leftDigits, rightDigits, group) { + var sign = value < 0 ? minus : plus; + var autoDetectDecimals = rightDigits === 0; + var rightDigitsOfDefault = rightDigits === undef || rightDigits < 0 ? 0 : rightDigits; + var absValue = Math.abs(value); + if (autoDetectDecimals) { + rightDigitsOfDefault = 1; + absValue *= 10; + while (Math.abs(Math.round(absValue) - absValue) > 1.0E-6 && rightDigitsOfDefault < 7) { + ++rightDigitsOfDefault; + absValue *= 10 + } + } else if (rightDigitsOfDefault !== 0) absValue *= Math.pow(10, rightDigitsOfDefault); + var number, doubled = absValue * 2; + if (Math.floor(absValue) === absValue) number = absValue; + else if (Math.floor(doubled) === doubled) { + var floored = Math.floor(absValue); + number = floored + floored % 2 + } else number = Math.round(absValue); + var buffer = ""; + var totalDigits = leftDigits + rightDigitsOfDefault; + while (totalDigits > 0 || number > 0) { + totalDigits--; + buffer = "" + number % 10 + buffer; + number = Math.floor(number / 10) + } + if (group !== undef) { + var i = buffer.length - 3 - rightDigitsOfDefault; + while (i > 0) { + buffer = buffer.substring(0, i) + group + buffer.substring(i); + i -= 3 + } + } + if (rightDigitsOfDefault > 0) return sign + buffer.substring(0, buffer.length - rightDigitsOfDefault) + "." + buffer.substring(buffer.length - rightDigitsOfDefault, buffer.length); + return sign + buffer + } + function nfCore(value, plus, minus, leftDigits, rightDigits, group) { + if (value instanceof Array) { + var arr = []; + for (var i = 0, len = value.length; i < len; i++) arr.push(nfCoreScalar(value[i], plus, minus, leftDigits, rightDigits, group)); + return arr + } + return nfCoreScalar(value, plus, minus, leftDigits, rightDigits, group) + } + p.nf = function(value, leftDigits, rightDigits) { + return nfCore(value, "", "-", leftDigits, rightDigits) + }; + p.nfs = function(value, leftDigits, rightDigits) { + return nfCore(value, " ", "-", leftDigits, rightDigits) + }; + p.nfp = function(value, leftDigits, rightDigits) { + return nfCore(value, "+", "-", leftDigits, rightDigits) + }; + p.nfc = function(value, leftDigits, rightDigits) { + return nfCore(value, "", "-", leftDigits, rightDigits, ",") + }; + var decimalToHex = function(d, padding) { + padding = padding === undef || padding === null ? padding = 8 : padding; + if (d < 0) d = 4294967295 + d + 1; + var hex = Number(d).toString(16).toUpperCase(); + while (hex.length < padding) hex = "0" + hex; + if (hex.length >= padding) hex = hex.substring(hex.length - padding, hex.length); + return hex + }; + p.hex = function(value, len) { + if (arguments.length === 1) if (value instanceof Char) len = 4; + else len = 8; + return decimalToHex(value, len) + }; + + function unhexScalar(hex) { + var value = parseInt("0x" + hex, 16); + if (value > 2147483647) value -= 4294967296; + return value + } + p.unhex = function(hex) { + if (hex instanceof Array) { + var arr = []; + for (var i = 0; i < hex.length; i++) arr.push(unhexScalar(hex[i])); + return arr + } + return unhexScalar(hex) + }; + p.loadStrings = function(filename) { + if (localStorage[filename]) return localStorage[filename].split("\n"); + var filecontent = ajax(filename); + if (typeof filecontent !== "string" || filecontent === "") return []; + filecontent = filecontent.replace(/(\r\n?)/g, "\n").replace(/\n$/, ""); + return filecontent.split("\n") + }; + p.saveStrings = function(filename, strings) { + localStorage[filename] = strings.join("\n") + }; + p.loadBytes = function(url) { + var string = ajax(url); + var ret = []; + for (var i = 0; i < string.length; i++) ret.push(string.charCodeAt(i)); + return ret + }; + + function removeFirstArgument(args) { + return Array.prototype.slice.call(args, 1) + } + p.matchAll = function(aString, aRegExp) { + var results = [], + latest; + var regexp = new RegExp(aRegExp, "g"); + while ((latest = regexp.exec(aString)) !== null) { + results.push(latest); + if (latest[0].length === 0)++regexp.lastIndex + } + return results.length > 0 ? results : null + }; + p.__contains = function(subject, subStr) { + if (typeof subject !== "string") return subject.contains.apply(subject, removeFirstArgument(arguments)); + return subject !== null && subStr !== null && typeof subStr === "string" && subject.indexOf(subStr) > -1 + }; + p.__replaceAll = function(subject, regex, replacement) { + if (typeof subject !== "string") return subject.replaceAll.apply(subject, removeFirstArgument(arguments)); + return subject.replace(new RegExp(regex, "g"), replacement) + }; + p.__replaceFirst = function(subject, regex, replacement) { + if (typeof subject !== "string") return subject.replaceFirst.apply(subject, removeFirstArgument(arguments)); + return subject.replace(new RegExp(regex, ""), replacement) + }; + p.__replace = function(subject, what, replacement) { + if (typeof subject !== "string") return subject.replace.apply(subject, removeFirstArgument(arguments)); + if (what instanceof RegExp) return subject.replace(what, replacement); + if (typeof what !== "string") what = what.toString(); + if (what === "") return subject; + var i = subject.indexOf(what); + if (i < 0) return subject; + var j = 0, + result = ""; + do { + result += subject.substring(j, i) + replacement; + j = i + what.length + } while ((i = subject.indexOf(what, j)) >= 0); + return result + subject.substring(j) + }; + p.__equals = function(subject, other) { + if (subject.equals instanceof + Function) return subject.equals.apply(subject, removeFirstArgument(arguments)); + return subject.valueOf() === other.valueOf() + }; + p.__equalsIgnoreCase = function(subject, other) { + if (typeof subject !== "string") return subject.equalsIgnoreCase.apply(subject, removeFirstArgument(arguments)); + return subject.toLowerCase() === other.toLowerCase() + }; + p.__toCharArray = function(subject) { + if (typeof subject !== "string") return subject.toCharArray.apply(subject, removeFirstArgument(arguments)); + var chars = []; + for (var i = 0, len = subject.length; i < len; ++i) chars[i] = new Char(subject.charAt(i)); + return chars + }; + p.__split = function(subject, regex, limit) { + if (typeof subject !== "string") return subject.split.apply(subject, removeFirstArgument(arguments)); + var pattern = new RegExp(regex); + if (limit === undef || limit < 1) return subject.split(pattern); + var result = [], + currSubject = subject, + pos; + while ((pos = currSubject.search(pattern)) !== -1 && result.length < limit - 1) { + var match = pattern.exec(currSubject).toString(); + result.push(currSubject.substring(0, pos)); + currSubject = currSubject.substring(pos + match.length) + } + if (pos !== -1 || currSubject !== "") result.push(currSubject); + return result + }; + p.__codePointAt = function(subject, idx) { + var code = subject.charCodeAt(idx), + hi, low; + if (55296 <= code && code <= 56319) { + hi = code; + low = subject.charCodeAt(idx + 1); + return (hi - 55296) * 1024 + (low - 56320) + 65536 + } + return code + }; + p.match = function(str, regexp) { + return str.match(regexp) + }; + p.__matches = function(str, regexp) { + return (new RegExp(regexp)).test(str) + }; + p.__startsWith = function(subject, prefix, toffset) { + if (typeof subject !== "string") return subject.startsWith.apply(subject, removeFirstArgument(arguments)); + toffset = toffset || 0; + if (toffset < 0 || toffset > subject.length) return false; + return prefix === "" || prefix === subject ? true : subject.indexOf(prefix) === toffset + }; + p.__endsWith = function(subject, suffix) { + if (typeof subject !== "string") return subject.endsWith.apply(subject, removeFirstArgument(arguments)); + var suffixLen = suffix ? suffix.length : 0; + return suffix === "" || suffix === subject ? true : subject.indexOf(suffix) === subject.length - suffixLen + }; + p.__hashCode = function(subject) { + if (subject.hashCode instanceof + Function) return subject.hashCode.apply(subject, removeFirstArgument(arguments)); + return virtHashCode(subject) + }; + p.__printStackTrace = function(subject) { + p.println("Exception: " + subject.toString()) + }; + var logBuffer = []; + p.println = function(message) { + var bufferLen = logBuffer.length; + if (bufferLen) { + Processing.logger.log(logBuffer.join("")); + logBuffer.length = 0 + } + if (arguments.length === 0 && bufferLen === 0) Processing.logger.log(""); + else if (arguments.length !== 0) Processing.logger.log(message) + }; + p.print = function(message) { + logBuffer.push(message) + }; + p.str = function(val) { + if (val instanceof Array) { + var arr = []; + for (var i = 0; i < val.length; i++) arr.push(val[i].toString() + ""); + return arr + } + return val.toString() + "" + }; + p.trim = function(str) { + if (str instanceof Array) { + var arr = []; + for (var i = 0; i < str.length; i++) arr.push(str[i].replace(/^\s*/, "").replace(/\s*$/, "").replace(/\r*$/, "")); + return arr + } + return str.replace(/^\s*/, "").replace(/\s*$/, "").replace(/\r*$/, "") + }; + + function booleanScalar(val) { + if (typeof val === "number") return val !== 0; + if (typeof val === "boolean") return val; + if (typeof val === "string") return val.toLowerCase() === "true"; + if (val instanceof Char) return val.code === 49 || val.code === 84 || val.code === 116 + } + p.parseBoolean = function(val) { + if (val instanceof Array) { + var ret = []; + for (var i = 0; i < val.length; i++) ret.push(booleanScalar(val[i])); + return ret + } + return booleanScalar(val) + }; + p.parseByte = function(what) { + if (what instanceof Array) { + var bytes = []; + for (var i = 0; i < what.length; i++) bytes.push(0 - (what[i] & 128) | what[i] & 127); + return bytes + } + return 0 - (what & 128) | what & 127 + }; + p.parseChar = function(key) { + if (typeof key === "number") return new Char(String.fromCharCode(key & 65535)); + if (key instanceof Array) { + var ret = []; + for (var i = 0; i < key.length; i++) ret.push(new Char(String.fromCharCode(key[i] & 65535))); + return ret + } + throw "char() may receive only one argument of type int, byte, int[], or byte[]."; + }; + + function floatScalar(val) { + if (typeof val === "number") return val; + if (typeof val === "boolean") return val ? 1 : 0; + if (typeof val === "string") return parseFloat(val); + if (val instanceof Char) return val.code + } + p.parseFloat = function(val) { + if (val instanceof + Array) { + var ret = []; + for (var i = 0; i < val.length; i++) ret.push(floatScalar(val[i])); + return ret + } + return floatScalar(val) + }; + + function intScalar(val, radix) { + if (typeof val === "number") return val & 4294967295; + if (typeof val === "boolean") return val ? 1 : 0; + if (typeof val === "string") { + var number = parseInt(val, radix || 10); + return number & 4294967295 + } + if (val instanceof Char) return val.code + } + p.parseInt = function(val, radix) { + if (val instanceof Array) { + var ret = []; + for (var i = 0; i < val.length; i++) if (typeof val[i] === "string" && !/^\s*[+\-]?\d+\s*$/.test(val[i])) ret.push(0); + else ret.push(intScalar(val[i], radix)); + return ret + } + return intScalar(val, radix) + }; + p.__int_cast = function(val) { + return 0 | val + }; + p.__instanceof = function(obj, type) { + if (typeof type !== "function") throw "Function is expected as type argument for instanceof operator"; + if (typeof obj === "string") return type === Object || type === String; + if (obj instanceof type) return true; + if (typeof obj !== "object" || obj === null) return false; + var objType = obj.constructor; + if (type.$isInterface) { + var interfaces = []; + while (objType) { + if (objType.$interfaces) interfaces = interfaces.concat(objType.$interfaces); + objType = objType.$base + } + while (interfaces.length > 0) { + var i = interfaces.shift(); + if (i === type) return true; + if (i.$interfaces) interfaces = interfaces.concat(i.$interfaces) + } + return false + } + while (objType.hasOwnProperty("$base")) { + objType = objType.$base; + if (objType === type) return true + } + return false + }; + p.abs = Math.abs; + p.ceil = Math.ceil; + p.constrain = function(aNumber, aMin, aMax) { + return aNumber > aMax ? aMax : aNumber < aMin ? aMin : aNumber + }; + p.dist = function() { + var dx, dy, dz; + if (arguments.length === 4) { + dx = arguments[0] - arguments[2]; + dy = arguments[1] - arguments[3]; + return Math.sqrt(dx * dx + dy * dy) + } + if (arguments.length === 6) { + dx = arguments[0] - arguments[3]; + dy = arguments[1] - arguments[4]; + dz = arguments[2] - arguments[5]; + return Math.sqrt(dx * dx + dy * dy + dz * dz) + } + }; + p.exp = Math.exp; + p.floor = Math.floor; + p.lerp = function(value1, value2, amt) { + return (value2 - value1) * amt + value1 + }; + p.log = Math.log; + p.mag = function(a, b, c) { + if (c) return Math.sqrt(a * a + b * b + c * c); + return Math.sqrt(a * a + b * b) + }; + p.map = function(value, istart, istop, ostart, ostop) { + return ostart + (ostop - ostart) * ((value - istart) / (istop - istart)) + }; + p.max = function() { + if (arguments.length === 2) return arguments[0] < arguments[1] ? arguments[1] : arguments[0]; + var numbers = arguments.length === 1 ? arguments[0] : arguments; + if (! ("length" in numbers && numbers.length > 0)) throw "Non-empty array is expected"; + var max = numbers[0], + count = numbers.length; + for (var i = 1; i < count; ++i) if (max < numbers[i]) max = numbers[i]; + return max + }; + p.min = function() { + if (arguments.length === 2) return arguments[0] < arguments[1] ? arguments[0] : arguments[1]; + var numbers = arguments.length === 1 ? arguments[0] : arguments; + if (! ("length" in numbers && numbers.length > 0)) throw "Non-empty array is expected"; + var min = numbers[0], + count = numbers.length; + for (var i = 1; i < count; ++i) if (min > numbers[i]) min = numbers[i]; + return min + }; + p.norm = function(aNumber, low, high) { + return (aNumber - low) / (high - low) + }; + p.pow = Math.pow; + p.round = Math.round; + p.sq = function(aNumber) { + return aNumber * aNumber + }; + p.sqrt = Math.sqrt; + p.acos = Math.acos; + p.asin = Math.asin; + p.atan = Math.atan; + p.atan2 = Math.atan2; + p.cos = Math.cos; + p.degrees = function(aAngle) { + return aAngle * 180 / Math.PI + }; + p.radians = function(aAngle) { + return aAngle / 180 * Math.PI + }; + p.sin = Math.sin; + p.tan = Math.tan; + var currentRandom = Math.random; + p.random = function() { + if (arguments.length === 0) return currentRandom(); + if (arguments.length === 1) return currentRandom() * arguments[0]; + var aMin = arguments[0], + aMax = arguments[1]; + return currentRandom() * (aMax - aMin) + aMin + }; + + function Marsaglia(i1, i2) { + var z = i1 || 362436069, + w = i2 || 521288629; + var nextInt = function() { + z = 36969 * (z & 65535) + (z >>> 16) & 4294967295; + w = 18E3 * (w & 65535) + (w >>> 16) & 4294967295; + return ((z & 65535) << 16 | w & 65535) & 4294967295 + }; + this.nextDouble = function() { + var i = nextInt() / 4294967296; + return i < 0 ? 1 + i : i + }; + this.nextInt = nextInt + } + Marsaglia.createRandomized = function() { + var now = new Date; + return new Marsaglia(now / 6E4 & 4294967295, now & 4294967295) + }; + p.randomSeed = function(seed) { + currentRandom = (new Marsaglia(seed)).nextDouble + }; + p.Random = function(seed) { + var haveNextNextGaussian = false, + nextNextGaussian, random; + this.nextGaussian = function() { + if (haveNextNextGaussian) { + haveNextNextGaussian = false; + return nextNextGaussian + } + var v1, v2, s; + do { + v1 = 2 * random() - 1; + v2 = 2 * random() - 1; + 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 + }; + random = seed === undef ? Math.random : (new Marsaglia(seed)).nextDouble + }; + + function PerlinNoise(seed) { + var rnd = seed !== undef ? new Marsaglia(seed) : Marsaglia.createRandomized(); + var i, j; + var perm = new Uint8Array(512); + for (i = 0; i < 256; ++i) perm[i] = i; + for (i = 0; i < 256; ++i) { + var t = perm[j = rnd.nextInt() & 255]; + perm[j] = perm[i]; + perm[i] = t + } + for (i = 0; i < 256; ++i) perm[i + 256] = perm[i]; + + function grad3d(i, x, y, z) { + var h = i & 15; + var u = h < 8 ? x : y, + v = h < 4 ? y : h === 12 || h === 14 ? x : z; + return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v) + } + function grad2d(i, x, y) { + var v = (i & 1) === 0 ? x : y; + return (i & 2) === 0 ? -v : v + } + function grad1d(i, x) { + return (i & 1) === 0 ? -x : x + } + function lerp(t, a, b) { + return a + t * (b - a) + } + this.noise3d = function(x, y, z) { + var X = Math.floor(x) & 255, + Y = Math.floor(y) & 255, + Z = Math.floor(z) & 255; + x -= Math.floor(x); + y -= Math.floor(y); + z -= Math.floor(z); + var fx = (3 - 2 * x) * x * x, + fy = (3 - 2 * y) * y * y, + fz = (3 - 2 * z) * z * z; + var p0 = perm[X] + Y, + p00 = perm[p0] + Z, + p01 = perm[p0 + 1] + Z, + p1 = perm[X + 1] + Y, + p10 = perm[p1] + Z, + p11 = perm[p1 + 1] + Z; + return lerp(fz, lerp(fy, lerp(fx, grad3d(perm[p00], x, y, z), grad3d(perm[p10], x - 1, y, z)), lerp(fx, grad3d(perm[p01], x, y - 1, z), grad3d(perm[p11], x - 1, y - 1, z))), lerp(fy, lerp(fx, grad3d(perm[p00 + 1], x, y, z - 1), grad3d(perm[p10 + 1], x - 1, y, z - 1)), lerp(fx, grad3d(perm[p01 + 1], x, y - 1, z - 1), grad3d(perm[p11 + 1], x - 1, y - 1, z - 1)))) + }; + this.noise2d = function(x, y) { + var X = Math.floor(x) & 255, + Y = Math.floor(y) & 255; + x -= Math.floor(x); + y -= Math.floor(y); + var fx = (3 - 2 * x) * x * x, + fy = (3 - 2 * y) * y * y; + var p0 = perm[X] + Y, + p1 = perm[X + 1] + Y; + return lerp(fy, lerp(fx, grad2d(perm[p0], x, y), grad2d(perm[p1], x - 1, y)), lerp(fx, grad2d(perm[p0 + 1], x, y - 1), grad2d(perm[p1 + 1], x - 1, y - 1))) + }; + this.noise1d = function(x) { + var X = Math.floor(x) & 255; + x -= Math.floor(x); + var fx = (3 - 2 * x) * x * x; + return lerp(fx, grad1d(perm[X], x), grad1d(perm[X + 1], x - 1)) + } + } + var noiseProfile = { + generator: undef, + octaves: 4, + fallout: 0.5, + seed: undef + }; + p.noise = function(x, y, z) { + if (noiseProfile.generator === undef) noiseProfile.generator = new PerlinNoise(noiseProfile.seed); + var generator = noiseProfile.generator; + var effect = 1, + k = 1, + sum = 0; + for (var i = 0; i < noiseProfile.octaves; ++i) { + effect *= noiseProfile.fallout; + switch (arguments.length) { + case 1: + sum += effect * (1 + generator.noise1d(k * x)) / 2; + break; + case 2: + sum += effect * (1 + generator.noise2d(k * x, k * y)) / 2; + break; + case 3: + sum += effect * (1 + generator.noise3d(k * x, k * y, k * z)) / 2; + break + } + k *= 2 + } + return sum + }; + p.noiseDetail = function(octaves, fallout) { + noiseProfile.octaves = octaves; + if (fallout !== undef) noiseProfile.fallout = fallout + }; + p.noiseSeed = function(seed) { + noiseProfile.seed = seed; + noiseProfile.generator = undef + }; + DrawingShared.prototype.size = function(aWidth, aHeight, aMode) { + if (doStroke) p.stroke(0); + if (doFill) p.fill(255); + var savedProperties = { + fillStyle: curContext.fillStyle, + strokeStyle: curContext.strokeStyle, + lineCap: curContext.lineCap, + lineJoin: curContext.lineJoin + }; + if (curElement.style.length > 0) { + curElement.style.removeProperty("width"); + curElement.style.removeProperty("height") + } + curElement.width = p.width = aWidth || 100; + curElement.height = p.height = aHeight || 100; + for (var prop in savedProperties) if (savedProperties.hasOwnProperty(prop)) curContext[prop] = savedProperties[prop]; + p.textFont(curTextFont); + p.background(); + maxPixelsCached = Math.max(1E3, aWidth * aHeight * 0.05); + p.externals.context = curContext; + for (var i = 0; i < 720; i++) { + sinLUT[i] = p.sin(i * (Math.PI / 180) * 0.5); + cosLUT[i] = p.cos(i * (Math.PI / 180) * 0.5) + } + }; + Drawing2D.prototype.size = function(aWidth, aHeight, aMode) { + if (curContext === undef) { + curContext = curElement.getContext("2d"); + userMatrixStack = new PMatrixStack; + userReverseMatrixStack = new PMatrixStack; + modelView = new PMatrix2D; + modelViewInv = new PMatrix2D + } + DrawingShared.prototype.size.apply(this, arguments) + }; + Drawing3D.prototype.size = function() { + var size3DCalled = false; + return function size(aWidth, aHeight, aMode) { + if (size3DCalled) throw "Multiple calls to size() for 3D renders are not allowed."; + size3DCalled = true; + + function getGLContext(canvas) { + var ctxNames = ["experimental-webgl", "webgl", "webkit-3d"], + gl; + for (var i = 0, l = ctxNames.length; i < l; i++) { + gl = canvas.getContext(ctxNames[i], { + antialias: false, + preserveDrawingBuffer: true + }); + if (gl) break + } + return gl + } + try { + curElement.width = p.width = aWidth || 100; + curElement.height = p.height = aHeight || 100; + curContext = getGLContext(curElement); + canTex = curContext.createTexture(); + textTex = curContext.createTexture() + } catch(e_size) { + Processing.debug(e_size) + } + if (!curContext) throw "WebGL context is not supported on this browser."; + curContext.viewport(0, 0, curElement.width, curElement.height); + curContext.enable(curContext.DEPTH_TEST); + curContext.enable(curContext.BLEND); + curContext.blendFunc(curContext.SRC_ALPHA, curContext.ONE_MINUS_SRC_ALPHA); + programObject2D = createProgramObject(curContext, vertexShaderSrc2D, fragmentShaderSrc2D); + programObjectUnlitShape = createProgramObject(curContext, vertexShaderSrcUnlitShape, fragmentShaderSrcUnlitShape); + p.strokeWeight(1); + programObject3D = createProgramObject(curContext, vertexShaderSrc3D, fragmentShaderSrc3D); + curContext.useProgram(programObject3D); + uniformi("usingTexture3d", programObject3D, "usingTexture", usingTexture); + p.lightFalloff(1, 0, 0); + p.shininess(1); + p.ambient(255, 255, 255); + p.specular(0, 0, 0); + p.emissive(0, 0, 0); + boxBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, boxBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, boxVerts, curContext.STATIC_DRAW); + boxNormBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, boxNormBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, boxNorms, curContext.STATIC_DRAW); + boxOutlineBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, boxOutlineBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, boxOutlineVerts, curContext.STATIC_DRAW); + rectBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, rectBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, rectVerts, curContext.STATIC_DRAW); + rectNormBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, rectNormBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, rectNorms, curContext.STATIC_DRAW); + sphereBuffer = curContext.createBuffer(); + lineBuffer = curContext.createBuffer(); + fillBuffer = curContext.createBuffer(); + fillColorBuffer = curContext.createBuffer(); + strokeColorBuffer = curContext.createBuffer(); + shapeTexVBO = curContext.createBuffer(); + pointBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, pointBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([0, 0, 0]), curContext.STATIC_DRAW); + textBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, textBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0]), curContext.STATIC_DRAW); + textureBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, textureBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]), curContext.STATIC_DRAW); + indexBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ELEMENT_ARRAY_BUFFER, indexBuffer); + curContext.bufferData(curContext.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 2, 3, 0]), curContext.STATIC_DRAW); + cam = new PMatrix3D; + cameraInv = new PMatrix3D; + modelView = new PMatrix3D; + modelViewInv = new PMatrix3D; + projection = new PMatrix3D; + p.camera(); + p.perspective(); + userMatrixStack = new PMatrixStack; + userReverseMatrixStack = new PMatrixStack; + curveBasisMatrix = new PMatrix3D; + curveToBezierMatrix = new PMatrix3D; + curveDrawMatrix = new PMatrix3D; + bezierDrawMatrix = new PMatrix3D; + bezierBasisInverse = new PMatrix3D; + bezierBasisMatrix = new PMatrix3D; + bezierBasisMatrix.set(-1, 3, -3, 1, 3, -6, 3, 0, -3, 3, 0, 0, 1, 0, 0, 0); + DrawingShared.prototype.size.apply(this, arguments) + } + }(); + Drawing2D.prototype.ambientLight = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.ambientLight = function(r, g, b, x, y, z) { + if (lightCount === 8) throw "can only create " + 8 + " lights"; + var pos = new PVector(x, y, z); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.mult(pos, pos); + var col = color$4(r, g, b, 0); + var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255]; + curContext.useProgram(programObject3D); + uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol); + uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array()); + uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 0); + uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount) + }; + Drawing2D.prototype.directionalLight = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.directionalLight = function(r, g, b, nx, ny, nz) { + if (lightCount === 8) throw "can only create " + 8 + " lights"; + curContext.useProgram(programObject3D); + var mvm = new PMatrix3D; + mvm.scale(1, -1, 1); + mvm.apply(modelView.array()); + mvm = mvm.array(); + var dir = [mvm[0] * nx + mvm[4] * ny + mvm[8] * nz, mvm[1] * nx + mvm[5] * ny + mvm[9] * nz, mvm[2] * nx + mvm[6] * ny + mvm[10] * nz]; + var col = color$4(r, g, b, 0); + var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255]; + uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol); + uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", dir); + uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 1); + uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount) + }; + Drawing2D.prototype.lightFalloff = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.lightFalloff = function(constant, linear, quadratic) { + curContext.useProgram(programObject3D); + uniformf("uFalloff3d", programObject3D, "uFalloff", [constant, linear, quadratic]) + }; + Drawing2D.prototype.lightSpecular = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.lightSpecular = function(r, g, b) { + var col = color$4(r, g, b, 0); + var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255]; + curContext.useProgram(programObject3D); + uniformf("uSpecular3d", programObject3D, "uSpecular", normalizedCol) + }; + p.lights = function() { + p.ambientLight(128, 128, 128); + p.directionalLight(128, 128, 128, 0, 0, -1); + p.lightFalloff(1, 0, 0); + p.lightSpecular(0, 0, 0) + }; + Drawing2D.prototype.pointLight = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.pointLight = function(r, g, b, x, y, z) { + if (lightCount === 8) throw "can only create " + 8 + " lights"; + var pos = new PVector(x, y, z); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.mult(pos, pos); + var col = color$4(r, g, b, 0); + var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255]; + curContext.useProgram(programObject3D); + uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol); + uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array()); + uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 2); + uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount) + }; + Drawing2D.prototype.noLights = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.noLights = function() { + lightCount = 0; + curContext.useProgram(programObject3D); + uniformi("uLightCount3d", programObject3D, "uLightCount", lightCount) + }; + Drawing2D.prototype.spotLight = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.spotLight = function(r, g, b, x, y, z, nx, ny, nz, angle, concentration) { + if (lightCount === 8) throw "can only create " + 8 + " lights"; + curContext.useProgram(programObject3D); + var pos = new PVector(x, y, z); + var mvm = new PMatrix3D; + mvm.scale(1, -1, 1); + mvm.apply(modelView.array()); + mvm.mult(pos, pos); + mvm = mvm.array(); + var dir = [mvm[0] * nx + mvm[4] * ny + mvm[8] * nz, mvm[1] * + nx + mvm[5] * ny + mvm[9] * nz, mvm[2] * nx + mvm[6] * ny + mvm[10] * nz]; + var col = color$4(r, g, b, 0); + var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255]; + uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol); + uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array()); + uniformf("uLights.direction.3d." + lightCount, programObject3D, "uLights" + lightCount + ".direction", dir); + uniformf("uLights.concentration.3d." + lightCount, programObject3D, "uLights" + lightCount + ".concentration", concentration); + uniformf("uLights.angle.3d." + lightCount, programObject3D, "uLights" + lightCount + ".angle", angle); + uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 3); + uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount) + }; + Drawing2D.prototype.beginCamera = function() { + throw "beginCamera() is not available in 2D mode"; + }; + Drawing3D.prototype.beginCamera = function() { + if (manipulatingCamera) throw "You cannot call beginCamera() again before calling endCamera()"; + manipulatingCamera = true; + modelView = cameraInv; + modelViewInv = cam + }; + Drawing2D.prototype.endCamera = function() { + throw "endCamera() is not available in 2D mode"; + }; + Drawing3D.prototype.endCamera = function() { + if (!manipulatingCamera) throw "You cannot call endCamera() before calling beginCamera()"; + modelView.set(cam); + modelViewInv.set(cameraInv); + manipulatingCamera = false + }; + p.camera = function(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ) { + if (eyeX === undef) { + cameraX = p.width / 2; + cameraY = p.height / 2; + cameraZ = cameraY / Math.tan(cameraFOV / 2); + eyeX = cameraX; + eyeY = cameraY; + eyeZ = cameraZ; + centerX = cameraX; + centerY = cameraY; + centerZ = 0; + upX = 0; + upY = 1; + upZ = 0 + } + var z = new PVector(eyeX - centerX, eyeY - centerY, eyeZ - centerZ); + var y = new PVector(upX, upY, upZ); + z.normalize(); + var x = PVector.cross(y, z); + y = PVector.cross(z, x); + x.normalize(); + y.normalize(); + var xX = x.x, + xY = x.y, + xZ = x.z; + var yX = y.x, + yY = y.y, + yZ = y.z; + var zX = z.x, + zY = z.y, + zZ = z.z; + cam.set(xX, xY, xZ, 0, yX, yY, yZ, 0, zX, zY, zZ, 0, 0, 0, 0, 1); + cam.translate(-eyeX, -eyeY, -eyeZ); + cameraInv.reset(); + cameraInv.invApply(xX, xY, xZ, 0, yX, yY, yZ, 0, zX, zY, zZ, 0, 0, 0, 0, 1); + cameraInv.translate(eyeX, eyeY, eyeZ); + modelView.set(cam); + modelViewInv.set(cameraInv) + }; + p.perspective = function(fov, aspect, near, far) { + if (arguments.length === 0) { + cameraY = curElement.height / 2; + cameraZ = cameraY / Math.tan(cameraFOV / 2); + cameraNear = cameraZ / 10; + cameraFar = cameraZ * 10; + cameraAspect = p.width / p.height; + fov = cameraFOV; + aspect = cameraAspect; + near = cameraNear; + far = cameraFar + } + var yMax, yMin, xMax, xMin; + yMax = near * Math.tan(fov / 2); + yMin = -yMax; + xMax = yMax * aspect; + xMin = yMin * aspect; + p.frustum(xMin, xMax, yMin, yMax, near, far) + }; + Drawing2D.prototype.frustum = function() { + throw "Processing.js: frustum() is not supported in 2D mode"; + }; + Drawing3D.prototype.frustum = function(left, right, bottom, top, near, far) { + frustumMode = true; + projection = new PMatrix3D; + projection.set(2 * near / (right - left), 0, (right + left) / (right - left), 0, 0, 2 * near / (top - bottom), (top + bottom) / (top - bottom), 0, 0, 0, -(far + near) / (far - near), -(2 * far * near) / (far - near), 0, 0, -1, 0); + var proj = new PMatrix3D; + proj.set(projection); + proj.transpose(); + curContext.useProgram(programObject2D); + uniformMatrix("projection2d", programObject2D, "uProjection", false, proj.array()); + curContext.useProgram(programObject3D); + uniformMatrix("projection3d", programObject3D, "uProjection", false, proj.array()); + curContext.useProgram(programObjectUnlitShape); + uniformMatrix("uProjectionUS", programObjectUnlitShape, "uProjection", false, proj.array()) + }; + p.ortho = function(left, right, bottom, top, near, far) { + if (arguments.length === 0) { + left = 0; + right = p.width; + bottom = 0; + top = p.height; + near = -10; + far = 10 + } + var x = 2 / (right - left); + var y = 2 / (top - bottom); + var z = -2 / (far - near); + var tx = -(right + left) / (right - left); + var ty = -(top + bottom) / (top - bottom); + var tz = -(far + near) / (far - near); + projection = new PMatrix3D; + projection.set(x, 0, 0, tx, 0, y, 0, ty, 0, 0, z, tz, 0, 0, 0, 1); + var proj = new PMatrix3D; + proj.set(projection); + proj.transpose(); + curContext.useProgram(programObject2D); + uniformMatrix("projection2d", programObject2D, "uProjection", false, proj.array()); + curContext.useProgram(programObject3D); + uniformMatrix("projection3d", programObject3D, "uProjection", false, proj.array()); + curContext.useProgram(programObjectUnlitShape); + uniformMatrix("uProjectionUS", programObjectUnlitShape, "uProjection", false, proj.array()); + frustumMode = false + }; + p.printProjection = function() { + projection.print() + }; + p.printCamera = function() { + cam.print() + }; + Drawing2D.prototype.box = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.box = function(w, h, d) { + if (!h || !d) h = d = w; + var model = new PMatrix3D; + model.scale(w, h, d); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + if (doFill) { + curContext.useProgram(programObject3D); + uniformMatrix("model3d", programObject3D, "uModel", false, model.array()); + uniformMatrix("view3d", programObject3D, "uView", false, view.array()); + curContext.enable(curContext.POLYGON_OFFSET_FILL); + curContext.polygonOffset(1, 1); + uniformf("color3d", programObject3D, "uColor", fillStyle); + if (lightCount > 0) { + var v = new PMatrix3D; + v.set(view); + var m = new PMatrix3D; + m.set(model); + v.mult(m); + var normalMatrix = new PMatrix3D; + normalMatrix.set(v); + normalMatrix.invert(); + normalMatrix.transpose(); + uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array()); + vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, boxNormBuffer) + } else disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal"); + vertexAttribPointer("aVertex3d", programObject3D, "aVertex", 3, boxBuffer); + disableVertexAttribPointer("aColor3d", programObject3D, "aColor"); + disableVertexAttribPointer("aTexture3d", programObject3D, "aTexture"); + curContext.drawArrays(curContext.TRIANGLES, 0, boxVerts.length / 3); + curContext.disable(curContext.POLYGON_OFFSET_FILL) + } + if (lineWidth > 0 && doStroke) { + curContext.useProgram(programObject2D); + uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array()); + uniformMatrix("uView2d", programObject2D, "uView", false, view.array()); + uniformf("uColor2d", programObject2D, "uColor", strokeStyle); + uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false); + vertexAttribPointer("vertex2d", programObject2D, "aVertex", 3, boxOutlineBuffer); + disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord"); + curContext.drawArrays(curContext.LINES, 0, boxOutlineVerts.length / 3) + } + }; + var initSphere = function() { + var i; + sphereVerts = []; + for (i = 0; i < sphereDetailU; i++) { + sphereVerts.push(0); + sphereVerts.push(-1); + sphereVerts.push(0); + sphereVerts.push(sphereX[i]); + sphereVerts.push(sphereY[i]); + sphereVerts.push(sphereZ[i]) + } + sphereVerts.push(0); + sphereVerts.push(-1); + sphereVerts.push(0); + sphereVerts.push(sphereX[0]); + sphereVerts.push(sphereY[0]); + sphereVerts.push(sphereZ[0]); + var v1, v11, v2; + var voff = 0; + for (i = 2; i < sphereDetailV; i++) { + v1 = v11 = voff; + voff += sphereDetailU; + v2 = voff; + for (var j = 0; j < sphereDetailU; j++) { + sphereVerts.push(sphereX[v1]); + sphereVerts.push(sphereY[v1]); + sphereVerts.push(sphereZ[v1++]); + sphereVerts.push(sphereX[v2]); + sphereVerts.push(sphereY[v2]); + sphereVerts.push(sphereZ[v2++]) + } + v1 = v11; + v2 = voff; + sphereVerts.push(sphereX[v1]); + sphereVerts.push(sphereY[v1]); + sphereVerts.push(sphereZ[v1]); + sphereVerts.push(sphereX[v2]); + sphereVerts.push(sphereY[v2]); + sphereVerts.push(sphereZ[v2]) + } + for (i = 0; i < sphereDetailU; i++) { + v2 = voff + i; + sphereVerts.push(sphereX[v2]); + sphereVerts.push(sphereY[v2]); + sphereVerts.push(sphereZ[v2]); + sphereVerts.push(0); + sphereVerts.push(1); + sphereVerts.push(0) + } + sphereVerts.push(sphereX[voff]); + sphereVerts.push(sphereY[voff]); + sphereVerts.push(sphereZ[voff]); + sphereVerts.push(0); + sphereVerts.push(1); + sphereVerts.push(0); + curContext.bindBuffer(curContext.ARRAY_BUFFER, sphereBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(sphereVerts), curContext.STATIC_DRAW) + }; + p.sphereDetail = function(ures, vres) { + var i; + if (arguments.length === 1) ures = vres = arguments[0]; + if (ures < 3) ures = 3; + if (vres < 2) vres = 2; + if (ures === sphereDetailU && vres === sphereDetailV) return; + var delta = 720 / ures; + var cx = new Float32Array(ures); + var cz = new Float32Array(ures); + for (i = 0; i < ures; i++) { + cx[i] = cosLUT[i * delta % 720 | 0]; + cz[i] = sinLUT[i * delta % 720 | 0] + } + var vertCount = ures * (vres - 1) + 2; + var currVert = 0; + sphereX = new Float32Array(vertCount); + sphereY = new Float32Array(vertCount); + sphereZ = new Float32Array(vertCount); + var angle_step = 720 * 0.5 / vres; + var angle = angle_step; + for (i = 1; i < vres; i++) { + var curradius = sinLUT[angle % 720 | 0]; + var currY = -cosLUT[angle % 720 | 0]; + for (var j = 0; j < ures; j++) { + sphereX[currVert] = cx[j] * curradius; + sphereY[currVert] = currY; + sphereZ[currVert++] = cz[j] * curradius + } + angle += angle_step + } + sphereDetailU = ures; + sphereDetailV = vres; + initSphere() + }; + Drawing2D.prototype.sphere = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.sphere = function() { + var sRad = arguments[0]; + if (sphereDetailU < 3 || sphereDetailV < 2) p.sphereDetail(30); + var model = new PMatrix3D; + model.scale(sRad, sRad, sRad); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + if (doFill) { + if (lightCount > 0) { + var v = new PMatrix3D; + v.set(view); + var m = new PMatrix3D; + m.set(model); + v.mult(m); + var normalMatrix = new PMatrix3D; + normalMatrix.set(v); + normalMatrix.invert(); + normalMatrix.transpose(); + uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array()); + vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, sphereBuffer) + } else disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal"); + curContext.useProgram(programObject3D); + disableVertexAttribPointer("aTexture3d", programObject3D, "aTexture"); + uniformMatrix("uModel3d", programObject3D, "uModel", false, model.array()); + uniformMatrix("uView3d", programObject3D, "uView", false, view.array()); + vertexAttribPointer("aVertex3d", programObject3D, "aVertex", 3, sphereBuffer); + disableVertexAttribPointer("aColor3d", programObject3D, "aColor"); + curContext.enable(curContext.POLYGON_OFFSET_FILL); + curContext.polygonOffset(1, 1); + uniformf("uColor3d", programObject3D, "uColor", fillStyle); + curContext.drawArrays(curContext.TRIANGLE_STRIP, 0, sphereVerts.length / 3); + curContext.disable(curContext.POLYGON_OFFSET_FILL) + } + if (lineWidth > 0 && doStroke) { + curContext.useProgram(programObject2D); + uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array()); + uniformMatrix("uView2d", programObject2D, "uView", false, view.array()); + vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, sphereBuffer); + disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord"); + uniformf("uColor2d", programObject2D, "uColor", strokeStyle); + uniformi("uIsDrawingText", programObject2D, "uIsDrawingText", false); + curContext.drawArrays(curContext.LINE_STRIP, 0, sphereVerts.length / 3) + } + }; + p.modelX = function(x, y, z) { + var mv = modelView.array(); + var ci = cameraInv.array(); + var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3]; + var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7]; + var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11]; + var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15]; + var ox = ci[0] * ax + ci[1] * ay + ci[2] * az + ci[3] * aw; + var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw; + return ow !== 0 ? ox / ow : ox + }; + p.modelY = function(x, y, z) { + var mv = modelView.array(); + var ci = cameraInv.array(); + var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3]; + var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7]; + var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11]; + var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15]; + var oy = ci[4] * ax + ci[5] * ay + ci[6] * az + ci[7] * aw; + var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw; + return ow !== 0 ? oy / ow : oy + }; + p.modelZ = function(x, y, z) { + var mv = modelView.array(); + var ci = cameraInv.array(); + var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3]; + var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7]; + var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11]; + var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15]; + var oz = ci[8] * ax + ci[9] * ay + ci[10] * az + ci[11] * aw; + var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw; + return ow !== 0 ? oz / ow : oz + }; + Drawing2D.prototype.ambient = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.ambient = function(v1, v2, v3) { + curContext.useProgram(programObject3D); + uniformi("uUsingMat3d", programObject3D, "uUsingMat", true); + var col = p.color(v1, v2, v3); + uniformf("uMaterialAmbient3d", programObject3D, "uMaterialAmbient", p.color.toGLArray(col).slice(0, 3)) + }; + Drawing2D.prototype.emissive = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.emissive = function(v1, v2, v3) { + curContext.useProgram(programObject3D); + uniformi("uUsingMat3d", programObject3D, "uUsingMat", true); + var col = p.color(v1, v2, v3); + uniformf("uMaterialEmissive3d", programObject3D, "uMaterialEmissive", p.color.toGLArray(col).slice(0, 3)) + }; + Drawing2D.prototype.shininess = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.shininess = function(shine) { + curContext.useProgram(programObject3D); + uniformi("uUsingMat3d", programObject3D, "uUsingMat", true); + uniformf("uShininess3d", programObject3D, "uShininess", shine) + }; + Drawing2D.prototype.specular = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.specular = function(v1, v2, v3) { + curContext.useProgram(programObject3D); + uniformi("uUsingMat3d", programObject3D, "uUsingMat", true); + var col = p.color(v1, v2, v3); + uniformf("uMaterialSpecular3d", programObject3D, "uMaterialSpecular", p.color.toGLArray(col).slice(0, 3)) + }; + p.screenX = function(x, y, z) { + var mv = modelView.array(); + if (mv.length === 16) { + var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3]; + var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7]; + var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11]; + var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15]; + var pj = projection.array(); + var ox = pj[0] * ax + pj[1] * ay + pj[2] * az + pj[3] * aw; + var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw; + if (ow !== 0) ox /= ow; + return p.width * (1 + ox) / 2 + } + return modelView.multX(x, y) + }; + p.screenY = function screenY(x, y, z) { + var mv = modelView.array(); + if (mv.length === 16) { + var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3]; + var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7]; + var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11]; + var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15]; + var pj = projection.array(); + var oy = pj[4] * ax + pj[5] * ay + pj[6] * az + pj[7] * aw; + var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw; + if (ow !== 0) oy /= ow; + return p.height * (1 + oy) / 2 + } + return modelView.multY(x, y) + }; + p.screenZ = function screenZ(x, y, z) { + var mv = modelView.array(); + if (mv.length !== 16) return 0; + var pj = projection.array(); + var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3]; + var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7]; + var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11]; + var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15]; + var oz = pj[8] * ax + pj[9] * ay + pj[10] * az + pj[11] * aw; + var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw; + if (ow !== 0) oz /= ow; + return (oz + 1) / 2 + }; + DrawingShared.prototype.fill = function() { + var color = p.color(arguments[0], arguments[1], arguments[2], arguments[3]); + if (color === currentFillColor && doFill) return; + doFill = true; + currentFillColor = color + }; + Drawing2D.prototype.fill = function() { + DrawingShared.prototype.fill.apply(this, arguments); + isFillDirty = true + }; + Drawing3D.prototype.fill = function() { + DrawingShared.prototype.fill.apply(this, arguments); + fillStyle = p.color.toGLArray(currentFillColor) + }; + + function executeContextFill() { + if (doFill) { + if (isFillDirty) { + curContext.fillStyle = p.color.toString(currentFillColor); + isFillDirty = false + } + curContext.fill() + } + } + p.noFill = function() { + doFill = false + }; + DrawingShared.prototype.stroke = function() { + var color = p.color(arguments[0], arguments[1], arguments[2], arguments[3]); + if (color === currentStrokeColor && doStroke) return; + doStroke = true; + currentStrokeColor = color + }; + Drawing2D.prototype.stroke = function() { + DrawingShared.prototype.stroke.apply(this, arguments); + isStrokeDirty = true + }; + Drawing3D.prototype.stroke = function() { + DrawingShared.prototype.stroke.apply(this, arguments); + strokeStyle = p.color.toGLArray(currentStrokeColor) + }; + + function executeContextStroke() { + if (doStroke) { + if (isStrokeDirty) { + curContext.strokeStyle = p.color.toString(currentStrokeColor); + isStrokeDirty = false + } + curContext.stroke() + } + } + p.noStroke = function() { + doStroke = false + }; + DrawingShared.prototype.strokeWeight = function(w) { + lineWidth = w + }; + Drawing2D.prototype.strokeWeight = function(w) { + DrawingShared.prototype.strokeWeight.apply(this, arguments); + curContext.lineWidth = w + }; + Drawing3D.prototype.strokeWeight = function(w) { + DrawingShared.prototype.strokeWeight.apply(this, arguments); + curContext.useProgram(programObject2D); + uniformf("pointSize2d", programObject2D, "uPointSize", w); + curContext.useProgram(programObjectUnlitShape); + uniformf("pointSizeUnlitShape", programObjectUnlitShape, "uPointSize", w); + curContext.lineWidth(w) + }; + p.strokeCap = function(value) { + drawing.$ensureContext().lineCap = value + }; + p.strokeJoin = function(value) { + drawing.$ensureContext().lineJoin = value + }; + Drawing2D.prototype.smooth = function() { + renderSmooth = true; + var style = curElement.style; + style.setProperty("image-rendering", "optimizeQuality", "important"); + style.setProperty("-ms-interpolation-mode", "bicubic", "important"); + if (curContext.hasOwnProperty("mozImageSmoothingEnabled")) curContext.mozImageSmoothingEnabled = true + }; + Drawing3D.prototype.smooth = function() { + renderSmooth = true + }; + Drawing2D.prototype.noSmooth = function() { + renderSmooth = false; + var style = curElement.style; + style.setProperty("image-rendering", "optimizeSpeed", "important"); + style.setProperty("image-rendering", "-moz-crisp-edges", "important"); + style.setProperty("image-rendering", "-webkit-optimize-contrast", "important"); + style.setProperty("image-rendering", "optimize-contrast", "important"); + style.setProperty("-ms-interpolation-mode", "nearest-neighbor", "important"); + if (curContext.hasOwnProperty("mozImageSmoothingEnabled")) curContext.mozImageSmoothingEnabled = false + }; + Drawing3D.prototype.noSmooth = function() { + renderSmooth = false + }; + Drawing2D.prototype.point = function(x, y) { + if (!doStroke) return; + x = Math.round(x); + y = Math.round(y); + curContext.fillStyle = p.color.toString(currentStrokeColor); + isFillDirty = true; + if (lineWidth > 1) { + curContext.beginPath(); + curContext.arc(x, y, lineWidth / 2, 0, 6.283185307179586, false); + curContext.fill() + } else curContext.fillRect(x, y, 1, 1) + }; + Drawing3D.prototype.point = function(x, y, z) { + var model = new PMatrix3D; + model.translate(x, y, z || 0); + model.transpose(); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + curContext.useProgram(programObject2D); + uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array()); + uniformMatrix("uView2d", programObject2D, "uView", false, view.array()); + if (lineWidth > 0 && doStroke) { + uniformf("uColor2d", programObject2D, "uColor", strokeStyle); + uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false); + uniformi("uSmooth2d", programObject2D, "uSmooth", renderSmooth); + vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, pointBuffer); + disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord"); + curContext.drawArrays(curContext.POINTS, 0, 1) + } + }; + p.beginShape = function(type) { + curShape = type; + curvePoints = []; + vertArray = [] + }; + Drawing2D.prototype.vertex = function(x, y, moveTo) { + var vert = []; + if (firstVert) firstVert = false; + vert["isVert"] = true; + vert[0] = x; + vert[1] = y; + vert[2] = 0; + vert[3] = 0; + vert[4] = 0; + vert[5] = currentFillColor; + vert[6] = currentStrokeColor; + vertArray.push(vert); + if (moveTo) vertArray[vertArray.length - 1]["moveTo"] = moveTo + }; + Drawing3D.prototype.vertex = function(x, y, z, u, v) { + var vert = []; + if (firstVert) firstVert = false; + vert["isVert"] = true; + if (v === undef && usingTexture) { + v = u; + u = z; + z = 0 + } + if (u !== undef && v !== undef) { + if (curTextureMode === 2) { + u /= curTexture.width; + v /= curTexture.height + } + u = u > 1 ? 1 : u; + u = u < 0 ? 0 : u; + v = v > 1 ? 1 : v; + v = v < 0 ? 0 : v + } + vert[0] = x; + vert[1] = y; + vert[2] = z || 0; + vert[3] = u || 0; + vert[4] = v || 0; + vert[5] = fillStyle[0]; + vert[6] = fillStyle[1]; + vert[7] = fillStyle[2]; + vert[8] = fillStyle[3]; + vert[9] = strokeStyle[0]; + vert[10] = strokeStyle[1]; + vert[11] = strokeStyle[2]; + vert[12] = strokeStyle[3]; + vert[13] = normalX; + vert[14] = normalY; + vert[15] = normalZ; + vertArray.push(vert) + }; + var point3D = function(vArray, cArray) { + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + curContext.useProgram(programObjectUnlitShape); + uniformMatrix("uViewUS", programObjectUnlitShape, "uView", false, view.array()); + uniformi("uSmoothUS", programObjectUnlitShape, "uSmooth", renderSmooth); + vertexAttribPointer("aVertexUS", programObjectUnlitShape, "aVertex", 3, pointBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW); + vertexAttribPointer("aColorUS", programObjectUnlitShape, "aColor", 4, fillColorBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW); + curContext.drawArrays(curContext.POINTS, 0, vArray.length / 3) + }; + var line3D = function(vArray, mode, cArray) { + var ctxMode; + if (mode === "LINES") ctxMode = curContext.LINES; + else if (mode === "LINE_LOOP") ctxMode = curContext.LINE_LOOP; + else ctxMode = curContext.LINE_STRIP; + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + curContext.useProgram(programObjectUnlitShape); + uniformMatrix("uViewUS", programObjectUnlitShape, "uView", false, view.array()); + vertexAttribPointer("aVertexUS", programObjectUnlitShape, "aVertex", 3, lineBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW); + vertexAttribPointer("aColorUS", programObjectUnlitShape, "aColor", 4, strokeColorBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW); + curContext.drawArrays(ctxMode, 0, vArray.length / 3) + }; + var fill3D = function(vArray, mode, cArray, tArray) { + var ctxMode; + if (mode === "TRIANGLES") ctxMode = curContext.TRIANGLES; + else if (mode === "TRIANGLE_FAN") ctxMode = curContext.TRIANGLE_FAN; + else ctxMode = curContext.TRIANGLE_STRIP; + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + curContext.useProgram(programObject3D); + uniformMatrix("model3d", programObject3D, "uModel", false, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); + uniformMatrix("view3d", programObject3D, "uView", false, view.array()); + curContext.enable(curContext.POLYGON_OFFSET_FILL); + curContext.polygonOffset(1, 1); + uniformf("color3d", programObject3D, "uColor", [-1, 0, 0, 0]); + vertexAttribPointer("vertex3d", programObject3D, "aVertex", 3, fillBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW); + if (usingTexture && curTint !== null) curTint3d(cArray); + vertexAttribPointer("aColor3d", programObject3D, "aColor", 4, fillColorBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW); + disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal"); + if (usingTexture) { + uniformi("uUsingTexture3d", programObject3D, "uUsingTexture", usingTexture); + vertexAttribPointer("aTexture3d", programObject3D, "aTexture", 2, shapeTexVBO); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(tArray), curContext.STREAM_DRAW) + } + curContext.drawArrays(ctxMode, 0, vArray.length / 3); + curContext.disable(curContext.POLYGON_OFFSET_FILL) + }; + + function fillStrokeClose() { + executeContextFill(); + executeContextStroke(); + curContext.closePath() + } + Drawing2D.prototype.endShape = function(mode) { + if (vertArray.length === 0) return; + var closeShape = mode === 2; + if (closeShape) vertArray.push(vertArray[0]); + var lineVertArray = []; + var fillVertArray = []; + var colorVertArray = []; + var strokeVertArray = []; + var texVertArray = []; + var cachedVertArray; + firstVert = true; + var i, j, k; + var vertArrayLength = vertArray.length; + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) fillVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + texVertArray.push(cachedVertArray[3]); + texVertArray.push(cachedVertArray[4]) + } + if (isCurve && (curShape === 20 || curShape === undef)) { + if (vertArrayLength > 3) { + var b = [], + s = 1 - curTightness; + curContext.beginPath(); + curContext.moveTo(vertArray[1][0], vertArray[1][1]); + for (i = 1; i + 2 < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + b[0] = [cachedVertArray[0], cachedVertArray[1]]; + b[1] = [cachedVertArray[0] + (s * vertArray[i + 1][0] - s * vertArray[i - 1][0]) / 6, cachedVertArray[1] + (s * vertArray[i + 1][1] - s * vertArray[i - 1][1]) / 6]; + b[2] = [vertArray[i + 1][0] + (s * vertArray[i][0] - s * vertArray[i + 2][0]) / 6, vertArray[i + 1][1] + (s * vertArray[i][1] - s * vertArray[i + 2][1]) / 6]; + b[3] = [vertArray[i + 1][0], vertArray[i + 1][1]]; + curContext.bezierCurveTo(b[1][0], b[1][1], b[2][0], b[2][1], b[3][0], b[3][1]) + } + fillStrokeClose() + } + } else if (isBezier && (curShape === 20 || curShape === undef)) { + curContext.beginPath(); + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + if (vertArray[i]["isVert"]) if (vertArray[i]["moveTo"]) curContext.moveTo(cachedVertArray[0], cachedVertArray[1]); + else curContext.lineTo(cachedVertArray[0], cachedVertArray[1]); + else curContext.bezierCurveTo(vertArray[i][0], vertArray[i][1], vertArray[i][2], vertArray[i][3], vertArray[i][4], vertArray[i][5]) + } + fillStrokeClose() + } else if (curShape === 2) for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + if (doStroke) p.stroke(cachedVertArray[6]); + p.point(cachedVertArray[0], cachedVertArray[1]) + } else if (curShape === 4) for (i = 0; i + 1 < vertArrayLength; i += 2) { + cachedVertArray = vertArray[i]; + if (doStroke) p.stroke(vertArray[i + 1][6]); + p.line(cachedVertArray[0], cachedVertArray[1], vertArray[i + 1][0], vertArray[i + 1][1]) + } else if (curShape === 9) for (i = 0; i + 2 < vertArrayLength; i += 3) { + cachedVertArray = vertArray[i]; + curContext.beginPath(); + curContext.moveTo(cachedVertArray[0], cachedVertArray[1]); + curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1]); + curContext.lineTo(vertArray[i + 2][0], vertArray[i + 2][1]); + curContext.lineTo(cachedVertArray[0], cachedVertArray[1]); + if (doFill) { + p.fill(vertArray[i + 2][5]); + executeContextFill() + } + if (doStroke) { + p.stroke(vertArray[i + 2][6]); + executeContextStroke() + } + curContext.closePath() + } else if (curShape === 10) for (i = 0; i + 1 < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + curContext.beginPath(); + curContext.moveTo(vertArray[i + 1][0], vertArray[i + 1][1]); + curContext.lineTo(cachedVertArray[0], cachedVertArray[1]); + if (doStroke) p.stroke(vertArray[i + 1][6]); + if (doFill) p.fill(vertArray[i + 1][5]); + if (i + 2 < vertArrayLength) { + curContext.lineTo(vertArray[i + 2][0], vertArray[i + 2][1]); + if (doStroke) p.stroke(vertArray[i + 2][6]); + if (doFill) p.fill(vertArray[i + 2][5]) + } + fillStrokeClose() + } else if (curShape === 11) { + if (vertArrayLength > 2) { + curContext.beginPath(); + curContext.moveTo(vertArray[0][0], vertArray[0][1]); + curContext.lineTo(vertArray[1][0], vertArray[1][1]); + curContext.lineTo(vertArray[2][0], vertArray[2][1]); + if (doFill) { + p.fill(vertArray[2][5]); + executeContextFill() + } + if (doStroke) { + p.stroke(vertArray[2][6]); + executeContextStroke() + } + curContext.closePath(); + for (i = 3; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + curContext.beginPath(); + curContext.moveTo(vertArray[0][0], vertArray[0][1]); + curContext.lineTo(vertArray[i - 1][0], vertArray[i - 1][1]); + curContext.lineTo(cachedVertArray[0], cachedVertArray[1]); + if (doFill) { + p.fill(cachedVertArray[5]); + executeContextFill() + } + if (doStroke) { + p.stroke(cachedVertArray[6]); + executeContextStroke() + } + curContext.closePath() + } + } + } else if (curShape === 16) for (i = 0; i + 3 < vertArrayLength; i += 4) { + cachedVertArray = vertArray[i]; + curContext.beginPath(); + curContext.moveTo(cachedVertArray[0], cachedVertArray[1]); + for (j = 1; j < 4; j++) curContext.lineTo(vertArray[i + j][0], vertArray[i + j][1]); + curContext.lineTo(cachedVertArray[0], cachedVertArray[1]); + if (doFill) { + p.fill(vertArray[i + 3][5]); + executeContextFill() + } + if (doStroke) { + p.stroke(vertArray[i + 3][6]); + executeContextStroke() + } + curContext.closePath() + } else if (curShape === 17) { + if (vertArrayLength > 3) for (i = 0; i + 1 < vertArrayLength; i += 2) { + cachedVertArray = vertArray[i]; + curContext.beginPath(); + if (i + 3 < vertArrayLength) { + curContext.moveTo(vertArray[i + 2][0], vertArray[i + 2][1]); + curContext.lineTo(cachedVertArray[0], cachedVertArray[1]); + curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1]); + curContext.lineTo(vertArray[i + 3][0], vertArray[i + 3][1]); + if (doFill) p.fill(vertArray[i + 3][5]); + if (doStroke) p.stroke(vertArray[i + 3][6]) + } else { + curContext.moveTo(cachedVertArray[0], cachedVertArray[1]); + curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1]) + } + fillStrokeClose() + } + } else { + curContext.beginPath(); + curContext.moveTo(vertArray[0][0], vertArray[0][1]); + for (i = 1; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + if (cachedVertArray["isVert"]) if (cachedVertArray["moveTo"]) curContext.moveTo(cachedVertArray[0], cachedVertArray[1]); + else curContext.lineTo(cachedVertArray[0], cachedVertArray[1]) + } + fillStrokeClose() + } + isCurve = false; + isBezier = false; + curveVertArray = []; + curveVertCount = 0; + if (closeShape) vertArray.pop() + }; + Drawing3D.prototype.endShape = function(mode) { + if (vertArray.length === 0) return; + var closeShape = mode === 2; + var lineVertArray = []; + var fillVertArray = []; + var colorVertArray = []; + var strokeVertArray = []; + var texVertArray = []; + var cachedVertArray; + firstVert = true; + var i, j, k; + var vertArrayLength = vertArray.length; + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) fillVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + texVertArray.push(cachedVertArray[3]); + texVertArray.push(cachedVertArray[4]) + } + if (closeShape) { + fillVertArray.push(vertArray[0][0]); + fillVertArray.push(vertArray[0][1]); + fillVertArray.push(vertArray[0][2]); + for (i = 5; i < 9; i++) colorVertArray.push(vertArray[0][i]); + for (i = 9; i < 13; i++) strokeVertArray.push(vertArray[0][i]); + texVertArray.push(vertArray[0][3]); + texVertArray.push(vertArray[0][4]) + } + if (isCurve && (curShape === 20 || curShape === undef)) { + lineVertArray = fillVertArray; + if (doStroke) line3D(lineVertArray, null, strokeVertArray); + if (doFill) fill3D(fillVertArray, null, colorVertArray) + } else if (isBezier && (curShape === 20 || curShape === undef)) { + lineVertArray = fillVertArray; + lineVertArray.splice(lineVertArray.length - 3); + strokeVertArray.splice(strokeVertArray.length - 4); + if (doStroke) line3D(lineVertArray, null, strokeVertArray); + if (doFill) fill3D(fillVertArray, "TRIANGLES", colorVertArray) + } else { + if (curShape === 2) { + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j]) + } + point3D(lineVertArray, strokeVertArray) + } else if (curShape === 4) { + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j]) + } + line3D(lineVertArray, "LINES", strokeVertArray) + } else if (curShape === 9) { + if (vertArrayLength > 2) for (i = 0; i + 2 < vertArrayLength; i += 3) { + fillVertArray = []; + texVertArray = []; + lineVertArray = []; + colorVertArray = []; + strokeVertArray = []; + for (j = 0; j < 3; j++) for (k = 0; k < 3; k++) { + lineVertArray.push(vertArray[i + j][k]); + fillVertArray.push(vertArray[i + j][k]) + } + for (j = 0; j < 3; j++) for (k = 3; k < 5; k++) texVertArray.push(vertArray[i + j][k]); + for (j = 0; j < 3; j++) for (k = 5; k < 9; k++) { + colorVertArray.push(vertArray[i + j][k]); + strokeVertArray.push(vertArray[i + j][k + 4]) + } + if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray); + if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLES", colorVertArray, texVertArray) + } + } else if (curShape === 10) { + if (vertArrayLength > 2) for (i = 0; i + 2 < vertArrayLength; i++) { + lineVertArray = []; + fillVertArray = []; + strokeVertArray = []; + colorVertArray = []; + texVertArray = []; + for (j = 0; j < 3; j++) for (k = 0; k < 3; k++) { + lineVertArray.push(vertArray[i + j][k]); + fillVertArray.push(vertArray[i + j][k]) + } + for (j = 0; j < 3; j++) for (k = 3; k < 5; k++) texVertArray.push(vertArray[i + j][k]); + for (j = 0; j < 3; j++) for (k = 5; k < 9; k++) { + strokeVertArray.push(vertArray[i + j][k + 4]); + colorVertArray.push(vertArray[i + j][k]) + } + if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_STRIP", colorVertArray, texVertArray); + if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray) + } + } else if (curShape === 11) { + if (vertArrayLength > 2) { + for (i = 0; i < 3; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < 3; i++) { + cachedVertArray = vertArray[i]; + for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j]) + } + if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray); + for (i = 2; i + 1 < vertArrayLength; i++) { + lineVertArray = []; + strokeVertArray = []; + lineVertArray.push(vertArray[0][0]); + lineVertArray.push(vertArray[0][1]); + lineVertArray.push(vertArray[0][2]); + strokeVertArray.push(vertArray[0][9]); + strokeVertArray.push(vertArray[0][10]); + strokeVertArray.push(vertArray[0][11]); + strokeVertArray.push(vertArray[0][12]); + for (j = 0; j < 2; j++) for (k = 0; k < 3; k++) lineVertArray.push(vertArray[i + j][k]); + for (j = 0; j < 2; j++) for (k = 9; k < 13; k++) strokeVertArray.push(vertArray[i + j][k]); + if (doStroke) line3D(lineVertArray, "LINE_STRIP", strokeVertArray) + } + if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray, texVertArray) + } + } else if (curShape === 16) for (i = 0; i + 3 < vertArrayLength; i += 4) { + lineVertArray = []; + for (j = 0; j < 4; j++) { + cachedVertArray = vertArray[i + j]; + for (k = 0; k < 3; k++) lineVertArray.push(cachedVertArray[k]) + } + if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray); + if (doFill) { + fillVertArray = []; + colorVertArray = []; + texVertArray = []; + for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i][j]); + for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i][j]); + for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 1][j]); + for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 1][j]); + for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 3][j]); + for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 3][j]); + for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 2][j]); + for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 2][j]); + if (usingTexture) { + texVertArray.push(vertArray[i + 0][3]); + texVertArray.push(vertArray[i + 0][4]); + texVertArray.push(vertArray[i + 1][3]); + texVertArray.push(vertArray[i + 1][4]); + texVertArray.push(vertArray[i + 3][3]); + texVertArray.push(vertArray[i + 3][4]); + texVertArray.push(vertArray[i + 2][3]); + texVertArray.push(vertArray[i + 2][4]) + } + fill3D(fillVertArray, "TRIANGLE_STRIP", colorVertArray, texVertArray) + } + } else if (curShape === 17) { + var tempArray = []; + if (vertArrayLength > 3) { + for (i = 0; i < 2; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < 2; i++) { + cachedVertArray = vertArray[i]; + for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j]) + } + line3D(lineVertArray, "LINE_STRIP", strokeVertArray); + if (vertArrayLength > 4 && vertArrayLength % 2 > 0) { + tempArray = fillVertArray.splice(fillVertArray.length - 3); + vertArray.pop() + } + for (i = 0; i + 3 < vertArrayLength; i += 2) { + lineVertArray = []; + strokeVertArray = []; + for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 1][j]); + for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 3][j]); + for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 2][j]); + for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 0][j]); + for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 1][j]); + for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 3][j]); + for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 2][j]); + for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 0][j]); + if (doStroke) line3D(lineVertArray, "LINE_STRIP", strokeVertArray) + } + if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_LIST", colorVertArray, texVertArray) + } + } else if (vertArrayLength === 1) { + for (j = 0; j < 3; j++) lineVertArray.push(vertArray[0][j]); + for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[0][j]); + point3D(lineVertArray, strokeVertArray) + } else { + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j]); + for (j = 5; j < 9; j++) strokeVertArray.push(cachedVertArray[j]) + } + if (doStroke && closeShape) line3D(lineVertArray, "LINE_LOOP", strokeVertArray); + else if (doStroke && !closeShape) line3D(lineVertArray, "LINE_STRIP", strokeVertArray); + if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray, texVertArray) + } + usingTexture = false; + curContext.useProgram(programObject3D); + uniformi("usingTexture3d", programObject3D, "uUsingTexture", usingTexture) + } + isCurve = false; + isBezier = false; + curveVertArray = []; + curveVertCount = 0 + }; + var splineForward = function(segments, matrix) { + var f = 1 / segments; + var ff = f * f; + var fff = ff * f; + matrix.set(0, 0, 0, 1, fff, ff, f, 0, 6 * fff, 2 * ff, 0, 0, 6 * fff, 0, 0, 0) + }; + var curveInit = function() { + if (!curveDrawMatrix) { + curveBasisMatrix = new PMatrix3D; + curveDrawMatrix = new PMatrix3D; + curveInited = true + } + var s = curTightness; + curveBasisMatrix.set((s - 1) / 2, (s + 3) / 2, (-3 - s) / 2, (1 - s) / 2, 1 - s, (-5 - s) / 2, s + 2, (s - 1) / 2, (s - 1) / 2, 0, (1 - s) / 2, 0, 0, 1, 0, 0); + splineForward(curveDet, curveDrawMatrix); + if (!bezierBasisInverse) curveToBezierMatrix = new PMatrix3D; + curveToBezierMatrix.set(curveBasisMatrix); + curveToBezierMatrix.preApply(bezierBasisInverse); + curveDrawMatrix.apply(curveBasisMatrix) + }; + Drawing2D.prototype.bezierVertex = function() { + isBezier = true; + var vert = []; + if (firstVert) throw "vertex() must be used at least once before calling bezierVertex()"; + for (var i = 0; i < arguments.length; i++) vert[i] = arguments[i]; + vertArray.push(vert); + vertArray[vertArray.length - 1]["isVert"] = false + }; + Drawing3D.prototype.bezierVertex = function() { + isBezier = true; + var vert = []; + if (firstVert) throw "vertex() must be used at least once before calling bezierVertex()"; + if (arguments.length === 9) { + if (bezierDrawMatrix === undef) bezierDrawMatrix = new PMatrix3D; + var lastPoint = vertArray.length - 1; + splineForward(bezDetail, bezierDrawMatrix); + bezierDrawMatrix.apply(bezierBasisMatrix); + var draw = bezierDrawMatrix.array(); + var x1 = vertArray[lastPoint][0], + y1 = vertArray[lastPoint][1], + z1 = vertArray[lastPoint][2]; + var xplot1 = draw[4] * x1 + draw[5] * arguments[0] + draw[6] * arguments[3] + draw[7] * arguments[6]; + var xplot2 = draw[8] * x1 + draw[9] * arguments[0] + draw[10] * arguments[3] + draw[11] * arguments[6]; + var xplot3 = draw[12] * x1 + draw[13] * arguments[0] + draw[14] * arguments[3] + draw[15] * arguments[6]; + var yplot1 = draw[4] * y1 + draw[5] * arguments[1] + draw[6] * arguments[4] + draw[7] * arguments[7]; + var yplot2 = draw[8] * y1 + draw[9] * arguments[1] + draw[10] * arguments[4] + draw[11] * arguments[7]; + var yplot3 = draw[12] * y1 + draw[13] * arguments[1] + draw[14] * arguments[4] + draw[15] * arguments[7]; + var zplot1 = draw[4] * z1 + draw[5] * arguments[2] + draw[6] * arguments[5] + draw[7] * arguments[8]; + var zplot2 = draw[8] * z1 + draw[9] * arguments[2] + draw[10] * arguments[5] + draw[11] * arguments[8]; + var zplot3 = draw[12] * z1 + draw[13] * arguments[2] + draw[14] * arguments[5] + draw[15] * arguments[8]; + for (var j = 0; j < bezDetail; j++) { + x1 += xplot1; + xplot1 += xplot2; + xplot2 += xplot3; + y1 += yplot1; + yplot1 += yplot2; + yplot2 += yplot3; + z1 += zplot1; + zplot1 += zplot2; + zplot2 += zplot3; + p.vertex(x1, y1, z1) + } + p.vertex(arguments[6], arguments[7], arguments[8]) + } + }; + p.texture = function(pimage) { + var curContext = drawing.$ensureContext(); + if (pimage.__texture) curContext.bindTexture(curContext.TEXTURE_2D, pimage.__texture); + else if (pimage.localName === "canvas") { + curContext.bindTexture(curContext.TEXTURE_2D, canTex); + curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, pimage); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR); + curContext.generateMipmap(curContext.TEXTURE_2D); + curTexture.width = pimage.width; + curTexture.height = pimage.height + } else { + var texture = curContext.createTexture(), + cvs = document.createElement("canvas"), + cvsTextureCtx = cvs.getContext("2d"), + pot; + if (pimage.width & pimage.width - 1 === 0) cvs.width = pimage.width; + else { + pot = 1; + while (pot < pimage.width) pot *= 2; + cvs.width = pot + } + if (pimage.height & pimage.height - 1 === 0) cvs.height = pimage.height; + else { + pot = 1; + while (pot < pimage.height) pot *= 2; + cvs.height = pot + } + cvsTextureCtx.drawImage(pimage.sourceImg, 0, 0, pimage.width, pimage.height, 0, 0, cvs.width, cvs.height); + curContext.bindTexture(curContext.TEXTURE_2D, texture); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR_MIPMAP_LINEAR); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_T, curContext.CLAMP_TO_EDGE); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_S, curContext.CLAMP_TO_EDGE); + curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, cvs); + curContext.generateMipmap(curContext.TEXTURE_2D); + pimage.__texture = texture; + curTexture.width = pimage.width; + curTexture.height = pimage.height + } + usingTexture = true; + curContext.useProgram(programObject3D); + uniformi("usingTexture3d", programObject3D, "uUsingTexture", usingTexture) + }; + p.textureMode = function(mode) { + curTextureMode = mode + }; + var curveVertexSegment = function(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) { + var x0 = x2; + var y0 = y2; + var z0 = z2; + var draw = curveDrawMatrix.array(); + var xplot1 = draw[4] * x1 + draw[5] * x2 + draw[6] * x3 + draw[7] * x4; + var xplot2 = draw[8] * x1 + draw[9] * x2 + draw[10] * x3 + draw[11] * x4; + var xplot3 = draw[12] * x1 + draw[13] * x2 + draw[14] * x3 + draw[15] * x4; + var yplot1 = draw[4] * y1 + draw[5] * y2 + draw[6] * y3 + draw[7] * y4; + var yplot2 = draw[8] * y1 + draw[9] * y2 + draw[10] * y3 + draw[11] * y4; + var yplot3 = draw[12] * y1 + draw[13] * y2 + draw[14] * y3 + draw[15] * y4; + var zplot1 = draw[4] * z1 + draw[5] * z2 + draw[6] * z3 + draw[7] * z4; + var zplot2 = draw[8] * z1 + draw[9] * z2 + draw[10] * z3 + draw[11] * z4; + var zplot3 = draw[12] * z1 + draw[13] * z2 + draw[14] * z3 + draw[15] * z4; + p.vertex(x0, y0, z0); + for (var j = 0; j < curveDet; j++) { + x0 += xplot1; + xplot1 += xplot2; + xplot2 += xplot3; + y0 += yplot1; + yplot1 += yplot2; + yplot2 += yplot3; + z0 += zplot1; + zplot1 += zplot2; + zplot2 += zplot3; + p.vertex(x0, y0, z0) + } + }; + Drawing2D.prototype.curveVertex = function(x, y) { + isCurve = true; + p.vertex(x, y) + }; + Drawing3D.prototype.curveVertex = function(x, y, z) { + isCurve = true; + if (!curveInited) curveInit(); + var vert = []; + vert[0] = x; + vert[1] = y; + vert[2] = z; + curveVertArray.push(vert); + curveVertCount++; + if (curveVertCount > 3) curveVertexSegment(curveVertArray[curveVertCount - 4][0], curveVertArray[curveVertCount - 4][1], curveVertArray[curveVertCount - 4][2], curveVertArray[curveVertCount - 3][0], curveVertArray[curveVertCount - 3][1], curveVertArray[curveVertCount - 3][2], curveVertArray[curveVertCount - 2][0], curveVertArray[curveVertCount - 2][1], curveVertArray[curveVertCount - 2][2], curveVertArray[curveVertCount - 1][0], curveVertArray[curveVertCount - 1][1], curveVertArray[curveVertCount - 1][2]) + }; + Drawing2D.prototype.curve = function(x1, y1, x2, y2, x3, y3, x4, y4) { + p.beginShape(); + p.curveVertex(x1, y1); + p.curveVertex(x2, y2); + p.curveVertex(x3, y3); + p.curveVertex(x4, y4); + p.endShape() + }; + Drawing3D.prototype.curve = function(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) { + if (z4 !== undef) { + p.beginShape(); + p.curveVertex(x1, y1, z1); + p.curveVertex(x2, y2, z2); + p.curveVertex(x3, y3, z3); + p.curveVertex(x4, y4, z4); + p.endShape(); + return + } + p.beginShape(); + p.curveVertex(x1, y1); + p.curveVertex(z1, x2); + p.curveVertex(y2, z2); + p.curveVertex(x3, y3); + p.endShape() + }; + p.curveTightness = function(tightness) { + curTightness = tightness + }; + p.curveDetail = function(detail) { + curveDet = detail; + curveInit() + }; + p.rectMode = function(aRectMode) { + curRectMode = aRectMode + }; + p.imageMode = function(mode) { + switch (mode) { + case 0: + imageModeConvert = imageModeCorner; + break; + case 1: + imageModeConvert = imageModeCorners; + break; + case 3: + imageModeConvert = imageModeCenter; + break; + default: + throw "Invalid imageMode"; + } + }; + p.ellipseMode = function(aEllipseMode) { + curEllipseMode = aEllipseMode + }; + p.arc = function(x, y, width, height, start, stop) { + if (width <= 0 || stop < start) return; + if (curEllipseMode === 1) { + width = width - x; + height = height - y + } else if (curEllipseMode === 2) { + x = x - width; + y = y - height; + width = width * 2; + height = height * 2 + } else if (curEllipseMode === 3) { + x = x - width / 2; + y = y - height / 2 + } + while (start < 0) { + start += 6.283185307179586; + stop += 6.283185307179586 + } + if (stop - start > 6.283185307179586) { + start = 0; + stop = 6.283185307179586 + } + var hr = width / 2, + vr = height / 2, + centerX = x + hr, + centerY = y + vr, + startLUT = 0 | 0.5 + start * p.RAD_TO_DEG * 2, + stopLUT = 0 | 0.5 + stop * p.RAD_TO_DEG * 2, + i, j; + if (doFill) { + var savedStroke = doStroke; + doStroke = false; + p.beginShape(); + p.vertex(centerX, centerY); + for (i = startLUT; i <= stopLUT; i++) { + j = i % 720; + p.vertex(centerX + cosLUT[j] * hr, centerY + sinLUT[j] * vr) + } + p.endShape(2); + doStroke = savedStroke + } + if (doStroke) { + var savedFill = doFill; + doFill = false; + p.beginShape(); + for (i = startLUT; i <= stopLUT; i++) { + j = i % 720; + p.vertex(centerX + cosLUT[j] * hr, centerY + sinLUT[j] * vr) + } + p.endShape(); + doFill = savedFill + } + }; + Drawing2D.prototype.line = function(x1, y1, x2, y2) { + if (!doStroke) return; + x1 = Math.round(x1); + x2 = Math.round(x2); + y1 = Math.round(y1); + y2 = Math.round(y2); + if (x1 === x2 && y1 === y2) { + p.point(x1, y1); + return + } + var swap = undef, + lineCap = undef, + drawCrisp = true, + currentModelView = modelView.array(), + identityMatrix = [1, 0, 0, 0, 1, 0]; + for (var i = 0; i < 6 && drawCrisp; i++) drawCrisp = currentModelView[i] === identityMatrix[i]; + if (drawCrisp) { + if (x1 === x2) { + if (y1 > y2) { + swap = y1; + y1 = y2; + y2 = swap + } + y2++; + if (lineWidth % 2 === 1) curContext.translate(0.5, 0) + } else if (y1 === y2) { + if (x1 > x2) { + swap = x1; + x1 = x2; + x2 = swap + } + x2++; + if (lineWidth % 2 === 1) curContext.translate(0, 0.5) + } + if (lineWidth === 1) { + lineCap = curContext.lineCap; + curContext.lineCap = "butt" + } + } + curContext.beginPath(); + curContext.moveTo(x1 || 0, y1 || 0); + curContext.lineTo(x2 || 0, y2 || 0); + executeContextStroke(); + if (drawCrisp) { + if (x1 === x2 && lineWidth % 2 === 1) curContext.translate(-0.5, 0); + else if (y1 === y2 && lineWidth % 2 === 1) curContext.translate(0, -0.5); + if (lineWidth === 1) curContext.lineCap = lineCap + } + }; + Drawing3D.prototype.line = function(x1, y1, z1, x2, y2, z2) { + if (y2 === undef || z2 === undef) { + z2 = 0; + y2 = x2; + x2 = z1; + z1 = 0 + } + if (x1 === x2 && y1 === y2 && z1 === z2) { + p.point(x1, y1, z1); + return + } + var lineVerts = [x1, y1, z1, x2, y2, z2]; + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + if (lineWidth > 0 && doStroke) { + curContext.useProgram(programObject2D); + uniformMatrix("uModel2d", programObject2D, "uModel", false, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); + uniformMatrix("uView2d", programObject2D, "uView", false, view.array()); + uniformf("uColor2d", programObject2D, "uColor", strokeStyle); + uniformi("uIsDrawingText", programObject2D, "uIsDrawingText", false); + vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, lineBuffer); + disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord"); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(lineVerts), curContext.STREAM_DRAW); + curContext.drawArrays(curContext.LINES, 0, 2) + } + }; + Drawing2D.prototype.bezier = function() { + if (arguments.length !== 8) throw "You must use 8 parameters for bezier() in 2D mode"; + p.beginShape(); + p.vertex(arguments[0], arguments[1]); + p.bezierVertex(arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7]); + p.endShape() + }; + Drawing3D.prototype.bezier = function() { + if (arguments.length !== 12) throw "You must use 12 parameters for bezier() in 3D mode"; + p.beginShape(); + p.vertex(arguments[0], arguments[1], arguments[2]); + p.bezierVertex(arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11]); + p.endShape() + }; + p.bezierDetail = function(detail) { + bezDetail = detail + }; + p.bezierPoint = function(a, b, c, d, t) { + return (1 - t) * (1 - t) * (1 - t) * a + 3 * (1 - t) * (1 - t) * t * b + 3 * (1 - t) * t * t * c + t * t * t * d + }; + p.bezierTangent = function(a, b, c, d, t) { + return 3 * t * t * (-a + 3 * b - 3 * c + d) + 6 * t * (a - 2 * b + c) + 3 * (-a + b) + }; + p.curvePoint = function(a, b, c, d, t) { + return 0.5 * (2 * b + (-a + c) * t + (2 * a - 5 * b + 4 * c - d) * t * t + (-a + 3 * b - 3 * c + d) * t * t * t) + }; + p.curveTangent = function(a, b, c, d, t) { + return 0.5 * (-a + c + 2 * (2 * a - 5 * b + 4 * c - d) * t + 3 * (-a + 3 * b - 3 * c + d) * t * t) + }; + p.triangle = function(x1, y1, x2, y2, x3, y3) { + p.beginShape(9); + p.vertex(x1, y1, 0); + p.vertex(x2, y2, 0); + p.vertex(x3, y3, 0); + p.endShape() + }; + p.quad = function(x1, y1, x2, y2, x3, y3, x4, y4) { + p.beginShape(16); + p.vertex(x1, y1, 0); + p.vertex(x2, y2, 0); + p.vertex(x3, y3, 0); + p.vertex(x4, y4, 0); + p.endShape() + }; + var roundedRect$2d = function(x, y, width, height, tl, tr, br, bl) { + if (bl === undef) { + tr = tl; + br = tl; + bl = tl + } + var halfWidth = width / 2, + halfHeight = height / 2; + if (tl > halfWidth || tl > halfHeight) tl = Math.min(halfWidth, halfHeight); + if (tr > halfWidth || tr > halfHeight) tr = Math.min(halfWidth, halfHeight); + if (br > halfWidth || br > halfHeight) br = Math.min(halfWidth, halfHeight); + if (bl > halfWidth || bl > halfHeight) bl = Math.min(halfWidth, halfHeight); + if (!doFill || doStroke) curContext.translate(0.5, 0.5); + curContext.beginPath(); + curContext.moveTo(x + tl, y); + curContext.lineTo(x + width - tr, y); + curContext.quadraticCurveTo(x + width, y, x + width, y + tr); + curContext.lineTo(x + width, y + height - br); + curContext.quadraticCurveTo(x + width, y + height, x + width - br, y + height); + curContext.lineTo(x + bl, y + height); + curContext.quadraticCurveTo(x, y + height, x, y + height - bl); + curContext.lineTo(x, y + tl); + curContext.quadraticCurveTo(x, y, x + tl, y); + if (!doFill || doStroke) curContext.translate(-0.5, -0.5); + executeContextFill(); + executeContextStroke() + }; + Drawing2D.prototype.rect = function(x, y, width, height, tl, tr, br, bl) { + if (!width && !height) return; + if (curRectMode === 1) { + width -= x; + height -= y + } else if (curRectMode === 2) { + width *= 2; + height *= 2; + x -= width / 2; + y -= height / 2 + } else if (curRectMode === 3) { + x -= width / 2; + y -= height / 2 + } + x = Math.round(x); + y = Math.round(y); + width = Math.round(width); + height = Math.round(height); + if (tl !== undef) { + roundedRect$2d(x, y, width, height, tl, tr, br, bl); + return + } + if (doStroke && lineWidth % 2 === 1) curContext.translate(0.5, 0.5); + curContext.beginPath(); + curContext.rect(x, y, width, height); + executeContextFill(); + executeContextStroke(); + if (doStroke && lineWidth % 2 === 1) curContext.translate(-0.5, -0.5) + }; + Drawing3D.prototype.rect = function(x, y, width, height, tl, tr, br, bl) { + if (tl !== undef) throw "rect() with rounded corners is not supported in 3D mode"; + if (curRectMode === 1) { + width -= x; + height -= y + } else if (curRectMode === 2) { + width *= 2; + height *= 2; + x -= width / 2; + y -= height / 2 + } else if (curRectMode === 3) { + x -= width / 2; + y -= height / 2 + } + var model = new PMatrix3D; + model.translate(x, y, 0); + model.scale(width, height, 1); + model.transpose(); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + if (lineWidth > 0 && doStroke) { + curContext.useProgram(programObject2D); + uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array()); + uniformMatrix("uView2d", programObject2D, "uView", false, view.array()); + uniformf("uColor2d", programObject2D, "uColor", strokeStyle); + uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false); + vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, rectBuffer); + disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord"); + curContext.drawArrays(curContext.LINE_LOOP, 0, rectVerts.length / 3) + } + if (doFill) { + curContext.useProgram(programObject3D); + uniformMatrix("uModel3d", programObject3D, "uModel", false, model.array()); + uniformMatrix("uView3d", programObject3D, "uView", false, view.array()); + curContext.enable(curContext.POLYGON_OFFSET_FILL); + curContext.polygonOffset(1, 1); + uniformf("color3d", programObject3D, "uColor", fillStyle); + if (lightCount > 0) { + var v = new PMatrix3D; + v.set(view); + var m = new PMatrix3D; + m.set(model); + v.mult(m); + var normalMatrix = new PMatrix3D; + normalMatrix.set(v); + normalMatrix.invert(); + normalMatrix.transpose(); + uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array()); + vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, rectNormBuffer) + } else disableVertexAttribPointer("normal3d", programObject3D, "aNormal"); + vertexAttribPointer("vertex3d", programObject3D, "aVertex", 3, rectBuffer); + curContext.drawArrays(curContext.TRIANGLE_FAN, 0, rectVerts.length / 3); + curContext.disable(curContext.POLYGON_OFFSET_FILL) + } + }; + Drawing2D.prototype.ellipse = function(x, y, width, height) { + x = x || 0; + y = y || 0; + if (width <= 0 && height <= 0) return; + if (curEllipseMode === 2) { + width *= 2; + height *= 2 + } else if (curEllipseMode === 1) { + width = width - x; + height = height - y; + x += width / 2; + y += height / 2 + } else if (curEllipseMode === 0) { + x += width / 2; + y += height / 2 + } + if (width === height) { + curContext.beginPath(); + curContext.arc(x, y, width / 2, 0, 6.283185307179586, false); + executeContextFill(); + executeContextStroke() + } else { + var w = width / 2, + h = height / 2, + C = 0.5522847498307933, + c_x = C * w, + c_y = C * h; + p.beginShape(); + p.vertex(x + w, y); + p.bezierVertex(x + w, y - c_y, x + c_x, y - h, x, y - h); + p.bezierVertex(x - c_x, y - h, x - w, y - c_y, x - w, y); + p.bezierVertex(x - w, y + c_y, x - c_x, y + h, x, y + h); + p.bezierVertex(x + c_x, y + h, x + w, y + c_y, x + w, y); + p.endShape() + } + }; + Drawing3D.prototype.ellipse = function(x, y, width, height) { + x = x || 0; + y = y || 0; + if (width <= 0 && height <= 0) return; + if (curEllipseMode === 2) { + width *= 2; + height *= 2 + } else if (curEllipseMode === 1) { + width = width - x; + height = height - y; + x += width / 2; + y += height / 2 + } else if (curEllipseMode === 0) { + x += width / 2; + y += height / 2 + } + var w = width / 2, + h = height / 2, + C = 0.5522847498307933, + c_x = C * w, + c_y = C * h; + p.beginShape(); + p.vertex(x + w, y); + p.bezierVertex(x + w, y - c_y, 0, x + c_x, y - h, 0, x, y - h, 0); + p.bezierVertex(x - c_x, y - h, 0, x - w, y - c_y, 0, x - w, y, 0); + p.bezierVertex(x - w, y + c_y, 0, x - c_x, y + h, 0, x, y + h, 0); + p.bezierVertex(x + c_x, y + h, 0, x + w, y + c_y, 0, x + w, y, 0); + p.endShape(); + if (doFill) { + var xAv = 0, + yAv = 0, + i, j; + for (i = 0; i < vertArray.length; i++) { + xAv += vertArray[i][0]; + yAv += vertArray[i][1] + } + xAv /= vertArray.length; + yAv /= vertArray.length; + var vert = [], + fillVertArray = [], + colorVertArray = []; + vert[0] = xAv; + vert[1] = yAv; + vert[2] = 0; + vert[3] = 0; + vert[4] = 0; + vert[5] = fillStyle[0]; + vert[6] = fillStyle[1]; + vert[7] = fillStyle[2]; + vert[8] = fillStyle[3]; + vert[9] = strokeStyle[0]; + vert[10] = strokeStyle[1]; + vert[11] = strokeStyle[2]; + vert[12] = strokeStyle[3]; + vert[13] = normalX; + vert[14] = normalY; + vert[15] = normalZ; + vertArray.unshift(vert); + for (i = 0; i < vertArray.length; i++) { + for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i][j]); + for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i][j]) + } + fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray) + } + }; + p.normal = function(nx, ny, nz) { + if (arguments.length !== 3 || !(typeof nx === "number" && typeof ny === "number" && typeof nz === "number")) throw "normal() requires three numeric arguments."; + normalX = nx; + normalY = ny; + normalZ = nz; + if (curShape !== 0) if (normalMode === 0) normalMode = 1; + else if (normalMode === 1) normalMode = 2 + }; + p.save = function(file, img) { + if (img !== undef) return window.open(img.toDataURL(), "_blank"); + return window.open(p.externals.canvas.toDataURL(), "_blank") + }; + var saveNumber = 0; + p.saveFrame = function(file) { + if (file === undef) file = "screen-####.png"; + var frameFilename = file.replace(/#+/, function(all) { + var s = "" + saveNumber++; + while (s.length < all.length) s = "0" + s; + return s + }); + p.save(frameFilename) + }; + var utilityContext2d = document.createElement("canvas").getContext("2d"); + var canvasDataCache = [undef, undef, undef]; + + function getCanvasData(obj, w, h) { + var canvasData = canvasDataCache.shift(); + if (canvasData === undef) { + canvasData = {}; + canvasData.canvas = document.createElement("canvas"); + canvasData.context = canvasData.canvas.getContext("2d") + } + canvasDataCache.push(canvasData); + var canvas = canvasData.canvas, + context = canvasData.context, + width = w || obj.width, + height = h || obj.height; + canvas.width = width; + canvas.height = height; + if (!obj) context.clearRect(0, 0, width, height); + else if ("data" in obj) context.putImageData(obj, 0, 0); + else { + context.clearRect(0, 0, width, height); + context.drawImage(obj, 0, 0, width, height) + } + return canvasData + } + function buildPixelsObject(pImage) { + return { + getLength: function(aImg) { + return function() { + if (aImg.isRemote) throw "Image is loaded remotely. Cannot get length."; + else return aImg.imageData.data.length ? aImg.imageData.data.length / 4 : 0 + } + }(pImage), + getPixel: function(aImg) { + return function(i) { + var offset = i * 4, + data = aImg.imageData.data; + if (aImg.isRemote) throw "Image is loaded remotely. Cannot get pixels."; + return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255 + } + }(pImage), + setPixel: function(aImg) { + return function(i, c) { + var offset = i * 4, + data = aImg.imageData.data; + if (aImg.isRemote) throw "Image is loaded remotely. Cannot set pixel."; + data[offset + 0] = (c >> 16) & 255; + data[offset + 1] = (c >> 8) & 255; + data[offset + 2] = c & 255; + data[offset + 3] = (c >> 24) & 255; + aImg.__isDirty = true + } + }(pImage), + toArray: function(aImg) { + return function() { + var arr = [], + data = aImg.imageData.data, + length = aImg.width * aImg.height; + if (aImg.isRemote) throw "Image is loaded remotely. Cannot get pixels."; + for (var i = 0, offset = 0; i < length; i++, offset += 4) arr.push((data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255); + return arr + } + }(pImage), + set: function(aImg) { + return function(arr) { + var offset, data, c; + if (this.isRemote) throw "Image is loaded remotely. Cannot set pixels."; + data = aImg.imageData.data; + for (var i = 0, aL = arr.length; i < aL; i++) { + c = arr[i]; + offset = i * 4; + data[offset + 0] = (c >> 16) & 255; + data[offset + 1] = (c >> 8) & 255; + data[offset + 2] = c & 255; + data[offset + 3] = (c >> 24) & 255 + } + aImg.__isDirty = true + } + }(pImage) + } + } + var PImage = function(aWidth, aHeight, aFormat) { + this.__isDirty = false; + if (aWidth instanceof HTMLImageElement) this.fromHTMLImageData(aWidth); + else if (aHeight || aFormat) { + this.width = aWidth || 1; + this.height = aHeight || 1; + var canvas = this.sourceImg = document.createElement("canvas"); + canvas.width = this.width; + canvas.height = this.height; + var imageData = this.imageData = canvas.getContext("2d").createImageData(this.width, this.height); + this.format = aFormat === 2 || aFormat === 4 ? aFormat : 1; + if (this.format === 1) for (var i = 3, data = this.imageData.data, len = data.length; i < len; i += 4) data[i] = 255; + this.__isDirty = true; + this.updatePixels() + } else { + this.width = 0; + this.height = 0; + this.imageData = utilityContext2d.createImageData(1, 1); + this.format = 2 + } + this.pixels = buildPixelsObject(this) + }; + PImage.prototype = { + __isPImage: true, + updatePixels: function() { + var canvas = this.sourceImg; + if (canvas && canvas instanceof HTMLCanvasElement && this.__isDirty) canvas.getContext("2d").putImageData(this.imageData, 0, 0); + this.__isDirty = false + }, + fromHTMLImageData: function(htmlImg) { + var canvasData = getCanvasData(htmlImg); + try { + var imageData = canvasData.context.getImageData(0, 0, htmlImg.width, htmlImg.height); + this.fromImageData(imageData) + } catch(e) { + if (htmlImg.width && htmlImg.height) { + this.isRemote = true; + this.width = htmlImg.width; + this.height = htmlImg.height + } + } + this.sourceImg = htmlImg + }, + "get": function(x, y, w, h) { + if (!arguments.length) return p.get(this); + if (arguments.length === 2) return p.get(x, y, this); + if (arguments.length === 4) return p.get(x, y, w, h, this) + }, + "set": function(x, y, c) { + p.set(x, y, c, this); + this.__isDirty = true + }, + blend: function(srcImg, x, y, width, height, dx, dy, dwidth, dheight, MODE) { + if (arguments.length === 9) p.blend(this, srcImg, x, y, width, height, dx, dy, dwidth, dheight, this); + else if (arguments.length === 10) p.blend(srcImg, x, y, width, height, dx, dy, dwidth, dheight, MODE, this); + delete this.sourceImg + }, + copy: function(srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, dheight) { + if (arguments.length === 8) p.blend(this, srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, 0, this); + else if (arguments.length === 9) p.blend(srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, dheight, 0, this); + delete this.sourceImg + }, + filter: function(mode, param) { + if (arguments.length === 2) p.filter(mode, param, this); + else if (arguments.length === 1) p.filter(mode, null, this); + delete this.sourceImg + }, + save: function(file) { + p.save(file, this) + }, + resize: function(w, h) { + if (this.isRemote) throw "Image is loaded remotely. Cannot resize."; + if (this.width !== 0 || this.height !== 0) { + if (w === 0 && h !== 0) w = Math.floor(this.width / this.height * h); + else if (h === 0 && w !== 0) h = Math.floor(this.height / this.width * w); + var canvas = getCanvasData(this.imageData).canvas; + var imageData = getCanvasData(canvas, w, h).context.getImageData(0, 0, w, h); + this.fromImageData(imageData) + } + }, + mask: function(mask) { + var obj = this.toImageData(), + i, size; + if (mask instanceof PImage || mask.__isPImage) if (mask.width === this.width && mask.height === this.height) { + mask = mask.toImageData(); + for (i = 2, size = this.width * this.height * 4; i < size; i += 4) obj.data[i + 1] = mask.data[i] + } else throw "mask must have the same dimensions as PImage."; + else if (mask instanceof + Array) if (this.width * this.height === mask.length) for (i = 0, size = mask.length; i < size; ++i) obj.data[i * 4 + 3] = mask[i]; + else throw "mask array must be the same length as PImage pixels array."; + this.fromImageData(obj) + }, + loadPixels: nop, + toImageData: function() { + if (this.isRemote) return this.sourceImg; + if (!this.__isDirty) return this.imageData; + var canvasData = getCanvasData(this.sourceImg); + return canvasData.context.getImageData(0, 0, this.width, this.height) + }, + toDataURL: function() { + if (this.isRemote) throw "Image is loaded remotely. Cannot create dataURI."; + var canvasData = getCanvasData(this.imageData); + return canvasData.canvas.toDataURL() + }, + fromImageData: function(canvasImg) { + var w = canvasImg.width, + h = canvasImg.height, + canvas = document.createElement("canvas"), + ctx = canvas.getContext("2d"); + this.width = canvas.width = w; + this.height = canvas.height = h; + ctx.putImageData(canvasImg, 0, 0); + this.format = 2; + this.imageData = canvasImg; + this.sourceImg = canvas + } + }; + p.PImage = PImage; + p.createImage = function(w, h, mode) { + return new PImage(w, h, mode) + }; + p.loadImage = function(file, type, callback) { + if (type) file = file + "." + type; + var pimg; + if (curSketch.imageCache.images[file]) { + pimg = new PImage(curSketch.imageCache.images[file]); + pimg.loaded = true; + return pimg + } + pimg = new PImage; + var img = document.createElement("img"); + pimg.sourceImg = img; + img.onload = function(aImage, aPImage, aCallback) { + var image = aImage; + var pimg = aPImage; + var callback = aCallback; + return function() { + pimg.fromHTMLImageData(image); + pimg.loaded = true; + if (callback) callback() + } + }(img, pimg, callback); + img.src = file; + return pimg + }; + p.requestImage = p.loadImage; + + function get$2(x, y) { + var data; + if (x >= p.width || x < 0 || y < 0 || y >= p.height) return 0; + if (isContextReplaced) { + var offset = ((0 | x) + p.width * (0 | y)) * 4; + data = p.imageData.data; + return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255 + } + data = p.toImageData(0 | x, 0 | y, 1, 1).data; + return (data[3] & 255) << 24 | (data[0] & 255) << 16 | (data[1] & 255) << 8 | data[2] & 255 + } + function get$3(x, y, img) { + if (img.isRemote) throw "Image is loaded remotely. Cannot get x,y."; + var offset = y * img.width * 4 + x * 4, + data = img.imageData.data; + return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255 + } + function get$4(x, y, w, h) { + var c = new PImage(w, h, 2); + c.fromImageData(p.toImageData(x, y, w, h)); + return c + } + function get$5(x, y, w, h, img) { + if (img.isRemote) throw "Image is loaded remotely. Cannot get x,y,w,h."; + var c = new PImage(w, h, 2), + cData = c.imageData.data, + imgWidth = img.width, + imgHeight = img.height, + imgData = img.imageData.data; + var startRow = Math.max(0, -y), + startColumn = Math.max(0, -x), + stopRow = Math.min(h, imgHeight - y), + stopColumn = Math.min(w, imgWidth - x); + for (var i = startRow; i < stopRow; ++i) { + var sourceOffset = ((y + i) * imgWidth + (x + startColumn)) * 4; + var targetOffset = (i * w + startColumn) * 4; + for (var j = startColumn; j < stopColumn; ++j) { + cData[targetOffset++] = imgData[sourceOffset++]; + cData[targetOffset++] = imgData[sourceOffset++]; + cData[targetOffset++] = imgData[sourceOffset++]; + cData[targetOffset++] = imgData[sourceOffset++] + } + } + c.__isDirty = true; + return c + } + p.get = function(x, y, w, h, img) { + if (img !== undefined) return get$5(x, y, w, h, img); + if (h !== undefined) return get$4(x, y, w, h); + if (w !== undefined) return get$3(x, y, w); + if (y !== undefined) return get$2(x, y); + if (x !== undefined) return get$5(0, 0, x.width, x.height, x); + return get$4(0, 0, p.width, p.height) + }; + p.createGraphics = function(w, h, render) { + var pg = new Processing; + pg.size(w, h, render); + pg.background(0, 0); + return pg + }; + + function resetContext() { + if (isContextReplaced) { + curContext = originalContext; + isContextReplaced = false; + p.updatePixels() + } + } + + function SetPixelContextWrapper() { + function wrapFunction(newContext, name) { + function wrapper() { + resetContext(); + curContext[name].apply(curContext, arguments) + } + newContext[name] = wrapper + } + function wrapProperty(newContext, name) { + function getter() { + resetContext(); + return curContext[name] + } + function setter(value) { + resetContext(); + curContext[name] = value + } + p.defineProperty(newContext, name, { + get: getter, + set: setter + }) + } + for (var n in curContext) if (typeof curContext[n] === "function") wrapFunction(this, n); + else wrapProperty(this, n) + } + function replaceContext() { + if (isContextReplaced) return; + p.loadPixels(); + if (proxyContext === null) { + originalContext = curContext; + proxyContext = new SetPixelContextWrapper + } + isContextReplaced = true; + curContext = proxyContext; + setPixelsCached = 0 + } + function set$3(x, y, c) { + if (x < p.width && x >= 0 && y >= 0 && y < p.height) { + replaceContext(); + p.pixels.setPixel((0 | x) + p.width * (0 | y), c); + if (++setPixelsCached > maxPixelsCached) resetContext() + } + } + function set$4(x, y, obj, img) { + if (img.isRemote) throw "Image is loaded remotely. Cannot set x,y."; + var c = p.color.toArray(obj); + var offset = y * img.width * 4 + x * 4; + var data = img.imageData.data; + data[offset] = c[0]; + data[offset + 1] = c[1]; + data[offset + 2] = c[2]; + data[offset + 3] = c[3] + } + p.set = function(x, y, obj, img) { + var color, oldFill; + if (arguments.length === 3) if (typeof obj === "number") set$3(x, y, obj); + else { + if (obj instanceof PImage || obj.__isPImage) p.image(obj, x, y) + } else if (arguments.length === 4) set$4(x, y, obj, img) + }; + p.imageData = {}; + p.pixels = { + getLength: function() { + return p.imageData.data.length ? p.imageData.data.length / 4 : 0 + }, + getPixel: function(i) { + var offset = i * 4, + data = p.imageData.data; + return data[offset + 3] << 24 & 4278190080 | data[offset + 0] << 16 & 16711680 | data[offset + 1] << 8 & 65280 | data[offset + 2] & 255 + }, + setPixel: function(i, c) { + var offset = i * 4, + data = p.imageData.data; + data[offset + 0] = (c & 16711680) >>> 16; + data[offset + 1] = (c & 65280) >>> 8; + data[offset + 2] = c & 255; + data[offset + 3] = (c & 4278190080) >>> 24 + }, + toArray: function() { + var arr = [], + length = p.imageData.width * p.imageData.height, + data = p.imageData.data; + for (var i = 0, offset = 0; i < length; i++, offset += 4) arr.push(data[offset + 3] << 24 & 4278190080 | data[offset + 0] << 16 & 16711680 | data[offset + 1] << 8 & 65280 | data[offset + 2] & 255); + return arr + }, + set: function(arr) { + for (var i = 0, aL = arr.length; i < aL; i++) this.setPixel(i, arr[i]) + } + }; + p.loadPixels = function() { + p.imageData = drawing.$ensureContext().getImageData(0, 0, p.width, p.height) + }; + p.updatePixels = function() { + if (p.imageData) drawing.$ensureContext().putImageData(p.imageData, 0, 0) + }; + p.hint = function(which) { + var curContext = drawing.$ensureContext(); + if (which === 4) { + curContext.disable(curContext.DEPTH_TEST); + curContext.depthMask(false); + curContext.clear(curContext.DEPTH_BUFFER_BIT) + } else if (which === -4) { + curContext.enable(curContext.DEPTH_TEST); + curContext.depthMask(true) + } else if (which === -1 || which === 2) renderSmooth = true; + else if (which === 1) renderSmooth = false + }; + var backgroundHelper = function(arg1, arg2, arg3, arg4) { + var obj; + if (arg1 instanceof PImage || arg1.__isPImage) { + obj = arg1; + if (!obj.loaded) throw "Error using image in background(): PImage not loaded."; + if (obj.width !== p.width || obj.height !== p.height) throw "Background image must be the same dimensions as the canvas."; + } else obj = p.color(arg1, arg2, arg3, arg4); + backgroundObj = obj + }; + Drawing2D.prototype.background = function(arg1, arg2, arg3, arg4) { + if (arg1 !== undef) backgroundHelper(arg1, arg2, arg3, arg4); + if (backgroundObj instanceof PImage || backgroundObj.__isPImage) { + saveContext(); + curContext.setTransform(1, 0, 0, 1, 0, 0); + p.image(backgroundObj, 0, 0); + restoreContext() + } else { + saveContext(); + curContext.setTransform(1, 0, 0, 1, 0, 0); + if (p.alpha(backgroundObj) !== colorModeA) curContext.clearRect(0, 0, p.width, p.height); + curContext.fillStyle = p.color.toString(backgroundObj); + curContext.fillRect(0, 0, p.width, p.height); + isFillDirty = true; + restoreContext() + } + }; + Drawing3D.prototype.background = function(arg1, arg2, arg3, arg4) { + if (arguments.length > 0) backgroundHelper(arg1, arg2, arg3, arg4); + var c = p.color.toGLArray(backgroundObj); + curContext.clearColor(c[0], c[1], c[2], c[3]); + curContext.clear(curContext.COLOR_BUFFER_BIT | curContext.DEPTH_BUFFER_BIT) + }; + Drawing2D.prototype.image = function(img, x, y, w, h) { + x = Math.round(x); + y = Math.round(y); + if (img.width > 0) { + var wid = w || img.width; + var hgt = h || img.height; + var bounds = imageModeConvert(x || 0, y || 0, w || img.width, h || img.height, arguments.length < 4); + var fastImage = !!img.sourceImg && curTint === null; + if (fastImage) { + var htmlElement = img.sourceImg; + if (img.__isDirty) img.updatePixels(); + curContext.drawImage(htmlElement, 0, 0, htmlElement.width, htmlElement.height, bounds.x, bounds.y, bounds.w, bounds.h) + } else { + var obj = img.toImageData(); + if (curTint !== null) { + curTint(obj); + img.__isDirty = true + } + curContext.drawImage(getCanvasData(obj).canvas, 0, 0, img.width, img.height, bounds.x, bounds.y, bounds.w, bounds.h) + } + } + }; + Drawing3D.prototype.image = function(img, x, y, w, h) { + if (img.width > 0) { + x = Math.round(x); + y = Math.round(y); + w = w || img.width; + h = h || img.height; + p.beginShape(p.QUADS); + p.texture(img); + p.vertex(x, y, 0, 0, 0); + p.vertex(x, y + h, 0, 0, h); + p.vertex(x + w, y + h, 0, w, h); + p.vertex(x + w, y, 0, w, 0); + p.endShape() + } + }; + p.tint = function(a1, a2, a3, a4) { + var tintColor = p.color(a1, a2, a3, a4); + var r = p.red(tintColor) / colorModeX; + var g = p.green(tintColor) / colorModeY; + var b = p.blue(tintColor) / colorModeZ; + var a = p.alpha(tintColor) / colorModeA; + curTint = function(obj) { + var data = obj.data, + length = 4 * obj.width * obj.height; + for (var i = 0; i < length;) { + data[i++] *= r; + data[i++] *= g; + data[i++] *= b; + data[i++] *= a + } + }; + curTint3d = function(data) { + for (var i = 0; i < data.length;) { + data[i++] = r; + data[i++] = g; + data[i++] = b; + data[i++] = a + } + } + }; + p.noTint = function() { + curTint = null; + curTint3d = null + }; + p.copy = function(src, sx, sy, sw, sh, dx, dy, dw, dh) { + if (dh === undef) { + dh = dw; + dw = dy; + dy = dx; + dx = sh; + sh = sw; + sw = sy; + sy = sx; + sx = src; + src = p + } + p.blend(src, sx, sy, sw, sh, dx, dy, dw, dh, 0) + }; + p.blend = function(src, sx, sy, sw, sh, dx, dy, dw, dh, mode, pimgdest) { + if (src.isRemote) throw "Image is loaded remotely. Cannot blend image."; + if (mode === undef) { + mode = dh; + dh = dw; + dw = dy; + dy = dx; + dx = sh; + sh = sw; + sw = sy; + sy = sx; + sx = src; + src = p + } + var sx2 = sx + sw, + sy2 = sy + sh, + dx2 = dx + dw, + dy2 = dy + dh, + dest = pimgdest || p; + if (pimgdest === undef || mode === undef) p.loadPixels(); + src.loadPixels(); + if (src === p && p.intersect(sx, sy, sx2, sy2, dx, dy, dx2, dy2)) p.blit_resize(p.get(sx, sy, sx2 - sx, sy2 - sy), 0, 0, sx2 - sx - 1, sy2 - sy - 1, dest.imageData.data, dest.width, dest.height, dx, dy, dx2, dy2, mode); + else p.blit_resize(src, sx, sy, sx2, sy2, dest.imageData.data, dest.width, dest.height, dx, dy, dx2, dy2, mode); + if (pimgdest === undef) p.updatePixels() + }; + var buildBlurKernel = function(r) { + var radius = p.floor(r * 3.5), + i, radiusi; + radius = radius < 1 ? 1 : radius < 248 ? radius : 248; + if (p.shared.blurRadius !== radius) { + p.shared.blurRadius = radius; + p.shared.blurKernelSize = 1 + (p.shared.blurRadius << 1); + p.shared.blurKernel = new Float32Array(p.shared.blurKernelSize); + var sharedBlurKernal = p.shared.blurKernel; + var sharedBlurKernelSize = p.shared.blurKernelSize; + var sharedBlurRadius = p.shared.blurRadius; + for (i = 0; i < sharedBlurKernelSize; i++) sharedBlurKernal[i] = 0; + var radiusiSquared = (radius - 1) * (radius - 1); + for (i = 1; i < radius; i++) sharedBlurKernal[radius + i] = sharedBlurKernal[radiusi] = radiusiSquared; + sharedBlurKernal[radius] = radius * radius + } + }; + var blurARGB = function(r, aImg) { + var sum, cr, cg, cb, ca, c, m; + var read, ri, ym, ymi, bk0; + var wh = aImg.pixels.getLength(); + var r2 = new Float32Array(wh); + var g2 = new Float32Array(wh); + var b2 = new Float32Array(wh); + var a2 = new Float32Array(wh); + var yi = 0; + var x, y, i, offset; + buildBlurKernel(r); + var aImgHeight = aImg.height; + var aImgWidth = aImg.width; + var sharedBlurKernelSize = p.shared.blurKernelSize; + var sharedBlurRadius = p.shared.blurRadius; + var sharedBlurKernal = p.shared.blurKernel; + var pix = aImg.imageData.data; + for (y = 0; y < aImgHeight; y++) { + for (x = 0; x < aImgWidth; x++) { + cb = cg = cr = ca = sum = 0; + read = x - sharedBlurRadius; + if (read < 0) { + bk0 = -read; + read = 0 + } else { + if (read >= aImgWidth) break; + bk0 = 0 + } + for (i = bk0; i < sharedBlurKernelSize; i++) { + if (read >= aImgWidth) break; + offset = (read + yi) * 4; + m = sharedBlurKernal[i]; + ca += m * pix[offset + 3]; + cr += m * pix[offset]; + cg += m * pix[offset + 1]; + cb += m * pix[offset + 2]; + sum += m; + read++ + } + ri = yi + x; + a2[ri] = ca / sum; + r2[ri] = cr / sum; + g2[ri] = cg / sum; + b2[ri] = cb / sum + } + yi += aImgWidth + } + yi = 0; + ym = -sharedBlurRadius; + ymi = ym * aImgWidth; + for (y = 0; y < aImgHeight; y++) { + for (x = 0; x < aImgWidth; x++) { + cb = cg = cr = ca = sum = 0; + if (ym < 0) { + bk0 = ri = -ym; + read = x + } else { + if (ym >= aImgHeight) break; + bk0 = 0; + ri = ym; + read = x + ymi + } + for (i = bk0; i < sharedBlurKernelSize; i++) { + if (ri >= aImgHeight) break; + m = sharedBlurKernal[i]; + ca += m * a2[read]; + cr += m * r2[read]; + cg += m * g2[read]; + cb += m * b2[read]; + sum += m; + ri++; + read += aImgWidth + } + offset = (x + yi) * 4; + pix[offset] = cr / sum; + pix[offset + 1] = cg / sum; + pix[offset + 2] = cb / sum; + pix[offset + 3] = ca / sum + } + yi += aImgWidth; + ymi += aImgWidth; + ym++ + } + }; + var dilate = function(isInverted, aImg) { + var currIdx = 0; + var maxIdx = aImg.pixels.getLength(); + var out = new Int32Array(maxIdx); + var currRowIdx, maxRowIdx, colOrig, colOut, currLum; + var idxRight, idxLeft, idxUp, idxDown, colRight, colLeft, colUp, colDown, lumRight, lumLeft, lumUp, lumDown; + if (!isInverted) while (currIdx < maxIdx) { + currRowIdx = currIdx; + maxRowIdx = currIdx + aImg.width; + while (currIdx < maxRowIdx) { + colOrig = colOut = aImg.pixels.getPixel(currIdx); + idxLeft = currIdx - 1; + idxRight = currIdx + 1; + idxUp = currIdx - aImg.width; + idxDown = currIdx + aImg.width; + if (idxLeft < currRowIdx) idxLeft = currIdx; + if (idxRight >= maxRowIdx) idxRight = currIdx; + if (idxUp < 0) idxUp = 0; + if (idxDown >= maxIdx) idxDown = currIdx; + colUp = aImg.pixels.getPixel(idxUp); + colLeft = aImg.pixels.getPixel(idxLeft); + colDown = aImg.pixels.getPixel(idxDown); + colRight = aImg.pixels.getPixel(idxRight); + currLum = 77 * (colOrig >> 16 & 255) + 151 * (colOrig >> 8 & 255) + 28 * (colOrig & 255); + lumLeft = 77 * (colLeft >> 16 & 255) + 151 * (colLeft >> 8 & 255) + 28 * (colLeft & 255); + lumRight = 77 * (colRight >> 16 & 255) + 151 * (colRight >> 8 & 255) + 28 * (colRight & 255); + lumUp = 77 * (colUp >> 16 & 255) + 151 * (colUp >> 8 & 255) + 28 * (colUp & 255); + lumDown = 77 * (colDown >> 16 & 255) + 151 * (colDown >> 8 & 255) + 28 * (colDown & 255); + if (lumLeft > currLum) { + colOut = colLeft; + currLum = lumLeft + } + if (lumRight > currLum) { + colOut = colRight; + currLum = lumRight + } + if (lumUp > currLum) { + colOut = colUp; + currLum = lumUp + } + if (lumDown > currLum) { + colOut = colDown; + currLum = lumDown + } + out[currIdx++] = colOut + } + } else while (currIdx < maxIdx) { + currRowIdx = currIdx; + maxRowIdx = currIdx + aImg.width; + while (currIdx < maxRowIdx) { + colOrig = colOut = aImg.pixels.getPixel(currIdx); + idxLeft = currIdx - 1; + idxRight = currIdx + 1; + idxUp = currIdx - aImg.width; + idxDown = currIdx + aImg.width; + if (idxLeft < currRowIdx) idxLeft = currIdx; + if (idxRight >= maxRowIdx) idxRight = currIdx; + if (idxUp < 0) idxUp = 0; + if (idxDown >= maxIdx) idxDown = currIdx; + colUp = aImg.pixels.getPixel(idxUp); + colLeft = aImg.pixels.getPixel(idxLeft); + colDown = aImg.pixels.getPixel(idxDown); + colRight = aImg.pixels.getPixel(idxRight); + currLum = 77 * (colOrig >> 16 & 255) + 151 * (colOrig >> 8 & 255) + 28 * (colOrig & 255); + lumLeft = 77 * (colLeft >> 16 & 255) + 151 * (colLeft >> 8 & 255) + 28 * (colLeft & 255); + lumRight = 77 * (colRight >> 16 & 255) + 151 * (colRight >> 8 & 255) + 28 * (colRight & 255); + lumUp = 77 * (colUp >> 16 & 255) + 151 * (colUp >> 8 & 255) + 28 * (colUp & 255); + lumDown = 77 * (colDown >> 16 & 255) + 151 * (colDown >> 8 & 255) + 28 * (colDown & 255); + if (lumLeft < currLum) { + colOut = colLeft; + currLum = lumLeft + } + if (lumRight < currLum) { + colOut = colRight; + currLum = lumRight + } + if (lumUp < currLum) { + colOut = colUp; + currLum = lumUp + } + if (lumDown < currLum) { + colOut = colDown; + currLum = lumDown + } + out[currIdx++] = colOut + } + } + aImg.pixels.set(out) + }; + p.filter = function(kind, param, aImg) { + var img, col, lum, i; + if (arguments.length === 3) { + aImg.loadPixels(); + img = aImg + } else { + p.loadPixels(); + img = p + } + if (param === undef) param = null; + if (img.isRemote) throw "Image is loaded remotely. Cannot filter image."; + var imglen = img.pixels.getLength(); + switch (kind) { + case 11: + var radius = param || 1; + blurARGB(radius, img); + break; + case 12: + if (img.format === 4) { + for (i = 0; i < imglen; i++) { + col = 255 - img.pixels.getPixel(i); + img.pixels.setPixel(i, 4278190080 | col << 16 | col << 8 | col) + } + img.format = 1 + } else for (i = 0; i < imglen; i++) { + col = img.pixels.getPixel(i); + lum = 77 * (col >> 16 & 255) + 151 * (col >> 8 & 255) + 28 * (col & 255) >> 8; + img.pixels.setPixel(i, col & 4278190080 | lum << 16 | lum << 8 | lum) + } + break; + case 13: + for (i = 0; i < imglen; i++) img.pixels.setPixel(i, img.pixels.getPixel(i) ^ 16777215); + break; + case 15: + if (param === null) throw "Use filter(POSTERIZE, int levels) instead of filter(POSTERIZE)"; + var levels = p.floor(param); + if (levels < 2 || levels > 255) throw "Levels must be between 2 and 255 for filter(POSTERIZE, levels)"; + var levels1 = levels - 1; + for (i = 0; i < imglen; i++) { + var rlevel = img.pixels.getPixel(i) >> 16 & 255; + var glevel = img.pixels.getPixel(i) >> 8 & 255; + var blevel = img.pixels.getPixel(i) & 255; + rlevel = (rlevel * levels >> 8) * 255 / levels1; + glevel = (glevel * levels >> 8) * 255 / levels1; + blevel = (blevel * levels >> 8) * 255 / levels1; + img.pixels.setPixel(i, 4278190080 & img.pixels.getPixel(i) | rlevel << 16 | glevel << 8 | blevel) + } + break; + case 14: + for (i = 0; i < imglen; i++) img.pixels.setPixel(i, img.pixels.getPixel(i) | 4278190080); + img.format = 1; + break; + case 16: + if (param === null) param = 0.5; + if (param < 0 || param > 1) throw "Level must be between 0 and 1 for filter(THRESHOLD, level)"; + var thresh = p.floor(param * 255); + for (i = 0; i < imglen; i++) { + var max = p.max((img.pixels.getPixel(i) & 16711680) >> 16, p.max((img.pixels.getPixel(i) & 65280) >> 8, img.pixels.getPixel(i) & 255)); + img.pixels.setPixel(i, img.pixels.getPixel(i) & 4278190080 | (max < thresh ? 0 : 16777215)) + } + break; + case 17: + dilate(true, img); + break; + case 18: + dilate(false, img); + break + } + img.updatePixels() + }; + p.shared = { + fracU: 0, + ifU: 0, + fracV: 0, + ifV: 0, + u1: 0, + u2: 0, + v1: 0, + v2: 0, + sX: 0, + sY: 0, + iw: 0, + iw1: 0, + ih1: 0, + ul: 0, + ll: 0, + ur: 0, + lr: 0, + cUL: 0, + cLL: 0, + cUR: 0, + cLR: 0, + srcXOffset: 0, + srcYOffset: 0, + r: 0, + g: 0, + b: 0, + a: 0, + srcBuffer: null, + blurRadius: 0, + blurKernelSize: 0, + blurKernel: null + }; + p.intersect = function(sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2) { + var sw = sx2 - sx1 + 1; + var sh = sy2 - sy1 + 1; + var dw = dx2 - dx1 + 1; + var dh = dy2 - dy1 + 1; + if (dx1 < sx1) { + dw += dx1 - sx1; + if (dw > sw) dw = sw + } else { + var w = sw + sx1 - dx1; + if (dw > w) dw = w + } + if (dy1 < sy1) { + dh += dy1 - sy1; + if (dh > sh) dh = sh + } else { + var h = sh + sy1 - dy1; + if (dh > h) dh = h + } + return ! (dw <= 0 || dh <= 0) + }; + var blendFuncs = {}; + blendFuncs[1] = p.modes.blend; + blendFuncs[2] = p.modes.add; + blendFuncs[4] = p.modes.subtract; + blendFuncs[8] = p.modes.lightest; + blendFuncs[16] = p.modes.darkest; + blendFuncs[0] = p.modes.replace; + blendFuncs[32] = p.modes.difference; + blendFuncs[64] = p.modes.exclusion; + blendFuncs[128] = p.modes.multiply; + blendFuncs[256] = p.modes.screen; + blendFuncs[512] = p.modes.overlay; + blendFuncs[1024] = p.modes.hard_light; + blendFuncs[2048] = p.modes.soft_light; + blendFuncs[4096] = p.modes.dodge; + blendFuncs[8192] = p.modes.burn; + p.blit_resize = function(img, srcX1, srcY1, srcX2, srcY2, destPixels, screenW, screenH, destX1, destY1, destX2, destY2, mode) { + var x, y; + if (srcX1 < 0) srcX1 = 0; + if (srcY1 < 0) srcY1 = 0; + if (srcX2 >= img.width) srcX2 = img.width - 1; + if (srcY2 >= img.height) srcY2 = img.height - 1; + var srcW = srcX2 - srcX1; + var srcH = srcY2 - srcY1; + var destW = destX2 - destX1; + var destH = destY2 - destY1; + if (destW <= 0 || destH <= 0 || srcW <= 0 || srcH <= 0 || destX1 >= screenW || destY1 >= screenH || srcX1 >= img.width || srcY1 >= img.height) return; + var dx = Math.floor(srcW / destW * 32768); + var dy = Math.floor(srcH / destH * 32768); + var pshared = p.shared; + pshared.srcXOffset = Math.floor(destX1 < 0 ? -destX1 * dx : srcX1 * 32768); + pshared.srcYOffset = Math.floor(destY1 < 0 ? -destY1 * dy : srcY1 * 32768); + if (destX1 < 0) { + destW += destX1; + destX1 = 0 + } + if (destY1 < 0) { + destH += destY1; + destY1 = 0 + } + destW = Math.min(destW, screenW - destX1); + destH = Math.min(destH, screenH - destY1); + var destOffset = destY1 * screenW + destX1; + var destColor; + pshared.srcBuffer = img.imageData.data; + pshared.iw = img.width; + pshared.iw1 = img.width - 1; + pshared.ih1 = img.height - 1; + var filterBilinear = p.filter_bilinear, + filterNewScanline = p.filter_new_scanline, + blendFunc = blendFuncs[mode], + blendedColor, idx, cULoffset, cURoffset, cLLoffset, cLRoffset, ALPHA_MASK = 4278190080, + RED_MASK = 16711680, + GREEN_MASK = 65280, + BLUE_MASK = 255, + PREC_MAXVAL = 32767, + PRECISIONB = 15, + PREC_RED_SHIFT = 1, + PREC_ALPHA_SHIFT = 9, + srcBuffer = pshared.srcBuffer, + min = Math.min; + for (y = 0; y < destH; y++) { + pshared.sX = pshared.srcXOffset; + pshared.fracV = pshared.srcYOffset & PREC_MAXVAL; + pshared.ifV = PREC_MAXVAL - pshared.fracV; + pshared.v1 = (pshared.srcYOffset >> PRECISIONB) * pshared.iw; + pshared.v2 = min((pshared.srcYOffset >> PRECISIONB) + 1, pshared.ih1) * pshared.iw; + for (x = 0; x < destW; x++) { + idx = (destOffset + x) * 4; + destColor = destPixels[idx + 3] << 24 & ALPHA_MASK | destPixels[idx] << 16 & RED_MASK | destPixels[idx + 1] << 8 & GREEN_MASK | destPixels[idx + 2] & BLUE_MASK; + pshared.fracU = pshared.sX & PREC_MAXVAL; + pshared.ifU = PREC_MAXVAL - pshared.fracU; + pshared.ul = pshared.ifU * pshared.ifV >> PRECISIONB; + pshared.ll = pshared.ifU * pshared.fracV >> PRECISIONB; + pshared.ur = pshared.fracU * pshared.ifV >> PRECISIONB; + pshared.lr = pshared.fracU * pshared.fracV >> PRECISIONB; + pshared.u1 = pshared.sX >> PRECISIONB; + pshared.u2 = min(pshared.u1 + 1, pshared.iw1); + cULoffset = (pshared.v1 + pshared.u1) * 4; + cURoffset = (pshared.v1 + pshared.u2) * 4; + cLLoffset = (pshared.v2 + pshared.u1) * 4; + cLRoffset = (pshared.v2 + pshared.u2) * 4; + pshared.cUL = srcBuffer[cULoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cULoffset] << 16 & RED_MASK | srcBuffer[cULoffset + 1] << 8 & GREEN_MASK | srcBuffer[cULoffset + 2] & BLUE_MASK; + pshared.cUR = srcBuffer[cURoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cURoffset] << 16 & RED_MASK | srcBuffer[cURoffset + 1] << 8 & GREEN_MASK | srcBuffer[cURoffset + 2] & BLUE_MASK; + pshared.cLL = srcBuffer[cLLoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cLLoffset] << 16 & RED_MASK | srcBuffer[cLLoffset + 1] << 8 & GREEN_MASK | srcBuffer[cLLoffset + 2] & BLUE_MASK; + pshared.cLR = srcBuffer[cLRoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cLRoffset] << 16 & RED_MASK | srcBuffer[cLRoffset + 1] << 8 & GREEN_MASK | srcBuffer[cLRoffset + 2] & BLUE_MASK; + pshared.r = pshared.ul * ((pshared.cUL & RED_MASK) >> 16) + pshared.ll * ((pshared.cLL & RED_MASK) >> 16) + pshared.ur * ((pshared.cUR & RED_MASK) >> 16) + pshared.lr * ((pshared.cLR & RED_MASK) >> 16) << PREC_RED_SHIFT & RED_MASK; + pshared.g = pshared.ul * (pshared.cUL & GREEN_MASK) + pshared.ll * (pshared.cLL & GREEN_MASK) + pshared.ur * (pshared.cUR & GREEN_MASK) + pshared.lr * (pshared.cLR & GREEN_MASK) >>> PRECISIONB & GREEN_MASK; + pshared.b = pshared.ul * (pshared.cUL & BLUE_MASK) + pshared.ll * (pshared.cLL & BLUE_MASK) + pshared.ur * (pshared.cUR & BLUE_MASK) + pshared.lr * (pshared.cLR & BLUE_MASK) >>> PRECISIONB; + pshared.a = pshared.ul * ((pshared.cUL & ALPHA_MASK) >>> 24) + pshared.ll * ((pshared.cLL & ALPHA_MASK) >>> 24) + pshared.ur * ((pshared.cUR & ALPHA_MASK) >>> 24) + pshared.lr * ((pshared.cLR & ALPHA_MASK) >>> 24) << PREC_ALPHA_SHIFT & ALPHA_MASK; + blendedColor = blendFunc(destColor, pshared.a | pshared.r | pshared.g | pshared.b); + destPixels[idx] = (blendedColor & RED_MASK) >>> 16; + destPixels[idx + 1] = (blendedColor & GREEN_MASK) >>> 8; + destPixels[idx + 2] = blendedColor & BLUE_MASK; + destPixels[idx + 3] = (blendedColor & ALPHA_MASK) >>> 24; + pshared.sX += dx + } + destOffset += screenW; + pshared.srcYOffset += dy + } + }; + p.loadFont = function(name, size) { + if (name === undef) throw "font name required in loadFont."; + if (name.indexOf(".svg") === -1) { + if (size === undef) size = curTextFont.size; + return PFont.get(name, size) + } + var font = p.loadGlyphs(name); + return { + name: name, + css: "12px sans-serif", + glyph: true, + units_per_em: font.units_per_em, + horiz_adv_x: 1 / font.units_per_em * font.horiz_adv_x, + ascent: font.ascent, + descent: font.descent, + width: function(str) { + var width = 0; + var len = str.length; + for (var i = 0; i < len; i++) try { + width += parseFloat(p.glyphLook(p.glyphTable[name], str[i]).horiz_adv_x) + } catch(e) { + Processing.debug(e) + } + return width / p.glyphTable[name].units_per_em + } + } + }; + p.createFont = function(name, size) { + return p.loadFont(name, size) + }; + p.textFont = function(pfont, size) { + if (size !== undef) { + if (!pfont.glyph) pfont = PFont.get(pfont.name, size); + curTextSize = size + } + curTextFont = pfont; + curFontName = curTextFont.name; + curTextAscent = curTextFont.ascent; + curTextDescent = curTextFont.descent; + curTextLeading = curTextFont.leading; + var curContext = drawing.$ensureContext(); + curContext.font = curTextFont.css + }; + p.textSize = function(size) { + curTextFont = PFont.get(curFontName, size); + curTextSize = size; + curTextAscent = curTextFont.ascent; + curTextDescent = curTextFont.descent; + curTextLeading = curTextFont.leading; + var curContext = drawing.$ensureContext(); + curContext.font = curTextFont.css + }; + p.textAscent = function() { + return curTextAscent + }; + p.textDescent = function() { + return curTextDescent + }; + p.textLeading = function(leading) { + curTextLeading = leading + }; + p.textAlign = function(xalign, yalign) { + horizontalTextAlignment = xalign; + verticalTextAlignment = yalign || 0 + }; + + function toP5String(obj) { + if (obj instanceof String) return obj; + if (typeof obj === "number") { + if (obj === (0 | obj)) return obj.toString(); + return p.nf(obj, 0, 3) + } + if (obj === null || obj === undef) return ""; + return obj.toString() + } + Drawing2D.prototype.textWidth = function(str) { + var lines = toP5String(str).split(/\r?\n/g), + width = 0; + var i, linesCount = lines.length; + curContext.font = curTextFont.css; + for (i = 0; i < linesCount; ++i) width = Math.max(width, curTextFont.measureTextWidth(lines[i])); + return width | 0 + }; + Drawing3D.prototype.textWidth = function(str) { + var lines = toP5String(str).split(/\r?\n/g), + width = 0; + var i, linesCount = lines.length; + if (textcanvas === undef) textcanvas = document.createElement("canvas"); + var textContext = textcanvas.getContext("2d"); + textContext.font = curTextFont.css; + for (i = 0; i < linesCount; ++i) width = Math.max(width, textContext.measureText(lines[i]).width); + return width | 0 + }; + p.glyphLook = function(font, chr) { + try { + switch (chr) { + case "1": + return font.one; + case "2": + return font.two; + case "3": + return font.three; + case "4": + return font.four; + case "5": + return font.five; + case "6": + return font.six; + case "7": + return font.seven; + case "8": + return font.eight; + case "9": + return font.nine; + case "0": + return font.zero; + case " ": + return font.space; + case "$": + return font.dollar; + case "!": + return font.exclam; + case '"': + return font.quotedbl; + case "#": + return font.numbersign; + case "%": + return font.percent; + case "&": + return font.ampersand; + case "'": + return font.quotesingle; + case "(": + return font.parenleft; + case ")": + return font.parenright; + case "*": + return font.asterisk; + case "+": + return font.plus; + case ",": + return font.comma; + case "-": + return font.hyphen; + case ".": + return font.period; + case "/": + return font.slash; + case "_": + return font.underscore; + case ":": + return font.colon; + case ";": + return font.semicolon; + case "<": + return font.less; + case "=": + return font.equal; + case ">": + return font.greater; + case "?": + return font.question; + case "@": + return font.at; + case "[": + return font.bracketleft; + case "\\": + return font.backslash; + case "]": + return font.bracketright; + case "^": + return font.asciicircum; + case "`": + return font.grave; + case "{": + return font.braceleft; + case "|": + return font.bar; + case "}": + return font.braceright; + case "~": + return font.asciitilde; + default: + return font[chr] + } + } catch(e) { + Processing.debug(e) + } + }; + Drawing2D.prototype.text$line = function(str, x, y, z, align) { + var textWidth = 0, + xOffset = 0; + if (!curTextFont.glyph) { + if (str && "fillText" in curContext) { + if (isFillDirty) { + curContext.fillStyle = p.color.toString(currentFillColor); + isFillDirty = false + } + if (align === 39 || align === 3) { + textWidth = curTextFont.measureTextWidth(str); + if (align === 39) xOffset = -textWidth; + else xOffset = -textWidth / 2 + } + curContext.fillText(str, x + xOffset, y) + } + } else { + var font = p.glyphTable[curFontName]; + saveContext(); + curContext.translate(x, y + curTextSize); + if (align === 39 || align === 3) { + textWidth = font.width(str); + if (align === 39) xOffset = -textWidth; + else xOffset = -textWidth / 2 + } + var upem = font.units_per_em, + newScale = 1 / upem * curTextSize; + curContext.scale(newScale, newScale); + for (var i = 0, len = str.length; i < len; i++) try { + p.glyphLook(font, str[i]).draw() + } catch(e) { + Processing.debug(e) + } + restoreContext() + } + }; + Drawing3D.prototype.text$line = function(str, x, y, z, align) { + if (textcanvas === undef) textcanvas = document.createElement("canvas"); + var oldContext = curContext; + curContext = textcanvas.getContext("2d"); + curContext.font = curTextFont.css; + var textWidth = curTextFont.measureTextWidth(str); + textcanvas.width = textWidth; + textcanvas.height = curTextSize; + curContext = textcanvas.getContext("2d"); + curContext.font = curTextFont.css; + curContext.textBaseline = "top"; + Drawing2D.prototype.text$line(str, 0, 0, 0, 37); + var aspect = textcanvas.width / textcanvas.height; + curContext = oldContext; + curContext.bindTexture(curContext.TEXTURE_2D, textTex); + curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, textcanvas); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_T, curContext.CLAMP_TO_EDGE); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_S, curContext.CLAMP_TO_EDGE); + var xOffset = 0; + if (align === 39) xOffset = -textWidth; + else if (align === 3) xOffset = -textWidth / 2; + var model = new PMatrix3D; + var scalefactor = curTextSize * 0.5; + model.translate(x + xOffset - scalefactor / 2, y - scalefactor, z); + model.scale(-aspect * scalefactor, -scalefactor, scalefactor); + model.translate(-1, -1, -1); + model.transpose(); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + curContext.useProgram(programObject2D); + vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, textBuffer); + vertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord", 2, textureBuffer); + uniformi("uSampler2d", programObject2D, "uSampler", [0]); + uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", true); + uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array()); + uniformMatrix("uView2d", programObject2D, "uView", false, view.array()); + uniformf("uColor2d", programObject2D, "uColor", fillStyle); + curContext.bindBuffer(curContext.ELEMENT_ARRAY_BUFFER, indexBuffer); + curContext.drawElements(curContext.TRIANGLES, 6, curContext.UNSIGNED_SHORT, 0) + }; + + function text$4(str, x, y, z) { + var lines, linesCount; + if (str.indexOf("\n") < 0) { + lines = [str]; + linesCount = 1 + } else { + lines = str.split(/\r?\n/g); + linesCount = lines.length + } + var yOffset = 0; + if (verticalTextAlignment === 101) yOffset = curTextAscent + curTextDescent; + else if (verticalTextAlignment === 3) yOffset = curTextAscent / 2 - (linesCount - 1) * curTextLeading / 2; + else if (verticalTextAlignment === 102) yOffset = -(curTextDescent + (linesCount - 1) * curTextLeading); + for (var i = 0; i < linesCount; ++i) { + var line = lines[i]; + drawing.text$line(line, x, y + yOffset, z, horizontalTextAlignment); + yOffset += curTextLeading + } + } + function text$6(str, x, y, width, height, z) { + if (str.length === 0 || width === 0 || height === 0) return; + if (curTextSize > height) return; + var spaceMark = -1; + var start = 0; + var lineWidth = 0; + var drawCommands = []; + for (var charPos = 0, len = str.length; charPos < len; charPos++) { + var currentChar = str[charPos]; + var spaceChar = currentChar === " "; + var letterWidth = curTextFont.measureTextWidth(currentChar); + if (currentChar !== "\n" && lineWidth + letterWidth <= width) { + if (spaceChar) spaceMark = charPos; + lineWidth += letterWidth + } else { + if (spaceMark + 1 === start) if (charPos > 0) spaceMark = charPos; + else return; + if (currentChar === "\n") { + drawCommands.push({ + text: str.substring(start, charPos), + width: lineWidth + }); + start = charPos + 1 + } else { + drawCommands.push({ + text: str.substring(start, spaceMark + 1), + width: lineWidth + }); + start = spaceMark + 1 + } + lineWidth = 0; + charPos = start - 1 + } + } + if (start < len) drawCommands.push({ + text: str.substring(start), + width: lineWidth + }); + var xOffset = 1, + yOffset = curTextAscent; + if (horizontalTextAlignment === 3) xOffset = width / 2; + else if (horizontalTextAlignment === 39) xOffset = width; + var linesCount = drawCommands.length, + visibleLines = Math.min(linesCount, Math.floor(height / curTextLeading)); + if (verticalTextAlignment === 101) yOffset = curTextAscent + curTextDescent; + else if (verticalTextAlignment === 3) yOffset = height / 2 - curTextLeading * (visibleLines / 2 - 1); + else if (verticalTextAlignment === 102) yOffset = curTextDescent + curTextLeading; + var command, drawCommand, leading; + for (command = 0; command < linesCount; command++) { + leading = command * curTextLeading; + if (yOffset + leading > height - curTextDescent) break; + drawCommand = drawCommands[command]; + drawing.text$line(drawCommand.text, x + xOffset, y + yOffset + leading, z, horizontalTextAlignment) + } + } + p.text = function() { + if (textMode === 5) return; + if (arguments.length === 3) text$4(toP5String(arguments[0]), arguments[1], arguments[2], 0); + else if (arguments.length === 4) text$4(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3]); + else if (arguments.length === 5) text$6(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3], arguments[4], 0); + else if (arguments.length === 6) text$6(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]) + }; + p.textMode = function(mode) { + textMode = mode + }; + p.loadGlyphs = function(url) { + var x, y, cx, cy, nx, ny, d, a, lastCom, lenC, horiz_adv_x, getXY = "[0-9\\-]+", + path; + var regex = function(needle, hay) { + var i = 0, + results = [], + latest, regexp = new RegExp(needle, "g"); + latest = results[i] = regexp.exec(hay); + while (latest) { + i++; + latest = results[i] = regexp.exec(hay) + } + return results + }; + var buildPath = function(d) { + var c = regex("[A-Za-z][0-9\\- ]+|Z", d); + var beforePathDraw = function() { + saveContext(); + return drawing.$ensureContext() + }; + var afterPathDraw = function() { + executeContextFill(); + executeContextStroke(); + restoreContext() + }; + path = "return {draw:function(){var curContext=beforePathDraw();curContext.beginPath();"; + x = 0; + y = 0; + cx = 0; + cy = 0; + nx = 0; + ny = 0; + d = 0; + a = 0; + lastCom = ""; + lenC = c.length - 1; + for (var j = 0; j < lenC; j++) { + var com = c[j][0], + xy = regex(getXY, com); + switch (com[0]) { + case "M": + x = parseFloat(xy[0][0]); + y = parseFloat(xy[1][0]); + path += "curContext.moveTo(" + x + "," + -y + ");"; + break; + case "L": + x = parseFloat(xy[0][0]); + y = parseFloat(xy[1][0]); + path += "curContext.lineTo(" + x + "," + -y + ");"; + break; + case "H": + x = parseFloat(xy[0][0]); + path += "curContext.lineTo(" + x + "," + -y + ");"; + break; + case "V": + y = parseFloat(xy[0][0]); + path += "curContext.lineTo(" + x + "," + -y + ");"; + break; + case "T": + nx = parseFloat(xy[0][0]); + ny = parseFloat(xy[1][0]); + if (lastCom === "Q" || lastCom === "T") { + d = Math.sqrt(Math.pow(x - cx, 2) + Math.pow(cy - y, 2)); + a = Math.PI + Math.atan2(cx - x, cy - y); + cx = x + Math.sin(a) * d; + cy = y + Math.cos(a) * d + } else { + cx = x; + cy = y + } + path += "curContext.quadraticCurveTo(" + cx + "," + -cy + "," + nx + "," + -ny + ");"; + x = nx; + y = ny; + break; + case "Q": + cx = parseFloat(xy[0][0]); + cy = parseFloat(xy[1][0]); + nx = parseFloat(xy[2][0]); + ny = parseFloat(xy[3][0]); + path += "curContext.quadraticCurveTo(" + cx + "," + -cy + "," + nx + "," + -ny + ");"; + x = nx; + y = ny; + break; + case "Z": + path += "curContext.closePath();"; + break + } + lastCom = com[0] + } + path += "afterPathDraw();"; + path += "curContext.translate(" + horiz_adv_x + ",0);"; + path += "}}"; + return (new Function("beforePathDraw", "afterPathDraw", path))(beforePathDraw, afterPathDraw) + }; + var parseSVGFont = function(svg) { + var font = svg.getElementsByTagName("font"); + p.glyphTable[url].horiz_adv_x = font[0].getAttribute("horiz-adv-x"); + var font_face = svg.getElementsByTagName("font-face")[0]; + p.glyphTable[url].units_per_em = parseFloat(font_face.getAttribute("units-per-em")); + p.glyphTable[url].ascent = parseFloat(font_face.getAttribute("ascent")); + p.glyphTable[url].descent = parseFloat(font_face.getAttribute("descent")); + var glyph = svg.getElementsByTagName("glyph"), + len = glyph.length; + for (var i = 0; i < len; i++) { + var unicode = glyph[i].getAttribute("unicode"); + var name = glyph[i].getAttribute("glyph-name"); + horiz_adv_x = glyph[i].getAttribute("horiz-adv-x"); + if (horiz_adv_x === null) horiz_adv_x = p.glyphTable[url].horiz_adv_x; + d = glyph[i].getAttribute("d"); + if (d !== undef) { + path = buildPath(d); + p.glyphTable[url][name] = { + name: name, + unicode: unicode, + horiz_adv_x: horiz_adv_x, + draw: path.draw + } + } + } + }; + var loadXML = function() { + var xmlDoc; + try { + xmlDoc = document.implementation.createDocument("", "", null) + } catch(e_fx_op) { + Processing.debug(e_fx_op.message); + return + } + try { + xmlDoc.async = false; + xmlDoc.load(url); + parseSVGFont(xmlDoc.getElementsByTagName("svg")[0]) + } catch(e_sf_ch) { + Processing.debug(e_sf_ch); + try { + var xmlhttp = new window.XMLHttpRequest; + xmlhttp.open("GET", url, false); + xmlhttp.send(null); + parseSVGFont(xmlhttp.responseXML.documentElement) + } catch(e) { + Processing.debug(e_sf_ch) + } + } + }; + p.glyphTable[url] = {}; + loadXML(url); + return p.glyphTable[url] + }; + p.param = function(name) { + var attributeName = "data-processing-" + name; + if (curElement.hasAttribute(attributeName)) return curElement.getAttribute(attributeName); + for (var i = 0, len = curElement.childNodes.length; i < len; ++i) { + var item = curElement.childNodes.item(i); + if (item.nodeType !== 1 || item.tagName.toLowerCase() !== "param") continue; + if (item.getAttribute("name") === name) return item.getAttribute("value") + } + if (curSketch.params.hasOwnProperty(name)) return curSketch.params[name]; + return null + }; + + function wireDimensionalFunctions(mode) { + if (mode === "3D") drawing = new Drawing3D; + else if (mode === "2D") drawing = new Drawing2D; + else drawing = new DrawingPre; + for (var i in DrawingPre.prototype) if (DrawingPre.prototype.hasOwnProperty(i) && i.indexOf("$") < 0) p[i] = drawing[i]; + drawing.$init() + } + function createDrawingPreFunction(name) { + return function() { + wireDimensionalFunctions("2D"); + return drawing[name].apply(this, arguments) + } + } + DrawingPre.prototype.translate = createDrawingPreFunction("translate"); + DrawingPre.prototype.transform = createDrawingPreFunction("transform"); + DrawingPre.prototype.scale = createDrawingPreFunction("scale"); + DrawingPre.prototype.pushMatrix = createDrawingPreFunction("pushMatrix"); + DrawingPre.prototype.popMatrix = createDrawingPreFunction("popMatrix"); + DrawingPre.prototype.resetMatrix = createDrawingPreFunction("resetMatrix"); + DrawingPre.prototype.applyMatrix = createDrawingPreFunction("applyMatrix"); + DrawingPre.prototype.rotate = createDrawingPreFunction("rotate"); + DrawingPre.prototype.rotateZ = createDrawingPreFunction("rotateZ"); + DrawingPre.prototype.shearX = createDrawingPreFunction("shearX"); + DrawingPre.prototype.shearY = createDrawingPreFunction("shearY"); + DrawingPre.prototype.redraw = createDrawingPreFunction("redraw"); + DrawingPre.prototype.toImageData = createDrawingPreFunction("toImageData"); + DrawingPre.prototype.ambientLight = createDrawingPreFunction("ambientLight"); + DrawingPre.prototype.directionalLight = createDrawingPreFunction("directionalLight"); + DrawingPre.prototype.lightFalloff = createDrawingPreFunction("lightFalloff"); + DrawingPre.prototype.lightSpecular = createDrawingPreFunction("lightSpecular"); + DrawingPre.prototype.pointLight = createDrawingPreFunction("pointLight"); + DrawingPre.prototype.noLights = createDrawingPreFunction("noLights"); + DrawingPre.prototype.spotLight = createDrawingPreFunction("spotLight"); + DrawingPre.prototype.beginCamera = createDrawingPreFunction("beginCamera"); + DrawingPre.prototype.endCamera = createDrawingPreFunction("endCamera"); + DrawingPre.prototype.frustum = createDrawingPreFunction("frustum"); + DrawingPre.prototype.box = createDrawingPreFunction("box"); + DrawingPre.prototype.sphere = createDrawingPreFunction("sphere"); + DrawingPre.prototype.ambient = createDrawingPreFunction("ambient"); + DrawingPre.prototype.emissive = createDrawingPreFunction("emissive"); + DrawingPre.prototype.shininess = createDrawingPreFunction("shininess"); + DrawingPre.prototype.specular = createDrawingPreFunction("specular"); + DrawingPre.prototype.fill = createDrawingPreFunction("fill"); + DrawingPre.prototype.stroke = createDrawingPreFunction("stroke"); + DrawingPre.prototype.strokeWeight = createDrawingPreFunction("strokeWeight"); + DrawingPre.prototype.smooth = createDrawingPreFunction("smooth"); + DrawingPre.prototype.noSmooth = createDrawingPreFunction("noSmooth"); + DrawingPre.prototype.point = createDrawingPreFunction("point"); + DrawingPre.prototype.vertex = createDrawingPreFunction("vertex"); + DrawingPre.prototype.endShape = createDrawingPreFunction("endShape"); + DrawingPre.prototype.bezierVertex = createDrawingPreFunction("bezierVertex"); + DrawingPre.prototype.curveVertex = createDrawingPreFunction("curveVertex"); + DrawingPre.prototype.curve = createDrawingPreFunction("curve"); + DrawingPre.prototype.line = createDrawingPreFunction("line"); + DrawingPre.prototype.bezier = createDrawingPreFunction("bezier"); + DrawingPre.prototype.rect = createDrawingPreFunction("rect"); + DrawingPre.prototype.ellipse = createDrawingPreFunction("ellipse"); + DrawingPre.prototype.background = createDrawingPreFunction("background"); + DrawingPre.prototype.image = createDrawingPreFunction("image"); + DrawingPre.prototype.textWidth = createDrawingPreFunction("textWidth"); + DrawingPre.prototype.text$line = createDrawingPreFunction("text$line"); + DrawingPre.prototype.$ensureContext = createDrawingPreFunction("$ensureContext"); + DrawingPre.prototype.$newPMatrix = createDrawingPreFunction("$newPMatrix"); + DrawingPre.prototype.size = function(aWidth, aHeight, aMode) { + wireDimensionalFunctions(aMode === 2 ? "3D" : "2D"); + p.size(aWidth, aHeight, aMode) + }; + DrawingPre.prototype.$init = nop; + Drawing2D.prototype.$init = function() { + p.size(p.width, p.height); + curContext.lineCap = "round"; + p.noSmooth(); + p.disableContextMenu() + }; + Drawing3D.prototype.$init = function() { + p.use3DContext = true; + p.disableContextMenu() + }; + DrawingShared.prototype.$ensureContext = function() { + return curContext + }; + + function calculateOffset(curElement, event) { + var element = curElement, + offsetX = 0, + offsetY = 0; + p.pmouseX = p.mouseX; + p.pmouseY = p.mouseY; + if (element.offsetParent) { + do { + offsetX += element.offsetLeft; + offsetY += element.offsetTop + } while ( !! (element = element.offsetParent)) + } + element = curElement; + do { + offsetX -= element.scrollLeft || 0; + offsetY -= element.scrollTop || 0 + } while ( !! (element = element.parentNode)); + offsetX += stylePaddingLeft; + offsetY += stylePaddingTop; + offsetX += styleBorderLeft; + offsetY += styleBorderTop; + offsetX += window.pageXOffset; + offsetY += window.pageYOffset; + return { + "X": offsetX, + "Y": offsetY + } + } + function updateMousePosition(curElement, event) { + var offset = calculateOffset(curElement, event); + p.mouseX = event.pageX - offset.X; + p.mouseY = event.pageY - offset.Y + } + function addTouchEventOffset(t) { + var offset = calculateOffset(t.changedTouches[0].target, t.changedTouches[0]), + i; + for (i = 0; i < t.touches.length; i++) { + var touch = t.touches[i]; + touch.offsetX = touch.pageX - offset.X; + touch.offsetY = touch.pageY - offset.Y + } + for (i = 0; i < t.targetTouches.length; i++) { + var targetTouch = t.targetTouches[i]; + targetTouch.offsetX = targetTouch.pageX - offset.X; + targetTouch.offsetY = targetTouch.pageY - offset.Y + } + for (i = 0; i < t.changedTouches.length; i++) { + var changedTouch = t.changedTouches[i]; + changedTouch.offsetX = changedTouch.pageX - offset.X; + changedTouch.offsetY = changedTouch.pageY - offset.Y + } + return t + } + attachEventHandler(curElement, "touchstart", function(t) { + curElement.setAttribute("style", "-webkit-user-select: none"); + curElement.setAttribute("onclick", "void(0)"); + curElement.setAttribute("style", "-webkit-tap-highlight-color:rgba(0,0,0,0)"); + for (var i = 0, ehl = eventHandlers.length; i < ehl; i++) { + var type = eventHandlers[i].type; + if (type === "mouseout" || type === "mousemove" || type === "mousedown" || type === "mouseup" || type === "DOMMouseScroll" || type === "mousewheel" || type === "touchstart") detachEventHandler(eventHandlers[i]) + } + if (p.touchStart !== undef || p.touchMove !== undef || p.touchEnd !== undef || p.touchCancel !== undef) { + attachEventHandler(curElement, "touchstart", function(t) { + if (p.touchStart !== undef) { + t = addTouchEventOffset(t); + p.touchStart(t) + } + }); + attachEventHandler(curElement, "touchmove", function(t) { + if (p.touchMove !== undef) { + t.preventDefault(); + t = addTouchEventOffset(t); + p.touchMove(t) + } + }); + attachEventHandler(curElement, "touchend", function(t) { + if (p.touchEnd !== undef) { + t = addTouchEventOffset(t); + p.touchEnd(t) + } + }); + attachEventHandler(curElement, "touchcancel", function(t) { + if (p.touchCancel !== undef) { + t = addTouchEventOffset(t); + p.touchCancel(t) + } + }) + } else { + attachEventHandler(curElement, "touchstart", function(e) { + updateMousePosition(curElement, e.touches[0]); + p.__mousePressed = true; + p.mouseDragging = false; + p.mouseButton = 37; + if (typeof p.mousePressed === "function") p.mousePressed() + }); + attachEventHandler(curElement, "touchmove", function(e) { + e.preventDefault(); + updateMousePosition(curElement, e.touches[0]); + if (typeof p.mouseMoved === "function" && !p.__mousePressed) p.mouseMoved(); + if (typeof p.mouseDragged === "function" && p.__mousePressed) { + p.mouseDragged(); + p.mouseDragging = true + } + }); + attachEventHandler(curElement, "touchend", function(e) { + p.__mousePressed = false; + if (typeof p.mouseClicked === "function" && !p.mouseDragging) p.mouseClicked(); + if (typeof p.mouseReleased === "function") p.mouseReleased() + }) + } + curElement.dispatchEvent(t) + }); + (function() { + var enabled = true, + contextMenu = function(e) { + e.preventDefault(); + e.stopPropagation() + }; + p.disableContextMenu = function() { + if (!enabled) return; + attachEventHandler(curElement, "contextmenu", contextMenu); + enabled = false + }; + p.enableContextMenu = function() { + if (enabled) return; + detachEventHandler({ + elem: curElement, + type: "contextmenu", + fn: contextMenu + }); + enabled = true + } + })(); + attachEventHandler(curElement, "mousemove", function(e) { + updateMousePosition(curElement, e); + if (typeof p.mouseMoved === "function" && !p.__mousePressed) p.mouseMoved(); + if (typeof p.mouseDragged === "function" && p.__mousePressed) { + p.mouseDragged(); + p.mouseDragging = true + } + }); + attachEventHandler(curElement, "mouseout", function(e) { + if (typeof p.mouseOut === "function") p.mouseOut() + }); + attachEventHandler(curElement, "mouseover", function(e) { + updateMousePosition(curElement, e); + if (typeof p.mouseOver === "function") p.mouseOver() + }); + curElement.onmousedown = function() { + curElement.focus(); + return false + }; + attachEventHandler(curElement, "mousedown", function(e) { + p.__mousePressed = true; + p.mouseDragging = false; + switch (e.which) { + case 1: + p.mouseButton = 37; + break; + case 2: + p.mouseButton = 3; + break; + case 3: + p.mouseButton = 39; + break + } + if (typeof p.mousePressed === "function") p.mousePressed() + }); + attachEventHandler(curElement, "mouseup", function(e) { + p.__mousePressed = false; + if (typeof p.mouseClicked === "function" && !p.mouseDragging) p.mouseClicked(); + if (typeof p.mouseReleased === "function") p.mouseReleased() + }); + var mouseWheelHandler = function(e) { + var delta = 0; + if (e.wheelDelta) { + delta = e.wheelDelta / 120; + if (window.opera) delta = -delta + } else if (e.detail) delta = -e.detail / 3; + p.mouseScroll = delta; + if (delta && typeof p.mouseScrolled === "function") p.mouseScrolled() + }; + attachEventHandler(document, "DOMMouseScroll", mouseWheelHandler); + attachEventHandler(document, "mousewheel", mouseWheelHandler); + if (!curElement.getAttribute("tabindex")) curElement.setAttribute("tabindex", 0); + + function getKeyCode(e) { + var code = e.which || e.keyCode; + switch (code) { + case 13: + return 10; + case 91: + case 93: + case 224: + return 157; + case 57392: + return 17; + case 46: + return 127; + case 45: + return 155 + } + return code + } + function getKeyChar(e) { + var c = e.which || e.keyCode; + var anyShiftPressed = e.shiftKey || e.ctrlKey || e.altKey || e.metaKey; + switch (c) { + case 13: + c = anyShiftPressed ? 13 : 10; + break; + case 8: + c = anyShiftPressed ? 127 : 8; + break + } + return new Char(c) + } + function suppressKeyEvent(e) { + if (typeof e.preventDefault === "function") e.preventDefault(); + else if (typeof e.stopPropagation === "function") e.stopPropagation(); + return false + } + function updateKeyPressed() { + var ch; + for (ch in pressedKeysMap) if (pressedKeysMap.hasOwnProperty(ch)) { + p.__keyPressed = true; + return + } + p.__keyPressed = false + } + function resetKeyPressed() { + p.__keyPressed = false; + pressedKeysMap = []; + lastPressedKeyCode = null + } + function simulateKeyTyped(code, c) { + pressedKeysMap[code] = c; + lastPressedKeyCode = null; + p.key = c; + p.keyCode = code; + p.keyPressed(); + p.keyCode = 0; + p.keyTyped(); + updateKeyPressed() + } + function handleKeydown(e) { + var code = getKeyCode(e); + if (code === 127) { + simulateKeyTyped(code, new Char(127)); + return + } + if (codedKeys.indexOf(code) < 0) { + lastPressedKeyCode = code; + return + } + var c = new Char(65535); + p.key = c; + p.keyCode = code; + pressedKeysMap[code] = c; + p.keyPressed(); + lastPressedKeyCode = null; + updateKeyPressed(); + return suppressKeyEvent(e) + } + function handleKeypress(e) { + if (lastPressedKeyCode === null) return; + var code = lastPressedKeyCode, + c = getKeyChar(e); + simulateKeyTyped(code, c); + return suppressKeyEvent(e) + } + function handleKeyup(e) { + var code = getKeyCode(e), + c = pressedKeysMap[code]; + if (c === undef) return; + p.key = c; + p.keyCode = code; + p.keyReleased(); + delete pressedKeysMap[code]; + updateKeyPressed() + } + if (!pgraphicsMode) { + if (aCode instanceof Processing.Sketch) curSketch = aCode; + else if (typeof aCode === "function") curSketch = new Processing.Sketch(aCode); + else if (!aCode) curSketch = new Processing.Sketch(function() {}); + else curSketch = Processing.compile(aCode); + p.externals.sketch = curSketch; + wireDimensionalFunctions(); + curElement.onfocus = function() { + p.focused = true + }; + curElement.onblur = function() { + p.focused = false; + if (!curSketch.options.globalKeyEvents) resetKeyPressed() + }; + if (curSketch.options.pauseOnBlur) { + attachEventHandler(window, "focus", function() { + if (doLoop) p.loop() + }); + attachEventHandler(window, "blur", function() { + if (doLoop && loopStarted) { + p.noLoop(); + doLoop = true + } + resetKeyPressed() + }) + } + var keyTrigger = curSketch.options.globalKeyEvents ? window : curElement; + attachEventHandler(keyTrigger, "keydown", handleKeydown); + attachEventHandler(keyTrigger, "keypress", handleKeypress); + attachEventHandler(keyTrigger, "keyup", handleKeyup); + for (var i in Processing.lib) if (Processing.lib.hasOwnProperty(i)) if (Processing.lib[i].hasOwnProperty("attach")) Processing.lib[i].attach(p); + else if (Processing.lib[i] instanceof Function) Processing.lib[i].call(this); + var retryInterval = 100; + var executeSketch = function(processing) { + if (! (curSketch.imageCache.pending || PFont.preloading.pending(retryInterval))) { + if (window.opera) { + var link, element, operaCache = curSketch.imageCache.operaCache; + for (link in operaCache) if (operaCache.hasOwnProperty(link)) { + element = operaCache[link]; + if (element !== null) document.body.removeChild(element); + delete operaCache[link] + } + } + curSketch.attach(processing, defaultScope); + curSketch.onLoad(processing); + if (processing.setup) { + processing.setup(); + processing.resetMatrix(); + curSketch.onSetup() + } + resetContext(); + if (processing.draw) if (!doLoop) processing.redraw(); + else processing.loop() + } else window.setTimeout(function() { + executeSketch(processing) + }, + retryInterval) + }; + addInstance(this); + executeSketch(p) + } else { + curSketch = new Processing.Sketch; + wireDimensionalFunctions(); + p.size = function(w, h, render) { + if (render && render === 2) wireDimensionalFunctions("3D"); + else wireDimensionalFunctions("2D"); + p.size(w, h, render) + } + } + }; + Processing.debug = debug; + Processing.prototype = defaultScope; + + function getGlobalMembers() { + var names = ["abs", "acos", "alpha", "ambient", "ambientLight", "append", + "applyMatrix", "arc", "arrayCopy", "asin", "atan", "atan2", "background", "beginCamera", "beginDraw", "beginShape", "bezier", "bezierDetail", "bezierPoint", "bezierTangent", "bezierVertex", "binary", "blend", "blendColor", "blit_resize", "blue", "box", "breakShape", "brightness", "camera", "ceil", "Character", "color", "colorMode", "concat", "constrain", "copy", "cos", "createFont", "createGraphics", "createImage", "cursor", "curve", "curveDetail", "curvePoint", "curveTangent", "curveTightness", "curveVertex", "day", "degrees", "directionalLight", + "disableContextMenu", "dist", "draw", "ellipse", "ellipseMode", "emissive", "enableContextMenu", "endCamera", "endDraw", "endShape", "exit", "exp", "expand", "externals", "fill", "filter", "floor", "focused", "frameCount", "frameRate", "frustum", "get", "glyphLook", "glyphTable", "green", "height", "hex", "hint", "hour", "hue", "image", "imageMode", "intersect", "join", "key", "keyCode", "keyPressed", "keyReleased", "keyTyped", "lerp", "lerpColor", "lightFalloff", "lights", "lightSpecular", "line", "link", "loadBytes", "loadFont", "loadGlyphs", + "loadImage", "loadPixels", "loadShape", "loadXML", "loadStrings", "log", "loop", "mag", "map", "match", "matchAll", "max", "millis", "min", "minute", "mix", "modelX", "modelY", "modelZ", "modes", "month", "mouseButton", "mouseClicked", "mouseDragged", "mouseMoved", "mouseOut", "mouseOver", "mousePressed", "mouseReleased", "mouseScroll", "mouseScrolled", "mouseX", "mouseY", "name", "nf", "nfc", "nfp", "nfs", "noCursor", "noFill", "noise", "noiseDetail", "noiseSeed", "noLights", "noLoop", "norm", "normal", "noSmooth", "noStroke", "noTint", "ortho", + "param", "parseBoolean", "parseByte", "parseChar", "parseFloat", "parseInt", "peg", "perspective", "PImage", "pixels", "PMatrix2D", "PMatrix3D", "PMatrixStack", "pmouseX", "pmouseY", "point", "pointLight", "popMatrix", "popStyle", "pow", "print", "printCamera", "println", "printMatrix", "printProjection", "PShape", "PShapeSVG", "pushMatrix", "pushStyle", "quad", "radians", "random", "Random", "randomSeed", "rect", "rectMode", "red", "redraw", "requestImage", "resetMatrix", "reverse", "rotate", "rotateX", "rotateY", "rotateZ", "round", "saturation", + "save", "saveFrame", "saveStrings", "scale", "screenX", "screenY", "screenZ", "second", "set", "setup", "shape", "shapeMode", "shared", "shearX", "shearY", "shininess", "shorten", "sin", "size", "smooth", "sort", "specular", "sphere", "sphereDetail", "splice", "split", "splitTokens", "spotLight", "sq", "sqrt", "status", "str", "stroke", "strokeCap", "strokeJoin", "strokeWeight", "subset", "tan", "text", "textAlign", "textAscent", "textDescent", "textFont", "textLeading", "textMode", "textSize", "texture", "textureMode", "textWidth", "tint", "toImageData", + "touchCancel", "touchEnd", "touchMove", "touchStart", "translate", "transform", "triangle", "trim", "unbinary", "unhex", "updatePixels", "use3DContext", "vertex", "width", "XMLElement", "XML", "year", "__contains", "__equals", "__equalsIgnoreCase", "__frameRate", "__hashCode", "__int_cast", "__instanceof", "__keyPressed", "__mousePressed", "__printStackTrace", "__replace", "__replaceAll", "__replaceFirst", "__toCharArray", "__split", "__codePointAt", "__startsWith", "__endsWith", "__matches"]; + var members = {}; + var i, l; + for (i = 0, l = names.length; i < l; ++i) members[names[i]] = null; + for (var lib in Processing.lib) if (Processing.lib.hasOwnProperty(lib)) if (Processing.lib[lib].exports) { + var exportedNames = Processing.lib[lib].exports; + for (i = 0, l = exportedNames.length; i < l; ++i) members[exportedNames[i]] = null + } + return members + } + function parseProcessing(code) { + var globalMembers = getGlobalMembers(); + + function splitToAtoms(code) { + var atoms = []; + var items = code.split(/([\{\[\(\)\]\}])/); + var result = items[0]; + var stack = []; + for (var i = 1; i < items.length; i += 2) { + var item = items[i]; + if (item === "[" || item === "{" || item === "(") { + stack.push(result); + result = item + } else if (item === "]" || item === "}" || item === ")") { + var kind = item === "}" ? "A" : item === ")" ? "B" : "C"; + var index = atoms.length; + atoms.push(result + item); + result = stack.pop() + '"' + kind + (index + 1) + '"' + } + result += items[i + 1] + } + atoms.unshift(result); + return atoms + } + function injectStrings(code, strings) { + return code.replace(/'(\d+)'/g, function(all, index) { + var val = strings[index]; + if (val.charAt(0) === "/") return val; + return /^'((?:[^'\\\n])|(?:\\.[0-9A-Fa-f]*))'$/.test(val) ? "(new $p.Character(" + val + "))" : val + }) + } + function trimSpaces(string) { + var m1 = /^\s*/.exec(string), + result; + if (m1[0].length === string.length) result = { + left: m1[0], + middle: "", + right: "" + }; + else { + var m2 = /\s*$/.exec(string); + result = { + left: m1[0], + middle: string.substring(m1[0].length, m2.index), + right: m2[0] + } + } + result.untrim = function(t) { + return this.left + t + this.right + }; + return result + } + function trim(string) { + return string.replace(/^\s+/, "").replace(/\s+$/, "") + } + function appendToLookupTable(table, array) { + for (var i = 0, l = array.length; i < l; ++i) table[array[i]] = null; + return table + } + function isLookupTableEmpty(table) { + for (var i in table) if (table.hasOwnProperty(i)) return false; + return true + } + function getAtomIndex(templ) { + return templ.substring(2, templ.length - 1) + } + var codeWoExtraCr = code.replace(/\r\n?|\n\r/g, "\n"); + var strings = []; + var codeWoStrings = codeWoExtraCr.replace(/("(?:[^"\\\n]|\\.)*")|('(?:[^'\\\n]|\\.)*')|(([\[\(=|&!\^:?]\s*)(\/(?![*\/])(?:[^\/\\\n]|\\.)*\/[gim]*)\b)|(\/\/[^\n]*\n)|(\/\*(?:(?!\*\/)(?:.|\n))*\*\/)/g, function(all, quoted, aposed, regexCtx, prefix, regex, singleComment, comment) { + var index; + if (quoted || aposed) { + index = strings.length; + strings.push(all); + return "'" + index + "'" + } + if (regexCtx) { + index = strings.length; + strings.push(regex); + return prefix + "'" + index + "'" + } + return comment !== "" ? " " : "\n" + }); + codeWoStrings = codeWoStrings.replace(/__x([0-9A-F]{4})/g, function(all, hexCode) { + return "__x005F_x" + hexCode + }); + codeWoStrings = codeWoStrings.replace(/\$/g, "__x0024"); + var genericsWereRemoved; + var codeWoGenerics = codeWoStrings; + var replaceFunc = function(all, before, types, after) { + if ( !! before || !!after) return all; + genericsWereRemoved = true; + return "" + }; + do { + genericsWereRemoved = false; + codeWoGenerics = codeWoGenerics.replace(/([<]?)<\s*((?:\?|[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\[\])*(?:\s+(?:extends|super)\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)?(?:\s*,\s*(?:\?|[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\[\])*(?:\s+(?:extends|super)\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)?)*)\s*>([=]?)/g, replaceFunc) + } while (genericsWereRemoved); + var atoms = splitToAtoms(codeWoGenerics); + var replaceContext; + var declaredClasses = {}, + currentClassId, classIdSeed = 0; + + function addAtom(text, type) { + var lastIndex = atoms.length; + atoms.push(text); + return '"' + type + lastIndex + '"' + } + function generateClassId() { + return "class" + ++classIdSeed + } + function appendClass(class_, classId, scopeId) { + class_.classId = classId; + class_.scopeId = scopeId; + declaredClasses[classId] = class_ + } + var transformClassBody, transformInterfaceBody, transformStatementsBlock, transformStatements, transformMain, transformExpression; + var classesRegex = /\b((?:(?:public|private|final|protected|static|abstract)\s+)*)(class|interface)\s+([A-Za-z_$][\w$]*\b)(\s+extends\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*\b)*)?(\s+implements\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*\b)*)?\s*("A\d+")/g; + var methodsRegex = /\b((?:(?:public|private|final|protected|static|abstract|synchronized)\s+)*)((?!(?:else|new|return|throw|function|public|private|protected)\b)[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*"C\d+")*)\s*([A-Za-z_$][\w$]*\b)\s*("B\d+")(\s*throws\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)*)?\s*("A\d+"|;)/g; + var fieldTest = /^((?:(?:public|private|final|protected|static)\s+)*)((?!(?:else|new|return|throw)\b)[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*"C\d+")*)\s*([A-Za-z_$][\w$]*\b)\s*(?:"C\d+"\s*)*([=,]|$)/; + var cstrsRegex = /\b((?:(?:public|private|final|protected|static|abstract)\s+)*)((?!(?:new|return|throw)\b)[A-Za-z_$][\w$]*\b)\s*("B\d+")(\s*throws\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)*)?\s*("A\d+")/g; + var attrAndTypeRegex = /^((?:(?:public|private|final|protected|static)\s+)*)((?!(?:new|return|throw)\b)[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*"C\d+")*)\s*/; + var functionsRegex = /\bfunction(?:\s+([A-Za-z_$][\w$]*))?\s*("B\d+")\s*("A\d+")/g; + + function extractClassesAndMethods(code) { + var s = code; + s = s.replace(classesRegex, function(all) { + return addAtom(all, "E") + }); + s = s.replace(methodsRegex, function(all) { + return addAtom(all, "D") + }); + s = s.replace(functionsRegex, function(all) { + return addAtom(all, "H") + }); + return s + } + function extractConstructors(code, className) { + var result = code.replace(cstrsRegex, function(all, attr, name, params, throws_, body) { + if (name !== className) return all; + return addAtom(all, "G") + }); + return result + } + function AstParam(name) { + this.name = name + } + AstParam.prototype.toString = function() { + return this.name + }; + + function AstParams(params, methodArgsParam) { + this.params = params; + this.methodArgsParam = methodArgsParam + } + AstParams.prototype.getNames = function() { + var names = []; + for (var i = 0, l = this.params.length; i < l; ++i) names.push(this.params[i].name); + return names + }; + AstParams.prototype.prependMethodArgs = function(body) { + if (!this.methodArgsParam) return body; + return "{\nvar " + this.methodArgsParam.name + " = Array.prototype.slice.call(arguments, " + this.params.length + ");\n" + body.substring(1) + }; + AstParams.prototype.toString = function() { + if (this.params.length === 0) return "()"; + var result = "("; + for (var i = 0, l = this.params.length; i < l; ++i) result += this.params[i] + ", "; + return result.substring(0, result.length - 2) + ")" + }; + + function transformParams(params) { + var paramsWoPars = trim(params.substring(1, params.length - 1)); + var result = [], + methodArgsParam = null; + if (paramsWoPars !== "") { + var paramList = paramsWoPars.split(","); + for (var i = 0; i < paramList.length; ++i) { + var param = /\b([A-Za-z_$][\w$]*\b)(\s*"[ABC][\d]*")*\s*$/.exec(paramList[i]); + if (i === paramList.length - 1 && paramList[i].indexOf("...") >= 0) { + methodArgsParam = new AstParam(param[1]); + break + } + result.push(new AstParam(param[1])) + } + } + return new AstParams(result, methodArgsParam) + } + function preExpressionTransform(expr) { + var s = expr; + s = s.replace(/\bnew\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\s*"C\d+")+\s*("A\d+")/g, function(all, type, init) { + return init + }); + s = s.replace(/\bnew\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\s*"B\d+")\s*("A\d+")/g, function(all, type, init) { + return addAtom(all, "F") + }); + s = s.replace(functionsRegex, function(all) { + return addAtom(all, "H") + }); + s = s.replace(/\bnew\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)\s*("C\d+"(?:\s*"C\d+")*)/g, function(all, type, index) { + var args = index.replace(/"C(\d+)"/g, function(all, j) { + return atoms[j] + }).replace(/\[\s*\]/g, "[null]").replace(/\s*\]\s*\[\s*/g, ", "); + var arrayInitializer = "{" + args.substring(1, args.length - 1) + "}"; + var createArrayArgs = "('" + type + "', " + addAtom(arrayInitializer, "A") + ")"; + return "$p.createJavaArray" + addAtom(createArrayArgs, "B") + }); + s = s.replace(/(\.\s*length)\s*"B\d+"/g, "$1"); + s = s.replace(/#([0-9A-Fa-f]{6})\b/g, function(all, digits) { + return "0xFF" + digits + }); + s = s.replace(/"B(\d+)"(\s*(?:[\w$']|"B))/g, function(all, index, next) { + var atom = atoms[index]; + if (!/^\(\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*\s*(?:"C\d+"\s*)*\)$/.test(atom)) return all; + if (/^\(\s*int\s*\)$/.test(atom)) return "(int)" + next; + var indexParts = atom.split(/"C(\d+)"/g); + if (indexParts.length > 1) if (!/^\[\s*\]$/.test(atoms[indexParts[1]])) return all; + return "" + next + }); + s = s.replace(/\(int\)([^,\]\)\}\?\:\*\+\-\/\^\|\%\&\~<\>\=]+)/g, function(all, arg) { + var trimmed = trimSpaces(arg); + return trimmed.untrim("__int_cast(" + trimmed.middle + ")") + }); + s = s.replace(/\bsuper(\s*"B\d+")/g, "$$superCstr$1").replace(/\bsuper(\s*\.)/g, "$$super$1"); + s = s.replace(/\b0+((\d*)(?:\.[\d*])?(?:[eE][\-\+]?\d+)?[fF]?)\b/, function(all, numberWo0, intPart) { + if (numberWo0 === intPart) return all; + return intPart === "" ? "0" + numberWo0 : numberWo0 + }); + s = s.replace(/\b(\.?\d+\.?)[fF]\b/g, "$1"); + s = s.replace(/([^\s])%([^=\s])/g, "$1 % $2"); + s = s.replace(/\b(frameRate|keyPressed|mousePressed)\b(?!\s*"B)/g, "__$1"); + s = s.replace(/\b(boolean|byte|char|float|int)\s*"B/g, function(all, name) { + return "parse" + name.substring(0, 1).toUpperCase() + name.substring(1) + '"B' + }); + s = s.replace(/\bpixels\b\s*(("C(\d+)")|\.length)?(\s*=(?!=)([^,\]\)\}]+))?/g, function(all, indexOrLength, index, atomIndex, equalsPart, rightSide) { + if (index) { + var atom = atoms[atomIndex]; + if (equalsPart) return "pixels.setPixel" + addAtom("(" + atom.substring(1, atom.length - 1) + "," + rightSide + ")", "B"); + return "pixels.getPixel" + addAtom("(" + atom.substring(1, atom.length - 1) + ")", "B") + } + if (indexOrLength) return "pixels.getLength" + addAtom("()", "B"); + if (equalsPart) return "pixels.set" + addAtom("(" + rightSide + ")", "B"); + return "pixels.toArray" + addAtom("()", "B") + }); + var repeatJavaReplacement; + + function replacePrototypeMethods(all, subject, method, atomIndex) { + var atom = atoms[atomIndex]; + repeatJavaReplacement = true; + var trimmed = trimSpaces(atom.substring(1, atom.length - 1)); + return "__" + method + (trimmed.middle === "" ? addAtom("(" + subject.replace(/\.\s*$/, "") + ")", "B") : addAtom("(" + subject.replace(/\.\s*$/, "") + "," + trimmed.middle + ")", "B")) + } + do { + repeatJavaReplacement = false; + s = s.replace(/((?:'\d+'|\b[A-Za-z_$][\w$]*\s*(?:"[BC]\d+")*)\s*\.\s*(?:[A-Za-z_$][\w$]*\s*(?:"[BC]\d+"\s*)*\.\s*)*)(replace|replaceAll|replaceFirst|contains|equals|equalsIgnoreCase|hashCode|toCharArray|printStackTrace|split|startsWith|endsWith|codePointAt|matches)\s*"B(\d+)"/g, replacePrototypeMethods) + } while (repeatJavaReplacement); + + function replaceInstanceof(all, subject, type) { + repeatJavaReplacement = true; + return "__instanceof" + addAtom("(" + subject + ", " + type + ")", "B") + } + do { + repeatJavaReplacement = false; + s = s.replace(/((?:'\d+'|\b[A-Za-z_$][\w$]*\s*(?:"[BC]\d+")*)\s*(?:\.\s*[A-Za-z_$][\w$]*\s*(?:"[BC]\d+"\s*)*)*)instanceof\s+([A-Za-z_$][\w$]*\s*(?:\.\s*[A-Za-z_$][\w$]*)*)/g, replaceInstanceof) + } while (repeatJavaReplacement); + s = s.replace(/\bthis(\s*"B\d+")/g, "$$constr$1"); + return s + } + function AstInlineClass(baseInterfaceName, body) { + this.baseInterfaceName = baseInterfaceName; + this.body = body; + body.owner = this + } + AstInlineClass.prototype.toString = function() { + return "new (" + this.body + ")" + }; + + function transformInlineClass(class_) { + var m = (new RegExp(/\bnew\s*([A-Za-z_$][\w$]*\s*(?:\.\s*[A-Za-z_$][\w$]*)*)\s*"B\d+"\s*"A(\d+)"/)).exec(class_); + var oldClassId = currentClassId, + newClassId = generateClassId(); + currentClassId = newClassId; + var uniqueClassName = m[1] + "$" + newClassId; + var inlineClass = new AstInlineClass(uniqueClassName, transformClassBody(atoms[m[2]], uniqueClassName, "", "implements " + m[1])); + appendClass(inlineClass, newClassId, oldClassId); + currentClassId = oldClassId; + return inlineClass + } + + function AstFunction(name, params, body) { + this.name = name; + this.params = params; + this.body = body + } + AstFunction.prototype.toString = function() { + var oldContext = replaceContext; + var names = appendToLookupTable({ + "this": null + }, + this.params.getNames()); + replaceContext = function(subject) { + return names.hasOwnProperty(subject.name) ? subject.name : oldContext(subject) + }; + var result = "function"; + if (this.name) result += " " + this.name; + var body = this.params.prependMethodArgs(this.body.toString()); + result += this.params + " " + body; + replaceContext = oldContext; + return result + }; + + function transformFunction(class_) { + var m = (new RegExp(/\b([A-Za-z_$][\w$]*)\s*"B(\d+)"\s*"A(\d+)"/)).exec(class_); + return new AstFunction(m[1] !== "function" ? m[1] : null, transformParams(atoms[m[2]]), transformStatementsBlock(atoms[m[3]])) + } + function AstInlineObject(members) { + this.members = members + } + AstInlineObject.prototype.toString = function() { + var oldContext = replaceContext; + replaceContext = function(subject) { + return subject.name === "this" ? "this" : oldContext(subject) + }; + var result = ""; + for (var i = 0, l = this.members.length; i < l; ++i) { + if (this.members[i].label) result += this.members[i].label + ": "; + result += this.members[i].value.toString() + ", " + } + replaceContext = oldContext; + return result.substring(0, result.length - 2) + }; + + function transformInlineObject(obj) { + var members = obj.split(","); + for (var i = 0; i < members.length; ++i) { + var label = members[i].indexOf(":"); + if (label < 0) members[i] = { + value: transformExpression(members[i]) + }; + else members[i] = { + label: trim(members[i].substring(0, label)), + value: transformExpression(trim(members[i].substring(label + 1))) + } + } + return new AstInlineObject(members) + } + + function expandExpression(expr) { + if (expr.charAt(0) === "(" || expr.charAt(0) === "[") return expr.charAt(0) + expandExpression(expr.substring(1, expr.length - 1)) + expr.charAt(expr.length - 1); + if (expr.charAt(0) === "{") { + if (/^\{\s*(?:[A-Za-z_$][\w$]*|'\d+')\s*:/.test(expr)) return "{" + addAtom(expr.substring(1, expr.length - 1), "I") + "}"; + return "[" + expandExpression(expr.substring(1, expr.length - 1)) + "]" + } + var trimmed = trimSpaces(expr); + var result = preExpressionTransform(trimmed.middle); + result = result.replace(/"[ABC](\d+)"/g, function(all, index) { + return expandExpression(atoms[index]) + }); + return trimmed.untrim(result) + } + function replaceContextInVars(expr) { + return expr.replace(/(\.\s*)?((?:\b[A-Za-z_]|\$)[\w$]*)(\s*\.\s*([A-Za-z_$][\w$]*)(\s*\()?)?/g, function(all, memberAccessSign, identifier, suffix, subMember, callSign) { + if (memberAccessSign) return all; + var subject = { + name: identifier, + member: subMember, + callSign: !!callSign + }; + return replaceContext(subject) + (suffix === undef ? "" : suffix) + }) + } + function AstExpression(expr, transforms) { + this.expr = expr; + this.transforms = transforms + } + AstExpression.prototype.toString = function() { + var transforms = this.transforms; + var expr = replaceContextInVars(this.expr); + return expr.replace(/"!(\d+)"/g, function(all, index) { + return transforms[index].toString() + }) + }; + transformExpression = function(expr) { + var transforms = []; + var s = expandExpression(expr); + s = s.replace(/"H(\d+)"/g, function(all, index) { + transforms.push(transformFunction(atoms[index])); + return '"!' + (transforms.length - 1) + '"' + }); + s = s.replace(/"F(\d+)"/g, function(all, index) { + transforms.push(transformInlineClass(atoms[index])); + return '"!' + (transforms.length - 1) + '"' + }); + s = s.replace(/"I(\d+)"/g, function(all, index) { + transforms.push(transformInlineObject(atoms[index])); + return '"!' + (transforms.length - 1) + '"' + }); + return new AstExpression(s, transforms) + }; + + function AstVarDefinition(name, value, isDefault) { + this.name = name; + this.value = value; + this.isDefault = isDefault + } + AstVarDefinition.prototype.toString = function() { + return this.name + " = " + this.value + }; + + function transformVarDefinition(def, defaultTypeValue) { + var eqIndex = def.indexOf("="); + var name, value, isDefault; + if (eqIndex < 0) { + name = def; + value = defaultTypeValue; + isDefault = true + } else { + name = def.substring(0, eqIndex); + value = transformExpression(def.substring(eqIndex + 1)); + isDefault = false + } + return new AstVarDefinition(trim(name.replace(/(\s*"C\d+")+/g, "")), value, isDefault) + } + function getDefaultValueForType(type) { + if (type === "int" || type === "float") return "0"; + if (type === "boolean") return "false"; + if (type === "color") return "0x00000000"; + return "null" + } + function AstVar(definitions, varType) { + this.definitions = definitions; + this.varType = varType + } + AstVar.prototype.getNames = function() { + var names = []; + for (var i = 0, l = this.definitions.length; i < l; ++i) names.push(this.definitions[i].name); + return names + }; + AstVar.prototype.toString = function() { + return "var " + this.definitions.join(",") + }; + + function AstStatement(expression) { + this.expression = expression + } + AstStatement.prototype.toString = function() { + return this.expression.toString() + }; + + function transformStatement(statement) { + if (fieldTest.test(statement)) { + var attrAndType = attrAndTypeRegex.exec(statement); + var definitions = statement.substring(attrAndType[0].length).split(","); + var defaultTypeValue = getDefaultValueForType(attrAndType[2]); + for (var i = 0; i < definitions.length; ++i) definitions[i] = transformVarDefinition(definitions[i], defaultTypeValue); + return new AstVar(definitions, attrAndType[2]) + } + return new AstStatement(transformExpression(statement)) + } + function AstForExpression(initStatement, condition, step) { + this.initStatement = initStatement; + this.condition = condition; + this.step = step + } + AstForExpression.prototype.toString = function() { + return "(" + this.initStatement + "; " + this.condition + "; " + this.step + ")" + }; + + function AstForInExpression(initStatement, container) { + this.initStatement = initStatement; + this.container = container + } + AstForInExpression.prototype.toString = function() { + var init = this.initStatement.toString(); + if (init.indexOf("=") >= 0) init = init.substring(0, init.indexOf("=")); + return "(" + init + " in " + this.container + ")" + }; + + function AstForEachExpression(initStatement, container) { + this.initStatement = initStatement; + this.container = container + } + AstForEachExpression.iteratorId = 0; + AstForEachExpression.prototype.toString = function() { + var init = this.initStatement.toString(); + var iterator = "$it" + AstForEachExpression.iteratorId++; + var variableName = init.replace(/^\s*var\s*/, "").split("=")[0]; + var initIteratorAndVariable = "var " + iterator + " = new $p.ObjectIterator(" + this.container + "), " + variableName + " = void(0)"; + var nextIterationCondition = iterator + ".hasNext() && ((" + variableName + " = " + iterator + ".next()) || true)"; + return "(" + initIteratorAndVariable + "; " + nextIterationCondition + ";)" + }; + + function transformForExpression(expr) { + var content; + if (/\bin\b/.test(expr)) { + content = expr.substring(1, expr.length - 1).split(/\bin\b/g); + return new AstForInExpression(transformStatement(trim(content[0])), transformExpression(content[1])) + } + if (expr.indexOf(":") >= 0 && expr.indexOf(";") < 0) { + content = expr.substring(1, expr.length - 1).split(":"); + return new AstForEachExpression(transformStatement(trim(content[0])), transformExpression(content[1])) + } + content = expr.substring(1, expr.length - 1).split(";"); + return new AstForExpression(transformStatement(trim(content[0])), transformExpression(content[1]), transformExpression(content[2])) + } + + function sortByWeight(array) { + array.sort(function(a, b) { + return b.weight - a.weight + }) + } + function AstInnerInterface(name, body, isStatic) { + this.name = name; + this.body = body; + this.isStatic = isStatic; + body.owner = this + } + AstInnerInterface.prototype.toString = function() { + return "" + this.body + }; + + function AstInnerClass(name, body, isStatic) { + this.name = name; + this.body = body; + this.isStatic = isStatic; + body.owner = this + } + AstInnerClass.prototype.toString = function() { + return "" + this.body + }; + + function transformInnerClass(class_) { + var m = classesRegex.exec(class_); + classesRegex.lastIndex = 0; + var isStatic = m[1].indexOf("static") >= 0; + var body = atoms[getAtomIndex(m[6])], + innerClass; + var oldClassId = currentClassId, + newClassId = generateClassId(); + currentClassId = newClassId; + if (m[2] === "interface") innerClass = new AstInnerInterface(m[3], transformInterfaceBody(body, m[3], m[4]), isStatic); + else innerClass = new AstInnerClass(m[3], transformClassBody(body, m[3], m[4], m[5]), isStatic); + appendClass(innerClass, newClassId, oldClassId); + currentClassId = oldClassId; + return innerClass + } + function AstClassMethod(name, params, body, isStatic) { + this.name = name; + this.params = params; + this.body = body; + this.isStatic = isStatic + } + AstClassMethod.prototype.toString = function() { + var paramNames = appendToLookupTable({}, + this.params.getNames()); + var oldContext = replaceContext; + replaceContext = function(subject) { + return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject) + }; + var body = this.params.prependMethodArgs(this.body.toString()); + var result = "function " + this.methodId + this.params + " " + body + "\n"; + replaceContext = oldContext; + return result + }; + + function transformClassMethod(method) { + var m = methodsRegex.exec(method); + methodsRegex.lastIndex = 0; + var isStatic = m[1].indexOf("static") >= 0; + var body = m[6] !== ";" ? atoms[getAtomIndex(m[6])] : "{}"; + return new AstClassMethod(m[3], transformParams(atoms[getAtomIndex(m[4])]), transformStatementsBlock(body), isStatic) + } + function AstClassField(definitions, fieldType, isStatic) { + this.definitions = definitions; + this.fieldType = fieldType; + this.isStatic = isStatic + } + AstClassField.prototype.getNames = function() { + var names = []; + for (var i = 0, l = this.definitions.length; i < l; ++i) names.push(this.definitions[i].name); + return names + }; + AstClassField.prototype.toString = function() { + var thisPrefix = replaceContext({ + name: "[this]" + }); + if (this.isStatic) { + var className = this.owner.name; + var staticDeclarations = []; + for (var i = 0, l = this.definitions.length; i < l; ++i) { + var definition = this.definitions[i]; + var name = definition.name, + staticName = className + "." + name; + var declaration = "if(" + staticName + " === void(0)) {\n" + " " + staticName + " = " + definition.value + "; }\n" + "$p.defineProperty(" + thisPrefix + ", " + "'" + name + "', { get: function(){return " + staticName + ";}, " + "set: function(val){" + staticName + " = val;} });\n"; + staticDeclarations.push(declaration) + } + return staticDeclarations.join("") + } + return thisPrefix + "." + this.definitions.join("; " + thisPrefix + ".") + }; + + function transformClassField(statement) { + var attrAndType = attrAndTypeRegex.exec(statement); + var isStatic = attrAndType[1].indexOf("static") >= 0; + var definitions = statement.substring(attrAndType[0].length).split(/,\s*/g); + var defaultTypeValue = getDefaultValueForType(attrAndType[2]); + for (var i = 0; i < definitions.length; ++i) definitions[i] = transformVarDefinition(definitions[i], defaultTypeValue); + return new AstClassField(definitions, attrAndType[2], isStatic) + } + function AstConstructor(params, body) { + this.params = params; + this.body = body + } + AstConstructor.prototype.toString = function() { + var paramNames = appendToLookupTable({}, + this.params.getNames()); + var oldContext = replaceContext; + replaceContext = function(subject) { + return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject) + }; + var prefix = "function $constr_" + this.params.params.length + this.params.toString(); + var body = this.params.prependMethodArgs(this.body.toString()); + if (!/\$(superCstr|constr)\b/.test(body)) body = "{\n$superCstr();\n" + body.substring(1); + replaceContext = oldContext; + return prefix + body + "\n" + }; + + function transformConstructor(cstr) { + var m = (new RegExp(/"B(\d+)"\s*"A(\d+)"/)).exec(cstr); + var params = transformParams(atoms[m[1]]); + return new AstConstructor(params, transformStatementsBlock(atoms[m[2]])) + } + function AstInterfaceBody(name, interfacesNames, methodsNames, fields, innerClasses, misc) { + var i, l; + this.name = name; + this.interfacesNames = interfacesNames; + this.methodsNames = methodsNames; + this.fields = fields; + this.innerClasses = innerClasses; + this.misc = misc; + for (i = 0, l = fields.length; i < l; ++i) fields[i].owner = this + } + AstInterfaceBody.prototype.getMembers = function(classFields, classMethods, classInners) { + if (this.owner.base) this.owner.base.body.getMembers(classFields, classMethods, classInners); + var i, j, l, m; + for (i = 0, l = this.fields.length; i < l; ++i) { + var fieldNames = this.fields[i].getNames(); + for (j = 0, m = fieldNames.length; j < m; ++j) classFields[fieldNames[j]] = this.fields[i] + } + for (i = 0, l = this.methodsNames.length; i < l; ++i) { + var methodName = this.methodsNames[i]; + classMethods[methodName] = true + } + for (i = 0, l = this.innerClasses.length; i < l; ++i) { + var innerClass = this.innerClasses[i]; + classInners[innerClass.name] = innerClass + } + }; + AstInterfaceBody.prototype.toString = function() { + function getScopeLevel(p) { + var i = 0; + while (p) { + ++i; + p = p.scope + } + return i + } + var scopeLevel = getScopeLevel(this.owner); + var className = this.name; + var staticDefinitions = ""; + var metadata = ""; + var thisClassFields = {}, + thisClassMethods = {}, + thisClassInners = {}; + this.getMembers(thisClassFields, thisClassMethods, thisClassInners); + var i, l, j, m; + if (this.owner.interfaces) { + var resolvedInterfaces = [], + resolvedInterface; + for (i = 0, l = this.interfacesNames.length; i < l; ++i) { + if (!this.owner.interfaces[i]) continue; + resolvedInterface = replaceContext({ + name: this.interfacesNames[i] + }); + resolvedInterfaces.push(resolvedInterface); + staticDefinitions += "$p.extendInterfaceMembers(" + className + ", " + resolvedInterface + ");\n" + } + metadata += className + ".$interfaces = [" + resolvedInterfaces.join(", ") + "];\n" + } + metadata += className + ".$isInterface = true;\n"; + metadata += className + ".$methods = ['" + this.methodsNames.join("', '") + "'];\n"; + sortByWeight(this.innerClasses); + for (i = 0, l = this.innerClasses.length; i < l; ++i) { + var innerClass = this.innerClasses[i]; + if (innerClass.isStatic) staticDefinitions += className + "." + innerClass.name + " = " + innerClass + ";\n" + } + for (i = 0, l = this.fields.length; i < l; ++i) { + var field = this.fields[i]; + if (field.isStatic) staticDefinitions += className + "." + field.definitions.join(";\n" + className + ".") + ";\n" + } + return "(function() {\n" + "function " + className + "() { throw 'Unable to create the interface'; }\n" + staticDefinitions + metadata + "return " + className + ";\n" + "})()" + }; + transformInterfaceBody = function(body, name, baseInterfaces) { + var declarations = body.substring(1, body.length - 1); + declarations = extractClassesAndMethods(declarations); + declarations = extractConstructors(declarations, name); + var methodsNames = [], + classes = []; + declarations = declarations.replace(/"([DE])(\d+)"/g, function(all, type, index) { + if (type === "D") methodsNames.push(index); + else if (type === "E") classes.push(index); + return "" + }); + var fields = declarations.split(/;(?:\s*;)*/g); + var baseInterfaceNames; + var i, l; + if (baseInterfaces !== undef) baseInterfaceNames = baseInterfaces.replace(/^\s*extends\s+(.+?)\s*$/g, "$1").split(/\s*,\s*/g); + for (i = 0, l = methodsNames.length; i < l; ++i) { + var method = transformClassMethod(atoms[methodsNames[i]]); + methodsNames[i] = method.name + } + for (i = 0, l = fields.length - 1; i < l; ++i) { + var field = trimSpaces(fields[i]); + fields[i] = transformClassField(field.middle) + } + var tail = fields.pop(); + for (i = 0, l = classes.length; i < l; ++i) classes[i] = transformInnerClass(atoms[classes[i]]); + return new AstInterfaceBody(name, baseInterfaceNames, methodsNames, fields, classes, { + tail: tail + }) + }; + + function AstClassBody(name, baseClassName, interfacesNames, functions, methods, fields, cstrs, innerClasses, misc) { + var i, l; + this.name = name; + this.baseClassName = baseClassName; + this.interfacesNames = interfacesNames; + this.functions = functions; + this.methods = methods; + this.fields = fields; + this.cstrs = cstrs; + this.innerClasses = innerClasses; + this.misc = misc; + for (i = 0, l = fields.length; i < l; ++i) fields[i].owner = this + } + AstClassBody.prototype.getMembers = function(classFields, classMethods, classInners) { + if (this.owner.base) this.owner.base.body.getMembers(classFields, classMethods, classInners); + var i, j, l, m; + for (i = 0, l = this.fields.length; i < l; ++i) { + var fieldNames = this.fields[i].getNames(); + for (j = 0, m = fieldNames.length; j < m; ++j) classFields[fieldNames[j]] = this.fields[i] + } + for (i = 0, l = this.methods.length; i < l; ++i) { + var method = this.methods[i]; + classMethods[method.name] = method + } + for (i = 0, l = this.innerClasses.length; i < l; ++i) { + var innerClass = this.innerClasses[i]; + classInners[innerClass.name] = innerClass + } + }; + AstClassBody.prototype.toString = function() { + function getScopeLevel(p) { + var i = 0; + while (p) { + ++i; + p = p.scope + } + return i + } + var scopeLevel = getScopeLevel(this.owner); + var selfId = "$this_" + scopeLevel; + var className = this.name; + var result = "var " + selfId + " = this;\n"; + var staticDefinitions = ""; + var metadata = ""; + var thisClassFields = {}, + thisClassMethods = {}, + thisClassInners = {}; + this.getMembers(thisClassFields, thisClassMethods, thisClassInners); + var oldContext = replaceContext; + replaceContext = function(subject) { + var name = subject.name; + if (name === "this") return subject.callSign || !subject.member ? selfId + ".$self" : selfId; + if (thisClassFields.hasOwnProperty(name)) return thisClassFields[name].isStatic ? className + "." + name : selfId + "." + name; + if (thisClassInners.hasOwnProperty(name)) return selfId + "." + name; + if (thisClassMethods.hasOwnProperty(name)) return thisClassMethods[name].isStatic ? className + "." + name : selfId + ".$self." + name; + return oldContext(subject) + }; + var resolvedBaseClassName; + if (this.baseClassName) { + resolvedBaseClassName = oldContext({ + name: this.baseClassName + }); + result += "var $super = { $upcast: " + selfId + " };\n"; + result += "function $superCstr(){" + resolvedBaseClassName + ".apply($super,arguments);if(!('$self' in $super)) $p.extendClassChain($super)}\n"; + metadata += className + ".$base = " + resolvedBaseClassName + ";\n" + } else result += "function $superCstr(){$p.extendClassChain(" + selfId + ")}\n"; + if (this.owner.base) staticDefinitions += "$p.extendStaticMembers(" + className + ", " + resolvedBaseClassName + ");\n"; + var i, l, j, m; + if (this.owner.interfaces) { + var resolvedInterfaces = [], + resolvedInterface; + for (i = 0, l = this.interfacesNames.length; i < l; ++i) { + if (!this.owner.interfaces[i]) continue; + resolvedInterface = oldContext({ + name: this.interfacesNames[i] + }); + resolvedInterfaces.push(resolvedInterface); + staticDefinitions += "$p.extendInterfaceMembers(" + className + ", " + resolvedInterface + ");\n" + } + metadata += className + ".$interfaces = [" + resolvedInterfaces.join(", ") + "];\n" + } + if (this.functions.length > 0) result += this.functions.join("\n") + "\n"; + sortByWeight(this.innerClasses); + for (i = 0, l = this.innerClasses.length; i < l; ++i) { + var innerClass = this.innerClasses[i]; + if (innerClass.isStatic) { + staticDefinitions += className + "." + innerClass.name + " = " + innerClass + ";\n"; + result += selfId + "." + innerClass.name + " = " + className + "." + innerClass.name + ";\n" + } else result += selfId + "." + innerClass.name + " = " + innerClass + ";\n" + } + for (i = 0, l = this.fields.length; i < l; ++i) { + var field = this.fields[i]; + if (field.isStatic) { + staticDefinitions += className + "." + field.definitions.join(";\n" + className + ".") + ";\n"; + for (j = 0, m = field.definitions.length; j < m; ++j) { + var fieldName = field.definitions[j].name, + staticName = className + "." + fieldName; + result += "$p.defineProperty(" + selfId + ", '" + fieldName + "', {" + "get: function(){return " + staticName + "}, " + "set: function(val){" + staticName + " = val}});\n" + } + } else result += selfId + "." + field.definitions.join(";\n" + selfId + ".") + ";\n" + } + var methodOverloads = {}; + for (i = 0, l = this.methods.length; i < l; ++i) { + var method = this.methods[i]; + var overload = methodOverloads[method.name]; + var methodId = method.name + "$" + method.params.params.length; + var hasMethodArgs = !!method.params.methodArgsParam; + if (overload) { + ++overload; + methodId += "_" + overload + } else overload = 1; + method.methodId = methodId; + methodOverloads[method.name] = overload; + if (method.isStatic) { + staticDefinitions += method; + staticDefinitions += "$p.addMethod(" + className + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n"; + result += "$p.addMethod(" + selfId + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n" + } else { + result += method; + result += "$p.addMethod(" + selfId + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n" + } + } + result += trim(this.misc.tail); + if (this.cstrs.length > 0) result += this.cstrs.join("\n") + "\n"; + result += "function $constr() {\n"; + var cstrsIfs = []; + for (i = 0, l = this.cstrs.length; i < l; ++i) { + var paramsLength = this.cstrs[i].params.params.length; + var methodArgsPresent = !!this.cstrs[i].params.methodArgsParam; + cstrsIfs.push("if(arguments.length " + (methodArgsPresent ? ">=" : "===") + " " + paramsLength + ") { " + "$constr_" + paramsLength + ".apply(" + selfId + ", arguments); }") + } + if (cstrsIfs.length > 0) result += cstrsIfs.join(" else ") + " else "; + result += "$superCstr();\n}\n"; + result += "$constr.apply(null, arguments);\n"; + replaceContext = oldContext; + return "(function() {\n" + "function " + className + "() {\n" + result + "}\n" + staticDefinitions + metadata + "return " + className + ";\n" + "})()" + }; + transformClassBody = function(body, name, baseName, interfaces) { + var declarations = body.substring(1, body.length - 1); + declarations = extractClassesAndMethods(declarations); + declarations = extractConstructors(declarations, name); + var methods = [], + classes = [], + cstrs = [], + functions = []; + declarations = declarations.replace(/"([DEGH])(\d+)"/g, function(all, type, index) { + if (type === "D") methods.push(index); + else if (type === "E") classes.push(index); + else if (type === "H") functions.push(index); + else cstrs.push(index); + return "" + }); + var fields = declarations.replace(/^(?:\s*;)+/, "").split(/;(?:\s*;)*/g); + var baseClassName, interfacesNames; + var i; + if (baseName !== undef) baseClassName = baseName.replace(/^\s*extends\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)\s*$/g, "$1"); + if (interfaces !== undef) interfacesNames = interfaces.replace(/^\s*implements\s+(.+?)\s*$/g, "$1").split(/\s*,\s*/g); + for (i = 0; i < functions.length; ++i) functions[i] = transformFunction(atoms[functions[i]]); + for (i = 0; i < methods.length; ++i) methods[i] = transformClassMethod(atoms[methods[i]]); + for (i = 0; i < fields.length - 1; ++i) { + var field = trimSpaces(fields[i]); + fields[i] = transformClassField(field.middle) + } + var tail = fields.pop(); + for (i = 0; i < cstrs.length; ++i) cstrs[i] = transformConstructor(atoms[cstrs[i]]); + for (i = 0; i < classes.length; ++i) classes[i] = transformInnerClass(atoms[classes[i]]); + return new AstClassBody(name, baseClassName, interfacesNames, functions, methods, fields, cstrs, classes, { + tail: tail + }) + }; + + function AstInterface(name, body) { + this.name = name; + this.body = body; + body.owner = this + } + AstInterface.prototype.toString = function() { + return "var " + this.name + " = " + this.body + ";\n" + "$p." + this.name + " = " + this.name + ";\n" + }; + + function AstClass(name, body) { + this.name = name; + this.body = body; + body.owner = this + } + AstClass.prototype.toString = function() { + return "var " + this.name + " = " + this.body + ";\n" + "$p." + this.name + " = " + this.name + ";\n" + }; + + function transformGlobalClass(class_) { + var m = classesRegex.exec(class_); + classesRegex.lastIndex = 0; + var body = atoms[getAtomIndex(m[6])]; + var oldClassId = currentClassId, + newClassId = generateClassId(); + currentClassId = newClassId; + var globalClass; + if (m[2] === "interface") globalClass = new AstInterface(m[3], transformInterfaceBody(body, m[3], m[4])); + else globalClass = new AstClass(m[3], transformClassBody(body, m[3], m[4], m[5])); + appendClass(globalClass, newClassId, oldClassId); + currentClassId = oldClassId; + return globalClass + } + function AstMethod(name, params, body) { + this.name = name; + this.params = params; + this.body = body + } + AstMethod.prototype.toString = function() { + var paramNames = appendToLookupTable({}, + this.params.getNames()); + var oldContext = replaceContext; + replaceContext = function(subject) { + return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject) + }; + var body = this.params.prependMethodArgs(this.body.toString()); + var result = "function " + this.name + this.params + " " + body + "\n" + "$p." + this.name + " = " + this.name + ";"; + replaceContext = oldContext; + return result + }; + + function transformGlobalMethod(method) { + var m = methodsRegex.exec(method); + var result = methodsRegex.lastIndex = 0; + return new AstMethod(m[3], transformParams(atoms[getAtomIndex(m[4])]), transformStatementsBlock(atoms[getAtomIndex(m[6])])) + } + function preStatementsTransform(statements) { + var s = statements; + s = s.replace(/\b(catch\s*"B\d+"\s*"A\d+")(\s*catch\s*"B\d+"\s*"A\d+")+/g, "$1"); + return s + } + function AstForStatement(argument, misc) { + this.argument = argument; + this.misc = misc + } + AstForStatement.prototype.toString = function() { + return this.misc.prefix + this.argument.toString() + }; + + function AstCatchStatement(argument, misc) { + this.argument = argument; + this.misc = misc + } + AstCatchStatement.prototype.toString = function() { + return this.misc.prefix + this.argument.toString() + }; + + function AstPrefixStatement(name, argument, misc) { + this.name = name; + this.argument = argument; + this.misc = misc + } + AstPrefixStatement.prototype.toString = function() { + var result = this.misc.prefix; + if (this.argument !== undef) result += this.argument.toString(); + return result + }; + + function AstSwitchCase(expr) { + this.expr = expr + } + AstSwitchCase.prototype.toString = function() { + return "case " + this.expr + ":" + }; + + function AstLabel(label) { + this.label = label + } + AstLabel.prototype.toString = function() { + return this.label + }; + transformStatements = function(statements, transformMethod, transformClass) { + var nextStatement = new RegExp(/\b(catch|for|if|switch|while|with)\s*"B(\d+)"|\b(do|else|finally|return|throw|try|break|continue)\b|("[ADEH](\d+)")|\b(case)\s+([^:]+):|\b([A-Za-z_$][\w$]*\s*:)|(;)/g); + var res = []; + statements = preStatementsTransform(statements); + var lastIndex = 0, + m, space; + while ((m = nextStatement.exec(statements)) !== null) { + if (m[1] !== undef) { + var i = statements.lastIndexOf('"B', nextStatement.lastIndex); + var statementsPrefix = statements.substring(lastIndex, i); + if (m[1] === "for") res.push(new AstForStatement(transformForExpression(atoms[m[2]]), { + prefix: statementsPrefix + })); + else if (m[1] === "catch") res.push(new AstCatchStatement(transformParams(atoms[m[2]]), { + prefix: statementsPrefix + })); + else res.push(new AstPrefixStatement(m[1], transformExpression(atoms[m[2]]), { + prefix: statementsPrefix + })) + } else if (m[3] !== undef) res.push(new AstPrefixStatement(m[3], undef, { + prefix: statements.substring(lastIndex, nextStatement.lastIndex) + })); + else if (m[4] !== undef) { + space = statements.substring(lastIndex, nextStatement.lastIndex - m[4].length); + if (trim(space).length !== 0) continue; + res.push(space); + var kind = m[4].charAt(1), + atomIndex = m[5]; + if (kind === "D") res.push(transformMethod(atoms[atomIndex])); + else if (kind === "E") res.push(transformClass(atoms[atomIndex])); + else if (kind === "H") res.push(transformFunction(atoms[atomIndex])); + else res.push(transformStatementsBlock(atoms[atomIndex])) + } else if (m[6] !== undef) res.push(new AstSwitchCase(transformExpression(trim(m[7])))); + else if (m[8] !== undef) { + space = statements.substring(lastIndex, nextStatement.lastIndex - m[8].length); + if (trim(space).length !== 0) continue; + res.push(new AstLabel(statements.substring(lastIndex, nextStatement.lastIndex))) + } else { + var statement = trimSpaces(statements.substring(lastIndex, nextStatement.lastIndex - 1)); + res.push(statement.left); + res.push(transformStatement(statement.middle)); + res.push(statement.right + ";") + } + lastIndex = nextStatement.lastIndex + } + var statementsTail = trimSpaces(statements.substring(lastIndex)); + res.push(statementsTail.left); + if (statementsTail.middle !== "") { + res.push(transformStatement(statementsTail.middle)); + res.push(";" + statementsTail.right) + } + return res + }; + + function getLocalNames(statements) { + var localNames = []; + for (var i = 0, l = statements.length; i < l; ++i) { + var statement = statements[i]; + if (statement instanceof AstVar) localNames = localNames.concat(statement.getNames()); + else if (statement instanceof AstForStatement && statement.argument.initStatement instanceof AstVar) localNames = localNames.concat(statement.argument.initStatement.getNames()); + else if (statement instanceof AstInnerInterface || statement instanceof AstInnerClass || statement instanceof AstInterface || statement instanceof AstClass || statement instanceof AstMethod || statement instanceof AstFunction) localNames.push(statement.name) + } + return appendToLookupTable({}, + localNames) + } + function AstStatementsBlock(statements) { + this.statements = statements + } + AstStatementsBlock.prototype.toString = function() { + var localNames = getLocalNames(this.statements); + var oldContext = replaceContext; + if (!isLookupTableEmpty(localNames)) replaceContext = function(subject) { + return localNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject) + }; + var result = "{\n" + this.statements.join("") + "\n}"; + replaceContext = oldContext; + return result + }; + transformStatementsBlock = function(block) { + var content = trimSpaces(block.substring(1, block.length - 1)); + return new AstStatementsBlock(transformStatements(content.middle)) + }; + + function AstRoot(statements) { + this.statements = statements + } + AstRoot.prototype.toString = function() { + var classes = [], + otherStatements = [], + statement; + for (var i = 0, len = this.statements.length; i < len; ++i) { + statement = this.statements[i]; + if (statement instanceof AstClass || statement instanceof AstInterface) classes.push(statement); + else otherStatements.push(statement) + } + sortByWeight(classes); + var localNames = getLocalNames(this.statements); + replaceContext = function(subject) { + var name = subject.name; + if (localNames.hasOwnProperty(name)) return name; + if (globalMembers.hasOwnProperty(name) || PConstants.hasOwnProperty(name) || defaultScope.hasOwnProperty(name)) return "$p." + name; + return name + }; + var result = "// this code was autogenerated from PJS\n" + "(function($p) {\n" + classes.join("") + "\n" + otherStatements.join("") + "\n})"; + replaceContext = null; + return result + }; + transformMain = function() { + var statements = extractClassesAndMethods(atoms[0]); + statements = statements.replace(/\bimport\s+[^;]+;/g, ""); + return new AstRoot(transformStatements(statements, transformGlobalMethod, transformGlobalClass)) + }; + + function generateMetadata(ast) { + var globalScope = {}; + var id, class_; + for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) { + class_ = declaredClasses[id]; + var scopeId = class_.scopeId, + name = class_.name; + if (scopeId) { + var scope = declaredClasses[scopeId]; + class_.scope = scope; + if (scope.inScope === undef) scope.inScope = {}; + scope.inScope[name] = class_ + } else globalScope[name] = class_ + } + function findInScopes(class_, name) { + var parts = name.split("."); + var currentScope = class_.scope, + found; + while (currentScope) { + if (currentScope.hasOwnProperty(parts[0])) { + found = currentScope[parts[0]]; + break + } + currentScope = currentScope.scope + } + if (found === undef) found = globalScope[parts[0]]; + for (var i = 1, l = parts.length; i < l && found; ++i) found = found.inScope[parts[i]]; + return found + } + for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) { + class_ = declaredClasses[id]; + var baseClassName = class_.body.baseClassName; + if (baseClassName) { + var parent = findInScopes(class_, baseClassName); + if (parent) { + class_.base = parent; + if (!parent.derived) parent.derived = []; + parent.derived.push(class_) + } + } + var interfacesNames = class_.body.interfacesNames, + interfaces = [], + i, l; + if (interfacesNames && interfacesNames.length > 0) { + for (i = 0, l = interfacesNames.length; i < l; ++i) { + var interface_ = findInScopes(class_, interfacesNames[i]); + interfaces.push(interface_); + if (!interface_) continue; + if (!interface_.derived) interface_.derived = []; + interface_.derived.push(class_) + } + if (interfaces.length > 0) class_.interfaces = interfaces + } + } + } + function setWeight(ast) { + var queue = [], + tocheck = {}; + var id, scopeId, class_; + for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) { + class_ = declaredClasses[id]; + if (!class_.inScope && !class_.derived) { + queue.push(id); + class_.weight = 0 + } else { + var dependsOn = []; + if (class_.inScope) for (scopeId in class_.inScope) if (class_.inScope.hasOwnProperty(scopeId)) dependsOn.push(class_.inScope[scopeId]); + if (class_.derived) dependsOn = dependsOn.concat(class_.derived); + tocheck[id] = dependsOn + } + } + function removeDependentAndCheck(targetId, from) { + var dependsOn = tocheck[targetId]; + if (!dependsOn) return false; + var i = dependsOn.indexOf(from); + if (i < 0) return false; + dependsOn.splice(i, 1); + if (dependsOn.length > 0) return false; + delete tocheck[targetId]; + return true + } + while (queue.length > 0) { + id = queue.shift(); + class_ = declaredClasses[id]; + if (class_.scopeId && removeDependentAndCheck(class_.scopeId, class_)) { + queue.push(class_.scopeId); + declaredClasses[class_.scopeId].weight = class_.weight + 1 + } + if (class_.base && removeDependentAndCheck(class_.base.classId, class_)) { + queue.push(class_.base.classId); + class_.base.weight = class_.weight + 1 + } + if (class_.interfaces) { + var i, l; + for (i = 0, l = class_.interfaces.length; i < l; ++i) { + if (!class_.interfaces[i] || !removeDependentAndCheck(class_.interfaces[i].classId, class_)) continue; + queue.push(class_.interfaces[i].classId); + class_.interfaces[i].weight = class_.weight + 1 + } + } + } + } + var transformed = transformMain(); + generateMetadata(transformed); + setWeight(transformed); + var redendered = transformed.toString(); + redendered = redendered.replace(/\s*\n(?:[\t ]*\n)+/g, "\n\n"); + redendered = redendered.replace(/__x([0-9A-F]{4})/g, function(all, hexCode) { + return String.fromCharCode(parseInt(hexCode, 16)) + }); + return injectStrings(redendered, strings) + } + + function preprocessCode(aCode, sketch) { + var dm = (new RegExp(/\/\*\s*@pjs\s+((?:[^\*]|\*+[^\*\/])*)\*\//g)).exec(aCode); + if (dm && dm.length === 2) { + var jsonItems = [], + directives = dm.splice(1, 2)[0].replace(/\{([\s\S]*?)\}/g, function() { + return function(all, item) { + jsonItems.push(item); + return "{" + (jsonItems.length - 1) + "}" + } + }()).replace("\n", "").replace("\r", "").split(";"); + var clean = function(s) { + return s.replace(/^\s*["']?/, "").replace(/["']?\s*$/, "") + }; + for (var i = 0, dl = directives.length; i < dl; i++) { + var pair = directives[i].split("="); + if (pair && pair.length === 2) { + var key = clean(pair[0]), + value = clean(pair[1]), + list = []; + if (key === "preload") { + list = value.split(","); + for (var j = 0, jl = list.length; j < jl; j++) { + var imageName = clean(list[j]); + sketch.imageCache.add(imageName) + } + } else if (key === "font") { + list = value.split(","); + for (var x = 0, xl = list.length; x < xl; x++) { + var fontName = clean(list[x]), + index = /^\{(\d*?)\}$/.exec(fontName); + PFont.preloading.add(index ? JSON.parse("{" + jsonItems[index[1]] + "}") : fontName) + } + } else if (key === "pauseOnBlur") sketch.options.pauseOnBlur = value === "true"; + else if (key === "globalKeyEvents") sketch.options.globalKeyEvents = value === "true"; + else if (key.substring(0, 6) === "param-") sketch.params[key.substring(6)] = value; + else sketch.options[key] = value + } + } + } + return aCode + } + Processing.compile = function(pdeCode) { + var sketch = new Processing.Sketch; + var code = preprocessCode(pdeCode, sketch); + var compiledPde = parseProcessing(code); + sketch.sourceCode = compiledPde; + return sketch + }; + var tinylogLite = function() { + var tinylogLite = {}, + undef = "undefined", + func = "function", + False = !1, + True = !0, + logLimit = 512, + log = "log"; + if (typeof tinylog !== undef && typeof tinylog[log] === func) tinylogLite[log] = tinylog[log]; + else if (typeof document !== undef && !document.fake)(function() { + var doc = document, + $div = "div", + $style = "style", + $title = "title", + containerStyles = { + zIndex: 1E4, + position: "fixed", + bottom: "0px", + width: "100%", + height: "15%", + fontFamily: "sans-serif", + color: "#ccc", + backgroundColor: "black" + }, + outputStyles = { + position: "relative", + fontFamily: "monospace", + overflow: "auto", + height: "100%", + paddingTop: "5px" + }, + resizerStyles = { + height: "5px", + marginTop: "-5px", + cursor: "n-resize", + backgroundColor: "darkgrey" + }, + closeButtonStyles = { + position: "absolute", + top: "5px", + right: "20px", + color: "#111", + MozBorderRadius: "4px", + webkitBorderRadius: "4px", + borderRadius: "4px", + cursor: "pointer", + fontWeight: "normal", + textAlign: "center", + padding: "3px 5px", + backgroundColor: "#333", + fontSize: "12px" + }, + entryStyles = { + minHeight: "16px" + }, + entryTextStyles = { + fontSize: "12px", + margin: "0 8px 0 8px", + maxWidth: "100%", + whiteSpace: "pre-wrap", + overflow: "auto" + }, + view = doc.defaultView, + docElem = doc.documentElement, + docElemStyle = docElem[$style], + setStyles = function() { + var i = arguments.length, + elemStyle, styles, style; + while (i--) { + styles = arguments[i--]; + elemStyle = arguments[i][$style]; + for (style in styles) if (styles.hasOwnProperty(style)) elemStyle[style] = styles[style] + } + }, + observer = function(obj, event, handler) { + if (obj.addEventListener) obj.addEventListener(event, handler, False); + else if (obj.attachEvent) obj.attachEvent("on" + event, handler); + return [obj, event, handler] + }, + unobserve = function(obj, event, handler) { + if (obj.removeEventListener) obj.removeEventListener(event, handler, False); + else if (obj.detachEvent) obj.detachEvent("on" + event, handler) + }, + clearChildren = function(node) { + var children = node.childNodes, + child = children.length; + while (child--) node.removeChild(children.item(0)) + }, + append = function(to, elem) { + return to.appendChild(elem) + }, + createElement = function(localName) { + return doc.createElement(localName) + }, + createTextNode = function(text) { + return doc.createTextNode(text) + }, + createLog = tinylogLite[log] = function(message) { + var uninit, originalPadding = docElemStyle.paddingBottom, + container = createElement($div), + containerStyle = container[$style], + resizer = append(container, createElement($div)), + output = append(container, createElement($div)), + closeButton = append(container, createElement($div)), + resizingLog = False, + previousHeight = False, + previousScrollTop = False, + messages = 0, + updateSafetyMargin = function() { + docElemStyle.paddingBottom = container.clientHeight + "px" + }, + setContainerHeight = function(height) { + var viewHeight = view.innerHeight, + resizerHeight = resizer.clientHeight; + if (height < 0) height = 0; + else if (height + resizerHeight > viewHeight) height = viewHeight - resizerHeight; + containerStyle.height = height / viewHeight * 100 + "%"; + updateSafetyMargin() + }, + observers = [observer(doc, "mousemove", function(evt) { + if (resizingLog) { + setContainerHeight(view.innerHeight - evt.clientY); + output.scrollTop = previousScrollTop + } + }), observer(doc, "mouseup", function() { + if (resizingLog) resizingLog = previousScrollTop = False + }), observer(resizer, "dblclick", function(evt) { + evt.preventDefault(); + if (previousHeight) { + setContainerHeight(previousHeight); + previousHeight = False + } else { + previousHeight = container.clientHeight; + containerStyle.height = "0px" + } + }), observer(resizer, "mousedown", function(evt) { + evt.preventDefault(); + resizingLog = True; + previousScrollTop = output.scrollTop + }), observer(resizer, "contextmenu", function() { + resizingLog = False + }), observer(closeButton, "click", function() { + uninit() + })]; + uninit = function() { + var i = observers.length; + while (i--) unobserve.apply(tinylogLite, observers[i]); + docElem.removeChild(container); + docElemStyle.paddingBottom = originalPadding; + clearChildren(output); + clearChildren(container); + tinylogLite[log] = createLog + }; + setStyles(container, containerStyles, output, outputStyles, resizer, resizerStyles, closeButton, closeButtonStyles); + closeButton[$title] = "Close Log"; + append(closeButton, createTextNode("\u2716")); + resizer[$title] = "Double-click to toggle log minimization"; + docElem.insertBefore(container, docElem.firstChild); + tinylogLite[log] = function(message) { + if (messages === logLimit) output.removeChild(output.firstChild); + else messages++; + var entry = append(output, createElement($div)), + entryText = append(entry, createElement($div)); + entry[$title] = (new Date).toLocaleTimeString(); + setStyles(entry, entryStyles, entryText, entryTextStyles); + append(entryText, createTextNode(message)); + output.scrollTop = output.scrollHeight + }; + tinylogLite[log](message); + updateSafetyMargin() + } + })(); + else if (typeof print === func) tinylogLite[log] = print; + return tinylogLite + }(); + Processing.logger = tinylogLite; + Processing.version = "1.4.1"; + Processing.lib = {}; + Processing.registerLibrary = function(name, desc) { + Processing.lib[name] = desc; + if (desc.hasOwnProperty("init")) desc.init(defaultScope) + }; + Processing.instances = processingInstances; + Processing.getInstanceById = function(name) { + return processingInstances[processingInstanceIds[name]] + }; + Processing.Sketch = function(attachFunction) { + this.attachFunction = attachFunction; + this.options = { + pauseOnBlur: false, + globalKeyEvents: false + }; + this.onLoad = nop; + this.onSetup = nop; + this.onPause = nop; + this.onLoop = nop; + this.onFrameStart = nop; + this.onFrameEnd = nop; + this.onExit = nop; + this.params = {}; + this.imageCache = { + pending: 0, + images: {}, + operaCache: {}, + add: function(href, img) { + if (this.images[href]) return; + if (!isDOMPresent) this.images[href] = null; + if (!img) { + img = new Image; + img.onload = function(owner) { + return function() { + owner.pending-- + } + }(this); + this.pending++; + img.src = href + } + this.images[href] = img; + if (window.opera) { + var div = document.createElement("div"); + div.appendChild(img); + div.style.position = "absolute"; + div.style.opacity = 0; + div.style.width = "1px"; + div.style.height = "1px"; + if (!this.operaCache[href]) { + document.body.appendChild(div); + this.operaCache[href] = div + } + } + } + }; + this.sourceCode = undefined; + this.attach = function(processing) { + if (typeof this.attachFunction === "function") this.attachFunction(processing); + else if (this.sourceCode) { + var func = (new Function("return (" + this.sourceCode + ");"))(); + func(processing); + this.attachFunction = func + } else throw "Unable to attach sketch to the processing instance"; + }; + this.toString = function() { + var i; + var code = "((function(Sketch) {\n"; + code += "var sketch = new Sketch(\n" + this.sourceCode + ");\n"; + for (i in this.options) if (this.options.hasOwnProperty(i)) { + var value = this.options[i]; + code += "sketch.options." + i + " = " + (typeof value === "string" ? '"' + value + '"' : "" + value) + ";\n" + } + for (i in this.imageCache) if (this.options.hasOwnProperty(i)) code += 'sketch.imageCache.add("' + i + '");\n'; + code += "return sketch;\n})(Processing.Sketch))"; + return code + } + }; + var loadSketchFromSources = function(canvas, sources) { + var code = [], + errors = [], + sourcesCount = sources.length, + loaded = 0; + + function ajaxAsync(url, callback) { + var xhr = new XMLHttpRequest; + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + var error; + if (xhr.status !== 200 && xhr.status !== 0) error = "Invalid XHR status " + xhr.status; + else if (xhr.responseText === "") if ("withCredentials" in new XMLHttpRequest && (new XMLHttpRequest).withCredentials === false && window.location.protocol === "file:") error = "XMLHttpRequest failure, possibly due to a same-origin policy violation. You can try loading this page in another browser, or load it from http://localhost using a local webserver. See the Processing.js README for a more detailed explanation of this problem and solutions."; + else error = "File is empty."; + callback(xhr.responseText, error) + } + }; + xhr.open("GET", url, true); + if (xhr.overrideMimeType) xhr.overrideMimeType("application/json"); + xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT"); + xhr.send(null) + } + function loadBlock(index, filename) { + function callback(block, error) { + code[index] = block; + ++loaded; + if (error) errors.push(filename + " ==> " + error); + if (loaded === sourcesCount) if (errors.length === 0) try { + return new Processing(canvas, code.join("\n")) + } catch(e) { + throw "Processing.js: Unable to execute pjs sketch: " + e; + } else throw "Processing.js: Unable to load pjs sketch files: " + errors.join("\n"); + } + if (filename.charAt(0) === "#") { + var scriptElement = document.getElementById(filename.substring(1)); + if (scriptElement) callback(scriptElement.text || scriptElement.textContent); + else callback("", "Unable to load pjs sketch: element with id '" + filename.substring(1) + "' was not found"); + return + } + ajaxAsync(filename, callback) + } + for (var i = 0; i < sourcesCount; ++i) loadBlock(i, sources[i]) + }; + var init = function() { + document.removeEventListener("DOMContentLoaded", init, false); + processingInstances = []; + var canvas = document.getElementsByTagName("canvas"), + filenames; + for (var i = 0, l = canvas.length; i < l; i++) { + var processingSources = canvas[i].getAttribute("data-processing-sources"); + if (processingSources === null) { + processingSources = canvas[i].getAttribute("data-src"); + if (processingSources === null) processingSources = canvas[i].getAttribute("datasrc") + } + if (processingSources) { + filenames = processingSources.split(/\s+/g); + for (var j = 0; j < filenames.length;) if (filenames[j]) j++; + else filenames.splice(j, 1); + loadSketchFromSources(canvas[i], filenames) + } + } + var s, last, source, instance, nodelist = document.getElementsByTagName("script"), + scripts = []; + for (s = nodelist.length - 1; s >= 0; s--) scripts.push(nodelist[s]); + for (s = 0, last = scripts.length; s < last; s++) { + var script = scripts[s]; + if (!script.getAttribute) continue; + var type = script.getAttribute("type"); + if (type && (type.toLowerCase() === "text/processing" || type.toLowerCase() === "application/processing")) { + var target = script.getAttribute("data-processing-target"); + canvas = undef; + if (target) canvas = document.getElementById(target); + else { + var nextSibling = script.nextSibling; + while (nextSibling && nextSibling.nodeType !== 1) nextSibling = nextSibling.nextSibling; + if (nextSibling && nextSibling.nodeName.toLowerCase() === "canvas") canvas = nextSibling + } + if (canvas) { + if (script.getAttribute("src")) { + filenames = script.getAttribute("src").split(/\s+/); + loadSketchFromSources(canvas, filenames); + continue + } + source = script.textContent || script.text; + instance = new Processing(canvas, source) + } + } + } + }; + Processing.reload = function() { + if (processingInstances.length > 0) for (var i = processingInstances.length - 1; i >= 0; i--) if (processingInstances[i]) processingInstances[i].exit(); + init() + }; + Processing.loadSketchFromSources = loadSketchFromSources; + Processing.disableInit = function() { + if (isDOMPresent) document.removeEventListener("DOMContentLoaded", init, false) + }; + if (isDOMPresent) { + window["Processing"] = Processing; + document.addEventListener("DOMContentLoaded", init, false) + } else this.Processing = Processing +})(window, window.document, Math); + diff --git a/CodeToAccompany9781430244646/ch04/bezierEllipse/template/template.html b/CodeToAccompany9781430244646/ch04/bezierEllipse/template/template.html new file mode 100644 index 0000000..91bf925 --- /dev/null +++ b/CodeToAccompany9781430244646/ch04/bezierEllipse/template/template.html @@ -0,0 +1,73 @@ + + + + @@sketch@@ : Built with Processing and Processing.js + + + + + + + @@scripts@@ + + +
+
+ +

Your browser does not support the canvas tag.

+ +
+ +
+

@@sketch@@

+

@@description@@

+

Source code: @@source@@

+

+ Built with Processing + and Processing.js +

+
+ + diff --git a/CodeToAccompany9781430244646/ch04/bezierEllipse/web-export/bezierEllipse.pde b/CodeToAccompany9781430244646/ch04/bezierEllipse/web-export/bezierEllipse.pde new file mode 100644 index 0000000..6d3e803 --- /dev/null +++ b/CodeToAccompany9781430244646/ch04/bezierEllipse/web-export/bezierEllipse.pde @@ -0,0 +1,65 @@ +// Bezier Ellipse Example +// requires 4 vertices + +void setup() { + size(400, 400); + background(255); + translate(width/2, height/2); + bezierEllipse(4, width*.375, 4); +} + +void bezierEllipse(int pts, float radius, float handleRadius) { + float theta = 0; + float cx1 = 0, cy1 = 0; + float cx2 = 0, cy2 = 0; + float ax = 0, ay = 0; + float rot = TWO_PI/pts; + float controlTheta1 = rot/3.0; + float controlTheta2 = controlTheta1*2.0; + float controlRadius = radius/cos(controlTheta1); + + beginShape(); + for (int i=0; i + + + bezierEllipse : Built with Processing and Processing.js + + + + + + + + + + +
+
+ +

Your browser does not support the canvas tag.

+ +
+ +
+

bezierEllipse

+

+

Source code: bezierEllipse

+

+ Built with Processing + and Processing.js +

+
+ + diff --git a/CodeToAccompany9781430244646/ch04/bezierEllipse/web-export/processing.js b/CodeToAccompany9781430244646/ch04/bezierEllipse/web-export/processing.js new file mode 100644 index 0000000..d9b41d7 --- /dev/null +++ b/CodeToAccompany9781430244646/ch04/bezierEllipse/web-export/processing.js @@ -0,0 +1,10203 @@ +/*** + + P R O C E S S I N G . J S - 1.4.1 + 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 + } + } + } + if (document.documentMode >= 9 && !document.doctype) throw "The doctype directive is missing. The recommended doctype in Internet Explorer is the HTML5 doctype: "; + 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(a) { + var array; + if (a instanceof ArrayList) array = a.toArray(); + else { + array = []; + if (typeof a === "number") array.length = a > 0 ? a : 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.lastIndexOf = function(item) { + for (var i = array.length - 1; i >= 0; --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.removeAll = function(c) { + var i, x, item, newList = new ArrayList; + newList.addAll(this); + this.clear(); + for (i = 0, x = 0; i < newList.size(); i++) { + item = newList.get(i); + if (!c.contains(item)) this.add(x++, item) + } + if (this.size() < newList.size()) 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; + var currentItem; + + 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() { + currentItem = conversion(buckets[bucketIndex][itemIndex]); + findNext(); + return currentItem + }; + this.remove = function() { + if (currentItem !== undef) { + removeItem(currentItem); + --itemIndex; + findNext() + } + }; + 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 overloadBaseClassFunction(object, name, basefn) { + if (!object.hasOwnProperty(name) || typeof object[name] !== "function") { + object[name] = basefn; + return + } + var fn = object[name]; + if ("$overloads" in fn) { + fn.$defaultOverload = basefn; + return + } + if (! ("$overloads" in basefn) && fn.length === basefn.length) return; + var overloads, defaultOverload; + if ("$overloads" in basefn) { + overloads = basefn.$overloads.slice(0); + overloads[fn.length] = fn; + defaultOverload = basefn.$defaultOverload + } else { + overloads = []; + overloads[basefn.length] = basefn; + overloads[fn.length] = fn; + defaultOverload = fn + } + var hubfn = function() { + var fn = hubfn.$overloads[arguments.length] || ("$methodArgsIndex" in hubfn && arguments.length > hubfn.$methodArgsIndex ? hubfn.$overloads[hubfn.$methodArgsIndex] : null) || hubfn.$defaultOverload; + return fn.apply(this, arguments) + }; + hubfn.$overloads = overloads; + if ("$methodArgsIndex" in basefn) hubfn.$methodArgsIndex = basefn.$methodArgsIndex; + hubfn.$defaultOverload = defaultOverload; + hubfn.name = name; + object[name] = hubfn + } + 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") overloadBaseClassFunction(subClass, propertyName, baseClass[propertyName]); + else if (propertyName.charAt(0) !== "$" && !(propertyName in subClass)) properties.push(propertyName); + while (properties.length > 0) extendGetterSetter(properties.shift()); + subClass.$super = baseClass + } + 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, hasMethodArgs) { + var existingfn = object[name]; + if (existingfn || hasMethodArgs) { + var args = fn.length; + if ("$overloads" in existingfn) existingfn.$overloads[args] = fn; + else { + var hubfn = function() { + var fn = hubfn.$overloads[arguments.length] || ("$methodArgsIndex" in hubfn && arguments.length > hubfn.$methodArgsIndex ? hubfn.$overloads[hubfn.$methodArgsIndex] : null) || hubfn.$defaultOverload; + return fn.apply(this, arguments) + }; + var overloads = []; + if (existingfn) overloads[existingfn.length] = existingfn; + overloads[args] = fn; + hubfn.$overloads = overloads; + hubfn.$defaultOverload = existingfn || fn; + if (hasMethodArgs) hubfn.$methodArgsIndex = args; + hubfn.name = name; + object[name] = hubfn + } + } else object[name] = fn + }; + + function isNumericalJavaType(type) { + if (typeof type !== "string") return false; + return ["byte", "int", "char", "color", "float", "long", "double"].indexOf(type) !== -1 + } + defaultScope.createJavaArray = function(type, bounds) { + var result = null, + defaultValue = null; + if (typeof type === "string") if (type === "boolean") defaultValue = false; + else if (isNumericalJavaType(type)) defaultValue = 0; + 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] = defaultValue + } 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 + } + }); + defaultScope.defineProperty(defaultScope, "online", { + get: function() { + return true + } + }); + 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; + 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); + if (pfont.caching) return ctx + } + 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 = computeFontMetrics(this); + this.css = this.getCSSDefinition(); + if (this.context2d) this.context2d.font = this.css + } + PFont.prototype.caching = true; + 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.prototype.measureTextWidthFallback = function(string) { + var canvas = document.createElement("canvas"), + ctx = canvas.getContext("2d"); + ctx.font = this.css; + return ctx.measureText(string).width + }; + PFont.PFontCache = { + length: 0 + }; + PFont.get = function(fontName, fontSize) { + fontSize = (fontSize * 10 + 0.5 | 0) / 10; + var cache = PFont.PFontCache, + idx = fontName + "/" + fontSize; + if (!cache[idx]) { + cache[idx] = new PFont(fontName, fontSize); + cache.length++; + if (cache.length === 50) { + PFont.prototype.measureTextWidth = PFont.prototype.measureTextWidthFallback; + PFont.prototype.caching = false; + var entry; + for (entry in cache) if (entry !== "length") cache[entry].context2d = null; + return new PFont(fontName, fontSize) + } + if (cache.length === 400) { + PFont.PFontCache = {}; + PFont.get = PFont.getFallback; + return new PFont(fontName, fontSize) + } + } + return cache[idx] + }; + PFont.getFallback = function(fontName, fontSize) { + return new PFont(fontName, fontSize) + }; + 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 vertexShaderSrcUnlitShape = "varying vec4 vFrontColor;" + "attribute vec3 aVertex;" + "attribute vec4 aColor;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform float uPointSize;" + "void main(void) {" + " vFrontColor = aColor;" + " gl_PointSize = uPointSize;" + " gl_Position = uProjection * uView * vec4(aVertex, 1.0);" + "}"; + var fragmentShaderSrcUnlitShape = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 vFrontColor;" + "uniform bool uSmooth;" + "void main(void){" + " if(uSmooth == true){" + " float dist = distance(gl_PointCoord, vec2(0.5));" + " if(dist > 0.5){" + " discard;" + " }" + " }" + " gl_FragColor = vFrontColor;" + "}"; + var vertexShaderSrc2D = "varying vec4 vFrontColor;" + "attribute vec3 aVertex;" + "attribute vec2 aTextureCoord;" + "uniform vec4 uColor;" + "uniform mat4 uModel;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform float uPointSize;" + "varying vec2 vTextureCoord;" + "void main(void) {" + " gl_PointSize = uPointSize;" + " vFrontColor = uColor;" + " gl_Position = uProjection * uView * uModel * vec4(aVertex, 1.0);" + " vTextureCoord = aTextureCoord;" + "}"; + var fragmentShaderSrc2D = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 vFrontColor;" + "varying vec2 vTextureCoord;" + "uniform sampler2D uSampler;" + "uniform int uIsDrawingText;" + "uniform bool uSmooth;" + "void main(void){" + " if(uSmooth == true){" + " float dist = distance(gl_PointCoord, vec2(0.5));" + " if(dist > 0.5){" + " discard;" + " }" + " }" + " if(uIsDrawingText == 1){" + " float alpha = texture2D(uSampler, vTextureCoord).a;" + " gl_FragColor = vec4(vFrontColor.rgb * alpha, alpha);" + " }" + " else{" + " gl_FragColor = vFrontColor;" + " }" + "}"; + var webglMaxTempsWorkaround = /Windows/.test(navigator.userAgent); + var vertexShaderSrc3D = "varying vec4 vFrontColor;" + "attribute vec3 aVertex;" + "attribute vec3 aNormal;" + "attribute vec4 aColor;" + "attribute vec2 aTexture;" + "varying vec2 vTexture;" + "uniform vec4 uColor;" + "uniform bool uUsingMat;" + "uniform vec3 uSpecular;" + "uniform vec3 uMaterialEmissive;" + "uniform vec3 uMaterialAmbient;" + "uniform vec3 uMaterialSpecular;" + "uniform float uShininess;" + "uniform mat4 uModel;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform mat4 uNormalTransform;" + "uniform int uLightCount;" + "uniform vec3 uFalloff;" + "struct Light {" + " int type;" + " vec3 color;" + " vec3 position;" + " vec3 direction;" + " float angle;" + " vec3 halfVector;" + " float concentration;" + "};" + "uniform Light uLights0;" + "uniform Light uLights1;" + "uniform Light uLights2;" + "uniform Light uLights3;" + "uniform Light uLights4;" + "uniform Light uLights5;" + "uniform Light uLights6;" + "uniform Light uLights7;" + "Light getLight(int index){" + " if(index == 0) return uLights0;" + " if(index == 1) return uLights1;" + " if(index == 2) return uLights2;" + " if(index == 3) return uLights3;" + " if(index == 4) return uLights4;" + " if(index == 5) return uLights5;" + " if(index == 6) return uLights6;" + " return uLights7;" + "}" + "void AmbientLight( inout vec3 totalAmbient, in vec3 ecPos, in Light light ) {" + " float d = length( light.position - ecPos );" + " float attenuation = 1.0 / ( uFalloff[0] + ( uFalloff[1] * d ) + ( uFalloff[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, uShininess );" + " }" + " col += light.color * nDotVP;" + " spec += uSpecular * 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 / ( uFalloff[0] + ( uFalloff[1] * d ) + ( uFalloff[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, uShininess );" + " }" + " spec += uSpecular * 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 = 0.0;" + " vec3 VP = light.position - ecPos;" + " vec3 ldir = normalize( -light.direction );" + " float d = length( VP );" + " VP = normalize( VP );" + " float attenuation = 1.0 / ( uFalloff[0] + ( uFalloff[1] * d ) + ( uFalloff[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 = pow( nDotHV, uShininess );" + " }" + " spec += uSpecular * powerFactor * attenuation;" + " col += light.color * nDotVP * attenuation;" + "}" + "void main(void) {" + " vec3 finalAmbient = vec3( 0.0 );" + " vec3 finalDiffuse = vec3( 0.0 );" + " vec3 finalSpecular = vec3( 0.0 );" + " vec4 col = uColor;" + " if ( uColor[0] == -1.0 ){" + " col = aColor;" + " }" + " vec3 norm = normalize(vec3( uNormalTransform * vec4( aNormal, 0.0 ) ));" + " vec4 ecPos4 = uView * uModel * vec4(aVertex, 1.0);" + " vec3 ecPos = (vec3(ecPos4))/ecPos4.w;" + " if( uLightCount == 0 ) {" + " vFrontColor = col + vec4(uMaterialSpecular, 1.0);" + " }" + " else {" + " for( int i = 0; i < 8; i++ ) {" + " Light l = getLight(i);" + " if( i >= uLightCount ){" + " 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( uUsingMat == false ) {" + " vFrontColor = vec4(" + " vec3( col ) * finalAmbient +" + " vec3( col ) * finalDiffuse +" + " vec3( col ) * finalSpecular," + " col[3] );" + " }" + " else{" + " vFrontColor = vec4( " + " uMaterialEmissive + " + " (vec3(col) * uMaterialAmbient * finalAmbient ) + " + " (vec3(col) * finalDiffuse) + " + " (uMaterialSpecular * finalSpecular), " + " col[3] );" + " }" + " }" + " vTexture.xy = aTexture.xy;" + " gl_Position = uProjection * uView * uModel * vec4( aVertex, 1.0 );" + "}"; + var fragmentShaderSrc3D = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 vFrontColor;" + "uniform sampler2D uSampler;" + "uniform bool uUsingTexture;" + "varying vec2 vTexture;" + "void main(void){" + " if( uUsingTexture ){" + " gl_FragColor = vec4(texture2D(uSampler, vTexture.xy)) * vFrontColor;" + " }" + " else{" + " gl_FragColor = vFrontColor;" + " }" + "}"; + + 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(renderContext) { + renderContext = renderContext || p; + if (this.visible) { + this.pre(renderContext); + this.drawImpl(renderContext); + this.post(renderContext) + } + }, + drawImpl: function(renderContext) { + if (this.family === 0) this.drawGroup(renderContext); + else if (this.family === 1) this.drawPrimitive(renderContext); + else if (this.family === 3) this.drawGeometry(renderContext); + else if (this.family === 21) this.drawPath(renderContext) + }, + drawPath: function(renderContext) { + var i, j; + if (this.vertices.length === 0) return; + renderContext.beginShape(); + if (this.vertexCodes.length === 0) if (this.vertices[0].length === 2) for (i = 0, j = this.vertices.length; i < j; i++) renderContext.vertex(this.vertices[i][0], this.vertices[i][1]); + else for (i = 0, j = this.vertices.length; i < j; i++) renderContext.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) { + renderContext.vertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index]["moveTo"]); + renderContext.breakShape = false; + index++ + } else if (this.vertexCodes[i] === 1) { + renderContext.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) { + renderContext.curveVertex(this.vertices[index][0], this.vertices[index][1]); + index++ + } else { + if (this.vertexCodes[i] === 3) renderContext.breakShape = true + } else for (i = 0, j = this.vertexCodes.length; i < j; i++) if (this.vertexCodes[i] === 0) { + renderContext.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; + renderContext.breakShape = false + } else if (this.vertexCodes[i] === 1) { + renderContext.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) { + renderContext.curveVertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index][2]); + index++ + } else if (this.vertexCodes[i] === 3) renderContext.breakShape = true + } + renderContext.endShape(this.close ? 2 : 1) + }, + drawGeometry: function(renderContext) { + var i, j; + renderContext.beginShape(this.kind); + if (this.style) for (i = 0, j = this.vertices.length; i < j; i++) renderContext.vertex(this.vertices[i]); + else for (i = 0, j = this.vertices.length; i < j; i++) { + var vert = this.vertices[i]; + if (vert[2] === 0) renderContext.vertex(vert[0], vert[1]); + else renderContext.vertex(vert[0], vert[1], vert[2]) + } + renderContext.endShape() + }, + drawGroup: function(renderContext) { + for (var i = 0, j = this.children.length; i < j; i++) this.children[i].draw(renderContext) + }, + drawPrimitive: function(renderContext) { + if (this.kind === 2) renderContext.point(this.params[0], this.params[1]); + else if (this.kind === 4) if (this.params.length === 4) renderContext.line(this.params[0], this.params[1], this.params[2], this.params[3]); + else renderContext.line(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]); + else if (this.kind === 8) renderContext.triangle(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]); + else if (this.kind === 16) renderContext.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) { + var imMode = imageModeConvert; + renderContext.imageMode(0); + renderContext.image(this.image, this.params[0], this.params[1], this.params[2], this.params[3]); + imageModeConvert = imMode + } else { + var rcMode = curRectMode; + renderContext.rectMode(0); + renderContext.rect(this.params[0], this.params[1], this.params[2], this.params[3]); + curRectMode = rcMode + } else if (this.kind === 31) { + var elMode = curEllipseMode; + renderContext.ellipseMode(0); + renderContext.ellipse(this.params[0], this.params[1], this.params[2], this.params[3]); + curEllipseMode = elMode + } else if (this.kind === 32) { + var eMode = curEllipseMode; + renderContext.ellipseMode(0); + renderContext.arc(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]); + curEllipseMode = eMode + } else if (this.kind === 41) if (this.params.length === 1) renderContext.box(this.params[0]); + else renderContext.box(this.params[0], this.params[1], this.params[2]); + else if (this.kind === 40) renderContext.sphere(this.params[0]) + }, + pre: function(renderContext) { + if (this.matrix) { + renderContext.pushMatrix(); + renderContext.transform(this.matrix) + } + if (this.style) { + renderContext.pushStyle(); + this.styles(renderContext) + } + }, + post: function(renderContext) { + if (this.matrix) renderContext.popMatrix(); + if (this.style) renderContext.popStyle() + }, + styles: function(renderContext) { + if (this.stroke) { + renderContext.stroke(this.strokeColor); + renderContext.strokeWeight(this.strokeWeight); + renderContext.strokeCap(this.strokeCap); + renderContext.strokeJoin(this.strokeJoin) + } else renderContext.noStroke(); + if (this.fill) renderContext.fill(this.fillColor); + else renderContext.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 , it's <" + this.element.getName() + ">"; + } else if (arguments.length === 2) if (typeof arguments[1] === "string") { + if (arguments[1].indexOf(".svg") > -1) { + this.element = new p.XMLElement(p, arguments[1]); + this.vertexCodes = []; + this.vertices = []; + this.opacity = 1; + this.stroke = false; + this.strokeColor = 4278190080; + this.strokeWeight = 1; + this.strokeCap = 'butt'; + this.strokeJoin = 'miter'; + this.strokeGradient = ""; + this.strokeGradientPaint = ""; + this.strokeName = ""; + this.strokeOpacity = 1; + this.fill = true; + this.fillColor = 4278190080; + this.fillGradient = null; + this.fillGradientPaint = null; + this.fillOpacity = 1 + } + } else if (arguments[0]) { + this.element = arguments[1]; + this.vertexCodes = arguments[0].vertexCodes.slice(); + this.vertices = arguments[0].vertices.slice(); + this.stroke = arguments[0].stroke; + this.strokeColor = arguments[0].strokeColor; + this.strokeWeight = arguments[0].strokeWeight; + this.strokeCap = arguments[0].strokeCap; + this.strokeJoin = arguments[0].strokeJoin; + this.strokeGradient = arguments[0].strokeGradient; + this.strokeGradientPaint = arguments[0].strokeGradientPaint; + this.strokeName = arguments[0].strokeName; + this.fill = arguments[0].fill; + this.fillColor = arguments[0].fillColor; + this.fillGradient = arguments[0].fillGradient; + this.fillGradientPaint = arguments[0].fillGradientPaint; + this.fillName = arguments[0].fillName; + this.strokeOpacity = arguments[0].strokeOpacity; + this.fillOpacity = arguments[0].fillOpacity; + this.opacity = arguments[0].opacity + } + this.name = this.element.getStringAttribute("id"); + var displayStr = this.element.getStringAttribute("display", "inline"); + this.visible = displayStr !== "none"; + var str = this.element.getAttribute("transform"); + if (str) this.matrix = this.parseMatrix(str); + var viewBoxStr = this.element.getStringAttribute("viewBox"); + if (viewBoxStr !== null) { + var viewBox = viewBoxStr.split(" "); + this.width = viewBox[2]; + this.height = viewBox[3] + } + var unitWidth = this.element.getStringAttribute("width"); + var unitHeight = this.element.getStringAttribute("height"); + if (unitWidth !== null) { + this.width = this.parseUnitSize(unitWidth); + this.height = this.parseUnitSize(unitHeight) + } else if (this.width === 0 || this.height === 0) { + this.width = 1; + this.height = 1; + throw "The width and/or height is not " + "readable in the tag of this file."; + } + this.parseColors(this.element); + this.parseChildren(this.element) + }; + PShapeSVG.prototype = new PShape; + PShapeSVG.prototype.parseMatrix = function() { + function getCoords(s) { + var m = []; + s.replace(/\((.*?)\)/, function() { + return function(all, params) { + m = params.replace(/,+/g, " ").split(/\s+/) + } + }()); + return m + } + return function(str) { + this.checkMatrix(2); + var pieces = []; + str.replace(/\s*(\w+)\((.*?)\)/g, function(all) { + pieces.push(p.trim(all)) + }); + if (pieces.length === 0) return null; + for (var i = 0, j = pieces.length; i < j; i++) { + var m = getCoords(pieces[i]); + if (pieces[i].indexOf("matrix") !== -1) this.matrix.set(m[0], m[2], m[4], m[1], m[3], m[5]); + else if (pieces[i].indexOf("translate") !== -1) { + var tx = m[0]; + var ty = m.length === 2 ? m[1] : 0; + this.matrix.translate(tx, ty) + } else if (pieces[i].indexOf("scale") !== -1) { + var sx = m[0]; + var sy = m.length === 2 ? m[1] : m[0]; + this.matrix.scale(sx, sy) + } else if (pieces[i].indexOf("rotate") !== -1) { + var angle = m[0]; + if (m.length === 1) this.matrix.rotate(p.radians(angle)); + else if (m.length === 3) { + this.matrix.translate(m[1], m[2]); + this.matrix.rotate(p.radians(m[0])); + this.matrix.translate(-m[1], -m[2]) + } + } else if (pieces[i].indexOf("skewX") !== -1) this.matrix.skewX(parseFloat(m[0])); + else if (pieces[i].indexOf("skewY") !== -1) this.matrix.skewY(m[0]); + else if (pieces[i].indexOf("shearX") !== -1) this.matrix.shearX(m[0]); + else if (pieces[i].indexOf("shearY") !== -1) this.matrix.shearY(m[0]) + } + return this.matrix + } + }(); + PShapeSVG.prototype.parseChildren = function(element) { + var newelement = element.getChildren(); + var children = new p.PShape; + for (var i = 0, j = newelement.length; i < j; i++) { + var kid = this.parseChild(newelement[i]); + if (kid) children.addChild(kid) + } + this.children.push(children) + }; + PShapeSVG.prototype.getName = function() { + return this.name + }; + PShapeSVG.prototype.parseChild = function(elem) { + var name = elem.getName(); + var shape; + if (name === "g") shape = new PShapeSVG(this, elem); + else if (name === "defs") shape = new PShapeSVG(this, elem); + else if (name === "line") { + shape = new PShapeSVG(this, elem); + shape.parseLine() + } else if (name === "circle") { + shape = new PShapeSVG(this, elem); + shape.parseEllipse(true) + } else if (name === "ellipse") { + shape = new PShapeSVG(this, elem); + shape.parseEllipse(false) + } else if (name === "rect") { + shape = new PShapeSVG(this, elem); + shape.parseRect() + } else if (name === "polygon") { + shape = new PShapeSVG(this, elem); + shape.parsePoly(true) + } else if (name === "polyline") { + shape = new PShapeSVG(this, elem); + shape.parsePoly(false) + } else if (name === "path") { + shape = new PShapeSVG(this, elem); + shape.parsePath() + } else if (name === "radialGradient") unimplemented("PShapeSVG.prototype.parseChild, name = radialGradient"); + else if (name === "linearGradient") unimplemented("PShapeSVG.prototype.parseChild, name = linearGradient"); + else if (name === "text") unimplemented("PShapeSVG.prototype.parseChild, name = text"); + else if (name === "filter") unimplemented("PShapeSVG.prototype.parseChild, name = filter"); + else if (name === "mask") unimplemented("PShapeSVG.prototype.parseChild, name = mask"); + else nop(); + return shape + }; + PShapeSVG.prototype.parsePath = function() { + this.family = 21; + this.kind = 0; + var pathDataChars = []; + var c; + var pathData = p.trim(this.element.getStringAttribute("d").replace(/[\s,]+/g, " ")); + if (pathData === null) return; + pathData = p.__toCharArray(pathData); + var cx = 0, + cy = 0, + ctrlX = 0, + ctrlY = 0, + ctrlX1 = 0, + ctrlX2 = 0, + ctrlY1 = 0, + ctrlY2 = 0, + endX = 0, + endY = 0, + ppx = 0, + ppy = 0, + px = 0, + py = 0, + i = 0, + valOf = 0; + var str = ""; + var tmpArray = []; + var flag = false; + var lastInstruction; + var command; + var j, k; + while (i < pathData.length) { + valOf = pathData[i].valueOf(); + if (valOf >= 65 && valOf <= 90 || valOf >= 97 && valOf <= 122) { + j = i; + i++; + if (i < pathData.length) { + tmpArray = []; + valOf = pathData[i].valueOf(); + while (! (valOf >= 65 && valOf <= 90 || valOf >= 97 && valOf <= 100 || valOf >= 102 && valOf <= 122) && flag === false) { + if (valOf === 32) { + if (str !== "") { + tmpArray.push(parseFloat(str)); + str = "" + } + i++ + } else if (valOf === 45) if (pathData[i - 1].valueOf() === 101) { + str += pathData[i].toString(); + i++ + } else { + if (str !== "") tmpArray.push(parseFloat(str)); + str = pathData[i].toString(); + i++ + } else { + str += pathData[i].toString(); + i++ + } + if (i === pathData.length) flag = true; + else valOf = pathData[i].valueOf() + } + } + if (str !== "") { + tmpArray.push(parseFloat(str)); + str = "" + } + command = pathData[j]; + valOf = command.valueOf(); + if (valOf === 77) { + if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) { + cx = tmpArray[0]; + cy = tmpArray[1]; + this.parsePathMoveto(cx, cy); + if (tmpArray.length > 2) for (j = 2, k = tmpArray.length; j < k; j += 2) { + cx = tmpArray[j]; + cy = tmpArray[j + 1]; + this.parsePathLineto(cx, cy) + } + } + } else if (valOf === 109) { + if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) { + cx += tmpArray[0]; + cy += tmpArray[1]; + this.parsePathMoveto(cx, cy); + if (tmpArray.length > 2) for (j = 2, k = tmpArray.length; j < k; j += 2) { + cx += tmpArray[j]; + cy += tmpArray[j + 1]; + this.parsePathLineto(cx, cy) + } + } + } else if (valOf === 76) { + if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) { + cx = tmpArray[j]; + cy = tmpArray[j + 1]; + this.parsePathLineto(cx, cy) + } + } else if (valOf === 108) { + if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) { + cx += tmpArray[j]; + cy += tmpArray[j + 1]; + this.parsePathLineto(cx, cy) + } + } else if (valOf === 72) for (j = 0, k = tmpArray.length; j < k; j++) { + cx = tmpArray[j]; + this.parsePathLineto(cx, cy) + } else if (valOf === 104) for (j = 0, k = tmpArray.length; j < k; j++) { + cx += tmpArray[j]; + this.parsePathLineto(cx, cy) + } else if (valOf === 86) for (j = 0, k = tmpArray.length; j < k; j++) { + cy = tmpArray[j]; + this.parsePathLineto(cx, cy) + } else if (valOf === 118) for (j = 0, k = tmpArray.length; j < k; j++) { + cy += tmpArray[j]; + this.parsePathLineto(cx, cy) + } else if (valOf === 67) { + if (tmpArray.length >= 6 && tmpArray.length % 6 === 0) for (j = 0, k = tmpArray.length; j < k; j += 6) { + ctrlX1 = tmpArray[j]; + ctrlY1 = tmpArray[j + 1]; + ctrlX2 = tmpArray[j + 2]; + ctrlY2 = tmpArray[j + 3]; + endX = tmpArray[j + 4]; + endY = tmpArray[j + 5]; + this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 99) { + if (tmpArray.length >= 6 && tmpArray.length % 6 === 0) for (j = 0, k = tmpArray.length; j < k; j += 6) { + ctrlX1 = cx + tmpArray[j]; + ctrlY1 = cy + tmpArray[j + 1]; + ctrlX2 = cx + tmpArray[j + 2]; + ctrlY2 = cy + tmpArray[j + 3]; + endX = cx + tmpArray[j + 4]; + endY = cy + tmpArray[j + 5]; + this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 83) { + if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) { + if (lastInstruction.toLowerCase() === "c" || lastInstruction.toLowerCase() === "s") { + ppx = this.vertices[this.vertices.length - 2][0]; + ppy = this.vertices[this.vertices.length - 2][1]; + px = this.vertices[this.vertices.length - 1][0]; + py = this.vertices[this.vertices.length - 1][1]; + ctrlX1 = px + (px - ppx); + ctrlY1 = py + (py - ppy) + } else { + ctrlX1 = this.vertices[this.vertices.length - 1][0]; + ctrlY1 = this.vertices[this.vertices.length - 1][1] + } + ctrlX2 = tmpArray[j]; + ctrlY2 = tmpArray[j + 1]; + endX = tmpArray[j + 2]; + endY = tmpArray[j + 3]; + this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 115) { + if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) { + if (lastInstruction.toLowerCase() === "c" || lastInstruction.toLowerCase() === "s") { + ppx = this.vertices[this.vertices.length - 2][0]; + ppy = this.vertices[this.vertices.length - 2][1]; + px = this.vertices[this.vertices.length - 1][0]; + py = this.vertices[this.vertices.length - 1][1]; + ctrlX1 = px + (px - ppx); + ctrlY1 = py + (py - ppy) + } else { + ctrlX1 = this.vertices[this.vertices.length - 1][0]; + ctrlY1 = this.vertices[this.vertices.length - 1][1] + } + ctrlX2 = cx + tmpArray[j]; + ctrlY2 = cy + tmpArray[j + 1]; + endX = cx + tmpArray[j + 2]; + endY = cy + tmpArray[j + 3]; + this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 81) { + if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) { + ctrlX = tmpArray[j]; + ctrlY = tmpArray[j + 1]; + endX = tmpArray[j + 2]; + endY = tmpArray[j + 3]; + this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 113) { + if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) { + ctrlX = cx + tmpArray[j]; + ctrlY = cy + tmpArray[j + 1]; + endX = cx + tmpArray[j + 2]; + endY = cy + tmpArray[j + 3]; + this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 84) { + if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) { + if (lastInstruction.toLowerCase() === "q" || lastInstruction.toLowerCase() === "t") { + ppx = this.vertices[this.vertices.length - 2][0]; + ppy = this.vertices[this.vertices.length - 2][1]; + px = this.vertices[this.vertices.length - 1][0]; + py = this.vertices[this.vertices.length - 1][1]; + ctrlX = px + (px - ppx); + ctrlY = py + (py - ppy) + } else { + ctrlX = cx; + ctrlY = cy + } + endX = tmpArray[j]; + endY = tmpArray[j + 1]; + this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 116) { + if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) { + if (lastInstruction.toLowerCase() === "q" || lastInstruction.toLowerCase() === "t") { + ppx = this.vertices[this.vertices.length - 2][0]; + ppy = this.vertices[this.vertices.length - 2][1]; + px = this.vertices[this.vertices.length - 1][0]; + py = this.vertices[this.vertices.length - 1][1]; + ctrlX = px + (px - ppx); + ctrlY = py + (py - ppy) + } else { + ctrlX = cx; + ctrlY = cy + } + endX = cx + tmpArray[j]; + endY = cy + tmpArray[j + 1]; + this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY); + cx = endX; + cy = endY + } + } else if (valOf === 90 || valOf === 122) this.close = true; + lastInstruction = command.toString() + } else i++ + } + }; + PShapeSVG.prototype.parsePathQuadto = function(x1, y1, cx, cy, x2, y2) { + if (this.vertices.length > 0) { + this.parsePathCode(1); + this.parsePathVertex(x1 + (cx - x1) * 2 / 3, y1 + (cy - y1) * 2 / 3); + this.parsePathVertex(x2 + (cx - x2) * 2 / 3, y2 + (cy - y2) * 2 / 3); + this.parsePathVertex(x2, y2) + } else throw "Path must start with M/m"; + }; + PShapeSVG.prototype.parsePathCurveto = function(x1, y1, x2, y2, x3, y3) { + if (this.vertices.length > 0) { + this.parsePathCode(1); + this.parsePathVertex(x1, y1); + this.parsePathVertex(x2, y2); + this.parsePathVertex(x3, y3) + } else throw "Path must start with M/m"; + }; + PShapeSVG.prototype.parsePathLineto = function(px, py) { + if (this.vertices.length > 0) { + this.parsePathCode(0); + this.parsePathVertex(px, py); + this.vertices[this.vertices.length - 1]["moveTo"] = false + } else throw "Path must start with M/m"; + }; + PShapeSVG.prototype.parsePathMoveto = function(px, py) { + if (this.vertices.length > 0) this.parsePathCode(3); + this.parsePathCode(0); + this.parsePathVertex(px, py); + this.vertices[this.vertices.length - 1]["moveTo"] = true + }; + PShapeSVG.prototype.parsePathVertex = function(x, y) { + var verts = []; + verts[0] = x; + verts[1] = y; + this.vertices.push(verts) + }; + PShapeSVG.prototype.parsePathCode = function(what) { + this.vertexCodes.push(what) + }; + PShapeSVG.prototype.parsePoly = function(val) { + this.family = 21; + this.close = val; + var pointsAttr = p.trim(this.element.getStringAttribute("points").replace(/[,\s]+/g, " ")); + if (pointsAttr !== null) { + var pointsBuffer = pointsAttr.split(" "); + if (pointsBuffer.length % 2 === 0) for (var i = 0, j = pointsBuffer.length; i < j; i++) { + var verts = []; + verts[0] = pointsBuffer[i]; + verts[1] = pointsBuffer[++i]; + this.vertices.push(verts) + } else throw "Error parsing polygon points: odd number of coordinates provided"; + } + }; + PShapeSVG.prototype.parseRect = function() { + this.kind = 30; + this.family = 1; + this.params = []; + this.params[0] = this.element.getFloatAttribute("x"); + this.params[1] = this.element.getFloatAttribute("y"); + this.params[2] = this.element.getFloatAttribute("width"); + this.params[3] = this.element.getFloatAttribute("height"); + if (this.params[2] < 0 || this.params[3] < 0) throw "svg error: negative width or height found while parsing "; + }; + PShapeSVG.prototype.parseEllipse = function(val) { + this.kind = 31; + this.family = 1; + this.params = []; + this.params[0] = this.element.getFloatAttribute("cx") | 0; + this.params[1] = this.element.getFloatAttribute("cy") | 0; + var rx, ry; + if (val) { + rx = ry = this.element.getFloatAttribute("r"); + if (rx < 0) throw "svg error: negative radius found while parsing "; + } else { + rx = this.element.getFloatAttribute("rx"); + ry = this.element.getFloatAttribute("ry"); + if (rx < 0 || ry < 0) throw "svg error: negative x-axis radius or y-axis radius found while parsing "; + } + this.params[0] -= rx; + this.params[1] -= ry; + this.params[2] = rx * 2; + this.params[3] = ry * 2 + }; + PShapeSVG.prototype.parseLine = function() { + this.kind = 4; + this.family = 1; + this.params = []; + this.params[0] = this.element.getFloatAttribute("x1"); + this.params[1] = this.element.getFloatAttribute("y1"); + this.params[2] = this.element.getFloatAttribute("x2"); + this.params[3] = this.element.getFloatAttribute("y2") + }; + PShapeSVG.prototype.parseColors = function(element) { + if (element.hasAttribute("opacity")) this.setOpacity(element.getAttribute("opacity")); + if (element.hasAttribute("stroke")) this.setStroke(element.getAttribute("stroke")); + if (element.hasAttribute("stroke-width")) this.setStrokeWeight(element.getAttribute("stroke-width")); + if (element.hasAttribute("stroke-linejoin")) this.setStrokeJoin(element.getAttribute("stroke-linejoin")); + if (element.hasAttribute("stroke-linecap")) this.setStrokeCap(element.getStringAttribute("stroke-linecap")); + if (element.hasAttribute("fill")) this.setFill(element.getStringAttribute("fill")); + if (element.hasAttribute("style")) { + var styleText = element.getStringAttribute("style"); + var styleTokens = styleText.toString().split(";"); + for (var i = 0, j = styleTokens.length; i < j; i++) { + var tokens = p.trim(styleTokens[i].split(":")); + if (tokens[0] === "fill") this.setFill(tokens[1]); + else if (tokens[0] === "fill-opacity") this.setFillOpacity(tokens[1]); + else if (tokens[0] === "stroke") this.setStroke(tokens[1]); + else if (tokens[0] === "stroke-width") this.setStrokeWeight(tokens[1]); + else if (tokens[0] === "stroke-linecap") this.setStrokeCap(tokens[1]); + else if (tokens[0] === "stroke-linejoin") this.setStrokeJoin(tokens[1]); + else if (tokens[0] === "stroke-opacity") this.setStrokeOpacity(tokens[1]); + else if (tokens[0] === "opacity") this.setOpacity(tokens[1]) + } + } + }; + PShapeSVG.prototype.setFillOpacity = function(opacityText) { + this.fillOpacity = parseFloat(opacityText); + this.fillColor = this.fillOpacity * 255 << 24 | this.fillColor & 16777215 + }; + PShapeSVG.prototype.setFill = function(fillText) { + var opacityMask = this.fillColor & 4278190080; + if (fillText === "none") this.fill = false; + else if (fillText.indexOf("#") === 0) { + this.fill = true; + if (fillText.length === 4) fillText = fillText.replace(/#(.)(.)(.)/, "#$1$1$2$2$3$3"); + this.fillColor = opacityMask | parseInt(fillText.substring(1), 16) & 16777215 + } else if (fillText.indexOf("rgb") === 0) { + this.fill = true; + this.fillColor = opacityMask | this.parseRGB(fillText) + } else if (fillText.indexOf("url(#") === 0) this.fillName = fillText.substring(5, fillText.length - 1); + else if (colors[fillText]) { + this.fill = true; + this.fillColor = opacityMask | parseInt(colors[fillText].substring(1), 16) & 16777215 + } + }; + PShapeSVG.prototype.setOpacity = function(opacity) { + this.strokeColor = parseFloat(opacity) * 255 << 24 | this.strokeColor & 16777215; + this.fillColor = parseFloat(opacity) * 255 << 24 | this.fillColor & 16777215 + }; + PShapeSVG.prototype.setStroke = function(strokeText) { + var opacityMask = this.strokeColor & 4278190080; + if (strokeText === "none") this.stroke = false; + else if (strokeText.charAt(0) === "#") { + this.stroke = true; + if (strokeText.length === 4) strokeText = strokeText.replace(/#(.)(.)(.)/, "#$1$1$2$2$3$3"); + this.strokeColor = opacityMask | parseInt(strokeText.substring(1), 16) & 16777215 + } else if (strokeText.indexOf("rgb") === 0) { + this.stroke = true; + this.strokeColor = opacityMask | this.parseRGB(strokeText) + } else if (strokeText.indexOf("url(#") === 0) this.strokeName = strokeText.substring(5, strokeText.length - 1); + else if (colors[strokeText]) { + this.stroke = true; + this.strokeColor = opacityMask | parseInt(colors[strokeText].substring(1), 16) & 16777215 + } + }; + PShapeSVG.prototype.setStrokeWeight = function(weight) { + this.strokeWeight = this.parseUnitSize(weight) + }; + PShapeSVG.prototype.setStrokeJoin = function(linejoin) { + if (linejoin === "miter") this.strokeJoin = 'miter'; + else if (linejoin === "round") this.strokeJoin = 'round'; + else if (linejoin === "bevel") this.strokeJoin = 'bevel' + }; + PShapeSVG.prototype.setStrokeCap = function(linecap) { + if (linecap === "butt") this.strokeCap = 'butt'; + else if (linecap === "round") this.strokeCap = 'round'; + else if (linecap === "square") this.strokeCap = 'square' + }; + PShapeSVG.prototype.setStrokeOpacity = function(opacityText) { + this.strokeOpacity = parseFloat(opacityText); + this.strokeColor = this.strokeOpacity * 255 << 24 | this.strokeColor & 16777215 + }; + PShapeSVG.prototype.parseRGB = function(color) { + var sub = color.substring(color.indexOf("(") + 1, color.indexOf(")")); + var values = sub.split(", "); + return values[0] << 16 | values[1] << 8 | values[2] + }; + PShapeSVG.prototype.parseUnitSize = function(text) { + var len = text.length - 2; + if (len < 0) return text; + if (text.indexOf("pt") === len) return parseFloat(text.substring(0, len)) * 1.25; + if (text.indexOf("pc") === len) return parseFloat(text.substring(0, len)) * 15; + if (text.indexOf("mm") === len) return parseFloat(text.substring(0, len)) * 3.543307; + if (text.indexOf("cm") === len) return parseFloat(text.substring(0, len)) * 35.43307; + if (text.indexOf("in") === len) return parseFloat(text.substring(0, len)) * 90; + if (text.indexOf("px") === len) return parseFloat(text.substring(0, len)); + return parseFloat(text) + }; + p.shape = function(shape, x, y, width, height) { + if (arguments.length >= 1 && arguments[0] !== null) if (shape.isVisible()) { + p.pushMatrix(); + if (curShapeMode === 3) if (arguments.length === 5) { + p.translate(x - width / 2, y - height / 2); + p.scale(width / shape.getWidth(), height / shape.getHeight()) + } else if (arguments.length === 3) p.translate(x - shape.getWidth() / 2, -shape.getHeight() / 2); + else p.translate(-shape.getWidth() / 2, -shape.getHeight() / 2); + else if (curShapeMode === 0) if (arguments.length === 5) { + p.translate(x, y); + p.scale(width / shape.getWidth(), height / shape.getHeight()) + } else { + if (arguments.length === 3) p.translate(x, y) + } else if (curShapeMode === 1) if (arguments.length === 5) { + width -= x; + height -= y; + p.translate(x, y); + p.scale(width / shape.getWidth(), height / shape.getHeight()) + } else if (arguments.length === 3) p.translate(x, y); + shape.draw(p); + if (arguments.length === 1 && curShapeMode === 3 || arguments.length > 1) p.popMatrix() + } + }; + p.shapeMode = function(mode) { + curShapeMode = mode + }; + p.loadShape = function(filename) { + if (arguments.length === 1) if (filename.indexOf(".svg") > -1) return new PShapeSVG(null, filename); + return null + }; + var XMLAttribute = function(fname, n, nameSpace, v, t) { + this.fullName = fname || ""; + this.name = n || ""; + this.namespace = nameSpace || ""; + this.value = v; + this.type = t + }; + XMLAttribute.prototype = { + getName: function() { + return this.name + }, + getFullName: function() { + return this.fullName + }, + getNamespace: function() { + return this.namespace + }, + getValue: function() { + return this.value + }, + getType: function() { + return this.type + }, + setValue: function(newval) { + this.value = newval + } + }; + var XMLElement = p.XMLElement = function(selector, uri, sysid, line) { + this.attributes = []; + this.children = []; + this.fullName = null; + this.name = null; + this.namespace = ""; + this.content = null; + this.parent = null; + this.lineNr = ""; + this.systemID = ""; + this.type = "ELEMENT"; + if (selector) if (typeof selector === "string") if (uri === undef && selector.indexOf("<") > -1) this.parse(selector); + else { + this.fullName = selector; + this.namespace = uri; + this.systemId = sysid; + this.lineNr = line + } else this.parse(uri) + }; + XMLElement.prototype = { + parse: function(textstring) { + var xmlDoc; + try { + var extension = textstring.substring(textstring.length - 4); + if (extension === ".xml" || extension === ".svg") textstring = ajax(textstring); + xmlDoc = (new DOMParser).parseFromString(textstring, "text/xml"); + var elements = xmlDoc.documentElement; + if (elements) this.parseChildrenRecursive(null, elements); + else throw "Error loading document"; + return this + } catch(e) { + throw e; + } + }, + parseChildrenRecursive: function(parent, elementpath) { + var xmlelement, xmlattribute, tmpattrib, l, m, child; + if (!parent) { + this.fullName = elementpath.localName; + this.name = elementpath.nodeName; + xmlelement = this + } else { + xmlelement = new XMLElement(elementpath.nodeName); + xmlelement.parent = parent + } + if (elementpath.nodeType === 3 && elementpath.textContent !== "") return this.createPCDataElement(elementpath.textContent); + if (elementpath.nodeType === 4) return this.createCDataElement(elementpath.textContent); + if (elementpath.attributes) for (l = 0, m = elementpath.attributes.length; l < m; l++) { + tmpattrib = elementpath.attributes[l]; + xmlattribute = new XMLAttribute(tmpattrib.getname, tmpattrib.nodeName, tmpattrib.namespaceURI, tmpattrib.nodeValue, tmpattrib.nodeType); + xmlelement.attributes.push(xmlattribute) + } + if (elementpath.childNodes) for (l = 0, m = elementpath.childNodes.length; l < m; l++) { + var node = elementpath.childNodes[l]; + child = xmlelement.parseChildrenRecursive(xmlelement, node); + if (child !== null) xmlelement.children.push(child) + } + return xmlelement + }, + createElement: function(fullname, namespaceuri, sysid, line) { + if (sysid === undef) return new XMLElement(fullname, namespaceuri); + return new XMLElement(fullname, namespaceuri, sysid, line) + }, + createPCDataElement: function(content, isCDATA) { + if (content.replace(/^\s+$/g, "") === "") return null; + var pcdata = new XMLElement; + pcdata.type = "TEXT"; + pcdata.content = content; + return pcdata + }, + createCDataElement: function(content) { + var cdata = this.createPCDataElement(content); + if (cdata === null) return null; + cdata.type = "CDATA"; + var htmlentities = { + "<": "<", + ">": ">", + "'": "'", + '"': """ + }, + entity; + for (entity in htmlentities) if (!Object.hasOwnProperty(htmlentities, entity)) content = content.replace(new RegExp(entity, "g"), htmlentities[entity]); + cdata.cdata = content; + return cdata + }, + hasAttribute: function() { + if (arguments.length === 1) return this.getAttribute(arguments[0]) !== null; + if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]) !== null + }, + equals: function(other) { + if (! (other instanceof XMLElement)) return false; + var i, j; + if (this.fullName !== other.fullName) return false; + if (this.attributes.length !== other.getAttributeCount()) return false; + if (this.attributes.length !== other.attributes.length) return false; + var attr_name, attr_ns, attr_value, attr_type, attr_other; + for (i = 0, j = this.attributes.length; i < j; i++) { + attr_name = this.attributes[i].getName(); + attr_ns = this.attributes[i].getNamespace(); + attr_other = other.findAttribute(attr_name, attr_ns); + if (attr_other === null) return false; + if (this.attributes[i].getValue() !== attr_other.getValue()) return false; + if (this.attributes[i].getType() !== attr_other.getType()) return false + } + if (this.children.length !== other.getChildCount()) return false; + if (this.children.length > 0) { + var child1, child2; + for (i = 0, j = this.children.length; i < j; i++) { + child1 = this.getChild(i); + child2 = other.getChild(i); + if (!child1.equals(child2)) return false + } + return true + } + return this.content === other.content + }, + getContent: function() { + if (this.type === "TEXT" || this.type === "CDATA") return this.content; + var children = this.children; + if (children.length === 1 && (children[0].type === "TEXT" || children[0].type === "CDATA")) return children[0].content; + return null + }, + getAttribute: function() { + var attribute; + if (arguments.length === 2) { + attribute = this.findAttribute(arguments[0]); + if (attribute) return attribute.getValue(); + return arguments[1] + } else if (arguments.length === 1) { + attribute = this.findAttribute(arguments[0]); + if (attribute) return attribute.getValue(); + return null + } else if (arguments.length === 3) { + attribute = this.findAttribute(arguments[0], arguments[1]); + if (attribute) return attribute.getValue(); + return arguments[2] + } + }, + getStringAttribute: function() { + if (arguments.length === 1) return this.getAttribute(arguments[0]); + if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]); + return this.getAttribute(arguments[0], arguments[1], arguments[2]) + }, + getString: function(attributeName) { + return this.getStringAttribute(attributeName) + }, + getFloatAttribute: function() { + if (arguments.length === 1) return parseFloat(this.getAttribute(arguments[0], 0)); + if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]); + return this.getAttribute(arguments[0], arguments[1], arguments[2]) + }, + getFloat: function(attributeName) { + return this.getFloatAttribute(attributeName) + }, + getIntAttribute: function() { + if (arguments.length === 1) return this.getAttribute(arguments[0], 0); + if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]); + return this.getAttribute(arguments[0], arguments[1], arguments[2]) + }, + getInt: function(attributeName) { + return this.getIntAttribute(attributeName) + }, + hasChildren: function() { + return this.children.length > 0 + }, + addChild: function(child) { + if (child !== null) { + child.parent = this; + this.children.push(child) + } + }, + insertChild: function(child, index) { + if (child) { + if (child.getLocalName() === null && !this.hasChildren()) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild.getLocalName() === null) { + lastChild.setContent(lastChild.getContent() + child.getContent()); + return + } + } + child.parent = this; + this.children.splice(index, 0, child) + } + }, + getChild: function(selector) { + if (typeof selector === "number") return this.children[selector]; + if (selector.indexOf("/") !== -1) return this.getChildRecursive(selector.split("/"), 0); + var kid, kidName; + for (var i = 0, j = this.getChildCount(); i < j; i++) { + kid = this.getChild(i); + kidName = kid.getName(); + if (kidName !== null && kidName === selector) return kid + } + return null + }, + getChildren: function() { + if (arguments.length === 1) { + if (typeof arguments[0] === "number") return this.getChild(arguments[0]); + if (arguments[0].indexOf("/") !== -1) return this.getChildrenRecursive(arguments[0].split("/"), 0); + var matches = []; + var kid, kidName; + for (var i = 0, j = this.getChildCount(); i < j; i++) { + kid = this.getChild(i); + kidName = kid.getName(); + if (kidName !== null && kidName === arguments[0]) matches.push(kid) + } + return matches + } + return this.children + }, + getChildCount: function() { + return this.children.length + }, + getChildRecursive: function(items, offset) { + if (offset === items.length) return this; + var kid, kidName, matchName = items[offset]; + for (var i = 0, j = this.getChildCount(); i < j; i++) { + kid = this.getChild(i); + kidName = kid.getName(); + if (kidName !== null && kidName === matchName) return kid.getChildRecursive(items, offset + 1) + } + return null + }, + getChildrenRecursive: function(items, offset) { + if (offset === items.length - 1) return this.getChildren(items[offset]); + var matches = this.getChildren(items[offset]); + var kidMatches = []; + for (var i = 0; i < matches.length; i++) kidMatches = kidMatches.concat(matches[i].getChildrenRecursive(items, offset + 1)); + return kidMatches + }, + isLeaf: function() { + return !this.hasChildren() + }, + listChildren: function() { + var arr = []; + for (var i = 0, j = this.children.length; i < j; i++) arr.push(this.getChild(i).getName()); + return arr + }, + removeAttribute: function(name, namespace) { + this.namespace = namespace || ""; + for (var i = 0, j = this.attributes.length; i < j; i++) if (this.attributes[i].getName() === name && this.attributes[i].getNamespace() === this.namespace) { + this.attributes.splice(i, 1); + break + } + }, + removeChild: function(child) { + if (child) for (var i = 0, j = this.children.length; i < j; i++) if (this.children[i].equals(child)) { + this.children.splice(i, 1); + break + } + }, + removeChildAtIndex: function(index) { + if (this.children.length > index) this.children.splice(index, 1) + }, + findAttribute: function(name, namespace) { + this.namespace = namespace || ""; + for (var i = 0, j = this.attributes.length; i < j; i++) if (this.attributes[i].getName() === name && this.attributes[i].getNamespace() === this.namespace) return this.attributes[i]; + return null + }, + setAttribute: function() { + var attr; + if (arguments.length === 3) { + var index = arguments[0].indexOf(":"); + var name = arguments[0].substring(index + 1); + attr = this.findAttribute(name, arguments[1]); + if (attr) attr.setValue(arguments[2]); + else { + attr = new XMLAttribute(arguments[0], name, arguments[1], arguments[2], "CDATA"); + this.attributes.push(attr) + } + } else { + attr = this.findAttribute(arguments[0]); + if (attr) attr.setValue(arguments[1]); + else { + attr = new XMLAttribute(arguments[0], arguments[0], null, arguments[1], "CDATA"); + this.attributes.push(attr) + } + } + }, + setString: function(attribute, value) { + this.setAttribute(attribute, value) + }, + setInt: function(attribute, value) { + this.setAttribute(attribute, value) + }, + setFloat: function(attribute, value) { + this.setAttribute(attribute, value) + }, + setContent: function(content) { + if (this.children.length > 0) Processing.debug("Tried to set content for XMLElement with children"); + this.content = content + }, + setName: function() { + if (arguments.length === 1) { + this.name = arguments[0]; + this.fullName = arguments[0]; + this.namespace = null + } else { + var index = arguments[0].indexOf(":"); + if (arguments[1] === null || index < 0) this.name = arguments[0]; + else this.name = arguments[0].substring(index + 1); + this.fullName = arguments[0]; + this.namespace = arguments[1] + } + }, + getName: function() { + return this.fullName + }, + getLocalName: function() { + return this.name + }, + getAttributeCount: function() { + return this.attributes.length + }, + toString: function() { + if (this.type === "TEXT") return this.content; + if (this.type === "CDATA") return this.cdata; + var tagstring = this.fullName; + var xmlstring = "<" + tagstring; + var a, c; + for (a = 0; a < this.attributes.length; a++) { + var attr = this.attributes[a]; + xmlstring += " " + attr.getName() + "=" + '"' + attr.getValue() + '"' + } + if (this.children.length === 0) if (this.content === "") xmlstring += "/>"; + else xmlstring += ">" + this.content + ""; + else { + xmlstring += ">"; + for (c = 0; c < this.children.length; c++) xmlstring += this.children[c].toString(); + xmlstring += "" + } + return xmlstring + } + }; + XMLElement.parse = function(xmlstring) { + var element = new XMLElement; + element.parse(xmlstring); + return element + }; + var XML = p.XML = p.XMLElement; + p.loadXML = function(uri) { + return new XML(p, uri) + }; + var printMatrixHelper = function(elements) { + var big = 0; + for (var i = 0; i < elements.length; i++) if (i !== 0) big = Math.max(big, Math.abs(elements[i])); + else big = Math.abs(elements[i]); + var digits = (big + "").indexOf("."); + if (digits === 0) digits = 1; + else if (digits === -1) digits = (big + "").length; + return digits + }; + var PMatrix2D = p.PMatrix2D = function() { + if (arguments.length === 0) this.reset(); + else if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) this.set(arguments[0].array()); + else if (arguments.length === 6) this.set(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]) + }; + PMatrix2D.prototype = { + set: function() { + if (arguments.length === 6) { + var a = arguments; + this.set([a[0], a[1], a[2], a[3], a[4], a[5]]) + } else if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) this.elements = arguments[0].array(); + else if (arguments.length === 1 && arguments[0] instanceof Array) this.elements = arguments[0].slice() + }, + get: function() { + var outgoing = new PMatrix2D; + outgoing.set(this.elements); + return outgoing + }, + reset: function() { + this.set([1, 0, 0, 0, 1, 0]) + }, + array: function array() { + return this.elements.slice() + }, + translate: function(tx, ty) { + this.elements[2] = tx * this.elements[0] + ty * this.elements[1] + this.elements[2]; + this.elements[5] = tx * this.elements[3] + ty * this.elements[4] + this.elements[5] + }, + invTranslate: function(tx, ty) { + this.translate(-tx, -ty) + }, + transpose: function() {}, + mult: function(source, target) { + var x, y; + if (source instanceof + PVector) { + x = source.x; + y = source.y; + if (!target) target = new PVector + } else if (source instanceof Array) { + x = source[0]; + y = source[1]; + if (!target) target = [] + } + if (target instanceof Array) { + target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2]; + target[1] = this.elements[3] * x + this.elements[4] * y + this.elements[5] + } else if (target instanceof PVector) { + target.x = this.elements[0] * x + this.elements[1] * y + this.elements[2]; + target.y = this.elements[3] * x + this.elements[4] * y + this.elements[5]; + target.z = 0 + } + return target + }, + multX: function(x, y) { + return x * this.elements[0] + y * this.elements[1] + this.elements[2] + }, + multY: function(x, y) { + return x * this.elements[3] + y * this.elements[4] + this.elements[5] + }, + skewX: function(angle) { + this.apply(1, 0, 1, angle, 0, 0) + }, + skewY: function(angle) { + this.apply(1, 0, 1, 0, angle, 0) + }, + shearX: function(angle) { + this.apply(1, 0, 1, Math.tan(angle), 0, 0) + }, + shearY: function(angle) { + this.apply(1, 0, 1, 0, Math.tan(angle), 0) + }, + determinant: function() { + return this.elements[0] * this.elements[4] - this.elements[1] * this.elements[3] + }, + invert: function() { + var d = this.determinant(); + if (Math.abs(d) > -2147483648) { + var old00 = this.elements[0]; + var old01 = this.elements[1]; + var old02 = this.elements[2]; + var old10 = this.elements[3]; + var old11 = this.elements[4]; + var old12 = this.elements[5]; + this.elements[0] = old11 / d; + this.elements[3] = -old10 / d; + this.elements[1] = -old01 / d; + this.elements[4] = old00 / d; + this.elements[2] = (old01 * old12 - old11 * old02) / d; + this.elements[5] = (old10 * old02 - old00 * old12) / d; + return true + } + return false + }, + scale: function(sx, sy) { + if (sx && !sy) sy = sx; + if (sx && sy) { + this.elements[0] *= sx; + this.elements[1] *= sy; + this.elements[3] *= sx; + this.elements[4] *= sy + } + }, + invScale: function(sx, sy) { + if (sx && !sy) sy = sx; + this.scale(1 / sx, 1 / sy) + }, + apply: function() { + var source; + if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) source = arguments[0].array(); + else if (arguments.length === 6) source = Array.prototype.slice.call(arguments); + else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0]; + var result = [0, 0, this.elements[2], 0, 0, this.elements[5]]; + var e = 0; + for (var row = 0; row < 2; row++) for (var col = 0; col < 3; col++, e++) result[e] += this.elements[row * 3 + 0] * source[col + 0] + this.elements[row * 3 + 1] * source[col + 3]; + this.elements = result.slice() + }, + preApply: function() { + var source; + if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) source = arguments[0].array(); + else if (arguments.length === 6) source = Array.prototype.slice.call(arguments); + else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0]; + var result = [0, 0, source[2], 0, 0, source[5]]; + result[2] = source[2] + this.elements[2] * source[0] + this.elements[5] * source[1]; + result[5] = source[5] + this.elements[2] * source[3] + this.elements[5] * source[4]; + result[0] = this.elements[0] * source[0] + this.elements[3] * source[1]; + result[3] = this.elements[0] * source[3] + this.elements[3] * source[4]; + result[1] = this.elements[1] * source[0] + this.elements[4] * source[1]; + result[4] = this.elements[1] * source[3] + this.elements[4] * source[4]; + this.elements = result.slice() + }, + rotate: function(angle) { + var c = Math.cos(angle); + var s = Math.sin(angle); + var temp1 = this.elements[0]; + var temp2 = this.elements[1]; + this.elements[0] = c * temp1 + s * temp2; + this.elements[1] = -s * temp1 + c * temp2; + temp1 = this.elements[3]; + temp2 = this.elements[4]; + this.elements[3] = c * temp1 + s * temp2; + this.elements[4] = -s * temp1 + c * temp2 + }, + rotateZ: function(angle) { + this.rotate(angle) + }, + invRotateZ: function(angle) { + this.rotateZ(angle - Math.PI) + }, + print: function() { + var digits = printMatrixHelper(this.elements); + var output = "" + p.nfs(this.elements[0], digits, 4) + " " + p.nfs(this.elements[1], digits, 4) + " " + p.nfs(this.elements[2], digits, 4) + "\n" + p.nfs(this.elements[3], digits, 4) + " " + p.nfs(this.elements[4], digits, 4) + " " + p.nfs(this.elements[5], digits, 4) + "\n\n"; + p.println(output) + } + }; + var PMatrix3D = p.PMatrix3D = function() { + this.reset() + }; + PMatrix3D.prototype = { + set: function() { + if (arguments.length === 16) this.elements = Array.prototype.slice.call(arguments); + else if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) this.elements = arguments[0].array(); + else if (arguments.length === 1 && arguments[0] instanceof Array) this.elements = arguments[0].slice() + }, + get: function() { + var outgoing = new PMatrix3D; + outgoing.set(this.elements); + return outgoing + }, + reset: function() { + this.elements = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] + }, + array: function array() { + return this.elements.slice() + }, + translate: function(tx, ty, tz) { + if (tz === undef) tz = 0; + this.elements[3] += tx * this.elements[0] + ty * this.elements[1] + tz * this.elements[2]; + this.elements[7] += tx * this.elements[4] + ty * this.elements[5] + tz * this.elements[6]; + this.elements[11] += tx * this.elements[8] + ty * this.elements[9] + tz * this.elements[10]; + this.elements[15] += tx * this.elements[12] + ty * this.elements[13] + tz * this.elements[14] + }, + transpose: function() { + var temp = this.elements[4]; + this.elements[4] = this.elements[1]; + this.elements[1] = temp; + temp = this.elements[8]; + this.elements[8] = this.elements[2]; + this.elements[2] = temp; + temp = this.elements[6]; + this.elements[6] = this.elements[9]; + this.elements[9] = temp; + temp = this.elements[3]; + this.elements[3] = this.elements[12]; + this.elements[12] = temp; + temp = this.elements[7]; + this.elements[7] = this.elements[13]; + this.elements[13] = temp; + temp = this.elements[11]; + this.elements[11] = this.elements[14]; + this.elements[14] = temp + }, + mult: function(source, target) { + var x, y, z, w; + if (source instanceof + PVector) { + x = source.x; + y = source.y; + z = source.z; + w = 1; + if (!target) target = new PVector + } else if (source instanceof Array) { + x = source[0]; + y = source[1]; + z = source[2]; + w = source[3] || 1; + if (!target || target.length !== 3 && target.length !== 4) target = [0, 0, 0] + } + if (target instanceof Array) if (target.length === 3) { + target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3]; + target[1] = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7]; + target[2] = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] + } else if (target.length === 4) { + target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3] * w; + target[1] = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7] * w; + target[2] = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] * w; + target[3] = this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15] * w + } + if (target instanceof PVector) { + target.x = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3]; + target.y = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7]; + target.z = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] + } + return target + }, + preApply: function() { + var source; + if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) source = arguments[0].array(); + else if (arguments.length === 16) source = Array.prototype.slice.call(arguments); + else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0]; + var result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + var e = 0; + for (var row = 0; row < 4; row++) for (var col = 0; col < 4; col++, e++) result[e] += this.elements[col + 0] * source[row * 4 + 0] + this.elements[col + 4] * source[row * 4 + 1] + this.elements[col + 8] * source[row * 4 + 2] + this.elements[col + 12] * source[row * 4 + 3]; + this.elements = result.slice() + }, + apply: function() { + var source; + if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) source = arguments[0].array(); + else if (arguments.length === 16) source = Array.prototype.slice.call(arguments); + else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0]; + var result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + var e = 0; + for (var row = 0; row < 4; row++) for (var col = 0; col < 4; col++, e++) result[e] += this.elements[row * 4 + 0] * source[col + 0] + this.elements[row * 4 + 1] * source[col + 4] + this.elements[row * 4 + 2] * source[col + 8] + this.elements[row * 4 + 3] * source[col + 12]; + this.elements = result.slice() + }, + rotate: function(angle, v0, v1, v2) { + if (!v1) this.rotateZ(angle); + else { + var c = p.cos(angle); + var s = p.sin(angle); + var t = 1 - c; + this.apply(t * v0 * v0 + c, t * v0 * v1 - s * v2, t * v0 * v2 + s * v1, 0, t * v0 * v1 + s * v2, t * v1 * v1 + c, t * v1 * v2 - s * v0, 0, t * v0 * v2 - s * v1, t * v1 * v2 + s * v0, t * v2 * v2 + c, 0, 0, 0, 0, 1) + } + }, + invApply: function() { + if (inverseCopy === undef) inverseCopy = new PMatrix3D; + var a = arguments; + inverseCopy.set(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]); + if (!inverseCopy.invert()) return false; + this.preApply(inverseCopy); + return true + }, + rotateX: function(angle) { + var c = p.cos(angle); + var s = p.sin(angle); + this.apply([1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1]) + }, + rotateY: function(angle) { + var c = p.cos(angle); + var s = p.sin(angle); + this.apply([c, + 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1]) + }, + rotateZ: function(angle) { + var c = Math.cos(angle); + var s = Math.sin(angle); + this.apply([c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]) + }, + scale: function(sx, sy, sz) { + if (sx && !sy && !sz) sy = sz = sx; + else if (sx && sy && !sz) sz = 1; + if (sx && sy && sz) { + this.elements[0] *= sx; + this.elements[1] *= sy; + this.elements[2] *= sz; + this.elements[4] *= sx; + this.elements[5] *= sy; + this.elements[6] *= sz; + this.elements[8] *= sx; + this.elements[9] *= sy; + this.elements[10] *= sz; + this.elements[12] *= sx; + this.elements[13] *= sy; + this.elements[14] *= sz + } + }, + skewX: function(angle) { + var t = Math.tan(angle); + this.apply(1, t, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) + }, + skewY: function(angle) { + var t = Math.tan(angle); + this.apply(1, 0, 0, 0, t, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) + }, + shearX: function(angle) { + var t = Math.tan(angle); + this.apply(1, t, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) + }, + shearY: function(angle) { + var t = Math.tan(angle); + this.apply(1, 0, 0, 0, t, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) + }, + multX: function(x, y, z, w) { + if (!z) return this.elements[0] * x + this.elements[1] * y + this.elements[3]; + if (!w) return this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3]; + return this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3] * w + }, + multY: function(x, y, z, w) { + if (!z) return this.elements[4] * x + this.elements[5] * y + this.elements[7]; + if (!w) return this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7]; + return this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7] * w + }, + multZ: function(x, y, z, w) { + if (!w) return this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11]; + return this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] * w + }, + multW: function(x, y, z, w) { + if (!w) return this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15]; + return this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15] * w + }, + invert: function() { + var fA0 = this.elements[0] * this.elements[5] - this.elements[1] * this.elements[4]; + var fA1 = this.elements[0] * this.elements[6] - this.elements[2] * this.elements[4]; + var fA2 = this.elements[0] * this.elements[7] - this.elements[3] * this.elements[4]; + var fA3 = this.elements[1] * this.elements[6] - this.elements[2] * this.elements[5]; + var fA4 = this.elements[1] * this.elements[7] - this.elements[3] * this.elements[5]; + var fA5 = this.elements[2] * this.elements[7] - this.elements[3] * this.elements[6]; + var fB0 = this.elements[8] * this.elements[13] - this.elements[9] * this.elements[12]; + var fB1 = this.elements[8] * this.elements[14] - this.elements[10] * this.elements[12]; + var fB2 = this.elements[8] * this.elements[15] - this.elements[11] * this.elements[12]; + var fB3 = this.elements[9] * this.elements[14] - this.elements[10] * this.elements[13]; + var fB4 = this.elements[9] * this.elements[15] - this.elements[11] * this.elements[13]; + var fB5 = this.elements[10] * this.elements[15] - this.elements[11] * this.elements[14]; + var fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0; + if (Math.abs(fDet) <= 1.0E-9) return false; + var kInv = []; + kInv[0] = +this.elements[5] * fB5 - this.elements[6] * fB4 + this.elements[7] * fB3; + kInv[4] = -this.elements[4] * fB5 + this.elements[6] * fB2 - this.elements[7] * fB1; + kInv[8] = +this.elements[4] * fB4 - this.elements[5] * fB2 + this.elements[7] * fB0; + kInv[12] = -this.elements[4] * fB3 + this.elements[5] * fB1 - this.elements[6] * fB0; + kInv[1] = -this.elements[1] * fB5 + this.elements[2] * fB4 - this.elements[3] * fB3; + kInv[5] = +this.elements[0] * fB5 - this.elements[2] * fB2 + this.elements[3] * fB1; + kInv[9] = -this.elements[0] * fB4 + this.elements[1] * fB2 - this.elements[3] * fB0; + kInv[13] = +this.elements[0] * fB3 - this.elements[1] * fB1 + this.elements[2] * fB0; + kInv[2] = +this.elements[13] * fA5 - this.elements[14] * fA4 + this.elements[15] * fA3; + kInv[6] = -this.elements[12] * fA5 + this.elements[14] * fA2 - this.elements[15] * fA1; + kInv[10] = +this.elements[12] * fA4 - this.elements[13] * fA2 + this.elements[15] * fA0; + kInv[14] = -this.elements[12] * fA3 + this.elements[13] * fA1 - this.elements[14] * fA0; + kInv[3] = -this.elements[9] * fA5 + this.elements[10] * fA4 - this.elements[11] * fA3; + kInv[7] = +this.elements[8] * fA5 - this.elements[10] * fA2 + this.elements[11] * fA1; + kInv[11] = -this.elements[8] * fA4 + this.elements[9] * fA2 - this.elements[11] * fA0; + kInv[15] = +this.elements[8] * fA3 - this.elements[9] * fA1 + this.elements[10] * fA0; + var fInvDet = 1 / fDet; + kInv[0] *= fInvDet; + kInv[1] *= fInvDet; + kInv[2] *= fInvDet; + kInv[3] *= fInvDet; + kInv[4] *= fInvDet; + kInv[5] *= fInvDet; + kInv[6] *= fInvDet; + kInv[7] *= fInvDet; + kInv[8] *= fInvDet; + kInv[9] *= fInvDet; + kInv[10] *= fInvDet; + kInv[11] *= fInvDet; + kInv[12] *= fInvDet; + kInv[13] *= fInvDet; + kInv[14] *= fInvDet; + kInv[15] *= fInvDet; + this.elements = kInv.slice(); + return true + }, + toString: function() { + var str = ""; + for (var i = 0; i < 15; i++) str += this.elements[i] + ", "; + str += this.elements[15]; + return str + }, + print: function() { + var digits = printMatrixHelper(this.elements); + var output = "" + p.nfs(this.elements[0], digits, 4) + " " + p.nfs(this.elements[1], digits, 4) + " " + p.nfs(this.elements[2], digits, 4) + " " + p.nfs(this.elements[3], digits, 4) + "\n" + p.nfs(this.elements[4], digits, 4) + " " + p.nfs(this.elements[5], digits, 4) + " " + p.nfs(this.elements[6], digits, 4) + " " + p.nfs(this.elements[7], digits, 4) + "\n" + p.nfs(this.elements[8], digits, 4) + " " + p.nfs(this.elements[9], digits, 4) + " " + p.nfs(this.elements[10], digits, 4) + " " + p.nfs(this.elements[11], digits, 4) + "\n" + p.nfs(this.elements[12], digits, 4) + " " + p.nfs(this.elements[13], digits, 4) + " " + p.nfs(this.elements[14], digits, 4) + " " + p.nfs(this.elements[15], digits, 4) + "\n\n"; + p.println(output) + }, + invTranslate: function(tx, ty, tz) { + this.preApply(1, 0, 0, -tx, 0, 1, 0, -ty, 0, 0, 1, -tz, 0, 0, 0, 1) + }, + invRotateX: function(angle) { + var c = Math.cos(-angle); + var s = Math.sin(-angle); + this.preApply([1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1]) + }, + invRotateY: function(angle) { + var c = Math.cos(-angle); + var s = Math.sin(-angle); + this.preApply([c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1]) + }, + invRotateZ: function(angle) { + var c = Math.cos(-angle); + var s = Math.sin(-angle); + this.preApply([c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]) + }, + invScale: function(x, y, z) { + this.preApply([1 / x, 0, 0, 0, 0, 1 / y, 0, 0, 0, 0, 1 / z, 0, 0, 0, 0, 1]) + } + }; + var PMatrixStack = p.PMatrixStack = function() { + this.matrixStack = [] + }; + PMatrixStack.prototype.load = function() { + var tmpMatrix = drawing.$newPMatrix(); + if (arguments.length === 1) tmpMatrix.set(arguments[0]); + else tmpMatrix.set(arguments); + this.matrixStack.push(tmpMatrix) + }; + Drawing2D.prototype.$newPMatrix = function() { + return new PMatrix2D + }; + Drawing3D.prototype.$newPMatrix = function() { + return new PMatrix3D + }; + PMatrixStack.prototype.push = function() { + this.matrixStack.push(this.peek()) + }; + PMatrixStack.prototype.pop = function() { + return this.matrixStack.pop() + }; + PMatrixStack.prototype.peek = function() { + var tmpMatrix = drawing.$newPMatrix(); + tmpMatrix.set(this.matrixStack[this.matrixStack.length - 1]); + return tmpMatrix + }; + PMatrixStack.prototype.mult = function(matrix) { + this.matrixStack[this.matrixStack.length - 1].apply(matrix) + }; + p.split = function(str, delim) { + return str.split(delim) + }; + p.splitTokens = function(str, tokens) { + if (tokens === undef) return str.split(/\s+/g); + var chars = tokens.split(/()/g), + buffer = "", + len = str.length, + i, c, tokenized = []; + for (i = 0; i < len; i++) { + c = str[i]; + if (chars.indexOf(c) > -1) { + if (buffer !== "") tokenized.push(buffer); + buffer = "" + } else buffer += c + } + if (buffer !== "") tokenized.push(buffer); + return tokenized + }; + p.append = function(array, element) { + array[array.length] = element; + return array + }; + p.concat = function(array1, array2) { + return array1.concat(array2) + }; + p.sort = function(array, numElem) { + var ret = []; + if (array.length > 0) { + var elemsToCopy = numElem > 0 ? numElem : array.length; + for (var i = 0; i < elemsToCopy; i++) ret.push(array[i]); + if (typeof array[0] === "string") ret.sort(); + else ret.sort(function(a, b) { + return a - b + }); + if (numElem > 0) for (var j = ret.length; j < array.length; j++) ret.push(array[j]) + } + return ret + }; + p.splice = function(array, value, index) { + if (value.length === 0) return array; + if (value instanceof Array) for (var i = 0, j = index; i < value.length; j++, i++) array.splice(j, 0, value[i]); + else array.splice(index, 0, value); + return array + }; + p.subset = function(array, offset, length) { + var end = length !== undef ? offset + length : array.length; + return array.slice(offset, end) + }; + p.join = function(array, seperator) { + return array.join(seperator) + }; + p.shorten = function(ary) { + var newary = []; + var len = ary.length; + for (var i = 0; i < len; i++) newary[i] = ary[i]; + newary.pop(); + return newary + }; + p.expand = function(ary, targetSize) { + var temp = ary.slice(0), + newSize = targetSize || ary.length * 2; + temp.length = newSize; + return temp + }; + p.arrayCopy = function() { + var src, srcPos = 0, + dest, destPos = 0, + length; + if (arguments.length === 2) { + src = arguments[0]; + dest = arguments[1]; + length = src.length + } else if (arguments.length === 3) { + src = arguments[0]; + dest = arguments[1]; + length = arguments[2] + } else if (arguments.length === 5) { + src = arguments[0]; + srcPos = arguments[1]; + dest = arguments[2]; + destPos = arguments[3]; + length = arguments[4] + } + for (var i = srcPos, j = destPos; i < length + srcPos; i++, j++) if (dest[j] !== undef) dest[j] = src[i]; + else throw "array index out of bounds exception"; + }; + p.reverse = function(array) { + return array.reverse() + }; + p.mix = function(a, b, f) { + return a + ((b - a) * f >> 8) + }; + p.peg = function(n) { + return n < 0 ? 0 : n > 255 ? 255 : n + }; + p.modes = function() { + var ALPHA_MASK = 4278190080, + RED_MASK = 16711680, + GREEN_MASK = 65280, + BLUE_MASK = 255, + min = Math.min, + max = Math.max; + + function applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) { + var a = min(((c1 & 4278190080) >>> 24) + f, 255) << 24; + var r = ar + ((cr - ar) * f >> 8); + r = (r < 0 ? 0 : r > 255 ? 255 : r) << 16; + var g = ag + ((cg - ag) * f >> 8); + g = (g < 0 ? 0 : g > 255 ? 255 : g) << 8; + var b = ab + ((cb - ab) * f >> 8); + b = b < 0 ? 0 : b > 255 ? 255 : b; + return a | r | g | b + } + return { + replace: function(c1, c2) { + return c2 + }, + blend: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = c1 & RED_MASK, + ag = c1 & GREEN_MASK, + ab = c1 & BLUE_MASK, + br = c2 & RED_MASK, + bg = c2 & GREEN_MASK, + bb = c2 & BLUE_MASK; + return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | ar + ((br - ar) * f >> 8) & RED_MASK | ag + ((bg - ag) * f >> 8) & GREEN_MASK | ab + ((bb - ab) * f >> 8) & BLUE_MASK + }, + add: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24; + return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | min((c1 & RED_MASK) + ((c2 & RED_MASK) >> 8) * f, RED_MASK) & RED_MASK | min((c1 & GREEN_MASK) + ((c2 & GREEN_MASK) >> 8) * f, GREEN_MASK) & GREEN_MASK | min((c1 & BLUE_MASK) + ((c2 & BLUE_MASK) * f >> 8), BLUE_MASK) + }, + subtract: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24; + return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | max((c1 & RED_MASK) - ((c2 & RED_MASK) >> 8) * f, GREEN_MASK) & RED_MASK | max((c1 & GREEN_MASK) - ((c2 & GREEN_MASK) >> 8) * f, BLUE_MASK) & GREEN_MASK | max((c1 & BLUE_MASK) - ((c2 & BLUE_MASK) * f >> 8), 0) + }, + lightest: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24; + return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | max(c1 & RED_MASK, ((c2 & RED_MASK) >> 8) * f) & RED_MASK | max(c1 & GREEN_MASK, ((c2 & GREEN_MASK) >> 8) * f) & GREEN_MASK | max(c1 & BLUE_MASK, (c2 & BLUE_MASK) * f >> 8) + }, + darkest: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = c1 & RED_MASK, + ag = c1 & GREEN_MASK, + ab = c1 & BLUE_MASK, + br = min(c1 & RED_MASK, ((c2 & RED_MASK) >> 8) * f), + bg = min(c1 & GREEN_MASK, ((c2 & GREEN_MASK) >> 8) * f), + bb = min(c1 & BLUE_MASK, (c2 & BLUE_MASK) * f >> 8); + return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | ar + ((br - ar) * f >> 8) & RED_MASK | ag + ((bg - ag) * f >> 8) & GREEN_MASK | ab + ((bb - ab) * f >> 8) & BLUE_MASK + }, + difference: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = ar > br ? ar - br : br - ar, + cg = ag > bg ? ag - bg : bg - ag, + cb = ab > bb ? ab - bb : bb - ab; + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + exclusion: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = ar + br - (ar * br >> 7), + cg = ag + bg - (ag * bg >> 7), + cb = ab + bb - (ab * bb >> 7); + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + multiply: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = ar * br >> 8, + cg = ag * bg >> 8, + cb = ab * bb >> 8; + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + screen: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = 255 - ((255 - ar) * (255 - br) >> 8), + cg = 255 - ((255 - ag) * (255 - bg) >> 8), + cb = 255 - ((255 - ab) * (255 - bb) >> 8); + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + hard_light: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = br < 128 ? ar * br >> 7 : 255 - ((255 - ar) * (255 - br) >> 7), + cg = bg < 128 ? ag * bg >> 7 : 255 - ((255 - ag) * (255 - bg) >> 7), + cb = bb < 128 ? ab * bb >> 7 : 255 - ((255 - ab) * (255 - bb) >> 7); + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + soft_light: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = (ar * br >> 7) + (ar * ar >> 8) - (ar * ar * br >> 15), + cg = (ag * bg >> 7) + (ag * ag >> 8) - (ag * ag * bg >> 15), + cb = (ab * bb >> 7) + (ab * ab >> 8) - (ab * ab * bb >> 15); + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + overlay: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK, + cr = ar < 128 ? ar * br >> 7 : 255 - ((255 - ar) * (255 - br) >> 7), + cg = ag < 128 ? ag * bg >> 7 : 255 - ((255 - ag) * (255 - bg) >> 7), + cb = ab < 128 ? ab * bb >> 7 : 255 - ((255 - ab) * (255 - bb) >> 7); + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + dodge: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK; + var cr = 255; + if (br !== 255) { + cr = (ar << 8) / (255 - br); + cr = cr < 0 ? 0 : cr > 255 ? 255 : cr + } + var cg = 255; + if (bg !== 255) { + cg = (ag << 8) / (255 - bg); + cg = cg < 0 ? 0 : cg > 255 ? 255 : cg + } + var cb = 255; + if (bb !== 255) { + cb = (ab << 8) / (255 - bb); + cb = cb < 0 ? 0 : cb > 255 ? 255 : cb + } + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + }, + burn: function(c1, c2) { + var f = (c2 & ALPHA_MASK) >>> 24, + ar = (c1 & RED_MASK) >> 16, + ag = (c1 & GREEN_MASK) >> 8, + ab = c1 & BLUE_MASK, + br = (c2 & RED_MASK) >> 16, + bg = (c2 & GREEN_MASK) >> 8, + bb = c2 & BLUE_MASK; + var cr = 0; + if (br !== 0) { + cr = (255 - ar << 8) / br; + cr = 255 - (cr < 0 ? 0 : cr > 255 ? 255 : cr) + } + var cg = 0; + if (bg !== 0) { + cg = (255 - ag << 8) / bg; + cg = 255 - (cg < 0 ? 0 : cg > 255 ? 255 : cg) + } + var cb = 0; + if (bb !== 0) { + cb = (255 - ab << 8) / bb; + cb = 255 - (cb < 0 ? 0 : cb > 255 ? 255 : cb) + } + return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) + } + } + }(); + + function color$4(aValue1, aValue2, aValue3, aValue4) { + var r, g, b, a; + if (curColorMode === 3) { + var rgb = p.color.toRGB(aValue1, aValue2, aValue3); + r = rgb[0]; + g = rgb[1]; + b = rgb[2] + } else { + r = Math.round(255 * (aValue1 / colorModeX)); + g = Math.round(255 * (aValue2 / colorModeY)); + b = Math.round(255 * (aValue3 / colorModeZ)) + } + a = Math.round(255 * (aValue4 / colorModeA)); + r = r < 0 ? 0 : r; + g = g < 0 ? 0 : g; + b = b < 0 ? 0 : b; + a = a < 0 ? 0 : a; + r = r > 255 ? 255 : r; + g = g > 255 ? 255 : g; + b = b > 255 ? 255 : b; + a = a > 255 ? 255 : a; + return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255 + } + function color$2(aValue1, aValue2) { + var a; + if (aValue1 & 4278190080) { + a = Math.round(255 * (aValue2 / colorModeA)); + a = a > 255 ? 255 : a; + a = a < 0 ? 0 : a; + return aValue1 - (aValue1 & 4278190080) + (a << 24 & 4278190080) + } + if (curColorMode === 1) return color$4(aValue1, aValue1, aValue1, aValue2); + if (curColorMode === 3) return color$4(0, 0, aValue1 / colorModeX * colorModeZ, aValue2) + } + function color$1(aValue1) { + if (aValue1 <= colorModeX && aValue1 >= 0) { + if (curColorMode === 1) return color$4(aValue1, aValue1, aValue1, colorModeA); + if (curColorMode === 3) return color$4(0, 0, aValue1 / colorModeX * colorModeZ, colorModeA) + } + if (aValue1) { + if (aValue1 > 2147483647) aValue1 -= 4294967296; + return aValue1 + } + } + p.color = function(aValue1, aValue2, aValue3, aValue4) { + if (aValue1 !== undef && aValue2 !== undef && aValue3 !== undef && aValue4 !== undef) return color$4(aValue1, aValue2, aValue3, aValue4); + if (aValue1 !== undef && aValue2 !== undef && aValue3 !== undef) return color$4(aValue1, aValue2, aValue3, colorModeA); + if (aValue1 !== undef && aValue2 !== undef) return color$2(aValue1, aValue2); + if (typeof aValue1 === "number") return color$1(aValue1); + return color$4(colorModeX, colorModeY, colorModeZ, colorModeA) + }; + p.color.toString = function(colorInt) { + return "rgba(" + ((colorInt >> 16) & 255) + "," + ((colorInt >> 8) & 255) + "," + (colorInt & 255) + "," + ((colorInt >> 24) & 255) / 255 + ")" + }; + p.color.toInt = function(r, g, b, a) { + return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255 + }; + p.color.toArray = function(colorInt) { + return [(colorInt >> 16) & 255, (colorInt >> 8) & 255, colorInt & 255, (colorInt >> 24) & 255] + }; + p.color.toGLArray = function(colorInt) { + return [((colorInt & 16711680) >>> 16) / 255, ((colorInt >> 8) & 255) / 255, (colorInt & 255) / 255, ((colorInt >> 24) & 255) / 255] + }; + p.color.toRGB = function(h, s, b) { + h = h > colorModeX ? colorModeX : h; + s = s > colorModeY ? colorModeY : s; + b = b > colorModeZ ? colorModeZ : b; + h = h / colorModeX * 360; + s = s / colorModeY * 100; + b = b / colorModeZ * 100; + var br = Math.round(b / 100 * 255); + if (s === 0) return [br, br, br]; + var hue = h % 360; + var f = hue % 60; + var p = Math.round(b * (100 - s) / 1E4 * 255); + var q = Math.round(b * (6E3 - s * f) / 6E5 * 255); + var t = Math.round(b * (6E3 - s * (60 - f)) / 6E5 * 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 colorToHSB(colorInt) { + var red, green, blue; + red = ((colorInt >> 16) & 255) / 255; + green = ((colorInt >> 8) & 255) / 255; + blue = (colorInt & 255) / 255; + var max = p.max(p.max(red, green), blue), + min = p.min(p.min(red, green), blue), + hue, saturation; + if (min === max) return [0, 0, max * colorModeZ]; + saturation = (max - min) / max; + if (red === max) hue = (green - blue) / (max - min); + else if (green === max) hue = 2 + (blue - red) / (max - min); + else hue = 4 + (red - green) / (max - min); + hue /= 6; + if (hue < 0) hue += 1; + else if (hue > 1) hue -= 1; + return [hue * colorModeX, saturation * colorModeY, max * colorModeZ] + } + p.brightness = function(colInt) { + return colorToHSB(colInt)[2] + }; + p.saturation = function(colInt) { + return colorToHSB(colInt)[1] + }; + p.hue = function(colInt) { + return colorToHSB(colInt)[0] + }; + p.red = function(aColor) { + return ((aColor >> 16) & 255) / 255 * colorModeX + }; + p.green = function(aColor) { + return ((aColor & 65280) >>> 8) / 255 * colorModeY + }; + p.blue = function(aColor) { + return (aColor & 255) / 255 * colorModeZ + }; + p.alpha = function(aColor) { + return ((aColor >> 24) & 255) / 255 * colorModeA + }; + p.lerpColor = function(c1, c2, amt) { + var r, g, b, a, r1, g1, b1, a1, r2, g2, b2, a2; + var hsb1, hsb2, rgb, h, s; + var colorBits1 = p.color(c1); + var colorBits2 = p.color(c2); + if (curColorMode === 3) { + hsb1 = colorToHSB(colorBits1); + a1 = ((colorBits1 >> 24) & 255) / colorModeA; + hsb2 = colorToHSB(colorBits2); + a2 = ((colorBits2 & 4278190080) >>> 24) / colorModeA; + h = p.lerp(hsb1[0], hsb2[0], amt); + s = p.lerp(hsb1[1], hsb2[1], amt); + b = p.lerp(hsb1[2], hsb2[2], amt); + rgb = p.color.toRGB(h, s, b); + a = p.lerp(a1, a2, amt) * colorModeA; + return a << 24 & 4278190080 | (rgb[0] & 255) << 16 | (rgb[1] & 255) << 8 | rgb[2] & 255 + } + r1 = (colorBits1 >> 16) & 255; + g1 = (colorBits1 >> 8) & 255; + b1 = colorBits1 & 255; + a1 = ((colorBits1 >> 24) & 255) / colorModeA; + r2 = (colorBits2 & 16711680) >>> 16; + g2 = (colorBits2 >> 8) & 255; + b2 = colorBits2 & 255; + a2 = ((colorBits2 >> 24) & 255) / colorModeA; + r = p.lerp(r1, r2, amt) | 0; + g = p.lerp(g1, g2, amt) | 0; + b = p.lerp(b1, b2, amt) | 0; + a = p.lerp(a1, a2, amt) * colorModeA; + return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255 + }; + p.colorMode = function() { + curColorMode = arguments[0]; + if (arguments.length > 1) { + colorModeX = arguments[1]; + colorModeY = arguments[2] || arguments[1]; + colorModeZ = arguments[3] || arguments[1]; + colorModeA = arguments[4] || arguments[1] + } + }; + p.blendColor = function(c1, c2, mode) { + if (mode === 0) return p.modes.replace(c1, c2); + else if (mode === 1) return p.modes.blend(c1, c2); + else if (mode === 2) return p.modes.add(c1, c2); + else if (mode === 4) return p.modes.subtract(c1, c2); + else if (mode === 8) return p.modes.lightest(c1, c2); + else if (mode === 16) return p.modes.darkest(c1, c2); + else if (mode === 32) return p.modes.difference(c1, c2); + else if (mode === 64) return p.modes.exclusion(c1, c2); + else if (mode === 128) return p.modes.multiply(c1, c2); + else if (mode === 256) return p.modes.screen(c1, c2); + else if (mode === 1024) return p.modes.hard_light(c1, c2); + else if (mode === 2048) return p.modes.soft_light(c1, c2); + else if (mode === 512) return p.modes.overlay(c1, c2); + else if (mode === 4096) return p.modes.dodge(c1, c2); + else if (mode === 8192) return p.modes.burn(c1, c2) + }; + + function saveContext() { + curContext.save() + } + function restoreContext() { + curContext.restore(); + isStrokeDirty = true; + isFillDirty = true + } + p.printMatrix = function() { + modelView.print() + }; + Drawing2D.prototype.translate = function(x, y) { + modelView.translate(x, y); + modelViewInv.invTranslate(x, y); + curContext.translate(x, y) + }; + Drawing3D.prototype.translate = function(x, y, z) { + modelView.translate(x, y, z); + modelViewInv.invTranslate(x, y, z) + }; + Drawing2D.prototype.scale = function(x, y) { + modelView.scale(x, y); + modelViewInv.invScale(x, y); + curContext.scale(x, y || x) + }; + Drawing3D.prototype.scale = function(x, y, z) { + modelView.scale(x, y, z); + modelViewInv.invScale(x, y, z) + }; + Drawing2D.prototype.transform = function(pmatrix) { + var e = pmatrix.array(); + curContext.transform(e[0], e[3], e[1], e[4], e[2], e[5]) + }; + Drawing3D.prototype.transformm = function(pmatrix3d) { + throw "p.transform is currently not supported in 3D mode"; + }; + Drawing2D.prototype.pushMatrix = function() { + userMatrixStack.load(modelView); + userReverseMatrixStack.load(modelViewInv); + saveContext() + }; + Drawing3D.prototype.pushMatrix = function() { + userMatrixStack.load(modelView); + userReverseMatrixStack.load(modelViewInv) + }; + Drawing2D.prototype.popMatrix = function() { + modelView.set(userMatrixStack.pop()); + modelViewInv.set(userReverseMatrixStack.pop()); + restoreContext() + }; + Drawing3D.prototype.popMatrix = function() { + modelView.set(userMatrixStack.pop()); + modelViewInv.set(userReverseMatrixStack.pop()) + }; + Drawing2D.prototype.resetMatrix = function() { + modelView.reset(); + modelViewInv.reset(); + curContext.setTransform(1, 0, 0, 1, 0, 0) + }; + Drawing3D.prototype.resetMatrix = function() { + modelView.reset(); + modelViewInv.reset() + }; + DrawingShared.prototype.applyMatrix = function() { + var a = arguments; + modelView.apply(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]); + modelViewInv.invApply(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]) + }; + Drawing2D.prototype.applyMatrix = function() { + var a = arguments; + for (var cnt = a.length; cnt < 16; cnt++) a[cnt] = 0; + a[10] = a[15] = 1; + DrawingShared.prototype.applyMatrix.apply(this, a) + }; + p.rotateX = function(angleInRadians) { + modelView.rotateX(angleInRadians); + modelViewInv.invRotateX(angleInRadians) + }; + Drawing2D.prototype.rotateZ = function() { + throw "rotateZ() is not supported in 2D mode. Use rotate(float) instead."; + }; + Drawing3D.prototype.rotateZ = function(angleInRadians) { + modelView.rotateZ(angleInRadians); + modelViewInv.invRotateZ(angleInRadians) + }; + p.rotateY = function(angleInRadians) { + modelView.rotateY(angleInRadians); + modelViewInv.invRotateY(angleInRadians) + }; + Drawing2D.prototype.rotate = function(angleInRadians) { + modelView.rotateZ(angleInRadians); + modelViewInv.invRotateZ(angleInRadians); + curContext.rotate(angleInRadians) + }; + Drawing3D.prototype.rotate = function(angleInRadians) { + p.rotateZ(angleInRadians) + }; + Drawing2D.prototype.shearX = function(angleInRadians) { + modelView.shearX(angleInRadians); + curContext.transform(1, 0, angleInRadians, 1, 0, 0) + }; + Drawing3D.prototype.shearX = function(angleInRadians) { + modelView.shearX(angleInRadians) + }; + Drawing2D.prototype.shearY = function(angleInRadians) { + modelView.shearY(angleInRadians); + curContext.transform(1, angleInRadians, 0, 1, 0, 0) + }; + Drawing3D.prototype.shearY = function(angleInRadians) { + modelView.shearY(angleInRadians) + }; + p.pushStyle = function() { + saveContext(); + p.pushMatrix(); + var newState = { + "doFill": doFill, + "currentFillColor": currentFillColor, + "doStroke": doStroke, + "currentStrokeColor": currentStrokeColor, + "curTint": curTint, + "curRectMode": curRectMode, + "curColorMode": curColorMode, + "colorModeX": colorModeX, + "colorModeZ": colorModeZ, + "colorModeY": colorModeY, + "colorModeA": colorModeA, + "curTextFont": curTextFont, + "horizontalTextAlignment": horizontalTextAlignment, + "verticalTextAlignment": verticalTextAlignment, + "textMode": textMode, + "curFontName": curFontName, + "curTextSize": curTextSize, + "curTextAscent": curTextAscent, + "curTextDescent": curTextDescent, + "curTextLeading": curTextLeading + }; + styleArray.push(newState) + }; + p.popStyle = function() { + var oldState = styleArray.pop(); + if (oldState) { + restoreContext(); + p.popMatrix(); + doFill = oldState.doFill; + currentFillColor = oldState.currentFillColor; + doStroke = oldState.doStroke; + currentStrokeColor = oldState.currentStrokeColor; + curTint = oldState.curTint; + curRectMode = oldState.curRectMode; + curColorMode = oldState.curColorMode; + colorModeX = oldState.colorModeX; + colorModeZ = oldState.colorModeZ; + colorModeY = oldState.colorModeY; + colorModeA = oldState.colorModeA; + curTextFont = oldState.curTextFont; + curFontName = oldState.curFontName; + curTextSize = oldState.curTextSize; + horizontalTextAlignment = oldState.horizontalTextAlignment; + verticalTextAlignment = oldState.verticalTextAlignment; + textMode = oldState.textMode; + curTextAscent = oldState.curTextAscent; + curTextDescent = oldState.curTextDescent; + curTextLeading = oldState.curTextLeading + } else throw "Too many popStyle() without enough pushStyle()"; + }; + p.year = function() { + return (new Date).getFullYear() + }; + p.month = function() { + return (new Date).getMonth() + 1 + }; + p.day = function() { + return (new Date).getDate() + }; + p.hour = function() { + return (new Date).getHours() + }; + p.minute = function() { + return (new Date).getMinutes() + }; + p.second = function() { + return (new Date).getSeconds() + }; + p.millis = function() { + return Date.now() - start + }; + + function redrawHelper() { + var sec = (Date.now() - timeSinceLastFPS) / 1E3; + framesSinceLastFPS++; + var fps = framesSinceLastFPS / sec; + if (sec > 0.5) { + timeSinceLastFPS = Date.now(); + framesSinceLastFPS = 0; + p.__frameRate = fps + } + p.frameCount++ + } + Drawing2D.prototype.redraw = function() { + redrawHelper(); + curContext.lineWidth = lineWidth; + var pmouseXLastEvent = p.pmouseX, + pmouseYLastEvent = p.pmouseY; + p.pmouseX = pmouseXLastFrame; + p.pmouseY = pmouseYLastFrame; + saveContext(); + p.draw(); + restoreContext(); + pmouseXLastFrame = p.mouseX; + pmouseYLastFrame = p.mouseY; + p.pmouseX = pmouseXLastEvent; + p.pmouseY = pmouseYLastEvent + }; + Drawing3D.prototype.redraw = function() { + redrawHelper(); + var pmouseXLastEvent = p.pmouseX, + pmouseYLastEvent = p.pmouseY; + p.pmouseX = pmouseXLastFrame; + p.pmouseY = pmouseYLastFrame; + curContext.clear(curContext.DEPTH_BUFFER_BIT); + curContextCache = { + attributes: {}, + locations: {} + }; + p.noLights(); + p.lightFalloff(1, 0, 0); + p.shininess(1); + p.ambient(255, 255, 255); + p.specular(0, 0, 0); + p.emissive(0, 0, 0); + p.camera(); + p.draw(); + pmouseXLastFrame = p.mouseX; + pmouseYLastFrame = p.mouseY; + p.pmouseX = pmouseXLastEvent; + p.pmouseY = pmouseYLastEvent + }; + p.noLoop = function() { + doLoop = false; + loopStarted = false; + clearInterval(looping); + curSketch.onPause() + }; + p.loop = function() { + if (loopStarted) return; + timeSinceLastFPS = Date.now(); + framesSinceLastFPS = 0; + looping = window.setInterval(function() { + try { + curSketch.onFrameStart(); + p.redraw(); + curSketch.onFrameEnd() + } catch(e_loop) { + window.clearInterval(looping); + throw e_loop; + } + }, + curMsPerFrame); + doLoop = true; + loopStarted = true; + curSketch.onLoop() + }; + p.frameRate = function(aRate) { + curFrameRate = aRate; + curMsPerFrame = 1E3 / curFrameRate; + if (doLoop) { + p.noLoop(); + p.loop() + } + }; + var eventHandlers = []; + + function attachEventHandler(elem, type, fn) { + if (elem.addEventListener) elem.addEventListener(type, fn, false); + else elem.attachEvent("on" + type, fn); + eventHandlers.push({ + elem: elem, + type: type, + fn: fn + }) + } + function detachEventHandler(eventHandler) { + var elem = eventHandler.elem, + type = eventHandler.type, + fn = eventHandler.fn; + if (elem.removeEventListener) elem.removeEventListener(type, fn, false); + else if (elem.detachEvent) elem.detachEvent("on" + type, fn) + } + p.exit = function() { + window.clearInterval(looping); + removeInstance(p.externals.canvas.id); + delete curElement.onmousedown; + for (var lib in Processing.lib) if (Processing.lib.hasOwnProperty(lib)) if (Processing.lib[lib].hasOwnProperty("detach")) Processing.lib[lib].detach(p); + var i = eventHandlers.length; + while (i--) detachEventHandler(eventHandlers[i]); + curSketch.onExit() + }; + p.cursor = function() { + if (arguments.length > 1 || arguments.length === 1 && arguments[0] instanceof p.PImage) { + var image = arguments[0], + x, y; + if (arguments.length >= 3) { + x = arguments[1]; + y = arguments[2]; + if (x < 0 || y < 0 || y >= image.height || x >= image.width) throw "x and y must be non-negative and less than the dimensions of the image"; + } else { + x = image.width >>> 1; + y = image.height >>> 1 + } + var imageDataURL = image.toDataURL(); + var style = 'url("' + imageDataURL + '") ' + x + " " + y + ", default"; + curCursor = curElement.style.cursor = style + } else if (arguments.length === 1) { + var mode = arguments[0]; + curCursor = curElement.style.cursor = mode + } else curCursor = curElement.style.cursor = oldCursor + }; + p.noCursor = function() { + curCursor = curElement.style.cursor = PConstants.NOCURSOR + }; + p.link = function(href, target) { + if (target !== undef) window.open(href, target); + else window.location = href + }; + p.beginDraw = nop; + p.endDraw = nop; + Drawing2D.prototype.toImageData = function(x, y, w, h) { + x = x !== undef ? x : 0; + y = y !== undef ? y : 0; + w = w !== undef ? w : p.width; + h = h !== undef ? h : p.height; + return curContext.getImageData(x, y, w, h) + }; + Drawing3D.prototype.toImageData = function(x, y, w, h) { + x = x !== undef ? x : 0; + y = y !== undef ? y : 0; + w = w !== undef ? w : p.width; + h = h !== undef ? h : p.height; + var c = document.createElement("canvas"), + ctx = c.getContext("2d"), + obj = ctx.createImageData(w, h), + uBuff = new Uint8Array(w * h * 4); + curContext.readPixels(x, y, w, h, curContext.RGBA, curContext.UNSIGNED_BYTE, uBuff); + for (var i = 0, ul = uBuff.length, obj_data = obj.data; i < ul; i++) obj_data[i] = uBuff[(h - 1 - Math.floor(i / 4 / w)) * w * 4 + i % (w * 4)]; + return obj + }; + p.status = function(text) { + window.status = text + }; + p.binary = function(num, numBits) { + var bit; + if (numBits > 0) bit = numBits; + else if (num instanceof Char) { + bit = 16; + num |= 0 + } else { + bit = 32; + while (bit > 1 && !(num >>> bit - 1 & 1)) bit-- + } + var result = ""; + while (bit > 0) result += num >>> --bit & 1 ? "1" : "0"; + return result + }; + p.unbinary = function(binaryString) { + var i = binaryString.length - 1, + mask = 1, + result = 0; + while (i >= 0) { + var ch = binaryString[i--]; + if (ch !== "0" && ch !== "1") throw "the value passed into unbinary was not an 8 bit binary number"; + if (ch === "1") result += mask; + mask <<= 1 + } + return result + }; + + function nfCoreScalar(value, plus, minus, leftDigits, rightDigits, group) { + var sign = value < 0 ? minus : plus; + var autoDetectDecimals = rightDigits === 0; + var rightDigitsOfDefault = rightDigits === undef || rightDigits < 0 ? 0 : rightDigits; + var absValue = Math.abs(value); + if (autoDetectDecimals) { + rightDigitsOfDefault = 1; + absValue *= 10; + while (Math.abs(Math.round(absValue) - absValue) > 1.0E-6 && rightDigitsOfDefault < 7) { + ++rightDigitsOfDefault; + absValue *= 10 + } + } else if (rightDigitsOfDefault !== 0) absValue *= Math.pow(10, rightDigitsOfDefault); + var number, doubled = absValue * 2; + if (Math.floor(absValue) === absValue) number = absValue; + else if (Math.floor(doubled) === doubled) { + var floored = Math.floor(absValue); + number = floored + floored % 2 + } else number = Math.round(absValue); + var buffer = ""; + var totalDigits = leftDigits + rightDigitsOfDefault; + while (totalDigits > 0 || number > 0) { + totalDigits--; + buffer = "" + number % 10 + buffer; + number = Math.floor(number / 10) + } + if (group !== undef) { + var i = buffer.length - 3 - rightDigitsOfDefault; + while (i > 0) { + buffer = buffer.substring(0, i) + group + buffer.substring(i); + i -= 3 + } + } + if (rightDigitsOfDefault > 0) return sign + buffer.substring(0, buffer.length - rightDigitsOfDefault) + "." + buffer.substring(buffer.length - rightDigitsOfDefault, buffer.length); + return sign + buffer + } + function nfCore(value, plus, minus, leftDigits, rightDigits, group) { + if (value instanceof Array) { + var arr = []; + for (var i = 0, len = value.length; i < len; i++) arr.push(nfCoreScalar(value[i], plus, minus, leftDigits, rightDigits, group)); + return arr + } + return nfCoreScalar(value, plus, minus, leftDigits, rightDigits, group) + } + p.nf = function(value, leftDigits, rightDigits) { + return nfCore(value, "", "-", leftDigits, rightDigits) + }; + p.nfs = function(value, leftDigits, rightDigits) { + return nfCore(value, " ", "-", leftDigits, rightDigits) + }; + p.nfp = function(value, leftDigits, rightDigits) { + return nfCore(value, "+", "-", leftDigits, rightDigits) + }; + p.nfc = function(value, leftDigits, rightDigits) { + return nfCore(value, "", "-", leftDigits, rightDigits, ",") + }; + var decimalToHex = function(d, padding) { + padding = padding === undef || padding === null ? padding = 8 : padding; + if (d < 0) d = 4294967295 + d + 1; + var hex = Number(d).toString(16).toUpperCase(); + while (hex.length < padding) hex = "0" + hex; + if (hex.length >= padding) hex = hex.substring(hex.length - padding, hex.length); + return hex + }; + p.hex = function(value, len) { + if (arguments.length === 1) if (value instanceof Char) len = 4; + else len = 8; + return decimalToHex(value, len) + }; + + function unhexScalar(hex) { + var value = parseInt("0x" + hex, 16); + if (value > 2147483647) value -= 4294967296; + return value + } + p.unhex = function(hex) { + if (hex instanceof Array) { + var arr = []; + for (var i = 0; i < hex.length; i++) arr.push(unhexScalar(hex[i])); + return arr + } + return unhexScalar(hex) + }; + p.loadStrings = function(filename) { + if (localStorage[filename]) return localStorage[filename].split("\n"); + var filecontent = ajax(filename); + if (typeof filecontent !== "string" || filecontent === "") return []; + filecontent = filecontent.replace(/(\r\n?)/g, "\n").replace(/\n$/, ""); + return filecontent.split("\n") + }; + p.saveStrings = function(filename, strings) { + localStorage[filename] = strings.join("\n") + }; + p.loadBytes = function(url) { + var string = ajax(url); + var ret = []; + for (var i = 0; i < string.length; i++) ret.push(string.charCodeAt(i)); + return ret + }; + + function removeFirstArgument(args) { + return Array.prototype.slice.call(args, 1) + } + p.matchAll = function(aString, aRegExp) { + var results = [], + latest; + var regexp = new RegExp(aRegExp, "g"); + while ((latest = regexp.exec(aString)) !== null) { + results.push(latest); + if (latest[0].length === 0)++regexp.lastIndex + } + return results.length > 0 ? results : null + }; + p.__contains = function(subject, subStr) { + if (typeof subject !== "string") return subject.contains.apply(subject, removeFirstArgument(arguments)); + return subject !== null && subStr !== null && typeof subStr === "string" && subject.indexOf(subStr) > -1 + }; + p.__replaceAll = function(subject, regex, replacement) { + if (typeof subject !== "string") return subject.replaceAll.apply(subject, removeFirstArgument(arguments)); + return subject.replace(new RegExp(regex, "g"), replacement) + }; + p.__replaceFirst = function(subject, regex, replacement) { + if (typeof subject !== "string") return subject.replaceFirst.apply(subject, removeFirstArgument(arguments)); + return subject.replace(new RegExp(regex, ""), replacement) + }; + p.__replace = function(subject, what, replacement) { + if (typeof subject !== "string") return subject.replace.apply(subject, removeFirstArgument(arguments)); + if (what instanceof RegExp) return subject.replace(what, replacement); + if (typeof what !== "string") what = what.toString(); + if (what === "") return subject; + var i = subject.indexOf(what); + if (i < 0) return subject; + var j = 0, + result = ""; + do { + result += subject.substring(j, i) + replacement; + j = i + what.length + } while ((i = subject.indexOf(what, j)) >= 0); + return result + subject.substring(j) + }; + p.__equals = function(subject, other) { + if (subject.equals instanceof + Function) return subject.equals.apply(subject, removeFirstArgument(arguments)); + return subject.valueOf() === other.valueOf() + }; + p.__equalsIgnoreCase = function(subject, other) { + if (typeof subject !== "string") return subject.equalsIgnoreCase.apply(subject, removeFirstArgument(arguments)); + return subject.toLowerCase() === other.toLowerCase() + }; + p.__toCharArray = function(subject) { + if (typeof subject !== "string") return subject.toCharArray.apply(subject, removeFirstArgument(arguments)); + var chars = []; + for (var i = 0, len = subject.length; i < len; ++i) chars[i] = new Char(subject.charAt(i)); + return chars + }; + p.__split = function(subject, regex, limit) { + if (typeof subject !== "string") return subject.split.apply(subject, removeFirstArgument(arguments)); + var pattern = new RegExp(regex); + if (limit === undef || limit < 1) return subject.split(pattern); + var result = [], + currSubject = subject, + pos; + while ((pos = currSubject.search(pattern)) !== -1 && result.length < limit - 1) { + var match = pattern.exec(currSubject).toString(); + result.push(currSubject.substring(0, pos)); + currSubject = currSubject.substring(pos + match.length) + } + if (pos !== -1 || currSubject !== "") result.push(currSubject); + return result + }; + p.__codePointAt = function(subject, idx) { + var code = subject.charCodeAt(idx), + hi, low; + if (55296 <= code && code <= 56319) { + hi = code; + low = subject.charCodeAt(idx + 1); + return (hi - 55296) * 1024 + (low - 56320) + 65536 + } + return code + }; + p.match = function(str, regexp) { + return str.match(regexp) + }; + p.__matches = function(str, regexp) { + return (new RegExp(regexp)).test(str) + }; + p.__startsWith = function(subject, prefix, toffset) { + if (typeof subject !== "string") return subject.startsWith.apply(subject, removeFirstArgument(arguments)); + toffset = toffset || 0; + if (toffset < 0 || toffset > subject.length) return false; + return prefix === "" || prefix === subject ? true : subject.indexOf(prefix) === toffset + }; + p.__endsWith = function(subject, suffix) { + if (typeof subject !== "string") return subject.endsWith.apply(subject, removeFirstArgument(arguments)); + var suffixLen = suffix ? suffix.length : 0; + return suffix === "" || suffix === subject ? true : subject.indexOf(suffix) === subject.length - suffixLen + }; + p.__hashCode = function(subject) { + if (subject.hashCode instanceof + Function) return subject.hashCode.apply(subject, removeFirstArgument(arguments)); + return virtHashCode(subject) + }; + p.__printStackTrace = function(subject) { + p.println("Exception: " + subject.toString()) + }; + var logBuffer = []; + p.println = function(message) { + var bufferLen = logBuffer.length; + if (bufferLen) { + Processing.logger.log(logBuffer.join("")); + logBuffer.length = 0 + } + if (arguments.length === 0 && bufferLen === 0) Processing.logger.log(""); + else if (arguments.length !== 0) Processing.logger.log(message) + }; + p.print = function(message) { + logBuffer.push(message) + }; + p.str = function(val) { + if (val instanceof Array) { + var arr = []; + for (var i = 0; i < val.length; i++) arr.push(val[i].toString() + ""); + return arr + } + return val.toString() + "" + }; + p.trim = function(str) { + if (str instanceof Array) { + var arr = []; + for (var i = 0; i < str.length; i++) arr.push(str[i].replace(/^\s*/, "").replace(/\s*$/, "").replace(/\r*$/, "")); + return arr + } + return str.replace(/^\s*/, "").replace(/\s*$/, "").replace(/\r*$/, "") + }; + + function booleanScalar(val) { + if (typeof val === "number") return val !== 0; + if (typeof val === "boolean") return val; + if (typeof val === "string") return val.toLowerCase() === "true"; + if (val instanceof Char) return val.code === 49 || val.code === 84 || val.code === 116 + } + p.parseBoolean = function(val) { + if (val instanceof Array) { + var ret = []; + for (var i = 0; i < val.length; i++) ret.push(booleanScalar(val[i])); + return ret + } + return booleanScalar(val) + }; + p.parseByte = function(what) { + if (what instanceof Array) { + var bytes = []; + for (var i = 0; i < what.length; i++) bytes.push(0 - (what[i] & 128) | what[i] & 127); + return bytes + } + return 0 - (what & 128) | what & 127 + }; + p.parseChar = function(key) { + if (typeof key === "number") return new Char(String.fromCharCode(key & 65535)); + if (key instanceof Array) { + var ret = []; + for (var i = 0; i < key.length; i++) ret.push(new Char(String.fromCharCode(key[i] & 65535))); + return ret + } + throw "char() may receive only one argument of type int, byte, int[], or byte[]."; + }; + + function floatScalar(val) { + if (typeof val === "number") return val; + if (typeof val === "boolean") return val ? 1 : 0; + if (typeof val === "string") return parseFloat(val); + if (val instanceof Char) return val.code + } + p.parseFloat = function(val) { + if (val instanceof + Array) { + var ret = []; + for (var i = 0; i < val.length; i++) ret.push(floatScalar(val[i])); + return ret + } + return floatScalar(val) + }; + + function intScalar(val, radix) { + if (typeof val === "number") return val & 4294967295; + if (typeof val === "boolean") return val ? 1 : 0; + if (typeof val === "string") { + var number = parseInt(val, radix || 10); + return number & 4294967295 + } + if (val instanceof Char) return val.code + } + p.parseInt = function(val, radix) { + if (val instanceof Array) { + var ret = []; + for (var i = 0; i < val.length; i++) if (typeof val[i] === "string" && !/^\s*[+\-]?\d+\s*$/.test(val[i])) ret.push(0); + else ret.push(intScalar(val[i], radix)); + return ret + } + return intScalar(val, radix) + }; + p.__int_cast = function(val) { + return 0 | val + }; + p.__instanceof = function(obj, type) { + if (typeof type !== "function") throw "Function is expected as type argument for instanceof operator"; + if (typeof obj === "string") return type === Object || type === String; + if (obj instanceof type) return true; + if (typeof obj !== "object" || obj === null) return false; + var objType = obj.constructor; + if (type.$isInterface) { + var interfaces = []; + while (objType) { + if (objType.$interfaces) interfaces = interfaces.concat(objType.$interfaces); + objType = objType.$base + } + while (interfaces.length > 0) { + var i = interfaces.shift(); + if (i === type) return true; + if (i.$interfaces) interfaces = interfaces.concat(i.$interfaces) + } + return false + } + while (objType.hasOwnProperty("$base")) { + objType = objType.$base; + if (objType === type) return true + } + return false + }; + p.abs = Math.abs; + p.ceil = Math.ceil; + p.constrain = function(aNumber, aMin, aMax) { + return aNumber > aMax ? aMax : aNumber < aMin ? aMin : aNumber + }; + p.dist = function() { + var dx, dy, dz; + if (arguments.length === 4) { + dx = arguments[0] - arguments[2]; + dy = arguments[1] - arguments[3]; + return Math.sqrt(dx * dx + dy * dy) + } + if (arguments.length === 6) { + dx = arguments[0] - arguments[3]; + dy = arguments[1] - arguments[4]; + dz = arguments[2] - arguments[5]; + return Math.sqrt(dx * dx + dy * dy + dz * dz) + } + }; + p.exp = Math.exp; + p.floor = Math.floor; + p.lerp = function(value1, value2, amt) { + return (value2 - value1) * amt + value1 + }; + p.log = Math.log; + p.mag = function(a, b, c) { + if (c) return Math.sqrt(a * a + b * b + c * c); + return Math.sqrt(a * a + b * b) + }; + p.map = function(value, istart, istop, ostart, ostop) { + return ostart + (ostop - ostart) * ((value - istart) / (istop - istart)) + }; + p.max = function() { + if (arguments.length === 2) return arguments[0] < arguments[1] ? arguments[1] : arguments[0]; + var numbers = arguments.length === 1 ? arguments[0] : arguments; + if (! ("length" in numbers && numbers.length > 0)) throw "Non-empty array is expected"; + var max = numbers[0], + count = numbers.length; + for (var i = 1; i < count; ++i) if (max < numbers[i]) max = numbers[i]; + return max + }; + p.min = function() { + if (arguments.length === 2) return arguments[0] < arguments[1] ? arguments[0] : arguments[1]; + var numbers = arguments.length === 1 ? arguments[0] : arguments; + if (! ("length" in numbers && numbers.length > 0)) throw "Non-empty array is expected"; + var min = numbers[0], + count = numbers.length; + for (var i = 1; i < count; ++i) if (min > numbers[i]) min = numbers[i]; + return min + }; + p.norm = function(aNumber, low, high) { + return (aNumber - low) / (high - low) + }; + p.pow = Math.pow; + p.round = Math.round; + p.sq = function(aNumber) { + return aNumber * aNumber + }; + p.sqrt = Math.sqrt; + p.acos = Math.acos; + p.asin = Math.asin; + p.atan = Math.atan; + p.atan2 = Math.atan2; + p.cos = Math.cos; + p.degrees = function(aAngle) { + return aAngle * 180 / Math.PI + }; + p.radians = function(aAngle) { + return aAngle / 180 * Math.PI + }; + p.sin = Math.sin; + p.tan = Math.tan; + var currentRandom = Math.random; + p.random = function() { + if (arguments.length === 0) return currentRandom(); + if (arguments.length === 1) return currentRandom() * arguments[0]; + var aMin = arguments[0], + aMax = arguments[1]; + return currentRandom() * (aMax - aMin) + aMin + }; + + function Marsaglia(i1, i2) { + var z = i1 || 362436069, + w = i2 || 521288629; + var nextInt = function() { + z = 36969 * (z & 65535) + (z >>> 16) & 4294967295; + w = 18E3 * (w & 65535) + (w >>> 16) & 4294967295; + return ((z & 65535) << 16 | w & 65535) & 4294967295 + }; + this.nextDouble = function() { + var i = nextInt() / 4294967296; + return i < 0 ? 1 + i : i + }; + this.nextInt = nextInt + } + Marsaglia.createRandomized = function() { + var now = new Date; + return new Marsaglia(now / 6E4 & 4294967295, now & 4294967295) + }; + p.randomSeed = function(seed) { + currentRandom = (new Marsaglia(seed)).nextDouble + }; + p.Random = function(seed) { + var haveNextNextGaussian = false, + nextNextGaussian, random; + this.nextGaussian = function() { + if (haveNextNextGaussian) { + haveNextNextGaussian = false; + return nextNextGaussian + } + var v1, v2, s; + do { + v1 = 2 * random() - 1; + v2 = 2 * random() - 1; + 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 + }; + random = seed === undef ? Math.random : (new Marsaglia(seed)).nextDouble + }; + + function PerlinNoise(seed) { + var rnd = seed !== undef ? new Marsaglia(seed) : Marsaglia.createRandomized(); + var i, j; + var perm = new Uint8Array(512); + for (i = 0; i < 256; ++i) perm[i] = i; + for (i = 0; i < 256; ++i) { + var t = perm[j = rnd.nextInt() & 255]; + perm[j] = perm[i]; + perm[i] = t + } + for (i = 0; i < 256; ++i) perm[i + 256] = perm[i]; + + function grad3d(i, x, y, z) { + var h = i & 15; + var u = h < 8 ? x : y, + v = h < 4 ? y : h === 12 || h === 14 ? x : z; + return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v) + } + function grad2d(i, x, y) { + var v = (i & 1) === 0 ? x : y; + return (i & 2) === 0 ? -v : v + } + function grad1d(i, x) { + return (i & 1) === 0 ? -x : x + } + function lerp(t, a, b) { + return a + t * (b - a) + } + this.noise3d = function(x, y, z) { + var X = Math.floor(x) & 255, + Y = Math.floor(y) & 255, + Z = Math.floor(z) & 255; + x -= Math.floor(x); + y -= Math.floor(y); + z -= Math.floor(z); + var fx = (3 - 2 * x) * x * x, + fy = (3 - 2 * y) * y * y, + fz = (3 - 2 * z) * z * z; + var p0 = perm[X] + Y, + p00 = perm[p0] + Z, + p01 = perm[p0 + 1] + Z, + p1 = perm[X + 1] + Y, + p10 = perm[p1] + Z, + p11 = perm[p1 + 1] + Z; + return lerp(fz, lerp(fy, lerp(fx, grad3d(perm[p00], x, y, z), grad3d(perm[p10], x - 1, y, z)), lerp(fx, grad3d(perm[p01], x, y - 1, z), grad3d(perm[p11], x - 1, y - 1, z))), lerp(fy, lerp(fx, grad3d(perm[p00 + 1], x, y, z - 1), grad3d(perm[p10 + 1], x - 1, y, z - 1)), lerp(fx, grad3d(perm[p01 + 1], x, y - 1, z - 1), grad3d(perm[p11 + 1], x - 1, y - 1, z - 1)))) + }; + this.noise2d = function(x, y) { + var X = Math.floor(x) & 255, + Y = Math.floor(y) & 255; + x -= Math.floor(x); + y -= Math.floor(y); + var fx = (3 - 2 * x) * x * x, + fy = (3 - 2 * y) * y * y; + var p0 = perm[X] + Y, + p1 = perm[X + 1] + Y; + return lerp(fy, lerp(fx, grad2d(perm[p0], x, y), grad2d(perm[p1], x - 1, y)), lerp(fx, grad2d(perm[p0 + 1], x, y - 1), grad2d(perm[p1 + 1], x - 1, y - 1))) + }; + this.noise1d = function(x) { + var X = Math.floor(x) & 255; + x -= Math.floor(x); + var fx = (3 - 2 * x) * x * x; + return lerp(fx, grad1d(perm[X], x), grad1d(perm[X + 1], x - 1)) + } + } + var noiseProfile = { + generator: undef, + octaves: 4, + fallout: 0.5, + seed: undef + }; + p.noise = function(x, y, z) { + if (noiseProfile.generator === undef) noiseProfile.generator = new PerlinNoise(noiseProfile.seed); + var generator = noiseProfile.generator; + var effect = 1, + k = 1, + sum = 0; + for (var i = 0; i < noiseProfile.octaves; ++i) { + effect *= noiseProfile.fallout; + switch (arguments.length) { + case 1: + sum += effect * (1 + generator.noise1d(k * x)) / 2; + break; + case 2: + sum += effect * (1 + generator.noise2d(k * x, k * y)) / 2; + break; + case 3: + sum += effect * (1 + generator.noise3d(k * x, k * y, k * z)) / 2; + break + } + k *= 2 + } + return sum + }; + p.noiseDetail = function(octaves, fallout) { + noiseProfile.octaves = octaves; + if (fallout !== undef) noiseProfile.fallout = fallout + }; + p.noiseSeed = function(seed) { + noiseProfile.seed = seed; + noiseProfile.generator = undef + }; + DrawingShared.prototype.size = function(aWidth, aHeight, aMode) { + if (doStroke) p.stroke(0); + if (doFill) p.fill(255); + var savedProperties = { + fillStyle: curContext.fillStyle, + strokeStyle: curContext.strokeStyle, + lineCap: curContext.lineCap, + lineJoin: curContext.lineJoin + }; + if (curElement.style.length > 0) { + curElement.style.removeProperty("width"); + curElement.style.removeProperty("height") + } + curElement.width = p.width = aWidth || 100; + curElement.height = p.height = aHeight || 100; + for (var prop in savedProperties) if (savedProperties.hasOwnProperty(prop)) curContext[prop] = savedProperties[prop]; + p.textFont(curTextFont); + p.background(); + maxPixelsCached = Math.max(1E3, aWidth * aHeight * 0.05); + p.externals.context = curContext; + for (var i = 0; i < 720; i++) { + sinLUT[i] = p.sin(i * (Math.PI / 180) * 0.5); + cosLUT[i] = p.cos(i * (Math.PI / 180) * 0.5) + } + }; + Drawing2D.prototype.size = function(aWidth, aHeight, aMode) { + if (curContext === undef) { + curContext = curElement.getContext("2d"); + userMatrixStack = new PMatrixStack; + userReverseMatrixStack = new PMatrixStack; + modelView = new PMatrix2D; + modelViewInv = new PMatrix2D + } + DrawingShared.prototype.size.apply(this, arguments) + }; + Drawing3D.prototype.size = function() { + var size3DCalled = false; + return function size(aWidth, aHeight, aMode) { + if (size3DCalled) throw "Multiple calls to size() for 3D renders are not allowed."; + size3DCalled = true; + + function getGLContext(canvas) { + var ctxNames = ["experimental-webgl", "webgl", "webkit-3d"], + gl; + for (var i = 0, l = ctxNames.length; i < l; i++) { + gl = canvas.getContext(ctxNames[i], { + antialias: false, + preserveDrawingBuffer: true + }); + if (gl) break + } + return gl + } + try { + curElement.width = p.width = aWidth || 100; + curElement.height = p.height = aHeight || 100; + curContext = getGLContext(curElement); + canTex = curContext.createTexture(); + textTex = curContext.createTexture() + } catch(e_size) { + Processing.debug(e_size) + } + if (!curContext) throw "WebGL context is not supported on this browser."; + curContext.viewport(0, 0, curElement.width, curElement.height); + curContext.enable(curContext.DEPTH_TEST); + curContext.enable(curContext.BLEND); + curContext.blendFunc(curContext.SRC_ALPHA, curContext.ONE_MINUS_SRC_ALPHA); + programObject2D = createProgramObject(curContext, vertexShaderSrc2D, fragmentShaderSrc2D); + programObjectUnlitShape = createProgramObject(curContext, vertexShaderSrcUnlitShape, fragmentShaderSrcUnlitShape); + p.strokeWeight(1); + programObject3D = createProgramObject(curContext, vertexShaderSrc3D, fragmentShaderSrc3D); + curContext.useProgram(programObject3D); + uniformi("usingTexture3d", programObject3D, "usingTexture", usingTexture); + p.lightFalloff(1, 0, 0); + p.shininess(1); + p.ambient(255, 255, 255); + p.specular(0, 0, 0); + p.emissive(0, 0, 0); + boxBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, boxBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, boxVerts, curContext.STATIC_DRAW); + boxNormBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, boxNormBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, boxNorms, curContext.STATIC_DRAW); + boxOutlineBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, boxOutlineBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, boxOutlineVerts, curContext.STATIC_DRAW); + rectBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, rectBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, rectVerts, curContext.STATIC_DRAW); + rectNormBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, rectNormBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, rectNorms, curContext.STATIC_DRAW); + sphereBuffer = curContext.createBuffer(); + lineBuffer = curContext.createBuffer(); + fillBuffer = curContext.createBuffer(); + fillColorBuffer = curContext.createBuffer(); + strokeColorBuffer = curContext.createBuffer(); + shapeTexVBO = curContext.createBuffer(); + pointBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, pointBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([0, 0, 0]), curContext.STATIC_DRAW); + textBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, textBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0]), curContext.STATIC_DRAW); + textureBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ARRAY_BUFFER, textureBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]), curContext.STATIC_DRAW); + indexBuffer = curContext.createBuffer(); + curContext.bindBuffer(curContext.ELEMENT_ARRAY_BUFFER, indexBuffer); + curContext.bufferData(curContext.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 2, 3, 0]), curContext.STATIC_DRAW); + cam = new PMatrix3D; + cameraInv = new PMatrix3D; + modelView = new PMatrix3D; + modelViewInv = new PMatrix3D; + projection = new PMatrix3D; + p.camera(); + p.perspective(); + userMatrixStack = new PMatrixStack; + userReverseMatrixStack = new PMatrixStack; + curveBasisMatrix = new PMatrix3D; + curveToBezierMatrix = new PMatrix3D; + curveDrawMatrix = new PMatrix3D; + bezierDrawMatrix = new PMatrix3D; + bezierBasisInverse = new PMatrix3D; + bezierBasisMatrix = new PMatrix3D; + bezierBasisMatrix.set(-1, 3, -3, 1, 3, -6, 3, 0, -3, 3, 0, 0, 1, 0, 0, 0); + DrawingShared.prototype.size.apply(this, arguments) + } + }(); + Drawing2D.prototype.ambientLight = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.ambientLight = function(r, g, b, x, y, z) { + if (lightCount === 8) throw "can only create " + 8 + " lights"; + var pos = new PVector(x, y, z); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.mult(pos, pos); + var col = color$4(r, g, b, 0); + var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255]; + curContext.useProgram(programObject3D); + uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol); + uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array()); + uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 0); + uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount) + }; + Drawing2D.prototype.directionalLight = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.directionalLight = function(r, g, b, nx, ny, nz) { + if (lightCount === 8) throw "can only create " + 8 + " lights"; + curContext.useProgram(programObject3D); + var mvm = new PMatrix3D; + mvm.scale(1, -1, 1); + mvm.apply(modelView.array()); + mvm = mvm.array(); + var dir = [mvm[0] * nx + mvm[4] * ny + mvm[8] * nz, mvm[1] * nx + mvm[5] * ny + mvm[9] * nz, mvm[2] * nx + mvm[6] * ny + mvm[10] * nz]; + var col = color$4(r, g, b, 0); + var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255]; + uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol); + uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", dir); + uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 1); + uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount) + }; + Drawing2D.prototype.lightFalloff = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.lightFalloff = function(constant, linear, quadratic) { + curContext.useProgram(programObject3D); + uniformf("uFalloff3d", programObject3D, "uFalloff", [constant, linear, quadratic]) + }; + Drawing2D.prototype.lightSpecular = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.lightSpecular = function(r, g, b) { + var col = color$4(r, g, b, 0); + var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255]; + curContext.useProgram(programObject3D); + uniformf("uSpecular3d", programObject3D, "uSpecular", normalizedCol) + }; + p.lights = function() { + p.ambientLight(128, 128, 128); + p.directionalLight(128, 128, 128, 0, 0, -1); + p.lightFalloff(1, 0, 0); + p.lightSpecular(0, 0, 0) + }; + Drawing2D.prototype.pointLight = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.pointLight = function(r, g, b, x, y, z) { + if (lightCount === 8) throw "can only create " + 8 + " lights"; + var pos = new PVector(x, y, z); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.mult(pos, pos); + var col = color$4(r, g, b, 0); + var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255]; + curContext.useProgram(programObject3D); + uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol); + uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array()); + uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 2); + uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount) + }; + Drawing2D.prototype.noLights = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.noLights = function() { + lightCount = 0; + curContext.useProgram(programObject3D); + uniformi("uLightCount3d", programObject3D, "uLightCount", lightCount) + }; + Drawing2D.prototype.spotLight = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.spotLight = function(r, g, b, x, y, z, nx, ny, nz, angle, concentration) { + if (lightCount === 8) throw "can only create " + 8 + " lights"; + curContext.useProgram(programObject3D); + var pos = new PVector(x, y, z); + var mvm = new PMatrix3D; + mvm.scale(1, -1, 1); + mvm.apply(modelView.array()); + mvm.mult(pos, pos); + mvm = mvm.array(); + var dir = [mvm[0] * nx + mvm[4] * ny + mvm[8] * nz, mvm[1] * + nx + mvm[5] * ny + mvm[9] * nz, mvm[2] * nx + mvm[6] * ny + mvm[10] * nz]; + var col = color$4(r, g, b, 0); + var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255]; + uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol); + uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array()); + uniformf("uLights.direction.3d." + lightCount, programObject3D, "uLights" + lightCount + ".direction", dir); + uniformf("uLights.concentration.3d." + lightCount, programObject3D, "uLights" + lightCount + ".concentration", concentration); + uniformf("uLights.angle.3d." + lightCount, programObject3D, "uLights" + lightCount + ".angle", angle); + uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 3); + uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount) + }; + Drawing2D.prototype.beginCamera = function() { + throw "beginCamera() is not available in 2D mode"; + }; + Drawing3D.prototype.beginCamera = function() { + if (manipulatingCamera) throw "You cannot call beginCamera() again before calling endCamera()"; + manipulatingCamera = true; + modelView = cameraInv; + modelViewInv = cam + }; + Drawing2D.prototype.endCamera = function() { + throw "endCamera() is not available in 2D mode"; + }; + Drawing3D.prototype.endCamera = function() { + if (!manipulatingCamera) throw "You cannot call endCamera() before calling beginCamera()"; + modelView.set(cam); + modelViewInv.set(cameraInv); + manipulatingCamera = false + }; + p.camera = function(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ) { + if (eyeX === undef) { + cameraX = p.width / 2; + cameraY = p.height / 2; + cameraZ = cameraY / Math.tan(cameraFOV / 2); + eyeX = cameraX; + eyeY = cameraY; + eyeZ = cameraZ; + centerX = cameraX; + centerY = cameraY; + centerZ = 0; + upX = 0; + upY = 1; + upZ = 0 + } + var z = new PVector(eyeX - centerX, eyeY - centerY, eyeZ - centerZ); + var y = new PVector(upX, upY, upZ); + z.normalize(); + var x = PVector.cross(y, z); + y = PVector.cross(z, x); + x.normalize(); + y.normalize(); + var xX = x.x, + xY = x.y, + xZ = x.z; + var yX = y.x, + yY = y.y, + yZ = y.z; + var zX = z.x, + zY = z.y, + zZ = z.z; + cam.set(xX, xY, xZ, 0, yX, yY, yZ, 0, zX, zY, zZ, 0, 0, 0, 0, 1); + cam.translate(-eyeX, -eyeY, -eyeZ); + cameraInv.reset(); + cameraInv.invApply(xX, xY, xZ, 0, yX, yY, yZ, 0, zX, zY, zZ, 0, 0, 0, 0, 1); + cameraInv.translate(eyeX, eyeY, eyeZ); + modelView.set(cam); + modelViewInv.set(cameraInv) + }; + p.perspective = function(fov, aspect, near, far) { + if (arguments.length === 0) { + cameraY = curElement.height / 2; + cameraZ = cameraY / Math.tan(cameraFOV / 2); + cameraNear = cameraZ / 10; + cameraFar = cameraZ * 10; + cameraAspect = p.width / p.height; + fov = cameraFOV; + aspect = cameraAspect; + near = cameraNear; + far = cameraFar + } + var yMax, yMin, xMax, xMin; + yMax = near * Math.tan(fov / 2); + yMin = -yMax; + xMax = yMax * aspect; + xMin = yMin * aspect; + p.frustum(xMin, xMax, yMin, yMax, near, far) + }; + Drawing2D.prototype.frustum = function() { + throw "Processing.js: frustum() is not supported in 2D mode"; + }; + Drawing3D.prototype.frustum = function(left, right, bottom, top, near, far) { + frustumMode = true; + projection = new PMatrix3D; + projection.set(2 * near / (right - left), 0, (right + left) / (right - left), 0, 0, 2 * near / (top - bottom), (top + bottom) / (top - bottom), 0, 0, 0, -(far + near) / (far - near), -(2 * far * near) / (far - near), 0, 0, -1, 0); + var proj = new PMatrix3D; + proj.set(projection); + proj.transpose(); + curContext.useProgram(programObject2D); + uniformMatrix("projection2d", programObject2D, "uProjection", false, proj.array()); + curContext.useProgram(programObject3D); + uniformMatrix("projection3d", programObject3D, "uProjection", false, proj.array()); + curContext.useProgram(programObjectUnlitShape); + uniformMatrix("uProjectionUS", programObjectUnlitShape, "uProjection", false, proj.array()) + }; + p.ortho = function(left, right, bottom, top, near, far) { + if (arguments.length === 0) { + left = 0; + right = p.width; + bottom = 0; + top = p.height; + near = -10; + far = 10 + } + var x = 2 / (right - left); + var y = 2 / (top - bottom); + var z = -2 / (far - near); + var tx = -(right + left) / (right - left); + var ty = -(top + bottom) / (top - bottom); + var tz = -(far + near) / (far - near); + projection = new PMatrix3D; + projection.set(x, 0, 0, tx, 0, y, 0, ty, 0, 0, z, tz, 0, 0, 0, 1); + var proj = new PMatrix3D; + proj.set(projection); + proj.transpose(); + curContext.useProgram(programObject2D); + uniformMatrix("projection2d", programObject2D, "uProjection", false, proj.array()); + curContext.useProgram(programObject3D); + uniformMatrix("projection3d", programObject3D, "uProjection", false, proj.array()); + curContext.useProgram(programObjectUnlitShape); + uniformMatrix("uProjectionUS", programObjectUnlitShape, "uProjection", false, proj.array()); + frustumMode = false + }; + p.printProjection = function() { + projection.print() + }; + p.printCamera = function() { + cam.print() + }; + Drawing2D.prototype.box = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.box = function(w, h, d) { + if (!h || !d) h = d = w; + var model = new PMatrix3D; + model.scale(w, h, d); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + if (doFill) { + curContext.useProgram(programObject3D); + uniformMatrix("model3d", programObject3D, "uModel", false, model.array()); + uniformMatrix("view3d", programObject3D, "uView", false, view.array()); + curContext.enable(curContext.POLYGON_OFFSET_FILL); + curContext.polygonOffset(1, 1); + uniformf("color3d", programObject3D, "uColor", fillStyle); + if (lightCount > 0) { + var v = new PMatrix3D; + v.set(view); + var m = new PMatrix3D; + m.set(model); + v.mult(m); + var normalMatrix = new PMatrix3D; + normalMatrix.set(v); + normalMatrix.invert(); + normalMatrix.transpose(); + uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array()); + vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, boxNormBuffer) + } else disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal"); + vertexAttribPointer("aVertex3d", programObject3D, "aVertex", 3, boxBuffer); + disableVertexAttribPointer("aColor3d", programObject3D, "aColor"); + disableVertexAttribPointer("aTexture3d", programObject3D, "aTexture"); + curContext.drawArrays(curContext.TRIANGLES, 0, boxVerts.length / 3); + curContext.disable(curContext.POLYGON_OFFSET_FILL) + } + if (lineWidth > 0 && doStroke) { + curContext.useProgram(programObject2D); + uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array()); + uniformMatrix("uView2d", programObject2D, "uView", false, view.array()); + uniformf("uColor2d", programObject2D, "uColor", strokeStyle); + uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false); + vertexAttribPointer("vertex2d", programObject2D, "aVertex", 3, boxOutlineBuffer); + disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord"); + curContext.drawArrays(curContext.LINES, 0, boxOutlineVerts.length / 3) + } + }; + var initSphere = function() { + var i; + sphereVerts = []; + for (i = 0; i < sphereDetailU; i++) { + sphereVerts.push(0); + sphereVerts.push(-1); + sphereVerts.push(0); + sphereVerts.push(sphereX[i]); + sphereVerts.push(sphereY[i]); + sphereVerts.push(sphereZ[i]) + } + sphereVerts.push(0); + sphereVerts.push(-1); + sphereVerts.push(0); + sphereVerts.push(sphereX[0]); + sphereVerts.push(sphereY[0]); + sphereVerts.push(sphereZ[0]); + var v1, v11, v2; + var voff = 0; + for (i = 2; i < sphereDetailV; i++) { + v1 = v11 = voff; + voff += sphereDetailU; + v2 = voff; + for (var j = 0; j < sphereDetailU; j++) { + sphereVerts.push(sphereX[v1]); + sphereVerts.push(sphereY[v1]); + sphereVerts.push(sphereZ[v1++]); + sphereVerts.push(sphereX[v2]); + sphereVerts.push(sphereY[v2]); + sphereVerts.push(sphereZ[v2++]) + } + v1 = v11; + v2 = voff; + sphereVerts.push(sphereX[v1]); + sphereVerts.push(sphereY[v1]); + sphereVerts.push(sphereZ[v1]); + sphereVerts.push(sphereX[v2]); + sphereVerts.push(sphereY[v2]); + sphereVerts.push(sphereZ[v2]) + } + for (i = 0; i < sphereDetailU; i++) { + v2 = voff + i; + sphereVerts.push(sphereX[v2]); + sphereVerts.push(sphereY[v2]); + sphereVerts.push(sphereZ[v2]); + sphereVerts.push(0); + sphereVerts.push(1); + sphereVerts.push(0) + } + sphereVerts.push(sphereX[voff]); + sphereVerts.push(sphereY[voff]); + sphereVerts.push(sphereZ[voff]); + sphereVerts.push(0); + sphereVerts.push(1); + sphereVerts.push(0); + curContext.bindBuffer(curContext.ARRAY_BUFFER, sphereBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(sphereVerts), curContext.STATIC_DRAW) + }; + p.sphereDetail = function(ures, vres) { + var i; + if (arguments.length === 1) ures = vres = arguments[0]; + if (ures < 3) ures = 3; + if (vres < 2) vres = 2; + if (ures === sphereDetailU && vres === sphereDetailV) return; + var delta = 720 / ures; + var cx = new Float32Array(ures); + var cz = new Float32Array(ures); + for (i = 0; i < ures; i++) { + cx[i] = cosLUT[i * delta % 720 | 0]; + cz[i] = sinLUT[i * delta % 720 | 0] + } + var vertCount = ures * (vres - 1) + 2; + var currVert = 0; + sphereX = new Float32Array(vertCount); + sphereY = new Float32Array(vertCount); + sphereZ = new Float32Array(vertCount); + var angle_step = 720 * 0.5 / vres; + var angle = angle_step; + for (i = 1; i < vres; i++) { + var curradius = sinLUT[angle % 720 | 0]; + var currY = -cosLUT[angle % 720 | 0]; + for (var j = 0; j < ures; j++) { + sphereX[currVert] = cx[j] * curradius; + sphereY[currVert] = currY; + sphereZ[currVert++] = cz[j] * curradius + } + angle += angle_step + } + sphereDetailU = ures; + sphereDetailV = vres; + initSphere() + }; + Drawing2D.prototype.sphere = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.sphere = function() { + var sRad = arguments[0]; + if (sphereDetailU < 3 || sphereDetailV < 2) p.sphereDetail(30); + var model = new PMatrix3D; + model.scale(sRad, sRad, sRad); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + if (doFill) { + if (lightCount > 0) { + var v = new PMatrix3D; + v.set(view); + var m = new PMatrix3D; + m.set(model); + v.mult(m); + var normalMatrix = new PMatrix3D; + normalMatrix.set(v); + normalMatrix.invert(); + normalMatrix.transpose(); + uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array()); + vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, sphereBuffer) + } else disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal"); + curContext.useProgram(programObject3D); + disableVertexAttribPointer("aTexture3d", programObject3D, "aTexture"); + uniformMatrix("uModel3d", programObject3D, "uModel", false, model.array()); + uniformMatrix("uView3d", programObject3D, "uView", false, view.array()); + vertexAttribPointer("aVertex3d", programObject3D, "aVertex", 3, sphereBuffer); + disableVertexAttribPointer("aColor3d", programObject3D, "aColor"); + curContext.enable(curContext.POLYGON_OFFSET_FILL); + curContext.polygonOffset(1, 1); + uniformf("uColor3d", programObject3D, "uColor", fillStyle); + curContext.drawArrays(curContext.TRIANGLE_STRIP, 0, sphereVerts.length / 3); + curContext.disable(curContext.POLYGON_OFFSET_FILL) + } + if (lineWidth > 0 && doStroke) { + curContext.useProgram(programObject2D); + uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array()); + uniformMatrix("uView2d", programObject2D, "uView", false, view.array()); + vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, sphereBuffer); + disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord"); + uniformf("uColor2d", programObject2D, "uColor", strokeStyle); + uniformi("uIsDrawingText", programObject2D, "uIsDrawingText", false); + curContext.drawArrays(curContext.LINE_STRIP, 0, sphereVerts.length / 3) + } + }; + p.modelX = function(x, y, z) { + var mv = modelView.array(); + var ci = cameraInv.array(); + var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3]; + var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7]; + var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11]; + var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15]; + var ox = ci[0] * ax + ci[1] * ay + ci[2] * az + ci[3] * aw; + var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw; + return ow !== 0 ? ox / ow : ox + }; + p.modelY = function(x, y, z) { + var mv = modelView.array(); + var ci = cameraInv.array(); + var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3]; + var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7]; + var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11]; + var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15]; + var oy = ci[4] * ax + ci[5] * ay + ci[6] * az + ci[7] * aw; + var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw; + return ow !== 0 ? oy / ow : oy + }; + p.modelZ = function(x, y, z) { + var mv = modelView.array(); + var ci = cameraInv.array(); + var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3]; + var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7]; + var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11]; + var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15]; + var oz = ci[8] * ax + ci[9] * ay + ci[10] * az + ci[11] * aw; + var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw; + return ow !== 0 ? oz / ow : oz + }; + Drawing2D.prototype.ambient = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.ambient = function(v1, v2, v3) { + curContext.useProgram(programObject3D); + uniformi("uUsingMat3d", programObject3D, "uUsingMat", true); + var col = p.color(v1, v2, v3); + uniformf("uMaterialAmbient3d", programObject3D, "uMaterialAmbient", p.color.toGLArray(col).slice(0, 3)) + }; + Drawing2D.prototype.emissive = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.emissive = function(v1, v2, v3) { + curContext.useProgram(programObject3D); + uniformi("uUsingMat3d", programObject3D, "uUsingMat", true); + var col = p.color(v1, v2, v3); + uniformf("uMaterialEmissive3d", programObject3D, "uMaterialEmissive", p.color.toGLArray(col).slice(0, 3)) + }; + Drawing2D.prototype.shininess = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.shininess = function(shine) { + curContext.useProgram(programObject3D); + uniformi("uUsingMat3d", programObject3D, "uUsingMat", true); + uniformf("uShininess3d", programObject3D, "uShininess", shine) + }; + Drawing2D.prototype.specular = DrawingShared.prototype.a3DOnlyFunction; + Drawing3D.prototype.specular = function(v1, v2, v3) { + curContext.useProgram(programObject3D); + uniformi("uUsingMat3d", programObject3D, "uUsingMat", true); + var col = p.color(v1, v2, v3); + uniformf("uMaterialSpecular3d", programObject3D, "uMaterialSpecular", p.color.toGLArray(col).slice(0, 3)) + }; + p.screenX = function(x, y, z) { + var mv = modelView.array(); + if (mv.length === 16) { + var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3]; + var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7]; + var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11]; + var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15]; + var pj = projection.array(); + var ox = pj[0] * ax + pj[1] * ay + pj[2] * az + pj[3] * aw; + var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw; + if (ow !== 0) ox /= ow; + return p.width * (1 + ox) / 2 + } + return modelView.multX(x, y) + }; + p.screenY = function screenY(x, y, z) { + var mv = modelView.array(); + if (mv.length === 16) { + var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3]; + var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7]; + var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11]; + var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15]; + var pj = projection.array(); + var oy = pj[4] * ax + pj[5] * ay + pj[6] * az + pj[7] * aw; + var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw; + if (ow !== 0) oy /= ow; + return p.height * (1 + oy) / 2 + } + return modelView.multY(x, y) + }; + p.screenZ = function screenZ(x, y, z) { + var mv = modelView.array(); + if (mv.length !== 16) return 0; + var pj = projection.array(); + var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3]; + var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7]; + var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11]; + var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15]; + var oz = pj[8] * ax + pj[9] * ay + pj[10] * az + pj[11] * aw; + var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw; + if (ow !== 0) oz /= ow; + return (oz + 1) / 2 + }; + DrawingShared.prototype.fill = function() { + var color = p.color(arguments[0], arguments[1], arguments[2], arguments[3]); + if (color === currentFillColor && doFill) return; + doFill = true; + currentFillColor = color + }; + Drawing2D.prototype.fill = function() { + DrawingShared.prototype.fill.apply(this, arguments); + isFillDirty = true + }; + Drawing3D.prototype.fill = function() { + DrawingShared.prototype.fill.apply(this, arguments); + fillStyle = p.color.toGLArray(currentFillColor) + }; + + function executeContextFill() { + if (doFill) { + if (isFillDirty) { + curContext.fillStyle = p.color.toString(currentFillColor); + isFillDirty = false + } + curContext.fill() + } + } + p.noFill = function() { + doFill = false + }; + DrawingShared.prototype.stroke = function() { + var color = p.color(arguments[0], arguments[1], arguments[2], arguments[3]); + if (color === currentStrokeColor && doStroke) return; + doStroke = true; + currentStrokeColor = color + }; + Drawing2D.prototype.stroke = function() { + DrawingShared.prototype.stroke.apply(this, arguments); + isStrokeDirty = true + }; + Drawing3D.prototype.stroke = function() { + DrawingShared.prototype.stroke.apply(this, arguments); + strokeStyle = p.color.toGLArray(currentStrokeColor) + }; + + function executeContextStroke() { + if (doStroke) { + if (isStrokeDirty) { + curContext.strokeStyle = p.color.toString(currentStrokeColor); + isStrokeDirty = false + } + curContext.stroke() + } + } + p.noStroke = function() { + doStroke = false + }; + DrawingShared.prototype.strokeWeight = function(w) { + lineWidth = w + }; + Drawing2D.prototype.strokeWeight = function(w) { + DrawingShared.prototype.strokeWeight.apply(this, arguments); + curContext.lineWidth = w + }; + Drawing3D.prototype.strokeWeight = function(w) { + DrawingShared.prototype.strokeWeight.apply(this, arguments); + curContext.useProgram(programObject2D); + uniformf("pointSize2d", programObject2D, "uPointSize", w); + curContext.useProgram(programObjectUnlitShape); + uniformf("pointSizeUnlitShape", programObjectUnlitShape, "uPointSize", w); + curContext.lineWidth(w) + }; + p.strokeCap = function(value) { + drawing.$ensureContext().lineCap = value + }; + p.strokeJoin = function(value) { + drawing.$ensureContext().lineJoin = value + }; + Drawing2D.prototype.smooth = function() { + renderSmooth = true; + var style = curElement.style; + style.setProperty("image-rendering", "optimizeQuality", "important"); + style.setProperty("-ms-interpolation-mode", "bicubic", "important"); + if (curContext.hasOwnProperty("mozImageSmoothingEnabled")) curContext.mozImageSmoothingEnabled = true + }; + Drawing3D.prototype.smooth = function() { + renderSmooth = true + }; + Drawing2D.prototype.noSmooth = function() { + renderSmooth = false; + var style = curElement.style; + style.setProperty("image-rendering", "optimizeSpeed", "important"); + style.setProperty("image-rendering", "-moz-crisp-edges", "important"); + style.setProperty("image-rendering", "-webkit-optimize-contrast", "important"); + style.setProperty("image-rendering", "optimize-contrast", "important"); + style.setProperty("-ms-interpolation-mode", "nearest-neighbor", "important"); + if (curContext.hasOwnProperty("mozImageSmoothingEnabled")) curContext.mozImageSmoothingEnabled = false + }; + Drawing3D.prototype.noSmooth = function() { + renderSmooth = false + }; + Drawing2D.prototype.point = function(x, y) { + if (!doStroke) return; + x = Math.round(x); + y = Math.round(y); + curContext.fillStyle = p.color.toString(currentStrokeColor); + isFillDirty = true; + if (lineWidth > 1) { + curContext.beginPath(); + curContext.arc(x, y, lineWidth / 2, 0, 6.283185307179586, false); + curContext.fill() + } else curContext.fillRect(x, y, 1, 1) + }; + Drawing3D.prototype.point = function(x, y, z) { + var model = new PMatrix3D; + model.translate(x, y, z || 0); + model.transpose(); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + curContext.useProgram(programObject2D); + uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array()); + uniformMatrix("uView2d", programObject2D, "uView", false, view.array()); + if (lineWidth > 0 && doStroke) { + uniformf("uColor2d", programObject2D, "uColor", strokeStyle); + uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false); + uniformi("uSmooth2d", programObject2D, "uSmooth", renderSmooth); + vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, pointBuffer); + disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord"); + curContext.drawArrays(curContext.POINTS, 0, 1) + } + }; + p.beginShape = function(type) { + curShape = type; + curvePoints = []; + vertArray = [] + }; + Drawing2D.prototype.vertex = function(x, y, moveTo) { + var vert = []; + if (firstVert) firstVert = false; + vert["isVert"] = true; + vert[0] = x; + vert[1] = y; + vert[2] = 0; + vert[3] = 0; + vert[4] = 0; + vert[5] = currentFillColor; + vert[6] = currentStrokeColor; + vertArray.push(vert); + if (moveTo) vertArray[vertArray.length - 1]["moveTo"] = moveTo + }; + Drawing3D.prototype.vertex = function(x, y, z, u, v) { + var vert = []; + if (firstVert) firstVert = false; + vert["isVert"] = true; + if (v === undef && usingTexture) { + v = u; + u = z; + z = 0 + } + if (u !== undef && v !== undef) { + if (curTextureMode === 2) { + u /= curTexture.width; + v /= curTexture.height + } + u = u > 1 ? 1 : u; + u = u < 0 ? 0 : u; + v = v > 1 ? 1 : v; + v = v < 0 ? 0 : v + } + vert[0] = x; + vert[1] = y; + vert[2] = z || 0; + vert[3] = u || 0; + vert[4] = v || 0; + vert[5] = fillStyle[0]; + vert[6] = fillStyle[1]; + vert[7] = fillStyle[2]; + vert[8] = fillStyle[3]; + vert[9] = strokeStyle[0]; + vert[10] = strokeStyle[1]; + vert[11] = strokeStyle[2]; + vert[12] = strokeStyle[3]; + vert[13] = normalX; + vert[14] = normalY; + vert[15] = normalZ; + vertArray.push(vert) + }; + var point3D = function(vArray, cArray) { + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + curContext.useProgram(programObjectUnlitShape); + uniformMatrix("uViewUS", programObjectUnlitShape, "uView", false, view.array()); + uniformi("uSmoothUS", programObjectUnlitShape, "uSmooth", renderSmooth); + vertexAttribPointer("aVertexUS", programObjectUnlitShape, "aVertex", 3, pointBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW); + vertexAttribPointer("aColorUS", programObjectUnlitShape, "aColor", 4, fillColorBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW); + curContext.drawArrays(curContext.POINTS, 0, vArray.length / 3) + }; + var line3D = function(vArray, mode, cArray) { + var ctxMode; + if (mode === "LINES") ctxMode = curContext.LINES; + else if (mode === "LINE_LOOP") ctxMode = curContext.LINE_LOOP; + else ctxMode = curContext.LINE_STRIP; + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + curContext.useProgram(programObjectUnlitShape); + uniformMatrix("uViewUS", programObjectUnlitShape, "uView", false, view.array()); + vertexAttribPointer("aVertexUS", programObjectUnlitShape, "aVertex", 3, lineBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW); + vertexAttribPointer("aColorUS", programObjectUnlitShape, "aColor", 4, strokeColorBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW); + curContext.drawArrays(ctxMode, 0, vArray.length / 3) + }; + var fill3D = function(vArray, mode, cArray, tArray) { + var ctxMode; + if (mode === "TRIANGLES") ctxMode = curContext.TRIANGLES; + else if (mode === "TRIANGLE_FAN") ctxMode = curContext.TRIANGLE_FAN; + else ctxMode = curContext.TRIANGLE_STRIP; + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + curContext.useProgram(programObject3D); + uniformMatrix("model3d", programObject3D, "uModel", false, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); + uniformMatrix("view3d", programObject3D, "uView", false, view.array()); + curContext.enable(curContext.POLYGON_OFFSET_FILL); + curContext.polygonOffset(1, 1); + uniformf("color3d", programObject3D, "uColor", [-1, 0, 0, 0]); + vertexAttribPointer("vertex3d", programObject3D, "aVertex", 3, fillBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW); + if (usingTexture && curTint !== null) curTint3d(cArray); + vertexAttribPointer("aColor3d", programObject3D, "aColor", 4, fillColorBuffer); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW); + disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal"); + if (usingTexture) { + uniformi("uUsingTexture3d", programObject3D, "uUsingTexture", usingTexture); + vertexAttribPointer("aTexture3d", programObject3D, "aTexture", 2, shapeTexVBO); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(tArray), curContext.STREAM_DRAW) + } + curContext.drawArrays(ctxMode, 0, vArray.length / 3); + curContext.disable(curContext.POLYGON_OFFSET_FILL) + }; + + function fillStrokeClose() { + executeContextFill(); + executeContextStroke(); + curContext.closePath() + } + Drawing2D.prototype.endShape = function(mode) { + if (vertArray.length === 0) return; + var closeShape = mode === 2; + if (closeShape) vertArray.push(vertArray[0]); + var lineVertArray = []; + var fillVertArray = []; + var colorVertArray = []; + var strokeVertArray = []; + var texVertArray = []; + var cachedVertArray; + firstVert = true; + var i, j, k; + var vertArrayLength = vertArray.length; + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) fillVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + texVertArray.push(cachedVertArray[3]); + texVertArray.push(cachedVertArray[4]) + } + if (isCurve && (curShape === 20 || curShape === undef)) { + if (vertArrayLength > 3) { + var b = [], + s = 1 - curTightness; + curContext.beginPath(); + curContext.moveTo(vertArray[1][0], vertArray[1][1]); + for (i = 1; i + 2 < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + b[0] = [cachedVertArray[0], cachedVertArray[1]]; + b[1] = [cachedVertArray[0] + (s * vertArray[i + 1][0] - s * vertArray[i - 1][0]) / 6, cachedVertArray[1] + (s * vertArray[i + 1][1] - s * vertArray[i - 1][1]) / 6]; + b[2] = [vertArray[i + 1][0] + (s * vertArray[i][0] - s * vertArray[i + 2][0]) / 6, vertArray[i + 1][1] + (s * vertArray[i][1] - s * vertArray[i + 2][1]) / 6]; + b[3] = [vertArray[i + 1][0], vertArray[i + 1][1]]; + curContext.bezierCurveTo(b[1][0], b[1][1], b[2][0], b[2][1], b[3][0], b[3][1]) + } + fillStrokeClose() + } + } else if (isBezier && (curShape === 20 || curShape === undef)) { + curContext.beginPath(); + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + if (vertArray[i]["isVert"]) if (vertArray[i]["moveTo"]) curContext.moveTo(cachedVertArray[0], cachedVertArray[1]); + else curContext.lineTo(cachedVertArray[0], cachedVertArray[1]); + else curContext.bezierCurveTo(vertArray[i][0], vertArray[i][1], vertArray[i][2], vertArray[i][3], vertArray[i][4], vertArray[i][5]) + } + fillStrokeClose() + } else if (curShape === 2) for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + if (doStroke) p.stroke(cachedVertArray[6]); + p.point(cachedVertArray[0], cachedVertArray[1]) + } else if (curShape === 4) for (i = 0; i + 1 < vertArrayLength; i += 2) { + cachedVertArray = vertArray[i]; + if (doStroke) p.stroke(vertArray[i + 1][6]); + p.line(cachedVertArray[0], cachedVertArray[1], vertArray[i + 1][0], vertArray[i + 1][1]) + } else if (curShape === 9) for (i = 0; i + 2 < vertArrayLength; i += 3) { + cachedVertArray = vertArray[i]; + curContext.beginPath(); + curContext.moveTo(cachedVertArray[0], cachedVertArray[1]); + curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1]); + curContext.lineTo(vertArray[i + 2][0], vertArray[i + 2][1]); + curContext.lineTo(cachedVertArray[0], cachedVertArray[1]); + if (doFill) { + p.fill(vertArray[i + 2][5]); + executeContextFill() + } + if (doStroke) { + p.stroke(vertArray[i + 2][6]); + executeContextStroke() + } + curContext.closePath() + } else if (curShape === 10) for (i = 0; i + 1 < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + curContext.beginPath(); + curContext.moveTo(vertArray[i + 1][0], vertArray[i + 1][1]); + curContext.lineTo(cachedVertArray[0], cachedVertArray[1]); + if (doStroke) p.stroke(vertArray[i + 1][6]); + if (doFill) p.fill(vertArray[i + 1][5]); + if (i + 2 < vertArrayLength) { + curContext.lineTo(vertArray[i + 2][0], vertArray[i + 2][1]); + if (doStroke) p.stroke(vertArray[i + 2][6]); + if (doFill) p.fill(vertArray[i + 2][5]) + } + fillStrokeClose() + } else if (curShape === 11) { + if (vertArrayLength > 2) { + curContext.beginPath(); + curContext.moveTo(vertArray[0][0], vertArray[0][1]); + curContext.lineTo(vertArray[1][0], vertArray[1][1]); + curContext.lineTo(vertArray[2][0], vertArray[2][1]); + if (doFill) { + p.fill(vertArray[2][5]); + executeContextFill() + } + if (doStroke) { + p.stroke(vertArray[2][6]); + executeContextStroke() + } + curContext.closePath(); + for (i = 3; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + curContext.beginPath(); + curContext.moveTo(vertArray[0][0], vertArray[0][1]); + curContext.lineTo(vertArray[i - 1][0], vertArray[i - 1][1]); + curContext.lineTo(cachedVertArray[0], cachedVertArray[1]); + if (doFill) { + p.fill(cachedVertArray[5]); + executeContextFill() + } + if (doStroke) { + p.stroke(cachedVertArray[6]); + executeContextStroke() + } + curContext.closePath() + } + } + } else if (curShape === 16) for (i = 0; i + 3 < vertArrayLength; i += 4) { + cachedVertArray = vertArray[i]; + curContext.beginPath(); + curContext.moveTo(cachedVertArray[0], cachedVertArray[1]); + for (j = 1; j < 4; j++) curContext.lineTo(vertArray[i + j][0], vertArray[i + j][1]); + curContext.lineTo(cachedVertArray[0], cachedVertArray[1]); + if (doFill) { + p.fill(vertArray[i + 3][5]); + executeContextFill() + } + if (doStroke) { + p.stroke(vertArray[i + 3][6]); + executeContextStroke() + } + curContext.closePath() + } else if (curShape === 17) { + if (vertArrayLength > 3) for (i = 0; i + 1 < vertArrayLength; i += 2) { + cachedVertArray = vertArray[i]; + curContext.beginPath(); + if (i + 3 < vertArrayLength) { + curContext.moveTo(vertArray[i + 2][0], vertArray[i + 2][1]); + curContext.lineTo(cachedVertArray[0], cachedVertArray[1]); + curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1]); + curContext.lineTo(vertArray[i + 3][0], vertArray[i + 3][1]); + if (doFill) p.fill(vertArray[i + 3][5]); + if (doStroke) p.stroke(vertArray[i + 3][6]) + } else { + curContext.moveTo(cachedVertArray[0], cachedVertArray[1]); + curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1]) + } + fillStrokeClose() + } + } else { + curContext.beginPath(); + curContext.moveTo(vertArray[0][0], vertArray[0][1]); + for (i = 1; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + if (cachedVertArray["isVert"]) if (cachedVertArray["moveTo"]) curContext.moveTo(cachedVertArray[0], cachedVertArray[1]); + else curContext.lineTo(cachedVertArray[0], cachedVertArray[1]) + } + fillStrokeClose() + } + isCurve = false; + isBezier = false; + curveVertArray = []; + curveVertCount = 0; + if (closeShape) vertArray.pop() + }; + Drawing3D.prototype.endShape = function(mode) { + if (vertArray.length === 0) return; + var closeShape = mode === 2; + var lineVertArray = []; + var fillVertArray = []; + var colorVertArray = []; + var strokeVertArray = []; + var texVertArray = []; + var cachedVertArray; + firstVert = true; + var i, j, k; + var vertArrayLength = vertArray.length; + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) fillVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + texVertArray.push(cachedVertArray[3]); + texVertArray.push(cachedVertArray[4]) + } + if (closeShape) { + fillVertArray.push(vertArray[0][0]); + fillVertArray.push(vertArray[0][1]); + fillVertArray.push(vertArray[0][2]); + for (i = 5; i < 9; i++) colorVertArray.push(vertArray[0][i]); + for (i = 9; i < 13; i++) strokeVertArray.push(vertArray[0][i]); + texVertArray.push(vertArray[0][3]); + texVertArray.push(vertArray[0][4]) + } + if (isCurve && (curShape === 20 || curShape === undef)) { + lineVertArray = fillVertArray; + if (doStroke) line3D(lineVertArray, null, strokeVertArray); + if (doFill) fill3D(fillVertArray, null, colorVertArray) + } else if (isBezier && (curShape === 20 || curShape === undef)) { + lineVertArray = fillVertArray; + lineVertArray.splice(lineVertArray.length - 3); + strokeVertArray.splice(strokeVertArray.length - 4); + if (doStroke) line3D(lineVertArray, null, strokeVertArray); + if (doFill) fill3D(fillVertArray, "TRIANGLES", colorVertArray) + } else { + if (curShape === 2) { + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j]) + } + point3D(lineVertArray, strokeVertArray) + } else if (curShape === 4) { + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j]) + } + line3D(lineVertArray, "LINES", strokeVertArray) + } else if (curShape === 9) { + if (vertArrayLength > 2) for (i = 0; i + 2 < vertArrayLength; i += 3) { + fillVertArray = []; + texVertArray = []; + lineVertArray = []; + colorVertArray = []; + strokeVertArray = []; + for (j = 0; j < 3; j++) for (k = 0; k < 3; k++) { + lineVertArray.push(vertArray[i + j][k]); + fillVertArray.push(vertArray[i + j][k]) + } + for (j = 0; j < 3; j++) for (k = 3; k < 5; k++) texVertArray.push(vertArray[i + j][k]); + for (j = 0; j < 3; j++) for (k = 5; k < 9; k++) { + colorVertArray.push(vertArray[i + j][k]); + strokeVertArray.push(vertArray[i + j][k + 4]) + } + if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray); + if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLES", colorVertArray, texVertArray) + } + } else if (curShape === 10) { + if (vertArrayLength > 2) for (i = 0; i + 2 < vertArrayLength; i++) { + lineVertArray = []; + fillVertArray = []; + strokeVertArray = []; + colorVertArray = []; + texVertArray = []; + for (j = 0; j < 3; j++) for (k = 0; k < 3; k++) { + lineVertArray.push(vertArray[i + j][k]); + fillVertArray.push(vertArray[i + j][k]) + } + for (j = 0; j < 3; j++) for (k = 3; k < 5; k++) texVertArray.push(vertArray[i + j][k]); + for (j = 0; j < 3; j++) for (k = 5; k < 9; k++) { + strokeVertArray.push(vertArray[i + j][k + 4]); + colorVertArray.push(vertArray[i + j][k]) + } + if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_STRIP", colorVertArray, texVertArray); + if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray) + } + } else if (curShape === 11) { + if (vertArrayLength > 2) { + for (i = 0; i < 3; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < 3; i++) { + cachedVertArray = vertArray[i]; + for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j]) + } + if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray); + for (i = 2; i + 1 < vertArrayLength; i++) { + lineVertArray = []; + strokeVertArray = []; + lineVertArray.push(vertArray[0][0]); + lineVertArray.push(vertArray[0][1]); + lineVertArray.push(vertArray[0][2]); + strokeVertArray.push(vertArray[0][9]); + strokeVertArray.push(vertArray[0][10]); + strokeVertArray.push(vertArray[0][11]); + strokeVertArray.push(vertArray[0][12]); + for (j = 0; j < 2; j++) for (k = 0; k < 3; k++) lineVertArray.push(vertArray[i + j][k]); + for (j = 0; j < 2; j++) for (k = 9; k < 13; k++) strokeVertArray.push(vertArray[i + j][k]); + if (doStroke) line3D(lineVertArray, "LINE_STRIP", strokeVertArray) + } + if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray, texVertArray) + } + } else if (curShape === 16) for (i = 0; i + 3 < vertArrayLength; i += 4) { + lineVertArray = []; + for (j = 0; j < 4; j++) { + cachedVertArray = vertArray[i + j]; + for (k = 0; k < 3; k++) lineVertArray.push(cachedVertArray[k]) + } + if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray); + if (doFill) { + fillVertArray = []; + colorVertArray = []; + texVertArray = []; + for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i][j]); + for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i][j]); + for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 1][j]); + for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 1][j]); + for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 3][j]); + for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 3][j]); + for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 2][j]); + for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 2][j]); + if (usingTexture) { + texVertArray.push(vertArray[i + 0][3]); + texVertArray.push(vertArray[i + 0][4]); + texVertArray.push(vertArray[i + 1][3]); + texVertArray.push(vertArray[i + 1][4]); + texVertArray.push(vertArray[i + 3][3]); + texVertArray.push(vertArray[i + 3][4]); + texVertArray.push(vertArray[i + 2][3]); + texVertArray.push(vertArray[i + 2][4]) + } + fill3D(fillVertArray, "TRIANGLE_STRIP", colorVertArray, texVertArray) + } + } else if (curShape === 17) { + var tempArray = []; + if (vertArrayLength > 3) { + for (i = 0; i < 2; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j]) + } + for (i = 0; i < 2; i++) { + cachedVertArray = vertArray[i]; + for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j]) + } + line3D(lineVertArray, "LINE_STRIP", strokeVertArray); + if (vertArrayLength > 4 && vertArrayLength % 2 > 0) { + tempArray = fillVertArray.splice(fillVertArray.length - 3); + vertArray.pop() + } + for (i = 0; i + 3 < vertArrayLength; i += 2) { + lineVertArray = []; + strokeVertArray = []; + for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 1][j]); + for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 3][j]); + for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 2][j]); + for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 0][j]); + for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 1][j]); + for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 3][j]); + for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 2][j]); + for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 0][j]); + if (doStroke) line3D(lineVertArray, "LINE_STRIP", strokeVertArray) + } + if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_LIST", colorVertArray, texVertArray) + } + } else if (vertArrayLength === 1) { + for (j = 0; j < 3; j++) lineVertArray.push(vertArray[0][j]); + for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[0][j]); + point3D(lineVertArray, strokeVertArray) + } else { + for (i = 0; i < vertArrayLength; i++) { + cachedVertArray = vertArray[i]; + for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j]); + for (j = 5; j < 9; j++) strokeVertArray.push(cachedVertArray[j]) + } + if (doStroke && closeShape) line3D(lineVertArray, "LINE_LOOP", strokeVertArray); + else if (doStroke && !closeShape) line3D(lineVertArray, "LINE_STRIP", strokeVertArray); + if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray, texVertArray) + } + usingTexture = false; + curContext.useProgram(programObject3D); + uniformi("usingTexture3d", programObject3D, "uUsingTexture", usingTexture) + } + isCurve = false; + isBezier = false; + curveVertArray = []; + curveVertCount = 0 + }; + var splineForward = function(segments, matrix) { + var f = 1 / segments; + var ff = f * f; + var fff = ff * f; + matrix.set(0, 0, 0, 1, fff, ff, f, 0, 6 * fff, 2 * ff, 0, 0, 6 * fff, 0, 0, 0) + }; + var curveInit = function() { + if (!curveDrawMatrix) { + curveBasisMatrix = new PMatrix3D; + curveDrawMatrix = new PMatrix3D; + curveInited = true + } + var s = curTightness; + curveBasisMatrix.set((s - 1) / 2, (s + 3) / 2, (-3 - s) / 2, (1 - s) / 2, 1 - s, (-5 - s) / 2, s + 2, (s - 1) / 2, (s - 1) / 2, 0, (1 - s) / 2, 0, 0, 1, 0, 0); + splineForward(curveDet, curveDrawMatrix); + if (!bezierBasisInverse) curveToBezierMatrix = new PMatrix3D; + curveToBezierMatrix.set(curveBasisMatrix); + curveToBezierMatrix.preApply(bezierBasisInverse); + curveDrawMatrix.apply(curveBasisMatrix) + }; + Drawing2D.prototype.bezierVertex = function() { + isBezier = true; + var vert = []; + if (firstVert) throw "vertex() must be used at least once before calling bezierVertex()"; + for (var i = 0; i < arguments.length; i++) vert[i] = arguments[i]; + vertArray.push(vert); + vertArray[vertArray.length - 1]["isVert"] = false + }; + Drawing3D.prototype.bezierVertex = function() { + isBezier = true; + var vert = []; + if (firstVert) throw "vertex() must be used at least once before calling bezierVertex()"; + if (arguments.length === 9) { + if (bezierDrawMatrix === undef) bezierDrawMatrix = new PMatrix3D; + var lastPoint = vertArray.length - 1; + splineForward(bezDetail, bezierDrawMatrix); + bezierDrawMatrix.apply(bezierBasisMatrix); + var draw = bezierDrawMatrix.array(); + var x1 = vertArray[lastPoint][0], + y1 = vertArray[lastPoint][1], + z1 = vertArray[lastPoint][2]; + var xplot1 = draw[4] * x1 + draw[5] * arguments[0] + draw[6] * arguments[3] + draw[7] * arguments[6]; + var xplot2 = draw[8] * x1 + draw[9] * arguments[0] + draw[10] * arguments[3] + draw[11] * arguments[6]; + var xplot3 = draw[12] * x1 + draw[13] * arguments[0] + draw[14] * arguments[3] + draw[15] * arguments[6]; + var yplot1 = draw[4] * y1 + draw[5] * arguments[1] + draw[6] * arguments[4] + draw[7] * arguments[7]; + var yplot2 = draw[8] * y1 + draw[9] * arguments[1] + draw[10] * arguments[4] + draw[11] * arguments[7]; + var yplot3 = draw[12] * y1 + draw[13] * arguments[1] + draw[14] * arguments[4] + draw[15] * arguments[7]; + var zplot1 = draw[4] * z1 + draw[5] * arguments[2] + draw[6] * arguments[5] + draw[7] * arguments[8]; + var zplot2 = draw[8] * z1 + draw[9] * arguments[2] + draw[10] * arguments[5] + draw[11] * arguments[8]; + var zplot3 = draw[12] * z1 + draw[13] * arguments[2] + draw[14] * arguments[5] + draw[15] * arguments[8]; + for (var j = 0; j < bezDetail; j++) { + x1 += xplot1; + xplot1 += xplot2; + xplot2 += xplot3; + y1 += yplot1; + yplot1 += yplot2; + yplot2 += yplot3; + z1 += zplot1; + zplot1 += zplot2; + zplot2 += zplot3; + p.vertex(x1, y1, z1) + } + p.vertex(arguments[6], arguments[7], arguments[8]) + } + }; + p.texture = function(pimage) { + var curContext = drawing.$ensureContext(); + if (pimage.__texture) curContext.bindTexture(curContext.TEXTURE_2D, pimage.__texture); + else if (pimage.localName === "canvas") { + curContext.bindTexture(curContext.TEXTURE_2D, canTex); + curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, pimage); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR); + curContext.generateMipmap(curContext.TEXTURE_2D); + curTexture.width = pimage.width; + curTexture.height = pimage.height + } else { + var texture = curContext.createTexture(), + cvs = document.createElement("canvas"), + cvsTextureCtx = cvs.getContext("2d"), + pot; + if (pimage.width & pimage.width - 1 === 0) cvs.width = pimage.width; + else { + pot = 1; + while (pot < pimage.width) pot *= 2; + cvs.width = pot + } + if (pimage.height & pimage.height - 1 === 0) cvs.height = pimage.height; + else { + pot = 1; + while (pot < pimage.height) pot *= 2; + cvs.height = pot + } + cvsTextureCtx.drawImage(pimage.sourceImg, 0, 0, pimage.width, pimage.height, 0, 0, cvs.width, cvs.height); + curContext.bindTexture(curContext.TEXTURE_2D, texture); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR_MIPMAP_LINEAR); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_T, curContext.CLAMP_TO_EDGE); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_S, curContext.CLAMP_TO_EDGE); + curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, cvs); + curContext.generateMipmap(curContext.TEXTURE_2D); + pimage.__texture = texture; + curTexture.width = pimage.width; + curTexture.height = pimage.height + } + usingTexture = true; + curContext.useProgram(programObject3D); + uniformi("usingTexture3d", programObject3D, "uUsingTexture", usingTexture) + }; + p.textureMode = function(mode) { + curTextureMode = mode + }; + var curveVertexSegment = function(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) { + var x0 = x2; + var y0 = y2; + var z0 = z2; + var draw = curveDrawMatrix.array(); + var xplot1 = draw[4] * x1 + draw[5] * x2 + draw[6] * x3 + draw[7] * x4; + var xplot2 = draw[8] * x1 + draw[9] * x2 + draw[10] * x3 + draw[11] * x4; + var xplot3 = draw[12] * x1 + draw[13] * x2 + draw[14] * x3 + draw[15] * x4; + var yplot1 = draw[4] * y1 + draw[5] * y2 + draw[6] * y3 + draw[7] * y4; + var yplot2 = draw[8] * y1 + draw[9] * y2 + draw[10] * y3 + draw[11] * y4; + var yplot3 = draw[12] * y1 + draw[13] * y2 + draw[14] * y3 + draw[15] * y4; + var zplot1 = draw[4] * z1 + draw[5] * z2 + draw[6] * z3 + draw[7] * z4; + var zplot2 = draw[8] * z1 + draw[9] * z2 + draw[10] * z3 + draw[11] * z4; + var zplot3 = draw[12] * z1 + draw[13] * z2 + draw[14] * z3 + draw[15] * z4; + p.vertex(x0, y0, z0); + for (var j = 0; j < curveDet; j++) { + x0 += xplot1; + xplot1 += xplot2; + xplot2 += xplot3; + y0 += yplot1; + yplot1 += yplot2; + yplot2 += yplot3; + z0 += zplot1; + zplot1 += zplot2; + zplot2 += zplot3; + p.vertex(x0, y0, z0) + } + }; + Drawing2D.prototype.curveVertex = function(x, y) { + isCurve = true; + p.vertex(x, y) + }; + Drawing3D.prototype.curveVertex = function(x, y, z) { + isCurve = true; + if (!curveInited) curveInit(); + var vert = []; + vert[0] = x; + vert[1] = y; + vert[2] = z; + curveVertArray.push(vert); + curveVertCount++; + if (curveVertCount > 3) curveVertexSegment(curveVertArray[curveVertCount - 4][0], curveVertArray[curveVertCount - 4][1], curveVertArray[curveVertCount - 4][2], curveVertArray[curveVertCount - 3][0], curveVertArray[curveVertCount - 3][1], curveVertArray[curveVertCount - 3][2], curveVertArray[curveVertCount - 2][0], curveVertArray[curveVertCount - 2][1], curveVertArray[curveVertCount - 2][2], curveVertArray[curveVertCount - 1][0], curveVertArray[curveVertCount - 1][1], curveVertArray[curveVertCount - 1][2]) + }; + Drawing2D.prototype.curve = function(x1, y1, x2, y2, x3, y3, x4, y4) { + p.beginShape(); + p.curveVertex(x1, y1); + p.curveVertex(x2, y2); + p.curveVertex(x3, y3); + p.curveVertex(x4, y4); + p.endShape() + }; + Drawing3D.prototype.curve = function(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) { + if (z4 !== undef) { + p.beginShape(); + p.curveVertex(x1, y1, z1); + p.curveVertex(x2, y2, z2); + p.curveVertex(x3, y3, z3); + p.curveVertex(x4, y4, z4); + p.endShape(); + return + } + p.beginShape(); + p.curveVertex(x1, y1); + p.curveVertex(z1, x2); + p.curveVertex(y2, z2); + p.curveVertex(x3, y3); + p.endShape() + }; + p.curveTightness = function(tightness) { + curTightness = tightness + }; + p.curveDetail = function(detail) { + curveDet = detail; + curveInit() + }; + p.rectMode = function(aRectMode) { + curRectMode = aRectMode + }; + p.imageMode = function(mode) { + switch (mode) { + case 0: + imageModeConvert = imageModeCorner; + break; + case 1: + imageModeConvert = imageModeCorners; + break; + case 3: + imageModeConvert = imageModeCenter; + break; + default: + throw "Invalid imageMode"; + } + }; + p.ellipseMode = function(aEllipseMode) { + curEllipseMode = aEllipseMode + }; + p.arc = function(x, y, width, height, start, stop) { + if (width <= 0 || stop < start) return; + if (curEllipseMode === 1) { + width = width - x; + height = height - y + } else if (curEllipseMode === 2) { + x = x - width; + y = y - height; + width = width * 2; + height = height * 2 + } else if (curEllipseMode === 3) { + x = x - width / 2; + y = y - height / 2 + } + while (start < 0) { + start += 6.283185307179586; + stop += 6.283185307179586 + } + if (stop - start > 6.283185307179586) { + start = 0; + stop = 6.283185307179586 + } + var hr = width / 2, + vr = height / 2, + centerX = x + hr, + centerY = y + vr, + startLUT = 0 | 0.5 + start * p.RAD_TO_DEG * 2, + stopLUT = 0 | 0.5 + stop * p.RAD_TO_DEG * 2, + i, j; + if (doFill) { + var savedStroke = doStroke; + doStroke = false; + p.beginShape(); + p.vertex(centerX, centerY); + for (i = startLUT; i <= stopLUT; i++) { + j = i % 720; + p.vertex(centerX + cosLUT[j] * hr, centerY + sinLUT[j] * vr) + } + p.endShape(2); + doStroke = savedStroke + } + if (doStroke) { + var savedFill = doFill; + doFill = false; + p.beginShape(); + for (i = startLUT; i <= stopLUT; i++) { + j = i % 720; + p.vertex(centerX + cosLUT[j] * hr, centerY + sinLUT[j] * vr) + } + p.endShape(); + doFill = savedFill + } + }; + Drawing2D.prototype.line = function(x1, y1, x2, y2) { + if (!doStroke) return; + x1 = Math.round(x1); + x2 = Math.round(x2); + y1 = Math.round(y1); + y2 = Math.round(y2); + if (x1 === x2 && y1 === y2) { + p.point(x1, y1); + return + } + var swap = undef, + lineCap = undef, + drawCrisp = true, + currentModelView = modelView.array(), + identityMatrix = [1, 0, 0, 0, 1, 0]; + for (var i = 0; i < 6 && drawCrisp; i++) drawCrisp = currentModelView[i] === identityMatrix[i]; + if (drawCrisp) { + if (x1 === x2) { + if (y1 > y2) { + swap = y1; + y1 = y2; + y2 = swap + } + y2++; + if (lineWidth % 2 === 1) curContext.translate(0.5, 0) + } else if (y1 === y2) { + if (x1 > x2) { + swap = x1; + x1 = x2; + x2 = swap + } + x2++; + if (lineWidth % 2 === 1) curContext.translate(0, 0.5) + } + if (lineWidth === 1) { + lineCap = curContext.lineCap; + curContext.lineCap = "butt" + } + } + curContext.beginPath(); + curContext.moveTo(x1 || 0, y1 || 0); + curContext.lineTo(x2 || 0, y2 || 0); + executeContextStroke(); + if (drawCrisp) { + if (x1 === x2 && lineWidth % 2 === 1) curContext.translate(-0.5, 0); + else if (y1 === y2 && lineWidth % 2 === 1) curContext.translate(0, -0.5); + if (lineWidth === 1) curContext.lineCap = lineCap + } + }; + Drawing3D.prototype.line = function(x1, y1, z1, x2, y2, z2) { + if (y2 === undef || z2 === undef) { + z2 = 0; + y2 = x2; + x2 = z1; + z1 = 0 + } + if (x1 === x2 && y1 === y2 && z1 === z2) { + p.point(x1, y1, z1); + return + } + var lineVerts = [x1, y1, z1, x2, y2, z2]; + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + if (lineWidth > 0 && doStroke) { + curContext.useProgram(programObject2D); + uniformMatrix("uModel2d", programObject2D, "uModel", false, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); + uniformMatrix("uView2d", programObject2D, "uView", false, view.array()); + uniformf("uColor2d", programObject2D, "uColor", strokeStyle); + uniformi("uIsDrawingText", programObject2D, "uIsDrawingText", false); + vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, lineBuffer); + disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord"); + curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(lineVerts), curContext.STREAM_DRAW); + curContext.drawArrays(curContext.LINES, 0, 2) + } + }; + Drawing2D.prototype.bezier = function() { + if (arguments.length !== 8) throw "You must use 8 parameters for bezier() in 2D mode"; + p.beginShape(); + p.vertex(arguments[0], arguments[1]); + p.bezierVertex(arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7]); + p.endShape() + }; + Drawing3D.prototype.bezier = function() { + if (arguments.length !== 12) throw "You must use 12 parameters for bezier() in 3D mode"; + p.beginShape(); + p.vertex(arguments[0], arguments[1], arguments[2]); + p.bezierVertex(arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11]); + p.endShape() + }; + p.bezierDetail = function(detail) { + bezDetail = detail + }; + p.bezierPoint = function(a, b, c, d, t) { + return (1 - t) * (1 - t) * (1 - t) * a + 3 * (1 - t) * (1 - t) * t * b + 3 * (1 - t) * t * t * c + t * t * t * d + }; + p.bezierTangent = function(a, b, c, d, t) { + return 3 * t * t * (-a + 3 * b - 3 * c + d) + 6 * t * (a - 2 * b + c) + 3 * (-a + b) + }; + p.curvePoint = function(a, b, c, d, t) { + return 0.5 * (2 * b + (-a + c) * t + (2 * a - 5 * b + 4 * c - d) * t * t + (-a + 3 * b - 3 * c + d) * t * t * t) + }; + p.curveTangent = function(a, b, c, d, t) { + return 0.5 * (-a + c + 2 * (2 * a - 5 * b + 4 * c - d) * t + 3 * (-a + 3 * b - 3 * c + d) * t * t) + }; + p.triangle = function(x1, y1, x2, y2, x3, y3) { + p.beginShape(9); + p.vertex(x1, y1, 0); + p.vertex(x2, y2, 0); + p.vertex(x3, y3, 0); + p.endShape() + }; + p.quad = function(x1, y1, x2, y2, x3, y3, x4, y4) { + p.beginShape(16); + p.vertex(x1, y1, 0); + p.vertex(x2, y2, 0); + p.vertex(x3, y3, 0); + p.vertex(x4, y4, 0); + p.endShape() + }; + var roundedRect$2d = function(x, y, width, height, tl, tr, br, bl) { + if (bl === undef) { + tr = tl; + br = tl; + bl = tl + } + var halfWidth = width / 2, + halfHeight = height / 2; + if (tl > halfWidth || tl > halfHeight) tl = Math.min(halfWidth, halfHeight); + if (tr > halfWidth || tr > halfHeight) tr = Math.min(halfWidth, halfHeight); + if (br > halfWidth || br > halfHeight) br = Math.min(halfWidth, halfHeight); + if (bl > halfWidth || bl > halfHeight) bl = Math.min(halfWidth, halfHeight); + if (!doFill || doStroke) curContext.translate(0.5, 0.5); + curContext.beginPath(); + curContext.moveTo(x + tl, y); + curContext.lineTo(x + width - tr, y); + curContext.quadraticCurveTo(x + width, y, x + width, y + tr); + curContext.lineTo(x + width, y + height - br); + curContext.quadraticCurveTo(x + width, y + height, x + width - br, y + height); + curContext.lineTo(x + bl, y + height); + curContext.quadraticCurveTo(x, y + height, x, y + height - bl); + curContext.lineTo(x, y + tl); + curContext.quadraticCurveTo(x, y, x + tl, y); + if (!doFill || doStroke) curContext.translate(-0.5, -0.5); + executeContextFill(); + executeContextStroke() + }; + Drawing2D.prototype.rect = function(x, y, width, height, tl, tr, br, bl) { + if (!width && !height) return; + if (curRectMode === 1) { + width -= x; + height -= y + } else if (curRectMode === 2) { + width *= 2; + height *= 2; + x -= width / 2; + y -= height / 2 + } else if (curRectMode === 3) { + x -= width / 2; + y -= height / 2 + } + x = Math.round(x); + y = Math.round(y); + width = Math.round(width); + height = Math.round(height); + if (tl !== undef) { + roundedRect$2d(x, y, width, height, tl, tr, br, bl); + return + } + if (doStroke && lineWidth % 2 === 1) curContext.translate(0.5, 0.5); + curContext.beginPath(); + curContext.rect(x, y, width, height); + executeContextFill(); + executeContextStroke(); + if (doStroke && lineWidth % 2 === 1) curContext.translate(-0.5, -0.5) + }; + Drawing3D.prototype.rect = function(x, y, width, height, tl, tr, br, bl) { + if (tl !== undef) throw "rect() with rounded corners is not supported in 3D mode"; + if (curRectMode === 1) { + width -= x; + height -= y + } else if (curRectMode === 2) { + width *= 2; + height *= 2; + x -= width / 2; + y -= height / 2 + } else if (curRectMode === 3) { + x -= width / 2; + y -= height / 2 + } + var model = new PMatrix3D; + model.translate(x, y, 0); + model.scale(width, height, 1); + model.transpose(); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + if (lineWidth > 0 && doStroke) { + curContext.useProgram(programObject2D); + uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array()); + uniformMatrix("uView2d", programObject2D, "uView", false, view.array()); + uniformf("uColor2d", programObject2D, "uColor", strokeStyle); + uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false); + vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, rectBuffer); + disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord"); + curContext.drawArrays(curContext.LINE_LOOP, 0, rectVerts.length / 3) + } + if (doFill) { + curContext.useProgram(programObject3D); + uniformMatrix("uModel3d", programObject3D, "uModel", false, model.array()); + uniformMatrix("uView3d", programObject3D, "uView", false, view.array()); + curContext.enable(curContext.POLYGON_OFFSET_FILL); + curContext.polygonOffset(1, 1); + uniformf("color3d", programObject3D, "uColor", fillStyle); + if (lightCount > 0) { + var v = new PMatrix3D; + v.set(view); + var m = new PMatrix3D; + m.set(model); + v.mult(m); + var normalMatrix = new PMatrix3D; + normalMatrix.set(v); + normalMatrix.invert(); + normalMatrix.transpose(); + uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array()); + vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, rectNormBuffer) + } else disableVertexAttribPointer("normal3d", programObject3D, "aNormal"); + vertexAttribPointer("vertex3d", programObject3D, "aVertex", 3, rectBuffer); + curContext.drawArrays(curContext.TRIANGLE_FAN, 0, rectVerts.length / 3); + curContext.disable(curContext.POLYGON_OFFSET_FILL) + } + }; + Drawing2D.prototype.ellipse = function(x, y, width, height) { + x = x || 0; + y = y || 0; + if (width <= 0 && height <= 0) return; + if (curEllipseMode === 2) { + width *= 2; + height *= 2 + } else if (curEllipseMode === 1) { + width = width - x; + height = height - y; + x += width / 2; + y += height / 2 + } else if (curEllipseMode === 0) { + x += width / 2; + y += height / 2 + } + if (width === height) { + curContext.beginPath(); + curContext.arc(x, y, width / 2, 0, 6.283185307179586, false); + executeContextFill(); + executeContextStroke() + } else { + var w = width / 2, + h = height / 2, + C = 0.5522847498307933, + c_x = C * w, + c_y = C * h; + p.beginShape(); + p.vertex(x + w, y); + p.bezierVertex(x + w, y - c_y, x + c_x, y - h, x, y - h); + p.bezierVertex(x - c_x, y - h, x - w, y - c_y, x - w, y); + p.bezierVertex(x - w, y + c_y, x - c_x, y + h, x, y + h); + p.bezierVertex(x + c_x, y + h, x + w, y + c_y, x + w, y); + p.endShape() + } + }; + Drawing3D.prototype.ellipse = function(x, y, width, height) { + x = x || 0; + y = y || 0; + if (width <= 0 && height <= 0) return; + if (curEllipseMode === 2) { + width *= 2; + height *= 2 + } else if (curEllipseMode === 1) { + width = width - x; + height = height - y; + x += width / 2; + y += height / 2 + } else if (curEllipseMode === 0) { + x += width / 2; + y += height / 2 + } + var w = width / 2, + h = height / 2, + C = 0.5522847498307933, + c_x = C * w, + c_y = C * h; + p.beginShape(); + p.vertex(x + w, y); + p.bezierVertex(x + w, y - c_y, 0, x + c_x, y - h, 0, x, y - h, 0); + p.bezierVertex(x - c_x, y - h, 0, x - w, y - c_y, 0, x - w, y, 0); + p.bezierVertex(x - w, y + c_y, 0, x - c_x, y + h, 0, x, y + h, 0); + p.bezierVertex(x + c_x, y + h, 0, x + w, y + c_y, 0, x + w, y, 0); + p.endShape(); + if (doFill) { + var xAv = 0, + yAv = 0, + i, j; + for (i = 0; i < vertArray.length; i++) { + xAv += vertArray[i][0]; + yAv += vertArray[i][1] + } + xAv /= vertArray.length; + yAv /= vertArray.length; + var vert = [], + fillVertArray = [], + colorVertArray = []; + vert[0] = xAv; + vert[1] = yAv; + vert[2] = 0; + vert[3] = 0; + vert[4] = 0; + vert[5] = fillStyle[0]; + vert[6] = fillStyle[1]; + vert[7] = fillStyle[2]; + vert[8] = fillStyle[3]; + vert[9] = strokeStyle[0]; + vert[10] = strokeStyle[1]; + vert[11] = strokeStyle[2]; + vert[12] = strokeStyle[3]; + vert[13] = normalX; + vert[14] = normalY; + vert[15] = normalZ; + vertArray.unshift(vert); + for (i = 0; i < vertArray.length; i++) { + for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i][j]); + for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i][j]) + } + fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray) + } + }; + p.normal = function(nx, ny, nz) { + if (arguments.length !== 3 || !(typeof nx === "number" && typeof ny === "number" && typeof nz === "number")) throw "normal() requires three numeric arguments."; + normalX = nx; + normalY = ny; + normalZ = nz; + if (curShape !== 0) if (normalMode === 0) normalMode = 1; + else if (normalMode === 1) normalMode = 2 + }; + p.save = function(file, img) { + if (img !== undef) return window.open(img.toDataURL(), "_blank"); + return window.open(p.externals.canvas.toDataURL(), "_blank") + }; + var saveNumber = 0; + p.saveFrame = function(file) { + if (file === undef) file = "screen-####.png"; + var frameFilename = file.replace(/#+/, function(all) { + var s = "" + saveNumber++; + while (s.length < all.length) s = "0" + s; + return s + }); + p.save(frameFilename) + }; + var utilityContext2d = document.createElement("canvas").getContext("2d"); + var canvasDataCache = [undef, undef, undef]; + + function getCanvasData(obj, w, h) { + var canvasData = canvasDataCache.shift(); + if (canvasData === undef) { + canvasData = {}; + canvasData.canvas = document.createElement("canvas"); + canvasData.context = canvasData.canvas.getContext("2d") + } + canvasDataCache.push(canvasData); + var canvas = canvasData.canvas, + context = canvasData.context, + width = w || obj.width, + height = h || obj.height; + canvas.width = width; + canvas.height = height; + if (!obj) context.clearRect(0, 0, width, height); + else if ("data" in obj) context.putImageData(obj, 0, 0); + else { + context.clearRect(0, 0, width, height); + context.drawImage(obj, 0, 0, width, height) + } + return canvasData + } + function buildPixelsObject(pImage) { + return { + getLength: function(aImg) { + return function() { + if (aImg.isRemote) throw "Image is loaded remotely. Cannot get length."; + else return aImg.imageData.data.length ? aImg.imageData.data.length / 4 : 0 + } + }(pImage), + getPixel: function(aImg) { + return function(i) { + var offset = i * 4, + data = aImg.imageData.data; + if (aImg.isRemote) throw "Image is loaded remotely. Cannot get pixels."; + return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255 + } + }(pImage), + setPixel: function(aImg) { + return function(i, c) { + var offset = i * 4, + data = aImg.imageData.data; + if (aImg.isRemote) throw "Image is loaded remotely. Cannot set pixel."; + data[offset + 0] = (c >> 16) & 255; + data[offset + 1] = (c >> 8) & 255; + data[offset + 2] = c & 255; + data[offset + 3] = (c >> 24) & 255; + aImg.__isDirty = true + } + }(pImage), + toArray: function(aImg) { + return function() { + var arr = [], + data = aImg.imageData.data, + length = aImg.width * aImg.height; + if (aImg.isRemote) throw "Image is loaded remotely. Cannot get pixels."; + for (var i = 0, offset = 0; i < length; i++, offset += 4) arr.push((data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255); + return arr + } + }(pImage), + set: function(aImg) { + return function(arr) { + var offset, data, c; + if (this.isRemote) throw "Image is loaded remotely. Cannot set pixels."; + data = aImg.imageData.data; + for (var i = 0, aL = arr.length; i < aL; i++) { + c = arr[i]; + offset = i * 4; + data[offset + 0] = (c >> 16) & 255; + data[offset + 1] = (c >> 8) & 255; + data[offset + 2] = c & 255; + data[offset + 3] = (c >> 24) & 255 + } + aImg.__isDirty = true + } + }(pImage) + } + } + var PImage = function(aWidth, aHeight, aFormat) { + this.__isDirty = false; + if (aWidth instanceof HTMLImageElement) this.fromHTMLImageData(aWidth); + else if (aHeight || aFormat) { + this.width = aWidth || 1; + this.height = aHeight || 1; + var canvas = this.sourceImg = document.createElement("canvas"); + canvas.width = this.width; + canvas.height = this.height; + var imageData = this.imageData = canvas.getContext("2d").createImageData(this.width, this.height); + this.format = aFormat === 2 || aFormat === 4 ? aFormat : 1; + if (this.format === 1) for (var i = 3, data = this.imageData.data, len = data.length; i < len; i += 4) data[i] = 255; + this.__isDirty = true; + this.updatePixels() + } else { + this.width = 0; + this.height = 0; + this.imageData = utilityContext2d.createImageData(1, 1); + this.format = 2 + } + this.pixels = buildPixelsObject(this) + }; + PImage.prototype = { + __isPImage: true, + updatePixels: function() { + var canvas = this.sourceImg; + if (canvas && canvas instanceof HTMLCanvasElement && this.__isDirty) canvas.getContext("2d").putImageData(this.imageData, 0, 0); + this.__isDirty = false + }, + fromHTMLImageData: function(htmlImg) { + var canvasData = getCanvasData(htmlImg); + try { + var imageData = canvasData.context.getImageData(0, 0, htmlImg.width, htmlImg.height); + this.fromImageData(imageData) + } catch(e) { + if (htmlImg.width && htmlImg.height) { + this.isRemote = true; + this.width = htmlImg.width; + this.height = htmlImg.height + } + } + this.sourceImg = htmlImg + }, + "get": function(x, y, w, h) { + if (!arguments.length) return p.get(this); + if (arguments.length === 2) return p.get(x, y, this); + if (arguments.length === 4) return p.get(x, y, w, h, this) + }, + "set": function(x, y, c) { + p.set(x, y, c, this); + this.__isDirty = true + }, + blend: function(srcImg, x, y, width, height, dx, dy, dwidth, dheight, MODE) { + if (arguments.length === 9) p.blend(this, srcImg, x, y, width, height, dx, dy, dwidth, dheight, this); + else if (arguments.length === 10) p.blend(srcImg, x, y, width, height, dx, dy, dwidth, dheight, MODE, this); + delete this.sourceImg + }, + copy: function(srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, dheight) { + if (arguments.length === 8) p.blend(this, srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, 0, this); + else if (arguments.length === 9) p.blend(srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, dheight, 0, this); + delete this.sourceImg + }, + filter: function(mode, param) { + if (arguments.length === 2) p.filter(mode, param, this); + else if (arguments.length === 1) p.filter(mode, null, this); + delete this.sourceImg + }, + save: function(file) { + p.save(file, this) + }, + resize: function(w, h) { + if (this.isRemote) throw "Image is loaded remotely. Cannot resize."; + if (this.width !== 0 || this.height !== 0) { + if (w === 0 && h !== 0) w = Math.floor(this.width / this.height * h); + else if (h === 0 && w !== 0) h = Math.floor(this.height / this.width * w); + var canvas = getCanvasData(this.imageData).canvas; + var imageData = getCanvasData(canvas, w, h).context.getImageData(0, 0, w, h); + this.fromImageData(imageData) + } + }, + mask: function(mask) { + var obj = this.toImageData(), + i, size; + if (mask instanceof PImage || mask.__isPImage) if (mask.width === this.width && mask.height === this.height) { + mask = mask.toImageData(); + for (i = 2, size = this.width * this.height * 4; i < size; i += 4) obj.data[i + 1] = mask.data[i] + } else throw "mask must have the same dimensions as PImage."; + else if (mask instanceof + Array) if (this.width * this.height === mask.length) for (i = 0, size = mask.length; i < size; ++i) obj.data[i * 4 + 3] = mask[i]; + else throw "mask array must be the same length as PImage pixels array."; + this.fromImageData(obj) + }, + loadPixels: nop, + toImageData: function() { + if (this.isRemote) return this.sourceImg; + if (!this.__isDirty) return this.imageData; + var canvasData = getCanvasData(this.sourceImg); + return canvasData.context.getImageData(0, 0, this.width, this.height) + }, + toDataURL: function() { + if (this.isRemote) throw "Image is loaded remotely. Cannot create dataURI."; + var canvasData = getCanvasData(this.imageData); + return canvasData.canvas.toDataURL() + }, + fromImageData: function(canvasImg) { + var w = canvasImg.width, + h = canvasImg.height, + canvas = document.createElement("canvas"), + ctx = canvas.getContext("2d"); + this.width = canvas.width = w; + this.height = canvas.height = h; + ctx.putImageData(canvasImg, 0, 0); + this.format = 2; + this.imageData = canvasImg; + this.sourceImg = canvas + } + }; + p.PImage = PImage; + p.createImage = function(w, h, mode) { + return new PImage(w, h, mode) + }; + p.loadImage = function(file, type, callback) { + if (type) file = file + "." + type; + var pimg; + if (curSketch.imageCache.images[file]) { + pimg = new PImage(curSketch.imageCache.images[file]); + pimg.loaded = true; + return pimg + } + pimg = new PImage; + var img = document.createElement("img"); + pimg.sourceImg = img; + img.onload = function(aImage, aPImage, aCallback) { + var image = aImage; + var pimg = aPImage; + var callback = aCallback; + return function() { + pimg.fromHTMLImageData(image); + pimg.loaded = true; + if (callback) callback() + } + }(img, pimg, callback); + img.src = file; + return pimg + }; + p.requestImage = p.loadImage; + + function get$2(x, y) { + var data; + if (x >= p.width || x < 0 || y < 0 || y >= p.height) return 0; + if (isContextReplaced) { + var offset = ((0 | x) + p.width * (0 | y)) * 4; + data = p.imageData.data; + return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255 + } + data = p.toImageData(0 | x, 0 | y, 1, 1).data; + return (data[3] & 255) << 24 | (data[0] & 255) << 16 | (data[1] & 255) << 8 | data[2] & 255 + } + function get$3(x, y, img) { + if (img.isRemote) throw "Image is loaded remotely. Cannot get x,y."; + var offset = y * img.width * 4 + x * 4, + data = img.imageData.data; + return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255 + } + function get$4(x, y, w, h) { + var c = new PImage(w, h, 2); + c.fromImageData(p.toImageData(x, y, w, h)); + return c + } + function get$5(x, y, w, h, img) { + if (img.isRemote) throw "Image is loaded remotely. Cannot get x,y,w,h."; + var c = new PImage(w, h, 2), + cData = c.imageData.data, + imgWidth = img.width, + imgHeight = img.height, + imgData = img.imageData.data; + var startRow = Math.max(0, -y), + startColumn = Math.max(0, -x), + stopRow = Math.min(h, imgHeight - y), + stopColumn = Math.min(w, imgWidth - x); + for (var i = startRow; i < stopRow; ++i) { + var sourceOffset = ((y + i) * imgWidth + (x + startColumn)) * 4; + var targetOffset = (i * w + startColumn) * 4; + for (var j = startColumn; j < stopColumn; ++j) { + cData[targetOffset++] = imgData[sourceOffset++]; + cData[targetOffset++] = imgData[sourceOffset++]; + cData[targetOffset++] = imgData[sourceOffset++]; + cData[targetOffset++] = imgData[sourceOffset++] + } + } + c.__isDirty = true; + return c + } + p.get = function(x, y, w, h, img) { + if (img !== undefined) return get$5(x, y, w, h, img); + if (h !== undefined) return get$4(x, y, w, h); + if (w !== undefined) return get$3(x, y, w); + if (y !== undefined) return get$2(x, y); + if (x !== undefined) return get$5(0, 0, x.width, x.height, x); + return get$4(0, 0, p.width, p.height) + }; + p.createGraphics = function(w, h, render) { + var pg = new Processing; + pg.size(w, h, render); + pg.background(0, 0); + return pg + }; + + function resetContext() { + if (isContextReplaced) { + curContext = originalContext; + isContextReplaced = false; + p.updatePixels() + } + } + + function SetPixelContextWrapper() { + function wrapFunction(newContext, name) { + function wrapper() { + resetContext(); + curContext[name].apply(curContext, arguments) + } + newContext[name] = wrapper + } + function wrapProperty(newContext, name) { + function getter() { + resetContext(); + return curContext[name] + } + function setter(value) { + resetContext(); + curContext[name] = value + } + p.defineProperty(newContext, name, { + get: getter, + set: setter + }) + } + for (var n in curContext) if (typeof curContext[n] === "function") wrapFunction(this, n); + else wrapProperty(this, n) + } + function replaceContext() { + if (isContextReplaced) return; + p.loadPixels(); + if (proxyContext === null) { + originalContext = curContext; + proxyContext = new SetPixelContextWrapper + } + isContextReplaced = true; + curContext = proxyContext; + setPixelsCached = 0 + } + function set$3(x, y, c) { + if (x < p.width && x >= 0 && y >= 0 && y < p.height) { + replaceContext(); + p.pixels.setPixel((0 | x) + p.width * (0 | y), c); + if (++setPixelsCached > maxPixelsCached) resetContext() + } + } + function set$4(x, y, obj, img) { + if (img.isRemote) throw "Image is loaded remotely. Cannot set x,y."; + var c = p.color.toArray(obj); + var offset = y * img.width * 4 + x * 4; + var data = img.imageData.data; + data[offset] = c[0]; + data[offset + 1] = c[1]; + data[offset + 2] = c[2]; + data[offset + 3] = c[3] + } + p.set = function(x, y, obj, img) { + var color, oldFill; + if (arguments.length === 3) if (typeof obj === "number") set$3(x, y, obj); + else { + if (obj instanceof PImage || obj.__isPImage) p.image(obj, x, y) + } else if (arguments.length === 4) set$4(x, y, obj, img) + }; + p.imageData = {}; + p.pixels = { + getLength: function() { + return p.imageData.data.length ? p.imageData.data.length / 4 : 0 + }, + getPixel: function(i) { + var offset = i * 4, + data = p.imageData.data; + return data[offset + 3] << 24 & 4278190080 | data[offset + 0] << 16 & 16711680 | data[offset + 1] << 8 & 65280 | data[offset + 2] & 255 + }, + setPixel: function(i, c) { + var offset = i * 4, + data = p.imageData.data; + data[offset + 0] = (c & 16711680) >>> 16; + data[offset + 1] = (c & 65280) >>> 8; + data[offset + 2] = c & 255; + data[offset + 3] = (c & 4278190080) >>> 24 + }, + toArray: function() { + var arr = [], + length = p.imageData.width * p.imageData.height, + data = p.imageData.data; + for (var i = 0, offset = 0; i < length; i++, offset += 4) arr.push(data[offset + 3] << 24 & 4278190080 | data[offset + 0] << 16 & 16711680 | data[offset + 1] << 8 & 65280 | data[offset + 2] & 255); + return arr + }, + set: function(arr) { + for (var i = 0, aL = arr.length; i < aL; i++) this.setPixel(i, arr[i]) + } + }; + p.loadPixels = function() { + p.imageData = drawing.$ensureContext().getImageData(0, 0, p.width, p.height) + }; + p.updatePixels = function() { + if (p.imageData) drawing.$ensureContext().putImageData(p.imageData, 0, 0) + }; + p.hint = function(which) { + var curContext = drawing.$ensureContext(); + if (which === 4) { + curContext.disable(curContext.DEPTH_TEST); + curContext.depthMask(false); + curContext.clear(curContext.DEPTH_BUFFER_BIT) + } else if (which === -4) { + curContext.enable(curContext.DEPTH_TEST); + curContext.depthMask(true) + } else if (which === -1 || which === 2) renderSmooth = true; + else if (which === 1) renderSmooth = false + }; + var backgroundHelper = function(arg1, arg2, arg3, arg4) { + var obj; + if (arg1 instanceof PImage || arg1.__isPImage) { + obj = arg1; + if (!obj.loaded) throw "Error using image in background(): PImage not loaded."; + if (obj.width !== p.width || obj.height !== p.height) throw "Background image must be the same dimensions as the canvas."; + } else obj = p.color(arg1, arg2, arg3, arg4); + backgroundObj = obj + }; + Drawing2D.prototype.background = function(arg1, arg2, arg3, arg4) { + if (arg1 !== undef) backgroundHelper(arg1, arg2, arg3, arg4); + if (backgroundObj instanceof PImage || backgroundObj.__isPImage) { + saveContext(); + curContext.setTransform(1, 0, 0, 1, 0, 0); + p.image(backgroundObj, 0, 0); + restoreContext() + } else { + saveContext(); + curContext.setTransform(1, 0, 0, 1, 0, 0); + if (p.alpha(backgroundObj) !== colorModeA) curContext.clearRect(0, 0, p.width, p.height); + curContext.fillStyle = p.color.toString(backgroundObj); + curContext.fillRect(0, 0, p.width, p.height); + isFillDirty = true; + restoreContext() + } + }; + Drawing3D.prototype.background = function(arg1, arg2, arg3, arg4) { + if (arguments.length > 0) backgroundHelper(arg1, arg2, arg3, arg4); + var c = p.color.toGLArray(backgroundObj); + curContext.clearColor(c[0], c[1], c[2], c[3]); + curContext.clear(curContext.COLOR_BUFFER_BIT | curContext.DEPTH_BUFFER_BIT) + }; + Drawing2D.prototype.image = function(img, x, y, w, h) { + x = Math.round(x); + y = Math.round(y); + if (img.width > 0) { + var wid = w || img.width; + var hgt = h || img.height; + var bounds = imageModeConvert(x || 0, y || 0, w || img.width, h || img.height, arguments.length < 4); + var fastImage = !!img.sourceImg && curTint === null; + if (fastImage) { + var htmlElement = img.sourceImg; + if (img.__isDirty) img.updatePixels(); + curContext.drawImage(htmlElement, 0, 0, htmlElement.width, htmlElement.height, bounds.x, bounds.y, bounds.w, bounds.h) + } else { + var obj = img.toImageData(); + if (curTint !== null) { + curTint(obj); + img.__isDirty = true + } + curContext.drawImage(getCanvasData(obj).canvas, 0, 0, img.width, img.height, bounds.x, bounds.y, bounds.w, bounds.h) + } + } + }; + Drawing3D.prototype.image = function(img, x, y, w, h) { + if (img.width > 0) { + x = Math.round(x); + y = Math.round(y); + w = w || img.width; + h = h || img.height; + p.beginShape(p.QUADS); + p.texture(img); + p.vertex(x, y, 0, 0, 0); + p.vertex(x, y + h, 0, 0, h); + p.vertex(x + w, y + h, 0, w, h); + p.vertex(x + w, y, 0, w, 0); + p.endShape() + } + }; + p.tint = function(a1, a2, a3, a4) { + var tintColor = p.color(a1, a2, a3, a4); + var r = p.red(tintColor) / colorModeX; + var g = p.green(tintColor) / colorModeY; + var b = p.blue(tintColor) / colorModeZ; + var a = p.alpha(tintColor) / colorModeA; + curTint = function(obj) { + var data = obj.data, + length = 4 * obj.width * obj.height; + for (var i = 0; i < length;) { + data[i++] *= r; + data[i++] *= g; + data[i++] *= b; + data[i++] *= a + } + }; + curTint3d = function(data) { + for (var i = 0; i < data.length;) { + data[i++] = r; + data[i++] = g; + data[i++] = b; + data[i++] = a + } + } + }; + p.noTint = function() { + curTint = null; + curTint3d = null + }; + p.copy = function(src, sx, sy, sw, sh, dx, dy, dw, dh) { + if (dh === undef) { + dh = dw; + dw = dy; + dy = dx; + dx = sh; + sh = sw; + sw = sy; + sy = sx; + sx = src; + src = p + } + p.blend(src, sx, sy, sw, sh, dx, dy, dw, dh, 0) + }; + p.blend = function(src, sx, sy, sw, sh, dx, dy, dw, dh, mode, pimgdest) { + if (src.isRemote) throw "Image is loaded remotely. Cannot blend image."; + if (mode === undef) { + mode = dh; + dh = dw; + dw = dy; + dy = dx; + dx = sh; + sh = sw; + sw = sy; + sy = sx; + sx = src; + src = p + } + var sx2 = sx + sw, + sy2 = sy + sh, + dx2 = dx + dw, + dy2 = dy + dh, + dest = pimgdest || p; + if (pimgdest === undef || mode === undef) p.loadPixels(); + src.loadPixels(); + if (src === p && p.intersect(sx, sy, sx2, sy2, dx, dy, dx2, dy2)) p.blit_resize(p.get(sx, sy, sx2 - sx, sy2 - sy), 0, 0, sx2 - sx - 1, sy2 - sy - 1, dest.imageData.data, dest.width, dest.height, dx, dy, dx2, dy2, mode); + else p.blit_resize(src, sx, sy, sx2, sy2, dest.imageData.data, dest.width, dest.height, dx, dy, dx2, dy2, mode); + if (pimgdest === undef) p.updatePixels() + }; + var buildBlurKernel = function(r) { + var radius = p.floor(r * 3.5), + i, radiusi; + radius = radius < 1 ? 1 : radius < 248 ? radius : 248; + if (p.shared.blurRadius !== radius) { + p.shared.blurRadius = radius; + p.shared.blurKernelSize = 1 + (p.shared.blurRadius << 1); + p.shared.blurKernel = new Float32Array(p.shared.blurKernelSize); + var sharedBlurKernal = p.shared.blurKernel; + var sharedBlurKernelSize = p.shared.blurKernelSize; + var sharedBlurRadius = p.shared.blurRadius; + for (i = 0; i < sharedBlurKernelSize; i++) sharedBlurKernal[i] = 0; + var radiusiSquared = (radius - 1) * (radius - 1); + for (i = 1; i < radius; i++) sharedBlurKernal[radius + i] = sharedBlurKernal[radiusi] = radiusiSquared; + sharedBlurKernal[radius] = radius * radius + } + }; + var blurARGB = function(r, aImg) { + var sum, cr, cg, cb, ca, c, m; + var read, ri, ym, ymi, bk0; + var wh = aImg.pixels.getLength(); + var r2 = new Float32Array(wh); + var g2 = new Float32Array(wh); + var b2 = new Float32Array(wh); + var a2 = new Float32Array(wh); + var yi = 0; + var x, y, i, offset; + buildBlurKernel(r); + var aImgHeight = aImg.height; + var aImgWidth = aImg.width; + var sharedBlurKernelSize = p.shared.blurKernelSize; + var sharedBlurRadius = p.shared.blurRadius; + var sharedBlurKernal = p.shared.blurKernel; + var pix = aImg.imageData.data; + for (y = 0; y < aImgHeight; y++) { + for (x = 0; x < aImgWidth; x++) { + cb = cg = cr = ca = sum = 0; + read = x - sharedBlurRadius; + if (read < 0) { + bk0 = -read; + read = 0 + } else { + if (read >= aImgWidth) break; + bk0 = 0 + } + for (i = bk0; i < sharedBlurKernelSize; i++) { + if (read >= aImgWidth) break; + offset = (read + yi) * 4; + m = sharedBlurKernal[i]; + ca += m * pix[offset + 3]; + cr += m * pix[offset]; + cg += m * pix[offset + 1]; + cb += m * pix[offset + 2]; + sum += m; + read++ + } + ri = yi + x; + a2[ri] = ca / sum; + r2[ri] = cr / sum; + g2[ri] = cg / sum; + b2[ri] = cb / sum + } + yi += aImgWidth + } + yi = 0; + ym = -sharedBlurRadius; + ymi = ym * aImgWidth; + for (y = 0; y < aImgHeight; y++) { + for (x = 0; x < aImgWidth; x++) { + cb = cg = cr = ca = sum = 0; + if (ym < 0) { + bk0 = ri = -ym; + read = x + } else { + if (ym >= aImgHeight) break; + bk0 = 0; + ri = ym; + read = x + ymi + } + for (i = bk0; i < sharedBlurKernelSize; i++) { + if (ri >= aImgHeight) break; + m = sharedBlurKernal[i]; + ca += m * a2[read]; + cr += m * r2[read]; + cg += m * g2[read]; + cb += m * b2[read]; + sum += m; + ri++; + read += aImgWidth + } + offset = (x + yi) * 4; + pix[offset] = cr / sum; + pix[offset + 1] = cg / sum; + pix[offset + 2] = cb / sum; + pix[offset + 3] = ca / sum + } + yi += aImgWidth; + ymi += aImgWidth; + ym++ + } + }; + var dilate = function(isInverted, aImg) { + var currIdx = 0; + var maxIdx = aImg.pixels.getLength(); + var out = new Int32Array(maxIdx); + var currRowIdx, maxRowIdx, colOrig, colOut, currLum; + var idxRight, idxLeft, idxUp, idxDown, colRight, colLeft, colUp, colDown, lumRight, lumLeft, lumUp, lumDown; + if (!isInverted) while (currIdx < maxIdx) { + currRowIdx = currIdx; + maxRowIdx = currIdx + aImg.width; + while (currIdx < maxRowIdx) { + colOrig = colOut = aImg.pixels.getPixel(currIdx); + idxLeft = currIdx - 1; + idxRight = currIdx + 1; + idxUp = currIdx - aImg.width; + idxDown = currIdx + aImg.width; + if (idxLeft < currRowIdx) idxLeft = currIdx; + if (idxRight >= maxRowIdx) idxRight = currIdx; + if (idxUp < 0) idxUp = 0; + if (idxDown >= maxIdx) idxDown = currIdx; + colUp = aImg.pixels.getPixel(idxUp); + colLeft = aImg.pixels.getPixel(idxLeft); + colDown = aImg.pixels.getPixel(idxDown); + colRight = aImg.pixels.getPixel(idxRight); + currLum = 77 * (colOrig >> 16 & 255) + 151 * (colOrig >> 8 & 255) + 28 * (colOrig & 255); + lumLeft = 77 * (colLeft >> 16 & 255) + 151 * (colLeft >> 8 & 255) + 28 * (colLeft & 255); + lumRight = 77 * (colRight >> 16 & 255) + 151 * (colRight >> 8 & 255) + 28 * (colRight & 255); + lumUp = 77 * (colUp >> 16 & 255) + 151 * (colUp >> 8 & 255) + 28 * (colUp & 255); + lumDown = 77 * (colDown >> 16 & 255) + 151 * (colDown >> 8 & 255) + 28 * (colDown & 255); + if (lumLeft > currLum) { + colOut = colLeft; + currLum = lumLeft + } + if (lumRight > currLum) { + colOut = colRight; + currLum = lumRight + } + if (lumUp > currLum) { + colOut = colUp; + currLum = lumUp + } + if (lumDown > currLum) { + colOut = colDown; + currLum = lumDown + } + out[currIdx++] = colOut + } + } else while (currIdx < maxIdx) { + currRowIdx = currIdx; + maxRowIdx = currIdx + aImg.width; + while (currIdx < maxRowIdx) { + colOrig = colOut = aImg.pixels.getPixel(currIdx); + idxLeft = currIdx - 1; + idxRight = currIdx + 1; + idxUp = currIdx - aImg.width; + idxDown = currIdx + aImg.width; + if (idxLeft < currRowIdx) idxLeft = currIdx; + if (idxRight >= maxRowIdx) idxRight = currIdx; + if (idxUp < 0) idxUp = 0; + if (idxDown >= maxIdx) idxDown = currIdx; + colUp = aImg.pixels.getPixel(idxUp); + colLeft = aImg.pixels.getPixel(idxLeft); + colDown = aImg.pixels.getPixel(idxDown); + colRight = aImg.pixels.getPixel(idxRight); + currLum = 77 * (colOrig >> 16 & 255) + 151 * (colOrig >> 8 & 255) + 28 * (colOrig & 255); + lumLeft = 77 * (colLeft >> 16 & 255) + 151 * (colLeft >> 8 & 255) + 28 * (colLeft & 255); + lumRight = 77 * (colRight >> 16 & 255) + 151 * (colRight >> 8 & 255) + 28 * (colRight & 255); + lumUp = 77 * (colUp >> 16 & 255) + 151 * (colUp >> 8 & 255) + 28 * (colUp & 255); + lumDown = 77 * (colDown >> 16 & 255) + 151 * (colDown >> 8 & 255) + 28 * (colDown & 255); + if (lumLeft < currLum) { + colOut = colLeft; + currLum = lumLeft + } + if (lumRight < currLum) { + colOut = colRight; + currLum = lumRight + } + if (lumUp < currLum) { + colOut = colUp; + currLum = lumUp + } + if (lumDown < currLum) { + colOut = colDown; + currLum = lumDown + } + out[currIdx++] = colOut + } + } + aImg.pixels.set(out) + }; + p.filter = function(kind, param, aImg) { + var img, col, lum, i; + if (arguments.length === 3) { + aImg.loadPixels(); + img = aImg + } else { + p.loadPixels(); + img = p + } + if (param === undef) param = null; + if (img.isRemote) throw "Image is loaded remotely. Cannot filter image."; + var imglen = img.pixels.getLength(); + switch (kind) { + case 11: + var radius = param || 1; + blurARGB(radius, img); + break; + case 12: + if (img.format === 4) { + for (i = 0; i < imglen; i++) { + col = 255 - img.pixels.getPixel(i); + img.pixels.setPixel(i, 4278190080 | col << 16 | col << 8 | col) + } + img.format = 1 + } else for (i = 0; i < imglen; i++) { + col = img.pixels.getPixel(i); + lum = 77 * (col >> 16 & 255) + 151 * (col >> 8 & 255) + 28 * (col & 255) >> 8; + img.pixels.setPixel(i, col & 4278190080 | lum << 16 | lum << 8 | lum) + } + break; + case 13: + for (i = 0; i < imglen; i++) img.pixels.setPixel(i, img.pixels.getPixel(i) ^ 16777215); + break; + case 15: + if (param === null) throw "Use filter(POSTERIZE, int levels) instead of filter(POSTERIZE)"; + var levels = p.floor(param); + if (levels < 2 || levels > 255) throw "Levels must be between 2 and 255 for filter(POSTERIZE, levels)"; + var levels1 = levels - 1; + for (i = 0; i < imglen; i++) { + var rlevel = img.pixels.getPixel(i) >> 16 & 255; + var glevel = img.pixels.getPixel(i) >> 8 & 255; + var blevel = img.pixels.getPixel(i) & 255; + rlevel = (rlevel * levels >> 8) * 255 / levels1; + glevel = (glevel * levels >> 8) * 255 / levels1; + blevel = (blevel * levels >> 8) * 255 / levels1; + img.pixels.setPixel(i, 4278190080 & img.pixels.getPixel(i) | rlevel << 16 | glevel << 8 | blevel) + } + break; + case 14: + for (i = 0; i < imglen; i++) img.pixels.setPixel(i, img.pixels.getPixel(i) | 4278190080); + img.format = 1; + break; + case 16: + if (param === null) param = 0.5; + if (param < 0 || param > 1) throw "Level must be between 0 and 1 for filter(THRESHOLD, level)"; + var thresh = p.floor(param * 255); + for (i = 0; i < imglen; i++) { + var max = p.max((img.pixels.getPixel(i) & 16711680) >> 16, p.max((img.pixels.getPixel(i) & 65280) >> 8, img.pixels.getPixel(i) & 255)); + img.pixels.setPixel(i, img.pixels.getPixel(i) & 4278190080 | (max < thresh ? 0 : 16777215)) + } + break; + case 17: + dilate(true, img); + break; + case 18: + dilate(false, img); + break + } + img.updatePixels() + }; + p.shared = { + fracU: 0, + ifU: 0, + fracV: 0, + ifV: 0, + u1: 0, + u2: 0, + v1: 0, + v2: 0, + sX: 0, + sY: 0, + iw: 0, + iw1: 0, + ih1: 0, + ul: 0, + ll: 0, + ur: 0, + lr: 0, + cUL: 0, + cLL: 0, + cUR: 0, + cLR: 0, + srcXOffset: 0, + srcYOffset: 0, + r: 0, + g: 0, + b: 0, + a: 0, + srcBuffer: null, + blurRadius: 0, + blurKernelSize: 0, + blurKernel: null + }; + p.intersect = function(sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2) { + var sw = sx2 - sx1 + 1; + var sh = sy2 - sy1 + 1; + var dw = dx2 - dx1 + 1; + var dh = dy2 - dy1 + 1; + if (dx1 < sx1) { + dw += dx1 - sx1; + if (dw > sw) dw = sw + } else { + var w = sw + sx1 - dx1; + if (dw > w) dw = w + } + if (dy1 < sy1) { + dh += dy1 - sy1; + if (dh > sh) dh = sh + } else { + var h = sh + sy1 - dy1; + if (dh > h) dh = h + } + return ! (dw <= 0 || dh <= 0) + }; + var blendFuncs = {}; + blendFuncs[1] = p.modes.blend; + blendFuncs[2] = p.modes.add; + blendFuncs[4] = p.modes.subtract; + blendFuncs[8] = p.modes.lightest; + blendFuncs[16] = p.modes.darkest; + blendFuncs[0] = p.modes.replace; + blendFuncs[32] = p.modes.difference; + blendFuncs[64] = p.modes.exclusion; + blendFuncs[128] = p.modes.multiply; + blendFuncs[256] = p.modes.screen; + blendFuncs[512] = p.modes.overlay; + blendFuncs[1024] = p.modes.hard_light; + blendFuncs[2048] = p.modes.soft_light; + blendFuncs[4096] = p.modes.dodge; + blendFuncs[8192] = p.modes.burn; + p.blit_resize = function(img, srcX1, srcY1, srcX2, srcY2, destPixels, screenW, screenH, destX1, destY1, destX2, destY2, mode) { + var x, y; + if (srcX1 < 0) srcX1 = 0; + if (srcY1 < 0) srcY1 = 0; + if (srcX2 >= img.width) srcX2 = img.width - 1; + if (srcY2 >= img.height) srcY2 = img.height - 1; + var srcW = srcX2 - srcX1; + var srcH = srcY2 - srcY1; + var destW = destX2 - destX1; + var destH = destY2 - destY1; + if (destW <= 0 || destH <= 0 || srcW <= 0 || srcH <= 0 || destX1 >= screenW || destY1 >= screenH || srcX1 >= img.width || srcY1 >= img.height) return; + var dx = Math.floor(srcW / destW * 32768); + var dy = Math.floor(srcH / destH * 32768); + var pshared = p.shared; + pshared.srcXOffset = Math.floor(destX1 < 0 ? -destX1 * dx : srcX1 * 32768); + pshared.srcYOffset = Math.floor(destY1 < 0 ? -destY1 * dy : srcY1 * 32768); + if (destX1 < 0) { + destW += destX1; + destX1 = 0 + } + if (destY1 < 0) { + destH += destY1; + destY1 = 0 + } + destW = Math.min(destW, screenW - destX1); + destH = Math.min(destH, screenH - destY1); + var destOffset = destY1 * screenW + destX1; + var destColor; + pshared.srcBuffer = img.imageData.data; + pshared.iw = img.width; + pshared.iw1 = img.width - 1; + pshared.ih1 = img.height - 1; + var filterBilinear = p.filter_bilinear, + filterNewScanline = p.filter_new_scanline, + blendFunc = blendFuncs[mode], + blendedColor, idx, cULoffset, cURoffset, cLLoffset, cLRoffset, ALPHA_MASK = 4278190080, + RED_MASK = 16711680, + GREEN_MASK = 65280, + BLUE_MASK = 255, + PREC_MAXVAL = 32767, + PRECISIONB = 15, + PREC_RED_SHIFT = 1, + PREC_ALPHA_SHIFT = 9, + srcBuffer = pshared.srcBuffer, + min = Math.min; + for (y = 0; y < destH; y++) { + pshared.sX = pshared.srcXOffset; + pshared.fracV = pshared.srcYOffset & PREC_MAXVAL; + pshared.ifV = PREC_MAXVAL - pshared.fracV; + pshared.v1 = (pshared.srcYOffset >> PRECISIONB) * pshared.iw; + pshared.v2 = min((pshared.srcYOffset >> PRECISIONB) + 1, pshared.ih1) * pshared.iw; + for (x = 0; x < destW; x++) { + idx = (destOffset + x) * 4; + destColor = destPixels[idx + 3] << 24 & ALPHA_MASK | destPixels[idx] << 16 & RED_MASK | destPixels[idx + 1] << 8 & GREEN_MASK | destPixels[idx + 2] & BLUE_MASK; + pshared.fracU = pshared.sX & PREC_MAXVAL; + pshared.ifU = PREC_MAXVAL - pshared.fracU; + pshared.ul = pshared.ifU * pshared.ifV >> PRECISIONB; + pshared.ll = pshared.ifU * pshared.fracV >> PRECISIONB; + pshared.ur = pshared.fracU * pshared.ifV >> PRECISIONB; + pshared.lr = pshared.fracU * pshared.fracV >> PRECISIONB; + pshared.u1 = pshared.sX >> PRECISIONB; + pshared.u2 = min(pshared.u1 + 1, pshared.iw1); + cULoffset = (pshared.v1 + pshared.u1) * 4; + cURoffset = (pshared.v1 + pshared.u2) * 4; + cLLoffset = (pshared.v2 + pshared.u1) * 4; + cLRoffset = (pshared.v2 + pshared.u2) * 4; + pshared.cUL = srcBuffer[cULoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cULoffset] << 16 & RED_MASK | srcBuffer[cULoffset + 1] << 8 & GREEN_MASK | srcBuffer[cULoffset + 2] & BLUE_MASK; + pshared.cUR = srcBuffer[cURoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cURoffset] << 16 & RED_MASK | srcBuffer[cURoffset + 1] << 8 & GREEN_MASK | srcBuffer[cURoffset + 2] & BLUE_MASK; + pshared.cLL = srcBuffer[cLLoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cLLoffset] << 16 & RED_MASK | srcBuffer[cLLoffset + 1] << 8 & GREEN_MASK | srcBuffer[cLLoffset + 2] & BLUE_MASK; + pshared.cLR = srcBuffer[cLRoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cLRoffset] << 16 & RED_MASK | srcBuffer[cLRoffset + 1] << 8 & GREEN_MASK | srcBuffer[cLRoffset + 2] & BLUE_MASK; + pshared.r = pshared.ul * ((pshared.cUL & RED_MASK) >> 16) + pshared.ll * ((pshared.cLL & RED_MASK) >> 16) + pshared.ur * ((pshared.cUR & RED_MASK) >> 16) + pshared.lr * ((pshared.cLR & RED_MASK) >> 16) << PREC_RED_SHIFT & RED_MASK; + pshared.g = pshared.ul * (pshared.cUL & GREEN_MASK) + pshared.ll * (pshared.cLL & GREEN_MASK) + pshared.ur * (pshared.cUR & GREEN_MASK) + pshared.lr * (pshared.cLR & GREEN_MASK) >>> PRECISIONB & GREEN_MASK; + pshared.b = pshared.ul * (pshared.cUL & BLUE_MASK) + pshared.ll * (pshared.cLL & BLUE_MASK) + pshared.ur * (pshared.cUR & BLUE_MASK) + pshared.lr * (pshared.cLR & BLUE_MASK) >>> PRECISIONB; + pshared.a = pshared.ul * ((pshared.cUL & ALPHA_MASK) >>> 24) + pshared.ll * ((pshared.cLL & ALPHA_MASK) >>> 24) + pshared.ur * ((pshared.cUR & ALPHA_MASK) >>> 24) + pshared.lr * ((pshared.cLR & ALPHA_MASK) >>> 24) << PREC_ALPHA_SHIFT & ALPHA_MASK; + blendedColor = blendFunc(destColor, pshared.a | pshared.r | pshared.g | pshared.b); + destPixels[idx] = (blendedColor & RED_MASK) >>> 16; + destPixels[idx + 1] = (blendedColor & GREEN_MASK) >>> 8; + destPixels[idx + 2] = blendedColor & BLUE_MASK; + destPixels[idx + 3] = (blendedColor & ALPHA_MASK) >>> 24; + pshared.sX += dx + } + destOffset += screenW; + pshared.srcYOffset += dy + } + }; + p.loadFont = function(name, size) { + if (name === undef) throw "font name required in loadFont."; + if (name.indexOf(".svg") === -1) { + if (size === undef) size = curTextFont.size; + return PFont.get(name, size) + } + var font = p.loadGlyphs(name); + return { + name: name, + css: "12px sans-serif", + glyph: true, + units_per_em: font.units_per_em, + horiz_adv_x: 1 / font.units_per_em * font.horiz_adv_x, + ascent: font.ascent, + descent: font.descent, + width: function(str) { + var width = 0; + var len = str.length; + for (var i = 0; i < len; i++) try { + width += parseFloat(p.glyphLook(p.glyphTable[name], str[i]).horiz_adv_x) + } catch(e) { + Processing.debug(e) + } + return width / p.glyphTable[name].units_per_em + } + } + }; + p.createFont = function(name, size) { + return p.loadFont(name, size) + }; + p.textFont = function(pfont, size) { + if (size !== undef) { + if (!pfont.glyph) pfont = PFont.get(pfont.name, size); + curTextSize = size + } + curTextFont = pfont; + curFontName = curTextFont.name; + curTextAscent = curTextFont.ascent; + curTextDescent = curTextFont.descent; + curTextLeading = curTextFont.leading; + var curContext = drawing.$ensureContext(); + curContext.font = curTextFont.css + }; + p.textSize = function(size) { + curTextFont = PFont.get(curFontName, size); + curTextSize = size; + curTextAscent = curTextFont.ascent; + curTextDescent = curTextFont.descent; + curTextLeading = curTextFont.leading; + var curContext = drawing.$ensureContext(); + curContext.font = curTextFont.css + }; + p.textAscent = function() { + return curTextAscent + }; + p.textDescent = function() { + return curTextDescent + }; + p.textLeading = function(leading) { + curTextLeading = leading + }; + p.textAlign = function(xalign, yalign) { + horizontalTextAlignment = xalign; + verticalTextAlignment = yalign || 0 + }; + + function toP5String(obj) { + if (obj instanceof String) return obj; + if (typeof obj === "number") { + if (obj === (0 | obj)) return obj.toString(); + return p.nf(obj, 0, 3) + } + if (obj === null || obj === undef) return ""; + return obj.toString() + } + Drawing2D.prototype.textWidth = function(str) { + var lines = toP5String(str).split(/\r?\n/g), + width = 0; + var i, linesCount = lines.length; + curContext.font = curTextFont.css; + for (i = 0; i < linesCount; ++i) width = Math.max(width, curTextFont.measureTextWidth(lines[i])); + return width | 0 + }; + Drawing3D.prototype.textWidth = function(str) { + var lines = toP5String(str).split(/\r?\n/g), + width = 0; + var i, linesCount = lines.length; + if (textcanvas === undef) textcanvas = document.createElement("canvas"); + var textContext = textcanvas.getContext("2d"); + textContext.font = curTextFont.css; + for (i = 0; i < linesCount; ++i) width = Math.max(width, textContext.measureText(lines[i]).width); + return width | 0 + }; + p.glyphLook = function(font, chr) { + try { + switch (chr) { + case "1": + return font.one; + case "2": + return font.two; + case "3": + return font.three; + case "4": + return font.four; + case "5": + return font.five; + case "6": + return font.six; + case "7": + return font.seven; + case "8": + return font.eight; + case "9": + return font.nine; + case "0": + return font.zero; + case " ": + return font.space; + case "$": + return font.dollar; + case "!": + return font.exclam; + case '"': + return font.quotedbl; + case "#": + return font.numbersign; + case "%": + return font.percent; + case "&": + return font.ampersand; + case "'": + return font.quotesingle; + case "(": + return font.parenleft; + case ")": + return font.parenright; + case "*": + return font.asterisk; + case "+": + return font.plus; + case ",": + return font.comma; + case "-": + return font.hyphen; + case ".": + return font.period; + case "/": + return font.slash; + case "_": + return font.underscore; + case ":": + return font.colon; + case ";": + return font.semicolon; + case "<": + return font.less; + case "=": + return font.equal; + case ">": + return font.greater; + case "?": + return font.question; + case "@": + return font.at; + case "[": + return font.bracketleft; + case "\\": + return font.backslash; + case "]": + return font.bracketright; + case "^": + return font.asciicircum; + case "`": + return font.grave; + case "{": + return font.braceleft; + case "|": + return font.bar; + case "}": + return font.braceright; + case "~": + return font.asciitilde; + default: + return font[chr] + } + } catch(e) { + Processing.debug(e) + } + }; + Drawing2D.prototype.text$line = function(str, x, y, z, align) { + var textWidth = 0, + xOffset = 0; + if (!curTextFont.glyph) { + if (str && "fillText" in curContext) { + if (isFillDirty) { + curContext.fillStyle = p.color.toString(currentFillColor); + isFillDirty = false + } + if (align === 39 || align === 3) { + textWidth = curTextFont.measureTextWidth(str); + if (align === 39) xOffset = -textWidth; + else xOffset = -textWidth / 2 + } + curContext.fillText(str, x + xOffset, y) + } + } else { + var font = p.glyphTable[curFontName]; + saveContext(); + curContext.translate(x, y + curTextSize); + if (align === 39 || align === 3) { + textWidth = font.width(str); + if (align === 39) xOffset = -textWidth; + else xOffset = -textWidth / 2 + } + var upem = font.units_per_em, + newScale = 1 / upem * curTextSize; + curContext.scale(newScale, newScale); + for (var i = 0, len = str.length; i < len; i++) try { + p.glyphLook(font, str[i]).draw() + } catch(e) { + Processing.debug(e) + } + restoreContext() + } + }; + Drawing3D.prototype.text$line = function(str, x, y, z, align) { + if (textcanvas === undef) textcanvas = document.createElement("canvas"); + var oldContext = curContext; + curContext = textcanvas.getContext("2d"); + curContext.font = curTextFont.css; + var textWidth = curTextFont.measureTextWidth(str); + textcanvas.width = textWidth; + textcanvas.height = curTextSize; + curContext = textcanvas.getContext("2d"); + curContext.font = curTextFont.css; + curContext.textBaseline = "top"; + Drawing2D.prototype.text$line(str, 0, 0, 0, 37); + var aspect = textcanvas.width / textcanvas.height; + curContext = oldContext; + curContext.bindTexture(curContext.TEXTURE_2D, textTex); + curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, textcanvas); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_T, curContext.CLAMP_TO_EDGE); + curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_S, curContext.CLAMP_TO_EDGE); + var xOffset = 0; + if (align === 39) xOffset = -textWidth; + else if (align === 3) xOffset = -textWidth / 2; + var model = new PMatrix3D; + var scalefactor = curTextSize * 0.5; + model.translate(x + xOffset - scalefactor / 2, y - scalefactor, z); + model.scale(-aspect * scalefactor, -scalefactor, scalefactor); + model.translate(-1, -1, -1); + model.transpose(); + var view = new PMatrix3D; + view.scale(1, -1, 1); + view.apply(modelView.array()); + view.transpose(); + curContext.useProgram(programObject2D); + vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, textBuffer); + vertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord", 2, textureBuffer); + uniformi("uSampler2d", programObject2D, "uSampler", [0]); + uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", true); + uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array()); + uniformMatrix("uView2d", programObject2D, "uView", false, view.array()); + uniformf("uColor2d", programObject2D, "uColor", fillStyle); + curContext.bindBuffer(curContext.ELEMENT_ARRAY_BUFFER, indexBuffer); + curContext.drawElements(curContext.TRIANGLES, 6, curContext.UNSIGNED_SHORT, 0) + }; + + function text$4(str, x, y, z) { + var lines, linesCount; + if (str.indexOf("\n") < 0) { + lines = [str]; + linesCount = 1 + } else { + lines = str.split(/\r?\n/g); + linesCount = lines.length + } + var yOffset = 0; + if (verticalTextAlignment === 101) yOffset = curTextAscent + curTextDescent; + else if (verticalTextAlignment === 3) yOffset = curTextAscent / 2 - (linesCount - 1) * curTextLeading / 2; + else if (verticalTextAlignment === 102) yOffset = -(curTextDescent + (linesCount - 1) * curTextLeading); + for (var i = 0; i < linesCount; ++i) { + var line = lines[i]; + drawing.text$line(line, x, y + yOffset, z, horizontalTextAlignment); + yOffset += curTextLeading + } + } + function text$6(str, x, y, width, height, z) { + if (str.length === 0 || width === 0 || height === 0) return; + if (curTextSize > height) return; + var spaceMark = -1; + var start = 0; + var lineWidth = 0; + var drawCommands = []; + for (var charPos = 0, len = str.length; charPos < len; charPos++) { + var currentChar = str[charPos]; + var spaceChar = currentChar === " "; + var letterWidth = curTextFont.measureTextWidth(currentChar); + if (currentChar !== "\n" && lineWidth + letterWidth <= width) { + if (spaceChar) spaceMark = charPos; + lineWidth += letterWidth + } else { + if (spaceMark + 1 === start) if (charPos > 0) spaceMark = charPos; + else return; + if (currentChar === "\n") { + drawCommands.push({ + text: str.substring(start, charPos), + width: lineWidth + }); + start = charPos + 1 + } else { + drawCommands.push({ + text: str.substring(start, spaceMark + 1), + width: lineWidth + }); + start = spaceMark + 1 + } + lineWidth = 0; + charPos = start - 1 + } + } + if (start < len) drawCommands.push({ + text: str.substring(start), + width: lineWidth + }); + var xOffset = 1, + yOffset = curTextAscent; + if (horizontalTextAlignment === 3) xOffset = width / 2; + else if (horizontalTextAlignment === 39) xOffset = width; + var linesCount = drawCommands.length, + visibleLines = Math.min(linesCount, Math.floor(height / curTextLeading)); + if (verticalTextAlignment === 101) yOffset = curTextAscent + curTextDescent; + else if (verticalTextAlignment === 3) yOffset = height / 2 - curTextLeading * (visibleLines / 2 - 1); + else if (verticalTextAlignment === 102) yOffset = curTextDescent + curTextLeading; + var command, drawCommand, leading; + for (command = 0; command < linesCount; command++) { + leading = command * curTextLeading; + if (yOffset + leading > height - curTextDescent) break; + drawCommand = drawCommands[command]; + drawing.text$line(drawCommand.text, x + xOffset, y + yOffset + leading, z, horizontalTextAlignment) + } + } + p.text = function() { + if (textMode === 5) return; + if (arguments.length === 3) text$4(toP5String(arguments[0]), arguments[1], arguments[2], 0); + else if (arguments.length === 4) text$4(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3]); + else if (arguments.length === 5) text$6(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3], arguments[4], 0); + else if (arguments.length === 6) text$6(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]) + }; + p.textMode = function(mode) { + textMode = mode + }; + p.loadGlyphs = function(url) { + var x, y, cx, cy, nx, ny, d, a, lastCom, lenC, horiz_adv_x, getXY = "[0-9\\-]+", + path; + var regex = function(needle, hay) { + var i = 0, + results = [], + latest, regexp = new RegExp(needle, "g"); + latest = results[i] = regexp.exec(hay); + while (latest) { + i++; + latest = results[i] = regexp.exec(hay) + } + return results + }; + var buildPath = function(d) { + var c = regex("[A-Za-z][0-9\\- ]+|Z", d); + var beforePathDraw = function() { + saveContext(); + return drawing.$ensureContext() + }; + var afterPathDraw = function() { + executeContextFill(); + executeContextStroke(); + restoreContext() + }; + path = "return {draw:function(){var curContext=beforePathDraw();curContext.beginPath();"; + x = 0; + y = 0; + cx = 0; + cy = 0; + nx = 0; + ny = 0; + d = 0; + a = 0; + lastCom = ""; + lenC = c.length - 1; + for (var j = 0; j < lenC; j++) { + var com = c[j][0], + xy = regex(getXY, com); + switch (com[0]) { + case "M": + x = parseFloat(xy[0][0]); + y = parseFloat(xy[1][0]); + path += "curContext.moveTo(" + x + "," + -y + ");"; + break; + case "L": + x = parseFloat(xy[0][0]); + y = parseFloat(xy[1][0]); + path += "curContext.lineTo(" + x + "," + -y + ");"; + break; + case "H": + x = parseFloat(xy[0][0]); + path += "curContext.lineTo(" + x + "," + -y + ");"; + break; + case "V": + y = parseFloat(xy[0][0]); + path += "curContext.lineTo(" + x + "," + -y + ");"; + break; + case "T": + nx = parseFloat(xy[0][0]); + ny = parseFloat(xy[1][0]); + if (lastCom === "Q" || lastCom === "T") { + d = Math.sqrt(Math.pow(x - cx, 2) + Math.pow(cy - y, 2)); + a = Math.PI + Math.atan2(cx - x, cy - y); + cx = x + Math.sin(a) * d; + cy = y + Math.cos(a) * d + } else { + cx = x; + cy = y + } + path += "curContext.quadraticCurveTo(" + cx + "," + -cy + "," + nx + "," + -ny + ");"; + x = nx; + y = ny; + break; + case "Q": + cx = parseFloat(xy[0][0]); + cy = parseFloat(xy[1][0]); + nx = parseFloat(xy[2][0]); + ny = parseFloat(xy[3][0]); + path += "curContext.quadraticCurveTo(" + cx + "," + -cy + "," + nx + "," + -ny + ");"; + x = nx; + y = ny; + break; + case "Z": + path += "curContext.closePath();"; + break + } + lastCom = com[0] + } + path += "afterPathDraw();"; + path += "curContext.translate(" + horiz_adv_x + ",0);"; + path += "}}"; + return (new Function("beforePathDraw", "afterPathDraw", path))(beforePathDraw, afterPathDraw) + }; + var parseSVGFont = function(svg) { + var font = svg.getElementsByTagName("font"); + p.glyphTable[url].horiz_adv_x = font[0].getAttribute("horiz-adv-x"); + var font_face = svg.getElementsByTagName("font-face")[0]; + p.glyphTable[url].units_per_em = parseFloat(font_face.getAttribute("units-per-em")); + p.glyphTable[url].ascent = parseFloat(font_face.getAttribute("ascent")); + p.glyphTable[url].descent = parseFloat(font_face.getAttribute("descent")); + var glyph = svg.getElementsByTagName("glyph"), + len = glyph.length; + for (var i = 0; i < len; i++) { + var unicode = glyph[i].getAttribute("unicode"); + var name = glyph[i].getAttribute("glyph-name"); + horiz_adv_x = glyph[i].getAttribute("horiz-adv-x"); + if (horiz_adv_x === null) horiz_adv_x = p.glyphTable[url].horiz_adv_x; + d = glyph[i].getAttribute("d"); + if (d !== undef) { + path = buildPath(d); + p.glyphTable[url][name] = { + name: name, + unicode: unicode, + horiz_adv_x: horiz_adv_x, + draw: path.draw + } + } + } + }; + var loadXML = function() { + var xmlDoc; + try { + xmlDoc = document.implementation.createDocument("", "", null) + } catch(e_fx_op) { + Processing.debug(e_fx_op.message); + return + } + try { + xmlDoc.async = false; + xmlDoc.load(url); + parseSVGFont(xmlDoc.getElementsByTagName("svg")[0]) + } catch(e_sf_ch) { + Processing.debug(e_sf_ch); + try { + var xmlhttp = new window.XMLHttpRequest; + xmlhttp.open("GET", url, false); + xmlhttp.send(null); + parseSVGFont(xmlhttp.responseXML.documentElement) + } catch(e) { + Processing.debug(e_sf_ch) + } + } + }; + p.glyphTable[url] = {}; + loadXML(url); + return p.glyphTable[url] + }; + p.param = function(name) { + var attributeName = "data-processing-" + name; + if (curElement.hasAttribute(attributeName)) return curElement.getAttribute(attributeName); + for (var i = 0, len = curElement.childNodes.length; i < len; ++i) { + var item = curElement.childNodes.item(i); + if (item.nodeType !== 1 || item.tagName.toLowerCase() !== "param") continue; + if (item.getAttribute("name") === name) return item.getAttribute("value") + } + if (curSketch.params.hasOwnProperty(name)) return curSketch.params[name]; + return null + }; + + function wireDimensionalFunctions(mode) { + if (mode === "3D") drawing = new Drawing3D; + else if (mode === "2D") drawing = new Drawing2D; + else drawing = new DrawingPre; + for (var i in DrawingPre.prototype) if (DrawingPre.prototype.hasOwnProperty(i) && i.indexOf("$") < 0) p[i] = drawing[i]; + drawing.$init() + } + function createDrawingPreFunction(name) { + return function() { + wireDimensionalFunctions("2D"); + return drawing[name].apply(this, arguments) + } + } + DrawingPre.prototype.translate = createDrawingPreFunction("translate"); + DrawingPre.prototype.transform = createDrawingPreFunction("transform"); + DrawingPre.prototype.scale = createDrawingPreFunction("scale"); + DrawingPre.prototype.pushMatrix = createDrawingPreFunction("pushMatrix"); + DrawingPre.prototype.popMatrix = createDrawingPreFunction("popMatrix"); + DrawingPre.prototype.resetMatrix = createDrawingPreFunction("resetMatrix"); + DrawingPre.prototype.applyMatrix = createDrawingPreFunction("applyMatrix"); + DrawingPre.prototype.rotate = createDrawingPreFunction("rotate"); + DrawingPre.prototype.rotateZ = createDrawingPreFunction("rotateZ"); + DrawingPre.prototype.shearX = createDrawingPreFunction("shearX"); + DrawingPre.prototype.shearY = createDrawingPreFunction("shearY"); + DrawingPre.prototype.redraw = createDrawingPreFunction("redraw"); + DrawingPre.prototype.toImageData = createDrawingPreFunction("toImageData"); + DrawingPre.prototype.ambientLight = createDrawingPreFunction("ambientLight"); + DrawingPre.prototype.directionalLight = createDrawingPreFunction("directionalLight"); + DrawingPre.prototype.lightFalloff = createDrawingPreFunction("lightFalloff"); + DrawingPre.prototype.lightSpecular = createDrawingPreFunction("lightSpecular"); + DrawingPre.prototype.pointLight = createDrawingPreFunction("pointLight"); + DrawingPre.prototype.noLights = createDrawingPreFunction("noLights"); + DrawingPre.prototype.spotLight = createDrawingPreFunction("spotLight"); + DrawingPre.prototype.beginCamera = createDrawingPreFunction("beginCamera"); + DrawingPre.prototype.endCamera = createDrawingPreFunction("endCamera"); + DrawingPre.prototype.frustum = createDrawingPreFunction("frustum"); + DrawingPre.prototype.box = createDrawingPreFunction("box"); + DrawingPre.prototype.sphere = createDrawingPreFunction("sphere"); + DrawingPre.prototype.ambient = createDrawingPreFunction("ambient"); + DrawingPre.prototype.emissive = createDrawingPreFunction("emissive"); + DrawingPre.prototype.shininess = createDrawingPreFunction("shininess"); + DrawingPre.prototype.specular = createDrawingPreFunction("specular"); + DrawingPre.prototype.fill = createDrawingPreFunction("fill"); + DrawingPre.prototype.stroke = createDrawingPreFunction("stroke"); + DrawingPre.prototype.strokeWeight = createDrawingPreFunction("strokeWeight"); + DrawingPre.prototype.smooth = createDrawingPreFunction("smooth"); + DrawingPre.prototype.noSmooth = createDrawingPreFunction("noSmooth"); + DrawingPre.prototype.point = createDrawingPreFunction("point"); + DrawingPre.prototype.vertex = createDrawingPreFunction("vertex"); + DrawingPre.prototype.endShape = createDrawingPreFunction("endShape"); + DrawingPre.prototype.bezierVertex = createDrawingPreFunction("bezierVertex"); + DrawingPre.prototype.curveVertex = createDrawingPreFunction("curveVertex"); + DrawingPre.prototype.curve = createDrawingPreFunction("curve"); + DrawingPre.prototype.line = createDrawingPreFunction("line"); + DrawingPre.prototype.bezier = createDrawingPreFunction("bezier"); + DrawingPre.prototype.rect = createDrawingPreFunction("rect"); + DrawingPre.prototype.ellipse = createDrawingPreFunction("ellipse"); + DrawingPre.prototype.background = createDrawingPreFunction("background"); + DrawingPre.prototype.image = createDrawingPreFunction("image"); + DrawingPre.prototype.textWidth = createDrawingPreFunction("textWidth"); + DrawingPre.prototype.text$line = createDrawingPreFunction("text$line"); + DrawingPre.prototype.$ensureContext = createDrawingPreFunction("$ensureContext"); + DrawingPre.prototype.$newPMatrix = createDrawingPreFunction("$newPMatrix"); + DrawingPre.prototype.size = function(aWidth, aHeight, aMode) { + wireDimensionalFunctions(aMode === 2 ? "3D" : "2D"); + p.size(aWidth, aHeight, aMode) + }; + DrawingPre.prototype.$init = nop; + Drawing2D.prototype.$init = function() { + p.size(p.width, p.height); + curContext.lineCap = "round"; + p.noSmooth(); + p.disableContextMenu() + }; + Drawing3D.prototype.$init = function() { + p.use3DContext = true; + p.disableContextMenu() + }; + DrawingShared.prototype.$ensureContext = function() { + return curContext + }; + + function calculateOffset(curElement, event) { + var element = curElement, + offsetX = 0, + offsetY = 0; + p.pmouseX = p.mouseX; + p.pmouseY = p.mouseY; + if (element.offsetParent) { + do { + offsetX += element.offsetLeft; + offsetY += element.offsetTop + } while ( !! (element = element.offsetParent)) + } + element = curElement; + do { + offsetX -= element.scrollLeft || 0; + offsetY -= element.scrollTop || 0 + } while ( !! (element = element.parentNode)); + offsetX += stylePaddingLeft; + offsetY += stylePaddingTop; + offsetX += styleBorderLeft; + offsetY += styleBorderTop; + offsetX += window.pageXOffset; + offsetY += window.pageYOffset; + return { + "X": offsetX, + "Y": offsetY + } + } + function updateMousePosition(curElement, event) { + var offset = calculateOffset(curElement, event); + p.mouseX = event.pageX - offset.X; + p.mouseY = event.pageY - offset.Y + } + function addTouchEventOffset(t) { + var offset = calculateOffset(t.changedTouches[0].target, t.changedTouches[0]), + i; + for (i = 0; i < t.touches.length; i++) { + var touch = t.touches[i]; + touch.offsetX = touch.pageX - offset.X; + touch.offsetY = touch.pageY - offset.Y + } + for (i = 0; i < t.targetTouches.length; i++) { + var targetTouch = t.targetTouches[i]; + targetTouch.offsetX = targetTouch.pageX - offset.X; + targetTouch.offsetY = targetTouch.pageY - offset.Y + } + for (i = 0; i < t.changedTouches.length; i++) { + var changedTouch = t.changedTouches[i]; + changedTouch.offsetX = changedTouch.pageX - offset.X; + changedTouch.offsetY = changedTouch.pageY - offset.Y + } + return t + } + attachEventHandler(curElement, "touchstart", function(t) { + curElement.setAttribute("style", "-webkit-user-select: none"); + curElement.setAttribute("onclick", "void(0)"); + curElement.setAttribute("style", "-webkit-tap-highlight-color:rgba(0,0,0,0)"); + for (var i = 0, ehl = eventHandlers.length; i < ehl; i++) { + var type = eventHandlers[i].type; + if (type === "mouseout" || type === "mousemove" || type === "mousedown" || type === "mouseup" || type === "DOMMouseScroll" || type === "mousewheel" || type === "touchstart") detachEventHandler(eventHandlers[i]) + } + if (p.touchStart !== undef || p.touchMove !== undef || p.touchEnd !== undef || p.touchCancel !== undef) { + attachEventHandler(curElement, "touchstart", function(t) { + if (p.touchStart !== undef) { + t = addTouchEventOffset(t); + p.touchStart(t) + } + }); + attachEventHandler(curElement, "touchmove", function(t) { + if (p.touchMove !== undef) { + t.preventDefault(); + t = addTouchEventOffset(t); + p.touchMove(t) + } + }); + attachEventHandler(curElement, "touchend", function(t) { + if (p.touchEnd !== undef) { + t = addTouchEventOffset(t); + p.touchEnd(t) + } + }); + attachEventHandler(curElement, "touchcancel", function(t) { + if (p.touchCancel !== undef) { + t = addTouchEventOffset(t); + p.touchCancel(t) + } + }) + } else { + attachEventHandler(curElement, "touchstart", function(e) { + updateMousePosition(curElement, e.touches[0]); + p.__mousePressed = true; + p.mouseDragging = false; + p.mouseButton = 37; + if (typeof p.mousePressed === "function") p.mousePressed() + }); + attachEventHandler(curElement, "touchmove", function(e) { + e.preventDefault(); + updateMousePosition(curElement, e.touches[0]); + if (typeof p.mouseMoved === "function" && !p.__mousePressed) p.mouseMoved(); + if (typeof p.mouseDragged === "function" && p.__mousePressed) { + p.mouseDragged(); + p.mouseDragging = true + } + }); + attachEventHandler(curElement, "touchend", function(e) { + p.__mousePressed = false; + if (typeof p.mouseClicked === "function" && !p.mouseDragging) p.mouseClicked(); + if (typeof p.mouseReleased === "function") p.mouseReleased() + }) + } + curElement.dispatchEvent(t) + }); + (function() { + var enabled = true, + contextMenu = function(e) { + e.preventDefault(); + e.stopPropagation() + }; + p.disableContextMenu = function() { + if (!enabled) return; + attachEventHandler(curElement, "contextmenu", contextMenu); + enabled = false + }; + p.enableContextMenu = function() { + if (enabled) return; + detachEventHandler({ + elem: curElement, + type: "contextmenu", + fn: contextMenu + }); + enabled = true + } + })(); + attachEventHandler(curElement, "mousemove", function(e) { + updateMousePosition(curElement, e); + if (typeof p.mouseMoved === "function" && !p.__mousePressed) p.mouseMoved(); + if (typeof p.mouseDragged === "function" && p.__mousePressed) { + p.mouseDragged(); + p.mouseDragging = true + } + }); + attachEventHandler(curElement, "mouseout", function(e) { + if (typeof p.mouseOut === "function") p.mouseOut() + }); + attachEventHandler(curElement, "mouseover", function(e) { + updateMousePosition(curElement, e); + if (typeof p.mouseOver === "function") p.mouseOver() + }); + curElement.onmousedown = function() { + curElement.focus(); + return false + }; + attachEventHandler(curElement, "mousedown", function(e) { + p.__mousePressed = true; + p.mouseDragging = false; + switch (e.which) { + case 1: + p.mouseButton = 37; + break; + case 2: + p.mouseButton = 3; + break; + case 3: + p.mouseButton = 39; + break + } + if (typeof p.mousePressed === "function") p.mousePressed() + }); + attachEventHandler(curElement, "mouseup", function(e) { + p.__mousePressed = false; + if (typeof p.mouseClicked === "function" && !p.mouseDragging) p.mouseClicked(); + if (typeof p.mouseReleased === "function") p.mouseReleased() + }); + var mouseWheelHandler = function(e) { + var delta = 0; + if (e.wheelDelta) { + delta = e.wheelDelta / 120; + if (window.opera) delta = -delta + } else if (e.detail) delta = -e.detail / 3; + p.mouseScroll = delta; + if (delta && typeof p.mouseScrolled === "function") p.mouseScrolled() + }; + attachEventHandler(document, "DOMMouseScroll", mouseWheelHandler); + attachEventHandler(document, "mousewheel", mouseWheelHandler); + if (!curElement.getAttribute("tabindex")) curElement.setAttribute("tabindex", 0); + + function getKeyCode(e) { + var code = e.which || e.keyCode; + switch (code) { + case 13: + return 10; + case 91: + case 93: + case 224: + return 157; + case 57392: + return 17; + case 46: + return 127; + case 45: + return 155 + } + return code + } + function getKeyChar(e) { + var c = e.which || e.keyCode; + var anyShiftPressed = e.shiftKey || e.ctrlKey || e.altKey || e.metaKey; + switch (c) { + case 13: + c = anyShiftPressed ? 13 : 10; + break; + case 8: + c = anyShiftPressed ? 127 : 8; + break + } + return new Char(c) + } + function suppressKeyEvent(e) { + if (typeof e.preventDefault === "function") e.preventDefault(); + else if (typeof e.stopPropagation === "function") e.stopPropagation(); + return false + } + function updateKeyPressed() { + var ch; + for (ch in pressedKeysMap) if (pressedKeysMap.hasOwnProperty(ch)) { + p.__keyPressed = true; + return + } + p.__keyPressed = false + } + function resetKeyPressed() { + p.__keyPressed = false; + pressedKeysMap = []; + lastPressedKeyCode = null + } + function simulateKeyTyped(code, c) { + pressedKeysMap[code] = c; + lastPressedKeyCode = null; + p.key = c; + p.keyCode = code; + p.keyPressed(); + p.keyCode = 0; + p.keyTyped(); + updateKeyPressed() + } + function handleKeydown(e) { + var code = getKeyCode(e); + if (code === 127) { + simulateKeyTyped(code, new Char(127)); + return + } + if (codedKeys.indexOf(code) < 0) { + lastPressedKeyCode = code; + return + } + var c = new Char(65535); + p.key = c; + p.keyCode = code; + pressedKeysMap[code] = c; + p.keyPressed(); + lastPressedKeyCode = null; + updateKeyPressed(); + return suppressKeyEvent(e) + } + function handleKeypress(e) { + if (lastPressedKeyCode === null) return; + var code = lastPressedKeyCode, + c = getKeyChar(e); + simulateKeyTyped(code, c); + return suppressKeyEvent(e) + } + function handleKeyup(e) { + var code = getKeyCode(e), + c = pressedKeysMap[code]; + if (c === undef) return; + p.key = c; + p.keyCode = code; + p.keyReleased(); + delete pressedKeysMap[code]; + updateKeyPressed() + } + if (!pgraphicsMode) { + if (aCode instanceof Processing.Sketch) curSketch = aCode; + else if (typeof aCode === "function") curSketch = new Processing.Sketch(aCode); + else if (!aCode) curSketch = new Processing.Sketch(function() {}); + else curSketch = Processing.compile(aCode); + p.externals.sketch = curSketch; + wireDimensionalFunctions(); + curElement.onfocus = function() { + p.focused = true + }; + curElement.onblur = function() { + p.focused = false; + if (!curSketch.options.globalKeyEvents) resetKeyPressed() + }; + if (curSketch.options.pauseOnBlur) { + attachEventHandler(window, "focus", function() { + if (doLoop) p.loop() + }); + attachEventHandler(window, "blur", function() { + if (doLoop && loopStarted) { + p.noLoop(); + doLoop = true + } + resetKeyPressed() + }) + } + var keyTrigger = curSketch.options.globalKeyEvents ? window : curElement; + attachEventHandler(keyTrigger, "keydown", handleKeydown); + attachEventHandler(keyTrigger, "keypress", handleKeypress); + attachEventHandler(keyTrigger, "keyup", handleKeyup); + for (var i in Processing.lib) if (Processing.lib.hasOwnProperty(i)) if (Processing.lib[i].hasOwnProperty("attach")) Processing.lib[i].attach(p); + else if (Processing.lib[i] instanceof Function) Processing.lib[i].call(this); + var retryInterval = 100; + var executeSketch = function(processing) { + if (! (curSketch.imageCache.pending || PFont.preloading.pending(retryInterval))) { + if (window.opera) { + var link, element, operaCache = curSketch.imageCache.operaCache; + for (link in operaCache) if (operaCache.hasOwnProperty(link)) { + element = operaCache[link]; + if (element !== null) document.body.removeChild(element); + delete operaCache[link] + } + } + curSketch.attach(processing, defaultScope); + curSketch.onLoad(processing); + if (processing.setup) { + processing.setup(); + processing.resetMatrix(); + curSketch.onSetup() + } + resetContext(); + if (processing.draw) if (!doLoop) processing.redraw(); + else processing.loop() + } else window.setTimeout(function() { + executeSketch(processing) + }, + retryInterval) + }; + addInstance(this); + executeSketch(p) + } else { + curSketch = new Processing.Sketch; + wireDimensionalFunctions(); + p.size = function(w, h, render) { + if (render && render === 2) wireDimensionalFunctions("3D"); + else wireDimensionalFunctions("2D"); + p.size(w, h, render) + } + } + }; + Processing.debug = debug; + Processing.prototype = defaultScope; + + function getGlobalMembers() { + var names = ["abs", "acos", "alpha", "ambient", "ambientLight", "append", + "applyMatrix", "arc", "arrayCopy", "asin", "atan", "atan2", "background", "beginCamera", "beginDraw", "beginShape", "bezier", "bezierDetail", "bezierPoint", "bezierTangent", "bezierVertex", "binary", "blend", "blendColor", "blit_resize", "blue", "box", "breakShape", "brightness", "camera", "ceil", "Character", "color", "colorMode", "concat", "constrain", "copy", "cos", "createFont", "createGraphics", "createImage", "cursor", "curve", "curveDetail", "curvePoint", "curveTangent", "curveTightness", "curveVertex", "day", "degrees", "directionalLight", + "disableContextMenu", "dist", "draw", "ellipse", "ellipseMode", "emissive", "enableContextMenu", "endCamera", "endDraw", "endShape", "exit", "exp", "expand", "externals", "fill", "filter", "floor", "focused", "frameCount", "frameRate", "frustum", "get", "glyphLook", "glyphTable", "green", "height", "hex", "hint", "hour", "hue", "image", "imageMode", "intersect", "join", "key", "keyCode", "keyPressed", "keyReleased", "keyTyped", "lerp", "lerpColor", "lightFalloff", "lights", "lightSpecular", "line", "link", "loadBytes", "loadFont", "loadGlyphs", + "loadImage", "loadPixels", "loadShape", "loadXML", "loadStrings", "log", "loop", "mag", "map", "match", "matchAll", "max", "millis", "min", "minute", "mix", "modelX", "modelY", "modelZ", "modes", "month", "mouseButton", "mouseClicked", "mouseDragged", "mouseMoved", "mouseOut", "mouseOver", "mousePressed", "mouseReleased", "mouseScroll", "mouseScrolled", "mouseX", "mouseY", "name", "nf", "nfc", "nfp", "nfs", "noCursor", "noFill", "noise", "noiseDetail", "noiseSeed", "noLights", "noLoop", "norm", "normal", "noSmooth", "noStroke", "noTint", "ortho", + "param", "parseBoolean", "parseByte", "parseChar", "parseFloat", "parseInt", "peg", "perspective", "PImage", "pixels", "PMatrix2D", "PMatrix3D", "PMatrixStack", "pmouseX", "pmouseY", "point", "pointLight", "popMatrix", "popStyle", "pow", "print", "printCamera", "println", "printMatrix", "printProjection", "PShape", "PShapeSVG", "pushMatrix", "pushStyle", "quad", "radians", "random", "Random", "randomSeed", "rect", "rectMode", "red", "redraw", "requestImage", "resetMatrix", "reverse", "rotate", "rotateX", "rotateY", "rotateZ", "round", "saturation", + "save", "saveFrame", "saveStrings", "scale", "screenX", "screenY", "screenZ", "second", "set", "setup", "shape", "shapeMode", "shared", "shearX", "shearY", "shininess", "shorten", "sin", "size", "smooth", "sort", "specular", "sphere", "sphereDetail", "splice", "split", "splitTokens", "spotLight", "sq", "sqrt", "status", "str", "stroke", "strokeCap", "strokeJoin", "strokeWeight", "subset", "tan", "text", "textAlign", "textAscent", "textDescent", "textFont", "textLeading", "textMode", "textSize", "texture", "textureMode", "textWidth", "tint", "toImageData", + "touchCancel", "touchEnd", "touchMove", "touchStart", "translate", "transform", "triangle", "trim", "unbinary", "unhex", "updatePixels", "use3DContext", "vertex", "width", "XMLElement", "XML", "year", "__contains", "__equals", "__equalsIgnoreCase", "__frameRate", "__hashCode", "__int_cast", "__instanceof", "__keyPressed", "__mousePressed", "__printStackTrace", "__replace", "__replaceAll", "__replaceFirst", "__toCharArray", "__split", "__codePointAt", "__startsWith", "__endsWith", "__matches"]; + var members = {}; + var i, l; + for (i = 0, l = names.length; i < l; ++i) members[names[i]] = null; + for (var lib in Processing.lib) if (Processing.lib.hasOwnProperty(lib)) if (Processing.lib[lib].exports) { + var exportedNames = Processing.lib[lib].exports; + for (i = 0, l = exportedNames.length; i < l; ++i) members[exportedNames[i]] = null + } + return members + } + function parseProcessing(code) { + var globalMembers = getGlobalMembers(); + + function splitToAtoms(code) { + var atoms = []; + var items = code.split(/([\{\[\(\)\]\}])/); + var result = items[0]; + var stack = []; + for (var i = 1; i < items.length; i += 2) { + var item = items[i]; + if (item === "[" || item === "{" || item === "(") { + stack.push(result); + result = item + } else if (item === "]" || item === "}" || item === ")") { + var kind = item === "}" ? "A" : item === ")" ? "B" : "C"; + var index = atoms.length; + atoms.push(result + item); + result = stack.pop() + '"' + kind + (index + 1) + '"' + } + result += items[i + 1] + } + atoms.unshift(result); + return atoms + } + function injectStrings(code, strings) { + return code.replace(/'(\d+)'/g, function(all, index) { + var val = strings[index]; + if (val.charAt(0) === "/") return val; + return /^'((?:[^'\\\n])|(?:\\.[0-9A-Fa-f]*))'$/.test(val) ? "(new $p.Character(" + val + "))" : val + }) + } + function trimSpaces(string) { + var m1 = /^\s*/.exec(string), + result; + if (m1[0].length === string.length) result = { + left: m1[0], + middle: "", + right: "" + }; + else { + var m2 = /\s*$/.exec(string); + result = { + left: m1[0], + middle: string.substring(m1[0].length, m2.index), + right: m2[0] + } + } + result.untrim = function(t) { + return this.left + t + this.right + }; + return result + } + function trim(string) { + return string.replace(/^\s+/, "").replace(/\s+$/, "") + } + function appendToLookupTable(table, array) { + for (var i = 0, l = array.length; i < l; ++i) table[array[i]] = null; + return table + } + function isLookupTableEmpty(table) { + for (var i in table) if (table.hasOwnProperty(i)) return false; + return true + } + function getAtomIndex(templ) { + return templ.substring(2, templ.length - 1) + } + var codeWoExtraCr = code.replace(/\r\n?|\n\r/g, "\n"); + var strings = []; + var codeWoStrings = codeWoExtraCr.replace(/("(?:[^"\\\n]|\\.)*")|('(?:[^'\\\n]|\\.)*')|(([\[\(=|&!\^:?]\s*)(\/(?![*\/])(?:[^\/\\\n]|\\.)*\/[gim]*)\b)|(\/\/[^\n]*\n)|(\/\*(?:(?!\*\/)(?:.|\n))*\*\/)/g, function(all, quoted, aposed, regexCtx, prefix, regex, singleComment, comment) { + var index; + if (quoted || aposed) { + index = strings.length; + strings.push(all); + return "'" + index + "'" + } + if (regexCtx) { + index = strings.length; + strings.push(regex); + return prefix + "'" + index + "'" + } + return comment !== "" ? " " : "\n" + }); + codeWoStrings = codeWoStrings.replace(/__x([0-9A-F]{4})/g, function(all, hexCode) { + return "__x005F_x" + hexCode + }); + codeWoStrings = codeWoStrings.replace(/\$/g, "__x0024"); + var genericsWereRemoved; + var codeWoGenerics = codeWoStrings; + var replaceFunc = function(all, before, types, after) { + if ( !! before || !!after) return all; + genericsWereRemoved = true; + return "" + }; + do { + genericsWereRemoved = false; + codeWoGenerics = codeWoGenerics.replace(/([<]?)<\s*((?:\?|[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\[\])*(?:\s+(?:extends|super)\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)?(?:\s*,\s*(?:\?|[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\[\])*(?:\s+(?:extends|super)\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)?)*)\s*>([=]?)/g, replaceFunc) + } while (genericsWereRemoved); + var atoms = splitToAtoms(codeWoGenerics); + var replaceContext; + var declaredClasses = {}, + currentClassId, classIdSeed = 0; + + function addAtom(text, type) { + var lastIndex = atoms.length; + atoms.push(text); + return '"' + type + lastIndex + '"' + } + function generateClassId() { + return "class" + ++classIdSeed + } + function appendClass(class_, classId, scopeId) { + class_.classId = classId; + class_.scopeId = scopeId; + declaredClasses[classId] = class_ + } + var transformClassBody, transformInterfaceBody, transformStatementsBlock, transformStatements, transformMain, transformExpression; + var classesRegex = /\b((?:(?:public|private|final|protected|static|abstract)\s+)*)(class|interface)\s+([A-Za-z_$][\w$]*\b)(\s+extends\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*\b)*)?(\s+implements\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*\b)*)?\s*("A\d+")/g; + var methodsRegex = /\b((?:(?:public|private|final|protected|static|abstract|synchronized)\s+)*)((?!(?:else|new|return|throw|function|public|private|protected)\b)[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*"C\d+")*)\s*([A-Za-z_$][\w$]*\b)\s*("B\d+")(\s*throws\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)*)?\s*("A\d+"|;)/g; + var fieldTest = /^((?:(?:public|private|final|protected|static)\s+)*)((?!(?:else|new|return|throw)\b)[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*"C\d+")*)\s*([A-Za-z_$][\w$]*\b)\s*(?:"C\d+"\s*)*([=,]|$)/; + var cstrsRegex = /\b((?:(?:public|private|final|protected|static|abstract)\s+)*)((?!(?:new|return|throw)\b)[A-Za-z_$][\w$]*\b)\s*("B\d+")(\s*throws\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)*)?\s*("A\d+")/g; + var attrAndTypeRegex = /^((?:(?:public|private|final|protected|static)\s+)*)((?!(?:new|return|throw)\b)[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*"C\d+")*)\s*/; + var functionsRegex = /\bfunction(?:\s+([A-Za-z_$][\w$]*))?\s*("B\d+")\s*("A\d+")/g; + + function extractClassesAndMethods(code) { + var s = code; + s = s.replace(classesRegex, function(all) { + return addAtom(all, "E") + }); + s = s.replace(methodsRegex, function(all) { + return addAtom(all, "D") + }); + s = s.replace(functionsRegex, function(all) { + return addAtom(all, "H") + }); + return s + } + function extractConstructors(code, className) { + var result = code.replace(cstrsRegex, function(all, attr, name, params, throws_, body) { + if (name !== className) return all; + return addAtom(all, "G") + }); + return result + } + function AstParam(name) { + this.name = name + } + AstParam.prototype.toString = function() { + return this.name + }; + + function AstParams(params, methodArgsParam) { + this.params = params; + this.methodArgsParam = methodArgsParam + } + AstParams.prototype.getNames = function() { + var names = []; + for (var i = 0, l = this.params.length; i < l; ++i) names.push(this.params[i].name); + return names + }; + AstParams.prototype.prependMethodArgs = function(body) { + if (!this.methodArgsParam) return body; + return "{\nvar " + this.methodArgsParam.name + " = Array.prototype.slice.call(arguments, " + this.params.length + ");\n" + body.substring(1) + }; + AstParams.prototype.toString = function() { + if (this.params.length === 0) return "()"; + var result = "("; + for (var i = 0, l = this.params.length; i < l; ++i) result += this.params[i] + ", "; + return result.substring(0, result.length - 2) + ")" + }; + + function transformParams(params) { + var paramsWoPars = trim(params.substring(1, params.length - 1)); + var result = [], + methodArgsParam = null; + if (paramsWoPars !== "") { + var paramList = paramsWoPars.split(","); + for (var i = 0; i < paramList.length; ++i) { + var param = /\b([A-Za-z_$][\w$]*\b)(\s*"[ABC][\d]*")*\s*$/.exec(paramList[i]); + if (i === paramList.length - 1 && paramList[i].indexOf("...") >= 0) { + methodArgsParam = new AstParam(param[1]); + break + } + result.push(new AstParam(param[1])) + } + } + return new AstParams(result, methodArgsParam) + } + function preExpressionTransform(expr) { + var s = expr; + s = s.replace(/\bnew\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\s*"C\d+")+\s*("A\d+")/g, function(all, type, init) { + return init + }); + s = s.replace(/\bnew\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\s*"B\d+")\s*("A\d+")/g, function(all, type, init) { + return addAtom(all, "F") + }); + s = s.replace(functionsRegex, function(all) { + return addAtom(all, "H") + }); + s = s.replace(/\bnew\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)\s*("C\d+"(?:\s*"C\d+")*)/g, function(all, type, index) { + var args = index.replace(/"C(\d+)"/g, function(all, j) { + return atoms[j] + }).replace(/\[\s*\]/g, "[null]").replace(/\s*\]\s*\[\s*/g, ", "); + var arrayInitializer = "{" + args.substring(1, args.length - 1) + "}"; + var createArrayArgs = "('" + type + "', " + addAtom(arrayInitializer, "A") + ")"; + return "$p.createJavaArray" + addAtom(createArrayArgs, "B") + }); + s = s.replace(/(\.\s*length)\s*"B\d+"/g, "$1"); + s = s.replace(/#([0-9A-Fa-f]{6})\b/g, function(all, digits) { + return "0xFF" + digits + }); + s = s.replace(/"B(\d+)"(\s*(?:[\w$']|"B))/g, function(all, index, next) { + var atom = atoms[index]; + if (!/^\(\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*\s*(?:"C\d+"\s*)*\)$/.test(atom)) return all; + if (/^\(\s*int\s*\)$/.test(atom)) return "(int)" + next; + var indexParts = atom.split(/"C(\d+)"/g); + if (indexParts.length > 1) if (!/^\[\s*\]$/.test(atoms[indexParts[1]])) return all; + return "" + next + }); + s = s.replace(/\(int\)([^,\]\)\}\?\:\*\+\-\/\^\|\%\&\~<\>\=]+)/g, function(all, arg) { + var trimmed = trimSpaces(arg); + return trimmed.untrim("__int_cast(" + trimmed.middle + ")") + }); + s = s.replace(/\bsuper(\s*"B\d+")/g, "$$superCstr$1").replace(/\bsuper(\s*\.)/g, "$$super$1"); + s = s.replace(/\b0+((\d*)(?:\.[\d*])?(?:[eE][\-\+]?\d+)?[fF]?)\b/, function(all, numberWo0, intPart) { + if (numberWo0 === intPart) return all; + return intPart === "" ? "0" + numberWo0 : numberWo0 + }); + s = s.replace(/\b(\.?\d+\.?)[fF]\b/g, "$1"); + s = s.replace(/([^\s])%([^=\s])/g, "$1 % $2"); + s = s.replace(/\b(frameRate|keyPressed|mousePressed)\b(?!\s*"B)/g, "__$1"); + s = s.replace(/\b(boolean|byte|char|float|int)\s*"B/g, function(all, name) { + return "parse" + name.substring(0, 1).toUpperCase() + name.substring(1) + '"B' + }); + s = s.replace(/\bpixels\b\s*(("C(\d+)")|\.length)?(\s*=(?!=)([^,\]\)\}]+))?/g, function(all, indexOrLength, index, atomIndex, equalsPart, rightSide) { + if (index) { + var atom = atoms[atomIndex]; + if (equalsPart) return "pixels.setPixel" + addAtom("(" + atom.substring(1, atom.length - 1) + "," + rightSide + ")", "B"); + return "pixels.getPixel" + addAtom("(" + atom.substring(1, atom.length - 1) + ")", "B") + } + if (indexOrLength) return "pixels.getLength" + addAtom("()", "B"); + if (equalsPart) return "pixels.set" + addAtom("(" + rightSide + ")", "B"); + return "pixels.toArray" + addAtom("()", "B") + }); + var repeatJavaReplacement; + + function replacePrototypeMethods(all, subject, method, atomIndex) { + var atom = atoms[atomIndex]; + repeatJavaReplacement = true; + var trimmed = trimSpaces(atom.substring(1, atom.length - 1)); + return "__" + method + (trimmed.middle === "" ? addAtom("(" + subject.replace(/\.\s*$/, "") + ")", "B") : addAtom("(" + subject.replace(/\.\s*$/, "") + "," + trimmed.middle + ")", "B")) + } + do { + repeatJavaReplacement = false; + s = s.replace(/((?:'\d+'|\b[A-Za-z_$][\w$]*\s*(?:"[BC]\d+")*)\s*\.\s*(?:[A-Za-z_$][\w$]*\s*(?:"[BC]\d+"\s*)*\.\s*)*)(replace|replaceAll|replaceFirst|contains|equals|equalsIgnoreCase|hashCode|toCharArray|printStackTrace|split|startsWith|endsWith|codePointAt|matches)\s*"B(\d+)"/g, replacePrototypeMethods) + } while (repeatJavaReplacement); + + function replaceInstanceof(all, subject, type) { + repeatJavaReplacement = true; + return "__instanceof" + addAtom("(" + subject + ", " + type + ")", "B") + } + do { + repeatJavaReplacement = false; + s = s.replace(/((?:'\d+'|\b[A-Za-z_$][\w$]*\s*(?:"[BC]\d+")*)\s*(?:\.\s*[A-Za-z_$][\w$]*\s*(?:"[BC]\d+"\s*)*)*)instanceof\s+([A-Za-z_$][\w$]*\s*(?:\.\s*[A-Za-z_$][\w$]*)*)/g, replaceInstanceof) + } while (repeatJavaReplacement); + s = s.replace(/\bthis(\s*"B\d+")/g, "$$constr$1"); + return s + } + function AstInlineClass(baseInterfaceName, body) { + this.baseInterfaceName = baseInterfaceName; + this.body = body; + body.owner = this + } + AstInlineClass.prototype.toString = function() { + return "new (" + this.body + ")" + }; + + function transformInlineClass(class_) { + var m = (new RegExp(/\bnew\s*([A-Za-z_$][\w$]*\s*(?:\.\s*[A-Za-z_$][\w$]*)*)\s*"B\d+"\s*"A(\d+)"/)).exec(class_); + var oldClassId = currentClassId, + newClassId = generateClassId(); + currentClassId = newClassId; + var uniqueClassName = m[1] + "$" + newClassId; + var inlineClass = new AstInlineClass(uniqueClassName, transformClassBody(atoms[m[2]], uniqueClassName, "", "implements " + m[1])); + appendClass(inlineClass, newClassId, oldClassId); + currentClassId = oldClassId; + return inlineClass + } + + function AstFunction(name, params, body) { + this.name = name; + this.params = params; + this.body = body + } + AstFunction.prototype.toString = function() { + var oldContext = replaceContext; + var names = appendToLookupTable({ + "this": null + }, + this.params.getNames()); + replaceContext = function(subject) { + return names.hasOwnProperty(subject.name) ? subject.name : oldContext(subject) + }; + var result = "function"; + if (this.name) result += " " + this.name; + var body = this.params.prependMethodArgs(this.body.toString()); + result += this.params + " " + body; + replaceContext = oldContext; + return result + }; + + function transformFunction(class_) { + var m = (new RegExp(/\b([A-Za-z_$][\w$]*)\s*"B(\d+)"\s*"A(\d+)"/)).exec(class_); + return new AstFunction(m[1] !== "function" ? m[1] : null, transformParams(atoms[m[2]]), transformStatementsBlock(atoms[m[3]])) + } + function AstInlineObject(members) { + this.members = members + } + AstInlineObject.prototype.toString = function() { + var oldContext = replaceContext; + replaceContext = function(subject) { + return subject.name === "this" ? "this" : oldContext(subject) + }; + var result = ""; + for (var i = 0, l = this.members.length; i < l; ++i) { + if (this.members[i].label) result += this.members[i].label + ": "; + result += this.members[i].value.toString() + ", " + } + replaceContext = oldContext; + return result.substring(0, result.length - 2) + }; + + function transformInlineObject(obj) { + var members = obj.split(","); + for (var i = 0; i < members.length; ++i) { + var label = members[i].indexOf(":"); + if (label < 0) members[i] = { + value: transformExpression(members[i]) + }; + else members[i] = { + label: trim(members[i].substring(0, label)), + value: transformExpression(trim(members[i].substring(label + 1))) + } + } + return new AstInlineObject(members) + } + + function expandExpression(expr) { + if (expr.charAt(0) === "(" || expr.charAt(0) === "[") return expr.charAt(0) + expandExpression(expr.substring(1, expr.length - 1)) + expr.charAt(expr.length - 1); + if (expr.charAt(0) === "{") { + if (/^\{\s*(?:[A-Za-z_$][\w$]*|'\d+')\s*:/.test(expr)) return "{" + addAtom(expr.substring(1, expr.length - 1), "I") + "}"; + return "[" + expandExpression(expr.substring(1, expr.length - 1)) + "]" + } + var trimmed = trimSpaces(expr); + var result = preExpressionTransform(trimmed.middle); + result = result.replace(/"[ABC](\d+)"/g, function(all, index) { + return expandExpression(atoms[index]) + }); + return trimmed.untrim(result) + } + function replaceContextInVars(expr) { + return expr.replace(/(\.\s*)?((?:\b[A-Za-z_]|\$)[\w$]*)(\s*\.\s*([A-Za-z_$][\w$]*)(\s*\()?)?/g, function(all, memberAccessSign, identifier, suffix, subMember, callSign) { + if (memberAccessSign) return all; + var subject = { + name: identifier, + member: subMember, + callSign: !!callSign + }; + return replaceContext(subject) + (suffix === undef ? "" : suffix) + }) + } + function AstExpression(expr, transforms) { + this.expr = expr; + this.transforms = transforms + } + AstExpression.prototype.toString = function() { + var transforms = this.transforms; + var expr = replaceContextInVars(this.expr); + return expr.replace(/"!(\d+)"/g, function(all, index) { + return transforms[index].toString() + }) + }; + transformExpression = function(expr) { + var transforms = []; + var s = expandExpression(expr); + s = s.replace(/"H(\d+)"/g, function(all, index) { + transforms.push(transformFunction(atoms[index])); + return '"!' + (transforms.length - 1) + '"' + }); + s = s.replace(/"F(\d+)"/g, function(all, index) { + transforms.push(transformInlineClass(atoms[index])); + return '"!' + (transforms.length - 1) + '"' + }); + s = s.replace(/"I(\d+)"/g, function(all, index) { + transforms.push(transformInlineObject(atoms[index])); + return '"!' + (transforms.length - 1) + '"' + }); + return new AstExpression(s, transforms) + }; + + function AstVarDefinition(name, value, isDefault) { + this.name = name; + this.value = value; + this.isDefault = isDefault + } + AstVarDefinition.prototype.toString = function() { + return this.name + " = " + this.value + }; + + function transformVarDefinition(def, defaultTypeValue) { + var eqIndex = def.indexOf("="); + var name, value, isDefault; + if (eqIndex < 0) { + name = def; + value = defaultTypeValue; + isDefault = true + } else { + name = def.substring(0, eqIndex); + value = transformExpression(def.substring(eqIndex + 1)); + isDefault = false + } + return new AstVarDefinition(trim(name.replace(/(\s*"C\d+")+/g, "")), value, isDefault) + } + function getDefaultValueForType(type) { + if (type === "int" || type === "float") return "0"; + if (type === "boolean") return "false"; + if (type === "color") return "0x00000000"; + return "null" + } + function AstVar(definitions, varType) { + this.definitions = definitions; + this.varType = varType + } + AstVar.prototype.getNames = function() { + var names = []; + for (var i = 0, l = this.definitions.length; i < l; ++i) names.push(this.definitions[i].name); + return names + }; + AstVar.prototype.toString = function() { + return "var " + this.definitions.join(",") + }; + + function AstStatement(expression) { + this.expression = expression + } + AstStatement.prototype.toString = function() { + return this.expression.toString() + }; + + function transformStatement(statement) { + if (fieldTest.test(statement)) { + var attrAndType = attrAndTypeRegex.exec(statement); + var definitions = statement.substring(attrAndType[0].length).split(","); + var defaultTypeValue = getDefaultValueForType(attrAndType[2]); + for (var i = 0; i < definitions.length; ++i) definitions[i] = transformVarDefinition(definitions[i], defaultTypeValue); + return new AstVar(definitions, attrAndType[2]) + } + return new AstStatement(transformExpression(statement)) + } + function AstForExpression(initStatement, condition, step) { + this.initStatement = initStatement; + this.condition = condition; + this.step = step + } + AstForExpression.prototype.toString = function() { + return "(" + this.initStatement + "; " + this.condition + "; " + this.step + ")" + }; + + function AstForInExpression(initStatement, container) { + this.initStatement = initStatement; + this.container = container + } + AstForInExpression.prototype.toString = function() { + var init = this.initStatement.toString(); + if (init.indexOf("=") >= 0) init = init.substring(0, init.indexOf("=")); + return "(" + init + " in " + this.container + ")" + }; + + function AstForEachExpression(initStatement, container) { + this.initStatement = initStatement; + this.container = container + } + AstForEachExpression.iteratorId = 0; + AstForEachExpression.prototype.toString = function() { + var init = this.initStatement.toString(); + var iterator = "$it" + AstForEachExpression.iteratorId++; + var variableName = init.replace(/^\s*var\s*/, "").split("=")[0]; + var initIteratorAndVariable = "var " + iterator + " = new $p.ObjectIterator(" + this.container + "), " + variableName + " = void(0)"; + var nextIterationCondition = iterator + ".hasNext() && ((" + variableName + " = " + iterator + ".next()) || true)"; + return "(" + initIteratorAndVariable + "; " + nextIterationCondition + ";)" + }; + + function transformForExpression(expr) { + var content; + if (/\bin\b/.test(expr)) { + content = expr.substring(1, expr.length - 1).split(/\bin\b/g); + return new AstForInExpression(transformStatement(trim(content[0])), transformExpression(content[1])) + } + if (expr.indexOf(":") >= 0 && expr.indexOf(";") < 0) { + content = expr.substring(1, expr.length - 1).split(":"); + return new AstForEachExpression(transformStatement(trim(content[0])), transformExpression(content[1])) + } + content = expr.substring(1, expr.length - 1).split(";"); + return new AstForExpression(transformStatement(trim(content[0])), transformExpression(content[1]), transformExpression(content[2])) + } + + function sortByWeight(array) { + array.sort(function(a, b) { + return b.weight - a.weight + }) + } + function AstInnerInterface(name, body, isStatic) { + this.name = name; + this.body = body; + this.isStatic = isStatic; + body.owner = this + } + AstInnerInterface.prototype.toString = function() { + return "" + this.body + }; + + function AstInnerClass(name, body, isStatic) { + this.name = name; + this.body = body; + this.isStatic = isStatic; + body.owner = this + } + AstInnerClass.prototype.toString = function() { + return "" + this.body + }; + + function transformInnerClass(class_) { + var m = classesRegex.exec(class_); + classesRegex.lastIndex = 0; + var isStatic = m[1].indexOf("static") >= 0; + var body = atoms[getAtomIndex(m[6])], + innerClass; + var oldClassId = currentClassId, + newClassId = generateClassId(); + currentClassId = newClassId; + if (m[2] === "interface") innerClass = new AstInnerInterface(m[3], transformInterfaceBody(body, m[3], m[4]), isStatic); + else innerClass = new AstInnerClass(m[3], transformClassBody(body, m[3], m[4], m[5]), isStatic); + appendClass(innerClass, newClassId, oldClassId); + currentClassId = oldClassId; + return innerClass + } + function AstClassMethod(name, params, body, isStatic) { + this.name = name; + this.params = params; + this.body = body; + this.isStatic = isStatic + } + AstClassMethod.prototype.toString = function() { + var paramNames = appendToLookupTable({}, + this.params.getNames()); + var oldContext = replaceContext; + replaceContext = function(subject) { + return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject) + }; + var body = this.params.prependMethodArgs(this.body.toString()); + var result = "function " + this.methodId + this.params + " " + body + "\n"; + replaceContext = oldContext; + return result + }; + + function transformClassMethod(method) { + var m = methodsRegex.exec(method); + methodsRegex.lastIndex = 0; + var isStatic = m[1].indexOf("static") >= 0; + var body = m[6] !== ";" ? atoms[getAtomIndex(m[6])] : "{}"; + return new AstClassMethod(m[3], transformParams(atoms[getAtomIndex(m[4])]), transformStatementsBlock(body), isStatic) + } + function AstClassField(definitions, fieldType, isStatic) { + this.definitions = definitions; + this.fieldType = fieldType; + this.isStatic = isStatic + } + AstClassField.prototype.getNames = function() { + var names = []; + for (var i = 0, l = this.definitions.length; i < l; ++i) names.push(this.definitions[i].name); + return names + }; + AstClassField.prototype.toString = function() { + var thisPrefix = replaceContext({ + name: "[this]" + }); + if (this.isStatic) { + var className = this.owner.name; + var staticDeclarations = []; + for (var i = 0, l = this.definitions.length; i < l; ++i) { + var definition = this.definitions[i]; + var name = definition.name, + staticName = className + "." + name; + var declaration = "if(" + staticName + " === void(0)) {\n" + " " + staticName + " = " + definition.value + "; }\n" + "$p.defineProperty(" + thisPrefix + ", " + "'" + name + "', { get: function(){return " + staticName + ";}, " + "set: function(val){" + staticName + " = val;} });\n"; + staticDeclarations.push(declaration) + } + return staticDeclarations.join("") + } + return thisPrefix + "." + this.definitions.join("; " + thisPrefix + ".") + }; + + function transformClassField(statement) { + var attrAndType = attrAndTypeRegex.exec(statement); + var isStatic = attrAndType[1].indexOf("static") >= 0; + var definitions = statement.substring(attrAndType[0].length).split(/,\s*/g); + var defaultTypeValue = getDefaultValueForType(attrAndType[2]); + for (var i = 0; i < definitions.length; ++i) definitions[i] = transformVarDefinition(definitions[i], defaultTypeValue); + return new AstClassField(definitions, attrAndType[2], isStatic) + } + function AstConstructor(params, body) { + this.params = params; + this.body = body + } + AstConstructor.prototype.toString = function() { + var paramNames = appendToLookupTable({}, + this.params.getNames()); + var oldContext = replaceContext; + replaceContext = function(subject) { + return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject) + }; + var prefix = "function $constr_" + this.params.params.length + this.params.toString(); + var body = this.params.prependMethodArgs(this.body.toString()); + if (!/\$(superCstr|constr)\b/.test(body)) body = "{\n$superCstr();\n" + body.substring(1); + replaceContext = oldContext; + return prefix + body + "\n" + }; + + function transformConstructor(cstr) { + var m = (new RegExp(/"B(\d+)"\s*"A(\d+)"/)).exec(cstr); + var params = transformParams(atoms[m[1]]); + return new AstConstructor(params, transformStatementsBlock(atoms[m[2]])) + } + function AstInterfaceBody(name, interfacesNames, methodsNames, fields, innerClasses, misc) { + var i, l; + this.name = name; + this.interfacesNames = interfacesNames; + this.methodsNames = methodsNames; + this.fields = fields; + this.innerClasses = innerClasses; + this.misc = misc; + for (i = 0, l = fields.length; i < l; ++i) fields[i].owner = this + } + AstInterfaceBody.prototype.getMembers = function(classFields, classMethods, classInners) { + if (this.owner.base) this.owner.base.body.getMembers(classFields, classMethods, classInners); + var i, j, l, m; + for (i = 0, l = this.fields.length; i < l; ++i) { + var fieldNames = this.fields[i].getNames(); + for (j = 0, m = fieldNames.length; j < m; ++j) classFields[fieldNames[j]] = this.fields[i] + } + for (i = 0, l = this.methodsNames.length; i < l; ++i) { + var methodName = this.methodsNames[i]; + classMethods[methodName] = true + } + for (i = 0, l = this.innerClasses.length; i < l; ++i) { + var innerClass = this.innerClasses[i]; + classInners[innerClass.name] = innerClass + } + }; + AstInterfaceBody.prototype.toString = function() { + function getScopeLevel(p) { + var i = 0; + while (p) { + ++i; + p = p.scope + } + return i + } + var scopeLevel = getScopeLevel(this.owner); + var className = this.name; + var staticDefinitions = ""; + var metadata = ""; + var thisClassFields = {}, + thisClassMethods = {}, + thisClassInners = {}; + this.getMembers(thisClassFields, thisClassMethods, thisClassInners); + var i, l, j, m; + if (this.owner.interfaces) { + var resolvedInterfaces = [], + resolvedInterface; + for (i = 0, l = this.interfacesNames.length; i < l; ++i) { + if (!this.owner.interfaces[i]) continue; + resolvedInterface = replaceContext({ + name: this.interfacesNames[i] + }); + resolvedInterfaces.push(resolvedInterface); + staticDefinitions += "$p.extendInterfaceMembers(" + className + ", " + resolvedInterface + ");\n" + } + metadata += className + ".$interfaces = [" + resolvedInterfaces.join(", ") + "];\n" + } + metadata += className + ".$isInterface = true;\n"; + metadata += className + ".$methods = ['" + this.methodsNames.join("', '") + "'];\n"; + sortByWeight(this.innerClasses); + for (i = 0, l = this.innerClasses.length; i < l; ++i) { + var innerClass = this.innerClasses[i]; + if (innerClass.isStatic) staticDefinitions += className + "." + innerClass.name + " = " + innerClass + ";\n" + } + for (i = 0, l = this.fields.length; i < l; ++i) { + var field = this.fields[i]; + if (field.isStatic) staticDefinitions += className + "." + field.definitions.join(";\n" + className + ".") + ";\n" + } + return "(function() {\n" + "function " + className + "() { throw 'Unable to create the interface'; }\n" + staticDefinitions + metadata + "return " + className + ";\n" + "})()" + }; + transformInterfaceBody = function(body, name, baseInterfaces) { + var declarations = body.substring(1, body.length - 1); + declarations = extractClassesAndMethods(declarations); + declarations = extractConstructors(declarations, name); + var methodsNames = [], + classes = []; + declarations = declarations.replace(/"([DE])(\d+)"/g, function(all, type, index) { + if (type === "D") methodsNames.push(index); + else if (type === "E") classes.push(index); + return "" + }); + var fields = declarations.split(/;(?:\s*;)*/g); + var baseInterfaceNames; + var i, l; + if (baseInterfaces !== undef) baseInterfaceNames = baseInterfaces.replace(/^\s*extends\s+(.+?)\s*$/g, "$1").split(/\s*,\s*/g); + for (i = 0, l = methodsNames.length; i < l; ++i) { + var method = transformClassMethod(atoms[methodsNames[i]]); + methodsNames[i] = method.name + } + for (i = 0, l = fields.length - 1; i < l; ++i) { + var field = trimSpaces(fields[i]); + fields[i] = transformClassField(field.middle) + } + var tail = fields.pop(); + for (i = 0, l = classes.length; i < l; ++i) classes[i] = transformInnerClass(atoms[classes[i]]); + return new AstInterfaceBody(name, baseInterfaceNames, methodsNames, fields, classes, { + tail: tail + }) + }; + + function AstClassBody(name, baseClassName, interfacesNames, functions, methods, fields, cstrs, innerClasses, misc) { + var i, l; + this.name = name; + this.baseClassName = baseClassName; + this.interfacesNames = interfacesNames; + this.functions = functions; + this.methods = methods; + this.fields = fields; + this.cstrs = cstrs; + this.innerClasses = innerClasses; + this.misc = misc; + for (i = 0, l = fields.length; i < l; ++i) fields[i].owner = this + } + AstClassBody.prototype.getMembers = function(classFields, classMethods, classInners) { + if (this.owner.base) this.owner.base.body.getMembers(classFields, classMethods, classInners); + var i, j, l, m; + for (i = 0, l = this.fields.length; i < l; ++i) { + var fieldNames = this.fields[i].getNames(); + for (j = 0, m = fieldNames.length; j < m; ++j) classFields[fieldNames[j]] = this.fields[i] + } + for (i = 0, l = this.methods.length; i < l; ++i) { + var method = this.methods[i]; + classMethods[method.name] = method + } + for (i = 0, l = this.innerClasses.length; i < l; ++i) { + var innerClass = this.innerClasses[i]; + classInners[innerClass.name] = innerClass + } + }; + AstClassBody.prototype.toString = function() { + function getScopeLevel(p) { + var i = 0; + while (p) { + ++i; + p = p.scope + } + return i + } + var scopeLevel = getScopeLevel(this.owner); + var selfId = "$this_" + scopeLevel; + var className = this.name; + var result = "var " + selfId + " = this;\n"; + var staticDefinitions = ""; + var metadata = ""; + var thisClassFields = {}, + thisClassMethods = {}, + thisClassInners = {}; + this.getMembers(thisClassFields, thisClassMethods, thisClassInners); + var oldContext = replaceContext; + replaceContext = function(subject) { + var name = subject.name; + if (name === "this") return subject.callSign || !subject.member ? selfId + ".$self" : selfId; + if (thisClassFields.hasOwnProperty(name)) return thisClassFields[name].isStatic ? className + "." + name : selfId + "." + name; + if (thisClassInners.hasOwnProperty(name)) return selfId + "." + name; + if (thisClassMethods.hasOwnProperty(name)) return thisClassMethods[name].isStatic ? className + "." + name : selfId + ".$self." + name; + return oldContext(subject) + }; + var resolvedBaseClassName; + if (this.baseClassName) { + resolvedBaseClassName = oldContext({ + name: this.baseClassName + }); + result += "var $super = { $upcast: " + selfId + " };\n"; + result += "function $superCstr(){" + resolvedBaseClassName + ".apply($super,arguments);if(!('$self' in $super)) $p.extendClassChain($super)}\n"; + metadata += className + ".$base = " + resolvedBaseClassName + ";\n" + } else result += "function $superCstr(){$p.extendClassChain(" + selfId + ")}\n"; + if (this.owner.base) staticDefinitions += "$p.extendStaticMembers(" + className + ", " + resolvedBaseClassName + ");\n"; + var i, l, j, m; + if (this.owner.interfaces) { + var resolvedInterfaces = [], + resolvedInterface; + for (i = 0, l = this.interfacesNames.length; i < l; ++i) { + if (!this.owner.interfaces[i]) continue; + resolvedInterface = oldContext({ + name: this.interfacesNames[i] + }); + resolvedInterfaces.push(resolvedInterface); + staticDefinitions += "$p.extendInterfaceMembers(" + className + ", " + resolvedInterface + ");\n" + } + metadata += className + ".$interfaces = [" + resolvedInterfaces.join(", ") + "];\n" + } + if (this.functions.length > 0) result += this.functions.join("\n") + "\n"; + sortByWeight(this.innerClasses); + for (i = 0, l = this.innerClasses.length; i < l; ++i) { + var innerClass = this.innerClasses[i]; + if (innerClass.isStatic) { + staticDefinitions += className + "." + innerClass.name + " = " + innerClass + ";\n"; + result += selfId + "." + innerClass.name + " = " + className + "." + innerClass.name + ";\n" + } else result += selfId + "." + innerClass.name + " = " + innerClass + ";\n" + } + for (i = 0, l = this.fields.length; i < l; ++i) { + var field = this.fields[i]; + if (field.isStatic) { + staticDefinitions += className + "." + field.definitions.join(";\n" + className + ".") + ";\n"; + for (j = 0, m = field.definitions.length; j < m; ++j) { + var fieldName = field.definitions[j].name, + staticName = className + "." + fieldName; + result += "$p.defineProperty(" + selfId + ", '" + fieldName + "', {" + "get: function(){return " + staticName + "}, " + "set: function(val){" + staticName + " = val}});\n" + } + } else result += selfId + "." + field.definitions.join(";\n" + selfId + ".") + ";\n" + } + var methodOverloads = {}; + for (i = 0, l = this.methods.length; i < l; ++i) { + var method = this.methods[i]; + var overload = methodOverloads[method.name]; + var methodId = method.name + "$" + method.params.params.length; + var hasMethodArgs = !!method.params.methodArgsParam; + if (overload) { + ++overload; + methodId += "_" + overload + } else overload = 1; + method.methodId = methodId; + methodOverloads[method.name] = overload; + if (method.isStatic) { + staticDefinitions += method; + staticDefinitions += "$p.addMethod(" + className + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n"; + result += "$p.addMethod(" + selfId + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n" + } else { + result += method; + result += "$p.addMethod(" + selfId + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n" + } + } + result += trim(this.misc.tail); + if (this.cstrs.length > 0) result += this.cstrs.join("\n") + "\n"; + result += "function $constr() {\n"; + var cstrsIfs = []; + for (i = 0, l = this.cstrs.length; i < l; ++i) { + var paramsLength = this.cstrs[i].params.params.length; + var methodArgsPresent = !!this.cstrs[i].params.methodArgsParam; + cstrsIfs.push("if(arguments.length " + (methodArgsPresent ? ">=" : "===") + " " + paramsLength + ") { " + "$constr_" + paramsLength + ".apply(" + selfId + ", arguments); }") + } + if (cstrsIfs.length > 0) result += cstrsIfs.join(" else ") + " else "; + result += "$superCstr();\n}\n"; + result += "$constr.apply(null, arguments);\n"; + replaceContext = oldContext; + return "(function() {\n" + "function " + className + "() {\n" + result + "}\n" + staticDefinitions + metadata + "return " + className + ";\n" + "})()" + }; + transformClassBody = function(body, name, baseName, interfaces) { + var declarations = body.substring(1, body.length - 1); + declarations = extractClassesAndMethods(declarations); + declarations = extractConstructors(declarations, name); + var methods = [], + classes = [], + cstrs = [], + functions = []; + declarations = declarations.replace(/"([DEGH])(\d+)"/g, function(all, type, index) { + if (type === "D") methods.push(index); + else if (type === "E") classes.push(index); + else if (type === "H") functions.push(index); + else cstrs.push(index); + return "" + }); + var fields = declarations.replace(/^(?:\s*;)+/, "").split(/;(?:\s*;)*/g); + var baseClassName, interfacesNames; + var i; + if (baseName !== undef) baseClassName = baseName.replace(/^\s*extends\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)\s*$/g, "$1"); + if (interfaces !== undef) interfacesNames = interfaces.replace(/^\s*implements\s+(.+?)\s*$/g, "$1").split(/\s*,\s*/g); + for (i = 0; i < functions.length; ++i) functions[i] = transformFunction(atoms[functions[i]]); + for (i = 0; i < methods.length; ++i) methods[i] = transformClassMethod(atoms[methods[i]]); + for (i = 0; i < fields.length - 1; ++i) { + var field = trimSpaces(fields[i]); + fields[i] = transformClassField(field.middle) + } + var tail = fields.pop(); + for (i = 0; i < cstrs.length; ++i) cstrs[i] = transformConstructor(atoms[cstrs[i]]); + for (i = 0; i < classes.length; ++i) classes[i] = transformInnerClass(atoms[classes[i]]); + return new AstClassBody(name, baseClassName, interfacesNames, functions, methods, fields, cstrs, classes, { + tail: tail + }) + }; + + function AstInterface(name, body) { + this.name = name; + this.body = body; + body.owner = this + } + AstInterface.prototype.toString = function() { + return "var " + this.name + " = " + this.body + ";\n" + "$p." + this.name + " = " + this.name + ";\n" + }; + + function AstClass(name, body) { + this.name = name; + this.body = body; + body.owner = this + } + AstClass.prototype.toString = function() { + return "var " + this.name + " = " + this.body + ";\n" + "$p." + this.name + " = " + this.name + ";\n" + }; + + function transformGlobalClass(class_) { + var m = classesRegex.exec(class_); + classesRegex.lastIndex = 0; + var body = atoms[getAtomIndex(m[6])]; + var oldClassId = currentClassId, + newClassId = generateClassId(); + currentClassId = newClassId; + var globalClass; + if (m[2] === "interface") globalClass = new AstInterface(m[3], transformInterfaceBody(body, m[3], m[4])); + else globalClass = new AstClass(m[3], transformClassBody(body, m[3], m[4], m[5])); + appendClass(globalClass, newClassId, oldClassId); + currentClassId = oldClassId; + return globalClass + } + function AstMethod(name, params, body) { + this.name = name; + this.params = params; + this.body = body + } + AstMethod.prototype.toString = function() { + var paramNames = appendToLookupTable({}, + this.params.getNames()); + var oldContext = replaceContext; + replaceContext = function(subject) { + return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject) + }; + var body = this.params.prependMethodArgs(this.body.toString()); + var result = "function " + this.name + this.params + " " + body + "\n" + "$p." + this.name + " = " + this.name + ";"; + replaceContext = oldContext; + return result + }; + + function transformGlobalMethod(method) { + var m = methodsRegex.exec(method); + var result = methodsRegex.lastIndex = 0; + return new AstMethod(m[3], transformParams(atoms[getAtomIndex(m[4])]), transformStatementsBlock(atoms[getAtomIndex(m[6])])) + } + function preStatementsTransform(statements) { + var s = statements; + s = s.replace(/\b(catch\s*"B\d+"\s*"A\d+")(\s*catch\s*"B\d+"\s*"A\d+")+/g, "$1"); + return s + } + function AstForStatement(argument, misc) { + this.argument = argument; + this.misc = misc + } + AstForStatement.prototype.toString = function() { + return this.misc.prefix + this.argument.toString() + }; + + function AstCatchStatement(argument, misc) { + this.argument = argument; + this.misc = misc + } + AstCatchStatement.prototype.toString = function() { + return this.misc.prefix + this.argument.toString() + }; + + function AstPrefixStatement(name, argument, misc) { + this.name = name; + this.argument = argument; + this.misc = misc + } + AstPrefixStatement.prototype.toString = function() { + var result = this.misc.prefix; + if (this.argument !== undef) result += this.argument.toString(); + return result + }; + + function AstSwitchCase(expr) { + this.expr = expr + } + AstSwitchCase.prototype.toString = function() { + return "case " + this.expr + ":" + }; + + function AstLabel(label) { + this.label = label + } + AstLabel.prototype.toString = function() { + return this.label + }; + transformStatements = function(statements, transformMethod, transformClass) { + var nextStatement = new RegExp(/\b(catch|for|if|switch|while|with)\s*"B(\d+)"|\b(do|else|finally|return|throw|try|break|continue)\b|("[ADEH](\d+)")|\b(case)\s+([^:]+):|\b([A-Za-z_$][\w$]*\s*:)|(;)/g); + var res = []; + statements = preStatementsTransform(statements); + var lastIndex = 0, + m, space; + while ((m = nextStatement.exec(statements)) !== null) { + if (m[1] !== undef) { + var i = statements.lastIndexOf('"B', nextStatement.lastIndex); + var statementsPrefix = statements.substring(lastIndex, i); + if (m[1] === "for") res.push(new AstForStatement(transformForExpression(atoms[m[2]]), { + prefix: statementsPrefix + })); + else if (m[1] === "catch") res.push(new AstCatchStatement(transformParams(atoms[m[2]]), { + prefix: statementsPrefix + })); + else res.push(new AstPrefixStatement(m[1], transformExpression(atoms[m[2]]), { + prefix: statementsPrefix + })) + } else if (m[3] !== undef) res.push(new AstPrefixStatement(m[3], undef, { + prefix: statements.substring(lastIndex, nextStatement.lastIndex) + })); + else if (m[4] !== undef) { + space = statements.substring(lastIndex, nextStatement.lastIndex - m[4].length); + if (trim(space).length !== 0) continue; + res.push(space); + var kind = m[4].charAt(1), + atomIndex = m[5]; + if (kind === "D") res.push(transformMethod(atoms[atomIndex])); + else if (kind === "E") res.push(transformClass(atoms[atomIndex])); + else if (kind === "H") res.push(transformFunction(atoms[atomIndex])); + else res.push(transformStatementsBlock(atoms[atomIndex])) + } else if (m[6] !== undef) res.push(new AstSwitchCase(transformExpression(trim(m[7])))); + else if (m[8] !== undef) { + space = statements.substring(lastIndex, nextStatement.lastIndex - m[8].length); + if (trim(space).length !== 0) continue; + res.push(new AstLabel(statements.substring(lastIndex, nextStatement.lastIndex))) + } else { + var statement = trimSpaces(statements.substring(lastIndex, nextStatement.lastIndex - 1)); + res.push(statement.left); + res.push(transformStatement(statement.middle)); + res.push(statement.right + ";") + } + lastIndex = nextStatement.lastIndex + } + var statementsTail = trimSpaces(statements.substring(lastIndex)); + res.push(statementsTail.left); + if (statementsTail.middle !== "") { + res.push(transformStatement(statementsTail.middle)); + res.push(";" + statementsTail.right) + } + return res + }; + + function getLocalNames(statements) { + var localNames = []; + for (var i = 0, l = statements.length; i < l; ++i) { + var statement = statements[i]; + if (statement instanceof AstVar) localNames = localNames.concat(statement.getNames()); + else if (statement instanceof AstForStatement && statement.argument.initStatement instanceof AstVar) localNames = localNames.concat(statement.argument.initStatement.getNames()); + else if (statement instanceof AstInnerInterface || statement instanceof AstInnerClass || statement instanceof AstInterface || statement instanceof AstClass || statement instanceof AstMethod || statement instanceof AstFunction) localNames.push(statement.name) + } + return appendToLookupTable({}, + localNames) + } + function AstStatementsBlock(statements) { + this.statements = statements + } + AstStatementsBlock.prototype.toString = function() { + var localNames = getLocalNames(this.statements); + var oldContext = replaceContext; + if (!isLookupTableEmpty(localNames)) replaceContext = function(subject) { + return localNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject) + }; + var result = "{\n" + this.statements.join("") + "\n}"; + replaceContext = oldContext; + return result + }; + transformStatementsBlock = function(block) { + var content = trimSpaces(block.substring(1, block.length - 1)); + return new AstStatementsBlock(transformStatements(content.middle)) + }; + + function AstRoot(statements) { + this.statements = statements + } + AstRoot.prototype.toString = function() { + var classes = [], + otherStatements = [], + statement; + for (var i = 0, len = this.statements.length; i < len; ++i) { + statement = this.statements[i]; + if (statement instanceof AstClass || statement instanceof AstInterface) classes.push(statement); + else otherStatements.push(statement) + } + sortByWeight(classes); + var localNames = getLocalNames(this.statements); + replaceContext = function(subject) { + var name = subject.name; + if (localNames.hasOwnProperty(name)) return name; + if (globalMembers.hasOwnProperty(name) || PConstants.hasOwnProperty(name) || defaultScope.hasOwnProperty(name)) return "$p." + name; + return name + }; + var result = "// this code was autogenerated from PJS\n" + "(function($p) {\n" + classes.join("") + "\n" + otherStatements.join("") + "\n})"; + replaceContext = null; + return result + }; + transformMain = function() { + var statements = extractClassesAndMethods(atoms[0]); + statements = statements.replace(/\bimport\s+[^;]+;/g, ""); + return new AstRoot(transformStatements(statements, transformGlobalMethod, transformGlobalClass)) + }; + + function generateMetadata(ast) { + var globalScope = {}; + var id, class_; + for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) { + class_ = declaredClasses[id]; + var scopeId = class_.scopeId, + name = class_.name; + if (scopeId) { + var scope = declaredClasses[scopeId]; + class_.scope = scope; + if (scope.inScope === undef) scope.inScope = {}; + scope.inScope[name] = class_ + } else globalScope[name] = class_ + } + function findInScopes(class_, name) { + var parts = name.split("."); + var currentScope = class_.scope, + found; + while (currentScope) { + if (currentScope.hasOwnProperty(parts[0])) { + found = currentScope[parts[0]]; + break + } + currentScope = currentScope.scope + } + if (found === undef) found = globalScope[parts[0]]; + for (var i = 1, l = parts.length; i < l && found; ++i) found = found.inScope[parts[i]]; + return found + } + for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) { + class_ = declaredClasses[id]; + var baseClassName = class_.body.baseClassName; + if (baseClassName) { + var parent = findInScopes(class_, baseClassName); + if (parent) { + class_.base = parent; + if (!parent.derived) parent.derived = []; + parent.derived.push(class_) + } + } + var interfacesNames = class_.body.interfacesNames, + interfaces = [], + i, l; + if (interfacesNames && interfacesNames.length > 0) { + for (i = 0, l = interfacesNames.length; i < l; ++i) { + var interface_ = findInScopes(class_, interfacesNames[i]); + interfaces.push(interface_); + if (!interface_) continue; + if (!interface_.derived) interface_.derived = []; + interface_.derived.push(class_) + } + if (interfaces.length > 0) class_.interfaces = interfaces + } + } + } + function setWeight(ast) { + var queue = [], + tocheck = {}; + var id, scopeId, class_; + for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) { + class_ = declaredClasses[id]; + if (!class_.inScope && !class_.derived) { + queue.push(id); + class_.weight = 0 + } else { + var dependsOn = []; + if (class_.inScope) for (scopeId in class_.inScope) if (class_.inScope.hasOwnProperty(scopeId)) dependsOn.push(class_.inScope[scopeId]); + if (class_.derived) dependsOn = dependsOn.concat(class_.derived); + tocheck[id] = dependsOn + } + } + function removeDependentAndCheck(targetId, from) { + var dependsOn = tocheck[targetId]; + if (!dependsOn) return false; + var i = dependsOn.indexOf(from); + if (i < 0) return false; + dependsOn.splice(i, 1); + if (dependsOn.length > 0) return false; + delete tocheck[targetId]; + return true + } + while (queue.length > 0) { + id = queue.shift(); + class_ = declaredClasses[id]; + if (class_.scopeId && removeDependentAndCheck(class_.scopeId, class_)) { + queue.push(class_.scopeId); + declaredClasses[class_.scopeId].weight = class_.weight + 1 + } + if (class_.base && removeDependentAndCheck(class_.base.classId, class_)) { + queue.push(class_.base.classId); + class_.base.weight = class_.weight + 1 + } + if (class_.interfaces) { + var i, l; + for (i = 0, l = class_.interfaces.length; i < l; ++i) { + if (!class_.interfaces[i] || !removeDependentAndCheck(class_.interfaces[i].classId, class_)) continue; + queue.push(class_.interfaces[i].classId); + class_.interfaces[i].weight = class_.weight + 1 + } + } + } + } + var transformed = transformMain(); + generateMetadata(transformed); + setWeight(transformed); + var redendered = transformed.toString(); + redendered = redendered.replace(/\s*\n(?:[\t ]*\n)+/g, "\n\n"); + redendered = redendered.replace(/__x([0-9A-F]{4})/g, function(all, hexCode) { + return String.fromCharCode(parseInt(hexCode, 16)) + }); + return injectStrings(redendered, strings) + } + + function preprocessCode(aCode, sketch) { + var dm = (new RegExp(/\/\*\s*@pjs\s+((?:[^\*]|\*+[^\*\/])*)\*\//g)).exec(aCode); + if (dm && dm.length === 2) { + var jsonItems = [], + directives = dm.splice(1, 2)[0].replace(/\{([\s\S]*?)\}/g, function() { + return function(all, item) { + jsonItems.push(item); + return "{" + (jsonItems.length - 1) + "}" + } + }()).replace("\n", "").replace("\r", "").split(";"); + var clean = function(s) { + return s.replace(/^\s*["']?/, "").replace(/["']?\s*$/, "") + }; + for (var i = 0, dl = directives.length; i < dl; i++) { + var pair = directives[i].split("="); + if (pair && pair.length === 2) { + var key = clean(pair[0]), + value = clean(pair[1]), + list = []; + if (key === "preload") { + list = value.split(","); + for (var j = 0, jl = list.length; j < jl; j++) { + var imageName = clean(list[j]); + sketch.imageCache.add(imageName) + } + } else if (key === "font") { + list = value.split(","); + for (var x = 0, xl = list.length; x < xl; x++) { + var fontName = clean(list[x]), + index = /^\{(\d*?)\}$/.exec(fontName); + PFont.preloading.add(index ? JSON.parse("{" + jsonItems[index[1]] + "}") : fontName) + } + } else if (key === "pauseOnBlur") sketch.options.pauseOnBlur = value === "true"; + else if (key === "globalKeyEvents") sketch.options.globalKeyEvents = value === "true"; + else if (key.substring(0, 6) === "param-") sketch.params[key.substring(6)] = value; + else sketch.options[key] = value + } + } + } + return aCode + } + Processing.compile = function(pdeCode) { + var sketch = new Processing.Sketch; + var code = preprocessCode(pdeCode, sketch); + var compiledPde = parseProcessing(code); + sketch.sourceCode = compiledPde; + return sketch + }; + var tinylogLite = function() { + var tinylogLite = {}, + undef = "undefined", + func = "function", + False = !1, + True = !0, + logLimit = 512, + log = "log"; + if (typeof tinylog !== undef && typeof tinylog[log] === func) tinylogLite[log] = tinylog[log]; + else if (typeof document !== undef && !document.fake)(function() { + var doc = document, + $div = "div", + $style = "style", + $title = "title", + containerStyles = { + zIndex: 1E4, + position: "fixed", + bottom: "0px", + width: "100%", + height: "15%", + fontFamily: "sans-serif", + color: "#ccc", + backgroundColor: "black" + }, + outputStyles = { + position: "relative", + fontFamily: "monospace", + overflow: "auto", + height: "100%", + paddingTop: "5px" + }, + resizerStyles = { + height: "5px", + marginTop: "-5px", + cursor: "n-resize", + backgroundColor: "darkgrey" + }, + closeButtonStyles = { + position: "absolute", + top: "5px", + right: "20px", + color: "#111", + MozBorderRadius: "4px", + webkitBorderRadius: "4px", + borderRadius: "4px", + cursor: "pointer", + fontWeight: "normal", + textAlign: "center", + padding: "3px 5px", + backgroundColor: "#333", + fontSize: "12px" + }, + entryStyles = { + minHeight: "16px" + }, + entryTextStyles = { + fontSize: "12px", + margin: "0 8px 0 8px", + maxWidth: "100%", + whiteSpace: "pre-wrap", + overflow: "auto" + }, + view = doc.defaultView, + docElem = doc.documentElement, + docElemStyle = docElem[$style], + setStyles = function() { + var i = arguments.length, + elemStyle, styles, style; + while (i--) { + styles = arguments[i--]; + elemStyle = arguments[i][$style]; + for (style in styles) if (styles.hasOwnProperty(style)) elemStyle[style] = styles[style] + } + }, + observer = function(obj, event, handler) { + if (obj.addEventListener) obj.addEventListener(event, handler, False); + else if (obj.attachEvent) obj.attachEvent("on" + event, handler); + return [obj, event, handler] + }, + unobserve = function(obj, event, handler) { + if (obj.removeEventListener) obj.removeEventListener(event, handler, False); + else if (obj.detachEvent) obj.detachEvent("on" + event, handler) + }, + clearChildren = function(node) { + var children = node.childNodes, + child = children.length; + while (child--) node.removeChild(children.item(0)) + }, + append = function(to, elem) { + return to.appendChild(elem) + }, + createElement = function(localName) { + return doc.createElement(localName) + }, + createTextNode = function(text) { + return doc.createTextNode(text) + }, + createLog = tinylogLite[log] = function(message) { + var uninit, originalPadding = docElemStyle.paddingBottom, + container = createElement($div), + containerStyle = container[$style], + resizer = append(container, createElement($div)), + output = append(container, createElement($div)), + closeButton = append(container, createElement($div)), + resizingLog = False, + previousHeight = False, + previousScrollTop = False, + messages = 0, + updateSafetyMargin = function() { + docElemStyle.paddingBottom = container.clientHeight + "px" + }, + setContainerHeight = function(height) { + var viewHeight = view.innerHeight, + resizerHeight = resizer.clientHeight; + if (height < 0) height = 0; + else if (height + resizerHeight > viewHeight) height = viewHeight - resizerHeight; + containerStyle.height = height / viewHeight * 100 + "%"; + updateSafetyMargin() + }, + observers = [observer(doc, "mousemove", function(evt) { + if (resizingLog) { + setContainerHeight(view.innerHeight - evt.clientY); + output.scrollTop = previousScrollTop + } + }), observer(doc, "mouseup", function() { + if (resizingLog) resizingLog = previousScrollTop = False + }), observer(resizer, "dblclick", function(evt) { + evt.preventDefault(); + if (previousHeight) { + setContainerHeight(previousHeight); + previousHeight = False + } else { + previousHeight = container.clientHeight; + containerStyle.height = "0px" + } + }), observer(resizer, "mousedown", function(evt) { + evt.preventDefault(); + resizingLog = True; + previousScrollTop = output.scrollTop + }), observer(resizer, "contextmenu", function() { + resizingLog = False + }), observer(closeButton, "click", function() { + uninit() + })]; + uninit = function() { + var i = observers.length; + while (i--) unobserve.apply(tinylogLite, observers[i]); + docElem.removeChild(container); + docElemStyle.paddingBottom = originalPadding; + clearChildren(output); + clearChildren(container); + tinylogLite[log] = createLog + }; + setStyles(container, containerStyles, output, outputStyles, resizer, resizerStyles, closeButton, closeButtonStyles); + closeButton[$title] = "Close Log"; + append(closeButton, createTextNode("\u2716")); + resizer[$title] = "Double-click to toggle log minimization"; + docElem.insertBefore(container, docElem.firstChild); + tinylogLite[log] = function(message) { + if (messages === logLimit) output.removeChild(output.firstChild); + else messages++; + var entry = append(output, createElement($div)), + entryText = append(entry, createElement($div)); + entry[$title] = (new Date).toLocaleTimeString(); + setStyles(entry, entryStyles, entryText, entryTextStyles); + append(entryText, createTextNode(message)); + output.scrollTop = output.scrollHeight + }; + tinylogLite[log](message); + updateSafetyMargin() + } + })(); + else if (typeof print === func) tinylogLite[log] = print; + return tinylogLite + }(); + Processing.logger = tinylogLite; + Processing.version = "1.4.1"; + Processing.lib = {}; + Processing.registerLibrary = function(name, desc) { + Processing.lib[name] = desc; + if (desc.hasOwnProperty("init")) desc.init(defaultScope) + }; + Processing.instances = processingInstances; + Processing.getInstanceById = function(name) { + return processingInstances[processingInstanceIds[name]] + }; + Processing.Sketch = function(attachFunction) { + this.attachFunction = attachFunction; + this.options = { + pauseOnBlur: false, + globalKeyEvents: false + }; + this.onLoad = nop; + this.onSetup = nop; + this.onPause = nop; + this.onLoop = nop; + this.onFrameStart = nop; + this.onFrameEnd = nop; + this.onExit = nop; + this.params = {}; + this.imageCache = { + pending: 0, + images: {}, + operaCache: {}, + add: function(href, img) { + if (this.images[href]) return; + if (!isDOMPresent) this.images[href] = null; + if (!img) { + img = new Image; + img.onload = function(owner) { + return function() { + owner.pending-- + } + }(this); + this.pending++; + img.src = href + } + this.images[href] = img; + if (window.opera) { + var div = document.createElement("div"); + div.appendChild(img); + div.style.position = "absolute"; + div.style.opacity = 0; + div.style.width = "1px"; + div.style.height = "1px"; + if (!this.operaCache[href]) { + document.body.appendChild(div); + this.operaCache[href] = div + } + } + } + }; + this.sourceCode = undefined; + this.attach = function(processing) { + if (typeof this.attachFunction === "function") this.attachFunction(processing); + else if (this.sourceCode) { + var func = (new Function("return (" + this.sourceCode + ");"))(); + func(processing); + this.attachFunction = func + } else throw "Unable to attach sketch to the processing instance"; + }; + this.toString = function() { + var i; + var code = "((function(Sketch) {\n"; + code += "var sketch = new Sketch(\n" + this.sourceCode + ");\n"; + for (i in this.options) if (this.options.hasOwnProperty(i)) { + var value = this.options[i]; + code += "sketch.options." + i + " = " + (typeof value === "string" ? '"' + value + '"' : "" + value) + ";\n" + } + for (i in this.imageCache) if (this.options.hasOwnProperty(i)) code += 'sketch.imageCache.add("' + i + '");\n'; + code += "return sketch;\n})(Processing.Sketch))"; + return code + } + }; + var loadSketchFromSources = function(canvas, sources) { + var code = [], + errors = [], + sourcesCount = sources.length, + loaded = 0; + + function ajaxAsync(url, callback) { + var xhr = new XMLHttpRequest; + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + var error; + if (xhr.status !== 200 && xhr.status !== 0) error = "Invalid XHR status " + xhr.status; + else if (xhr.responseText === "") if ("withCredentials" in new XMLHttpRequest && (new XMLHttpRequest).withCredentials === false && window.location.protocol === "file:") error = "XMLHttpRequest failure, possibly due to a same-origin policy violation. You can try loading this page in another browser, or load it from http://localhost using a local webserver. See the Processing.js README for a more detailed explanation of this problem and solutions."; + else error = "File is empty."; + callback(xhr.responseText, error) + } + }; + xhr.open("GET", url, true); + if (xhr.overrideMimeType) xhr.overrideMimeType("application/json"); + xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT"); + xhr.send(null) + } + function loadBlock(index, filename) { + function callback(block, error) { + code[index] = block; + ++loaded; + if (error) errors.push(filename + " ==> " + error); + if (loaded === sourcesCount) if (errors.length === 0) try { + return new Processing(canvas, code.join("\n")) + } catch(e) { + throw "Processing.js: Unable to execute pjs sketch: " + e; + } else throw "Processing.js: Unable to load pjs sketch files: " + errors.join("\n"); + } + if (filename.charAt(0) === "#") { + var scriptElement = document.getElementById(filename.substring(1)); + if (scriptElement) callback(scriptElement.text || scriptElement.textContent); + else callback("", "Unable to load pjs sketch: element with id '" + filename.substring(1) + "' was not found"); + return + } + ajaxAsync(filename, callback) + } + for (var i = 0; i < sourcesCount; ++i) loadBlock(i, sources[i]) + }; + var init = function() { + document.removeEventListener("DOMContentLoaded", init, false); + processingInstances = []; + var canvas = document.getElementsByTagName("canvas"), + filenames; + for (var i = 0, l = canvas.length; i < l; i++) { + var processingSources = canvas[i].getAttribute("data-processing-sources"); + if (processingSources === null) { + processingSources = canvas[i].getAttribute("data-src"); + if (processingSources === null) processingSources = canvas[i].getAttribute("datasrc") + } + if (processingSources) { + filenames = processingSources.split(/\s+/g); + for (var j = 0; j < filenames.length;) if (filenames[j]) j++; + else filenames.splice(j, 1); + loadSketchFromSources(canvas[i], filenames) + } + } + var s, last, source, instance, nodelist = document.getElementsByTagName("script"), + scripts = []; + for (s = nodelist.length - 1; s >= 0; s--) scripts.push(nodelist[s]); + for (s = 0, last = scripts.length; s < last; s++) { + var script = scripts[s]; + if (!script.getAttribute) continue; + var type = script.getAttribute("type"); + if (type && (type.toLowerCase() === "text/processing" || type.toLowerCase() === "application/processing")) { + var target = script.getAttribute("data-processing-target"); + canvas = undef; + if (target) canvas = document.getElementById(target); + else { + var nextSibling = script.nextSibling; + while (nextSibling && nextSibling.nodeType !== 1) nextSibling = nextSibling.nextSibling; + if (nextSibling && nextSibling.nodeName.toLowerCase() === "canvas") canvas = nextSibling + } + if (canvas) { + if (script.getAttribute("src")) { + filenames = script.getAttribute("src").split(/\s+/); + loadSketchFromSources(canvas, filenames); + continue + } + source = script.textContent || script.text; + instance = new Processing(canvas, source) + } + } + } + }; + Processing.reload = function() { + if (processingInstances.length > 0) for (var i = processingInstances.length - 1; i >= 0; i--) if (processingInstances[i]) processingInstances[i].exit(); + init() + }; + Processing.loadSketchFromSources = loadSketchFromSources; + Processing.disableInit = function() { + if (isDOMPresent) document.removeEventListener("DOMContentLoaded", init, false) + }; + if (isDOMPresent) { + window["Processing"] = Processing; + document.addEventListener("DOMContentLoaded", init, false) + } else this.Processing = Processing +})(window, window.document, Math); + diff --git a/CodeToAccompany9781430244646/ch04/bezierEllipse_page/bezierEllipse_page.pde b/CodeToAccompany9781430244646/ch04/bezierEllipse_page/bezierEllipse_page.pde new file mode 100644 index 0000000..f807523 --- /dev/null +++ b/CodeToAccompany9781430244646/ch04/bezierEllipse_page/bezierEllipse_page.pde @@ -0,0 +1,95 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ +// bezierEllipse_page.pde, chapter 4 +// Examples of randomized, closed Bezier curves. + +void setup() { + size(800, 800); + background(0); + int cols = 10; + int rows = 10; + float formWidth = width/cols; + float formRadius = formWidth/2; + fill(255); + for (int i=0; isliderBarX && mouseX < sliderBarX + sliderBarW) { + sliderHandleX = mouseX; + } + // detect if mouse is on control/anchor point + if (dist(mouseX, mouseY, sliderHandleX, sliderHandleY) < sliderHandleW/2) { + isOnSliderHandle = true; + } + + // ensures slider handle values between to sliderMin to sliderMax + curvature = map(sliderHandleX, sliderBarX, sliderBarX+sliderBarW, sliderMin, sliderMax); +} // setCurvature() + +void mouseDragged() { + // move points + if (isOnAnchor >=0 && isOnAnchor (width-radius)) { // bounce against the right edge + x = width-radius; + dx = -dx; + } + if (x < radius) { // bounce against the left edge + x = radius; + dx = -dx; + } + if (y > (height-radius)) { // bounce against the bottom edge + y = height-radius; + speed = speed * dampen ; + } + } // bounce() +} // class ball + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_2/sketch_6_2.pde b/CodeToAccompany9781430244646/ch06/sketch_6_2/sketch_6_2.pde new file mode 100644 index 0000000..090ac4c --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_2/sketch_6_2.pde @@ -0,0 +1,34 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch: 6-2: Creating and displaying three ball objects +ball b1, b2, b3; +void setup() { + size(400, 400); + smooth(); + // create the balls + b1 = new ball(); + b2 = new ball(); + b3 = new ball(); +} // setup() +void draw() { + background(255); + // display the balls + b1.move(); + b1.display(); + b2.move(); + b2.display(); + b3.move(); + b3.display(); +} // draw() + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_3/ball.pde b/CodeToAccompany9781430244646/ch06/sketch_6_3/ball.pde new file mode 100644 index 0000000..1f13560 --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_3/ball.pde @@ -0,0 +1,70 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-3: balls in a box + +class ball { // Define the ball class + // Attributes + PVector location; // ball's location + color ballColor; // its color + float radius; // its radius in pixels + PVector speed; // dx and dy + box b; // ball is inside Box, b + + ball(box b) { // Default Constructor + this(random(width), random(height), 25, color(255, 0, 0), b); + } // ball() + ball(float x, float y, float r, color c, box _b ) { + location = new PVector(x, y); // set up ball with position (x, y), radius r, color c + radius = r; // radius, r pixels + ballColor = c; // color, c + // speed at which the ball travels + speed = new PVector(random(1, 3), random(1, 3)); + // Its enclosing box + b = _b; + } // ball() + // Behaviors... + void display() { + // display the ball + // set color attributes + noStroke(); + fill(ballColor); + // draw the ball + ellipse(location.x, location.y, 2*radius, 2*radius); + } // display() + +void move() { + location.add(speed); + bounce(); + } // move() + void bounce() { + if (location.x > (b.w-radius)) { // bounce against the right edge + location.x = b.h-radius; + speed.x = -speed.x; + } + if (location.x < radius) { // bounce against the left edge + location.x = radius; + speed.x = -speed.x; + } + if (location.y > (b.h-radius)) { // bounce against the bottm edge + location.y = b.h-radius; + speed.y = -speed.y; + } + if (location.y < radius) { // bounce against the top edge + location.y = radius; + speed.y = -speed.y; + } + } // bounce() + +} // class ball + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_3/box.pde b/CodeToAccompany9781430244646/ch06/sketch_6_3/box.pde new file mode 100644 index 0000000..a7bf1e8 --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_3/box.pde @@ -0,0 +1,55 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-3: balls in a box + +class box { + float x, y, w, h; // top left corner (x, y), width (w), height (h) + int nBalls; // # of balls in the box + int ballRadius = 2; + ball [] balls; // place to store all the balls in this box + +// Constructor + box(float x, float y, float w, float h, int n) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + this.nBalls = n; + // Create balls... + balls = new ball[nBalls]; + for (int i=0; i < balls.length; i++) { + balls[i] = new ball(w/2, h/2, ballRadius, color(0), this); + } + } // box() + void display() { + // draw box + pushMatrix(); + translate(x, y); + stroke(0); + fill(255); + rect(0, 0, w, h); + // draw balls + for (int i=0; i < balls.length; i++) { + balls[i].display(); + } + popMatrix(); + } // display() + void update() { + // move each ball... + for (int i=0; i < balls.length; i++) { + balls[i].move(); + } + } // update +} // class box + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_3/sketch_6_3.pde b/CodeToAccompany9781430244646/ch06/sketch_6_3/sketch_6_3.pde new file mode 100644 index 0000000..781f8bc --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_3/sketch_6_3.pde @@ -0,0 +1,28 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-3: balls in a box +box b; +void setup() { + size(400, 400); + smooth(); + // Create a 200*200 box with 50 balls + b = new box(100, 100, 200, 200, 50); +} // setup() +void draw() { + background(255); + // display the balls + b.update(); + b.display(); +} // draw() + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_4/ball.pde b/CodeToAccompany9781430244646/ch06/sketch_6_4/ball.pde new file mode 100644 index 0000000..ef1760b --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_4/ball.pde @@ -0,0 +1,68 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-4: Two balls and a stick + +class ball { // Define the ball class + // Attributes + PVector location; // ball's location + color ballColor; // its color + float radius; // its radius in pixels + PVector speed; // dx and dy + + ball() { // Default Constructor + this(random(width), random(height), 10, color(255, 0, 0)); + } // ball() + + ball(float x, float y, float r, color c) { + location = new PVector(x, y); // set up ball with position (x, y), radius r, color c + radius = r; // radius, r pixels + ballColor = c; // color, c + // speed at which the ball travels + speed = new PVector(random(1, 3), random(1, 3)); + } // ball() + // Behaviors... + void display() { + // display the ball + // set color attributes + noStroke(); + fill(ballColor); + // draw the ball + ellipse(location.x, location.y, 2*radius, 2*radius); + } // display() + +void move() { + location.add(speed); + bounce(); + } // move() + void bounce() { + if (location.x > (width-radius)) { // bounce against the right edge + location.x = width-radius; + speed.x = -speed.x; + } + if (location.x < radius) { // bounce against the left edge + location.x = radius; + speed.x = -speed.x; + } + if (location.y > (height-radius)) { // bounce against the bottm edge + location.y = height-radius; + speed.y = -speed.y; + } + if (location.y < radius) { // bounce against the top edge + location.y = radius; + speed.y = -speed.y; + } + } // bounce() + +} // class ball + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_4/sketch_6_4.pde b/CodeToAccompany9781430244646/ch06/sketch_6_4/sketch_6_4.pde new file mode 100644 index 0000000..b453fd7 --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_4/sketch_6_4.pde @@ -0,0 +1,31 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-4: Two balls and a stick +ball b1, b2; +stick s; +int stickLen = 80; +void setup() { + size(400, 400); + smooth(); + + b1 = new ball(width/2, height/2+stickLen/2, 10, color(0)); + b2 = new ball(width/2, height/2+stickLen, 10, color(0)); + s = new stick(b1, b2); +} // setup() +void draw() { + background(255); + s.update(); + s.display(); +} // draw() + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_4/stick.pde b/CodeToAccompany9781430244646/ch06/sketch_6_4/stick.pde new file mode 100644 index 0000000..159ef3e --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_4/stick.pde @@ -0,0 +1,54 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-4: Two balls and a stick + +class stick { + ball b1, b2; // the two balls + float r; // the length of the stick + stick(ball b1, ball b2) { + this.b1 = b1; + this.b2 = b2; + // Compute the length of the stick + // Same as the initial distance between the two balls + r = b1.location.dist(b2.location); + } //stick + void display() { + // first display the balls + b1.display(); + b2.display(); + // display the stick + stroke(255, 0, 0); + strokeWeight(5); + line(b1.location.x, b1.location.y, b2.location.x, b2.location.y); + } // display() + + void update() { + b1.move(); + b2.move(); + constrainLength(); + } // update() + + void constrainLength(){ + float k = 0.1 ; + PVector delta = PVector.sub(b2.location, b1.location); + float deltaLength = delta.mag(); + float d = ((deltaLength - r) / deltaLength); + b1.location.x += delta.x * k * d/2; + b1.location.y += delta.y * k * d/2; + b2.location.x -= delta.x * k * d/2; + b2.location.y -= delta.y * k * d/2; + } // constrainLength + +} // class stick + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_5/ball.pde b/CodeToAccompany9781430244646/ch06/sketch_6_5/ball.pde new file mode 100644 index 0000000..7c4266f --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_5/ball.pde @@ -0,0 +1,67 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-5: ball and stick chain + +class ball { // Define the ball class + // Attributes + PVector location; // ball's location + color ballColor; // its color + float radius; // its radius in pixels + PVector speed; // dx and dy + + ball() { // Default Constructor + this(random(width), random(height), 10, color(255, 0, 0)); + } // ball() + + ball(float x, float y, float r, color c) { + location = new PVector(x, y); // set up ball with position (x, y), radius r, color c + radius = r; // radius, r pixels + ballColor = c; // color, c + // speed at which the ball travels + speed = new PVector(random(1, 3), random(1, 3)); + } // ball() + // Behaviors... + void display() { + // display the ball + // set color attributes + noStroke(); + fill(ballColor); + // draw the ball + ellipse(location.x, location.y, 2*radius, 2*radius); + } // display() + +void move() { + location.add(speed); + bounce(); + } // move() + void bounce() { + if (location.x > (width-radius)) { // bounce against the right edge + location.x = width-radius; + speed.x = -speed.x; + } + if (location.x < radius) { // bounce against the left edge + location.x = radius; + speed.x = -speed.x; + } + if (location.y > (height-radius)) { // bounce against the bottm edge + location.y = height-radius; + speed.y = -speed.y; + } + if (location.y < radius) { // bounce against the top edge + location.y = radius; + speed.y = -speed.y; + } + } // bounce() + +} // class ball diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_5/sketch_6_5.pde b/CodeToAccompany9781430244646/ch06/sketch_6_5/sketch_6_5.pde new file mode 100644 index 0000000..3a753ab --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_5/sketch_6_5.pde @@ -0,0 +1,44 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-5: ball and stick chain + +ball [] balls; +stick [] sticks; +int stickLen = 80; +int nBalls = 10; +int nSticks = nBalls - 1; +void setup() { + size(400, 400); + smooth(); + // Allocate the ball and stick arrays + balls = new ball[nBalls]; + sticks = new stick[nSticks]; + // create the balls and sticks and link them up + for (int i=0; i < nBalls; i++) { + //PVector p = new PVector(width/2+stickLen*i, height/2); + balls[i] = new ball(width/2+stickLen*i, height/2, 10, color(0)); + if (i > 0) { + sticks[i-1] = new stick(balls[i-1], balls[i]); + } + } +} // setup() +void draw() { + background(255); + // Animate + for (int i=0; i < nSticks; i++) { + sticks[i].update(); + sticks[i].display(); + } +} // draw() + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_5/stick.pde b/CodeToAccompany9781430244646/ch06/sketch_6_5/stick.pde new file mode 100644 index 0000000..3beac0e --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_5/stick.pde @@ -0,0 +1,54 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-5: ball and stick chain + +class stick { + ball b1, b2; // the two balls + float r; // the length of the stick + stick(ball b1, ball b2) { + this.b1 = b1; + this.b2 = b2; + // Compute the length of the stick + // Same as the initial distance between the two balls + r = b1.location.dist(b2.location); + } //stick + void display() { + // first display the balls + b1.display(); + b2.display(); + // display the stick + stroke(255, 0, 0); + strokeWeight(5); + line(b1.location.x, b1.location.y, b2.location.x, b2.location.y); + } // display() + + void update() { + b1.move(); + b2.move(); + constrainLength(); + } // update() + + void constrainLength(){ + float k = 0.1 ; + PVector delta = PVector.sub(b2.location, b1.location); + float deltaLength = delta.mag(); + float d = ((deltaLength - r) / deltaLength); + b1.location.x += delta.x * k * d/2; + b1.location.y += delta.y * k * d/2; + b2.location.x -= delta.x * k * d/2; + b2.location.y -= delta.y * k * d/2; + } // constrainLength + +} // class stick + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_6/disc.pde b/CodeToAccompany9781430244646/ch06/sketch_6_6/disc.pde new file mode 100644 index 0000000..d4d7634 --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_6/disc.pde @@ -0,0 +1,59 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-6: widgets, discs, and hexagons + +class disc extends widget { + // A disc is a circular shape + float r; + PVector speed; + disc() { + this(new PVector(random(width), random(height)), 30, color(0)); + } // disc() + disc(PVector loc, float s, color c) { + super(loc, s, c); + r = sz/2; + speed = new PVector(random(1, 3), random(1, 3)); + } // disc() + void display() { + noStroke(); + fill(col); + ellipse(location.x, location.y, sz, sz); + } // display() + void setSpeed(PVector s) { + speed = s; + } // setSpeed() + void move() { + location.add(speed); + bounce(); + } // move() + void bounce() { + if (location.x > (width-r)) { // bounce against the right edge + location.x = width-r; + speed.x = -speed.x; + } + if (location.x < r) { // bounce against the left edge + location.x = r; + speed.x = -speed.x; + } + if (location.y > (height-r)) { // bounce against the bottm edge + location.y = height-r; + speed.y = -speed.y; + } + if (location.y < r) { // bounce against the top edge + location.y = r; + speed.y = -speed.y; + } + } // bounce() +} // class disc + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_6/hexagon.pde b/CodeToAccompany9781430244646/ch06/sketch_6_6/hexagon.pde new file mode 100644 index 0000000..083ddcb --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_6/hexagon.pde @@ -0,0 +1,88 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-6: widgets, discs, and hexagons + +class hexagon extends widget { + + int nSides = 6; + float r; + float rot; + PVector speed; + + hexagon() { + this(new PVector(random(width), random(height)), 30, color(0)); + } // hexagon() + + hexagon(PVector loc, float s, color c) { + super(loc, s, c); + r = sz/2; + rot = 0; + speed = new PVector(random(-2, 2), random(-2, 2)); + } // hexagon() + void setSpeed(PVector s) { + s.mult(-2); + speed = s; + } // setSpeed() + + void display() { + + float x1, y1; + float theta = rot; + + noStroke(); + fill(col); + + beginShape(); + + for (int i = 0; i (width-r)) { // bounce against the right edge + location.x = width-r; + speed.x = -speed.x; + } + if (location.x < r) { // bounce against the left edge + location.x = r; + speed.x = -speed.x; + } + if (location.y > (height-r)) { // bounce against the bottm edge + location.y = height-r; + speed.y = -speed.y; + } + if (location.y < r) { // bounce against the top edge + location.y = r; + speed.y = -speed.y; + } + } // bounce() +// +// boolean clicked() { +// PVector m = new PVector(mouseX, mouseY); +// return (PVector.dist(location, m) < r); +// } //clicked() +} // class hexagon + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_6/sketch_6_6.pde b/CodeToAccompany9781430244646/ch06/sketch_6_6/sketch_6_6.pde new file mode 100644 index 0000000..67a53a0 --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_6/sketch_6_6.pde @@ -0,0 +1,31 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-6: widgets, discs, and hexagons + +disc d; +hexagon h; +void setup() { + size(500, 500); + smooth(); + d = new disc(); + h = new hexagon(); +} // setup() +void draw() { + background(255); + d.move(); + d.display(); + h.move(); + h.display(); +} // draw() + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_6/widget.pde b/CodeToAccompany9781430244646/ch06/sketch_6_6/widget.pde new file mode 100644 index 0000000..39fd3fe --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_6/widget.pde @@ -0,0 +1,37 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-6: widgets, discs, and hexagons + +abstract class widget { + // Every shape has a x-, y- location, size, and color + PVector location; + float sz; + color col; + widget() { + this(new PVector(random(width), random(height)), 30, color(0)); + } // widget() + + widget(PVector loc, float s, color c) { + location = loc; + sz = s; + col = c; + } // widget() + // Every shape can be displayed + abstract void display(); + // Every shape can move + abstract void move(); + // Set the speed at which the widget moves + abstract void setSpeed(PVector s); +} // class widget + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_7/disc.pde b/CodeToAccompany9781430244646/ch06/sketch_6_7/disc.pde new file mode 100644 index 0000000..b9b6929 --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_7/disc.pde @@ -0,0 +1,59 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-7: Several widgets + +class disc extends widget { + // A disc is a circular shape + float r; + PVector speed; + disc() { + this(new PVector(random(width), random(height)), 30, color(0)); + } // disc() + disc(PVector loc, float s, color c) { + super(loc, s, c); + r = sz/2; + speed = new PVector(random(1, 3), random(1, 3)); + } // disc() + void display() { + noStroke(); + fill(col); + ellipse(location.x, location.y, sz, sz); + } // display() + void setSpeed(PVector s) { + speed = s; + } // setSpeed() + void move() { + location.add(speed); + bounce(); + } // move() + void bounce() { + if (location.x > (width-r)) { // bounce against the right edge + location.x = width-r; + speed.x = -speed.x; + } + if (location.x < r) { // bounce against the left edge + location.x = r; + speed.x = -speed.x; + } + if (location.y > (height-r)) { // bounce against the bottm edge + location.y = height-r; + speed.y = -speed.y; + } + if (location.y < r) { // bounce against the top edge + location.y = r; + speed.y = -speed.y; + } + } // bounce() +} // class disc + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_7/hexagon.pde b/CodeToAccompany9781430244646/ch06/sketch_6_7/hexagon.pde new file mode 100644 index 0000000..481b204 --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_7/hexagon.pde @@ -0,0 +1,87 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-7: Several widgets + +class hexagon extends widget { + + int nSides = 6; + float r; + float rot; + PVector speed; + + hexagon() { + this(new PVector(random(width), random(height)), 30, color(0)); + } // hexagon() + + hexagon(PVector loc, float s, color c) { + super(loc, s, c); + r = sz/2; + rot = 0; + speed = new PVector(random(-2, 2), random(-2, 2)); + } // hexagon() + void setSpeed(PVector s) { + s.mult(-2); + speed = s; + } // setSpeed() + + void display() { + + float x1, y1; + float theta = rot; + + noStroke(); + fill(col); + + beginShape(); + + for (int i = 0; i (width-r)) { // bounce against the right edge + location.x = width-r; + speed.x = -speed.x; + } + if (location.x < r) { // bounce against the left edge + location.x = r; + speed.x = -speed.x; + } + if (location.y > (height-r)) { // bounce against the bottm edge + location.y = height-r; + speed.y = -speed.y; + } + if (location.y < r) { // bounce against the top edge + location.y = r; + speed.y = -speed.y; + } + } // bounce() +// +// boolean clicked() { +// PVector m = new PVector(mouseX, mouseY); +// return (PVector.dist(location, m) < r); +// } //clicked() +} // class hexagon diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_7/sketch_6_7.pde b/CodeToAccompany9781430244646/ch06/sketch_6_7/sketch_6_7.pde new file mode 100644 index 0000000..ec20b83 --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_7/sketch_6_7.pde @@ -0,0 +1,40 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-7: Several widgets + +widget [] pieces; +int N = 10; +void setup() { + size(500, 500); + smooth(); + pieces = new widget[N]; + for (int i=0; i < N; i++) { + color c = color(random(50, 200), random(50, 200), random(50, 200)); + switch (int(random(2))) { + case 0: + pieces[i] = new disc(new PVector(random(width), random(height)), 20, c); + break; + default: + pieces[i] = new hexagon(new PVector(width/2, height/2), 40, c); + } + } +} // setup() +void draw() { + background(255); + for (int i=0; i < N; i++) { + pieces[i].move(); + pieces[i].display(); + } +} // draw() + diff --git a/CodeToAccompany9781430244646/ch06/sketch_6_7/widget.pde b/CodeToAccompany9781430244646/ch06/sketch_6_7/widget.pde new file mode 100644 index 0000000..31f7959 --- /dev/null +++ b/CodeToAccompany9781430244646/ch06/sketch_6_7/widget.pde @@ -0,0 +1,36 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 6-7: Several widgets + +abstract class widget { + // Every shape has a x-, y- location, size, and color + PVector location; + float sz; + color col; + widget() { + this(new PVector(random(width), random(height)), 30, color(0)); + } // widget() + + widget(PVector loc, float s, color c) { + location = loc; + sz = s; + col = c; + } // widget() + // Every shape can be displayed + abstract void display(); + // Every shape can move + abstract void move(); + // Set the speed at which the widget moves + abstract void setSpeed(PVector s); +} // class widget diff --git a/CodeToAccompany9781430244646/ch07/Sketch_7_5/Sketch_7_5.pde b/CodeToAccompany9781430244646/ch07/Sketch_7_5/Sketch_7_5.pde new file mode 100644 index 0000000..00f4d49 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/Sketch_7_5/Sketch_7_5.pde @@ -0,0 +1,31 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-5: Displaying Simple Text +String sentence = "A man, a plan, a canal, Panama."; + +void setup() { + size(400, 100); + smooth(); +} // setup() + +void draw() { + background(200); + fill(0); + textSize(24); + text(sentence, 10, height/2); +} // draw() + +void mouseClicked(){ + save("Figure7-1.tif"); +} diff --git a/CodeToAccompany9781430244646/ch07/Sketch_7_8/Sketch_7_8.pde b/CodeToAccompany9781430244646/ch07/Sketch_7_8/Sketch_7_8.pde new file mode 100644 index 0000000..5fddcde --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/Sketch_7_8/Sketch_7_8.pde @@ -0,0 +1,32 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-8: Displaying Simple Text using attributes +String sentence = "A man, a plan, a canal, Panama."; + +void setup() { + size(400, 100); + smooth(); +} // setup() + +void draw() { + background(200); + fill(0); + textSize(24); + text(sentence, 10, height/2); + line(10, height/2, 10+textWidth(sentence), height/2); +} // draw() + +void mouseClicked(){ + save("978-1-4302-4464-6_kumar_Ch07_Figure7-4.tif"); +} diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_1/Data/Obama.txt b/CodeToAccompany9781430244646/ch07/sketch_7_1/Data/Obama.txt new file mode 100644 index 0000000..5dd7b12 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_1/Data/Obama.txt @@ -0,0 +1,239 @@ +Your Majesties, Your Royal Highnesses, Distinguished Members of the Norwegian Nobel Committee, citizens of America, and citizens of the world: + +I receive this honor with deep gratitude and great humility. It is an award that speaks to our highest aspirations - that for all the cruelty +and hardship of our world, we are not mere prisoners of fate. Our actions matter, and can bend history in the direction of justice. + +And yet I would be remiss if I did not acknowledge the considerable controversy that your generous decision has generated. In part, this is +because I am at the beginning, and not the end, of my labors on the world stage. Compared to some of the giants of history who have received +this prize - Schweitzer and King; Marshall and Mandela - my accomplishments are slight. And then there are the men and women around the world +who have been jailed and beaten in the pursuit of justice; those who toil in humanitarian organizations to relieve suffering; the unrecognized +millions whose quiet acts of courage and compassion inspire even the most hardened of cynics. I cannot argue with those who find these men and +women - some known, some obscure to all but those they help - to be far more deserving of this honor than I. + +But perhaps the most profound issue surrounding my receipt of this prize is the fact that I am the Commander-in-Chief of a nation in the midst +of two wars. One of these wars is winding down. The other is a conflict that America did not seek; one in which we are joined by forty three other +countries - including Norway - in an effort to defend ourselves and all nations from further attacks. + +Still, we are at war, and I am responsible for the deployment of thousands of young Americans to battle in a distant land. Some will kill. Some +will be killed. And so I come here with an acute sense of the cost of armed conflict - filled with difficult questions about the relationship +between war and peace, and our effort to replace one with the other. + +These questions are not new. War, in one form or another, appeared with the first man. At the dawn of history, its morality was not questioned; +it was simply a fact, like drought or disease - the manner in which tribes and then civilizations sought power and settled their differences. + + +Over time, as codes of law sought to control violence within groups, so did philosophers, clerics, and statesmen seek to regulate the destructive +power of war. The concept of a "just war" emerged, suggesting that war is justified only when it meets certain preconditions: if it is waged +as a last resort or in self-defense; if the forced used is proportional, and if, whenever possible, civilians are spared from violence. + +For most of history, this concept of just war was rarely observed. The capacity of human beings to think up new ways to kill one another proved +inexhaustible, as did our capacity to exempt from mercy those who look different or pray to a different God. Wars between armies gave way to wars +between nations - total wars in which the distinction between combatant and civilian became blurred. In the span of thirty years, such carnage +would twice engulf this continent. And while it is hard to conceive of a cause more just than the defeat of the Third Reich and the Axis powers, +World War II was a conflict in which the total number of civilians who died exceeded the number of soldiers who perished. + +In the wake of such destruction, and with the advent of the nuclear age, it became clear to victor and vanquished alike that the world needed +institutions to prevent another World War. And so, a quarter century after the United States Senate rejected the League of Nations - an idea for +which Woodrow Wilson received this Prize - America led the world in constructing an architecture to keep the peace: a Marshall Plan and a +United Nations, mechanisms to govern the waging of war, treaties to protect human rights, prevent genocide, and restrict the most dangerous weapons. + +In many ways, these efforts succeeded. Yes, terrible wars have been fought, and atrocities committed. But there has been no Third World War. The Cold +War ended with jubilant crowds dismantling a wall. Commerce has stitched much of the world together. Billions have been lifted from poverty. The ideals +of liberty, self-determination, equality and the rule of law have haltingly advanced. We are the heirs of the fortitude and foresight of generations +past, and it is a legacy for which my own country is rightfully proud. + +A decade into a new century, this old architecture is buckling under the weight of new threats. The world may no longer shudder at the prospect of +war between two nuclear superpowers, but proliferation may increase the risk of catastrophe. Terrorism has long been a tactic, but modern technology +allows a few small men with outsized rage to murder innocents on a horrific scale. + +Moreover, wars between nations have increasingly given way to wars within nations. The resurgence of ethnic or sectarian conflicts; the growth +of secessionist movements, insurgencies, and failed states; have increasingly trapped civilians in unending chaos. In today's wars, many more +civilians are killed than soldiers; the seeds of future conflict are sewn, economies are wrecked, civil societies torn asunder, refugees +amassed, and children scarred. + +I do not bring with me today a definitive solution to the problems of war. What I do know is that meeting these challenges will require +the same vision, hard work, and persistence of those men and women who acted so boldly decades ago. And it will require us to think in +new ways about the notions of just war and the imperatives of a just peace. + +We must begin by acknowledging the hard truth that we will not eradicate violent conflict in our lifetimes. There will be times when +nations - acting individually or in concert - will find the use of force not only necessary but morally justified. + +I make this statement mindful of what Martin Luther King said in this same ceremony years ago - "Violence never brings permanent peace. It +solves no social problem: it merely creates new and more complicated ones." As someone who stands here as a direct consequence of Dr. King's +life's work, I am living testimony to the moral force of non-violence. I know there is nothing weak -nothing passive - nothing naïve - in the +creed and lives of Gandhi and King. + +But as a head of state sworn to protect and defend my nation, I cannot be guided by their examples alone. I face the world as it is, and +cannot stand idle in the face of threats to the American people. For make no mistake: evil does exist in the world. A non-violent movement +could not have halted Hitler's armies. Negotiations cannot convince al Qaeda's leaders to lay down their arms. To say that force is sometimes +necessary is not a call to cynicism - it is a recognition of history; the imperfections of man and the limits of reason. + +I raise this point because in many countries there is a deep ambivalence about military action today, no matter the cause. At times, this +is joined by a reflexive suspicion of America, the world's sole military superpower. + +Yet the world must remember that it was not simply international institutions - not just treaties and declarations - that brought stability +to a post-World War II world. Whatever mistakes we have made, the plain fact is this: the United States of America has helped underwrite +global security for more than six decades with the blood of our citizens and the strength of our arms. The service and sacrifice of our +men and women in uniform has promoted peace and prosperity from Germany to Korea, and enabled democracy to take hold in places like the +Balkans. We have borne this burden not because we seek to impose our will. We have done so out of enlightened self-interest - because +we seek a better future for our children and grandchildren, and we believe that their lives will be better if other peoples' children +and grandchildren can live in freedom and prosperity. + +So yes, the instruments of war do have a role to play in preserving the peace. And yet this truth must coexist with another - that +no matter how justified, war promises human tragedy. The soldier's courage and sacrifice is full of glory, expressing devotion to +country, to cause and to comrades in arms. But war itself is never glorious, and we must never trumpet it as such. + +So part of our challenge is reconciling these two seemingly irreconcilable truths - that war is sometimes necessary, and war is at +some level an expression of human feelings. Concretely, we must direct our effort to the task that President Kennedy called for long +ago. "Let us focus," he said, "on a more practical, more attainable peace, based not on a sudden revolution in human nature but +on a gradual evolution in human institutions." + +What might this evolution look like? What might these practical steps be? + +To begin with, I believe that all nations - strong and weak alike - must adhere to standards that govern the use of force. I - like any +head of state - reserve the right to act unilaterally if necessary to defend my nation. Nevertheless, I am convinced that adhering +to standards strengthens those who do, and isolates - and weakens - those who don't. + +The world rallied around America after the 9/11 attacks, and continues to support our efforts in Afghanistan, because of the horror +of those senseless attacks and the recognized principle of self-defense. Likewise, the world recognized the need to confront Saddam +Hussein when he invaded Kuwait - a consensus that sent a clear message to all about the cost of aggression. + +Furthermore, America cannot insist that others follow the rules of the road if we refuse to follow them ourselves. For when we don't, +our action can appear arbitrary, and undercut the legitimacy of future intervention - no matter how justified. + +This becomes particularly important when the purpose of military action extends beyond self defense or the defense of one nation +against an aggressor. More and more, we all confront difficult questions about how to prevent the slaughter of civilians by their +own government, or to stop a civil war whose violence and suffering can engulf an entire region. + +I believe that force can be justified on humanitarian grounds, as it was in the Balkans, or in other places that have been scarred +by war. Inaction tears at our conscience and can lead to more costly intervention later. That is why all responsible nations must +embrace the role that militaries with a clear mandate can play to keep the peace. + +America's commitment to global security will never waiver. But in a world in which threats are more diffuse, and missions more +complex, America cannot act alone. This is true in Afghanistan. This is true in failed states like Somalia, where terrorism and +piracy is joined by famine and human suffering. And sadly, it will continue to be true in unstable regions for years to come. + +The leaders and soldiers of NATO countries - and other friends and allies - demonstrate this truth through the capacity and courage +they have shown in Afghanistan. But in many countries, there is a disconnect between the efforts of those who serve and the ambivalence +of the broader public. I understand why war is not popular. But I also know this: the belief that peace is desirable is rarely enough to achieve it. Peace requires responsibility. Peace entails sacrifice. That is why NATO continues to be indispensable. That is why we must strengthen UN and regional peacekeeping, and not leave the task to a few countries. That is why we honor those who return home from peacekeeping and training abroad to Oslo and Rome; to Ottawa and Sydney; to Dhaka and Kigali - we honor them not as makers of war, but as wagers of peace. + +Let me make one final point about the use of force. Even as we make difficult decisions about going to war, we must also think clearly +about how we fight it. The Nobel Committee recognized this truth in awarding its first prize for peace to Henry Dunant - the founder +of the Red Cross, and a driving force behind the Geneva Conventions. + +Where force is necessary, we have a moral and strategic interest in binding ourselves to certain rules of conduct. And even as we +confront a vicious adversary that abides by no rules, I believe that the United States of America must remain a standard bearer in +the conduct of war. That is what makes us different from those whom we fight. That is a source of our strength. That is why I +prohibited torture. That is why I ordered the prison at Guantanamo Bay closed. And that is why I have reaffirmed America's +commitment to abide by the Geneva Conventions. We lose ourselves when we compromise the very ideals that we fight to defend. +And we honor those ideals by upholding them not just when it is easy, but when it is hard. + +I have spoken to the questions that must weigh on our minds and our hearts as we choose to wage war. But let me turn now to +our effort to avoid such tragic choices, and speak of three ways that we can build a just and lasting peace. + +First, in dealing with those nations that break rules and laws, I believe that we must develop alternatives to violence that +are tough enough to change behavior - for if we want a lasting peace, then the words of the international community must mean +something. Those regimes that break the rules must be held accountable. Sanctions must exact a real price. Intransigence must +be met with increased pressure - and such pressure exists only when the world stands together as one. + +One urgent example is the effort to prevent the spread of nuclear weapons, and to seek a world without them. In the middle of +the last century, nations agreed to be bound by a treaty whose bargain is clear: all will have access to peaceful nuclear power; +those without nuclear weapons will forsake them; and those with nuclear weapons will work toward disarmament. I am committed to +upholding this treaty. It is a centerpiece of my foreign policy. And I am working with President Medvedev to reduce America a +nd Russia's nuclear stockpiles. + +But it is also incumbent upon all of us to insist that nations like Iran and North Korea do not game the system. Those who +claim to respect international law cannot avert their eyes when those laws are flouted. Those who care for their own security +cannot ignore the danger of an arms race in the Middle East or East Asia. Those who seek peace cannot stand idly by as nations +arm themselves for nuclear war. + +The same principle applies to those who violate international law by brutalizing their own people. When there is genocide in +Darfur; systematic rape in Congo; or repression in Burma - there must be consequences. And the closer we stand together, the +less likely we will be faced with the choice between armed intervention and complicity in oppression. + +This brings me to a second point - the nature of the peace that we seek. For peace is not merely the absence of visible conflict. +Only a just peace based upon the inherent rights and dignity of every individual can truly be lasting. + +It was this insight that drove drafters of the Universal Declaration of Human Rights after the Second World War. In the wake of +devastation, they recognized that if human rights are not protected, peace is a hollow promise. + +And yet all too often, these words are ignored. In some countries, the failure to uphold human rights is excused by the false +suggestion that these are Western principles, foreign to local cultures or stages of a nation's development. And within America, +there has long been a tension between those who describe themselves as realists or idealists - a tension that suggests a stark +choice between the narrow pursuit of interests or an endless campaign to impose our values. + +I reject this choice. I believe that peace is unstable where citizens are denied the right to speak freely or worship as they +please; choose their own leaders or assemble without fear. Pent up grievances fester, and the suppression of tribal and religious +identity can lead to violence. We also know that the opposite is true. Only when Europe became free did it finally find peace. +America has never fought a war against a democracy, and our closest friends are governments that protect the rights of their +citizens. No matter how callously defined, neither America's interests - nor the world's -are served by the denial of human aspirations. + +So even as we respect the unique culture and traditions of different countries, America will always be a voice for those aspirations +that are universal. We will bear witness to the quiet dignity of reformers like Aung Sang Suu Kyi; to the bravery of Zimbabweans who +cast their ballots in the face of beatings; to the hundreds of thousands who have marched silently through the streets of Iran. It is +telling that the leaders of these governments fear the aspirations of their own people more than the power of any other nation. And +it is the responsibility of all free people and free nations to make clear to these movements that hope and history are on their side + +Let me also say this: the promotion of human rights cannot be about exhortation alone. At times, it must be coupled with painstaking +diplomacy. I know that engagement with repressive regimes lacks the satisfying purity of indignation. But I also know that sanctions +without outreach - and condemnation without discussion - can carry forward a crippling status quo. No repressive regime can move down +a new path unless it has the choice of an open door. + +In light of the Cultural Revolution's horrors, Nixon's meeting with Mao appeared inexcusable - and yet it surely helped set China on +a path where millions of its citizens have been lifted from poverty, and connected to open societies. Pope John Paul's engagement +with Poland created space not just for the Catholic Church, but for labor leaders like Lech Walesa. Ronald Reagan's efforts on arms control and embrace of perestroika not only improved relations with the Soviet Union, but empowered dissidents throughout Eastern Europe. There is no simple formula here. But we must try as best we can to balance isolation and engagement; pressure and incentives, so that human rights and dignity are advanced over time. + +Third, a just peace includes not only civil and political rights - it must encompass economic security and opportunity. For true +peace is not just freedom from fear, but freedom from want. + +It is undoubtedly true that development rarely takes root without security; it is also true that security does not exist where +human beings do not have access to enough food, or clean water, or the medicine they need to survive. It does not exist where +children cannot aspire to a decent education or a job that supports a family. The absence of hope can rot a society from within. + +And that is why helping farmers feed their own people - or nations educate their children and care for the sick - is not mere +charity. It is also why the world must come together to confront climate change. There is little scientific dispute that if we +do nothing, we will face more drought, famine and mass displacement that will fuel more conflict for decades. For this reason, it is not merely scientists and activists who call for swift and forceful action - it is military leaders in my country and others who understand that our common security hangs in the balance. + +Agreements among nations. Strong institutions. Support for human rights. Investments in development. All of these are vital +ingredients in bringing about the evolution that President Kennedy spoke about. And yet, I do not believe that we will have the will, +or the staying power, to complete this work without something more - and that is the continued expansion of our moral imagination; +an insistence that there is something irreducible that we all share. + +As the world grows smaller, you might think it would be easier for human beings to recognize how similar we are; to understand that +we all basically want the same things; that we all hope for the chance to live out our lives with some measure of happiness and +fulfillment for ourselves and our families. + +And yet, given the dizzying pace of globalization, and the cultural leveling of modernity, it should come as no surprise that people +fear the loss of what they cherish about their particular identities - their race, their tribe, and perhaps most powerfully their +religion. In some places, this fear has led to conflict. At times, it even feels like we are moving backwards. We see it in Middle +East, as the conflict between Arabs and Jews seems to harden. We see it in nations that are torn asunder by tribal lines. + +Most dangerously, we see it in the way that religion is used to justify the murder of innocents by those who have distorted and +defiled the great religion of Islam, and who attacked my country from Afghanistan. These extremists are not the first to kill in +the name of God; the cruelties of the Crusades are amply recorded. But they remind us that no Holy War can ever be a just war. For if you truly believe that you are carrying out divine will, then there is no need for restraint - no need to spare the pregnant mother, or the medic, or even a person of one's own faith. Such a warped view of religion is not just incompatible with the concept of peace, but the purpose of faith - for the one rule that lies at the heart of every major religion is that we do unto others as we would have them do unto us. + +Adhering to this law of love has always been the core struggle of human nature. We are fallible. We make mistakes, and fall +victim to the temptations of pride, and power, and sometimes evil. Even those of us with the best intentions will at times +fail to right the wrongs before us. + +But we do not have to think that human nature is perfect for us to still believe that the human condition can be perfected. +We do not have to live in an idealized world to still reach for those ideals that will make it a better place. The non-violence +practiced by men like Gandhi and King may not have been practical or possible in every circumstance, but the love that they preached - +their faith in human progress - must always be the North Star that guides us on our journey. + +For if we lose that faith - if we dismiss it as silly or naïve; if we divorce it from the decisions that we make on issues of war +and peace - then we lose what is best about humanity. We lose our sense of possibility. We lose our moral compass. + +Like generations have before us, we must reject that future. As Dr. King said at this occasion so many years ago, "I refuse to +accept despair as the final response to the ambiguities of history. I refuse to accept the idea that the 'isness' of man's present +nature makes him morally incapable of reaching up for the eternal 'oughtness' that forever confronts him." + +So let us reach for the world that ought to be - that spark of the divine that still stirs within each of our souls. Somewhere +today, in the here and now, a soldier sees he's outgunned but stands firm to keep the peace. Somewhere today, in this world, +a young protestor awaits the brutality of her government, but has the courage to march on. Somewhere today, a mother facing +punishing poverty still takes the time to teach her child, who believes that a cruel world still has a place for his dreams. + +Let us live by their example. We can acknowledge that oppression will always be with us, and still strive for justice. We +can admit the intractability of depravation, and still strive for dignity. We can understand that there will be war, and +still strive for peace. We can do that - for that is the story of human progress; that is the hope of all the world; and +at this moment of challenge, that must be our work here on Earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_1/Data/gettysburg.txt b/CodeToAccompany9781430244646/ch07/sketch_7_1/Data/gettysburg.txt new file mode 100644 index 0000000..1d9643e --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_1/Data/gettysburg.txt @@ -0,0 +1,22 @@ +Four score and seven years ago our fathers brought forth on this continent, a +new nation, conceived in Liberty, and dedicated to the proposition that all men +are created equal. + +Now we are engaged in a great civil war, testing whether that nation, or any +nation so conceived and so dedicated, can long endure. We are met on a great +battle-field of that war. We have come to dedicate a portion of that field, as a +final resting place for those who here gave their lives that that nation might +live. It is altogether fitting and proper that we should do this. + +But, in a larger sense, we can not dedicate -- we can not consecrate -- we can not +hallow -- this ground. The brave men, living and dead, who struggled here, have +consecrated it, far above our poor power to add or detract. The world will +little note, nor long remember what we say here, but it can never forget what +they did here. It is for us the living, rather, to be dedicated here to the +unfinished work which they who fought here have thus far so nobly advanced. It +is rather for us to be here dedicated to the great task remaining before us -- +that from these honored dead we take increased devotion to that cause for +which they gave the last full measure of devotion -- that we here highly resolve +that these dead shall not have died in vain -- that this nation, under God, shall +have a new birth of freedom -- and that government of the people, by the people, +for the people, shall not perish from the earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_1/Data/stopwords.txt b/CodeToAccompany9781430244646/ch07/sketch_7_1/Data/stopwords.txt new file mode 100644 index 0000000..0a1f0d2 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_1/Data/stopwords.txt @@ -0,0 +1,667 @@ +AT +A +a +able +about +above +abst +accordance +according +accordingly +across +act +actually +added +adj +adopted +affected +affecting +affects +after +afterwards +again +against +ah +al +all +almost +alone +along +already +also +although +always +am +among +amongst +an +and +announce +another +any +anybody +anyhow +anymore +anyone +anything +anyway +anyways +anywhere +apparently +approximately +are +aren +arent +arise +around +as +aside +ask +asking +at +auth +available +away +awfully +b +back +be +became +because +become +becomes +becoming +been +before +beforehand +begin +beginning +beginnings +begins +behind +being +believe +below +beside +besides +between +beyond +biol +both +brief +briefly +but +But +by +c +ca +came +can +cannot +cause +causes +certain +certainly +co +com +come +comes +contain +containing +contains +could +couldnt +d +date +did +didn +different +do +does +doesn +doing +done +don +down +downwards +due +during +e +each +ed +edu +effect +eg +eight +eighty +either +else +elsewhere +end +ending +enough +especially +et +etc +even +ever +every +everybody +everyone +everything +everywhere +ex +except +f +far +few +ff +fifth +first +five +fix +followed +following +follows +for +former +formerly +forth +found +four +from +further +furthermore +g +gave +get +gets +getting +give +given +gives +giving +go +goes +gone +got +gotten +h +had +happens +hardly +has +hasn +have +haven +having +he +hed +hence +her +here +hereafter +hereby +herein +heres +hereupon +hers +herself +hes +hi +hid +him +himself +his +hither +home +how +howbeit +however +hundred +i +id +ie +if +im +immediate +immediately +importance +important +in +In +inc +indeed +index +information +instead +into +invention +inward +is +isn +it +It +itd +its +itself +j +just +k +keep +keeps +kept +keys +kg +km +know +known +knows +l +largely +last +lately +later +latter +latterly +least +less +lest +let +lets +like +liked +likely +line +little +look +looking +looks +ltd +m +made +mainly +make +makes +many +may +maybe +me +mean +means +meantime +meanwhile +merely +mg +might +million +miss +ml +more +moreover +most +mostly +mr +mrs +much +mug +must +my +myself +n +na +name +namely +nay +nd +near +nearly +necessarily +necessary +need +needs +neither +never +nevertheless +new +next +nine +ninety +no +nobody +non +none +nonetheless +noone +nor +normally +nos +not +noted +nothing +now +nowhere +o +obtain +obtained +obviously +of +off +often +oh +ok +okay +old +omitted +on +once +one +ones +only +onto +or +ord +other +others +otherwise +ought +our +Our +ours +ourselves +out +outside +over +overall +owing +own +p +page +pages +part +particular +particularly +past +per +perhaps +placed +please +plus +poorly +possible +possibly +potentially +pp +predominantly +present +previously +primarily +probably +promptly +proud +provides +put +q +que +quickly +quite +qv +r +ran +rather +rd +re +readily +really +recent +recently +ref +refs +regarding +regardless +regards +related +relatively +research +respectively +resulted +resulting +results +right +run +s +said +same +saw +say +saying +says +sec +section +see +seeing +seem +seemed +seeming +seems +seen +self +selves +sent +seven +several +shall +she +shed +shes +should +shouldn +show +showed +shown +showns +shows +significant +significantly +similar +similarly +since +six +slightly +so +So +some +somebody +somehow +someone +somethan +something +sometime +sometimes +somewhat +somewhere +soon +sorry +specifically +specified +specify +specifying +state +states +still +stop +strongly +sub +substantially +successfully +such +sufficiently +suggest +sup +sure +t +take +taken +taking +tell +tends +th +than +thank +thanks +thanx +that +thats +the +their +Their +theirs +them +themselves +then +thence +there +There +thereafter +thereby +thered +therefore +therein +thereof +therere +theres +thereto +thereupon +these +They +These +they +theyd +theyre +think +this +This +those +Those +thou +though +thoughh +thousand +throug +through +throughout +thru +thus +til +tip +to +together +too +took +toward +towards +tried +tries +truly +try +trying +ts +twice +two +u +un +under +unfortunately +unless +unlike +unlikely +until +unto +up +upon +ups +us +use +used +useful +usefully +usefulness +uses +using +usually +v +value +various +ve +very +via +viz +vol +vols +vs +w +want +wants +was +wasn +way +we +wed +welcom +went +were +weren +what +whatever +whats +when +whence +whenever +where +whereafter +whereas +whereby +wherein +wheres +whereupon +wherever +whether +which +while +whim +whither +who +whod +whoever +whole +whom +whomever +whos +whose +why +widely +will +willing +wish +with +within +without +words +world +would +wouldn +www +x +y +yes +yet +you +youd +your +Your +youre +yours +yourself +yourselves +z +zero \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_1/sketch_7_1.pde b/CodeToAccompany9781430244646/ch07/sketch_7_1/sketch_7_1.pde new file mode 100644 index 0000000..85fa9d6 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_1/sketch_7_1.pde @@ -0,0 +1,29 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-1: Parsing an input text file +String inputTextFile = "Obama.txt"; +String [] fileContents; +String rawText; +String tokens[]; +String delimiters = " ,./?<>;:'\"[{]}\\|=+-_()*&^%$#@!~"; +// Input and parse text file +fileContents = loadStrings(inputTextFile); +rawText = join(fileContents, " "); +rawText = rawText.toLowerCase(); +tokens = splitTokens(rawText, delimiters); +// print out the list of tokens +println(tokens.length+" tokens found in file: "+inputTextFile); +for (int i=0; i < 50 ; i++) { + println(tokens[i]); +} diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10/Data/Obama.txt b/CodeToAccompany9781430244646/ch07/sketch_7_10/Data/Obama.txt new file mode 100644 index 0000000..5dd7b12 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10/Data/Obama.txt @@ -0,0 +1,239 @@ +Your Majesties, Your Royal Highnesses, Distinguished Members of the Norwegian Nobel Committee, citizens of America, and citizens of the world: + +I receive this honor with deep gratitude and great humility. It is an award that speaks to our highest aspirations - that for all the cruelty +and hardship of our world, we are not mere prisoners of fate. Our actions matter, and can bend history in the direction of justice. + +And yet I would be remiss if I did not acknowledge the considerable controversy that your generous decision has generated. In part, this is +because I am at the beginning, and not the end, of my labors on the world stage. Compared to some of the giants of history who have received +this prize - Schweitzer and King; Marshall and Mandela - my accomplishments are slight. And then there are the men and women around the world +who have been jailed and beaten in the pursuit of justice; those who toil in humanitarian organizations to relieve suffering; the unrecognized +millions whose quiet acts of courage and compassion inspire even the most hardened of cynics. I cannot argue with those who find these men and +women - some known, some obscure to all but those they help - to be far more deserving of this honor than I. + +But perhaps the most profound issue surrounding my receipt of this prize is the fact that I am the Commander-in-Chief of a nation in the midst +of two wars. One of these wars is winding down. The other is a conflict that America did not seek; one in which we are joined by forty three other +countries - including Norway - in an effort to defend ourselves and all nations from further attacks. + +Still, we are at war, and I am responsible for the deployment of thousands of young Americans to battle in a distant land. Some will kill. Some +will be killed. And so I come here with an acute sense of the cost of armed conflict - filled with difficult questions about the relationship +between war and peace, and our effort to replace one with the other. + +These questions are not new. War, in one form or another, appeared with the first man. At the dawn of history, its morality was not questioned; +it was simply a fact, like drought or disease - the manner in which tribes and then civilizations sought power and settled their differences. + + +Over time, as codes of law sought to control violence within groups, so did philosophers, clerics, and statesmen seek to regulate the destructive +power of war. The concept of a "just war" emerged, suggesting that war is justified only when it meets certain preconditions: if it is waged +as a last resort or in self-defense; if the forced used is proportional, and if, whenever possible, civilians are spared from violence. + +For most of history, this concept of just war was rarely observed. The capacity of human beings to think up new ways to kill one another proved +inexhaustible, as did our capacity to exempt from mercy those who look different or pray to a different God. Wars between armies gave way to wars +between nations - total wars in which the distinction between combatant and civilian became blurred. In the span of thirty years, such carnage +would twice engulf this continent. And while it is hard to conceive of a cause more just than the defeat of the Third Reich and the Axis powers, +World War II was a conflict in which the total number of civilians who died exceeded the number of soldiers who perished. + +In the wake of such destruction, and with the advent of the nuclear age, it became clear to victor and vanquished alike that the world needed +institutions to prevent another World War. And so, a quarter century after the United States Senate rejected the League of Nations - an idea for +which Woodrow Wilson received this Prize - America led the world in constructing an architecture to keep the peace: a Marshall Plan and a +United Nations, mechanisms to govern the waging of war, treaties to protect human rights, prevent genocide, and restrict the most dangerous weapons. + +In many ways, these efforts succeeded. Yes, terrible wars have been fought, and atrocities committed. But there has been no Third World War. The Cold +War ended with jubilant crowds dismantling a wall. Commerce has stitched much of the world together. Billions have been lifted from poverty. The ideals +of liberty, self-determination, equality and the rule of law have haltingly advanced. We are the heirs of the fortitude and foresight of generations +past, and it is a legacy for which my own country is rightfully proud. + +A decade into a new century, this old architecture is buckling under the weight of new threats. The world may no longer shudder at the prospect of +war between two nuclear superpowers, but proliferation may increase the risk of catastrophe. Terrorism has long been a tactic, but modern technology +allows a few small men with outsized rage to murder innocents on a horrific scale. + +Moreover, wars between nations have increasingly given way to wars within nations. The resurgence of ethnic or sectarian conflicts; the growth +of secessionist movements, insurgencies, and failed states; have increasingly trapped civilians in unending chaos. In today's wars, many more +civilians are killed than soldiers; the seeds of future conflict are sewn, economies are wrecked, civil societies torn asunder, refugees +amassed, and children scarred. + +I do not bring with me today a definitive solution to the problems of war. What I do know is that meeting these challenges will require +the same vision, hard work, and persistence of those men and women who acted so boldly decades ago. And it will require us to think in +new ways about the notions of just war and the imperatives of a just peace. + +We must begin by acknowledging the hard truth that we will not eradicate violent conflict in our lifetimes. There will be times when +nations - acting individually or in concert - will find the use of force not only necessary but morally justified. + +I make this statement mindful of what Martin Luther King said in this same ceremony years ago - "Violence never brings permanent peace. It +solves no social problem: it merely creates new and more complicated ones." As someone who stands here as a direct consequence of Dr. King's +life's work, I am living testimony to the moral force of non-violence. I know there is nothing weak -nothing passive - nothing naïve - in the +creed and lives of Gandhi and King. + +But as a head of state sworn to protect and defend my nation, I cannot be guided by their examples alone. I face the world as it is, and +cannot stand idle in the face of threats to the American people. For make no mistake: evil does exist in the world. A non-violent movement +could not have halted Hitler's armies. Negotiations cannot convince al Qaeda's leaders to lay down their arms. To say that force is sometimes +necessary is not a call to cynicism - it is a recognition of history; the imperfections of man and the limits of reason. + +I raise this point because in many countries there is a deep ambivalence about military action today, no matter the cause. At times, this +is joined by a reflexive suspicion of America, the world's sole military superpower. + +Yet the world must remember that it was not simply international institutions - not just treaties and declarations - that brought stability +to a post-World War II world. Whatever mistakes we have made, the plain fact is this: the United States of America has helped underwrite +global security for more than six decades with the blood of our citizens and the strength of our arms. The service and sacrifice of our +men and women in uniform has promoted peace and prosperity from Germany to Korea, and enabled democracy to take hold in places like the +Balkans. We have borne this burden not because we seek to impose our will. We have done so out of enlightened self-interest - because +we seek a better future for our children and grandchildren, and we believe that their lives will be better if other peoples' children +and grandchildren can live in freedom and prosperity. + +So yes, the instruments of war do have a role to play in preserving the peace. And yet this truth must coexist with another - that +no matter how justified, war promises human tragedy. The soldier's courage and sacrifice is full of glory, expressing devotion to +country, to cause and to comrades in arms. But war itself is never glorious, and we must never trumpet it as such. + +So part of our challenge is reconciling these two seemingly irreconcilable truths - that war is sometimes necessary, and war is at +some level an expression of human feelings. Concretely, we must direct our effort to the task that President Kennedy called for long +ago. "Let us focus," he said, "on a more practical, more attainable peace, based not on a sudden revolution in human nature but +on a gradual evolution in human institutions." + +What might this evolution look like? What might these practical steps be? + +To begin with, I believe that all nations - strong and weak alike - must adhere to standards that govern the use of force. I - like any +head of state - reserve the right to act unilaterally if necessary to defend my nation. Nevertheless, I am convinced that adhering +to standards strengthens those who do, and isolates - and weakens - those who don't. + +The world rallied around America after the 9/11 attacks, and continues to support our efforts in Afghanistan, because of the horror +of those senseless attacks and the recognized principle of self-defense. Likewise, the world recognized the need to confront Saddam +Hussein when he invaded Kuwait - a consensus that sent a clear message to all about the cost of aggression. + +Furthermore, America cannot insist that others follow the rules of the road if we refuse to follow them ourselves. For when we don't, +our action can appear arbitrary, and undercut the legitimacy of future intervention - no matter how justified. + +This becomes particularly important when the purpose of military action extends beyond self defense or the defense of one nation +against an aggressor. More and more, we all confront difficult questions about how to prevent the slaughter of civilians by their +own government, or to stop a civil war whose violence and suffering can engulf an entire region. + +I believe that force can be justified on humanitarian grounds, as it was in the Balkans, or in other places that have been scarred +by war. Inaction tears at our conscience and can lead to more costly intervention later. That is why all responsible nations must +embrace the role that militaries with a clear mandate can play to keep the peace. + +America's commitment to global security will never waiver. But in a world in which threats are more diffuse, and missions more +complex, America cannot act alone. This is true in Afghanistan. This is true in failed states like Somalia, where terrorism and +piracy is joined by famine and human suffering. And sadly, it will continue to be true in unstable regions for years to come. + +The leaders and soldiers of NATO countries - and other friends and allies - demonstrate this truth through the capacity and courage +they have shown in Afghanistan. But in many countries, there is a disconnect between the efforts of those who serve and the ambivalence +of the broader public. I understand why war is not popular. But I also know this: the belief that peace is desirable is rarely enough to achieve it. Peace requires responsibility. Peace entails sacrifice. That is why NATO continues to be indispensable. That is why we must strengthen UN and regional peacekeeping, and not leave the task to a few countries. That is why we honor those who return home from peacekeeping and training abroad to Oslo and Rome; to Ottawa and Sydney; to Dhaka and Kigali - we honor them not as makers of war, but as wagers of peace. + +Let me make one final point about the use of force. Even as we make difficult decisions about going to war, we must also think clearly +about how we fight it. The Nobel Committee recognized this truth in awarding its first prize for peace to Henry Dunant - the founder +of the Red Cross, and a driving force behind the Geneva Conventions. + +Where force is necessary, we have a moral and strategic interest in binding ourselves to certain rules of conduct. And even as we +confront a vicious adversary that abides by no rules, I believe that the United States of America must remain a standard bearer in +the conduct of war. That is what makes us different from those whom we fight. That is a source of our strength. That is why I +prohibited torture. That is why I ordered the prison at Guantanamo Bay closed. And that is why I have reaffirmed America's +commitment to abide by the Geneva Conventions. We lose ourselves when we compromise the very ideals that we fight to defend. +And we honor those ideals by upholding them not just when it is easy, but when it is hard. + +I have spoken to the questions that must weigh on our minds and our hearts as we choose to wage war. But let me turn now to +our effort to avoid such tragic choices, and speak of three ways that we can build a just and lasting peace. + +First, in dealing with those nations that break rules and laws, I believe that we must develop alternatives to violence that +are tough enough to change behavior - for if we want a lasting peace, then the words of the international community must mean +something. Those regimes that break the rules must be held accountable. Sanctions must exact a real price. Intransigence must +be met with increased pressure - and such pressure exists only when the world stands together as one. + +One urgent example is the effort to prevent the spread of nuclear weapons, and to seek a world without them. In the middle of +the last century, nations agreed to be bound by a treaty whose bargain is clear: all will have access to peaceful nuclear power; +those without nuclear weapons will forsake them; and those with nuclear weapons will work toward disarmament. I am committed to +upholding this treaty. It is a centerpiece of my foreign policy. And I am working with President Medvedev to reduce America a +nd Russia's nuclear stockpiles. + +But it is also incumbent upon all of us to insist that nations like Iran and North Korea do not game the system. Those who +claim to respect international law cannot avert their eyes when those laws are flouted. Those who care for their own security +cannot ignore the danger of an arms race in the Middle East or East Asia. Those who seek peace cannot stand idly by as nations +arm themselves for nuclear war. + +The same principle applies to those who violate international law by brutalizing their own people. When there is genocide in +Darfur; systematic rape in Congo; or repression in Burma - there must be consequences. And the closer we stand together, the +less likely we will be faced with the choice between armed intervention and complicity in oppression. + +This brings me to a second point - the nature of the peace that we seek. For peace is not merely the absence of visible conflict. +Only a just peace based upon the inherent rights and dignity of every individual can truly be lasting. + +It was this insight that drove drafters of the Universal Declaration of Human Rights after the Second World War. In the wake of +devastation, they recognized that if human rights are not protected, peace is a hollow promise. + +And yet all too often, these words are ignored. In some countries, the failure to uphold human rights is excused by the false +suggestion that these are Western principles, foreign to local cultures or stages of a nation's development. And within America, +there has long been a tension between those who describe themselves as realists or idealists - a tension that suggests a stark +choice between the narrow pursuit of interests or an endless campaign to impose our values. + +I reject this choice. I believe that peace is unstable where citizens are denied the right to speak freely or worship as they +please; choose their own leaders or assemble without fear. Pent up grievances fester, and the suppression of tribal and religious +identity can lead to violence. We also know that the opposite is true. Only when Europe became free did it finally find peace. +America has never fought a war against a democracy, and our closest friends are governments that protect the rights of their +citizens. No matter how callously defined, neither America's interests - nor the world's -are served by the denial of human aspirations. + +So even as we respect the unique culture and traditions of different countries, America will always be a voice for those aspirations +that are universal. We will bear witness to the quiet dignity of reformers like Aung Sang Suu Kyi; to the bravery of Zimbabweans who +cast their ballots in the face of beatings; to the hundreds of thousands who have marched silently through the streets of Iran. It is +telling that the leaders of these governments fear the aspirations of their own people more than the power of any other nation. And +it is the responsibility of all free people and free nations to make clear to these movements that hope and history are on their side + +Let me also say this: the promotion of human rights cannot be about exhortation alone. At times, it must be coupled with painstaking +diplomacy. I know that engagement with repressive regimes lacks the satisfying purity of indignation. But I also know that sanctions +without outreach - and condemnation without discussion - can carry forward a crippling status quo. No repressive regime can move down +a new path unless it has the choice of an open door. + +In light of the Cultural Revolution's horrors, Nixon's meeting with Mao appeared inexcusable - and yet it surely helped set China on +a path where millions of its citizens have been lifted from poverty, and connected to open societies. Pope John Paul's engagement +with Poland created space not just for the Catholic Church, but for labor leaders like Lech Walesa. Ronald Reagan's efforts on arms control and embrace of perestroika not only improved relations with the Soviet Union, but empowered dissidents throughout Eastern Europe. There is no simple formula here. But we must try as best we can to balance isolation and engagement; pressure and incentives, so that human rights and dignity are advanced over time. + +Third, a just peace includes not only civil and political rights - it must encompass economic security and opportunity. For true +peace is not just freedom from fear, but freedom from want. + +It is undoubtedly true that development rarely takes root without security; it is also true that security does not exist where +human beings do not have access to enough food, or clean water, or the medicine they need to survive. It does not exist where +children cannot aspire to a decent education or a job that supports a family. The absence of hope can rot a society from within. + +And that is why helping farmers feed their own people - or nations educate their children and care for the sick - is not mere +charity. It is also why the world must come together to confront climate change. There is little scientific dispute that if we +do nothing, we will face more drought, famine and mass displacement that will fuel more conflict for decades. For this reason, it is not merely scientists and activists who call for swift and forceful action - it is military leaders in my country and others who understand that our common security hangs in the balance. + +Agreements among nations. Strong institutions. Support for human rights. Investments in development. All of these are vital +ingredients in bringing about the evolution that President Kennedy spoke about. And yet, I do not believe that we will have the will, +or the staying power, to complete this work without something more - and that is the continued expansion of our moral imagination; +an insistence that there is something irreducible that we all share. + +As the world grows smaller, you might think it would be easier for human beings to recognize how similar we are; to understand that +we all basically want the same things; that we all hope for the chance to live out our lives with some measure of happiness and +fulfillment for ourselves and our families. + +And yet, given the dizzying pace of globalization, and the cultural leveling of modernity, it should come as no surprise that people +fear the loss of what they cherish about their particular identities - their race, their tribe, and perhaps most powerfully their +religion. In some places, this fear has led to conflict. At times, it even feels like we are moving backwards. We see it in Middle +East, as the conflict between Arabs and Jews seems to harden. We see it in nations that are torn asunder by tribal lines. + +Most dangerously, we see it in the way that religion is used to justify the murder of innocents by those who have distorted and +defiled the great religion of Islam, and who attacked my country from Afghanistan. These extremists are not the first to kill in +the name of God; the cruelties of the Crusades are amply recorded. But they remind us that no Holy War can ever be a just war. For if you truly believe that you are carrying out divine will, then there is no need for restraint - no need to spare the pregnant mother, or the medic, or even a person of one's own faith. Such a warped view of religion is not just incompatible with the concept of peace, but the purpose of faith - for the one rule that lies at the heart of every major religion is that we do unto others as we would have them do unto us. + +Adhering to this law of love has always been the core struggle of human nature. We are fallible. We make mistakes, and fall +victim to the temptations of pride, and power, and sometimes evil. Even those of us with the best intentions will at times +fail to right the wrongs before us. + +But we do not have to think that human nature is perfect for us to still believe that the human condition can be perfected. +We do not have to live in an idealized world to still reach for those ideals that will make it a better place. The non-violence +practiced by men like Gandhi and King may not have been practical or possible in every circumstance, but the love that they preached - +their faith in human progress - must always be the North Star that guides us on our journey. + +For if we lose that faith - if we dismiss it as silly or naïve; if we divorce it from the decisions that we make on issues of war +and peace - then we lose what is best about humanity. We lose our sense of possibility. We lose our moral compass. + +Like generations have before us, we must reject that future. As Dr. King said at this occasion so many years ago, "I refuse to +accept despair as the final response to the ambiguities of history. I refuse to accept the idea that the 'isness' of man's present +nature makes him morally incapable of reaching up for the eternal 'oughtness' that forever confronts him." + +So let us reach for the world that ought to be - that spark of the divine that still stirs within each of our souls. Somewhere +today, in the here and now, a soldier sees he's outgunned but stands firm to keep the peace. Somewhere today, in this world, +a young protestor awaits the brutality of her government, but has the courage to march on. Somewhere today, a mother facing +punishing poverty still takes the time to teach her child, who believes that a cruel world still has a place for his dreams. + +Let us live by their example. We can acknowledge that oppression will always be with us, and still strive for justice. We +can admit the intractability of depravation, and still strive for dignity. We can understand that there will be war, and +still strive for peace. We can do that - for that is the story of human progress; that is the hope of all the world; and +at this moment of challenge, that must be our work here on Earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10/Data/gettysburg.txt b/CodeToAccompany9781430244646/ch07/sketch_7_10/Data/gettysburg.txt new file mode 100644 index 0000000..1d9643e --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10/Data/gettysburg.txt @@ -0,0 +1,22 @@ +Four score and seven years ago our fathers brought forth on this continent, a +new nation, conceived in Liberty, and dedicated to the proposition that all men +are created equal. + +Now we are engaged in a great civil war, testing whether that nation, or any +nation so conceived and so dedicated, can long endure. We are met on a great +battle-field of that war. We have come to dedicate a portion of that field, as a +final resting place for those who here gave their lives that that nation might +live. It is altogether fitting and proper that we should do this. + +But, in a larger sense, we can not dedicate -- we can not consecrate -- we can not +hallow -- this ground. The brave men, living and dead, who struggled here, have +consecrated it, far above our poor power to add or detract. The world will +little note, nor long remember what we say here, but it can never forget what +they did here. It is for us the living, rather, to be dedicated here to the +unfinished work which they who fought here have thus far so nobly advanced. It +is rather for us to be here dedicated to the great task remaining before us -- +that from these honored dead we take increased devotion to that cause for +which they gave the last full measure of devotion -- that we here highly resolve +that these dead shall not have died in vain -- that this nation, under God, shall +have a new birth of freedom -- and that government of the people, by the people, +for the people, shall not perish from the earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10/Data/stopwords.txt b/CodeToAccompany9781430244646/ch07/sketch_7_10/Data/stopwords.txt new file mode 100644 index 0000000..0a1f0d2 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10/Data/stopwords.txt @@ -0,0 +1,667 @@ +AT +A +a +able +about +above +abst +accordance +according +accordingly +across +act +actually +added +adj +adopted +affected +affecting +affects +after +afterwards +again +against +ah +al +all +almost +alone +along +already +also +although +always +am +among +amongst +an +and +announce +another +any +anybody +anyhow +anymore +anyone +anything +anyway +anyways +anywhere +apparently +approximately +are +aren +arent +arise +around +as +aside +ask +asking +at +auth +available +away +awfully +b +back +be +became +because +become +becomes +becoming +been +before +beforehand +begin +beginning +beginnings +begins +behind +being +believe +below +beside +besides +between +beyond +biol +both +brief +briefly +but +But +by +c +ca +came +can +cannot +cause +causes +certain +certainly +co +com +come +comes +contain +containing +contains +could +couldnt +d +date +did +didn +different +do +does +doesn +doing +done +don +down +downwards +due +during +e +each +ed +edu +effect +eg +eight +eighty +either +else +elsewhere +end +ending +enough +especially +et +etc +even +ever +every +everybody +everyone +everything +everywhere +ex +except +f +far +few +ff +fifth +first +five +fix +followed +following +follows +for +former +formerly +forth +found +four +from +further +furthermore +g +gave +get +gets +getting +give +given +gives +giving +go +goes +gone +got +gotten +h +had +happens +hardly +has +hasn +have +haven +having +he +hed +hence +her +here +hereafter +hereby +herein +heres +hereupon +hers +herself +hes +hi +hid +him +himself +his +hither +home +how +howbeit +however +hundred +i +id +ie +if +im +immediate +immediately +importance +important +in +In +inc +indeed +index +information +instead +into +invention +inward +is +isn +it +It +itd +its +itself +j +just +k +keep +keeps +kept +keys +kg +km +know +known +knows +l +largely +last +lately +later +latter +latterly +least +less +lest +let +lets +like +liked +likely +line +little +look +looking +looks +ltd +m +made +mainly +make +makes +many +may +maybe +me +mean +means +meantime +meanwhile +merely +mg +might +million +miss +ml +more +moreover +most +mostly +mr +mrs +much +mug +must +my +myself +n +na +name +namely +nay +nd +near +nearly +necessarily +necessary +need +needs +neither +never +nevertheless +new +next +nine +ninety +no +nobody +non +none +nonetheless +noone +nor +normally +nos +not +noted +nothing +now +nowhere +o +obtain +obtained +obviously +of +off +often +oh +ok +okay +old +omitted +on +once +one +ones +only +onto +or +ord +other +others +otherwise +ought +our +Our +ours +ourselves +out +outside +over +overall +owing +own +p +page +pages +part +particular +particularly +past +per +perhaps +placed +please +plus +poorly +possible +possibly +potentially +pp +predominantly +present +previously +primarily +probably +promptly +proud +provides +put +q +que +quickly +quite +qv +r +ran +rather +rd +re +readily +really +recent +recently +ref +refs +regarding +regardless +regards +related +relatively +research +respectively +resulted +resulting +results +right +run +s +said +same +saw +say +saying +says +sec +section +see +seeing +seem +seemed +seeming +seems +seen +self +selves +sent +seven +several +shall +she +shed +shes +should +shouldn +show +showed +shown +showns +shows +significant +significantly +similar +similarly +since +six +slightly +so +So +some +somebody +somehow +someone +somethan +something +sometime +sometimes +somewhat +somewhere +soon +sorry +specifically +specified +specify +specifying +state +states +still +stop +strongly +sub +substantially +successfully +such +sufficiently +suggest +sup +sure +t +take +taken +taking +tell +tends +th +than +thank +thanks +thanx +that +thats +the +their +Their +theirs +them +themselves +then +thence +there +There +thereafter +thereby +thered +therefore +therein +thereof +therere +theres +thereto +thereupon +these +They +These +they +theyd +theyre +think +this +This +those +Those +thou +though +thoughh +thousand +throug +through +throughout +thru +thus +til +tip +to +together +too +took +toward +towards +tried +tries +truly +try +trying +ts +twice +two +u +un +under +unfortunately +unless +unlike +unlikely +until +unto +up +upon +ups +us +use +used +useful +usefully +usefulness +uses +using +usually +v +value +various +ve +very +via +viz +vol +vols +vs +w +want +wants +was +wasn +way +we +wed +welcom +went +were +weren +what +whatever +whats +when +whence +whenever +where +whereafter +whereas +whereby +wherein +wheres +whereupon +wherever +whether +which +while +whim +whither +who +whod +whoever +whole +whom +whomever +whos +whose +why +widely +will +willing +wish +with +within +without +words +world +would +wouldn +www +x +y +yes +yet +you +youd +your +Your +youre +yours +yourself +yourselves +z +zero \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10/Word.pde b/CodeToAccompany9781430244646/ch07/sketch_7_10/Word.pde new file mode 100644 index 0000000..b9a1c01 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10/Word.pde @@ -0,0 +1,37 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-10: Word Cloud Visualization – First Draft +// Sketch 7-10b: The Word class +class Word { + // Each Word is a pair: the word, and its frequency + String word; + int freq; + Word(String newWord) { // Constructor + word = newWord; + freq = 1; + } // Word() + String getWord() { + return word; + } // getWord() + int getFreq() { + return freq; + } // getFreq() + void incr() { // increments the word count + freq++; + } // incr() + String toString() { // print representation of Word objects + return "<"+word+", "+freq+">"; + } +} // class Word + diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10/WordFreq.pde b/CodeToAccompany9781430244646/ch07/sketch_7_10/WordFreq.pde new file mode 100644 index 0000000..f87d298 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10/WordFreq.pde @@ -0,0 +1,112 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-10: Word Cloud Visualization – First Draft +// Sketch 7-10a: The Word frequency table class +class WordFreq { + // A Frequency table class for Words + ArrayList wordFrequency; + String [] stopWords = loadStrings("stopwords.txt"); + + WordFreq(String[] tokens) { // Constructor + + wordFrequency = new ArrayList(); + // Compute the wordFrequency table using tokens + for (String t : tokens) { + if (!_isStopWord(t)) { + // See if token t is already a known word + int index = _search(t, wordFrequency); + if (index >= 0) { + ( wordFrequency.get(index)).incr(); + } + else { + wordFrequency.add(new WordTile(t)); + } + } + } // for + } // WordFreq() + + void tabulate(int n) { // console printout + //int n = wordFrequency.size(); + println("There are "+N()+" entries."); + for (int i=0; i < n; i++) { + println(wordFrequency.get(i)); + } + } // tabulate + + void arrange(int N) { // arrange or map the first N tiles in sketch + for (int i=0; i < N; i++) { + WordTile tile = wordFrequency.get(i); + tile.setFontSize(); + tile.setSize(); + tile.setXY(random(width), random(height)); + } + } // arrange() + + void display(int N) { + for (int i=0; i < N; i++) { + WordTile tile = wordFrequency.get(i); + tile.display(); + } + } // display() + + int N() { // Number of table entries + return wordFrequency.size(); + } // N() + + String[] samples() { // Returns all the words + String [] k = new String[N()]; + int i=0; + for (WordTile w : wordFrequency) { + k[i++] = w.getWord(); + } + return k; + } // samples() + + int[] counts() { // Returns all the frequencies + int [] v = new int[N()]; + int i=0; + for (WordTile w : wordFrequency) { + v[i++] = w.getFreq(); + } + return v; + } // counts() + + int maxFreq() { // The max frequency + return max(counts()); + } // maxFreq() + + int _search(String w, ArrayList L) { + // search for word w in L. + // Returns index of w in L if found, -1 o/w + for (int i=0; i < L.size(); i++) { + if (L.get(i).getWord().equals(w)) + return i; + } + return -1; + } // _search() + + boolean _isStopWord(String word) { // Is word a stop word? + for (String stopWord : stopWords) { + if (word.equals(stopWord)) { + return true; + } + } + return false; + } // _isStopWord() + + String toString() { // Print representation + return "Word Frequency Table with"+N()+" entries."; + } // toString() + } // class WordFreq + diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10/WordTile.pde b/CodeToAccompany9781430244646/ch07/sketch_7_10/WordTile.pde new file mode 100644 index 0000000..0f966b0 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10/WordTile.pde @@ -0,0 +1,52 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-10: Word Cloud Visualization – First Draft +// Sketch 7-10c: The WordTile class +class WordTile extends Word { + // A graphical tile conatining a word and additional attributes + PVector location; // The top left corner of the tile (x, y) + float tileW, tileH; // width and height of the tile + color tileColor; // fill color of word + float tileFS = 24; // the font size of tile, default is 24 + + WordTile(String newWord) { // Constructor + super(newWord); + setSize(); + location = new PVector(0, 0); + tileColor = color(0); + } // WordTile() + + void setXY (float x, float y) { + location.x = x; + location.y = y; + } // setXY() + + void setFontSize() { + tileFS = map(freq, 1, 30, 10, 120); + setSize(); + } // setFontSize() + + void setSize() { + textSize(tileFS); + tileW = textWidth(word); + tileH = textAscent(); + } // setTileSize() + + void display() { + fill(tileColor); + textSize(tileFS); + text(word, location.x, location.y); + } // display() +} // class WordTile + diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10/sketch_7_10.pde b/CodeToAccompany9781430244646/ch07/sketch_7_10/sketch_7_10.pde new file mode 100644 index 0000000..02f59a8 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10/sketch_7_10.pde @@ -0,0 +1,46 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-10: Word Cloud Visualization – First Draft +String inputTextFile = "Obama.txt"; +WordFreq table; +PFont tnr; // The font to be used +int N = 150; // The number of words to be displayed + +void setup() { + // Input and parse text file + String [] fileContents = loadStrings(inputTextFile); + String rawText = join(fileContents, " "); + rawText = rawText.toLowerCase(); + String [] tokens; + String delimiters = " ,./?<>;:'\"[{]}\\|=+-_()*&^%$#@!~"; + tokens = splitTokens(rawText, delimiters); + println(tokens.length+" tokens found in file: "+inputTextFile); + // display stuff + size(800, 800); + tnr = createFont("Times New Roman", 120); + textFont(tnr); + textSize(24); + noLoop(); + // Create the word frequency table + table = new WordFreq(tokens); + println("Max frequency:"+table.maxFreq()); + table.arrange(N); +} // setup() + +void draw() { + background(255); + table.display(N); + table.tabulate(N); +} // draw() + diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10b/Data/Obama.txt b/CodeToAccompany9781430244646/ch07/sketch_7_10b/Data/Obama.txt new file mode 100644 index 0000000..5dd7b12 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10b/Data/Obama.txt @@ -0,0 +1,239 @@ +Your Majesties, Your Royal Highnesses, Distinguished Members of the Norwegian Nobel Committee, citizens of America, and citizens of the world: + +I receive this honor with deep gratitude and great humility. It is an award that speaks to our highest aspirations - that for all the cruelty +and hardship of our world, we are not mere prisoners of fate. Our actions matter, and can bend history in the direction of justice. + +And yet I would be remiss if I did not acknowledge the considerable controversy that your generous decision has generated. In part, this is +because I am at the beginning, and not the end, of my labors on the world stage. Compared to some of the giants of history who have received +this prize - Schweitzer and King; Marshall and Mandela - my accomplishments are slight. And then there are the men and women around the world +who have been jailed and beaten in the pursuit of justice; those who toil in humanitarian organizations to relieve suffering; the unrecognized +millions whose quiet acts of courage and compassion inspire even the most hardened of cynics. I cannot argue with those who find these men and +women - some known, some obscure to all but those they help - to be far more deserving of this honor than I. + +But perhaps the most profound issue surrounding my receipt of this prize is the fact that I am the Commander-in-Chief of a nation in the midst +of two wars. One of these wars is winding down. The other is a conflict that America did not seek; one in which we are joined by forty three other +countries - including Norway - in an effort to defend ourselves and all nations from further attacks. + +Still, we are at war, and I am responsible for the deployment of thousands of young Americans to battle in a distant land. Some will kill. Some +will be killed. And so I come here with an acute sense of the cost of armed conflict - filled with difficult questions about the relationship +between war and peace, and our effort to replace one with the other. + +These questions are not new. War, in one form or another, appeared with the first man. At the dawn of history, its morality was not questioned; +it was simply a fact, like drought or disease - the manner in which tribes and then civilizations sought power and settled their differences. + + +Over time, as codes of law sought to control violence within groups, so did philosophers, clerics, and statesmen seek to regulate the destructive +power of war. The concept of a "just war" emerged, suggesting that war is justified only when it meets certain preconditions: if it is waged +as a last resort or in self-defense; if the forced used is proportional, and if, whenever possible, civilians are spared from violence. + +For most of history, this concept of just war was rarely observed. The capacity of human beings to think up new ways to kill one another proved +inexhaustible, as did our capacity to exempt from mercy those who look different or pray to a different God. Wars between armies gave way to wars +between nations - total wars in which the distinction between combatant and civilian became blurred. In the span of thirty years, such carnage +would twice engulf this continent. And while it is hard to conceive of a cause more just than the defeat of the Third Reich and the Axis powers, +World War II was a conflict in which the total number of civilians who died exceeded the number of soldiers who perished. + +In the wake of such destruction, and with the advent of the nuclear age, it became clear to victor and vanquished alike that the world needed +institutions to prevent another World War. And so, a quarter century after the United States Senate rejected the League of Nations - an idea for +which Woodrow Wilson received this Prize - America led the world in constructing an architecture to keep the peace: a Marshall Plan and a +United Nations, mechanisms to govern the waging of war, treaties to protect human rights, prevent genocide, and restrict the most dangerous weapons. + +In many ways, these efforts succeeded. Yes, terrible wars have been fought, and atrocities committed. But there has been no Third World War. The Cold +War ended with jubilant crowds dismantling a wall. Commerce has stitched much of the world together. Billions have been lifted from poverty. The ideals +of liberty, self-determination, equality and the rule of law have haltingly advanced. We are the heirs of the fortitude and foresight of generations +past, and it is a legacy for which my own country is rightfully proud. + +A decade into a new century, this old architecture is buckling under the weight of new threats. The world may no longer shudder at the prospect of +war between two nuclear superpowers, but proliferation may increase the risk of catastrophe. Terrorism has long been a tactic, but modern technology +allows a few small men with outsized rage to murder innocents on a horrific scale. + +Moreover, wars between nations have increasingly given way to wars within nations. The resurgence of ethnic or sectarian conflicts; the growth +of secessionist movements, insurgencies, and failed states; have increasingly trapped civilians in unending chaos. In today's wars, many more +civilians are killed than soldiers; the seeds of future conflict are sewn, economies are wrecked, civil societies torn asunder, refugees +amassed, and children scarred. + +I do not bring with me today a definitive solution to the problems of war. What I do know is that meeting these challenges will require +the same vision, hard work, and persistence of those men and women who acted so boldly decades ago. And it will require us to think in +new ways about the notions of just war and the imperatives of a just peace. + +We must begin by acknowledging the hard truth that we will not eradicate violent conflict in our lifetimes. There will be times when +nations - acting individually or in concert - will find the use of force not only necessary but morally justified. + +I make this statement mindful of what Martin Luther King said in this same ceremony years ago - "Violence never brings permanent peace. It +solves no social problem: it merely creates new and more complicated ones." As someone who stands here as a direct consequence of Dr. King's +life's work, I am living testimony to the moral force of non-violence. I know there is nothing weak -nothing passive - nothing naïve - in the +creed and lives of Gandhi and King. + +But as a head of state sworn to protect and defend my nation, I cannot be guided by their examples alone. I face the world as it is, and +cannot stand idle in the face of threats to the American people. For make no mistake: evil does exist in the world. A non-violent movement +could not have halted Hitler's armies. Negotiations cannot convince al Qaeda's leaders to lay down their arms. To say that force is sometimes +necessary is not a call to cynicism - it is a recognition of history; the imperfections of man and the limits of reason. + +I raise this point because in many countries there is a deep ambivalence about military action today, no matter the cause. At times, this +is joined by a reflexive suspicion of America, the world's sole military superpower. + +Yet the world must remember that it was not simply international institutions - not just treaties and declarations - that brought stability +to a post-World War II world. Whatever mistakes we have made, the plain fact is this: the United States of America has helped underwrite +global security for more than six decades with the blood of our citizens and the strength of our arms. The service and sacrifice of our +men and women in uniform has promoted peace and prosperity from Germany to Korea, and enabled democracy to take hold in places like the +Balkans. We have borne this burden not because we seek to impose our will. We have done so out of enlightened self-interest - because +we seek a better future for our children and grandchildren, and we believe that their lives will be better if other peoples' children +and grandchildren can live in freedom and prosperity. + +So yes, the instruments of war do have a role to play in preserving the peace. And yet this truth must coexist with another - that +no matter how justified, war promises human tragedy. The soldier's courage and sacrifice is full of glory, expressing devotion to +country, to cause and to comrades in arms. But war itself is never glorious, and we must never trumpet it as such. + +So part of our challenge is reconciling these two seemingly irreconcilable truths - that war is sometimes necessary, and war is at +some level an expression of human feelings. Concretely, we must direct our effort to the task that President Kennedy called for long +ago. "Let us focus," he said, "on a more practical, more attainable peace, based not on a sudden revolution in human nature but +on a gradual evolution in human institutions." + +What might this evolution look like? What might these practical steps be? + +To begin with, I believe that all nations - strong and weak alike - must adhere to standards that govern the use of force. I - like any +head of state - reserve the right to act unilaterally if necessary to defend my nation. Nevertheless, I am convinced that adhering +to standards strengthens those who do, and isolates - and weakens - those who don't. + +The world rallied around America after the 9/11 attacks, and continues to support our efforts in Afghanistan, because of the horror +of those senseless attacks and the recognized principle of self-defense. Likewise, the world recognized the need to confront Saddam +Hussein when he invaded Kuwait - a consensus that sent a clear message to all about the cost of aggression. + +Furthermore, America cannot insist that others follow the rules of the road if we refuse to follow them ourselves. For when we don't, +our action can appear arbitrary, and undercut the legitimacy of future intervention - no matter how justified. + +This becomes particularly important when the purpose of military action extends beyond self defense or the defense of one nation +against an aggressor. More and more, we all confront difficult questions about how to prevent the slaughter of civilians by their +own government, or to stop a civil war whose violence and suffering can engulf an entire region. + +I believe that force can be justified on humanitarian grounds, as it was in the Balkans, or in other places that have been scarred +by war. Inaction tears at our conscience and can lead to more costly intervention later. That is why all responsible nations must +embrace the role that militaries with a clear mandate can play to keep the peace. + +America's commitment to global security will never waiver. But in a world in which threats are more diffuse, and missions more +complex, America cannot act alone. This is true in Afghanistan. This is true in failed states like Somalia, where terrorism and +piracy is joined by famine and human suffering. And sadly, it will continue to be true in unstable regions for years to come. + +The leaders and soldiers of NATO countries - and other friends and allies - demonstrate this truth through the capacity and courage +they have shown in Afghanistan. But in many countries, there is a disconnect between the efforts of those who serve and the ambivalence +of the broader public. I understand why war is not popular. But I also know this: the belief that peace is desirable is rarely enough to achieve it. Peace requires responsibility. Peace entails sacrifice. That is why NATO continues to be indispensable. That is why we must strengthen UN and regional peacekeeping, and not leave the task to a few countries. That is why we honor those who return home from peacekeeping and training abroad to Oslo and Rome; to Ottawa and Sydney; to Dhaka and Kigali - we honor them not as makers of war, but as wagers of peace. + +Let me make one final point about the use of force. Even as we make difficult decisions about going to war, we must also think clearly +about how we fight it. The Nobel Committee recognized this truth in awarding its first prize for peace to Henry Dunant - the founder +of the Red Cross, and a driving force behind the Geneva Conventions. + +Where force is necessary, we have a moral and strategic interest in binding ourselves to certain rules of conduct. And even as we +confront a vicious adversary that abides by no rules, I believe that the United States of America must remain a standard bearer in +the conduct of war. That is what makes us different from those whom we fight. That is a source of our strength. That is why I +prohibited torture. That is why I ordered the prison at Guantanamo Bay closed. And that is why I have reaffirmed America's +commitment to abide by the Geneva Conventions. We lose ourselves when we compromise the very ideals that we fight to defend. +And we honor those ideals by upholding them not just when it is easy, but when it is hard. + +I have spoken to the questions that must weigh on our minds and our hearts as we choose to wage war. But let me turn now to +our effort to avoid such tragic choices, and speak of three ways that we can build a just and lasting peace. + +First, in dealing with those nations that break rules and laws, I believe that we must develop alternatives to violence that +are tough enough to change behavior - for if we want a lasting peace, then the words of the international community must mean +something. Those regimes that break the rules must be held accountable. Sanctions must exact a real price. Intransigence must +be met with increased pressure - and such pressure exists only when the world stands together as one. + +One urgent example is the effort to prevent the spread of nuclear weapons, and to seek a world without them. In the middle of +the last century, nations agreed to be bound by a treaty whose bargain is clear: all will have access to peaceful nuclear power; +those without nuclear weapons will forsake them; and those with nuclear weapons will work toward disarmament. I am committed to +upholding this treaty. It is a centerpiece of my foreign policy. And I am working with President Medvedev to reduce America a +nd Russia's nuclear stockpiles. + +But it is also incumbent upon all of us to insist that nations like Iran and North Korea do not game the system. Those who +claim to respect international law cannot avert their eyes when those laws are flouted. Those who care for their own security +cannot ignore the danger of an arms race in the Middle East or East Asia. Those who seek peace cannot stand idly by as nations +arm themselves for nuclear war. + +The same principle applies to those who violate international law by brutalizing their own people. When there is genocide in +Darfur; systematic rape in Congo; or repression in Burma - there must be consequences. And the closer we stand together, the +less likely we will be faced with the choice between armed intervention and complicity in oppression. + +This brings me to a second point - the nature of the peace that we seek. For peace is not merely the absence of visible conflict. +Only a just peace based upon the inherent rights and dignity of every individual can truly be lasting. + +It was this insight that drove drafters of the Universal Declaration of Human Rights after the Second World War. In the wake of +devastation, they recognized that if human rights are not protected, peace is a hollow promise. + +And yet all too often, these words are ignored. In some countries, the failure to uphold human rights is excused by the false +suggestion that these are Western principles, foreign to local cultures or stages of a nation's development. And within America, +there has long been a tension between those who describe themselves as realists or idealists - a tension that suggests a stark +choice between the narrow pursuit of interests or an endless campaign to impose our values. + +I reject this choice. I believe that peace is unstable where citizens are denied the right to speak freely or worship as they +please; choose their own leaders or assemble without fear. Pent up grievances fester, and the suppression of tribal and religious +identity can lead to violence. We also know that the opposite is true. Only when Europe became free did it finally find peace. +America has never fought a war against a democracy, and our closest friends are governments that protect the rights of their +citizens. No matter how callously defined, neither America's interests - nor the world's -are served by the denial of human aspirations. + +So even as we respect the unique culture and traditions of different countries, America will always be a voice for those aspirations +that are universal. We will bear witness to the quiet dignity of reformers like Aung Sang Suu Kyi; to the bravery of Zimbabweans who +cast their ballots in the face of beatings; to the hundreds of thousands who have marched silently through the streets of Iran. It is +telling that the leaders of these governments fear the aspirations of their own people more than the power of any other nation. And +it is the responsibility of all free people and free nations to make clear to these movements that hope and history are on their side + +Let me also say this: the promotion of human rights cannot be about exhortation alone. At times, it must be coupled with painstaking +diplomacy. I know that engagement with repressive regimes lacks the satisfying purity of indignation. But I also know that sanctions +without outreach - and condemnation without discussion - can carry forward a crippling status quo. No repressive regime can move down +a new path unless it has the choice of an open door. + +In light of the Cultural Revolution's horrors, Nixon's meeting with Mao appeared inexcusable - and yet it surely helped set China on +a path where millions of its citizens have been lifted from poverty, and connected to open societies. Pope John Paul's engagement +with Poland created space not just for the Catholic Church, but for labor leaders like Lech Walesa. Ronald Reagan's efforts on arms control and embrace of perestroika not only improved relations with the Soviet Union, but empowered dissidents throughout Eastern Europe. There is no simple formula here. But we must try as best we can to balance isolation and engagement; pressure and incentives, so that human rights and dignity are advanced over time. + +Third, a just peace includes not only civil and political rights - it must encompass economic security and opportunity. For true +peace is not just freedom from fear, but freedom from want. + +It is undoubtedly true that development rarely takes root without security; it is also true that security does not exist where +human beings do not have access to enough food, or clean water, or the medicine they need to survive. It does not exist where +children cannot aspire to a decent education or a job that supports a family. The absence of hope can rot a society from within. + +And that is why helping farmers feed their own people - or nations educate their children and care for the sick - is not mere +charity. It is also why the world must come together to confront climate change. There is little scientific dispute that if we +do nothing, we will face more drought, famine and mass displacement that will fuel more conflict for decades. For this reason, it is not merely scientists and activists who call for swift and forceful action - it is military leaders in my country and others who understand that our common security hangs in the balance. + +Agreements among nations. Strong institutions. Support for human rights. Investments in development. All of these are vital +ingredients in bringing about the evolution that President Kennedy spoke about. And yet, I do not believe that we will have the will, +or the staying power, to complete this work without something more - and that is the continued expansion of our moral imagination; +an insistence that there is something irreducible that we all share. + +As the world grows smaller, you might think it would be easier for human beings to recognize how similar we are; to understand that +we all basically want the same things; that we all hope for the chance to live out our lives with some measure of happiness and +fulfillment for ourselves and our families. + +And yet, given the dizzying pace of globalization, and the cultural leveling of modernity, it should come as no surprise that people +fear the loss of what they cherish about their particular identities - their race, their tribe, and perhaps most powerfully their +religion. In some places, this fear has led to conflict. At times, it even feels like we are moving backwards. We see it in Middle +East, as the conflict between Arabs and Jews seems to harden. We see it in nations that are torn asunder by tribal lines. + +Most dangerously, we see it in the way that religion is used to justify the murder of innocents by those who have distorted and +defiled the great religion of Islam, and who attacked my country from Afghanistan. These extremists are not the first to kill in +the name of God; the cruelties of the Crusades are amply recorded. But they remind us that no Holy War can ever be a just war. For if you truly believe that you are carrying out divine will, then there is no need for restraint - no need to spare the pregnant mother, or the medic, or even a person of one's own faith. Such a warped view of religion is not just incompatible with the concept of peace, but the purpose of faith - for the one rule that lies at the heart of every major religion is that we do unto others as we would have them do unto us. + +Adhering to this law of love has always been the core struggle of human nature. We are fallible. We make mistakes, and fall +victim to the temptations of pride, and power, and sometimes evil. Even those of us with the best intentions will at times +fail to right the wrongs before us. + +But we do not have to think that human nature is perfect for us to still believe that the human condition can be perfected. +We do not have to live in an idealized world to still reach for those ideals that will make it a better place. The non-violence +practiced by men like Gandhi and King may not have been practical or possible in every circumstance, but the love that they preached - +their faith in human progress - must always be the North Star that guides us on our journey. + +For if we lose that faith - if we dismiss it as silly or naïve; if we divorce it from the decisions that we make on issues of war +and peace - then we lose what is best about humanity. We lose our sense of possibility. We lose our moral compass. + +Like generations have before us, we must reject that future. As Dr. King said at this occasion so many years ago, "I refuse to +accept despair as the final response to the ambiguities of history. I refuse to accept the idea that the 'isness' of man's present +nature makes him morally incapable of reaching up for the eternal 'oughtness' that forever confronts him." + +So let us reach for the world that ought to be - that spark of the divine that still stirs within each of our souls. Somewhere +today, in the here and now, a soldier sees he's outgunned but stands firm to keep the peace. Somewhere today, in this world, +a young protestor awaits the brutality of her government, but has the courage to march on. Somewhere today, a mother facing +punishing poverty still takes the time to teach her child, who believes that a cruel world still has a place for his dreams. + +Let us live by their example. We can acknowledge that oppression will always be with us, and still strive for justice. We +can admit the intractability of depravation, and still strive for dignity. We can understand that there will be war, and +still strive for peace. We can do that - for that is the story of human progress; that is the hope of all the world; and +at this moment of challenge, that must be our work here on Earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10b/Data/gettysburg.txt b/CodeToAccompany9781430244646/ch07/sketch_7_10b/Data/gettysburg.txt new file mode 100644 index 0000000..1d9643e --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10b/Data/gettysburg.txt @@ -0,0 +1,22 @@ +Four score and seven years ago our fathers brought forth on this continent, a +new nation, conceived in Liberty, and dedicated to the proposition that all men +are created equal. + +Now we are engaged in a great civil war, testing whether that nation, or any +nation so conceived and so dedicated, can long endure. We are met on a great +battle-field of that war. We have come to dedicate a portion of that field, as a +final resting place for those who here gave their lives that that nation might +live. It is altogether fitting and proper that we should do this. + +But, in a larger sense, we can not dedicate -- we can not consecrate -- we can not +hallow -- this ground. The brave men, living and dead, who struggled here, have +consecrated it, far above our poor power to add or detract. The world will +little note, nor long remember what we say here, but it can never forget what +they did here. It is for us the living, rather, to be dedicated here to the +unfinished work which they who fought here have thus far so nobly advanced. It +is rather for us to be here dedicated to the great task remaining before us -- +that from these honored dead we take increased devotion to that cause for +which they gave the last full measure of devotion -- that we here highly resolve +that these dead shall not have died in vain -- that this nation, under God, shall +have a new birth of freedom -- and that government of the people, by the people, +for the people, shall not perish from the earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10b/Data/stopwords.txt b/CodeToAccompany9781430244646/ch07/sketch_7_10b/Data/stopwords.txt new file mode 100644 index 0000000..0a1f0d2 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10b/Data/stopwords.txt @@ -0,0 +1,667 @@ +AT +A +a +able +about +above +abst +accordance +according +accordingly +across +act +actually +added +adj +adopted +affected +affecting +affects +after +afterwards +again +against +ah +al +all +almost +alone +along +already +also +although +always +am +among +amongst +an +and +announce +another +any +anybody +anyhow +anymore +anyone +anything +anyway +anyways +anywhere +apparently +approximately +are +aren +arent +arise +around +as +aside +ask +asking +at +auth +available +away +awfully +b +back +be +became +because +become +becomes +becoming +been +before +beforehand +begin +beginning +beginnings +begins +behind +being +believe +below +beside +besides +between +beyond +biol +both +brief +briefly +but +But +by +c +ca +came +can +cannot +cause +causes +certain +certainly +co +com +come +comes +contain +containing +contains +could +couldnt +d +date +did +didn +different +do +does +doesn +doing +done +don +down +downwards +due +during +e +each +ed +edu +effect +eg +eight +eighty +either +else +elsewhere +end +ending +enough +especially +et +etc +even +ever +every +everybody +everyone +everything +everywhere +ex +except +f +far +few +ff +fifth +first +five +fix +followed +following +follows +for +former +formerly +forth +found +four +from +further +furthermore +g +gave +get +gets +getting +give +given +gives +giving +go +goes +gone +got +gotten +h +had +happens +hardly +has +hasn +have +haven +having +he +hed +hence +her +here +hereafter +hereby +herein +heres +hereupon +hers +herself +hes +hi +hid +him +himself +his +hither +home +how +howbeit +however +hundred +i +id +ie +if +im +immediate +immediately +importance +important +in +In +inc +indeed +index +information +instead +into +invention +inward +is +isn +it +It +itd +its +itself +j +just +k +keep +keeps +kept +keys +kg +km +know +known +knows +l +largely +last +lately +later +latter +latterly +least +less +lest +let +lets +like +liked +likely +line +little +look +looking +looks +ltd +m +made +mainly +make +makes +many +may +maybe +me +mean +means +meantime +meanwhile +merely +mg +might +million +miss +ml +more +moreover +most +mostly +mr +mrs +much +mug +must +my +myself +n +na +name +namely +nay +nd +near +nearly +necessarily +necessary +need +needs +neither +never +nevertheless +new +next +nine +ninety +no +nobody +non +none +nonetheless +noone +nor +normally +nos +not +noted +nothing +now +nowhere +o +obtain +obtained +obviously +of +off +often +oh +ok +okay +old +omitted +on +once +one +ones +only +onto +or +ord +other +others +otherwise +ought +our +Our +ours +ourselves +out +outside +over +overall +owing +own +p +page +pages +part +particular +particularly +past +per +perhaps +placed +please +plus +poorly +possible +possibly +potentially +pp +predominantly +present +previously +primarily +probably +promptly +proud +provides +put +q +que +quickly +quite +qv +r +ran +rather +rd +re +readily +really +recent +recently +ref +refs +regarding +regardless +regards +related +relatively +research +respectively +resulted +resulting +results +right +run +s +said +same +saw +say +saying +says +sec +section +see +seeing +seem +seemed +seeming +seems +seen +self +selves +sent +seven +several +shall +she +shed +shes +should +shouldn +show +showed +shown +showns +shows +significant +significantly +similar +similarly +since +six +slightly +so +So +some +somebody +somehow +someone +somethan +something +sometime +sometimes +somewhat +somewhere +soon +sorry +specifically +specified +specify +specifying +state +states +still +stop +strongly +sub +substantially +successfully +such +sufficiently +suggest +sup +sure +t +take +taken +taking +tell +tends +th +than +thank +thanks +thanx +that +thats +the +their +Their +theirs +them +themselves +then +thence +there +There +thereafter +thereby +thered +therefore +therein +thereof +therere +theres +thereto +thereupon +these +They +These +they +theyd +theyre +think +this +This +those +Those +thou +though +thoughh +thousand +throug +through +throughout +thru +thus +til +tip +to +together +too +took +toward +towards +tried +tries +truly +try +trying +ts +twice +two +u +un +under +unfortunately +unless +unlike +unlikely +until +unto +up +upon +ups +us +use +used +useful +usefully +usefulness +uses +using +usually +v +value +various +ve +very +via +viz +vol +vols +vs +w +want +wants +was +wasn +way +we +wed +welcom +went +were +weren +what +whatever +whats +when +whence +whenever +where +whereafter +whereas +whereby +wherein +wheres +whereupon +wherever +whether +which +while +whim +whither +who +whod +whoever +whole +whom +whomever +whos +whose +why +widely +will +willing +wish +with +within +without +words +world +would +wouldn +www +x +y +yes +yet +you +youd +your +Your +youre +yours +yourself +yourselves +z +zero \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10b/Word.pde b/CodeToAccompany9781430244646/ch07/sketch_7_10b/Word.pde new file mode 100644 index 0000000..c323a24 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10b/Word.pde @@ -0,0 +1,36 @@ +/*------------------------------------------------------------ + Copyright (c) 2013, Friends of Ed (An Apress Company) + All rights reserved. + + The code provided here accompanies the book: + + Processing: Creative Coding and Generative Art in Processing 2 + By Ira Greenberg, Dianna Xu, and Deepak Kumar + Friends of Ed (An APress Company), 2013 + ISBN-13 978-1430244646 + Please refer to the associated README for a full disclaimer. + ------------------------------------------------------------*/ + +// Sketch 7-10b: The Word class +class Word { + // Each Word is a pair: the word, and its frequency + String word; + int freq; + Word(String newWord) { // Constructor + word = newWord; + freq = 1; + } // Word() + String getWord() { + return word; + } // getWord() + int getFreq() { + return freq; + } // getFreq() + void incr() { // increments the word count + freq++; + } // incr() + String toString() { // print representation of Word objects + return "<"+word+", "+freq+">"; + } +} // class Word + diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10b/WordFreq.pde b/CodeToAccompany9781430244646/ch07/sketch_7_10b/WordFreq.pde new file mode 100644 index 0000000..f6446e7 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10b/WordFreq.pde @@ -0,0 +1,127 @@ +/*------------------------------------------------------------ + Copyright (c) 2013, Friends of Ed (An Apress Company) + All rights reserved. + + The code provided here accompanies the book: + + Processing: Creative Coding and Generative Art in Processing 2 + By Ira Greenberg, Dianna Xu, and Deepak Kumar + Friends of Ed (An APress Company), 2013 + ISBN-13 978-1430244646 + Please refer to the associated README for a full disclaimer. + ------------------------------------------------------------*/ + +// Sketch 7-10b: The Word frequency table class +class WordFreq { + // A Frequency table class for Words + ArrayList wordFrequency; + String [] stopWords = loadStrings("stopwords.txt"); + + WordFreq(String[] tokens) { // Constructor + + wordFrequency = new ArrayList(); + // Compute the wordFrequency table using tokens + for (String t : tokens) { + if (!_isStopWord(t)) { + // See if token t is already a known word + int index = _search(t, wordFrequency); + if (index >= 0) { + ( wordFrequency.get(index)).incr(); + } + else { + wordFrequency.add(new WordTile(t)); + } + } + } // for + } // WordFreq() + + void tabulate(int n) { // console printout + //int n = wordFrequency.size(); + println("There are "+N()+" entries."); + for (int i=0; i < n; i++) { + println(wordFrequency.get(i)); + } + } // tabulate + + void arrange(int N) { // arrange or map the first N tiles in sketch + WordTile tile; + for (int i=0; i < N; i++) { + tile = wordFrequency.get(i); // the tile to be placed + tile.setFontSize(); + do { // find a random x, y for tile, i + float x = random(width-tile.tileW); + float y = random(tile.tileH, height); + tile.setXY(x, y); + } // until the tile is clear of all other tiles + while (!clear (i)); + } + } // arrange() + boolean clear(int n) { // Is tile, i clear of tiles 0..i-1? + WordTile tile1 = wordFrequency.get(n); + for (int i=0; i < n; i++) { + WordTile tile2 = wordFrequency.get(i); + if (tile1.intersect(tile2)) { + return false; + } + } // for + return true; + } // clear() + + + void display(int N) { + for (int i=0; i < N; i++) { + WordTile tile = wordFrequency.get(i); + tile.display(); + } + } // display() + + int N() { // Number of table entries + return wordFrequency.size(); + } // N() + + String[] samples() { // Returns all the words + String [] k = new String[N()]; + int i=0; + for (WordTile w : wordFrequency) { + k[i++] = w.getWord(); + } + return k; + } // samples() + + int[] counts() { // Returns all the frequencies + int [] v = new int[N()]; + int i=0; + for (WordTile w : wordFrequency) { + v[i++] = w.getFreq(); + } + return v; + } // counts() + + int maxFreq() { // The max frequency + return max(counts()); + } // maxFreq() + + int _search(String w, ArrayList L) { + // search for word w in L. + // Returns index of w in L if found, -1 o/w + for (int i=0; i < L.size(); i++) { + if (L.get(i).getWord().equals(w)) + return i; + } + return -1; + } // _search() + + boolean _isStopWord(String word) { // Is word a stop word? + for (String stopWord : stopWords) { + if (word.equals(stopWord)) { + return true; + } + } + return false; + } // _isStopWord() + + String toString() { // Print representation + return "Word Frequency Table with"+N()+" entries."; + } // toString() +} // class WordFreq + diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10b/WordTile.pde b/CodeToAccompany9781430244646/ch07/sketch_7_10b/WordTile.pde new file mode 100644 index 0000000..41485f0 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10b/WordTile.pde @@ -0,0 +1,63 @@ +/*------------------------------------------------------------ + Copyright (c) 2013, Friends of Ed (An Apress Company) + All rights reserved. + + The code provided here accompanies the book: + + Processing: Creative Coding and Generative Art in Processing 2 + By Ira Greenberg, Dianna Xu, and Deepak Kumar + Friends of Ed (An APress Company), 2013 + ISBN-13 978-1430244646 + Please refer to the associated README for a full disclaimer. + ------------------------------------------------------------*/ + +// Sketch 7-10b: The WordTile class +class WordTile extends Word { + // A graphical tile conatining a word and additional attributes + PVector location; // The top left corner of the tile (x, y) + float tileW, tileH; // width and height of the tile + color tileColor; // fill color of word + float tileFS = 24; // the font size of tile, default is 24 + + WordTile(String newWord) { // Constructor + super(newWord); + setSize(); + location = new PVector(0, 0); + tileColor = color(0); + } // WordTile() + + void setXY (float x, float y) { + location.x = x; + location.y = y; + } // setXY() + + void setFontSize() { + tileFS = map(freq, 1, 30, 10, 120); + setSize(); + } // setFontSize() + + void setSize() { + textSize(tileFS); + tileW = textWidth(word); + tileH = textAscent(); + } // setTileSize() + + boolean intersect(WordTile t2) { + float left1 = location.x; // the first tile’s bounding box + float right1 = location.x+tileW; + float top1 = location.y-tileH; + float bot1 = location.y; + float left2 = t2.location.x; // the second tile’s bounding box + float right2 = left2+t2.tileW; + float bot2 = t2.location.y; + float top2 = bot2-t2.tileH; + return !(right1 < left2 || left1 > right2 || bot1 < top2 || top1 > bot2); // testing intersection + } // intersect() + + void display() { + fill(tileColor); + textSize(tileFS); + text(word, location.x, location.y); + } // display() +} // class WordTile + diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_10b/sketch_7_10b.pde b/CodeToAccompany9781430244646/ch07/sketch_7_10b/sketch_7_10b.pde new file mode 100644 index 0000000..ef5eb79 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_10b/sketch_7_10b.pde @@ -0,0 +1,48 @@ +/*------------------------------------------------------------ + Copyright (c) 2013, Friends of Ed (An Apress Company) + All rights reserved. + + The code provided here accompanies the book: + + Processing: Creative Coding and Generative Art in Processing 2 + By Ira Greenberg, Dianna Xu, and Deepak Kumar + Friends of Ed (An APress Company), 2013 + ISBN-13 978-1430244646 + Please refer to the associated README for a full disclaimer. + ------------------------------------------------------------*/ +import processing.opengl.*; + +// Sketch 7-10b: Word Cloud Visualization – First Draft +String inputTextFile = "Obama.txt"; +WordFreq table; +PFont tnr; // The font to be used +int N = 150; // The number of words to be displayed + +void setup() { + // Input and parse text file + String [] fileContents = loadStrings(inputTextFile); + String rawText = join(fileContents, " "); + rawText = rawText.toLowerCase(); + String [] tokens; + String delimiters = " ,./?<>;:'\"[{]}\\|=+-_()*&^%$#@!~"; + tokens = splitTokens(rawText, delimiters); + println(tokens.length+" tokens found in file: "+inputTextFile); + + // display stuff + size(800, 800, OPENGL); + tnr = createFont("Times New Roman", 120); + textFont(tnr); + textSize(24); + noLoop(); + // Create the word frequency table + table = new WordFreq(tokens); + println("Max frequency:"+table.maxFreq()); + table.arrange(N); +} // setup() + +void draw() { + background(255); + table.display(N); + table.tabulate(N); +} // draw() + diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_11/Data/Obama.txt b/CodeToAccompany9781430244646/ch07/sketch_7_11/Data/Obama.txt new file mode 100644 index 0000000..5dd7b12 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_11/Data/Obama.txt @@ -0,0 +1,239 @@ +Your Majesties, Your Royal Highnesses, Distinguished Members of the Norwegian Nobel Committee, citizens of America, and citizens of the world: + +I receive this honor with deep gratitude and great humility. It is an award that speaks to our highest aspirations - that for all the cruelty +and hardship of our world, we are not mere prisoners of fate. Our actions matter, and can bend history in the direction of justice. + +And yet I would be remiss if I did not acknowledge the considerable controversy that your generous decision has generated. In part, this is +because I am at the beginning, and not the end, of my labors on the world stage. Compared to some of the giants of history who have received +this prize - Schweitzer and King; Marshall and Mandela - my accomplishments are slight. And then there are the men and women around the world +who have been jailed and beaten in the pursuit of justice; those who toil in humanitarian organizations to relieve suffering; the unrecognized +millions whose quiet acts of courage and compassion inspire even the most hardened of cynics. I cannot argue with those who find these men and +women - some known, some obscure to all but those they help - to be far more deserving of this honor than I. + +But perhaps the most profound issue surrounding my receipt of this prize is the fact that I am the Commander-in-Chief of a nation in the midst +of two wars. One of these wars is winding down. The other is a conflict that America did not seek; one in which we are joined by forty three other +countries - including Norway - in an effort to defend ourselves and all nations from further attacks. + +Still, we are at war, and I am responsible for the deployment of thousands of young Americans to battle in a distant land. Some will kill. Some +will be killed. And so I come here with an acute sense of the cost of armed conflict - filled with difficult questions about the relationship +between war and peace, and our effort to replace one with the other. + +These questions are not new. War, in one form or another, appeared with the first man. At the dawn of history, its morality was not questioned; +it was simply a fact, like drought or disease - the manner in which tribes and then civilizations sought power and settled their differences. + + +Over time, as codes of law sought to control violence within groups, so did philosophers, clerics, and statesmen seek to regulate the destructive +power of war. The concept of a "just war" emerged, suggesting that war is justified only when it meets certain preconditions: if it is waged +as a last resort or in self-defense; if the forced used is proportional, and if, whenever possible, civilians are spared from violence. + +For most of history, this concept of just war was rarely observed. The capacity of human beings to think up new ways to kill one another proved +inexhaustible, as did our capacity to exempt from mercy those who look different or pray to a different God. Wars between armies gave way to wars +between nations - total wars in which the distinction between combatant and civilian became blurred. In the span of thirty years, such carnage +would twice engulf this continent. And while it is hard to conceive of a cause more just than the defeat of the Third Reich and the Axis powers, +World War II was a conflict in which the total number of civilians who died exceeded the number of soldiers who perished. + +In the wake of such destruction, and with the advent of the nuclear age, it became clear to victor and vanquished alike that the world needed +institutions to prevent another World War. And so, a quarter century after the United States Senate rejected the League of Nations - an idea for +which Woodrow Wilson received this Prize - America led the world in constructing an architecture to keep the peace: a Marshall Plan and a +United Nations, mechanisms to govern the waging of war, treaties to protect human rights, prevent genocide, and restrict the most dangerous weapons. + +In many ways, these efforts succeeded. Yes, terrible wars have been fought, and atrocities committed. But there has been no Third World War. The Cold +War ended with jubilant crowds dismantling a wall. Commerce has stitched much of the world together. Billions have been lifted from poverty. The ideals +of liberty, self-determination, equality and the rule of law have haltingly advanced. We are the heirs of the fortitude and foresight of generations +past, and it is a legacy for which my own country is rightfully proud. + +A decade into a new century, this old architecture is buckling under the weight of new threats. The world may no longer shudder at the prospect of +war between two nuclear superpowers, but proliferation may increase the risk of catastrophe. Terrorism has long been a tactic, but modern technology +allows a few small men with outsized rage to murder innocents on a horrific scale. + +Moreover, wars between nations have increasingly given way to wars within nations. The resurgence of ethnic or sectarian conflicts; the growth +of secessionist movements, insurgencies, and failed states; have increasingly trapped civilians in unending chaos. In today's wars, many more +civilians are killed than soldiers; the seeds of future conflict are sewn, economies are wrecked, civil societies torn asunder, refugees +amassed, and children scarred. + +I do not bring with me today a definitive solution to the problems of war. What I do know is that meeting these challenges will require +the same vision, hard work, and persistence of those men and women who acted so boldly decades ago. And it will require us to think in +new ways about the notions of just war and the imperatives of a just peace. + +We must begin by acknowledging the hard truth that we will not eradicate violent conflict in our lifetimes. There will be times when +nations - acting individually or in concert - will find the use of force not only necessary but morally justified. + +I make this statement mindful of what Martin Luther King said in this same ceremony years ago - "Violence never brings permanent peace. It +solves no social problem: it merely creates new and more complicated ones." As someone who stands here as a direct consequence of Dr. King's +life's work, I am living testimony to the moral force of non-violence. I know there is nothing weak -nothing passive - nothing naïve - in the +creed and lives of Gandhi and King. + +But as a head of state sworn to protect and defend my nation, I cannot be guided by their examples alone. I face the world as it is, and +cannot stand idle in the face of threats to the American people. For make no mistake: evil does exist in the world. A non-violent movement +could not have halted Hitler's armies. Negotiations cannot convince al Qaeda's leaders to lay down their arms. To say that force is sometimes +necessary is not a call to cynicism - it is a recognition of history; the imperfections of man and the limits of reason. + +I raise this point because in many countries there is a deep ambivalence about military action today, no matter the cause. At times, this +is joined by a reflexive suspicion of America, the world's sole military superpower. + +Yet the world must remember that it was not simply international institutions - not just treaties and declarations - that brought stability +to a post-World War II world. Whatever mistakes we have made, the plain fact is this: the United States of America has helped underwrite +global security for more than six decades with the blood of our citizens and the strength of our arms. The service and sacrifice of our +men and women in uniform has promoted peace and prosperity from Germany to Korea, and enabled democracy to take hold in places like the +Balkans. We have borne this burden not because we seek to impose our will. We have done so out of enlightened self-interest - because +we seek a better future for our children and grandchildren, and we believe that their lives will be better if other peoples' children +and grandchildren can live in freedom and prosperity. + +So yes, the instruments of war do have a role to play in preserving the peace. And yet this truth must coexist with another - that +no matter how justified, war promises human tragedy. The soldier's courage and sacrifice is full of glory, expressing devotion to +country, to cause and to comrades in arms. But war itself is never glorious, and we must never trumpet it as such. + +So part of our challenge is reconciling these two seemingly irreconcilable truths - that war is sometimes necessary, and war is at +some level an expression of human feelings. Concretely, we must direct our effort to the task that President Kennedy called for long +ago. "Let us focus," he said, "on a more practical, more attainable peace, based not on a sudden revolution in human nature but +on a gradual evolution in human institutions." + +What might this evolution look like? What might these practical steps be? + +To begin with, I believe that all nations - strong and weak alike - must adhere to standards that govern the use of force. I - like any +head of state - reserve the right to act unilaterally if necessary to defend my nation. Nevertheless, I am convinced that adhering +to standards strengthens those who do, and isolates - and weakens - those who don't. + +The world rallied around America after the 9/11 attacks, and continues to support our efforts in Afghanistan, because of the horror +of those senseless attacks and the recognized principle of self-defense. Likewise, the world recognized the need to confront Saddam +Hussein when he invaded Kuwait - a consensus that sent a clear message to all about the cost of aggression. + +Furthermore, America cannot insist that others follow the rules of the road if we refuse to follow them ourselves. For when we don't, +our action can appear arbitrary, and undercut the legitimacy of future intervention - no matter how justified. + +This becomes particularly important when the purpose of military action extends beyond self defense or the defense of one nation +against an aggressor. More and more, we all confront difficult questions about how to prevent the slaughter of civilians by their +own government, or to stop a civil war whose violence and suffering can engulf an entire region. + +I believe that force can be justified on humanitarian grounds, as it was in the Balkans, or in other places that have been scarred +by war. Inaction tears at our conscience and can lead to more costly intervention later. That is why all responsible nations must +embrace the role that militaries with a clear mandate can play to keep the peace. + +America's commitment to global security will never waiver. But in a world in which threats are more diffuse, and missions more +complex, America cannot act alone. This is true in Afghanistan. This is true in failed states like Somalia, where terrorism and +piracy is joined by famine and human suffering. And sadly, it will continue to be true in unstable regions for years to come. + +The leaders and soldiers of NATO countries - and other friends and allies - demonstrate this truth through the capacity and courage +they have shown in Afghanistan. But in many countries, there is a disconnect between the efforts of those who serve and the ambivalence +of the broader public. I understand why war is not popular. But I also know this: the belief that peace is desirable is rarely enough to achieve it. Peace requires responsibility. Peace entails sacrifice. That is why NATO continues to be indispensable. That is why we must strengthen UN and regional peacekeeping, and not leave the task to a few countries. That is why we honor those who return home from peacekeeping and training abroad to Oslo and Rome; to Ottawa and Sydney; to Dhaka and Kigali - we honor them not as makers of war, but as wagers of peace. + +Let me make one final point about the use of force. Even as we make difficult decisions about going to war, we must also think clearly +about how we fight it. The Nobel Committee recognized this truth in awarding its first prize for peace to Henry Dunant - the founder +of the Red Cross, and a driving force behind the Geneva Conventions. + +Where force is necessary, we have a moral and strategic interest in binding ourselves to certain rules of conduct. And even as we +confront a vicious adversary that abides by no rules, I believe that the United States of America must remain a standard bearer in +the conduct of war. That is what makes us different from those whom we fight. That is a source of our strength. That is why I +prohibited torture. That is why I ordered the prison at Guantanamo Bay closed. And that is why I have reaffirmed America's +commitment to abide by the Geneva Conventions. We lose ourselves when we compromise the very ideals that we fight to defend. +And we honor those ideals by upholding them not just when it is easy, but when it is hard. + +I have spoken to the questions that must weigh on our minds and our hearts as we choose to wage war. But let me turn now to +our effort to avoid such tragic choices, and speak of three ways that we can build a just and lasting peace. + +First, in dealing with those nations that break rules and laws, I believe that we must develop alternatives to violence that +are tough enough to change behavior - for if we want a lasting peace, then the words of the international community must mean +something. Those regimes that break the rules must be held accountable. Sanctions must exact a real price. Intransigence must +be met with increased pressure - and such pressure exists only when the world stands together as one. + +One urgent example is the effort to prevent the spread of nuclear weapons, and to seek a world without them. In the middle of +the last century, nations agreed to be bound by a treaty whose bargain is clear: all will have access to peaceful nuclear power; +those without nuclear weapons will forsake them; and those with nuclear weapons will work toward disarmament. I am committed to +upholding this treaty. It is a centerpiece of my foreign policy. And I am working with President Medvedev to reduce America a +nd Russia's nuclear stockpiles. + +But it is also incumbent upon all of us to insist that nations like Iran and North Korea do not game the system. Those who +claim to respect international law cannot avert their eyes when those laws are flouted. Those who care for their own security +cannot ignore the danger of an arms race in the Middle East or East Asia. Those who seek peace cannot stand idly by as nations +arm themselves for nuclear war. + +The same principle applies to those who violate international law by brutalizing their own people. When there is genocide in +Darfur; systematic rape in Congo; or repression in Burma - there must be consequences. And the closer we stand together, the +less likely we will be faced with the choice between armed intervention and complicity in oppression. + +This brings me to a second point - the nature of the peace that we seek. For peace is not merely the absence of visible conflict. +Only a just peace based upon the inherent rights and dignity of every individual can truly be lasting. + +It was this insight that drove drafters of the Universal Declaration of Human Rights after the Second World War. In the wake of +devastation, they recognized that if human rights are not protected, peace is a hollow promise. + +And yet all too often, these words are ignored. In some countries, the failure to uphold human rights is excused by the false +suggestion that these are Western principles, foreign to local cultures or stages of a nation's development. And within America, +there has long been a tension between those who describe themselves as realists or idealists - a tension that suggests a stark +choice between the narrow pursuit of interests or an endless campaign to impose our values. + +I reject this choice. I believe that peace is unstable where citizens are denied the right to speak freely or worship as they +please; choose their own leaders or assemble without fear. Pent up grievances fester, and the suppression of tribal and religious +identity can lead to violence. We also know that the opposite is true. Only when Europe became free did it finally find peace. +America has never fought a war against a democracy, and our closest friends are governments that protect the rights of their +citizens. No matter how callously defined, neither America's interests - nor the world's -are served by the denial of human aspirations. + +So even as we respect the unique culture and traditions of different countries, America will always be a voice for those aspirations +that are universal. We will bear witness to the quiet dignity of reformers like Aung Sang Suu Kyi; to the bravery of Zimbabweans who +cast their ballots in the face of beatings; to the hundreds of thousands who have marched silently through the streets of Iran. It is +telling that the leaders of these governments fear the aspirations of their own people more than the power of any other nation. And +it is the responsibility of all free people and free nations to make clear to these movements that hope and history are on their side + +Let me also say this: the promotion of human rights cannot be about exhortation alone. At times, it must be coupled with painstaking +diplomacy. I know that engagement with repressive regimes lacks the satisfying purity of indignation. But I also know that sanctions +without outreach - and condemnation without discussion - can carry forward a crippling status quo. No repressive regime can move down +a new path unless it has the choice of an open door. + +In light of the Cultural Revolution's horrors, Nixon's meeting with Mao appeared inexcusable - and yet it surely helped set China on +a path where millions of its citizens have been lifted from poverty, and connected to open societies. Pope John Paul's engagement +with Poland created space not just for the Catholic Church, but for labor leaders like Lech Walesa. Ronald Reagan's efforts on arms control and embrace of perestroika not only improved relations with the Soviet Union, but empowered dissidents throughout Eastern Europe. There is no simple formula here. But we must try as best we can to balance isolation and engagement; pressure and incentives, so that human rights and dignity are advanced over time. + +Third, a just peace includes not only civil and political rights - it must encompass economic security and opportunity. For true +peace is not just freedom from fear, but freedom from want. + +It is undoubtedly true that development rarely takes root without security; it is also true that security does not exist where +human beings do not have access to enough food, or clean water, or the medicine they need to survive. It does not exist where +children cannot aspire to a decent education or a job that supports a family. The absence of hope can rot a society from within. + +And that is why helping farmers feed their own people - or nations educate their children and care for the sick - is not mere +charity. It is also why the world must come together to confront climate change. There is little scientific dispute that if we +do nothing, we will face more drought, famine and mass displacement that will fuel more conflict for decades. For this reason, it is not merely scientists and activists who call for swift and forceful action - it is military leaders in my country and others who understand that our common security hangs in the balance. + +Agreements among nations. Strong institutions. Support for human rights. Investments in development. All of these are vital +ingredients in bringing about the evolution that President Kennedy spoke about. And yet, I do not believe that we will have the will, +or the staying power, to complete this work without something more - and that is the continued expansion of our moral imagination; +an insistence that there is something irreducible that we all share. + +As the world grows smaller, you might think it would be easier for human beings to recognize how similar we are; to understand that +we all basically want the same things; that we all hope for the chance to live out our lives with some measure of happiness and +fulfillment for ourselves and our families. + +And yet, given the dizzying pace of globalization, and the cultural leveling of modernity, it should come as no surprise that people +fear the loss of what they cherish about their particular identities - their race, their tribe, and perhaps most powerfully their +religion. In some places, this fear has led to conflict. At times, it even feels like we are moving backwards. We see it in Middle +East, as the conflict between Arabs and Jews seems to harden. We see it in nations that are torn asunder by tribal lines. + +Most dangerously, we see it in the way that religion is used to justify the murder of innocents by those who have distorted and +defiled the great religion of Islam, and who attacked my country from Afghanistan. These extremists are not the first to kill in +the name of God; the cruelties of the Crusades are amply recorded. But they remind us that no Holy War can ever be a just war. For if you truly believe that you are carrying out divine will, then there is no need for restraint - no need to spare the pregnant mother, or the medic, or even a person of one's own faith. Such a warped view of religion is not just incompatible with the concept of peace, but the purpose of faith - for the one rule that lies at the heart of every major religion is that we do unto others as we would have them do unto us. + +Adhering to this law of love has always been the core struggle of human nature. We are fallible. We make mistakes, and fall +victim to the temptations of pride, and power, and sometimes evil. Even those of us with the best intentions will at times +fail to right the wrongs before us. + +But we do not have to think that human nature is perfect for us to still believe that the human condition can be perfected. +We do not have to live in an idealized world to still reach for those ideals that will make it a better place. The non-violence +practiced by men like Gandhi and King may not have been practical or possible in every circumstance, but the love that they preached - +their faith in human progress - must always be the North Star that guides us on our journey. + +For if we lose that faith - if we dismiss it as silly or naïve; if we divorce it from the decisions that we make on issues of war +and peace - then we lose what is best about humanity. We lose our sense of possibility. We lose our moral compass. + +Like generations have before us, we must reject that future. As Dr. King said at this occasion so many years ago, "I refuse to +accept despair as the final response to the ambiguities of history. I refuse to accept the idea that the 'isness' of man's present +nature makes him morally incapable of reaching up for the eternal 'oughtness' that forever confronts him." + +So let us reach for the world that ought to be - that spark of the divine that still stirs within each of our souls. Somewhere +today, in the here and now, a soldier sees he's outgunned but stands firm to keep the peace. Somewhere today, in this world, +a young protestor awaits the brutality of her government, but has the courage to march on. Somewhere today, a mother facing +punishing poverty still takes the time to teach her child, who believes that a cruel world still has a place for his dreams. + +Let us live by their example. We can acknowledge that oppression will always be with us, and still strive for justice. We +can admit the intractability of depravation, and still strive for dignity. We can understand that there will be war, and +still strive for peace. We can do that - for that is the story of human progress; that is the hope of all the world; and +at this moment of challenge, that must be our work here on Earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_11/Data/gettysburg.txt b/CodeToAccompany9781430244646/ch07/sketch_7_11/Data/gettysburg.txt new file mode 100644 index 0000000..1d9643e --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_11/Data/gettysburg.txt @@ -0,0 +1,22 @@ +Four score and seven years ago our fathers brought forth on this continent, a +new nation, conceived in Liberty, and dedicated to the proposition that all men +are created equal. + +Now we are engaged in a great civil war, testing whether that nation, or any +nation so conceived and so dedicated, can long endure. We are met on a great +battle-field of that war. We have come to dedicate a portion of that field, as a +final resting place for those who here gave their lives that that nation might +live. It is altogether fitting and proper that we should do this. + +But, in a larger sense, we can not dedicate -- we can not consecrate -- we can not +hallow -- this ground. The brave men, living and dead, who struggled here, have +consecrated it, far above our poor power to add or detract. The world will +little note, nor long remember what we say here, but it can never forget what +they did here. It is for us the living, rather, to be dedicated here to the +unfinished work which they who fought here have thus far so nobly advanced. It +is rather for us to be here dedicated to the great task remaining before us -- +that from these honored dead we take increased devotion to that cause for +which they gave the last full measure of devotion -- that we here highly resolve +that these dead shall not have died in vain -- that this nation, under God, shall +have a new birth of freedom -- and that government of the people, by the people, +for the people, shall not perish from the earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_11/Data/stopwords.txt b/CodeToAccompany9781430244646/ch07/sketch_7_11/Data/stopwords.txt new file mode 100644 index 0000000..0a1f0d2 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_11/Data/stopwords.txt @@ -0,0 +1,667 @@ +AT +A +a +able +about +above +abst +accordance +according +accordingly +across +act +actually +added +adj +adopted +affected +affecting +affects +after +afterwards +again +against +ah +al +all +almost +alone +along +already +also +although +always +am +among +amongst +an +and +announce +another +any +anybody +anyhow +anymore +anyone +anything +anyway +anyways +anywhere +apparently +approximately +are +aren +arent +arise +around +as +aside +ask +asking +at +auth +available +away +awfully +b +back +be +became +because +become +becomes +becoming +been +before +beforehand +begin +beginning +beginnings +begins +behind +being +believe +below +beside +besides +between +beyond +biol +both +brief +briefly +but +But +by +c +ca +came +can +cannot +cause +causes +certain +certainly +co +com +come +comes +contain +containing +contains +could +couldnt +d +date +did +didn +different +do +does +doesn +doing +done +don +down +downwards +due +during +e +each +ed +edu +effect +eg +eight +eighty +either +else +elsewhere +end +ending +enough +especially +et +etc +even +ever +every +everybody +everyone +everything +everywhere +ex +except +f +far +few +ff +fifth +first +five +fix +followed +following +follows +for +former +formerly +forth +found +four +from +further +furthermore +g +gave +get +gets +getting +give +given +gives +giving +go +goes +gone +got +gotten +h +had +happens +hardly +has +hasn +have +haven +having +he +hed +hence +her +here +hereafter +hereby +herein +heres +hereupon +hers +herself +hes +hi +hid +him +himself +his +hither +home +how +howbeit +however +hundred +i +id +ie +if +im +immediate +immediately +importance +important +in +In +inc +indeed +index +information +instead +into +invention +inward +is +isn +it +It +itd +its +itself +j +just +k +keep +keeps +kept +keys +kg +km +know +known +knows +l +largely +last +lately +later +latter +latterly +least +less +lest +let +lets +like +liked +likely +line +little +look +looking +looks +ltd +m +made +mainly +make +makes +many +may +maybe +me +mean +means +meantime +meanwhile +merely +mg +might +million +miss +ml +more +moreover +most +mostly +mr +mrs +much +mug +must +my +myself +n +na +name +namely +nay +nd +near +nearly +necessarily +necessary +need +needs +neither +never +nevertheless +new +next +nine +ninety +no +nobody +non +none +nonetheless +noone +nor +normally +nos +not +noted +nothing +now +nowhere +o +obtain +obtained +obviously +of +off +often +oh +ok +okay +old +omitted +on +once +one +ones +only +onto +or +ord +other +others +otherwise +ought +our +Our +ours +ourselves +out +outside +over +overall +owing +own +p +page +pages +part +particular +particularly +past +per +perhaps +placed +please +plus +poorly +possible +possibly +potentially +pp +predominantly +present +previously +primarily +probably +promptly +proud +provides +put +q +que +quickly +quite +qv +r +ran +rather +rd +re +readily +really +recent +recently +ref +refs +regarding +regardless +regards +related +relatively +research +respectively +resulted +resulting +results +right +run +s +said +same +saw +say +saying +says +sec +section +see +seeing +seem +seemed +seeming +seems +seen +self +selves +sent +seven +several +shall +she +shed +shes +should +shouldn +show +showed +shown +showns +shows +significant +significantly +similar +similarly +since +six +slightly +so +So +some +somebody +somehow +someone +somethan +something +sometime +sometimes +somewhat +somewhere +soon +sorry +specifically +specified +specify +specifying +state +states +still +stop +strongly +sub +substantially +successfully +such +sufficiently +suggest +sup +sure +t +take +taken +taking +tell +tends +th +than +thank +thanks +thanx +that +thats +the +their +Their +theirs +them +themselves +then +thence +there +There +thereafter +thereby +thered +therefore +therein +thereof +therere +theres +thereto +thereupon +these +They +These +they +theyd +theyre +think +this +This +those +Those +thou +though +thoughh +thousand +throug +through +throughout +thru +thus +til +tip +to +together +too +took +toward +towards +tried +tries +truly +try +trying +ts +twice +two +u +un +under +unfortunately +unless +unlike +unlikely +until +unto +up +upon +ups +us +use +used +useful +usefully +usefulness +uses +using +usually +v +value +various +ve +very +via +viz +vol +vols +vs +w +want +wants +was +wasn +way +we +wed +welcom +went +were +weren +what +whatever +whats +when +whence +whenever +where +whereafter +whereas +whereby +wherein +wheres +whereupon +wherever +whether +which +while +whim +whither +who +whod +whoever +whole +whom +whomever +whos +whose +why +widely +will +willing +wish +with +within +without +words +world +would +wouldn +www +x +y +yes +yet +you +youd +your +Your +youre +yours +yourself +yourselves +z +zero \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_11/Word.pde b/CodeToAccompany9781430244646/ch07/sketch_7_11/Word.pde new file mode 100644 index 0000000..f4bb883 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_11/Word.pde @@ -0,0 +1,48 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-11: Word Cloud Visualization +// Sketch 7-11: The Word class +class Word implements Comparable { + + // Each Word is a pair: the word, and its frequency + String word; + int freq; + + Word(String newWord) { // Constructor + word = newWord; + freq = 1; + } // Word() + + String getWord() { + return word; + } // getWord() + + int getFreq() { + return freq; + } // getFreq() + + void incr() { // increments the word count + freq++; + } // incr() + + public int compareTo(Word w) { + //return word.compareTo(w.word); + return freq - w.freq; + } + + String toString() { // print representation of Word objects + return "<"+word+", "+freq+">"; + } +} // class Word + diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_11/WordFreq.pde b/CodeToAccompany9781430244646/ch07/sketch_7_11/WordFreq.pde new file mode 100644 index 0000000..9708776 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_11/WordFreq.pde @@ -0,0 +1,188 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-11: Word Cloud Visualization +// Sketch 7-11: The Word frequency table class + +class WordFreq { + // A Frequency table class for Words + ArrayList wordFrequency; + String [] stopWords = loadStrings("stopwords.txt"); + + WordFreq(String[] tokens) { // Constructor + + wordFrequency = new ArrayList(); + + // Compute the wordFrequency table using tokens + for (String t : tokens) { + if (!_isStopWord(t, stopWords)) { + // See if token t is already a known word + int index = _search(t, wordFrequency); + if (index >= 0) { + ( wordFrequency.get(index)).incr(); + } + else { + wordFrequency.add(new WordTile(t)); + } + } + } // for + // Sort the table in reverse order of frequencies + _sort(wordFrequency); + //Collections.sort(wordFrequency, Collections.reverseOrder()); + } // WordFreq() + + void tabulate(int n) { // console printout + //int n = wordFrequency.size(); + println("There are "+N()+" entries."); + for (int i=0; i < n; i++) { + println(wordFrequency.get(i)); + } + } // tabulate + + void arrange(int N) { // arrange or map the first N tiles in sketch + WordTile tile; + for (int i=0; i < N; i++) { + tile = wordFrequency.get(i); + tile.setFontSize(); + + // Exploring the spiral layout + float cx = width/2-50, cy = height/2, px, py; + float R = 0.0, dR = 0.2, theta = 0.0, dTheta = 0.5; + do { // find the next x, y for tile, i in spiral + float x = cx + R*cos(theta); + float y = cy + R*sin(theta); + tile.setXY(x, y); + px = x; + py = y; + theta+=dTheta; + R += dR; + } // until the tile is clear of all other tiles + while (!clear (i)); + } + } // arrange() + + boolean clear(int n) { // Is tile, i clear of tiles 0..i-1? + WordTile tile1 = wordFrequency.get(n); + for (int i=0; i < n; i++) { + WordTile tile2 = wordFrequency.get(i); + if (tile1.intersect(tile2)) { + return false; + } + } // for + return true; + } // clear() + + void display(int N) { + for (int i=0; i < N; i++) { + WordTile tile = wordFrequency.get(i); + tile.display(); + } + } // display() + + void interact(float mx, float my) { + // Find out which tile was clicked + WordTile tile = _searchTile(wordFrequency, mx, my); + + println("Tile Clicked: "+tile); + // Do something on it + if (tile != null) { + tile.tileColor = color(255, 0, 0); + tile.display(); + } + } // interact() + + int N() { // Number of table entries + return wordFrequency.size(); + } // N() + + String[] samples() { // Returns all the words + String [] k = new String[N()]; + int i=0; + for (Word w : wordFrequency) { + k[i++] = w.getWord(); + } + return k; + } // keys() + + int[] counts() { // Returns all the frequencies + int [] v = new int[N()]; + int i=0; + for (Word w : wordFrequency) { + v[i++] = w.getFreq(); + } + return v; + } // values() + + int maxFreq() { // The max frequency + return max(counts()); + } // maxFreq() + + int _search(String w, ArrayList L) { + // Search for word, w in L + for (int i=0; i < L.size(); i++) { + if (L.get(i).getWord().equals(w)) + return i; + } + return -1; + } // search() + + WordTile _searchTile(ArrayList L, float mx, float my) { + + for (int i=0; i < L.size(); i++) { + WordTile tile = L.get(i); + if (ptInTile(tile, mx, my)) { + return(tile); + } + } + return null; + } // _searchTile() + + boolean ptInTile(WordTile t, float x, float y) { + float x1 = t.location.x; + float y1 = t.location.y - t.tileH; + float x2 = x1+t.tileW; + float y2 = t.location.y; + + return ((x >= x1 && x <= x2) && (y >= y1 && y <= y2)); + } // ptInTile() + boolean _isStopWord(String word, String[] stopWords) { + for (String stopWord : stopWords) { + if (word.equals(stopWord)) { + return true; + } + } + return false; + } // isStopWord() + + void _sort(ArrayList A) { // sort the array A in ascending order + // for i=1 through N-1: + for (int i=0; i < A.size(); i++) { + // insert A[i] in A[0] .. A[i] such that A[0] <= A[1] <= … <= A[i] + WordTile a = A.get(i); // Save A[i] in p + int pos = i; + //while ( (pos > 0) && (A.get(pos-1).getFreq() < a.getFreq())) { + while ( (pos > 0) && (a.compareTo(A.get(pos-1))>0)) { + // Move A[pos-1] back by 1 + A.set(pos, A.get(pos-1)); + pos--; + } // while + // A[pos] is where a gets inserted + A.set(pos, a); + }// for + } // _sort + + String toString() { // Print representation + return "Word Frequency Table with"+N()+" entries."; + } // toString() +} // class WordFreq + diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_11/WordTile.pde b/CodeToAccompany9781430244646/ch07/sketch_7_11/WordTile.pde new file mode 100644 index 0000000..031ba28 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_11/WordTile.pde @@ -0,0 +1,63 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-11: Word Cloud Visualization +// The WordTile class +class WordTile extends Word { + // A graphical tile conatining a word and additional attributes + PVector location; // The top left corner of the tile (x, y) + float tileW, tileH; // width and height of the tile + color tileColor; // fill color of word + float tileFS = 24; // the font size of tile, default is 24 + + WordTile(String newWord) { // Constructor + super(newWord); + setSize(); + location = new PVector(0, 0); + tileColor = color(0); + } // WordTile() + + void setXY (float x, float y) { + location.x = x; + location.y = y; + } // setXY() + + void setFontSize() { + tileFS = map(freq, 1, 30, 10, 120); + setSize(); + } // setFontSize() + + void setSize() { + textSize(tileFS); + tileW = textWidth(word); + tileH = textAscent(); + } // setTileSize() + + boolean intersect(WordTile t2) { + float left1 = location.x; // the first tile’s bounding box + float right1 = location.x+tileW; + float top1 = location.y-tileH; + float bot1 = location.y; + float left2 = t2.location.x; // the second tile’s bounding box + float right2 = left2+t2.tileW; + float bot2 = t2.location.y; + float top2 = bot2-t2.tileH; + return !(right1 < left2 || left1 > right2 || bot1 < top2 || top1 > bot2); // testing intersection + } // intersect() + + void display() { + fill(tileColor); + textSize(tileFS); + text(word, location.x, location.y); + } // display() +} // class WordTile diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_11/sketch_7_11.pde b/CodeToAccompany9781430244646/ch07/sketch_7_11/sketch_7_11.pde new file mode 100644 index 0000000..8c7ea63 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_11/sketch_7_11.pde @@ -0,0 +1,51 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-11: Word Cloud Visualization +import processing.opengl.*; +String inputTextFile = "Obama.txt"; +WordFreq table; +PFont tnr; // The font to be used +int N = 150; // The number of words to be displayed + +void setup() { + // Input and parse text file + String [] fileContents = loadStrings(inputTextFile); + String rawText = join(fileContents, " "); + rawText = rawText.toLowerCase(); + String [] tokens; + String delimiters = " ,./?<>;:'\"[{]}\\|=+-_()*&^%$#@!~"; + tokens = splitTokens(rawText, delimiters); + println(tokens.length+" tokens found in file: "+inputTextFile); + // display stuff + size(800, 800, OPENGL); + tnr = createFont("Times New Roman", 120); + textFont(tnr); + textSize(24); + noLoop(); + // Create the word frequency table + table = new WordFreq(tokens); + println("Max frequency:"+table.maxFreq()); + table.arrange(N); +} // setup() + +void draw() { + background(255); + table.display(N); + table.tabulate(N); +} // draw() + +// Bonus: The start of building interaction... +void mouseClicked() { + table.interact(mouseX, mouseY); +} // mouseClicked() diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_2/Data/Obama.txt b/CodeToAccompany9781430244646/ch07/sketch_7_2/Data/Obama.txt new file mode 100644 index 0000000..5dd7b12 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_2/Data/Obama.txt @@ -0,0 +1,239 @@ +Your Majesties, Your Royal Highnesses, Distinguished Members of the Norwegian Nobel Committee, citizens of America, and citizens of the world: + +I receive this honor with deep gratitude and great humility. It is an award that speaks to our highest aspirations - that for all the cruelty +and hardship of our world, we are not mere prisoners of fate. Our actions matter, and can bend history in the direction of justice. + +And yet I would be remiss if I did not acknowledge the considerable controversy that your generous decision has generated. In part, this is +because I am at the beginning, and not the end, of my labors on the world stage. Compared to some of the giants of history who have received +this prize - Schweitzer and King; Marshall and Mandela - my accomplishments are slight. And then there are the men and women around the world +who have been jailed and beaten in the pursuit of justice; those who toil in humanitarian organizations to relieve suffering; the unrecognized +millions whose quiet acts of courage and compassion inspire even the most hardened of cynics. I cannot argue with those who find these men and +women - some known, some obscure to all but those they help - to be far more deserving of this honor than I. + +But perhaps the most profound issue surrounding my receipt of this prize is the fact that I am the Commander-in-Chief of a nation in the midst +of two wars. One of these wars is winding down. The other is a conflict that America did not seek; one in which we are joined by forty three other +countries - including Norway - in an effort to defend ourselves and all nations from further attacks. + +Still, we are at war, and I am responsible for the deployment of thousands of young Americans to battle in a distant land. Some will kill. Some +will be killed. And so I come here with an acute sense of the cost of armed conflict - filled with difficult questions about the relationship +between war and peace, and our effort to replace one with the other. + +These questions are not new. War, in one form or another, appeared with the first man. At the dawn of history, its morality was not questioned; +it was simply a fact, like drought or disease - the manner in which tribes and then civilizations sought power and settled their differences. + + +Over time, as codes of law sought to control violence within groups, so did philosophers, clerics, and statesmen seek to regulate the destructive +power of war. The concept of a "just war" emerged, suggesting that war is justified only when it meets certain preconditions: if it is waged +as a last resort or in self-defense; if the forced used is proportional, and if, whenever possible, civilians are spared from violence. + +For most of history, this concept of just war was rarely observed. The capacity of human beings to think up new ways to kill one another proved +inexhaustible, as did our capacity to exempt from mercy those who look different or pray to a different God. Wars between armies gave way to wars +between nations - total wars in which the distinction between combatant and civilian became blurred. In the span of thirty years, such carnage +would twice engulf this continent. And while it is hard to conceive of a cause more just than the defeat of the Third Reich and the Axis powers, +World War II was a conflict in which the total number of civilians who died exceeded the number of soldiers who perished. + +In the wake of such destruction, and with the advent of the nuclear age, it became clear to victor and vanquished alike that the world needed +institutions to prevent another World War. And so, a quarter century after the United States Senate rejected the League of Nations - an idea for +which Woodrow Wilson received this Prize - America led the world in constructing an architecture to keep the peace: a Marshall Plan and a +United Nations, mechanisms to govern the waging of war, treaties to protect human rights, prevent genocide, and restrict the most dangerous weapons. + +In many ways, these efforts succeeded. Yes, terrible wars have been fought, and atrocities committed. But there has been no Third World War. The Cold +War ended with jubilant crowds dismantling a wall. Commerce has stitched much of the world together. Billions have been lifted from poverty. The ideals +of liberty, self-determination, equality and the rule of law have haltingly advanced. We are the heirs of the fortitude and foresight of generations +past, and it is a legacy for which my own country is rightfully proud. + +A decade into a new century, this old architecture is buckling under the weight of new threats. The world may no longer shudder at the prospect of +war between two nuclear superpowers, but proliferation may increase the risk of catastrophe. Terrorism has long been a tactic, but modern technology +allows a few small men with outsized rage to murder innocents on a horrific scale. + +Moreover, wars between nations have increasingly given way to wars within nations. The resurgence of ethnic or sectarian conflicts; the growth +of secessionist movements, insurgencies, and failed states; have increasingly trapped civilians in unending chaos. In today's wars, many more +civilians are killed than soldiers; the seeds of future conflict are sewn, economies are wrecked, civil societies torn asunder, refugees +amassed, and children scarred. + +I do not bring with me today a definitive solution to the problems of war. What I do know is that meeting these challenges will require +the same vision, hard work, and persistence of those men and women who acted so boldly decades ago. And it will require us to think in +new ways about the notions of just war and the imperatives of a just peace. + +We must begin by acknowledging the hard truth that we will not eradicate violent conflict in our lifetimes. There will be times when +nations - acting individually or in concert - will find the use of force not only necessary but morally justified. + +I make this statement mindful of what Martin Luther King said in this same ceremony years ago - "Violence never brings permanent peace. It +solves no social problem: it merely creates new and more complicated ones." As someone who stands here as a direct consequence of Dr. King's +life's work, I am living testimony to the moral force of non-violence. I know there is nothing weak -nothing passive - nothing naïve - in the +creed and lives of Gandhi and King. + +But as a head of state sworn to protect and defend my nation, I cannot be guided by their examples alone. I face the world as it is, and +cannot stand idle in the face of threats to the American people. For make no mistake: evil does exist in the world. A non-violent movement +could not have halted Hitler's armies. Negotiations cannot convince al Qaeda's leaders to lay down their arms. To say that force is sometimes +necessary is not a call to cynicism - it is a recognition of history; the imperfections of man and the limits of reason. + +I raise this point because in many countries there is a deep ambivalence about military action today, no matter the cause. At times, this +is joined by a reflexive suspicion of America, the world's sole military superpower. + +Yet the world must remember that it was not simply international institutions - not just treaties and declarations - that brought stability +to a post-World War II world. Whatever mistakes we have made, the plain fact is this: the United States of America has helped underwrite +global security for more than six decades with the blood of our citizens and the strength of our arms. The service and sacrifice of our +men and women in uniform has promoted peace and prosperity from Germany to Korea, and enabled democracy to take hold in places like the +Balkans. We have borne this burden not because we seek to impose our will. We have done so out of enlightened self-interest - because +we seek a better future for our children and grandchildren, and we believe that their lives will be better if other peoples' children +and grandchildren can live in freedom and prosperity. + +So yes, the instruments of war do have a role to play in preserving the peace. And yet this truth must coexist with another - that +no matter how justified, war promises human tragedy. The soldier's courage and sacrifice is full of glory, expressing devotion to +country, to cause and to comrades in arms. But war itself is never glorious, and we must never trumpet it as such. + +So part of our challenge is reconciling these two seemingly irreconcilable truths - that war is sometimes necessary, and war is at +some level an expression of human feelings. Concretely, we must direct our effort to the task that President Kennedy called for long +ago. "Let us focus," he said, "on a more practical, more attainable peace, based not on a sudden revolution in human nature but +on a gradual evolution in human institutions." + +What might this evolution look like? What might these practical steps be? + +To begin with, I believe that all nations - strong and weak alike - must adhere to standards that govern the use of force. I - like any +head of state - reserve the right to act unilaterally if necessary to defend my nation. Nevertheless, I am convinced that adhering +to standards strengthens those who do, and isolates - and weakens - those who don't. + +The world rallied around America after the 9/11 attacks, and continues to support our efforts in Afghanistan, because of the horror +of those senseless attacks and the recognized principle of self-defense. Likewise, the world recognized the need to confront Saddam +Hussein when he invaded Kuwait - a consensus that sent a clear message to all about the cost of aggression. + +Furthermore, America cannot insist that others follow the rules of the road if we refuse to follow them ourselves. For when we don't, +our action can appear arbitrary, and undercut the legitimacy of future intervention - no matter how justified. + +This becomes particularly important when the purpose of military action extends beyond self defense or the defense of one nation +against an aggressor. More and more, we all confront difficult questions about how to prevent the slaughter of civilians by their +own government, or to stop a civil war whose violence and suffering can engulf an entire region. + +I believe that force can be justified on humanitarian grounds, as it was in the Balkans, or in other places that have been scarred +by war. Inaction tears at our conscience and can lead to more costly intervention later. That is why all responsible nations must +embrace the role that militaries with a clear mandate can play to keep the peace. + +America's commitment to global security will never waiver. But in a world in which threats are more diffuse, and missions more +complex, America cannot act alone. This is true in Afghanistan. This is true in failed states like Somalia, where terrorism and +piracy is joined by famine and human suffering. And sadly, it will continue to be true in unstable regions for years to come. + +The leaders and soldiers of NATO countries - and other friends and allies - demonstrate this truth through the capacity and courage +they have shown in Afghanistan. But in many countries, there is a disconnect between the efforts of those who serve and the ambivalence +of the broader public. I understand why war is not popular. But I also know this: the belief that peace is desirable is rarely enough to achieve it. Peace requires responsibility. Peace entails sacrifice. That is why NATO continues to be indispensable. That is why we must strengthen UN and regional peacekeeping, and not leave the task to a few countries. That is why we honor those who return home from peacekeeping and training abroad to Oslo and Rome; to Ottawa and Sydney; to Dhaka and Kigali - we honor them not as makers of war, but as wagers of peace. + +Let me make one final point about the use of force. Even as we make difficult decisions about going to war, we must also think clearly +about how we fight it. The Nobel Committee recognized this truth in awarding its first prize for peace to Henry Dunant - the founder +of the Red Cross, and a driving force behind the Geneva Conventions. + +Where force is necessary, we have a moral and strategic interest in binding ourselves to certain rules of conduct. And even as we +confront a vicious adversary that abides by no rules, I believe that the United States of America must remain a standard bearer in +the conduct of war. That is what makes us different from those whom we fight. That is a source of our strength. That is why I +prohibited torture. That is why I ordered the prison at Guantanamo Bay closed. And that is why I have reaffirmed America's +commitment to abide by the Geneva Conventions. We lose ourselves when we compromise the very ideals that we fight to defend. +And we honor those ideals by upholding them not just when it is easy, but when it is hard. + +I have spoken to the questions that must weigh on our minds and our hearts as we choose to wage war. But let me turn now to +our effort to avoid such tragic choices, and speak of three ways that we can build a just and lasting peace. + +First, in dealing with those nations that break rules and laws, I believe that we must develop alternatives to violence that +are tough enough to change behavior - for if we want a lasting peace, then the words of the international community must mean +something. Those regimes that break the rules must be held accountable. Sanctions must exact a real price. Intransigence must +be met with increased pressure - and such pressure exists only when the world stands together as one. + +One urgent example is the effort to prevent the spread of nuclear weapons, and to seek a world without them. In the middle of +the last century, nations agreed to be bound by a treaty whose bargain is clear: all will have access to peaceful nuclear power; +those without nuclear weapons will forsake them; and those with nuclear weapons will work toward disarmament. I am committed to +upholding this treaty. It is a centerpiece of my foreign policy. And I am working with President Medvedev to reduce America a +nd Russia's nuclear stockpiles. + +But it is also incumbent upon all of us to insist that nations like Iran and North Korea do not game the system. Those who +claim to respect international law cannot avert their eyes when those laws are flouted. Those who care for their own security +cannot ignore the danger of an arms race in the Middle East or East Asia. Those who seek peace cannot stand idly by as nations +arm themselves for nuclear war. + +The same principle applies to those who violate international law by brutalizing their own people. When there is genocide in +Darfur; systematic rape in Congo; or repression in Burma - there must be consequences. And the closer we stand together, the +less likely we will be faced with the choice between armed intervention and complicity in oppression. + +This brings me to a second point - the nature of the peace that we seek. For peace is not merely the absence of visible conflict. +Only a just peace based upon the inherent rights and dignity of every individual can truly be lasting. + +It was this insight that drove drafters of the Universal Declaration of Human Rights after the Second World War. In the wake of +devastation, they recognized that if human rights are not protected, peace is a hollow promise. + +And yet all too often, these words are ignored. In some countries, the failure to uphold human rights is excused by the false +suggestion that these are Western principles, foreign to local cultures or stages of a nation's development. And within America, +there has long been a tension between those who describe themselves as realists or idealists - a tension that suggests a stark +choice between the narrow pursuit of interests or an endless campaign to impose our values. + +I reject this choice. I believe that peace is unstable where citizens are denied the right to speak freely or worship as they +please; choose their own leaders or assemble without fear. Pent up grievances fester, and the suppression of tribal and religious +identity can lead to violence. We also know that the opposite is true. Only when Europe became free did it finally find peace. +America has never fought a war against a democracy, and our closest friends are governments that protect the rights of their +citizens. No matter how callously defined, neither America's interests - nor the world's -are served by the denial of human aspirations. + +So even as we respect the unique culture and traditions of different countries, America will always be a voice for those aspirations +that are universal. We will bear witness to the quiet dignity of reformers like Aung Sang Suu Kyi; to the bravery of Zimbabweans who +cast their ballots in the face of beatings; to the hundreds of thousands who have marched silently through the streets of Iran. It is +telling that the leaders of these governments fear the aspirations of their own people more than the power of any other nation. And +it is the responsibility of all free people and free nations to make clear to these movements that hope and history are on their side + +Let me also say this: the promotion of human rights cannot be about exhortation alone. At times, it must be coupled with painstaking +diplomacy. I know that engagement with repressive regimes lacks the satisfying purity of indignation. But I also know that sanctions +without outreach - and condemnation without discussion - can carry forward a crippling status quo. No repressive regime can move down +a new path unless it has the choice of an open door. + +In light of the Cultural Revolution's horrors, Nixon's meeting with Mao appeared inexcusable - and yet it surely helped set China on +a path where millions of its citizens have been lifted from poverty, and connected to open societies. Pope John Paul's engagement +with Poland created space not just for the Catholic Church, but for labor leaders like Lech Walesa. Ronald Reagan's efforts on arms control and embrace of perestroika not only improved relations with the Soviet Union, but empowered dissidents throughout Eastern Europe. There is no simple formula here. But we must try as best we can to balance isolation and engagement; pressure and incentives, so that human rights and dignity are advanced over time. + +Third, a just peace includes not only civil and political rights - it must encompass economic security and opportunity. For true +peace is not just freedom from fear, but freedom from want. + +It is undoubtedly true that development rarely takes root without security; it is also true that security does not exist where +human beings do not have access to enough food, or clean water, or the medicine they need to survive. It does not exist where +children cannot aspire to a decent education or a job that supports a family. The absence of hope can rot a society from within. + +And that is why helping farmers feed their own people - or nations educate their children and care for the sick - is not mere +charity. It is also why the world must come together to confront climate change. There is little scientific dispute that if we +do nothing, we will face more drought, famine and mass displacement that will fuel more conflict for decades. For this reason, it is not merely scientists and activists who call for swift and forceful action - it is military leaders in my country and others who understand that our common security hangs in the balance. + +Agreements among nations. Strong institutions. Support for human rights. Investments in development. All of these are vital +ingredients in bringing about the evolution that President Kennedy spoke about. And yet, I do not believe that we will have the will, +or the staying power, to complete this work without something more - and that is the continued expansion of our moral imagination; +an insistence that there is something irreducible that we all share. + +As the world grows smaller, you might think it would be easier for human beings to recognize how similar we are; to understand that +we all basically want the same things; that we all hope for the chance to live out our lives with some measure of happiness and +fulfillment for ourselves and our families. + +And yet, given the dizzying pace of globalization, and the cultural leveling of modernity, it should come as no surprise that people +fear the loss of what they cherish about their particular identities - their race, their tribe, and perhaps most powerfully their +religion. In some places, this fear has led to conflict. At times, it even feels like we are moving backwards. We see it in Middle +East, as the conflict between Arabs and Jews seems to harden. We see it in nations that are torn asunder by tribal lines. + +Most dangerously, we see it in the way that religion is used to justify the murder of innocents by those who have distorted and +defiled the great religion of Islam, and who attacked my country from Afghanistan. These extremists are not the first to kill in +the name of God; the cruelties of the Crusades are amply recorded. But they remind us that no Holy War can ever be a just war. For if you truly believe that you are carrying out divine will, then there is no need for restraint - no need to spare the pregnant mother, or the medic, or even a person of one's own faith. Such a warped view of religion is not just incompatible with the concept of peace, but the purpose of faith - for the one rule that lies at the heart of every major religion is that we do unto others as we would have them do unto us. + +Adhering to this law of love has always been the core struggle of human nature. We are fallible. We make mistakes, and fall +victim to the temptations of pride, and power, and sometimes evil. Even those of us with the best intentions will at times +fail to right the wrongs before us. + +But we do not have to think that human nature is perfect for us to still believe that the human condition can be perfected. +We do not have to live in an idealized world to still reach for those ideals that will make it a better place. The non-violence +practiced by men like Gandhi and King may not have been practical or possible in every circumstance, but the love that they preached - +their faith in human progress - must always be the North Star that guides us on our journey. + +For if we lose that faith - if we dismiss it as silly or naïve; if we divorce it from the decisions that we make on issues of war +and peace - then we lose what is best about humanity. We lose our sense of possibility. We lose our moral compass. + +Like generations have before us, we must reject that future. As Dr. King said at this occasion so many years ago, "I refuse to +accept despair as the final response to the ambiguities of history. I refuse to accept the idea that the 'isness' of man's present +nature makes him morally incapable of reaching up for the eternal 'oughtness' that forever confronts him." + +So let us reach for the world that ought to be - that spark of the divine that still stirs within each of our souls. Somewhere +today, in the here and now, a soldier sees he's outgunned but stands firm to keep the peace. Somewhere today, in this world, +a young protestor awaits the brutality of her government, but has the courage to march on. Somewhere today, a mother facing +punishing poverty still takes the time to teach her child, who believes that a cruel world still has a place for his dreams. + +Let us live by their example. We can acknowledge that oppression will always be with us, and still strive for justice. We +can admit the intractability of depravation, and still strive for dignity. We can understand that there will be war, and +still strive for peace. We can do that - for that is the story of human progress; that is the hope of all the world; and +at this moment of challenge, that must be our work here on Earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_2/Data/gettysburg.txt b/CodeToAccompany9781430244646/ch07/sketch_7_2/Data/gettysburg.txt new file mode 100644 index 0000000..1d9643e --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_2/Data/gettysburg.txt @@ -0,0 +1,22 @@ +Four score and seven years ago our fathers brought forth on this continent, a +new nation, conceived in Liberty, and dedicated to the proposition that all men +are created equal. + +Now we are engaged in a great civil war, testing whether that nation, or any +nation so conceived and so dedicated, can long endure. We are met on a great +battle-field of that war. We have come to dedicate a portion of that field, as a +final resting place for those who here gave their lives that that nation might +live. It is altogether fitting and proper that we should do this. + +But, in a larger sense, we can not dedicate -- we can not consecrate -- we can not +hallow -- this ground. The brave men, living and dead, who struggled here, have +consecrated it, far above our poor power to add or detract. The world will +little note, nor long remember what we say here, but it can never forget what +they did here. It is for us the living, rather, to be dedicated here to the +unfinished work which they who fought here have thus far so nobly advanced. It +is rather for us to be here dedicated to the great task remaining before us -- +that from these honored dead we take increased devotion to that cause for +which they gave the last full measure of devotion -- that we here highly resolve +that these dead shall not have died in vain -- that this nation, under God, shall +have a new birth of freedom -- and that government of the people, by the people, +for the people, shall not perish from the earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_2/Data/stopwords.txt b/CodeToAccompany9781430244646/ch07/sketch_7_2/Data/stopwords.txt new file mode 100644 index 0000000..0a1f0d2 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_2/Data/stopwords.txt @@ -0,0 +1,667 @@ +AT +A +a +able +about +above +abst +accordance +according +accordingly +across +act +actually +added +adj +adopted +affected +affecting +affects +after +afterwards +again +against +ah +al +all +almost +alone +along +already +also +although +always +am +among +amongst +an +and +announce +another +any +anybody +anyhow +anymore +anyone +anything +anyway +anyways +anywhere +apparently +approximately +are +aren +arent +arise +around +as +aside +ask +asking +at +auth +available +away +awfully +b +back +be +became +because +become +becomes +becoming +been +before +beforehand +begin +beginning +beginnings +begins +behind +being +believe +below +beside +besides +between +beyond +biol +both +brief +briefly +but +But +by +c +ca +came +can +cannot +cause +causes +certain +certainly +co +com +come +comes +contain +containing +contains +could +couldnt +d +date +did +didn +different +do +does +doesn +doing +done +don +down +downwards +due +during +e +each +ed +edu +effect +eg +eight +eighty +either +else +elsewhere +end +ending +enough +especially +et +etc +even +ever +every +everybody +everyone +everything +everywhere +ex +except +f +far +few +ff +fifth +first +five +fix +followed +following +follows +for +former +formerly +forth +found +four +from +further +furthermore +g +gave +get +gets +getting +give +given +gives +giving +go +goes +gone +got +gotten +h +had +happens +hardly +has +hasn +have +haven +having +he +hed +hence +her +here +hereafter +hereby +herein +heres +hereupon +hers +herself +hes +hi +hid +him +himself +his +hither +home +how +howbeit +however +hundred +i +id +ie +if +im +immediate +immediately +importance +important +in +In +inc +indeed +index +information +instead +into +invention +inward +is +isn +it +It +itd +its +itself +j +just +k +keep +keeps +kept +keys +kg +km +know +known +knows +l +largely +last +lately +later +latter +latterly +least +less +lest +let +lets +like +liked +likely +line +little +look +looking +looks +ltd +m +made +mainly +make +makes +many +may +maybe +me +mean +means +meantime +meanwhile +merely +mg +might +million +miss +ml +more +moreover +most +mostly +mr +mrs +much +mug +must +my +myself +n +na +name +namely +nay +nd +near +nearly +necessarily +necessary +need +needs +neither +never +nevertheless +new +next +nine +ninety +no +nobody +non +none +nonetheless +noone +nor +normally +nos +not +noted +nothing +now +nowhere +o +obtain +obtained +obviously +of +off +often +oh +ok +okay +old +omitted +on +once +one +ones +only +onto +or +ord +other +others +otherwise +ought +our +Our +ours +ourselves +out +outside +over +overall +owing +own +p +page +pages +part +particular +particularly +past +per +perhaps +placed +please +plus +poorly +possible +possibly +potentially +pp +predominantly +present +previously +primarily +probably +promptly +proud +provides +put +q +que +quickly +quite +qv +r +ran +rather +rd +re +readily +really +recent +recently +ref +refs +regarding +regardless +regards +related +relatively +research +respectively +resulted +resulting +results +right +run +s +said +same +saw +say +saying +says +sec +section +see +seeing +seem +seemed +seeming +seems +seen +self +selves +sent +seven +several +shall +she +shed +shes +should +shouldn +show +showed +shown +showns +shows +significant +significantly +similar +similarly +since +six +slightly +so +So +some +somebody +somehow +someone +somethan +something +sometime +sometimes +somewhat +somewhere +soon +sorry +specifically +specified +specify +specifying +state +states +still +stop +strongly +sub +substantially +successfully +such +sufficiently +suggest +sup +sure +t +take +taken +taking +tell +tends +th +than +thank +thanks +thanx +that +thats +the +their +Their +theirs +them +themselves +then +thence +there +There +thereafter +thereby +thered +therefore +therein +thereof +therere +theres +thereto +thereupon +these +They +These +they +theyd +theyre +think +this +This +those +Those +thou +though +thoughh +thousand +throug +through +throughout +thru +thus +til +tip +to +together +too +took +toward +towards +tried +tries +truly +try +trying +ts +twice +two +u +un +under +unfortunately +unless +unlike +unlikely +until +unto +up +upon +ups +us +use +used +useful +usefully +usefulness +uses +using +usually +v +value +various +ve +very +via +viz +vol +vols +vs +w +want +wants +was +wasn +way +we +wed +welcom +went +were +weren +what +whatever +whats +when +whence +whenever +where +whereafter +whereas +whereby +wherein +wheres +whereupon +wherever +whether +which +while +whim +whither +who +whod +whoever +whole +whom +whomever +whos +whose +why +widely +will +willing +wish +with +within +without +words +world +would +wouldn +www +x +y +yes +yet +you +youd +your +Your +youre +yours +yourself +yourselves +z +zero \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_2/Word.pde b/CodeToAccompany9781430244646/ch07/sketch_7_2/Word.pde new file mode 100644 index 0000000..c0cfefe --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_2/Word.pde @@ -0,0 +1,35 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-2: Using Arraylists for word frequencies +class Word { + // Each Word is a pair: the word, and its frequency + String word; + int freq; + Word(String newWord) { // Constructor + word = newWord; + freq = 1; + } // Word() + String getWord() { + return word; + } // getWord() + int getFreq() { + return freq; + } // getFreq() + void incr() { // increments the word count + freq++; + } // incr() + String toString() { // print representation of Word objects + return "<"+word+", "+freq+">"; + } +} // class Word diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_2/sketch_7_2.pde b/CodeToAccompany9781430244646/ch07/sketch_7_2/sketch_7_2.pde new file mode 100644 index 0000000..9b831d3 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_2/sketch_7_2.pde @@ -0,0 +1,40 @@ +// Sketch 7-2: Using ArrayLists for word frequencies +String inputTextFile = "Obama.txt"; +String [] fileContents; +String rawText; +String [] tokens; +String delimiters = " ,./?<>;:'\"[{]}\\|=+-_()*&^%$#@!~"; +ArrayList wordFrequency = new ArrayList(); +void setup() { + // Input and parse text file + fileContents = loadStrings(inputTextFile); + rawText = join(fileContents, " "); + rawText = rawText.toLowerCase(); + tokens = splitTokens(rawText, delimiters); + // print out the number of tokens found + println(tokens.length+" tokens found in file: "+inputTextFile); + // Compute the wordFrequency table using tokens + for (String t : tokens) { + // See if token t is already a known word + int index = search(t, wordFrequency); + if (index >= 0) { + wordFrequency.get(index).incr(); + } + else { + wordFrequency.add(new Word(t)); + } // if + } // for + println("There were "+wordFrequency.size()+" words."); + for (int i=0; i < wordFrequency.size(); i++) { + println(wordFrequency.get(i)); + } +} // setup() +int search(String w, ArrayList L) { + // search for word w in L. + // Returns index of w in L if found, -1 o/w + for (int i=0; i < L.size(); i++) { + if (L.get(i).getWord().equals(w)) + return i; + } + return -1; +} // search() diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_3/Data/Obama.txt b/CodeToAccompany9781430244646/ch07/sketch_7_3/Data/Obama.txt new file mode 100644 index 0000000..5dd7b12 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_3/Data/Obama.txt @@ -0,0 +1,239 @@ +Your Majesties, Your Royal Highnesses, Distinguished Members of the Norwegian Nobel Committee, citizens of America, and citizens of the world: + +I receive this honor with deep gratitude and great humility. It is an award that speaks to our highest aspirations - that for all the cruelty +and hardship of our world, we are not mere prisoners of fate. Our actions matter, and can bend history in the direction of justice. + +And yet I would be remiss if I did not acknowledge the considerable controversy that your generous decision has generated. In part, this is +because I am at the beginning, and not the end, of my labors on the world stage. Compared to some of the giants of history who have received +this prize - Schweitzer and King; Marshall and Mandela - my accomplishments are slight. And then there are the men and women around the world +who have been jailed and beaten in the pursuit of justice; those who toil in humanitarian organizations to relieve suffering; the unrecognized +millions whose quiet acts of courage and compassion inspire even the most hardened of cynics. I cannot argue with those who find these men and +women - some known, some obscure to all but those they help - to be far more deserving of this honor than I. + +But perhaps the most profound issue surrounding my receipt of this prize is the fact that I am the Commander-in-Chief of a nation in the midst +of two wars. One of these wars is winding down. The other is a conflict that America did not seek; one in which we are joined by forty three other +countries - including Norway - in an effort to defend ourselves and all nations from further attacks. + +Still, we are at war, and I am responsible for the deployment of thousands of young Americans to battle in a distant land. Some will kill. Some +will be killed. And so I come here with an acute sense of the cost of armed conflict - filled with difficult questions about the relationship +between war and peace, and our effort to replace one with the other. + +These questions are not new. War, in one form or another, appeared with the first man. At the dawn of history, its morality was not questioned; +it was simply a fact, like drought or disease - the manner in which tribes and then civilizations sought power and settled their differences. + + +Over time, as codes of law sought to control violence within groups, so did philosophers, clerics, and statesmen seek to regulate the destructive +power of war. The concept of a "just war" emerged, suggesting that war is justified only when it meets certain preconditions: if it is waged +as a last resort or in self-defense; if the forced used is proportional, and if, whenever possible, civilians are spared from violence. + +For most of history, this concept of just war was rarely observed. The capacity of human beings to think up new ways to kill one another proved +inexhaustible, as did our capacity to exempt from mercy those who look different or pray to a different God. Wars between armies gave way to wars +between nations - total wars in which the distinction between combatant and civilian became blurred. In the span of thirty years, such carnage +would twice engulf this continent. And while it is hard to conceive of a cause more just than the defeat of the Third Reich and the Axis powers, +World War II was a conflict in which the total number of civilians who died exceeded the number of soldiers who perished. + +In the wake of such destruction, and with the advent of the nuclear age, it became clear to victor and vanquished alike that the world needed +institutions to prevent another World War. And so, a quarter century after the United States Senate rejected the League of Nations - an idea for +which Woodrow Wilson received this Prize - America led the world in constructing an architecture to keep the peace: a Marshall Plan and a +United Nations, mechanisms to govern the waging of war, treaties to protect human rights, prevent genocide, and restrict the most dangerous weapons. + +In many ways, these efforts succeeded. Yes, terrible wars have been fought, and atrocities committed. But there has been no Third World War. The Cold +War ended with jubilant crowds dismantling a wall. Commerce has stitched much of the world together. Billions have been lifted from poverty. The ideals +of liberty, self-determination, equality and the rule of law have haltingly advanced. We are the heirs of the fortitude and foresight of generations +past, and it is a legacy for which my own country is rightfully proud. + +A decade into a new century, this old architecture is buckling under the weight of new threats. The world may no longer shudder at the prospect of +war between two nuclear superpowers, but proliferation may increase the risk of catastrophe. Terrorism has long been a tactic, but modern technology +allows a few small men with outsized rage to murder innocents on a horrific scale. + +Moreover, wars between nations have increasingly given way to wars within nations. The resurgence of ethnic or sectarian conflicts; the growth +of secessionist movements, insurgencies, and failed states; have increasingly trapped civilians in unending chaos. In today's wars, many more +civilians are killed than soldiers; the seeds of future conflict are sewn, economies are wrecked, civil societies torn asunder, refugees +amassed, and children scarred. + +I do not bring with me today a definitive solution to the problems of war. What I do know is that meeting these challenges will require +the same vision, hard work, and persistence of those men and women who acted so boldly decades ago. And it will require us to think in +new ways about the notions of just war and the imperatives of a just peace. + +We must begin by acknowledging the hard truth that we will not eradicate violent conflict in our lifetimes. There will be times when +nations - acting individually or in concert - will find the use of force not only necessary but morally justified. + +I make this statement mindful of what Martin Luther King said in this same ceremony years ago - "Violence never brings permanent peace. It +solves no social problem: it merely creates new and more complicated ones." As someone who stands here as a direct consequence of Dr. King's +life's work, I am living testimony to the moral force of non-violence. I know there is nothing weak -nothing passive - nothing naïve - in the +creed and lives of Gandhi and King. + +But as a head of state sworn to protect and defend my nation, I cannot be guided by their examples alone. I face the world as it is, and +cannot stand idle in the face of threats to the American people. For make no mistake: evil does exist in the world. A non-violent movement +could not have halted Hitler's armies. Negotiations cannot convince al Qaeda's leaders to lay down their arms. To say that force is sometimes +necessary is not a call to cynicism - it is a recognition of history; the imperfections of man and the limits of reason. + +I raise this point because in many countries there is a deep ambivalence about military action today, no matter the cause. At times, this +is joined by a reflexive suspicion of America, the world's sole military superpower. + +Yet the world must remember that it was not simply international institutions - not just treaties and declarations - that brought stability +to a post-World War II world. Whatever mistakes we have made, the plain fact is this: the United States of America has helped underwrite +global security for more than six decades with the blood of our citizens and the strength of our arms. The service and sacrifice of our +men and women in uniform has promoted peace and prosperity from Germany to Korea, and enabled democracy to take hold in places like the +Balkans. We have borne this burden not because we seek to impose our will. We have done so out of enlightened self-interest - because +we seek a better future for our children and grandchildren, and we believe that their lives will be better if other peoples' children +and grandchildren can live in freedom and prosperity. + +So yes, the instruments of war do have a role to play in preserving the peace. And yet this truth must coexist with another - that +no matter how justified, war promises human tragedy. The soldier's courage and sacrifice is full of glory, expressing devotion to +country, to cause and to comrades in arms. But war itself is never glorious, and we must never trumpet it as such. + +So part of our challenge is reconciling these two seemingly irreconcilable truths - that war is sometimes necessary, and war is at +some level an expression of human feelings. Concretely, we must direct our effort to the task that President Kennedy called for long +ago. "Let us focus," he said, "on a more practical, more attainable peace, based not on a sudden revolution in human nature but +on a gradual evolution in human institutions." + +What might this evolution look like? What might these practical steps be? + +To begin with, I believe that all nations - strong and weak alike - must adhere to standards that govern the use of force. I - like any +head of state - reserve the right to act unilaterally if necessary to defend my nation. Nevertheless, I am convinced that adhering +to standards strengthens those who do, and isolates - and weakens - those who don't. + +The world rallied around America after the 9/11 attacks, and continues to support our efforts in Afghanistan, because of the horror +of those senseless attacks and the recognized principle of self-defense. Likewise, the world recognized the need to confront Saddam +Hussein when he invaded Kuwait - a consensus that sent a clear message to all about the cost of aggression. + +Furthermore, America cannot insist that others follow the rules of the road if we refuse to follow them ourselves. For when we don't, +our action can appear arbitrary, and undercut the legitimacy of future intervention - no matter how justified. + +This becomes particularly important when the purpose of military action extends beyond self defense or the defense of one nation +against an aggressor. More and more, we all confront difficult questions about how to prevent the slaughter of civilians by their +own government, or to stop a civil war whose violence and suffering can engulf an entire region. + +I believe that force can be justified on humanitarian grounds, as it was in the Balkans, or in other places that have been scarred +by war. Inaction tears at our conscience and can lead to more costly intervention later. That is why all responsible nations must +embrace the role that militaries with a clear mandate can play to keep the peace. + +America's commitment to global security will never waiver. But in a world in which threats are more diffuse, and missions more +complex, America cannot act alone. This is true in Afghanistan. This is true in failed states like Somalia, where terrorism and +piracy is joined by famine and human suffering. And sadly, it will continue to be true in unstable regions for years to come. + +The leaders and soldiers of NATO countries - and other friends and allies - demonstrate this truth through the capacity and courage +they have shown in Afghanistan. But in many countries, there is a disconnect between the efforts of those who serve and the ambivalence +of the broader public. I understand why war is not popular. But I also know this: the belief that peace is desirable is rarely enough to achieve it. Peace requires responsibility. Peace entails sacrifice. That is why NATO continues to be indispensable. That is why we must strengthen UN and regional peacekeeping, and not leave the task to a few countries. That is why we honor those who return home from peacekeeping and training abroad to Oslo and Rome; to Ottawa and Sydney; to Dhaka and Kigali - we honor them not as makers of war, but as wagers of peace. + +Let me make one final point about the use of force. Even as we make difficult decisions about going to war, we must also think clearly +about how we fight it. The Nobel Committee recognized this truth in awarding its first prize for peace to Henry Dunant - the founder +of the Red Cross, and a driving force behind the Geneva Conventions. + +Where force is necessary, we have a moral and strategic interest in binding ourselves to certain rules of conduct. And even as we +confront a vicious adversary that abides by no rules, I believe that the United States of America must remain a standard bearer in +the conduct of war. That is what makes us different from those whom we fight. That is a source of our strength. That is why I +prohibited torture. That is why I ordered the prison at Guantanamo Bay closed. And that is why I have reaffirmed America's +commitment to abide by the Geneva Conventions. We lose ourselves when we compromise the very ideals that we fight to defend. +And we honor those ideals by upholding them not just when it is easy, but when it is hard. + +I have spoken to the questions that must weigh on our minds and our hearts as we choose to wage war. But let me turn now to +our effort to avoid such tragic choices, and speak of three ways that we can build a just and lasting peace. + +First, in dealing with those nations that break rules and laws, I believe that we must develop alternatives to violence that +are tough enough to change behavior - for if we want a lasting peace, then the words of the international community must mean +something. Those regimes that break the rules must be held accountable. Sanctions must exact a real price. Intransigence must +be met with increased pressure - and such pressure exists only when the world stands together as one. + +One urgent example is the effort to prevent the spread of nuclear weapons, and to seek a world without them. In the middle of +the last century, nations agreed to be bound by a treaty whose bargain is clear: all will have access to peaceful nuclear power; +those without nuclear weapons will forsake them; and those with nuclear weapons will work toward disarmament. I am committed to +upholding this treaty. It is a centerpiece of my foreign policy. And I am working with President Medvedev to reduce America a +nd Russia's nuclear stockpiles. + +But it is also incumbent upon all of us to insist that nations like Iran and North Korea do not game the system. Those who +claim to respect international law cannot avert their eyes when those laws are flouted. Those who care for their own security +cannot ignore the danger of an arms race in the Middle East or East Asia. Those who seek peace cannot stand idly by as nations +arm themselves for nuclear war. + +The same principle applies to those who violate international law by brutalizing their own people. When there is genocide in +Darfur; systematic rape in Congo; or repression in Burma - there must be consequences. And the closer we stand together, the +less likely we will be faced with the choice between armed intervention and complicity in oppression. + +This brings me to a second point - the nature of the peace that we seek. For peace is not merely the absence of visible conflict. +Only a just peace based upon the inherent rights and dignity of every individual can truly be lasting. + +It was this insight that drove drafters of the Universal Declaration of Human Rights after the Second World War. In the wake of +devastation, they recognized that if human rights are not protected, peace is a hollow promise. + +And yet all too often, these words are ignored. In some countries, the failure to uphold human rights is excused by the false +suggestion that these are Western principles, foreign to local cultures or stages of a nation's development. And within America, +there has long been a tension between those who describe themselves as realists or idealists - a tension that suggests a stark +choice between the narrow pursuit of interests or an endless campaign to impose our values. + +I reject this choice. I believe that peace is unstable where citizens are denied the right to speak freely or worship as they +please; choose their own leaders or assemble without fear. Pent up grievances fester, and the suppression of tribal and religious +identity can lead to violence. We also know that the opposite is true. Only when Europe became free did it finally find peace. +America has never fought a war against a democracy, and our closest friends are governments that protect the rights of their +citizens. No matter how callously defined, neither America's interests - nor the world's -are served by the denial of human aspirations. + +So even as we respect the unique culture and traditions of different countries, America will always be a voice for those aspirations +that are universal. We will bear witness to the quiet dignity of reformers like Aung Sang Suu Kyi; to the bravery of Zimbabweans who +cast their ballots in the face of beatings; to the hundreds of thousands who have marched silently through the streets of Iran. It is +telling that the leaders of these governments fear the aspirations of their own people more than the power of any other nation. And +it is the responsibility of all free people and free nations to make clear to these movements that hope and history are on their side + +Let me also say this: the promotion of human rights cannot be about exhortation alone. At times, it must be coupled with painstaking +diplomacy. I know that engagement with repressive regimes lacks the satisfying purity of indignation. But I also know that sanctions +without outreach - and condemnation without discussion - can carry forward a crippling status quo. No repressive regime can move down +a new path unless it has the choice of an open door. + +In light of the Cultural Revolution's horrors, Nixon's meeting with Mao appeared inexcusable - and yet it surely helped set China on +a path where millions of its citizens have been lifted from poverty, and connected to open societies. Pope John Paul's engagement +with Poland created space not just for the Catholic Church, but for labor leaders like Lech Walesa. Ronald Reagan's efforts on arms control and embrace of perestroika not only improved relations with the Soviet Union, but empowered dissidents throughout Eastern Europe. There is no simple formula here. But we must try as best we can to balance isolation and engagement; pressure and incentives, so that human rights and dignity are advanced over time. + +Third, a just peace includes not only civil and political rights - it must encompass economic security and opportunity. For true +peace is not just freedom from fear, but freedom from want. + +It is undoubtedly true that development rarely takes root without security; it is also true that security does not exist where +human beings do not have access to enough food, or clean water, or the medicine they need to survive. It does not exist where +children cannot aspire to a decent education or a job that supports a family. The absence of hope can rot a society from within. + +And that is why helping farmers feed their own people - or nations educate their children and care for the sick - is not mere +charity. It is also why the world must come together to confront climate change. There is little scientific dispute that if we +do nothing, we will face more drought, famine and mass displacement that will fuel more conflict for decades. For this reason, it is not merely scientists and activists who call for swift and forceful action - it is military leaders in my country and others who understand that our common security hangs in the balance. + +Agreements among nations. Strong institutions. Support for human rights. Investments in development. All of these are vital +ingredients in bringing about the evolution that President Kennedy spoke about. And yet, I do not believe that we will have the will, +or the staying power, to complete this work without something more - and that is the continued expansion of our moral imagination; +an insistence that there is something irreducible that we all share. + +As the world grows smaller, you might think it would be easier for human beings to recognize how similar we are; to understand that +we all basically want the same things; that we all hope for the chance to live out our lives with some measure of happiness and +fulfillment for ourselves and our families. + +And yet, given the dizzying pace of globalization, and the cultural leveling of modernity, it should come as no surprise that people +fear the loss of what they cherish about their particular identities - their race, their tribe, and perhaps most powerfully their +religion. In some places, this fear has led to conflict. At times, it even feels like we are moving backwards. We see it in Middle +East, as the conflict between Arabs and Jews seems to harden. We see it in nations that are torn asunder by tribal lines. + +Most dangerously, we see it in the way that religion is used to justify the murder of innocents by those who have distorted and +defiled the great religion of Islam, and who attacked my country from Afghanistan. These extremists are not the first to kill in +the name of God; the cruelties of the Crusades are amply recorded. But they remind us that no Holy War can ever be a just war. For if you truly believe that you are carrying out divine will, then there is no need for restraint - no need to spare the pregnant mother, or the medic, or even a person of one's own faith. Such a warped view of religion is not just incompatible with the concept of peace, but the purpose of faith - for the one rule that lies at the heart of every major religion is that we do unto others as we would have them do unto us. + +Adhering to this law of love has always been the core struggle of human nature. We are fallible. We make mistakes, and fall +victim to the temptations of pride, and power, and sometimes evil. Even those of us with the best intentions will at times +fail to right the wrongs before us. + +But we do not have to think that human nature is perfect for us to still believe that the human condition can be perfected. +We do not have to live in an idealized world to still reach for those ideals that will make it a better place. The non-violence +practiced by men like Gandhi and King may not have been practical or possible in every circumstance, but the love that they preached - +their faith in human progress - must always be the North Star that guides us on our journey. + +For if we lose that faith - if we dismiss it as silly or naïve; if we divorce it from the decisions that we make on issues of war +and peace - then we lose what is best about humanity. We lose our sense of possibility. We lose our moral compass. + +Like generations have before us, we must reject that future. As Dr. King said at this occasion so many years ago, "I refuse to +accept despair as the final response to the ambiguities of history. I refuse to accept the idea that the 'isness' of man's present +nature makes him morally incapable of reaching up for the eternal 'oughtness' that forever confronts him." + +So let us reach for the world that ought to be - that spark of the divine that still stirs within each of our souls. Somewhere +today, in the here and now, a soldier sees he's outgunned but stands firm to keep the peace. Somewhere today, in this world, +a young protestor awaits the brutality of her government, but has the courage to march on. Somewhere today, a mother facing +punishing poverty still takes the time to teach her child, who believes that a cruel world still has a place for his dreams. + +Let us live by their example. We can acknowledge that oppression will always be with us, and still strive for justice. We +can admit the intractability of depravation, and still strive for dignity. We can understand that there will be war, and +still strive for peace. We can do that - for that is the story of human progress; that is the hope of all the world; and +at this moment of challenge, that must be our work here on Earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_3/Data/gettysburg.txt b/CodeToAccompany9781430244646/ch07/sketch_7_3/Data/gettysburg.txt new file mode 100644 index 0000000..1d9643e --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_3/Data/gettysburg.txt @@ -0,0 +1,22 @@ +Four score and seven years ago our fathers brought forth on this continent, a +new nation, conceived in Liberty, and dedicated to the proposition that all men +are created equal. + +Now we are engaged in a great civil war, testing whether that nation, or any +nation so conceived and so dedicated, can long endure. We are met on a great +battle-field of that war. We have come to dedicate a portion of that field, as a +final resting place for those who here gave their lives that that nation might +live. It is altogether fitting and proper that we should do this. + +But, in a larger sense, we can not dedicate -- we can not consecrate -- we can not +hallow -- this ground. The brave men, living and dead, who struggled here, have +consecrated it, far above our poor power to add or detract. The world will +little note, nor long remember what we say here, but it can never forget what +they did here. It is for us the living, rather, to be dedicated here to the +unfinished work which they who fought here have thus far so nobly advanced. It +is rather for us to be here dedicated to the great task remaining before us -- +that from these honored dead we take increased devotion to that cause for +which they gave the last full measure of devotion -- that we here highly resolve +that these dead shall not have died in vain -- that this nation, under God, shall +have a new birth of freedom -- and that government of the people, by the people, +for the people, shall not perish from the earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_3/Data/stopwords.txt b/CodeToAccompany9781430244646/ch07/sketch_7_3/Data/stopwords.txt new file mode 100644 index 0000000..0a1f0d2 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_3/Data/stopwords.txt @@ -0,0 +1,667 @@ +AT +A +a +able +about +above +abst +accordance +according +accordingly +across +act +actually +added +adj +adopted +affected +affecting +affects +after +afterwards +again +against +ah +al +all +almost +alone +along +already +also +although +always +am +among +amongst +an +and +announce +another +any +anybody +anyhow +anymore +anyone +anything +anyway +anyways +anywhere +apparently +approximately +are +aren +arent +arise +around +as +aside +ask +asking +at +auth +available +away +awfully +b +back +be +became +because +become +becomes +becoming +been +before +beforehand +begin +beginning +beginnings +begins +behind +being +believe +below +beside +besides +between +beyond +biol +both +brief +briefly +but +But +by +c +ca +came +can +cannot +cause +causes +certain +certainly +co +com +come +comes +contain +containing +contains +could +couldnt +d +date +did +didn +different +do +does +doesn +doing +done +don +down +downwards +due +during +e +each +ed +edu +effect +eg +eight +eighty +either +else +elsewhere +end +ending +enough +especially +et +etc +even +ever +every +everybody +everyone +everything +everywhere +ex +except +f +far +few +ff +fifth +first +five +fix +followed +following +follows +for +former +formerly +forth +found +four +from +further +furthermore +g +gave +get +gets +getting +give +given +gives +giving +go +goes +gone +got +gotten +h +had +happens +hardly +has +hasn +have +haven +having +he +hed +hence +her +here +hereafter +hereby +herein +heres +hereupon +hers +herself +hes +hi +hid +him +himself +his +hither +home +how +howbeit +however +hundred +i +id +ie +if +im +immediate +immediately +importance +important +in +In +inc +indeed +index +information +instead +into +invention +inward +is +isn +it +It +itd +its +itself +j +just +k +keep +keeps +kept +keys +kg +km +know +known +knows +l +largely +last +lately +later +latter +latterly +least +less +lest +let +lets +like +liked +likely +line +little +look +looking +looks +ltd +m +made +mainly +make +makes +many +may +maybe +me +mean +means +meantime +meanwhile +merely +mg +might +million +miss +ml +more +moreover +most +mostly +mr +mrs +much +mug +must +my +myself +n +na +name +namely +nay +nd +near +nearly +necessarily +necessary +need +needs +neither +never +nevertheless +new +next +nine +ninety +no +nobody +non +none +nonetheless +noone +nor +normally +nos +not +noted +nothing +now +nowhere +o +obtain +obtained +obviously +of +off +often +oh +ok +okay +old +omitted +on +once +one +ones +only +onto +or +ord +other +others +otherwise +ought +our +Our +ours +ourselves +out +outside +over +overall +owing +own +p +page +pages +part +particular +particularly +past +per +perhaps +placed +please +plus +poorly +possible +possibly +potentially +pp +predominantly +present +previously +primarily +probably +promptly +proud +provides +put +q +que +quickly +quite +qv +r +ran +rather +rd +re +readily +really +recent +recently +ref +refs +regarding +regardless +regards +related +relatively +research +respectively +resulted +resulting +results +right +run +s +said +same +saw +say +saying +says +sec +section +see +seeing +seem +seemed +seeming +seems +seen +self +selves +sent +seven +several +shall +she +shed +shes +should +shouldn +show +showed +shown +showns +shows +significant +significantly +similar +similarly +since +six +slightly +so +So +some +somebody +somehow +someone +somethan +something +sometime +sometimes +somewhat +somewhere +soon +sorry +specifically +specified +specify +specifying +state +states +still +stop +strongly +sub +substantially +successfully +such +sufficiently +suggest +sup +sure +t +take +taken +taking +tell +tends +th +than +thank +thanks +thanx +that +thats +the +their +Their +theirs +them +themselves +then +thence +there +There +thereafter +thereby +thered +therefore +therein +thereof +therere +theres +thereto +thereupon +these +They +These +they +theyd +theyre +think +this +This +those +Those +thou +though +thoughh +thousand +throug +through +throughout +thru +thus +til +tip +to +together +too +took +toward +towards +tried +tries +truly +try +trying +ts +twice +two +u +un +under +unfortunately +unless +unlike +unlikely +until +unto +up +upon +ups +us +use +used +useful +usefully +usefulness +uses +using +usually +v +value +various +ve +very +via +viz +vol +vols +vs +w +want +wants +was +wasn +way +we +wed +welcom +went +were +weren +what +whatever +whats +when +whence +whenever +where +whereafter +whereas +whereby +wherein +wheres +whereupon +wherever +whether +which +while +whim +whither +who +whod +whoever +whole +whom +whomever +whos +whose +why +widely +will +willing +wish +with +within +without +words +world +would +wouldn +www +x +y +yes +yet +you +youd +your +Your +youre +yours +yourself +yourselves +z +zero \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_3/Word.pde b/CodeToAccompany9781430244646/ch07/sketch_7_3/Word.pde new file mode 100644 index 0000000..752b299 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_3/Word.pde @@ -0,0 +1,36 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-3: Using ArrayLists for word frequencies +// And eliminating stop words +class Word { + // Each Word is a pair: the word, and its frequency + String word; + int freq; + Word(String newWord) { // Constructor + word = newWord; + freq = 1; + } // Word() + String getWord() { + return word; + } // getWord() + int getFreq() { + return freq; + } // getFreq() + void incr() { // increments the word count + freq++; + } // incr() + String toString() { // print representation of Word objects + return "<"+word+", "+freq+">"; + } +} // class Word diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_3/sketch_7_3.pde b/CodeToAccompany9781430244646/ch07/sketch_7_3/sketch_7_3.pde new file mode 100644 index 0000000..cb84ff9 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_3/sketch_7_3.pde @@ -0,0 +1,83 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-3: Using ArrayLists for word frequencies +// And eliminating stop words +String inputTextFile = "Obama.txt"; +String [] fileContents; +String rawText; +String [] tokens; +String delimiters = " ,./?<>;:'\"[{]}\\|=+-_()*&^%$#@!~"; +ArrayList wordFrequency = new ArrayList(); + +String [] stopWords; + +void setup() { + // Input and parse text file + fileContents = loadStrings(inputTextFile); + rawText = join(fileContents, " "); + rawText = rawText.toLowerCase(); + tokens = splitTokens(rawText, delimiters); + // print out the number of tokens found + println(tokens.length+" tokens found in file: "+inputTextFile); + + // Get stop words + stopWords = loadStrings("stopwords.txt"); + // Compute the wordFrequency table using tokens + for (String t : tokens) { + if (!isStopWord(t)) { + // See if token t is already a known word + int index = search(t, wordFrequency); + if (index >= 0) { + wordFrequency.get(index).incr(); + } + else { + wordFrequency.add(new Word(t)); + } + }// if + } // for + + // Compute the wordFrequency table using tokens + for (String t : tokens) { + // See if token t is already a known word + int index = search(t, wordFrequency); + if (index >= 0) { + wordFrequency.get(index).incr(); + } + else { + wordFrequency.add(new Word(t)); + } // if + } // for + println("There were "+wordFrequency.size()+" words."); + for (int i=0; i < wordFrequency.size(); i++) { + println(wordFrequency.get(i)); + } +} // setup() +int search(String w, ArrayList L) { + // search for word w in L. + // Returns index of w in L if found, -1 o/w + for (int i=0; i < L.size(); i++) { + if (L.get(i).getWord().equals(w)) + return i; + } + return -1; +} // search() + +boolean isStopWord(String word) { // Is word a stop word? + for (String stopWord : stopWords) { + if (word.equals(stopWord)) { + return true; + } + } + return false; +} // isStopWord() diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_4/Data/Obama.txt b/CodeToAccompany9781430244646/ch07/sketch_7_4/Data/Obama.txt new file mode 100644 index 0000000..5dd7b12 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_4/Data/Obama.txt @@ -0,0 +1,239 @@ +Your Majesties, Your Royal Highnesses, Distinguished Members of the Norwegian Nobel Committee, citizens of America, and citizens of the world: + +I receive this honor with deep gratitude and great humility. It is an award that speaks to our highest aspirations - that for all the cruelty +and hardship of our world, we are not mere prisoners of fate. Our actions matter, and can bend history in the direction of justice. + +And yet I would be remiss if I did not acknowledge the considerable controversy that your generous decision has generated. In part, this is +because I am at the beginning, and not the end, of my labors on the world stage. Compared to some of the giants of history who have received +this prize - Schweitzer and King; Marshall and Mandela - my accomplishments are slight. And then there are the men and women around the world +who have been jailed and beaten in the pursuit of justice; those who toil in humanitarian organizations to relieve suffering; the unrecognized +millions whose quiet acts of courage and compassion inspire even the most hardened of cynics. I cannot argue with those who find these men and +women - some known, some obscure to all but those they help - to be far more deserving of this honor than I. + +But perhaps the most profound issue surrounding my receipt of this prize is the fact that I am the Commander-in-Chief of a nation in the midst +of two wars. One of these wars is winding down. The other is a conflict that America did not seek; one in which we are joined by forty three other +countries - including Norway - in an effort to defend ourselves and all nations from further attacks. + +Still, we are at war, and I am responsible for the deployment of thousands of young Americans to battle in a distant land. Some will kill. Some +will be killed. And so I come here with an acute sense of the cost of armed conflict - filled with difficult questions about the relationship +between war and peace, and our effort to replace one with the other. + +These questions are not new. War, in one form or another, appeared with the first man. At the dawn of history, its morality was not questioned; +it was simply a fact, like drought or disease - the manner in which tribes and then civilizations sought power and settled their differences. + + +Over time, as codes of law sought to control violence within groups, so did philosophers, clerics, and statesmen seek to regulate the destructive +power of war. The concept of a "just war" emerged, suggesting that war is justified only when it meets certain preconditions: if it is waged +as a last resort or in self-defense; if the forced used is proportional, and if, whenever possible, civilians are spared from violence. + +For most of history, this concept of just war was rarely observed. The capacity of human beings to think up new ways to kill one another proved +inexhaustible, as did our capacity to exempt from mercy those who look different or pray to a different God. Wars between armies gave way to wars +between nations - total wars in which the distinction between combatant and civilian became blurred. In the span of thirty years, such carnage +would twice engulf this continent. And while it is hard to conceive of a cause more just than the defeat of the Third Reich and the Axis powers, +World War II was a conflict in which the total number of civilians who died exceeded the number of soldiers who perished. + +In the wake of such destruction, and with the advent of the nuclear age, it became clear to victor and vanquished alike that the world needed +institutions to prevent another World War. And so, a quarter century after the United States Senate rejected the League of Nations - an idea for +which Woodrow Wilson received this Prize - America led the world in constructing an architecture to keep the peace: a Marshall Plan and a +United Nations, mechanisms to govern the waging of war, treaties to protect human rights, prevent genocide, and restrict the most dangerous weapons. + +In many ways, these efforts succeeded. Yes, terrible wars have been fought, and atrocities committed. But there has been no Third World War. The Cold +War ended with jubilant crowds dismantling a wall. Commerce has stitched much of the world together. Billions have been lifted from poverty. The ideals +of liberty, self-determination, equality and the rule of law have haltingly advanced. We are the heirs of the fortitude and foresight of generations +past, and it is a legacy for which my own country is rightfully proud. + +A decade into a new century, this old architecture is buckling under the weight of new threats. The world may no longer shudder at the prospect of +war between two nuclear superpowers, but proliferation may increase the risk of catastrophe. Terrorism has long been a tactic, but modern technology +allows a few small men with outsized rage to murder innocents on a horrific scale. + +Moreover, wars between nations have increasingly given way to wars within nations. The resurgence of ethnic or sectarian conflicts; the growth +of secessionist movements, insurgencies, and failed states; have increasingly trapped civilians in unending chaos. In today's wars, many more +civilians are killed than soldiers; the seeds of future conflict are sewn, economies are wrecked, civil societies torn asunder, refugees +amassed, and children scarred. + +I do not bring with me today a definitive solution to the problems of war. What I do know is that meeting these challenges will require +the same vision, hard work, and persistence of those men and women who acted so boldly decades ago. And it will require us to think in +new ways about the notions of just war and the imperatives of a just peace. + +We must begin by acknowledging the hard truth that we will not eradicate violent conflict in our lifetimes. There will be times when +nations - acting individually or in concert - will find the use of force not only necessary but morally justified. + +I make this statement mindful of what Martin Luther King said in this same ceremony years ago - "Violence never brings permanent peace. It +solves no social problem: it merely creates new and more complicated ones." As someone who stands here as a direct consequence of Dr. King's +life's work, I am living testimony to the moral force of non-violence. I know there is nothing weak -nothing passive - nothing naïve - in the +creed and lives of Gandhi and King. + +But as a head of state sworn to protect and defend my nation, I cannot be guided by their examples alone. I face the world as it is, and +cannot stand idle in the face of threats to the American people. For make no mistake: evil does exist in the world. A non-violent movement +could not have halted Hitler's armies. Negotiations cannot convince al Qaeda's leaders to lay down their arms. To say that force is sometimes +necessary is not a call to cynicism - it is a recognition of history; the imperfections of man and the limits of reason. + +I raise this point because in many countries there is a deep ambivalence about military action today, no matter the cause. At times, this +is joined by a reflexive suspicion of America, the world's sole military superpower. + +Yet the world must remember that it was not simply international institutions - not just treaties and declarations - that brought stability +to a post-World War II world. Whatever mistakes we have made, the plain fact is this: the United States of America has helped underwrite +global security for more than six decades with the blood of our citizens and the strength of our arms. The service and sacrifice of our +men and women in uniform has promoted peace and prosperity from Germany to Korea, and enabled democracy to take hold in places like the +Balkans. We have borne this burden not because we seek to impose our will. We have done so out of enlightened self-interest - because +we seek a better future for our children and grandchildren, and we believe that their lives will be better if other peoples' children +and grandchildren can live in freedom and prosperity. + +So yes, the instruments of war do have a role to play in preserving the peace. And yet this truth must coexist with another - that +no matter how justified, war promises human tragedy. The soldier's courage and sacrifice is full of glory, expressing devotion to +country, to cause and to comrades in arms. But war itself is never glorious, and we must never trumpet it as such. + +So part of our challenge is reconciling these two seemingly irreconcilable truths - that war is sometimes necessary, and war is at +some level an expression of human feelings. Concretely, we must direct our effort to the task that President Kennedy called for long +ago. "Let us focus," he said, "on a more practical, more attainable peace, based not on a sudden revolution in human nature but +on a gradual evolution in human institutions." + +What might this evolution look like? What might these practical steps be? + +To begin with, I believe that all nations - strong and weak alike - must adhere to standards that govern the use of force. I - like any +head of state - reserve the right to act unilaterally if necessary to defend my nation. Nevertheless, I am convinced that adhering +to standards strengthens those who do, and isolates - and weakens - those who don't. + +The world rallied around America after the 9/11 attacks, and continues to support our efforts in Afghanistan, because of the horror +of those senseless attacks and the recognized principle of self-defense. Likewise, the world recognized the need to confront Saddam +Hussein when he invaded Kuwait - a consensus that sent a clear message to all about the cost of aggression. + +Furthermore, America cannot insist that others follow the rules of the road if we refuse to follow them ourselves. For when we don't, +our action can appear arbitrary, and undercut the legitimacy of future intervention - no matter how justified. + +This becomes particularly important when the purpose of military action extends beyond self defense or the defense of one nation +against an aggressor. More and more, we all confront difficult questions about how to prevent the slaughter of civilians by their +own government, or to stop a civil war whose violence and suffering can engulf an entire region. + +I believe that force can be justified on humanitarian grounds, as it was in the Balkans, or in other places that have been scarred +by war. Inaction tears at our conscience and can lead to more costly intervention later. That is why all responsible nations must +embrace the role that militaries with a clear mandate can play to keep the peace. + +America's commitment to global security will never waiver. But in a world in which threats are more diffuse, and missions more +complex, America cannot act alone. This is true in Afghanistan. This is true in failed states like Somalia, where terrorism and +piracy is joined by famine and human suffering. And sadly, it will continue to be true in unstable regions for years to come. + +The leaders and soldiers of NATO countries - and other friends and allies - demonstrate this truth through the capacity and courage +they have shown in Afghanistan. But in many countries, there is a disconnect between the efforts of those who serve and the ambivalence +of the broader public. I understand why war is not popular. But I also know this: the belief that peace is desirable is rarely enough to achieve it. Peace requires responsibility. Peace entails sacrifice. That is why NATO continues to be indispensable. That is why we must strengthen UN and regional peacekeeping, and not leave the task to a few countries. That is why we honor those who return home from peacekeeping and training abroad to Oslo and Rome; to Ottawa and Sydney; to Dhaka and Kigali - we honor them not as makers of war, but as wagers of peace. + +Let me make one final point about the use of force. Even as we make difficult decisions about going to war, we must also think clearly +about how we fight it. The Nobel Committee recognized this truth in awarding its first prize for peace to Henry Dunant - the founder +of the Red Cross, and a driving force behind the Geneva Conventions. + +Where force is necessary, we have a moral and strategic interest in binding ourselves to certain rules of conduct. And even as we +confront a vicious adversary that abides by no rules, I believe that the United States of America must remain a standard bearer in +the conduct of war. That is what makes us different from those whom we fight. That is a source of our strength. That is why I +prohibited torture. That is why I ordered the prison at Guantanamo Bay closed. And that is why I have reaffirmed America's +commitment to abide by the Geneva Conventions. We lose ourselves when we compromise the very ideals that we fight to defend. +And we honor those ideals by upholding them not just when it is easy, but when it is hard. + +I have spoken to the questions that must weigh on our minds and our hearts as we choose to wage war. But let me turn now to +our effort to avoid such tragic choices, and speak of three ways that we can build a just and lasting peace. + +First, in dealing with those nations that break rules and laws, I believe that we must develop alternatives to violence that +are tough enough to change behavior - for if we want a lasting peace, then the words of the international community must mean +something. Those regimes that break the rules must be held accountable. Sanctions must exact a real price. Intransigence must +be met with increased pressure - and such pressure exists only when the world stands together as one. + +One urgent example is the effort to prevent the spread of nuclear weapons, and to seek a world without them. In the middle of +the last century, nations agreed to be bound by a treaty whose bargain is clear: all will have access to peaceful nuclear power; +those without nuclear weapons will forsake them; and those with nuclear weapons will work toward disarmament. I am committed to +upholding this treaty. It is a centerpiece of my foreign policy. And I am working with President Medvedev to reduce America a +nd Russia's nuclear stockpiles. + +But it is also incumbent upon all of us to insist that nations like Iran and North Korea do not game the system. Those who +claim to respect international law cannot avert their eyes when those laws are flouted. Those who care for their own security +cannot ignore the danger of an arms race in the Middle East or East Asia. Those who seek peace cannot stand idly by as nations +arm themselves for nuclear war. + +The same principle applies to those who violate international law by brutalizing their own people. When there is genocide in +Darfur; systematic rape in Congo; or repression in Burma - there must be consequences. And the closer we stand together, the +less likely we will be faced with the choice between armed intervention and complicity in oppression. + +This brings me to a second point - the nature of the peace that we seek. For peace is not merely the absence of visible conflict. +Only a just peace based upon the inherent rights and dignity of every individual can truly be lasting. + +It was this insight that drove drafters of the Universal Declaration of Human Rights after the Second World War. In the wake of +devastation, they recognized that if human rights are not protected, peace is a hollow promise. + +And yet all too often, these words are ignored. In some countries, the failure to uphold human rights is excused by the false +suggestion that these are Western principles, foreign to local cultures or stages of a nation's development. And within America, +there has long been a tension between those who describe themselves as realists or idealists - a tension that suggests a stark +choice between the narrow pursuit of interests or an endless campaign to impose our values. + +I reject this choice. I believe that peace is unstable where citizens are denied the right to speak freely or worship as they +please; choose their own leaders or assemble without fear. Pent up grievances fester, and the suppression of tribal and religious +identity can lead to violence. We also know that the opposite is true. Only when Europe became free did it finally find peace. +America has never fought a war against a democracy, and our closest friends are governments that protect the rights of their +citizens. No matter how callously defined, neither America's interests - nor the world's -are served by the denial of human aspirations. + +So even as we respect the unique culture and traditions of different countries, America will always be a voice for those aspirations +that are universal. We will bear witness to the quiet dignity of reformers like Aung Sang Suu Kyi; to the bravery of Zimbabweans who +cast their ballots in the face of beatings; to the hundreds of thousands who have marched silently through the streets of Iran. It is +telling that the leaders of these governments fear the aspirations of their own people more than the power of any other nation. And +it is the responsibility of all free people and free nations to make clear to these movements that hope and history are on their side + +Let me also say this: the promotion of human rights cannot be about exhortation alone. At times, it must be coupled with painstaking +diplomacy. I know that engagement with repressive regimes lacks the satisfying purity of indignation. But I also know that sanctions +without outreach - and condemnation without discussion - can carry forward a crippling status quo. No repressive regime can move down +a new path unless it has the choice of an open door. + +In light of the Cultural Revolution's horrors, Nixon's meeting with Mao appeared inexcusable - and yet it surely helped set China on +a path where millions of its citizens have been lifted from poverty, and connected to open societies. Pope John Paul's engagement +with Poland created space not just for the Catholic Church, but for labor leaders like Lech Walesa. Ronald Reagan's efforts on arms control and embrace of perestroika not only improved relations with the Soviet Union, but empowered dissidents throughout Eastern Europe. There is no simple formula here. But we must try as best we can to balance isolation and engagement; pressure and incentives, so that human rights and dignity are advanced over time. + +Third, a just peace includes not only civil and political rights - it must encompass economic security and opportunity. For true +peace is not just freedom from fear, but freedom from want. + +It is undoubtedly true that development rarely takes root without security; it is also true that security does not exist where +human beings do not have access to enough food, or clean water, or the medicine they need to survive. It does not exist where +children cannot aspire to a decent education or a job that supports a family. The absence of hope can rot a society from within. + +And that is why helping farmers feed their own people - or nations educate their children and care for the sick - is not mere +charity. It is also why the world must come together to confront climate change. There is little scientific dispute that if we +do nothing, we will face more drought, famine and mass displacement that will fuel more conflict for decades. For this reason, it is not merely scientists and activists who call for swift and forceful action - it is military leaders in my country and others who understand that our common security hangs in the balance. + +Agreements among nations. Strong institutions. Support for human rights. Investments in development. All of these are vital +ingredients in bringing about the evolution that President Kennedy spoke about. And yet, I do not believe that we will have the will, +or the staying power, to complete this work without something more - and that is the continued expansion of our moral imagination; +an insistence that there is something irreducible that we all share. + +As the world grows smaller, you might think it would be easier for human beings to recognize how similar we are; to understand that +we all basically want the same things; that we all hope for the chance to live out our lives with some measure of happiness and +fulfillment for ourselves and our families. + +And yet, given the dizzying pace of globalization, and the cultural leveling of modernity, it should come as no surprise that people +fear the loss of what they cherish about their particular identities - their race, their tribe, and perhaps most powerfully their +religion. In some places, this fear has led to conflict. At times, it even feels like we are moving backwards. We see it in Middle +East, as the conflict between Arabs and Jews seems to harden. We see it in nations that are torn asunder by tribal lines. + +Most dangerously, we see it in the way that religion is used to justify the murder of innocents by those who have distorted and +defiled the great religion of Islam, and who attacked my country from Afghanistan. These extremists are not the first to kill in +the name of God; the cruelties of the Crusades are amply recorded. But they remind us that no Holy War can ever be a just war. For if you truly believe that you are carrying out divine will, then there is no need for restraint - no need to spare the pregnant mother, or the medic, or even a person of one's own faith. Such a warped view of religion is not just incompatible with the concept of peace, but the purpose of faith - for the one rule that lies at the heart of every major religion is that we do unto others as we would have them do unto us. + +Adhering to this law of love has always been the core struggle of human nature. We are fallible. We make mistakes, and fall +victim to the temptations of pride, and power, and sometimes evil. Even those of us with the best intentions will at times +fail to right the wrongs before us. + +But we do not have to think that human nature is perfect for us to still believe that the human condition can be perfected. +We do not have to live in an idealized world to still reach for those ideals that will make it a better place. The non-violence +practiced by men like Gandhi and King may not have been practical or possible in every circumstance, but the love that they preached - +their faith in human progress - must always be the North Star that guides us on our journey. + +For if we lose that faith - if we dismiss it as silly or naïve; if we divorce it from the decisions that we make on issues of war +and peace - then we lose what is best about humanity. We lose our sense of possibility. We lose our moral compass. + +Like generations have before us, we must reject that future. As Dr. King said at this occasion so many years ago, "I refuse to +accept despair as the final response to the ambiguities of history. I refuse to accept the idea that the 'isness' of man's present +nature makes him morally incapable of reaching up for the eternal 'oughtness' that forever confronts him." + +So let us reach for the world that ought to be - that spark of the divine that still stirs within each of our souls. Somewhere +today, in the here and now, a soldier sees he's outgunned but stands firm to keep the peace. Somewhere today, in this world, +a young protestor awaits the brutality of her government, but has the courage to march on. Somewhere today, a mother facing +punishing poverty still takes the time to teach her child, who believes that a cruel world still has a place for his dreams. + +Let us live by their example. We can acknowledge that oppression will always be with us, and still strive for justice. We +can admit the intractability of depravation, and still strive for dignity. We can understand that there will be war, and +still strive for peace. We can do that - for that is the story of human progress; that is the hope of all the world; and +at this moment of challenge, that must be our work here on Earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_4/Data/gettysburg.txt b/CodeToAccompany9781430244646/ch07/sketch_7_4/Data/gettysburg.txt new file mode 100644 index 0000000..1d9643e --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_4/Data/gettysburg.txt @@ -0,0 +1,22 @@ +Four score and seven years ago our fathers brought forth on this continent, a +new nation, conceived in Liberty, and dedicated to the proposition that all men +are created equal. + +Now we are engaged in a great civil war, testing whether that nation, or any +nation so conceived and so dedicated, can long endure. We are met on a great +battle-field of that war. We have come to dedicate a portion of that field, as a +final resting place for those who here gave their lives that that nation might +live. It is altogether fitting and proper that we should do this. + +But, in a larger sense, we can not dedicate -- we can not consecrate -- we can not +hallow -- this ground. The brave men, living and dead, who struggled here, have +consecrated it, far above our poor power to add or detract. The world will +little note, nor long remember what we say here, but it can never forget what +they did here. It is for us the living, rather, to be dedicated here to the +unfinished work which they who fought here have thus far so nobly advanced. It +is rather for us to be here dedicated to the great task remaining before us -- +that from these honored dead we take increased devotion to that cause for +which they gave the last full measure of devotion -- that we here highly resolve +that these dead shall not have died in vain -- that this nation, under God, shall +have a new birth of freedom -- and that government of the people, by the people, +for the people, shall not perish from the earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_4/Data/stopwords.txt b/CodeToAccompany9781430244646/ch07/sketch_7_4/Data/stopwords.txt new file mode 100644 index 0000000..0a1f0d2 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_4/Data/stopwords.txt @@ -0,0 +1,667 @@ +AT +A +a +able +about +above +abst +accordance +according +accordingly +across +act +actually +added +adj +adopted +affected +affecting +affects +after +afterwards +again +against +ah +al +all +almost +alone +along +already +also +although +always +am +among +amongst +an +and +announce +another +any +anybody +anyhow +anymore +anyone +anything +anyway +anyways +anywhere +apparently +approximately +are +aren +arent +arise +around +as +aside +ask +asking +at +auth +available +away +awfully +b +back +be +became +because +become +becomes +becoming +been +before +beforehand +begin +beginning +beginnings +begins +behind +being +believe +below +beside +besides +between +beyond +biol +both +brief +briefly +but +But +by +c +ca +came +can +cannot +cause +causes +certain +certainly +co +com +come +comes +contain +containing +contains +could +couldnt +d +date +did +didn +different +do +does +doesn +doing +done +don +down +downwards +due +during +e +each +ed +edu +effect +eg +eight +eighty +either +else +elsewhere +end +ending +enough +especially +et +etc +even +ever +every +everybody +everyone +everything +everywhere +ex +except +f +far +few +ff +fifth +first +five +fix +followed +following +follows +for +former +formerly +forth +found +four +from +further +furthermore +g +gave +get +gets +getting +give +given +gives +giving +go +goes +gone +got +gotten +h +had +happens +hardly +has +hasn +have +haven +having +he +hed +hence +her +here +hereafter +hereby +herein +heres +hereupon +hers +herself +hes +hi +hid +him +himself +his +hither +home +how +howbeit +however +hundred +i +id +ie +if +im +immediate +immediately +importance +important +in +In +inc +indeed +index +information +instead +into +invention +inward +is +isn +it +It +itd +its +itself +j +just +k +keep +keeps +kept +keys +kg +km +know +known +knows +l +largely +last +lately +later +latter +latterly +least +less +lest +let +lets +like +liked +likely +line +little +look +looking +looks +ltd +m +made +mainly +make +makes +many +may +maybe +me +mean +means +meantime +meanwhile +merely +mg +might +million +miss +ml +more +moreover +most +mostly +mr +mrs +much +mug +must +my +myself +n +na +name +namely +nay +nd +near +nearly +necessarily +necessary +need +needs +neither +never +nevertheless +new +next +nine +ninety +no +nobody +non +none +nonetheless +noone +nor +normally +nos +not +noted +nothing +now +nowhere +o +obtain +obtained +obviously +of +off +often +oh +ok +okay +old +omitted +on +once +one +ones +only +onto +or +ord +other +others +otherwise +ought +our +Our +ours +ourselves +out +outside +over +overall +owing +own +p +page +pages +part +particular +particularly +past +per +perhaps +placed +please +plus +poorly +possible +possibly +potentially +pp +predominantly +present +previously +primarily +probably +promptly +proud +provides +put +q +que +quickly +quite +qv +r +ran +rather +rd +re +readily +really +recent +recently +ref +refs +regarding +regardless +regards +related +relatively +research +respectively +resulted +resulting +results +right +run +s +said +same +saw +say +saying +says +sec +section +see +seeing +seem +seemed +seeming +seems +seen +self +selves +sent +seven +several +shall +she +shed +shes +should +shouldn +show +showed +shown +showns +shows +significant +significantly +similar +similarly +since +six +slightly +so +So +some +somebody +somehow +someone +somethan +something +sometime +sometimes +somewhat +somewhere +soon +sorry +specifically +specified +specify +specifying +state +states +still +stop +strongly +sub +substantially +successfully +such +sufficiently +suggest +sup +sure +t +take +taken +taking +tell +tends +th +than +thank +thanks +thanx +that +thats +the +their +Their +theirs +them +themselves +then +thence +there +There +thereafter +thereby +thered +therefore +therein +thereof +therere +theres +thereto +thereupon +these +They +These +they +theyd +theyre +think +this +This +those +Those +thou +though +thoughh +thousand +throug +through +throughout +thru +thus +til +tip +to +together +too +took +toward +towards +tried +tries +truly +try +trying +ts +twice +two +u +un +under +unfortunately +unless +unlike +unlikely +until +unto +up +upon +ups +us +use +used +useful +usefully +usefulness +uses +using +usually +v +value +various +ve +very +via +viz +vol +vols +vs +w +want +wants +was +wasn +way +we +wed +welcom +went +were +weren +what +whatever +whats +when +whence +whenever +where +whereafter +whereas +whereby +wherein +wheres +whereupon +wherever +whether +which +while +whim +whither +who +whod +whoever +whole +whom +whomever +whos +whose +why +widely +will +willing +wish +with +within +without +words +world +would +wouldn +www +x +y +yes +yet +you +youd +your +Your +youre +yours +yourself +yourselves +z +zero \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_4/Word.pde b/CodeToAccompany9781430244646/ch07/sketch_7_4/Word.pde new file mode 100644 index 0000000..e008e5a --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_4/Word.pde @@ -0,0 +1,37 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-4: Using ArrayLists for word frequencies +// And eliminating stop words +// And using the WordFreq class +class Word { + // Each Word is a pair: the word, and its frequency + String word; + int freq; + Word(String newWord) { // Constructor + word = newWord; + freq = 1; + } // Word() + String getWord() { + return word; + } // getWord() + int getFreq() { + return freq; + } // getFreq() + void incr() { // increments the word count + freq++; + } // incr() + String toString() { // print representation of Word objects + return "<"+word+", "+freq+">"; + } +} // class Word diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_4/WordFreq.pde b/CodeToAccompany9781430244646/ch07/sketch_7_4/WordFreq.pde new file mode 100644 index 0000000..d13cbdc --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_4/WordFreq.pde @@ -0,0 +1,93 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-4: Using ArrayLists for word frequencies +// And eliminating stop words +// And using the WordFreq class + +// Sketch 7-4a: The Word frequency table class +class WordFreq { + // A Frequency table class for Words + ArrayList wordFrequency; + String [] stopWords = loadStrings("stopwords.txt"); + + WordFreq(String[] tokens) { // Constructor + + wordFrequency = new ArrayList(); + // Compute the wordFrequency table using tokens + for (String t : tokens) { + if (!_isStopWord(t)) { + // See if token t is already a known word + int index = _search(t, wordFrequency); + if (index >= 0) { + ( wordFrequency.get(index)).incr(); + } + else { + wordFrequency.add(new Word(t)); + } + } + } // for + } // WordFreq() + void tabulate() { // console printout + int n = wordFrequency.size(); + println("There are "+N()+" entries."); + for (int i=0; i < n; i++) { + println(wordFrequency.get(i)); + } + } // tabulate + int N() { // Number of table entries + return wordFrequency.size(); + } // N() + String[] samples() { // Returns all the words + String [] k = new String[N()]; + int i=0; + for (Word w : wordFrequency) { + k[i++] = w.getWord(); + } + return k; + } // samples() + int[] counts() { // Returns all the frequencies + int [] v = new int[N()]; + int i=0; + for (Word w : wordFrequency) { + v[i++] = w.getFreq(); + } + return v; + } // counts() + int maxFreq() { // The max frequency + return max(counts()); + } // maxFreq() + + int _search(String w, ArrayList L) { + // search for word w in L. + // Returns index of w in L if found, -1 o/w + for (int i=0; i < L.size(); i++) { + if (L.get(i).getWord().equals(w)) + return i; + } + return -1; + } // _search() + + boolean _isStopWord(String word) { // Is word a stop word? + for (String stopWord : stopWords) { + if (word.equals(stopWord)) { + return true; + } + } + return false; + } // _isStopWord() + + String toString() { // Print representation + return "Word Frequency Table with"+N()+" entries."; + } // toString() +} // class WordFreq diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_4/sketch_7_4.pde b/CodeToAccompany9781430244646/ch07/sketch_7_4/sketch_7_4.pde new file mode 100644 index 0000000..abfa47c --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_4/sketch_7_4.pde @@ -0,0 +1,31 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-4: Using ArrayLists for word frequencies +// And eliminating stop words +// And using the WordFreq class +String inputTextFile = "Obama.txt"; +WordFreq table; +void setup() { + // Input and parse text file + String [] fileContents = loadStrings(inputTextFile); + String rawText = join(fileContents, " ").toLowerCase(); + String [] tokens; + String delimiters = " ,./?<>;:'\"[{]}\\|=+-_()*&^%$#@!~"; + tokens = splitTokens(rawText, delimiters); + println(tokens.length+" tokens found in file: "+inputTextFile); + // Create the word frequency table + table = new WordFreq(tokens); + table.tabulate(); + println("Max frequency:"+table.maxFreq()); +} // setup() diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_6/data/TimesNewRomanPSMT-48.vlw b/CodeToAccompany9781430244646/ch07/sketch_7_6/data/TimesNewRomanPSMT-48.vlw new file mode 100644 index 0000000..d2e7a52 Binary files /dev/null and b/CodeToAccompany9781430244646/ch07/sketch_7_6/data/TimesNewRomanPSMT-48.vlw differ diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_6/sketch_7_6.pde b/CodeToAccompany9781430244646/ch07/sketch_7_6/sketch_7_6.pde new file mode 100644 index 0000000..2235f3c --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_6/sketch_7_6.pde @@ -0,0 +1,34 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-6: isplayingText in a Specific Font +String sentence = "A man, a plan, a canal, Panama."; +PFont tnr; +void setup() { + size(400, 100); + smooth(); + //tnr = createFont("Times New Roman", 48); + tnr = loadFont("TimesNewRomanPSMT-48.vlw"); + println(PFont.list()); +} // setup() +void draw() { + background(200); + fill(0); + textFont(tnr); + textSize(24); + text(sentence, 10, height/2); +} // draw() + +void mouseClicked(){ + save("978-1-4302-4464-6_kumar_Ch07_Figure7-2.tif"); +} diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_7/sketch_7_7.pde b/CodeToAccompany9781430244646/ch07/sketch_7_7/sketch_7_7.pde new file mode 100644 index 0000000..eac0f8e --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_7/sketch_7_7.pde @@ -0,0 +1,34 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Skjetch 7-7: List of fonts +String[] fonts; +PFont font; +int N, i; +void setup() { + size(500, 500); + background(255); + fonts = PFont.list(); + N = fonts.length; + i = 0; + println("There are "+N+" fonts installed."); +} // setup() + +void mousePressed() { + font = createFont(fonts[i], 24); + textFont(font); + fill(0); + text(fonts[i], mouseX, mouseY); + i++; +} // mousePressed() + diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_9/Data/Obama.txt b/CodeToAccompany9781430244646/ch07/sketch_7_9/Data/Obama.txt new file mode 100644 index 0000000..5dd7b12 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_9/Data/Obama.txt @@ -0,0 +1,239 @@ +Your Majesties, Your Royal Highnesses, Distinguished Members of the Norwegian Nobel Committee, citizens of America, and citizens of the world: + +I receive this honor with deep gratitude and great humility. It is an award that speaks to our highest aspirations - that for all the cruelty +and hardship of our world, we are not mere prisoners of fate. Our actions matter, and can bend history in the direction of justice. + +And yet I would be remiss if I did not acknowledge the considerable controversy that your generous decision has generated. In part, this is +because I am at the beginning, and not the end, of my labors on the world stage. Compared to some of the giants of history who have received +this prize - Schweitzer and King; Marshall and Mandela - my accomplishments are slight. And then there are the men and women around the world +who have been jailed and beaten in the pursuit of justice; those who toil in humanitarian organizations to relieve suffering; the unrecognized +millions whose quiet acts of courage and compassion inspire even the most hardened of cynics. I cannot argue with those who find these men and +women - some known, some obscure to all but those they help - to be far more deserving of this honor than I. + +But perhaps the most profound issue surrounding my receipt of this prize is the fact that I am the Commander-in-Chief of a nation in the midst +of two wars. One of these wars is winding down. The other is a conflict that America did not seek; one in which we are joined by forty three other +countries - including Norway - in an effort to defend ourselves and all nations from further attacks. + +Still, we are at war, and I am responsible for the deployment of thousands of young Americans to battle in a distant land. Some will kill. Some +will be killed. And so I come here with an acute sense of the cost of armed conflict - filled with difficult questions about the relationship +between war and peace, and our effort to replace one with the other. + +These questions are not new. War, in one form or another, appeared with the first man. At the dawn of history, its morality was not questioned; +it was simply a fact, like drought or disease - the manner in which tribes and then civilizations sought power and settled their differences. + + +Over time, as codes of law sought to control violence within groups, so did philosophers, clerics, and statesmen seek to regulate the destructive +power of war. The concept of a "just war" emerged, suggesting that war is justified only when it meets certain preconditions: if it is waged +as a last resort or in self-defense; if the forced used is proportional, and if, whenever possible, civilians are spared from violence. + +For most of history, this concept of just war was rarely observed. The capacity of human beings to think up new ways to kill one another proved +inexhaustible, as did our capacity to exempt from mercy those who look different or pray to a different God. Wars between armies gave way to wars +between nations - total wars in which the distinction between combatant and civilian became blurred. In the span of thirty years, such carnage +would twice engulf this continent. And while it is hard to conceive of a cause more just than the defeat of the Third Reich and the Axis powers, +World War II was a conflict in which the total number of civilians who died exceeded the number of soldiers who perished. + +In the wake of such destruction, and with the advent of the nuclear age, it became clear to victor and vanquished alike that the world needed +institutions to prevent another World War. And so, a quarter century after the United States Senate rejected the League of Nations - an idea for +which Woodrow Wilson received this Prize - America led the world in constructing an architecture to keep the peace: a Marshall Plan and a +United Nations, mechanisms to govern the waging of war, treaties to protect human rights, prevent genocide, and restrict the most dangerous weapons. + +In many ways, these efforts succeeded. Yes, terrible wars have been fought, and atrocities committed. But there has been no Third World War. The Cold +War ended with jubilant crowds dismantling a wall. Commerce has stitched much of the world together. Billions have been lifted from poverty. The ideals +of liberty, self-determination, equality and the rule of law have haltingly advanced. We are the heirs of the fortitude and foresight of generations +past, and it is a legacy for which my own country is rightfully proud. + +A decade into a new century, this old architecture is buckling under the weight of new threats. The world may no longer shudder at the prospect of +war between two nuclear superpowers, but proliferation may increase the risk of catastrophe. Terrorism has long been a tactic, but modern technology +allows a few small men with outsized rage to murder innocents on a horrific scale. + +Moreover, wars between nations have increasingly given way to wars within nations. The resurgence of ethnic or sectarian conflicts; the growth +of secessionist movements, insurgencies, and failed states; have increasingly trapped civilians in unending chaos. In today's wars, many more +civilians are killed than soldiers; the seeds of future conflict are sewn, economies are wrecked, civil societies torn asunder, refugees +amassed, and children scarred. + +I do not bring with me today a definitive solution to the problems of war. What I do know is that meeting these challenges will require +the same vision, hard work, and persistence of those men and women who acted so boldly decades ago. And it will require us to think in +new ways about the notions of just war and the imperatives of a just peace. + +We must begin by acknowledging the hard truth that we will not eradicate violent conflict in our lifetimes. There will be times when +nations - acting individually or in concert - will find the use of force not only necessary but morally justified. + +I make this statement mindful of what Martin Luther King said in this same ceremony years ago - "Violence never brings permanent peace. It +solves no social problem: it merely creates new and more complicated ones." As someone who stands here as a direct consequence of Dr. King's +life's work, I am living testimony to the moral force of non-violence. I know there is nothing weak -nothing passive - nothing naïve - in the +creed and lives of Gandhi and King. + +But as a head of state sworn to protect and defend my nation, I cannot be guided by their examples alone. I face the world as it is, and +cannot stand idle in the face of threats to the American people. For make no mistake: evil does exist in the world. A non-violent movement +could not have halted Hitler's armies. Negotiations cannot convince al Qaeda's leaders to lay down their arms. To say that force is sometimes +necessary is not a call to cynicism - it is a recognition of history; the imperfections of man and the limits of reason. + +I raise this point because in many countries there is a deep ambivalence about military action today, no matter the cause. At times, this +is joined by a reflexive suspicion of America, the world's sole military superpower. + +Yet the world must remember that it was not simply international institutions - not just treaties and declarations - that brought stability +to a post-World War II world. Whatever mistakes we have made, the plain fact is this: the United States of America has helped underwrite +global security for more than six decades with the blood of our citizens and the strength of our arms. The service and sacrifice of our +men and women in uniform has promoted peace and prosperity from Germany to Korea, and enabled democracy to take hold in places like the +Balkans. We have borne this burden not because we seek to impose our will. We have done so out of enlightened self-interest - because +we seek a better future for our children and grandchildren, and we believe that their lives will be better if other peoples' children +and grandchildren can live in freedom and prosperity. + +So yes, the instruments of war do have a role to play in preserving the peace. And yet this truth must coexist with another - that +no matter how justified, war promises human tragedy. The soldier's courage and sacrifice is full of glory, expressing devotion to +country, to cause and to comrades in arms. But war itself is never glorious, and we must never trumpet it as such. + +So part of our challenge is reconciling these two seemingly irreconcilable truths - that war is sometimes necessary, and war is at +some level an expression of human feelings. Concretely, we must direct our effort to the task that President Kennedy called for long +ago. "Let us focus," he said, "on a more practical, more attainable peace, based not on a sudden revolution in human nature but +on a gradual evolution in human institutions." + +What might this evolution look like? What might these practical steps be? + +To begin with, I believe that all nations - strong and weak alike - must adhere to standards that govern the use of force. I - like any +head of state - reserve the right to act unilaterally if necessary to defend my nation. Nevertheless, I am convinced that adhering +to standards strengthens those who do, and isolates - and weakens - those who don't. + +The world rallied around America after the 9/11 attacks, and continues to support our efforts in Afghanistan, because of the horror +of those senseless attacks and the recognized principle of self-defense. Likewise, the world recognized the need to confront Saddam +Hussein when he invaded Kuwait - a consensus that sent a clear message to all about the cost of aggression. + +Furthermore, America cannot insist that others follow the rules of the road if we refuse to follow them ourselves. For when we don't, +our action can appear arbitrary, and undercut the legitimacy of future intervention - no matter how justified. + +This becomes particularly important when the purpose of military action extends beyond self defense or the defense of one nation +against an aggressor. More and more, we all confront difficult questions about how to prevent the slaughter of civilians by their +own government, or to stop a civil war whose violence and suffering can engulf an entire region. + +I believe that force can be justified on humanitarian grounds, as it was in the Balkans, or in other places that have been scarred +by war. Inaction tears at our conscience and can lead to more costly intervention later. That is why all responsible nations must +embrace the role that militaries with a clear mandate can play to keep the peace. + +America's commitment to global security will never waiver. But in a world in which threats are more diffuse, and missions more +complex, America cannot act alone. This is true in Afghanistan. This is true in failed states like Somalia, where terrorism and +piracy is joined by famine and human suffering. And sadly, it will continue to be true in unstable regions for years to come. + +The leaders and soldiers of NATO countries - and other friends and allies - demonstrate this truth through the capacity and courage +they have shown in Afghanistan. But in many countries, there is a disconnect between the efforts of those who serve and the ambivalence +of the broader public. I understand why war is not popular. But I also know this: the belief that peace is desirable is rarely enough to achieve it. Peace requires responsibility. Peace entails sacrifice. That is why NATO continues to be indispensable. That is why we must strengthen UN and regional peacekeeping, and not leave the task to a few countries. That is why we honor those who return home from peacekeeping and training abroad to Oslo and Rome; to Ottawa and Sydney; to Dhaka and Kigali - we honor them not as makers of war, but as wagers of peace. + +Let me make one final point about the use of force. Even as we make difficult decisions about going to war, we must also think clearly +about how we fight it. The Nobel Committee recognized this truth in awarding its first prize for peace to Henry Dunant - the founder +of the Red Cross, and a driving force behind the Geneva Conventions. + +Where force is necessary, we have a moral and strategic interest in binding ourselves to certain rules of conduct. And even as we +confront a vicious adversary that abides by no rules, I believe that the United States of America must remain a standard bearer in +the conduct of war. That is what makes us different from those whom we fight. That is a source of our strength. That is why I +prohibited torture. That is why I ordered the prison at Guantanamo Bay closed. And that is why I have reaffirmed America's +commitment to abide by the Geneva Conventions. We lose ourselves when we compromise the very ideals that we fight to defend. +And we honor those ideals by upholding them not just when it is easy, but when it is hard. + +I have spoken to the questions that must weigh on our minds and our hearts as we choose to wage war. But let me turn now to +our effort to avoid such tragic choices, and speak of three ways that we can build a just and lasting peace. + +First, in dealing with those nations that break rules and laws, I believe that we must develop alternatives to violence that +are tough enough to change behavior - for if we want a lasting peace, then the words of the international community must mean +something. Those regimes that break the rules must be held accountable. Sanctions must exact a real price. Intransigence must +be met with increased pressure - and such pressure exists only when the world stands together as one. + +One urgent example is the effort to prevent the spread of nuclear weapons, and to seek a world without them. In the middle of +the last century, nations agreed to be bound by a treaty whose bargain is clear: all will have access to peaceful nuclear power; +those without nuclear weapons will forsake them; and those with nuclear weapons will work toward disarmament. I am committed to +upholding this treaty. It is a centerpiece of my foreign policy. And I am working with President Medvedev to reduce America a +nd Russia's nuclear stockpiles. + +But it is also incumbent upon all of us to insist that nations like Iran and North Korea do not game the system. Those who +claim to respect international law cannot avert their eyes when those laws are flouted. Those who care for their own security +cannot ignore the danger of an arms race in the Middle East or East Asia. Those who seek peace cannot stand idly by as nations +arm themselves for nuclear war. + +The same principle applies to those who violate international law by brutalizing their own people. When there is genocide in +Darfur; systematic rape in Congo; or repression in Burma - there must be consequences. And the closer we stand together, the +less likely we will be faced with the choice between armed intervention and complicity in oppression. + +This brings me to a second point - the nature of the peace that we seek. For peace is not merely the absence of visible conflict. +Only a just peace based upon the inherent rights and dignity of every individual can truly be lasting. + +It was this insight that drove drafters of the Universal Declaration of Human Rights after the Second World War. In the wake of +devastation, they recognized that if human rights are not protected, peace is a hollow promise. + +And yet all too often, these words are ignored. In some countries, the failure to uphold human rights is excused by the false +suggestion that these are Western principles, foreign to local cultures or stages of a nation's development. And within America, +there has long been a tension between those who describe themselves as realists or idealists - a tension that suggests a stark +choice between the narrow pursuit of interests or an endless campaign to impose our values. + +I reject this choice. I believe that peace is unstable where citizens are denied the right to speak freely or worship as they +please; choose their own leaders or assemble without fear. Pent up grievances fester, and the suppression of tribal and religious +identity can lead to violence. We also know that the opposite is true. Only when Europe became free did it finally find peace. +America has never fought a war against a democracy, and our closest friends are governments that protect the rights of their +citizens. No matter how callously defined, neither America's interests - nor the world's -are served by the denial of human aspirations. + +So even as we respect the unique culture and traditions of different countries, America will always be a voice for those aspirations +that are universal. We will bear witness to the quiet dignity of reformers like Aung Sang Suu Kyi; to the bravery of Zimbabweans who +cast their ballots in the face of beatings; to the hundreds of thousands who have marched silently through the streets of Iran. It is +telling that the leaders of these governments fear the aspirations of their own people more than the power of any other nation. And +it is the responsibility of all free people and free nations to make clear to these movements that hope and history are on their side + +Let me also say this: the promotion of human rights cannot be about exhortation alone. At times, it must be coupled with painstaking +diplomacy. I know that engagement with repressive regimes lacks the satisfying purity of indignation. But I also know that sanctions +without outreach - and condemnation without discussion - can carry forward a crippling status quo. No repressive regime can move down +a new path unless it has the choice of an open door. + +In light of the Cultural Revolution's horrors, Nixon's meeting with Mao appeared inexcusable - and yet it surely helped set China on +a path where millions of its citizens have been lifted from poverty, and connected to open societies. Pope John Paul's engagement +with Poland created space not just for the Catholic Church, but for labor leaders like Lech Walesa. Ronald Reagan's efforts on arms control and embrace of perestroika not only improved relations with the Soviet Union, but empowered dissidents throughout Eastern Europe. There is no simple formula here. But we must try as best we can to balance isolation and engagement; pressure and incentives, so that human rights and dignity are advanced over time. + +Third, a just peace includes not only civil and political rights - it must encompass economic security and opportunity. For true +peace is not just freedom from fear, but freedom from want. + +It is undoubtedly true that development rarely takes root without security; it is also true that security does not exist where +human beings do not have access to enough food, or clean water, or the medicine they need to survive. It does not exist where +children cannot aspire to a decent education or a job that supports a family. The absence of hope can rot a society from within. + +And that is why helping farmers feed their own people - or nations educate their children and care for the sick - is not mere +charity. It is also why the world must come together to confront climate change. There is little scientific dispute that if we +do nothing, we will face more drought, famine and mass displacement that will fuel more conflict for decades. For this reason, it is not merely scientists and activists who call for swift and forceful action - it is military leaders in my country and others who understand that our common security hangs in the balance. + +Agreements among nations. Strong institutions. Support for human rights. Investments in development. All of these are vital +ingredients in bringing about the evolution that President Kennedy spoke about. And yet, I do not believe that we will have the will, +or the staying power, to complete this work without something more - and that is the continued expansion of our moral imagination; +an insistence that there is something irreducible that we all share. + +As the world grows smaller, you might think it would be easier for human beings to recognize how similar we are; to understand that +we all basically want the same things; that we all hope for the chance to live out our lives with some measure of happiness and +fulfillment for ourselves and our families. + +And yet, given the dizzying pace of globalization, and the cultural leveling of modernity, it should come as no surprise that people +fear the loss of what they cherish about their particular identities - their race, their tribe, and perhaps most powerfully their +religion. In some places, this fear has led to conflict. At times, it even feels like we are moving backwards. We see it in Middle +East, as the conflict between Arabs and Jews seems to harden. We see it in nations that are torn asunder by tribal lines. + +Most dangerously, we see it in the way that religion is used to justify the murder of innocents by those who have distorted and +defiled the great religion of Islam, and who attacked my country from Afghanistan. These extremists are not the first to kill in +the name of God; the cruelties of the Crusades are amply recorded. But they remind us that no Holy War can ever be a just war. For if you truly believe that you are carrying out divine will, then there is no need for restraint - no need to spare the pregnant mother, or the medic, or even a person of one's own faith. Such a warped view of religion is not just incompatible with the concept of peace, but the purpose of faith - for the one rule that lies at the heart of every major religion is that we do unto others as we would have them do unto us. + +Adhering to this law of love has always been the core struggle of human nature. We are fallible. We make mistakes, and fall +victim to the temptations of pride, and power, and sometimes evil. Even those of us with the best intentions will at times +fail to right the wrongs before us. + +But we do not have to think that human nature is perfect for us to still believe that the human condition can be perfected. +We do not have to live in an idealized world to still reach for those ideals that will make it a better place. The non-violence +practiced by men like Gandhi and King may not have been practical or possible in every circumstance, but the love that they preached - +their faith in human progress - must always be the North Star that guides us on our journey. + +For if we lose that faith - if we dismiss it as silly or naïve; if we divorce it from the decisions that we make on issues of war +and peace - then we lose what is best about humanity. We lose our sense of possibility. We lose our moral compass. + +Like generations have before us, we must reject that future. As Dr. King said at this occasion so many years ago, "I refuse to +accept despair as the final response to the ambiguities of history. I refuse to accept the idea that the 'isness' of man's present +nature makes him morally incapable of reaching up for the eternal 'oughtness' that forever confronts him." + +So let us reach for the world that ought to be - that spark of the divine that still stirs within each of our souls. Somewhere +today, in the here and now, a soldier sees he's outgunned but stands firm to keep the peace. Somewhere today, in this world, +a young protestor awaits the brutality of her government, but has the courage to march on. Somewhere today, a mother facing +punishing poverty still takes the time to teach her child, who believes that a cruel world still has a place for his dreams. + +Let us live by their example. We can acknowledge that oppression will always be with us, and still strive for justice. We +can admit the intractability of depravation, and still strive for dignity. We can understand that there will be war, and +still strive for peace. We can do that - for that is the story of human progress; that is the hope of all the world; and +at this moment of challenge, that must be our work here on Earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_9/Data/gettysburg.txt b/CodeToAccompany9781430244646/ch07/sketch_7_9/Data/gettysburg.txt new file mode 100644 index 0000000..1d9643e --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_9/Data/gettysburg.txt @@ -0,0 +1,22 @@ +Four score and seven years ago our fathers brought forth on this continent, a +new nation, conceived in Liberty, and dedicated to the proposition that all men +are created equal. + +Now we are engaged in a great civil war, testing whether that nation, or any +nation so conceived and so dedicated, can long endure. We are met on a great +battle-field of that war. We have come to dedicate a portion of that field, as a +final resting place for those who here gave their lives that that nation might +live. It is altogether fitting and proper that we should do this. + +But, in a larger sense, we can not dedicate -- we can not consecrate -- we can not +hallow -- this ground. The brave men, living and dead, who struggled here, have +consecrated it, far above our poor power to add or detract. The world will +little note, nor long remember what we say here, but it can never forget what +they did here. It is for us the living, rather, to be dedicated here to the +unfinished work which they who fought here have thus far so nobly advanced. It +is rather for us to be here dedicated to the great task remaining before us -- +that from these honored dead we take increased devotion to that cause for +which they gave the last full measure of devotion -- that we here highly resolve +that these dead shall not have died in vain -- that this nation, under God, shall +have a new birth of freedom -- and that government of the people, by the people, +for the people, shall not perish from the earth. \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_9/Data/stopwords.txt b/CodeToAccompany9781430244646/ch07/sketch_7_9/Data/stopwords.txt new file mode 100644 index 0000000..0a1f0d2 --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_9/Data/stopwords.txt @@ -0,0 +1,667 @@ +AT +A +a +able +about +above +abst +accordance +according +accordingly +across +act +actually +added +adj +adopted +affected +affecting +affects +after +afterwards +again +against +ah +al +all +almost +alone +along +already +also +although +always +am +among +amongst +an +and +announce +another +any +anybody +anyhow +anymore +anyone +anything +anyway +anyways +anywhere +apparently +approximately +are +aren +arent +arise +around +as +aside +ask +asking +at +auth +available +away +awfully +b +back +be +became +because +become +becomes +becoming +been +before +beforehand +begin +beginning +beginnings +begins +behind +being +believe +below +beside +besides +between +beyond +biol +both +brief +briefly +but +But +by +c +ca +came +can +cannot +cause +causes +certain +certainly +co +com +come +comes +contain +containing +contains +could +couldnt +d +date +did +didn +different +do +does +doesn +doing +done +don +down +downwards +due +during +e +each +ed +edu +effect +eg +eight +eighty +either +else +elsewhere +end +ending +enough +especially +et +etc +even +ever +every +everybody +everyone +everything +everywhere +ex +except +f +far +few +ff +fifth +first +five +fix +followed +following +follows +for +former +formerly +forth +found +four +from +further +furthermore +g +gave +get +gets +getting +give +given +gives +giving +go +goes +gone +got +gotten +h +had +happens +hardly +has +hasn +have +haven +having +he +hed +hence +her +here +hereafter +hereby +herein +heres +hereupon +hers +herself +hes +hi +hid +him +himself +his +hither +home +how +howbeit +however +hundred +i +id +ie +if +im +immediate +immediately +importance +important +in +In +inc +indeed +index +information +instead +into +invention +inward +is +isn +it +It +itd +its +itself +j +just +k +keep +keeps +kept +keys +kg +km +know +known +knows +l +largely +last +lately +later +latter +latterly +least +less +lest +let +lets +like +liked +likely +line +little +look +looking +looks +ltd +m +made +mainly +make +makes +many +may +maybe +me +mean +means +meantime +meanwhile +merely +mg +might +million +miss +ml +more +moreover +most +mostly +mr +mrs +much +mug +must +my +myself +n +na +name +namely +nay +nd +near +nearly +necessarily +necessary +need +needs +neither +never +nevertheless +new +next +nine +ninety +no +nobody +non +none +nonetheless +noone +nor +normally +nos +not +noted +nothing +now +nowhere +o +obtain +obtained +obviously +of +off +often +oh +ok +okay +old +omitted +on +once +one +ones +only +onto +or +ord +other +others +otherwise +ought +our +Our +ours +ourselves +out +outside +over +overall +owing +own +p +page +pages +part +particular +particularly +past +per +perhaps +placed +please +plus +poorly +possible +possibly +potentially +pp +predominantly +present +previously +primarily +probably +promptly +proud +provides +put +q +que +quickly +quite +qv +r +ran +rather +rd +re +readily +really +recent +recently +ref +refs +regarding +regardless +regards +related +relatively +research +respectively +resulted +resulting +results +right +run +s +said +same +saw +say +saying +says +sec +section +see +seeing +seem +seemed +seeming +seems +seen +self +selves +sent +seven +several +shall +she +shed +shes +should +shouldn +show +showed +shown +showns +shows +significant +significantly +similar +similarly +since +six +slightly +so +So +some +somebody +somehow +someone +somethan +something +sometime +sometimes +somewhat +somewhere +soon +sorry +specifically +specified +specify +specifying +state +states +still +stop +strongly +sub +substantially +successfully +such +sufficiently +suggest +sup +sure +t +take +taken +taking +tell +tends +th +than +thank +thanks +thanx +that +thats +the +their +Their +theirs +them +themselves +then +thence +there +There +thereafter +thereby +thered +therefore +therein +thereof +therere +theres +thereto +thereupon +these +They +These +they +theyd +theyre +think +this +This +those +Those +thou +though +thoughh +thousand +throug +through +throughout +thru +thus +til +tip +to +together +too +took +toward +towards +tried +tries +truly +try +trying +ts +twice +two +u +un +under +unfortunately +unless +unlike +unlikely +until +unto +up +upon +ups +us +use +used +useful +usefully +usefulness +uses +using +usually +v +value +various +ve +very +via +viz +vol +vols +vs +w +want +wants +was +wasn +way +we +wed +welcom +went +were +weren +what +whatever +whats +when +whence +whenever +where +whereafter +whereas +whereby +wherein +wheres +whereupon +wherever +whether +which +while +whim +whither +who +whod +whoever +whole +whom +whomever +whos +whose +why +widely +will +willing +wish +with +within +without +words +world +would +wouldn +www +x +y +yes +yet +you +youd +your +Your +youre +yours +yourself +yourselves +z +zero \ No newline at end of file diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_9/Word.pde b/CodeToAccompany9781430244646/ch07/sketch_7_9/Word.pde new file mode 100644 index 0000000..6dbbd7e --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_9/Word.pde @@ -0,0 +1,39 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-9: Using ArrayLists for word frequencies +// And eliminating stop words +// And using the WordFreq class +// Sketch 7-9a: The Word class +class Word { + // Each Word is a pair: the word, and its frequency + String word; + int freq; + Word(String newWord) { // Constructor + word = newWord; + freq = 1; + } // Word() + String getWord() { + return word; + } // getWord() + int getFreq() { + return freq; + } // getFreq() + void incr() { // increments the word count + freq++; + } // incr() + String toString() { // print representation of Word objects + return "<"+word+", "+freq+">"; + } +} // class Word + diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_9/WordFreq.pde b/CodeToAccompany9781430244646/ch07/sketch_7_9/WordFreq.pde new file mode 100644 index 0000000..2f80fad --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_9/WordFreq.pde @@ -0,0 +1,92 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-9: Using ArrayLists for word frequencies +// And eliminating stop words +// And using the WordFreq class +// Sketch 7-9a: The Word frequency table class +class WordFreq { + // A Frequency table class for Words + ArrayList wordFrequency; + String [] stopWords = loadStrings("stopwords.txt"); + + WordFreq(String[] tokens) { // Constructor + + wordFrequency = new ArrayList(); + // Compute the wordFrequency table using tokens + for (String t : tokens) { + if (!_isStopWord(t)) { + // See if token t is already a known word + int index = _search(t, wordFrequency); + if (index >= 0) { + ( wordFrequency.get(index)).incr(); + } + else { + wordFrequency.add(new Word(t)); + } + } + } // for + } // WordFreq() + void tabulate() { // console printout + int n = wordFrequency.size(); + println("There are "+N()+" entries."); + for (int i=0; i < n; i++) { + println(wordFrequency.get(i)); + } + } // tabulate + int N() { // Number of table entries + return wordFrequency.size(); + } // N() + String[] samples() { // Returns all the words + String [] k = new String[N()]; + int i=0; + for (Word w : wordFrequency) { + k[i++] = w.getWord(); + } + return k; + } // samples() + int[] counts() { // Returns all the frequencies + int [] v = new int[N()]; + int i=0; + for (Word w : wordFrequency) { + v[i++] = w.getFreq(); + } + return v; + } // counts() + int maxFreq() { // The max frequency + return max(counts()); + } // maxFreq() + + int _search(String w, ArrayList L) { + // search for word w in L. + // Returns index of w in L if found, -1 o/w + for (int i=0; i < L.size(); i++) { + if (L.get(i).getWord().equals(w)) + return i; + } + return -1; + } // _search() + + boolean _isStopWord(String word) { // Is word a stop word? + for (String stopWord : stopWords) { + if (word.equals(stopWord)) { + return true; + } + } + return false; + } // _isStopWord() + + String toString() { // Print representation + return "Word Frequency Table with"+N()+" entries."; + } // toString() +} // class WordFreq diff --git a/CodeToAccompany9781430244646/ch07/sketch_7_9/sketch_7_9.pde b/CodeToAccompany9781430244646/ch07/sketch_7_9/sketch_7_9.pde new file mode 100644 index 0000000..abfa47c --- /dev/null +++ b/CodeToAccompany9781430244646/ch07/sketch_7_9/sketch_7_9.pde @@ -0,0 +1,31 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, Friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +Friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ + +// Sketch 7-4: Using ArrayLists for word frequencies +// And eliminating stop words +// And using the WordFreq class +String inputTextFile = "Obama.txt"; +WordFreq table; +void setup() { + // Input and parse text file + String [] fileContents = loadStrings(inputTextFile); + String rawText = join(fileContents, " ").toLowerCase(); + String [] tokens; + String delimiters = " ,./?<>;:'\"[{]}\\|=+-_()*&^%$#@!~"; + tokens = splitTokens(rawText, delimiters); + println(tokens.length+" tokens found in file: "+inputTextFile); + // Create the word frequency table + table = new WordFreq(tokens); + table.tabulate(); + println("Max frequency:"+table.maxFreq()); +} // setup() diff --git a/CodeToAccompany9781430244646/ch08/Lsystem/Lsys.pde b/CodeToAccompany9781430244646/ch08/Lsystem/Lsys.pde new file mode 100644 index 0000000..c10f253 --- /dev/null +++ b/CodeToAccompany9781430244646/ch08/Lsystem/Lsys.pde @@ -0,0 +1,78 @@ +class Lsys { + String axiom; + ArrayList rules; + String out; // final output string + + Lsys() { + axiom = new String(); + rules = new ArrayList(); + out = new String(); + }// end Lsys() + + void setAxiom(String s) { + axiom += s; + out += axiom; + }// end setAxiom() + + void addRule(String rule) { + String r = new String(rule); + rules.add(r); + }// end addRule; + + // search for a specific rule that starts with character c + // return the arrayList index if found, -1 if not + int searchRule(char c) { + for (int i=0; i0) { + String temp = ""; + for (int i=0; i substring of length 1 + } + else { + String r = (String) rules.get(idx); + temp += r.substring(1); //substring starting at the 2nd char + } + } + out = new String(temp); + genString(n-1); + } + }// end genString() + + void render(float size, float angle) { + for (int i=0; i width || center.x < 0 || center.y > height || center.y < 0); + } // end update() + + boolean converge() { + return stable; + } +} // end class Particle + diff --git a/CodeToAccompany9781430244646/ch09/emergentVoronoi/emergentVoronoi.pde b/CodeToAccompany9781430244646/ch09/emergentVoronoi/emergentVoronoi.pde new file mode 100644 index 0000000..649311d --- /dev/null +++ b/CodeToAccompany9781430244646/ch09/emergentVoronoi/emergentVoronoi.pde @@ -0,0 +1,77 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ +// emergentVoronoi.pde, chapter 9 +// A Voronoi diagram drawn with an emergent system. +// Particles move to get further away from the closest site, +// until they are equidistant to two or more. +// Left mouse click releases one new particle at mouse point +// Right mouse click or any key press resets the entire system + +PVector[] sites; // sites +ArrayList ps; // particles +int numSites = 10; +int numParticles = 5000; + +void setup() { + size(800, 800); + smooth(); + colorMode(HSB, 360, 100, 100); + sites = new PVector[numSites]; + reset(); +} // end setup() + +void draw() { + background(255); + // draws the sites + for (int i=0; i=0; i--) { + Particle p = (Particle)ps.get(i); + p.display(); + if (!p.converge()) { // if p has not converged + if (p.update()) { // move p and if out of screen after moving + ps.remove(i); // remove particle from ps + } + } + } +} // end draw() + +// creates all new randomly placed sites and particles +void reset() { + for (int i=0; i> 4; + + // Strip off least significant 4 bits of R, G, B from cover image + cp = cp & ~clearCoverMask; + + // Add the bits from the secret image to cover's least significant bits + cp = cp | sp; + + // Replace the encoded pixel back into the picture + cover.pixels[i] = cp; + } + + // Update pixels and save the encoded picture to a new file + cover.updatePixels(); + image(cover, 0, 0); + cover.save("encoded.png"); // save to named file as PNG +} // end mousePressed() + diff --git a/CodeToAccompany9781430244646/ch09/encode/fall.jpg b/CodeToAccompany9781430244646/ch09/encode/fall.jpg new file mode 100644 index 0000000..73d59da Binary files /dev/null and b/CodeToAccompany9781430244646/ch09/encode/fall.jpg differ diff --git a/CodeToAccompany9781430244646/ch09/encode/woods.jpg b/CodeToAccompany9781430244646/ch09/encode/woods.jpg new file mode 100644 index 0000000..fa9fada Binary files /dev/null and b/CodeToAccompany9781430244646/ch09/encode/woods.jpg differ diff --git a/CodeToAccompany9781430244646/ch09/grayScaleTrigAnimation/grayScaleTrigAnimation.pde b/CodeToAccompany9781430244646/ch09/grayScaleTrigAnimation/grayScaleTrigAnimation.pde new file mode 100644 index 0000000..5cfb6e9 --- /dev/null +++ b/CodeToAccompany9781430244646/ch09/grayScaleTrigAnimation/grayScaleTrigAnimation.pde @@ -0,0 +1,58 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ +// grayScaleTrigAnimation.pde, chapter 9 +// 2D array with periodic gradient shading visualized with continuous animation + +int rows = 100; +int cols = 100; +float[][] grays = new float[rows][cols]; +int cellSize = 5; +float[][] incs = new float[rows][cols]; + +void setup() { + size(cellSize*cols, cellSize*rows); + noStroke(); + // uncommment for full color variation + //colorMode(HSB); + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + float x = map(i, 0, rows-1, 0, 2*PI); + float y = map(j, 0, cols-1, 0, 2*PI); + float z = sin(x)*cos(y); + grays[i][j] = map(z, -1.0, 1.0, 0.0, 255.0); + incs[i][j] = 1; + } + } +} + +void draw() { + background(255); + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + fill(grays[i][j]); + // full color variation, uncomment colorMode(HSB) above + //fill(grays[i][j], 255, 255); + pushMatrix(); + // j is the column index, which correspond to the x screen coordinate + translate(j*cellSize, i*cellSize); + rect(0, 0, cellSize, cellSize); + popMatrix(); + + if (grays[i][j] > 255 || grays[i][j] < 0) + incs[i][j] = -incs[i][j]; + grays[i][j] += incs[i][j]; + } + } +} + diff --git a/CodeToAccompany9781430244646/ch09/greyScale2DArray/greyScale2DArray.pde b/CodeToAccompany9781430244646/ch09/greyScale2DArray/greyScale2DArray.pde new file mode 100644 index 0000000..7e571fa --- /dev/null +++ b/CodeToAccompany9781430244646/ch09/greyScale2DArray/greyScale2DArray.pde @@ -0,0 +1,56 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ +//grayScale2DArray.pde, chapter 9 +//2D arrray of values visualized as grayscale colors + +void setup() { + int[][] array2D = {{84, 208, 73, 105, 11, 54, 212, 93, 4, 157}, + {15, 155, 57, 75, 3, 157, 93, 118, 11, 77}, + {227, 75, 143, 23, 192, 218, 87, 15, 13, 72}, + {68, 228, 74, 70, 78, 225, 191, 121, 232, 190}, + {162, 22, 119, 255, 179, 45, 166, 96, 135, 200}, + {114, 196, 234, 80, 232, 100, 183, 165, 203, 23}, + {178, 65, 130, 3, 71, 179, 44, 31, 44, 183}, + {18, 34, 153, 96, 231, 92, 240, 204, 157, 0}}; + int cellsize = 40; + int rows = array2D.length; + int cols = array2D[0].length; + size(cellsize*cols+1, cellsize*rows+1); + + //uncomment each of the code blocks below to see the effects + /* + array2D[4][3] = 0; + */ + /* + for (int i=0; i 0 && j == 0) { // first tile of a row, starting from the 2nd row + if (tiles[i-1][0].orient == tiles[i][0].orient) { // same orientation as tile directly above + tiles[i][0].swapColors = !tiles[i-1][0].swapColors; // set to opposite coloring of my neighbor above + } + else { + tiles[i][0].swapColors = tiles[i-1][0].swapColors; // set to same coloring of my neighbor above + } + } + if (j > 0) { // subsequent tiles in a row, including the first + if (tiles[i][j-1].orient == tiles[i][j].orient) { + tiles[i][j].swapColors = !tiles[i][j-1].swapColors; // set to opposite coloring of my neighbor to the left + } + else { + tiles[i][j].swapColors = tiles[i][j-1].swapColors; // set to same coloring of my neighbor to the left + } + } +} + +void grid() { + stroke(50); + for (int i=0; i < rows; i++) { + line(0, i*tileSize, width, i*tileSize); + } + for (int j = 0; j < cols; j++) { + line(j*tileSize, 0, j*tileSize, height); + } +} + diff --git a/CodeToAccompany9781430244646/ch09/whiteLine/whiteLine.pde b/CodeToAccompany9781430244646/ch09/whiteLine/whiteLine.pde new file mode 100644 index 0000000..40d2579 --- /dev/null +++ b/CodeToAccompany9781430244646/ch09/whiteLine/whiteLine.pde @@ -0,0 +1,27 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ +// whiteLine.pde, chapter 9 +// Draws a white line at the middle of the screen (height), +// of a single pixel width. +void setup() { + size(500, 500); + background(0); + loadPixels(); + + for (int x = 0; x < width; x++) { + pixels[height/2*width+x] = color(255); + } + + updatePixels(); +} // end setup() + diff --git a/CodeToAccompany9781430244646/ch10/.DS_Store b/CodeToAccompany9781430244646/ch10/.DS_Store new file mode 100644 index 0000000..39b94bc Binary files /dev/null and b/CodeToAccompany9781430244646/ch10/.DS_Store differ diff --git a/CodeToAccompany9781430244646/ch10/blending/Lenna.png b/CodeToAccompany9781430244646/ch10/blending/Lenna.png new file mode 100644 index 0000000..59ef68a Binary files /dev/null and b/CodeToAccompany9781430244646/ch10/blending/Lenna.png differ diff --git a/CodeToAccompany9781430244646/ch10/blending/blending.pde b/CodeToAccompany9781430244646/ch10/blending/blending.pde new file mode 100644 index 0000000..6168435 --- /dev/null +++ b/CodeToAccompany9781430244646/ch10/blending/blending.pde @@ -0,0 +1,34 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ +// blending.pde, chapter 10 +// Different ways of blending of two images + +void setup() { + PImage src = loadImage("Lenna.png"); // blending image + PImage dest = loadImage("prinzipal.jpg"); // background image + size(dest.width, dest.height); // size sketch window as background image + background(dest); // load image into background + + blend(src, 0, 0, src.width, src.height, 0, 0, dest.width, dest.height, DARKEST); + + // variations, comment the blend() call above + //blend(src, 0, 0, dest.width/2, src.height, 0, 0, dest.width/2, src.height, DARKEST); + //blend(src, 0, 0, src.width, src.height, dest.width/2, 0, dest.width/2, src.height, DARKEST); + //blend(src, 0, 0, dest.width/2, src.height, 0, height-src.height, dest.width/2, src.height, LIGHTEST); + //blend(src, 0, 0, src.width, src.height, dest.width/2, height-src.height, dest.width/2, src.height, LIGHTEST); + + // variation with OVERLAY, comment all the blend() calls above + //PImage src2 = loadImage("brynmawr.png"); // blending image + //blend(src2, 0, 0, src.width, src.height, 0, 700, width, height-700, OVERLAY); +} // end setup() + diff --git a/CodeToAccompany9781430244646/ch10/blending/brynmawr.png b/CodeToAccompany9781430244646/ch10/blending/brynmawr.png new file mode 100644 index 0000000..78a3d56 Binary files /dev/null and b/CodeToAccompany9781430244646/ch10/blending/brynmawr.png differ diff --git a/CodeToAccompany9781430244646/ch10/blending/prinzipal.jpg b/CodeToAccompany9781430244646/ch10/blending/prinzipal.jpg new file mode 100644 index 0000000..276b100 Binary files /dev/null and b/CodeToAccompany9781430244646/ch10/blending/prinzipal.jpg differ diff --git a/CodeToAccompany9781430244646/ch10/colonyMask/colony.tif b/CodeToAccompany9781430244646/ch10/colonyMask/colony.tif new file mode 100644 index 0000000..4517763 Binary files /dev/null and b/CodeToAccompany9781430244646/ch10/colonyMask/colony.tif differ diff --git a/CodeToAccompany9781430244646/ch10/colonyMask/colonyMask.pde b/CodeToAccompany9781430244646/ch10/colonyMask/colonyMask.pde new file mode 100644 index 0000000..49b05f2 --- /dev/null +++ b/CodeToAccompany9781430244646/ch10/colonyMask/colonyMask.pde @@ -0,0 +1,24 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ +// colonyMask.pde, chapter 10 +// Masking to blackout background of an image + +void setup() { + PImage img = loadImage("colony.tif"); + PImage msk = loadImage("mask.tif"); + background(0); + size(img.width, img.height); + img.mask(msk); + image(img, 0, 0); +} // end setup() + diff --git a/CodeToAccompany9781430244646/ch10/colonyMask/mask.tif b/CodeToAccompany9781430244646/ch10/colonyMask/mask.tif new file mode 100644 index 0000000..d7f708c Binary files /dev/null and b/CodeToAccompany9781430244646/ch10/colonyMask/mask.tif differ diff --git a/CodeToAccompany9781430244646/ch10/convolution/Filter.pde b/CodeToAccompany9781430244646/ch10/convolution/Filter.pde new file mode 100644 index 0000000..4c35067 --- /dev/null +++ b/CodeToAccompany9781430244646/ch10/convolution/Filter.pde @@ -0,0 +1,35 @@ +class Filter{ + float[][] kernel; // convolution kernel + float normalizer; // normalizing factor + float offset; // brightening offset + String name; // display label + + Filter(float[][] kernel, float normalizer, float offset, String name) { + this.kernel = kernel; + this.normalizer = normalizer; + this.offset = offset; + this.name = name; + } // end Filter() + + // returns the color for pixel(x, y) after applying filter + color apply(int x, int y, PImage img) { + int halfSize = kernel.length/2; // used for moving from the center out to the corners + float r = 0.0, g = 0.0, b = 0.0; + + for (int i = 0; i < kernel.length; i++) { + for (int j= 0; j < kernel[i].length; j++) { + // Which neighbor are we using + int newX = x+i-halfSize; + int newY = y+j-halfSize; + int idx = img.width*newY + newX; + idx = constrain(idx, 0, img.pixels.length-1); // constraint the edge pixels + // Calculate the convolution + r += (red(img.pixels[idx]) * kernel[i][j]/normalizer); + g += (green(img.pixels[idx]) * kernel[i][j]/normalizer); + b += (blue(img.pixels[idx]) * kernel[i][j]/normalizer); + } + } + + return color(r+offset, g+offset, b+offset); + } // end apply() +} // end class Filter diff --git a/CodeToAccompany9781430244646/ch10/convolution/convolution.pde b/CodeToAccompany9781430244646/ch10/convolution/convolution.pde new file mode 100644 index 0000000..fc0c3ec --- /dev/null +++ b/CodeToAccompany9781430244646/ch10/convolution/convolution.pde @@ -0,0 +1,70 @@ +/*------------------------------------------------------------ +Copyright (c) 2013, friends of Ed (An Apress Company) +All rights reserved. + +The code provided here accompanies the book: + +Processing: Creative Coding and Generative Art in Processing 2 +By Ira Greenberg, Dianna Xu, and Deepak Kumar +friends of Ed (An APress Company), 2013 +ISBN-13 978-1430244646 +Please refer to the associated README for a full disclaimer. +------------------------------------------------------------*/ +// convolution.pde, chapter 10 +// 9 convolution filters +// Press '0'-'8' to cycle through the filters + +float[][][] ks = {{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + {{1, 2, 1}, {2, 4, 2}, {1, 2, 1}}, + {{1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1}}, + {{0, -2, 0}, {-2, 11, -2}, {0, -2, 0}}, + {{-1, -1, -1}, {-1, 9, -1}, {-1, -1, -1}}, + {{1, 1, 1}, {1, -7, 1}, {1, 1, 1}}, + {{0, -1, 0}, {-1, 4, -1}, {0, -1, 0}}, + {{-1, -1, -1}, {-1, 8, -1}, {-1, -1, -1}}, + {{1,1,0},{1,0,-1},{0,-1,-1}}}; + +Filter[] filters = {new Filter(ks[0], 9, 0, "Mean"), + new Filter(ks[1], 16, 0, "Gaussian Blur"), + new Filter(ks[2], 9, 0, "Motion Blur"), + new Filter(ks[3], 3, 0, "Sharpen"), + new Filter(ks[4], 1, 0, "Mean Removal"), + new Filter(ks[5], 1, 0, "Mystery"), + new Filter(ks[6], 1, 0, "Edge Detection Horizontal/Vertical"), + new Filter(ks[7], 1, 0, "Edge Detection with Diagonal"), + new Filter(ks[8], 1, 127, "Emboss")}; +PImage img, img2; + +void setup() { + img = loadImage("prinzipal.jpg"); //original image + img2 = createImage(img.width, img.height, RGB); // new image to store the changed pixels + size(img.width*2, img.height); + + img.loadPixels(); + img2.loadPixels(); + applyFilter(0); // apply first filter - Mean +} // end setup() + +void draw(){} + +void keyPressed() { + if (key >= '0' && key <= '8') { + applyFilter(key-'0'); + } +} // end keyPressed() + +void applyFilter(int n) { + for (int y=0; y 600 || blue(c) > 190) { // cloud or sky + msk.pixels[y*img.width+x] = 0; + } + else { + msk.pixels[y*img.width+x] = 255; + } + } + } + msk.updatePixels(); + image(img, 0, 0); + img.mask(msk); + image(img, img.width, 0); +} // end setup() + diff --git a/CodeToAccompany9781430244646/ch10/imageMask/prinzipal.jpg b/CodeToAccompany9781430244646/ch10/imageMask/prinzipal.jpg new file mode 100644 index 0000000..276b100 Binary files /dev/null and b/CodeToAccompany9781430244646/ch10/imageMask/prinzipal.jpg differ diff --git a/CodeToAccompany9781430244646/ch10/imageMosaic/Lenna.png b/CodeToAccompany9781430244646/ch10/imageMosaic/Lenna.png new file mode 100644 index 0000000..59ef68a Binary files /dev/null and b/CodeToAccompany9781430244646/ch10/imageMosaic/Lenna.png differ diff --git a/CodeToAccompany9781430244646/ch10/imageMosaic/Tile.pde b/CodeToAccompany9781430244646/ch10/imageMosaic/Tile.pde new file mode 100644 index 0000000..a1e2cbc --- /dev/null +++ b/CodeToAccompany9781430244646/ch10/imageMosaic/Tile.pde @@ -0,0 +1,29 @@ +class Tile { + PImage img; + float avgR; // average red of tile + float avgG; // average green + float avgB; // average blue + + Tile(PImage img, int size) { + this.img = img; + img.resize(size, size); + calcAvg(); + } + + void calcAvg() { + img.loadPixels(); + float r=0, g=0, b=0; + + for (int i=0; i