# HG changeset patch # User Mitesh Patel # Date 1259033161 28800 # Node ID 8b5d3cffe0b711a3008e548ec4823f9dd9c4af7d # Parent 96dc9920ce447ee8d235e0faa0301d0ad2349155 #1321/sagenb: A graph editor by Radoslav Kirov diff --git a/sagenb/data/graph_editor/graph_editor.html b/sagenb/data/graph_editor/graph_editor.html new file mode 100644 --- /dev/null +++ b/sagenb/data/graph_editor/graph_editor.html @@ -0,0 +1,85 @@ + + + Graph Editor + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ live: + + +
+ variable name: + + +
+ strength: + + +
+
+ length: + + +
+
+ + + + diff --git a/sagenb/data/graph_editor/graph_editor.js b/sagenb/data/graph_editor/graph_editor.js new file mode 100644 --- /dev/null +++ b/sagenb/data/graph_editor/graph_editor.js @@ -0,0 +1,396 @@ +/*global $, document, p: true, Processing, top, window */ +/*jslint white: false, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, strict: true, newcap: true, immed: true */ +"use strict"; +var edge_list = [], nodes = [], NODES, EDGES, SIZE, NEW_RADIUS, + DOUBLECLICK, LIVE, SPRING, FIXED_LENGTH, + selected_node, dragged_node, dragging_flag, last_click_time, + initial_x, initial_y + +var edges = [], num_vertices = null, pos = null; + +NODES = 10; +EDGES = 20; +SIZE = 350; +NEW_RADIUS = 20; +DOUBLECLICK = 250; +LIVE = false; +SPRING = 0.999; +FIXED_LENGTH = 100.0; + +function rand(a, b) { + return a + Math.floor(Math.random() * (b - a)); +} + +function Node(x, y) { + this.x = x; + this.y = y; + this.size = 7; +} + +Node.prototype.display = function () { + p.stroke(0); + if (this.selected) { + p.fill(255, 0, 0); + p.ellipse(this.x, this.y, this.size, this.size); + } else { + p.fill(0); + p.ellipse(this.x, this.y, this.size, this.size); + } +}; + +Node.prototype.distance_to = function (x, y) { + return Math.sqrt(Math.pow((x - this.x), 2) + Math.pow((y - this.y), 2)); +}; + +Node.prototype.is_hit = function (x, y) { + return Math.abs(x - this.x) < this.size && + Math.abs(y - this.y) < this.size; +}; + +function Edge(node1, node2) { + this.node1 = node1; + this.node2 = node2; +} + +Edge.prototype.shrink = function () { + var d, gx, gy, mx, my; + + mx = (this.node1.x + this.node2.x) / 2; + my = (this.node1.y + this.node2.y) / 2; + + if (this.node1 !== dragged_node) { + d = this.node1.distance_to(mx, my); + gx = mx + (this.node1.x - mx) / d * FIXED_LENGTH / 2; + gy = my + (this.node1.y - my) / d * FIXED_LENGTH / 2; + this.node1.x = gx + (this.node1.x - gx) * SPRING; + this.node1.y = gy + (this.node1.y - gy) * SPRING; + } + if (this.node2 !== dragged_node) { + d = this.node2.distance_to(mx, my); + gx = mx + (this.node2.x - mx) / d * FIXED_LENGTH / 2; + gy = my + (this.node2.y - my) / d * FIXED_LENGTH / 2; + this.node2.x = gx + (this.node2.x - gx) * SPRING; + this.node2.y = gy + (this.node2.y - gy) * SPRING; + } +}; + +Edge.prototype.display = function () { + if (this.node1.x > SIZE || this.node1.y > SIZE || + this.node1.x < 0 || this.node1.y < 0 || + this.node2.x > SIZE || this.node2.y > SIZE || + this.node2.x < 0 || this.node2.y < 0) { + p.stroke(255, 0, 0); + } else { + if (this.node1.selected || this.node2.selected) { + p.stroke(0, 0, 200); + } else { + p.stroke(0); + } + } + p.line(this.node1.x, this.node1.y, this.node2.x, this.node2.y); +}; + +function add_node(node) { + if (nodes.indexOf(node) === -1) { + nodes.push(node); + } +} + +function remove_node(node) { + var edge, i, index; + for (i = edge_list.length - 1; i > -1; i -= 1) { + edge = edge_list[i]; + if (edge.node1 === node || edge.node2 === node) { + edge_list.splice(i, 1); + } + } + index = nodes.indexOf(node); + if (index !== -1) { + nodes.splice(index, 1); + } +} + +function add_edge_between_nodes(node1, node2) { + if (node1 === node2) { + // Only simple graphs are implemented so far. + return; + } + edge_list.push(new Edge(node1, node2)); + if (nodes.indexOf(node1) === -1) { + nodes.add(node1); + } + if (nodes.indexOf(node2) === -1) { + nodes.add(node2); + } +} + +function toggle_edge(node1, node2) { + var edge, existing = false, i, new_edge; + if (node1 === node2) { + // Only simple graphs are implemented so far. + return; + } + new_edge = new Edge(node1, node2); + for (i = edge_list.length - 1; i > -1; i -= 1) { + edge = edge_list[i]; + if ((edge.node1 === new_edge.node1 && edge.node2 === new_edge.node2) || + (edge.node1 === new_edge.node2 && edge.node2 === new_edge.node1)) { + existing = true; + break; + } + } + if (existing) { + edge_list.splice(i, 1); + } else { + edge_list.push(new_edge); + } +} + +function set_graph() { + var i, n1, n2; + + if (!pos) { + for (i = 0; i < NODES; i += 1) { + add_node(new Node(rand(0, SIZE), rand(0, SIZE))); + } + for (i = 0; i < EDGES; i += 1) { + n1 = rand(0, NODES); + n2 = rand(0, NODES); + add_edge_between_nodes(nodes[n1], nodes[n2]); + } + } + for (i = 0; i < num_vertices; i += 1) { + if (pos) { + add_node(new Node(pos[i][0] * 8 * SIZE / 10 + SIZE / 10, + pos[i][1] * 8 * SIZE / 10 + SIZE / 10)); + } else { + add_node(new Node(rand(0, SIZE), rand(0, SIZE))); + } + } + for (i = 0; i < edges.length; i += 1) { + add_edge_between_nodes(nodes[edges[i][0]], nodes[edges[i][1]]); + } + p.draw(); +} + +function display_graph() { + var i; + for (i = 0; i < edge_list.length; i += 1) { + edge_list[i].display(); + if (LIVE) { + edge_list[i].shrink(); + } + } + for (i = 0; i < nodes.length; i += 1) { + nodes[i].display(); + } +} + +function setup() { + p.size(SIZE, SIZE); + set_graph(); + p.rectMode(p.RADIUS); + p.ellipseMode(p.RADIUS); + p.noLoop(); +} + +function update_sliders() { + SPRING = (1 - 1e-2) + 1e-4 * (100 - $('#val_edge').val()); + FIXED_LENGTH = $('#val_fixed_length').val(); +} + +function draw() { + update_sliders(); + p.background(255); + display_graph(); +} + +function toggle_live() { + if (LIVE) { + LIVE = false; + p.noLoop(); + } else { + LIVE = true; + p.loop(); + } +} + +function mousePressed() { + var clicked_node, closest_distance, i, new_distance; + if (!LIVE) { + p.loop(); + } + for (i = 0; i < nodes.length; i += 1) { + if (nodes[i].is_hit(p.mouseX, p.mouseY)) { + clicked_node = nodes[i]; + break; + } + } + if (!clicked_node) { + closest_distance = SIZE; + for (i = 0; i < nodes.length; i += 1) { + new_distance = nodes[i].distance_to(p.mouseX, p.mouseY); + if (new_distance < closest_distance) { + closest_distance = new_distance; + } + } + if (closest_distance > NEW_RADIUS) { + add_node(new Node(p.mouseX, p.mouseY)); + } + return; + } else { + dragged_node = clicked_node; + initial_x = dragged_node.x; + initial_y = dragged_node.y; + } +} + +function mouseDragged() { + if (dragged_node) { + dragging_flag = true; + dragged_node.x = p.mouseX; + dragged_node.y = p.mouseY; + } +} + +function mouseReleased() { + if (dragged_node) { + if (dragging_flag) { + dragging_flag = false; + if (dragged_node.x > SIZE || dragged_node.y > SIZE || + dragged_node.x < 0 || dragged_node.y < 0) { + remove_node(dragged_node); + if (selected_node === dragged_node) { + selected_node = false; + } + dragged_node = false; + } + } else { + if (p.millis() - last_click_time < DOUBLECLICK) { + remove_node(dragged_node); + if (selected_node === dragged_node) { + selected_node = false; + } + } else if (selected_node) { + toggle_edge(selected_node, dragged_node); + if (!p.keyPressed) { + selected_node.selected = false; + selected_node = false; + } else { + if (selected_node === dragged_node) { + selected_node.selected = false; + selected_node = false; + } + } + } else { + selected_node = dragged_node; + selected_node.selected = true; + } + } + dragged_node = false; + last_click_time = p.millis(); + p.redraw(); + } + if (!LIVE) { + p.noLoop(); + } +} + +function mouse_out() { + if (dragged_node) { + dragged_node.x = initial_x; + dragged_node.y = initial_y; + dragged_node = false; + } +} + +function positions_dict() { + var i, out; + out = "{"; + for (i = 0; i < nodes.length; i += 1) { + out += i + ":[" + nodes[i].x + "," + (SIZE - nodes[i].y) + "],"; + } + return out.substring(0, out.length - 1) + "}"; +} + +function adjacency_lists_dict() { + var edge, empty, i, j, node, out; + out = "{"; + for (i = 0; i < nodes.length; i += 1) { + out += i + ":["; + node = nodes[i]; + empty = true; + for (j = 0; j < edge_list.length; j += 1) { + edge = edge_list[j]; + if (edge.node1 === node) { + if (!empty) { + out += ","; + } + empty = false; + out += nodes.indexOf(edge.node2); + } + if (edge.node2 === node) { + if (!empty) { + out+=","; + } + empty = false; + out += nodes.indexOf(edge.node1); + } + } + out += "],"; + } + return out.substring(0, out.length - 1) + "}"; +} + +function update_sage() { + return [adjacency_lists_dict(), positions_dict(), $('#graph_name').val()]; +} + + +$(document).ready(function () { + var cell_id, cell_outer, loc; + + // Retrieve graph data and name from parent document. + loc = window.location.href; + cell_id = parseInt(loc.slice(loc.search('cell_id=') + 8), 10); + cell_outer = $('#cell_outer_' + cell_id, top.document); + eval($('#graph_data_' + cell_id, cell_outer).val()); + $('#graph_name').val($('#graph_name_' + cell_id, cell_outer).val()); + + // Set up processing.js. + p = Processing($('#canvas')[0], ''); + p.setup = setup; + p.draw = draw; + p.mouseDragged = mouseDragged; + p.mousePressed = mousePressed; + p.mouseReleased = mouseReleased; + p.init(); + + $('#help').hide(); + + $('#help_button').click(function () { + $('#help').toggle(); + }); + + $('#live').click(function() { + toggle_live(); + }); + + $('#slider_edge').slider({ + min: 0, + max: 100, + value: 50, + slide: function(event, ui) { + $('#val_edge').val(ui.value); + } + }); + + $('#slider_fixed_length').slider({ + min: 0, + max: 200, + value: 100, + slide: function(event, ui) { + $('#val_fixed_length').val(ui.value); + } + }); +}); diff --git a/sagenb/data/graph_editor/processing.editor.js b/sagenb/data/graph_editor/processing.editor.js new file mode 100644 --- /dev/null +++ b/sagenb/data/graph_editor/processing.editor.js @@ -0,0 +1,1266 @@ +(function() { + this.Processing = function Processing(aElement, aCode) { + if (typeof aElement == "string") aElement = document.getElementById(aElement); + var p = buildProcessing(aElement); + if (aCode) p.init(aCode); + return p; + }; + + function log() { + try { + console.log.apply(console, arguments); + } catch(e) { + try { + opera.postError.apply(opera, arguments); + } catch(e) {} + } + } + var parse = Processing.parse = function parse(aCode, p) { + aCode = aCode.replace(/\/\/ .*\n/g, "\n"); + aCode = aCode.replace(/([^\s])%([^\s])/g, "$1 % $2"); + aCode = aCode.replace(/(?:static )?(\w+ )(\w+)\s*(\([^\)]*\)\s*{)/g, function(all, type, name, args) { + if (name == "if" || name == "for" || name == "while") { + return all; + } else { + return "Processing." + name + " = function " + name + args; + } + }); + aCode = aCode.replace(/\.length\(\)/g, ".length"); + aCode = aCode.replace(/([\(,]\s*)(\w+)((?:\[\])+| )\s*(\w+\s*[\),])/g, "$1$4"); + aCode = aCode.replace(/([\(,]\s*)(\w+)((?:\[\])+| )\s*(\w+\s*[\),])/g, "$1$4"); + aCode = aCode.replace(/new (\w+)((?:\[([^\]]*)\])+)/g, function(all, name, args) { + return "new ArrayList(" + args.slice(1, -1).split("][").join(", ") + ")"; + }); + aCode = aCode.replace(/(?:static )?\w+\[\]\s*(\w+)\[?\]?\s*=\s*{.*?};/g, function(all) { + return all.replace(/{/g, "[").replace(/}/g, "]"); + }); + var intFloat = /(\n\s*(?:int|float)(?:\[\])?(?:\s*|[^\(]*?,\s*))([a-z]\w*)(;|,)/i; + while (intFloat.test(aCode)) { + aCode = aCode.replace(new RegExp(intFloat), function(all, type, name, sep) { + return type + " " + name + " = 0" + sep; + }); + } + aCode = aCode.replace(/(?:static )?(\w+)((?:\[\])+| ) *(\w+)\[?\]?(\s*[=,;])/g, function(all, type, arr, name, sep) { + if (type == "return") return all; + else return "var " + name + sep; + }); + aCode = aCode.replace(/=\s*{((.|\s)*?)};/g, function(all, data) { + return "= [" + data.replace(/{/g, "[").replace(/}/g, "]") + "]"; + }); + aCode = aCode.replace(/static\s*{((.|\n)*?)}/g, function(all, init) { + return init; + }); + aCode = aCode.replace(/super\(/g, "superMethod("); + var classes = ["int", "float", "boolean", "string"]; + + function ClassReplace(all, name, extend, vars, last) { + classes.push(name); + var static = ""; + vars = vars.replace(/final\s+var\s+(\w+\s*=\s*.*?;)/g, function(all, set) { + static += " " + name + "." + set; + return ""; + }); + return "function " + name + "() {with(this){\n " + (extend ? "var __self=this;function superMethod(){extendClass(__self,arguments," + extend + ");}\n" : "") + vars.replace(/,\s?/g, ";\n this.").replace(/\b(var |final |public )+\s*/g, "this.").replace(/this.(\w+);/g, "this.$1 = null;") + (extend ? "extendClass(this, " + extend + ");\n" : "") + "" + (typeof last == "string" ? last : name + "("); + } + var matchClasses = /(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?{\s*((?:.|\n)*?)\b\1\s*\(/g; + var matchNoCon = /(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?{\s*((?:.|\n)*?)(Processing)/g; + aCode = aCode.replace(matchClasses, ClassReplace); + aCode = aCode.replace(matchNoCon, ClassReplace); + var matchClass = //, + m; + while ((m = aCode.match(matchClass))) { + var left = RegExp.leftContext, + allRest = RegExp.rightContext, + rest = nextBrace(allRest), + className = m[1], + staticVars = m[2] || ""; + allRest = allRest.slice(rest.length + 1); + rest = rest.replace(new RegExp("\\b" + className + "\\(([^\\)]*?)\\)\\s*{", "g"), function(all, args) { + args = args.split(/,\s*?/); + if (args[0].match(/^\s*$/)) args.shift(); + var fn = "if ( arguments.length == " + args.length + " ) {\n"; + for (var i = 0; i < args.length; i++) { + fn += " var " + args[i] + " = arguments[" + i + "];\n"; + } + return fn; + }); + rest = rest.replace(/(?:public )?Processing.\w+ = function (\w+)\((.*?)\)/g, function(all, name, args) { + return "ADDMETHOD(this, '" + name + "', function(" + args + ")"; + }); + var matchMethod = /ADDMETHOD([\s\S]*?{)/, + mc; + var methods = ""; + while ((mc = rest.match(matchMethod))) { + var prev = RegExp.leftContext, + allNext = RegExp.rightContext, + next = nextBrace(allNext); + methods += "addMethod" + mc[1] + next + "});" + rest = prev + allNext.slice(next.length + 1); + } + rest = methods + rest; + aCode = left + rest + "\n}}" + staticVars + allRest; + } + aCode = aCode.replace(/Processing.\w+ = function addMethod/g, "addMethod"); + + function nextBrace(right) { + var rest = right; + var position = 0; + var leftCount = 1, + rightCount = 0; + while (leftCount != rightCount) { + var nextLeft = rest.indexOf("{"); + var nextRight = rest.indexOf("}"); + if (nextLeft < nextRight && nextLeft != -1) { + leftCount++; + rest = rest.slice(nextLeft + 1); + position += nextLeft + 1; + } else { + rightCount++; + rest = rest.slice(nextRight + 1); + position += nextRight + 1; + } + } + return right.slice(0, position - 1); + } + aCode = aCode.replace(/\(int\)/g, "0|"); + aCode = aCode.replace(new RegExp("\\((" + classes.join("|") + ")(\\[\\])?\\)", "g"), ""); + aCode = aCode.replace(/(\d+)f/g, "$1"); + aCode = aCode.replace(/('[a-zA-Z0-9]')/g, "$1.charCodeAt(0)"); + aCode = aCode.replace(/#([a-f0-9]{6})/ig, function(m, hex) { + var num = toNumbers(hex); + return "color(" + num[0] + "," + num[1] + "," + num[2] + ")"; + }); + + function toNumbers(str) { + var ret = []; + str.replace(/(..)/g, function(str) { + ret.push(parseInt(str, 16)); + }); + return ret; + } + return aCode; + }; + + function buildProcessing(curElement) { + var p = {}; + p.PI = Math.PI; + p.TWO_PI = 2 * p.PI; + p.HALF_PI = p.PI / 2; + p.P3D = 3; + p.CORNER = 0; + p.RADIUS = 1; + p.CENTER_RADIUS = 1; + p.CENTER = 2; + p.POLYGON = 2; + p.QUADS = 5; + p.TRIANGLES = 6; + p.POINTS = 7; + p.LINES = 8; + p.TRIANGLE_STRIP = 9; + p.TRIANGLE_FAN = 4; + p.QUAD_STRIP = 3; + p.CORNERS = 10; + p.CLOSE = true; + p.RGB = 1; + p.HSB = 2; + p.CENTER = 88888880; + p.CODED = 88888888; + p.UP = 88888870; + p.RIGHT = 88888871; + p.DOWN = 88888872; + p.LEFT = 88888869; + p.codedKeys = [69, 70, 71, 72]; + var curContext = curElement.getContext("2d"); + var doFill = true; + var doStroke = true; + var loopStarted = false; + var hasBackground = false; + var doLoop = true; + var looping = 0; + var curRectMode = p.CORNER; + var curEllipseMode = p.CENTER; + var inSetup = false; + var inDraw = false; + var curBackground = "rgba(204,204,204,1)"; + var curFrameRate = 1000; + var curShape = p.POLYGON; + var curShapeCount = 0; + var curvePoints = []; + var curTightness = 0; + var opacityRange = 255; + var redRange = 255; + var greenRange = 255; + var blueRange = 255; + var pathOpen = false; + var mousePressed = false; + var keyPressed = false; + var firstX, firstY, secondX, secondY, prevX, prevY; + var curColorMode = p.RGB; + var curTint = -1; + var curTextSize = 12; + var curTextFont = "Arial"; + var getLoaded = false; + var start = (new Date).getTime(); + p.pmouseX = 0; + p.pmouseY = 0; + p.mouseX = 0; + p.mouseY = 0; + p.mouseButton = 0; + p.mouseDragged = undefined; + p.mouseMoved = undefined; + p.mousePressed = undefined; + p.mouseReleased = undefined; + p.keyPressed = undefined; + p.keyReleased = undefined; + p.draw = undefined; + p.setup = undefined; + p.width = curElement.width - 0; + p.height = curElement.height - 0; + p.frameCount = 0; + p.ajax = function(url) { + if (window.XMLHttpRequest) { + AJAX = new XMLHttpRequest(); + } else { + AJAX = new ActiveXObject("Microsoft.XMLHTTP"); + } + if (AJAX) { + AJAX.open("GET", url, false); + AJAX.send(null); + return AJAX.responseText; + } else { + return false; + } + } + p.loadStrings = function loadStrings(url) { + return p.ajax(url).split("\n"); + }; + p.color = function color(aValue1, aValue2, aValue3, aValue4) { + var aColor = ""; + if (arguments.length == 3) { + aColor = p.color(aValue1, aValue2, aValue3, opacityRange); + } else if (arguments.length == 4) { + var a = aValue4 / opacityRange; + a = isNaN(a) ? 1 : a; + if (curColorMode == p.HSB) { + var rgb = HSBtoRGB(aValue1, aValue2, aValue3); + var r = rgb[0], + g = rgb[1], + b = rgb[2]; + } else { + var r = getColor(aValue1, redRange); + var g = getColor(aValue2, greenRange); + var b = getColor(aValue3, blueRange); + } + aColor = "rgba(" + r + "," + g + "," + b + "," + a + ")"; + } else if (typeof aValue1 == "string") { + aColor = aValue1; + if (arguments.length == 2) { + var c = aColor.split(","); + c[3] = (aValue2 / opacityRange) + ")"; + aColor = c.join(","); + } + } else if (arguments.length == 2) { + aColor = p.color(aValue1, aValue1, aValue1, aValue2); + } else if (typeof aValue1 == "number") { + aColor = p.color(aValue1, aValue1, aValue1, opacityRange); + } else { + aColor = p.color(redRange, greenRange, blueRange, opacityRange); + } + + function HSBtoRGB(h, s, b) { + h = (h / redRange) * 100; + s = (s / greenRange) * 100; + b = (b / blueRange) * 100; + if (s == 0) { + return [b, b, b]; + } else { + var hue = h % 360; + var f = hue % 60; + var br = Math.round(b / 100 * 255); + var p = Math.round((b * (100 - s)) / 10000 * 255); + var q = Math.round((b * (6000 - s * f)) / 600000 * 255); + var t = Math.round((b * (6000 - s * (60 - f))) / 600000 * 255); + switch (Math.floor(hue / 60)) { + case 0: + return [br, t, p]; + case 1: + return [q, br, p]; + case 2: + return [p, br, t]; + case 3: + return [p, q, br]; + case 4: + return [t, p, br]; + case 5: + return [br, p, q]; + } + } + } + + function getColor(aValue, range) { + return Math.round(255 * (aValue / range)); + } + return aColor; + } + p.red = function(aColor) { + return parseInt(verifyChannel(aColor).slice(5)); + }; + p.green = function(aColor) { + return parseInt(verifyChannel(aColor).split(",")[1]); + }; + p.blue = function(aColor) { + return parseInt(verifyChannel(aColor).split(",")[2]); + }; + p.alpha = function(aColor) { + return parseInt(parseFloat(verifyChannel(aColor).split(",")[3]) * 255); + }; + + function verifyChannel(aColor) { + if (aColor.constructor == Array) { + return aColor; + } else { + return p.color(aColor); + } + } + p.lerpColor = function lerpColor(c1, c2, amt) { + var colors1 = p.color(c1).split(","); + var r1 = parseInt(colors1[0].split("(")[1]); + var g1 = parseInt(colors1[1]); + var b1 = parseInt(colors1[2]); + var a1 = parseFloat(colors1[3].split(")")[0]); + var colors2 = p.color(c2).split(","); + var r2 = parseInt(colors2[0].split("(")[1]); + var g2 = parseInt(colors2[1]); + var b2 = parseInt(colors2[2]); + var a2 = parseFloat(colors2[3].split(")")[0]); + var r = parseInt(p.lerp(r1, r2, amt)); + var g = parseInt(p.lerp(g1, g2, amt)); + var b = parseInt(p.lerp(b1, b2, amt)); + var a = parseFloat(p.lerp(a1, a2, amt)); + aColor = "rgba(" + r + "," + g + "," + b + "," + a + ")"; + return aColor; + } + p.nf = function(num, pad) { + var str = "" + num; + while (pad - str.length) str = "0" + str; + return str; + }; + p.AniSprite = function(prefix, frames) { + this.images = []; + this.pos = 0; + for (var i = 0; i < frames; i++) { + this.images.push(prefix + p.nf(i, ("" + frames).length) + ".gif"); + } + this.display = function(x, y) { + p.image(this.images[this.pos], x, y); + if (++this.pos >= frames) this.pos = 0; + }; + this.getWidth = function() { + return getImage(this.images[0]).width; + }; + this.getHeight = function() { + return getImage(this.images[0]).height; + }; + }; + + function buildImageObject(obj) { + var pixels = obj.data; + var data = p.createImage(obj.width, obj.height); + if (data.__defineGetter__ && data.__lookupGetter__ && !data.__lookupGetter__("pixels")) { + var pixelsDone; + data.__defineGetter__("pixels", function() { + if (pixelsDone) return pixelsDone; + pixelsDone = []; + for (var i = 0; i < pixels.length; i += 4) { + pixelsDone.push(p.color(pixels[i], pixels[i + 1], pixels[i + 2], pixels[i + 3])); + } + return pixelsDone; + }); + } else { + data.pixels = []; + for (var i = 0; i < pixels.length; i += 4) { + data.pixels.push(p.color(pixels[i], pixels[i + 1], pixels[i + 2], pixels[i + 3])); + } + } + return data; + } + p.createImage = function createImage(w, h, mode) { + var data = {}; + data.width = w; + data.height = h; + data.data = []; + if (curContext.createImageData) { + data = curContext.createImageData(w, h); + } + data.pixels = new Array(w * h); + data.get = function(x, y) { + return this.pixels[w * y + x]; + }; + data._mask = null; + data.mask = function(img) { + this._mask = img; + }; + data.loadPixels = function() {}; + data.updatePixels = function() {}; + return data; + }; + p.createGraphics = function createGraphics(w, h) { + var canvas = document.createElement("canvas"); + var ret = buildProcessing(canvas); + ret.size(w, h); + ret.canvas = canvas; + return ret; + }; + p.beginDraw = function beginDraw() {}; + p.endDraw = function endDraw() {}; + p.tint = function tint(rgb, a) { + curTint = a; + }; + + function getImage(img) { + if (typeof img == "string") { + return document.getElementById(img); + } + if (img.img || img.canvas) { + return img.img || img.canvas; + } + for (var i = 0, l = img.pixels.length; i < l; i++) { + var pos = i * 4; + var c = (img.pixels[i] || "rgba(0,0,0,1)").slice(5, -1).split(","); + img.data[pos] = parseInt(c[0]); + img.data[pos + 1] = parseInt(c[1]); + img.data[pos + 2] = parseInt(c[2]); + img.data[pos + 3] = parseFloat(c[3]) * 100; + } + var canvas = document.createElement("canvas") canvas.width = img.width; + canvas.height = img.height; + var context = canvas.getContext("2d"); + context.putImageData(img, 0, 0); + img.canvas = canvas; + return canvas; + } + p.image = function image(img, x, y, w, h) { + x = x || 0; + y = y || 0; + var obj = getImage(img); + if (curTint >= 0) { + var oldAlpha = curContext.globalAlpha; + curContext.globalAlpha = curTint / opacityRange; + } + if (arguments.length == 3) { + curContext.drawImage(obj, x, y); + } else { + curContext.drawImage(obj, x, y, w, h); + } + if (curTint >= 0) { + curContext.globalAlpha = oldAlpha; + } + if (img._mask) { + var oldComposite = curContext.globalCompositeOperation; + curContext.globalCompositeOperation = "darker"; + p.image(img._mask, x, y); + curContext.globalCompositeOperation = oldComposite; + } + }; + p.exit = function exit() { + clearInterval(looping); + }; + p.save = function save(file) {}; + p.loadImage = function loadImage(file) { + var img = document.getElementById(file); + if (!img) return; + var h = img.height, + w = img.width; + var canvas = document.createElement("canvas"); + canvas.width = w; + canvas.height = h; + var context = canvas.getContext("2d"); + context.drawImage(img, 0, 0); + var data = buildImageObject(context.getImageData(0, 0, w, h)); + data.img = img; + return data; + }; + p.loadFont = function loadFont(name) { + return { + name: name, + width: function(str) { + if (curContext.mozMeasureText) return curContext.mozMeasureText(typeof str == "number" ? String.fromCharCode(str) : str) / curTextSize; + else return 0; + } + }; + }; + p.textFont = function textFont(name, size) { + curTextFont = name; + p.textSize(size); + }; + p.textSize = function textSize(size) { + if (size) { + curTextSize = size; + } + }; + p.textAlign = function textAlign() {}; + p.text = function text(str, x, y) { + if (str && curContext.mozDrawText) { + curContext.save(); + curContext.mozTextStyle = curTextSize + "px " + curTextFont.name; + curContext.translate(x, y); + curContext.mozDrawText(typeof str == "number" ? String.fromCharCode(str) : str); + curContext.restore(); + } + }; + p.print = function print(output) { + alert(output); + } + p.println = p.print; + p.char = function char(key) { + return key; + }; + p.map = function map(value, istart, istop, ostart, ostop) { + return ostart + (ostop - ostart) * ((value - istart) / (istop - istart)); + }; + String.prototype.replaceAll = function(re, replace) { + return this.replace(new RegExp(re, "g"), replace); + }; + p.Point = function Point(x, y) { + this.x = x; + this.y = y; + this.copy = function() { + return new Point(x, y); + } + }; + p.Random = function() { + var haveNextNextGaussian = false; + var nextNextGaussian; + this.nextGaussian = function() { + if (haveNextNextGaussian) { + haveNextNextGaussian = false; + return nextNextGaussian; + } else { + var v1, v2, s; + do { + v1 = 2 * p.random(1) - 1; + v2 = 2 * p.random(1) - 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; + } + }; + }; + p.ArrayList = function ArrayList(size, size2, size3) { + var array = new Array(0 | size); + if (size2) { + for (var i = 0; i < size; i++) { + array[i] = []; + for (var j = 0; j < size2; j++) { + var a = array[i][j] = size3 ? new Array(size3) : 0; + for (var k = 0; k < size3; k++) { + a[k] = 0; + } + } + } + } else { + for (var i = 0; i < size; i++) { + array[i] = 0; + } + } + array.size = function() { + return this.length; + }; + array.get = function(i) { + return this[i]; + }; + array.remove = function(i) { + return this.splice(i, 1); + }; + array.add = function(item) { + return this.push(item); + }; + array.clone = function() { + var a = new ArrayList(size); + for (var i = 0; i < size; i++) { + a[i] = this[i]; + } + return a; + }; + array.isEmpty = function() { + return !this.length; + }; + array.clear = function() { + this.length = 0; + }; + return array; + }; + p.colorMode = function colorMode(mode, range1, range2, range3, range4) { + curColorMode = mode; + if (arguments.length >= 4) { + redRange = range1; + greenRange = range2; + blueRange = range3; + } + if (arguments.length == 5) { + opacityRange = range4; + } + if (arguments.length == 2) { + p.colorMode(mode, range1, range1, range1, range1); + } + }; + p.beginShape = function beginShape(type) { + curShape = type; + curShapeCount = 0; + curvePoints = []; + }; + p.endShape = function endShape(close) { + if (curShapeCount != 0) { + if (close || doFill) curContext.lineTo(firstX, firstY); + if (doFill) curContext.fill(); + if (doStroke) curContext.stroke(); + curContext.closePath(); + curShapeCount = 0; + pathOpen = false; + } + if (pathOpen) { + if (doFill) curContext.fill(); + if (doStroke) curContext.stroke(); + curContext.closePath(); + curShapeCount = 0; + pathOpen = false; + } + }; + p.vertex = function vertex(x, y, x2, y2, x3, y3) { + if (curShapeCount == 0 && curShape != p.POINTS) { + pathOpen = true; + curContext.beginPath(); + curContext.moveTo(x, y); + firstX = x; + firstY = y; + } else { + if (curShape == p.POINTS) { + p.point(x, y); + } else if (arguments.length == 2) { + if (curShape != p.QUAD_STRIP || curShapeCount != 2) curContext.lineTo(x, y); + if (curShape == p.TRIANGLE_STRIP) { + if (curShapeCount == 2) { + p.endShape(p.CLOSE); + pathOpen = true; + curContext.beginPath(); + curContext.moveTo(prevX, prevY); + curContext.lineTo(x, y); + curShapeCount = 1; + } + firstX = prevX; + firstY = prevY; + } + if (curShape == p.TRIANGLE_FAN && curShapeCount == 2) { + p.endShape(p.CLOSE); + pathOpen = true; + curContext.beginPath(); + curContext.moveTo(firstX, firstY); + curContext.lineTo(x, y); + curShapeCount = 1; + } + if (curShape == p.QUAD_STRIP && curShapeCount == 3) { + curContext.lineTo(prevX, prevY); + p.endShape(p.CLOSE); + pathOpen = true; + curContext.beginPath(); + curContext.moveTo(prevX, prevY); + curContext.lineTo(x, y); + curShapeCount = 1; + } + if (curShape == p.QUAD_STRIP) { + firstX = secondX; + firstY = secondY; + secondX = prevX; + secondY = prevY; + } + } else if (arguments.length == 4) { + if (curShapeCount > 1) { + curContext.moveTo(prevX, prevY); + curContext.quadraticCurveTo(firstX, firstY, x, y); + curShapeCount = 1; + } + } else if (arguments.length == 6) { + curContext.bezierCurveTo(x, y, x2, y2, x3, y3); + } + } + prevX = x; + prevY = y; + curShapeCount++; + if (curShape == p.LINES && curShapeCount == 2 || (curShape == p.TRIANGLES) && curShapeCount == 3 || (curShape == p.QUADS) && curShapeCount == 4) { + p.endShape(p.CLOSE); + } + }; + p.curveVertex = function(x, y, x2, y2) { + if (curvePoints.length < 3) { + curvePoints.push([x, y]); + } else { + var b = [], + s = 1 - curTightness; + curvePoints.push([x, y]); + b[0] = [curvePoints[1][0], curvePoints[1][1]]; + b[1] = [curvePoints[1][0] + (s * curvePoints[2][0] - s * curvePoints[0][0]) / 6, curvePoints[1][1] + (s * curvePoints[2][1] - s * curvePoints[0][1]) / 6]; + b[2] = [curvePoints[2][0] + (s * curvePoints[1][0] - s * curvePoints[3][0]) / 6, curvePoints[2][1] + (s * curvePoints[1][1] - s * curvePoints[3][1]) / 6]; + b[3] = [curvePoints[2][0], curvePoints[2][1]]; + if (!pathOpen) { + p.vertex(b[0][0], b[0][1]); + } else { + curShapeCount = 1; + } + p.vertex(b[1][0], b[1][1], b[2][0], b[2][1], b[3][0], b[3][1]); + curvePoints.shift(); + } + }; + p.curveTightness = function(tightness) { + curTightness = tightness; + }; + p.bezierVertex = p.vertex; + p.rectMode = function rectMode(aRectMode) { + curRectMode = aRectMode; + }; + p.imageMode = function() {}; + p.ellipseMode = function ellipseMode(aEllipseMode) { + curEllipseMode = aEllipseMode; + }; + p.dist = function dist(x1, y1, x2, y2) { + return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); + }; + p.year = function year() { + return (new Date).getYear() + 1900; + }; + p.month = function month() { + return (new Date).getMonth(); + }; + p.day = function day() { + return (new Date).getDay(); + }; + p.hour = function hour() { + return (new Date).getHours(); + }; + p.minute = function minute() { + return (new Date).getMinutes(); + }; + p.second = function second() { + return (new Date).getSeconds(); + }; + p.millis = function millis() { + return (new Date).getTime() - start; + }; + p.ortho = function ortho() {}; + p.translate = function translate(x, y) { + curContext.translate(x, y); + }; + p.scale = function scale(x, y) { + curContext.scale(x, y || x); + }; + p.rotate = function rotate(aAngle) { + curContext.rotate(aAngle); + }; + p.pushMatrix = function pushMatrix() { + curContext.save(); + }; + p.popMatrix = function popMatrix() { + curContext.restore(); + }; + p.redraw = function redraw() { + if (hasBackground) { + p.background(); + } + p.frameCount++; + inDraw = true; + p.pushMatrix(); + p.draw(); + p.popMatrix(); + inDraw = false; + }; + p.loop = function loop() { + if (loopStarted) return; + looping = setInterval(function() { + try { + if (!p.paused) { + p.redraw(); + } + } catch(e) { + clearInterval(looping); + throw e; + } + }, + 1000 / curFrameRate); + loopStarted = true; + }; + p.frameRate = function frameRate(aRate) { + curFrameRate = aRate; + }; + p.background = function background(img) { + if (arguments.length) { + if (img && img.img) { + curBackground = img; + } else { + curBackground = p.color.apply(this, arguments); + } + } + if (curBackground.img) { + p.image(curBackground, 0, 0); + } else { + var oldFill = curContext.fillStyle; + curContext.fillStyle = curBackground + ""; + curContext.fillRect(0, 0, p.width, p.height); + curContext.fillStyle = oldFill; + } + }; + p.clear = function clear(x, y, width, height) { + arguments.length == 0 ? curContext.clearRect(0, 0, p.width, p.height) : curContext.clearRect(x, y, width, height); + } + p.str = function str(aNumber) { + return aNumber + ''; + } + p.sq = function sq(aNumber) { + return aNumber * aNumber; + }; + p.sqrt = function sqrt(aNumber) { + return Math.sqrt(aNumber); + }; + p.ngsqrt = function ngsqrt(aNumber) { + if (aNumber <= 0) { + return Math.sqrt(-aNumber); + } else { + return Math.sqrt(aNumber); + } + }; + p.int = function int(aNumber) { + return Math.floor(aNumber); + }; + p.min = function min(aNumber, aNumber2) { + return Math.min(aNumber, aNumber2); + }; + p.max = function max(aNumber, aNumber2) { + return Math.max(aNumber, aNumber2); + }; + p.ceil = function ceil(aNumber) { + return Math.ceil(aNumber); + }; + p.round = function round(aNumber) { + return Math.round(aNumber); + }; + p.norm = function norm(aNumber, low, high) { + var range = high - low; + return ((1 / range) * aNumber) - ((1 / range) * low); + }; + p.lerp = function lerp(value1, value2, amt) { + var range = value2 - value1; + return (range * amt) + value1; + } + p.floor = function floor(aNumber) { + return Math.floor(aNumber); + }; + p.float = function float(aNumber) { + return parseFloat(aNumber); + }; + p.byte = function byte(aNumber) { + return aNumber || 0; + }; + p.random = function random(aMin, aMax) { + return arguments.length == 2 ? aMin + (Math.random() * (aMax - aMin)) : Math.random() * aMin; + }; + p.noise = function(x, y, z) { + return arguments.length >= 2 ? PerlinNoise_2D(x, y) : PerlinNoise_2D(x, x); + }; + + function Noise(x, y) { + var n = x + y * 57; + n = (n << 13) ^ n; + return Math.abs(1.0 - (((n * ((n * n * 15731) + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0)); + }; + + function SmoothedNoise(x, y) { + var corners = (Noise(x - 1, y - 1) + Noise(x + 1, y - 1) + Noise(x - 1, y + 1) + Noise(x + 1, y + 1)) / 16; + var sides = (Noise(x - 1, y) + Noise(x + 1, y) + Noise(x, y - 1) + Noise(x, y + 1)) / 8; + var center = Noise(x, y) / 4; + return corners + sides + center; + }; + + function InterpolatedNoise(x, y) { + var integer_X = Math.floor(x); + var fractional_X = x - integer_X; + var integer_Y = Math.floor(y); + var fractional_Y = y - integer_Y; + var v1 = SmoothedNoise(integer_X, integer_Y); + var v2 = SmoothedNoise(integer_X + 1, integer_Y); + var v3 = SmoothedNoise(integer_X, integer_Y + 1); + var v4 = SmoothedNoise(integer_X + 1, integer_Y + 1); + var i1 = Interpolate(v1, v2, fractional_X); + var i2 = Interpolate(v3, v4, fractional_X); + return Interpolate(i1, i2, fractional_Y); + } + + function PerlinNoise_2D(x, y) { + var total = 0; + var p = 0.25; + var n = 3; + for (var i = 0; i <= n; i++) { + var frequency = Math.pow(2, i); + var amplitude = Math.pow(p, i); + total = total + InterpolatedNoise(x * frequency, y * frequency) * amplitude; + } + return total; + } + + function Interpolate(a, b, x) { + var ft = x * p.PI; + var f = (1 - p.cos(ft)) * .5; + return a * (1 - f) + b * f; + } + p.abs = function abs(aNumber) { + return Math.abs(aNumber); + }; + p.cos = function cos(aNumber) { + return Math.cos(aNumber); + }; + p.sin = function sin(aNumber) { + return Math.sin(aNumber); + }; + p.pow = function pow(aNumber, aExponent) { + return Math.pow(aNumber, aExponent); + }; + p.constrain = function constrain(aNumber, aMin, aMax) { + return Math.min(Math.max(aNumber, aMin), aMax); + }; + p.sqrt = function sqrt(aNumber) { + return Math.sqrt(aNumber); + }; + p.atan2 = function atan2(aNumber, aNumber2) { + return Math.atan2(aNumber, aNumber2); + }; + p.radians = function radians(aAngle) { + return (aAngle / 180) * p.PI; + }; + p.degrees = function degrees(aAngle) { + aAngle = (aAngle * 180) / p.PI; + if (aAngle < 0) { + aAngle = 360 + aAngle + } + return aAngle; + }; + p.size = function size(aWidth, aHeight) { + var fillStyle = curContext.fillStyle; + var strokeStyle = curContext.strokeStyle; + curElement.width = p.width = aWidth; + curElement.height = p.height = aHeight; + curContext.fillStyle = fillStyle; + curContext.strokeStyle = strokeStyle; + }; + p.noStroke = function noStroke() { + doStroke = false; + }; + p.noFill = function noFill() { + doFill = false; + }; + p.smooth = function smooth() {}; + p.noSmooth = function noSmooth() {}; + p.noLoop = function noLoop() { + clearInterval(looping); + loopStarted = false; + doLoop = false; + }; + p.fill = function fill() { + doFill = true; + curContext.fillStyle = p.color.apply(this, arguments); + }; + p.stroke = function stroke() { + doStroke = true; + curContext.strokeStyle = p.color.apply(this, arguments); + }; + p.strokeWeight = function strokeWeight(w) { + curContext.lineWidth = w; + }; + p.point = function point(x, y) { + var oldFill = curContext.fillStyle; + curContext.fillStyle = curContext.strokeStyle; + curContext.fillRect(Math.round(x), Math.round(y), 1, 1); + curContext.fillStyle = oldFill; + }; + p.get = function get(x, y) { + if (arguments.length == 0) { + var c = p.createGraphics(p.width, p.height); + c.image(curContext, 0, 0); + return c; + } + if (!getLoaded) { + getLoaded = buildImageObject(curContext.getImageData(0, 0, p.width, p.height)); + } + return getLoaded.get(x, y); + }; + p.set = function set(x, y, obj) { + if (obj && obj.img) { + p.image(obj, x, y); + } else { + var oldFill = curContext.fillStyle; + var color = obj; + curContext.fillStyle = color; + curContext.fillRect(Math.round(x), Math.round(y), 1, 1); + curContext.fillStyle = oldFill; + } + }; + p.arc = function arc(x, y, width, height, start, stop) { + if (width <= 0) return; + if (curEllipseMode == p.CORNER) { + x += width / 2; + y += height / 2; + } + curContext.moveTo(x, y); + curContext.beginPath(); + curContext.arc(x, y, curEllipseMode == p.CENTER_RADIUS ? width : width / 2, start, stop, false); + if (doStroke) curContext.stroke(); + curContext.lineTo(x, y); + if (doFill) curContext.fill(); + curContext.closePath(); + }; + p.line = function line(x1, y1, x2, y2) { + curContext.lineCap = "round"; + curContext.beginPath(); + curContext.moveTo(x1 || 0, y1 || 0); + curContext.lineTo(x2 || 0, y2 || 0); + curContext.stroke(); + curContext.closePath(); + }; + p.bezier = function bezier(x1, y1, x2, y2, x3, y3, x4, y4) { + curContext.lineCap = "butt"; + curContext.beginPath(); + curContext.moveTo(x1, y1); + curContext.bezierCurveTo(x2, y2, x3, y3, x4, y4); + curContext.stroke(); + curContext.closePath(); + }; + p.triangle = function triangle(x1, y1, x2, y2, x3, y3) { + p.beginShape(); + p.vertex(x1, y1); + p.vertex(x2, y2); + p.vertex(x3, y3); + p.endShape(); + }; + p.quad = function quad(x1, y1, x2, y2, x3, y3, x4, y4) { + curContext.lineCap = "square"; + p.beginShape(); + p.vertex(x1, y1); + p.vertex(x2, y2); + p.vertex(x3, y3); + p.vertex(x4, y4); + p.endShape(); + }; + p.rect = function rect(x, y, width, height) { + if (width == 0 && height == 0) return; + curContext.beginPath(); + var offsetStart = 0; + var offsetEnd = 0; + if (curRectMode == p.CORNERS) { + width -= x; + height -= y; + } + if (curRectMode == p.RADIUS) { + width *= 2; + height *= 2; + } + if (curRectMode == p.CENTER || curRectMode == p.RADIUS) { + x -= width / 2; + y -= height / 2; + } + curContext.rect(Math.round(x) - offsetStart, Math.round(y) - offsetStart, Math.round(width) + offsetEnd, Math.round(height) + offsetEnd); + if (doFill) curContext.fill(); + if (doStroke) curContext.stroke(); + curContext.closePath(); + }; + p.ellipse = function ellipse(x, y, width, height) { + x = x || 0; + y = y || 0; + if (width <= 0 && height <= 0) return; + curContext.beginPath(); + if (curEllipseMode == p.RADIUS) { + width *= 2; + height *= 2; + } + var offsetStart = 0; + if (width == height) { + curContext.arc(x - offsetStart, y - offsetStart, width / 2, 0, Math.PI * 2, false); + } else { + var w = width / 2; + var h = height / 2; + var C = 0.5522847498307933; + var c_x = C * w; + var c_y = C * h; + curContext.moveTo(x + w, y); + curContext.bezierCurveTo(x + w, y - c_y, x + c_x, y - h, x, y - h); + curContext.bezierCurveTo(x - c_x, y - h, x - w, y - c_y, x - w, y); + curContext.bezierCurveTo(x - w, y + c_y, x - c_x, y + h, x, y + h); + curContext.bezierCurveTo(x + c_x, y + h, x + w, y + c_y, x + w, y); + } + if (doFill) curContext.fill(); + if (doStroke) curContext.stroke(); + curContext.closePath(); + }; + p.link = function(href, target) { + window.location = href; + }; + p.loadPixels = function() { + p.pixels = buildImageObject(curContext.getImageData(0, 0, p.width, p.height)).pixels; + }; + p.updatePixels = function() { + var colors = /(\d+),(\d+),(\d+),(\d+)/; + var pixels = {}; + pixels.width = p.width; + pixels.height = p.height; + pixels.data = []; + if (curContext.createImageData) { + pixels = curContext.createImageData(p.width, p.height); + } + var data = pixels.data; + var pos = 0; + for (var i = 0, l = p.pixels.length; i < l; i++) { + var c = (p.pixels[i] || "rgba(0,0,0,1)").match(colors); + data[pos] = parseInt(c[1]); + data[pos + 1] = parseInt(c[2]); + data[pos + 2] = parseInt(c[3]); + data[pos + 3] = parseFloat(c[4]) * 255; + pos += 4; + } + curContext.putImageData(pixels, 0, 0); + }; + p.extendClass = function extendClass(obj, args, fn) { + if (arguments.length == 3) { + fn.apply(obj, args); + } else { + args.call(obj); + } + }; + p.addMethod = function addMethod(object, name, fn) { + if (object[name]) { + var args = fn.length; + var oldfn = object[name]; + object[name] = function() { + if (arguments.length == args) return fn.apply(this, arguments); + else return oldfn.apply(this, arguments); + }; + } else { + object[name] = fn; + } + }; + p.init = function init(code) { + p.stroke(0); + p.fill(255); + curContext.translate(0.5, 0.5); + if (code) { + (function(Processing) { + with(p) { + eval(parse(code, p)); + } + })(p); + } + if (p.setup) { + inSetup = true; + p.setup(); + } + inSetup = false; + if (p.draw) { + if (!doLoop) { + p.redraw(); + } else { + p.loop(); + } + } + attach(document, "mousemove", function(e) { + var scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset; + var scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset; + p.pmouseX = p.mouseX; + p.pmouseY = p.mouseY; + p.mouseX = e.clientX - curElement.offsetLeft + scrollX; + p.mouseY = e.clientY - curElement.offsetTop + scrollY; + if (p.mouseMoved) { + p.mouseMoved(); + } + if (mousePressed && p.mouseDragged) { + p.mouseDragged(); + } + }); + attach(curElement, "mousedown", function(e) { + mousePressed = true; + switch (e.which) { + case 1: + p.mouseButton = p.LEFT; + break; + case 2: + p.mouseButton = p.CENTER; + break; + case 3: + p.mouseButton = p.RIGHT; + break; + } + if (typeof p.mousePressed == "function") { + p.mousePressed(); + } else { + p.mousePressed = true; + } + }); + attach(curElement, "contextmenu", function(e) { + e.preventDefault(); + e.stopPropagation(); + }); + attach(document, "mouseup", function(e) { + mousePressed = false; + if (typeof p.mousePressed != "function") { + p.mousePressed = false; + } + if (p.mouseReleased) { + p.mouseReleased(); + } + }); + attach(document, "keydown", function(e) { + keyPressed = true; + p.key = e.keyCode + 32; + var i; + for (i = 0; i < p.codedKeys.length; i++) { + if (p.key == p.codedKeys[i]) { + switch (p.key) { + case 70: + p.keyCode = p.UP; + break; + case 71: + p.keyCode = p.RIGHT; + break; + case 72: + p.keyCode = p.DOWN; + break; + case 69: + p.keyCode = p.LEFT; + break; + } + p.key = p.CODED; + } + } + if (e.shiftKey) { + p.key = String.fromCharCode(p.key).toUpperCase().charCodeAt(0); + } + if (typeof p.keyPressed == "function") { + p.keyPressed(); + } else { + p.keyPressed = true; + } + }); + attach(document, "keyup", function(e) { + keyPressed = false; + if (typeof p.keyPressed != "function") { + p.keyPressed = false; + } + if (p.keyReleased) { + p.keyReleased(); + } + }); + + function attach(elem, type, fn) { + if (elem.addEventListener) elem.addEventListener(type, fn, false); + else elem.attachEvent("on" + type, fn); + } + }; + return p; + } +})(); diff --git a/sagenb/data/graph_editor/processing.editor.min.js b/sagenb/data/graph_editor/processing.editor.min.js new file mode 100644 --- /dev/null +++ b/sagenb/data/graph_editor/processing.editor.min.js @@ -0,0 +1,111 @@ +(function(){this.Processing=function Processing(aElement,aCode){if(typeof aElement=="string") +aElement=document.getElementById(aElement);var p=buildProcessing(aElement);if(aCode) +p.init(aCode);return p;};function log(){try{console.log.apply(console,arguments);}catch(e){try{opera.postError.apply(opera,arguments);}catch(e){}}} +var parse=Processing.parse=function parse(aCode,p){aCode=aCode.replace(/\/\/ .*\n/g,"\n");aCode=aCode.replace(/([^\s])%([^\s])/g,"$1 % $2");aCode=aCode.replace(/(?:static )?(\w+ )(\w+)\s*(\([^\)]*\)\s*{)/g,function(all,type,name,args){if(name=="if"||name=="for"||name=="while"){return all;}else{return"Processing."+name+" = function "+name+args;}});aCode=aCode.replace(/\.length\(\)/g,".length");aCode=aCode.replace(/([\(,]\s*)(\w+)((?:\[\])+| )\s*(\w+\s*[\),])/g,"$1$4");aCode=aCode.replace(/([\(,]\s*)(\w+)((?:\[\])+| )\s*(\w+\s*[\),])/g,"$1$4");aCode=aCode.replace(/new (\w+)((?:\[([^\]]*)\])+)/g,function(all,name,args){return"new ArrayList("+args.slice(1,-1).split("][").join(", ")+")";});aCode=aCode.replace(/(?:static )?\w+\[\]\s*(\w+)\[?\]?\s*=\s*{.*?};/g,function(all){return all.replace(/{/g,"[").replace(/}/g,"]");});var intFloat=/(\n\s*(?:int|float)(?:\[\])?(?:\s*|[^\(]*?,\s*))([a-z]\w*)(;|,)/i;while(intFloat.test(aCode)){aCode=aCode.replace(new RegExp(intFloat),function(all,type,name,sep){return type+" "+name+" = 0"+sep;});} +aCode=aCode.replace(/(?:static )?(\w+)((?:\[\])+| ) *(\w+)\[?\]?(\s*[=,;])/g,function(all,type,arr,name,sep){if(type=="return") +return all;else +return"var "+name+sep;});aCode=aCode.replace(/=\s*{((.|\s)*?)};/g,function(all,data){return"= ["+data.replace(/{/g,"[").replace(/}/g,"]")+"]";});aCode=aCode.replace(/static\s*{((.|\n)*?)}/g,function(all,init){return init;});aCode=aCode.replace(/super\(/g,"superMethod(");var classes=["int","float","boolean","string"];function ClassReplace(all,name,extend,vars,last){classes.push(name);var static="";vars=vars.replace(/final\s+var\s+(\w+\s*=\s*.*?;)/g,function(all,set){static+=" "+name+"."+set;return"";});return"function "+name+"() {with(this){\n "+ +(extend?"var __self=this;function superMethod(){extendClass(__self,arguments,"+extend+");}\n":"")+ +vars.replace(/,\s?/g,";\n this.").replace(/\b(var |final |public )+\s*/g,"this.").replace(/this.(\w+);/g,"this.$1 = null;")+ +(extend?"extendClass(this, "+extend+");\n":"")+""+(typeof last=="string"?last:name+"(");} +var matchClasses=/(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?{\s*((?:.|\n)*?)\b\1\s*\(/g;var matchNoCon=/(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?{\s*((?:.|\n)*?)(Processing)/g;aCode=aCode.replace(matchClasses,ClassReplace);aCode=aCode.replace(matchNoCon,ClassReplace);var matchClass=//,m;while((m=aCode.match(matchClass))){var left=RegExp.leftContext,allRest=RegExp.rightContext,rest=nextBrace(allRest),className=m[1],staticVars=m[2]||"";allRest=allRest.slice(rest.length+1);rest=rest.replace(new RegExp("\\b"+className+"\\(([^\\)]*?)\\)\\s*{","g"),function(all,args){args=args.split(/,\s*?/);if(args[0].match(/^\s*$/)) +args.shift();var fn="if ( arguments.length == "+args.length+" ) {\n";for(var i=0;i=frames) +this.pos=0;};this.getWidth=function(){return getImage(this.images[0]).width;};this.getHeight=function(){return getImage(this.images[0]).height;};};function buildImageObject(obj){var pixels=obj.data;var data=p.createImage(obj.width,obj.height);if(data.__defineGetter__&&data.__lookupGetter__&&!data.__lookupGetter__("pixels")){var pixelsDone;data.__defineGetter__("pixels",function(){if(pixelsDone) +return pixelsDone;pixelsDone=[];for(var i=0;i=0){var oldAlpha=curContext.globalAlpha;curContext.globalAlpha=curTint/opacityRange;} +if(arguments.length==3){curContext.drawImage(obj,x,y);}else{curContext.drawImage(obj,x,y,w,h);} +if(curTint>=0){curContext.globalAlpha=oldAlpha;} +if(img._mask){var oldComposite=curContext.globalCompositeOperation;curContext.globalCompositeOperation="darker";p.image(img._mask,x,y);curContext.globalCompositeOperation=oldComposite;}};p.exit=function exit(){clearInterval(looping);};p.save=function save(file){};p.loadImage=function loadImage(file){var img=document.getElementById(file);if(!img) +return;var h=img.height,w=img.width;var canvas=document.createElement("canvas");canvas.width=w;canvas.height=h;var context=canvas.getContext("2d");context.drawImage(img,0,0);var data=buildImageObject(context.getImageData(0,0,w,h));data.img=img;return data;};p.loadFont=function loadFont(name){return{name:name,width:function(str){if(curContext.mozMeasureText) +return curContext.mozMeasureText(typeof str=="number"?String.fromCharCode(str):str)/curTextSize;else +return 0;}};};p.textFont=function textFont(name,size){curTextFont=name;p.textSize(size);};p.textSize=function textSize(size){if(size){curTextSize=size;}};p.textAlign=function textAlign(){};p.text=function text(str,x,y){if(str&&curContext.mozDrawText){curContext.save();curContext.mozTextStyle=curTextSize+"px "+curTextFont.name;curContext.translate(x,y);curContext.mozDrawText(typeof str=="number"?String.fromCharCode(str):str);curContext.restore();}};p.print=function print(output){alert(output);} +p.println=p.print;p.char=function char(key){return key;};p.map=function map(value,istart,istop,ostart,ostop){return ostart+(ostop-ostart)*((value-istart)/(istop-istart));};String.prototype.replaceAll=function(re,replace){return this.replace(new RegExp(re,"g"),replace);};p.Point=function Point(x,y){this.x=x;this.y=y;this.copy=function(){return new Point(x,y);}};p.Random=function(){var haveNextNextGaussian=false;var nextNextGaussian;this.nextGaussian=function(){if(haveNextNextGaussian){haveNextNextGaussian=false;return nextNextGaussian;}else{var v1,v2,s;do{v1=2*p.random(1)-1;v2=2*p.random(1)-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;}};};p.ArrayList=function ArrayList(size,size2,size3){var array=new Array(0|size);if(size2){for(var i=0;i=4){redRange=range1;greenRange=range2;blueRange=range3;} +if(arguments.length==5){opacityRange=range4;} +if(arguments.length==2){p.colorMode(mode,range1,range1,range1,range1);}};p.beginShape=function beginShape(type){curShape=type;curShapeCount=0;curvePoints=[];};p.endShape=function endShape(close){if(curShapeCount!=0){if(close||doFill) +curContext.lineTo(firstX,firstY);if(doFill) +curContext.fill();if(doStroke) +curContext.stroke();curContext.closePath();curShapeCount=0;pathOpen=false;} +if(pathOpen){if(doFill) +curContext.fill();if(doStroke) +curContext.stroke();curContext.closePath();curShapeCount=0;pathOpen=false;}};p.vertex=function vertex(x,y,x2,y2,x3,y3){if(curShapeCount==0&&curShape!=p.POINTS){pathOpen=true;curContext.beginPath();curContext.moveTo(x,y);firstX=x;firstY=y;}else{if(curShape==p.POINTS){p.point(x,y);}else if(arguments.length==2){if(curShape!=p.QUAD_STRIP||curShapeCount!=2) +curContext.lineTo(x,y);if(curShape==p.TRIANGLE_STRIP){if(curShapeCount==2){p.endShape(p.CLOSE);pathOpen=true;curContext.beginPath();curContext.moveTo(prevX,prevY);curContext.lineTo(x,y);curShapeCount=1;} +firstX=prevX;firstY=prevY;} +if(curShape==p.TRIANGLE_FAN&&curShapeCount==2){p.endShape(p.CLOSE);pathOpen=true;curContext.beginPath();curContext.moveTo(firstX,firstY);curContext.lineTo(x,y);curShapeCount=1;} +if(curShape==p.QUAD_STRIP&&curShapeCount==3){curContext.lineTo(prevX,prevY);p.endShape(p.CLOSE);pathOpen=true;curContext.beginPath();curContext.moveTo(prevX,prevY);curContext.lineTo(x,y);curShapeCount=1;} +if(curShape==p.QUAD_STRIP){firstX=secondX;firstY=secondY;secondX=prevX;secondY=prevY;}}else if(arguments.length==4){if(curShapeCount>1){curContext.moveTo(prevX,prevY);curContext.quadraticCurveTo(firstX,firstY,x,y);curShapeCount=1;}}else if(arguments.length==6){curContext.bezierCurveTo(x,y,x2,y2,x3,y3);}} +prevX=x;prevY=y;curShapeCount++;if(curShape==p.LINES&&curShapeCount==2||(curShape==p.TRIANGLES)&&curShapeCount==3||(curShape==p.QUADS)&&curShapeCount==4){p.endShape(p.CLOSE);}};p.curveVertex=function(x,y,x2,y2){if(curvePoints.length<3){curvePoints.push([x,y]);}else{var b=[],s=1-curTightness;curvePoints.push([x,y]);b[0]=[curvePoints[1][0],curvePoints[1][1]];b[1]=[curvePoints[1][0]+(s*curvePoints[2][0]-s*curvePoints[0][0])/6,curvePoints[1][1]+(s*curvePoints[2][1]-s*curvePoints[0][1])/6];b[2]=[curvePoints[2][0]+(s*curvePoints[1][0]-s*curvePoints[3][0])/6,curvePoints[2][1]+(s*curvePoints[1][1]-s*curvePoints[3][1])/6];b[3]=[curvePoints[2][0],curvePoints[2][1]];if(!pathOpen){p.vertex(b[0][0],b[0][1]);}else{curShapeCount=1;} +p.vertex(b[1][0],b[1][1],b[2][0],b[2][1],b[3][0],b[3][1]);curvePoints.shift();}};p.curveTightness=function(tightness){curTightness=tightness;};p.bezierVertex=p.vertex;p.rectMode=function rectMode(aRectMode){curRectMode=aRectMode;};p.imageMode=function(){};p.ellipseMode=function ellipseMode(aEllipseMode){curEllipseMode=aEllipseMode;};p.dist=function dist(x1,y1,x2,y2){return Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));};p.year=function year(){return(new Date).getYear()+1900;};p.month=function month(){return(new Date).getMonth();};p.day=function day(){return(new Date).getDay();};p.hour=function hour(){return(new Date).getHours();};p.minute=function minute(){return(new Date).getMinutes();};p.second=function second(){return(new Date).getSeconds();};p.millis=function millis(){return(new Date).getTime()-start;};p.ortho=function ortho(){};p.translate=function translate(x,y){curContext.translate(x,y);};p.scale=function scale(x,y){curContext.scale(x,y||x);};p.rotate=function rotate(aAngle){curContext.rotate(aAngle);};p.pushMatrix=function pushMatrix(){curContext.save();};p.popMatrix=function popMatrix(){curContext.restore();};p.redraw=function redraw(){if(hasBackground){p.background();} +p.frameCount++;inDraw=true;p.pushMatrix();p.draw();p.popMatrix();inDraw=false;};p.loop=function loop(){if(loopStarted) +return;looping=setInterval(function(){try{if(!p.paused){p.redraw();}} +catch(e){clearInterval(looping);throw e;}},1000/curFrameRate);loopStarted=true;};p.frameRate=function frameRate(aRate){curFrameRate=aRate;};p.background=function background(img){if(arguments.length){if(img&&img.img){curBackground=img;}else{curBackground=p.color.apply(this,arguments);}} +if(curBackground.img){p.image(curBackground,0,0);}else{var oldFill=curContext.fillStyle;curContext.fillStyle=curBackground+"";curContext.fillRect(0,0,p.width,p.height);curContext.fillStyle=oldFill;}};p.clear=function clear(x,y,width,height){arguments.length==0?curContext.clearRect(0,0,p.width,p.height):curContext.clearRect(x,y,width,height);} +p.str=function str(aNumber){return aNumber+'';} +p.sq=function sq(aNumber){return aNumber*aNumber;};p.sqrt=function sqrt(aNumber){return Math.sqrt(aNumber);};p.ngsqrt=function ngsqrt(aNumber){if(aNumber<=0){return Math.sqrt(-aNumber);}else{return Math.sqrt(aNumber);}};p.int=function int(aNumber){return Math.floor(aNumber);};p.min=function min(aNumber,aNumber2){return Math.min(aNumber,aNumber2);};p.max=function max(aNumber,aNumber2){return Math.max(aNumber,aNumber2);};p.ceil=function ceil(aNumber){return Math.ceil(aNumber);};p.round=function round(aNumber){return Math.round(aNumber);};p.norm=function norm(aNumber,low,high){var range=high-low;return((1/range)*aNumber)-((1/range)*low);};p.lerp=function lerp(value1,value2,amt){var range=value2-value1;return(range*amt)+value1;} +p.floor=function floor(aNumber){return Math.floor(aNumber);};p.float=function float(aNumber){return parseFloat(aNumber);};p.byte=function byte(aNumber){return aNumber||0;};p.random=function random(aMin,aMax){return arguments.length==2?aMin+(Math.random()*(aMax-aMin)):Math.random()*aMin;};p.noise=function(x,y,z){return arguments.length>=2?PerlinNoise_2D(x,y):PerlinNoise_2D(x,x);};function Noise(x,y){var n=x+y*57;n=(n<<13)^n;return Math.abs(1.0-(((n*((n*n*15731)+789221)+1376312589)&0x7fffffff)/1073741824.0));};function SmoothedNoise(x,y){var corners=(Noise(x-1,y-1)+Noise(x+1,y-1)+Noise(x-1,y+1)+Noise(x+1,y+1))/16;var sides=(Noise(x-1,y)+Noise(x+1,y)+Noise(x,y-1)+Noise(x,y+1))/8;var center=Noise(x,y)/4;return corners+sides+center;};function InterpolatedNoise(x,y){var integer_X=Math.floor(x);var fractional_X=x-integer_X;var integer_Y=Math.floor(y);var fractional_Y=y-integer_Y;var v1=SmoothedNoise(integer_X,integer_Y);var v2=SmoothedNoise(integer_X+1,integer_Y);var v3=SmoothedNoise(integer_X,integer_Y+1);var v4=SmoothedNoise(integer_X+1,integer_Y+1);var i1=Interpolate(v1,v2,fractional_X);var i2=Interpolate(v3,v4,fractional_X);return Interpolate(i1,i2,fractional_Y);} +function PerlinNoise_2D(x,y){var total=0;var p=0.25;var n=3;for(var i=0;i<=n;i++){var frequency=Math.pow(2,i);var amplitude=Math.pow(p,i);total=total+InterpolatedNoise(x*frequency,y*frequency)*amplitude;} +return total;} +function Interpolate(a,b,x){var ft=x*p.PI;var f=(1-p.cos(ft))*.5;return a*(1-f)+b*f;} +p.abs=function abs(aNumber){return Math.abs(aNumber);};p.cos=function cos(aNumber){return Math.cos(aNumber);};p.sin=function sin(aNumber){return Math.sin(aNumber);};p.pow=function pow(aNumber,aExponent){return Math.pow(aNumber,aExponent);};p.constrain=function constrain(aNumber,aMin,aMax){return Math.min(Math.max(aNumber,aMin),aMax);};p.sqrt=function sqrt(aNumber){return Math.sqrt(aNumber);};p.atan2=function atan2(aNumber,aNumber2){return Math.atan2(aNumber,aNumber2);};p.radians=function radians(aAngle){return(aAngle/180)*p.PI;};p.degrees=function degrees(aAngle){aAngle=(aAngle*180)/p.PI;if(aAngle<0){aAngle=360+aAngle} +return aAngle;};p.size=function size(aWidth,aHeight){var fillStyle=curContext.fillStyle;var strokeStyle=curContext.strokeStyle;curElement.width=p.width=aWidth;curElement.height=p.height=aHeight;curContext.fillStyle=fillStyle;curContext.strokeStyle=strokeStyle;};p.noStroke=function noStroke(){doStroke=false;};p.noFill=function noFill(){doFill=false;};p.smooth=function smooth(){};p.noSmooth=function noSmooth(){};p.noLoop=function noLoop(){clearInterval(looping);loopStarted=false;doLoop=false;};p.fill=function fill(){doFill=true;curContext.fillStyle=p.color.apply(this,arguments);};p.stroke=function stroke(){doStroke=true;curContext.strokeStyle=p.color.apply(this,arguments);};p.strokeWeight=function strokeWeight(w){curContext.lineWidth=w;};p.point=function point(x,y){var oldFill=curContext.fillStyle;curContext.fillStyle=curContext.strokeStyle;curContext.fillRect(Math.round(x),Math.round(y),1,1);curContext.fillStyle=oldFill;};p.get=function get(x,y){if(arguments.length==0){var c=p.createGraphics(p.width,p.height);c.image(curContext,0,0);return c;} +if(!getLoaded){getLoaded=buildImageObject(curContext.getImageData(0,0,p.width,p.height));} +return getLoaded.get(x,y);};p.set=function set(x,y,obj){if(obj&&obj.img){p.image(obj,x,y);}else{var oldFill=curContext.fillStyle;var color=obj;curContext.fillStyle=color;curContext.fillRect(Math.round(x),Math.round(y),1,1);curContext.fillStyle=oldFill;}};p.arc=function arc(x,y,width,height,start,stop){if(width<=0) +return;if(curEllipseMode==p.CORNER){x+=width/2;y+=height/2;} +curContext.moveTo(x,y);curContext.beginPath();curContext.arc(x,y,curEllipseMode==p.CENTER_RADIUS?width:width/2,start,stop,false);if(doStroke) +curContext.stroke();curContext.lineTo(x,y);if(doFill) +curContext.fill();curContext.closePath();};p.line=function line(x1,y1,x2,y2){curContext.lineCap="round";curContext.beginPath();curContext.moveTo(x1||0,y1||0);curContext.lineTo(x2||0,y2||0);curContext.stroke();curContext.closePath();};p.bezier=function bezier(x1,y1,x2,y2,x3,y3,x4,y4){curContext.lineCap="butt";curContext.beginPath();curContext.moveTo(x1,y1);curContext.bezierCurveTo(x2,y2,x3,y3,x4,y4);curContext.stroke();curContext.closePath();};p.triangle=function triangle(x1,y1,x2,y2,x3,y3){p.beginShape();p.vertex(x1,y1);p.vertex(x2,y2);p.vertex(x3,y3);p.endShape();};p.quad=function quad(x1,y1,x2,y2,x3,y3,x4,y4){curContext.lineCap="square";p.beginShape();p.vertex(x1,y1);p.vertex(x2,y2);p.vertex(x3,y3);p.vertex(x4,y4);p.endShape();};p.rect=function rect(x,y,width,height){if(width==0&&height==0) +return;curContext.beginPath();var offsetStart=0;var offsetEnd=0;if(curRectMode==p.CORNERS){width-=x;height-=y;} +if(curRectMode==p.RADIUS){width*=2;height*=2;} +if(curRectMode==p.CENTER||curRectMode==p.RADIUS){x-=width/2;y-=height/2;} +curContext.rect(Math.round(x)-offsetStart,Math.round(y)-offsetStart,Math.round(width)+offsetEnd,Math.round(height)+offsetEnd);if(doFill) +curContext.fill();if(doStroke) +curContext.stroke();curContext.closePath();};p.ellipse=function ellipse(x,y,width,height){x=x||0;y=y||0;if(width<=0&&height<=0) +return;curContext.beginPath();if(curEllipseMode==p.RADIUS){width*=2;height*=2;} +var offsetStart=0;if(width==height){curContext.arc(x-offsetStart,y-offsetStart,width/2,0,Math.PI*2,false);}else{var w=width/2;var h=height/2;var C=0.5522847498307933;var c_x=C*w;var c_y=C*h;curContext.moveTo(x+w,y);curContext.bezierCurveTo(x+w,y-c_y,x+c_x,y-h,x,y-h);curContext.bezierCurveTo(x-c_x,y-h,x-w,y-c_y,x-w,y);curContext.bezierCurveTo(x-w,y+c_y,x-c_x,y+h,x,y+h);curContext.bezierCurveTo(x+c_x,y+h,x+w,y+c_y,x+w,y);} +if(doFill) +curContext.fill();if(doStroke) +curContext.stroke();curContext.closePath();};p.link=function(href,target){window.location=href;};p.loadPixels=function(){p.pixels=buildImageObject(curContext.getImageData(0,0,p.width,p.height)).pixels;};p.updatePixels=function(){var colors=/(\d+),(\d+),(\d+),(\d+)/;var pixels={};pixels.width=p.width;pixels.height=p.height;pixels.data=[];if(curContext.createImageData){pixels=curContext.createImageData(p.width,p.height);} +var data=pixels.data;var pos=0;for(var i=0,l=p.pixels.length;i" + ( typeof last == "string" ? last : name + "(" ); + } + + var matchClasses = /(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?{\s*((?:.|\n)*?)\b\1\s*\(/g; + var matchNoCon = /(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?{\s*((?:.|\n)*?)(Processing)/g; + + aCode = aCode.replace( matchClasses, ClassReplace ); + aCode = aCode.replace( matchNoCon, ClassReplace ); + + var matchClass = //, m; + + while ( ( m = aCode.match( matchClass ) ) ){ + + var left = RegExp.leftContext, + allRest = RegExp.rightContext, + rest = nextBrace( allRest ), + className = m[ 1 ], + staticVars = m[ 2 ] || ""; + + allRest = allRest.slice( rest.length + 1 ); + + rest = rest.replace( new RegExp("\\b" + className + "\\(([^\\)]*?)\\)\\s*{", "g"), function( all, args ){ + args = args.split( /,\s*?/ ); + + if( args[ 0 ].match( /^\s*$/ ) ){ + args.shift(); + } + + var fn = "if ( arguments.length == " + args.length + " ) {\n"; + + for ( var i = 0; i < args.length; i++ ) { + fn += " var " + args[ i ] + " = arguments["+ i +"];\n"; + } + + return fn; + }); + + // Fix class method names + // this.collide = function() { ... } + // and add closing } for with(this) ... + rest = rest.replace( /(?:public )?Processing.\w+ = function (\w+)\((.*?)\)/g, function( all, name, args ){ + return "ADDMETHOD(this, '" + name + "', function(" + args + ")"; + }); + + var matchMethod = /ADDMETHOD([\s\S]*?{)/, mc; + var methods = ""; + + while ( ( mc = rest.match( matchMethod ) ) ){ + var prev = RegExp.leftContext, + allNext = RegExp.rightContext, + next = nextBrace(allNext); + + methods += "addMethod" + mc[ 1 ] + next + "});"; + + rest = prev + allNext.slice( next.length + 1 ); + } + + rest = methods + rest; + + aCode = left + rest + "\n}}" + staticVars + allRest; + } + + // Do some tidying up, where necessary + aCode = aCode.replace( /Processing.\w+ = function addMethod/g, "addMethod" ); + + function nextBrace( right ) { + + var rest = right, + position = 0, + leftCount = 1, + rightCount = 0; + + while( leftCount != rightCount ) { + + var nextLeft = rest.indexOf( "{" ), + nextRight = rest.indexOf( "}" ); + + if( nextLeft < nextRight && nextLeft != - 1 ) { + + leftCount++; + rest = rest.slice( nextLeft + 1 ); + position += nextLeft + 1; + + }else{ + + rightCount++; + rest = rest.slice( nextRight + 1 ); + position += nextRight + 1; + + } + + } + + return right.slice( 0, position - 1 ); + } + + // Handle (int) Casting + aCode = aCode.replace( /\(int\)/g, "0|" ); + + // Remove Casting + aCode = aCode.replace( new RegExp("\\((" + classes.join("|") + ")(\\[\\])?\\)", "g"), "" ); + + // Convert 3.0f to just 3.0 + aCode = aCode.replace( /(\d+)f[^a-zA-Z0-9]/g, "$1" ); + + // Force numbers to exist // + //aCode = aCode.replace(/([^.])(\w+)\s*\+=/g, "$1$2 = ($2||0) +"); + +//! // Force characters-as-bytes to work --> Ping: Andor + aCode = aCode.replace(/('[a-zA-Z0-9]')/g, "$1.charCodeAt(0)"); + + // Convert #aaaaaa into color + aCode = aCode.replace(/#([a-f0-9]{6})/ig, function(m, hex){ + var num = toNumbers(hex); + return "DefaultColor(" + num[0] + "," + num[1] + "," + num[2] + ")"; + }); + + function toNumbers( str ){ + var ret = []; + + str.replace( /(..)/g, function( str ){ + ret.push( parseInt( str, 16 ) ); + }); + + return ret; + } + + return aCode; + + }; + + + // Attach Processing functions to 'p' + function buildProcessing( curElement ){ + + // Create the 'p' object + var p = {}; + + // Set Processing defaults / environment variables + p.name = 'Processing.js Instance'; + p.PI = Math.PI; + p.TWO_PI = 2 * p.PI; + p.HALF_PI = p.PI / 2; + p.P3D = 3; + p.CORNER = 0; + p.RADIUS = 1; + p.CENTER_RADIUS = 1; + p.CENTER = 2; + p.POLYGON = 2; + p.QUADS = 5; + p.TRIANGLES = 6; + p.POINTS = 7; + p.LINES = 8; + p.TRIANGLE_STRIP = 9; + p.TRIANGLE_FAN = 4; + p.QUAD_STRIP = 3; + p.CORNERS = 10; + p.CLOSE = true; + p.RGB = 1; + p.HSB = 2; + + // KeyCode table + p.CENTER = 88888880; + p.CODED = 88888888; + p.UP = 88888870; + p.RIGHT = 88888871; + p.DOWN = 88888872; + p.LEFT = 88888869; + +//! // Description required... + p.codedKeys = [ 69, 70, 71, 72 ]; + + // "Private" variables used to maintain state + var curContext = curElement.getContext( "2d" ), + doFill = true, + doStroke = true, + loopStarted = false, + hasBackground = false, + doLoop = true, + looping = 0, + curRectMode = p.CORNER, + curEllipseMode = p.CENTER, + inSetup = false, + inDraw = false, + curBackground = "rgba( 204, 204, 204, 1 )", + curFrameRate = 1000, + curMsPerFrame = 1, + curShape = p.POLYGON, + curShapeCount = 0, + curvePoints = [], + curTightness = 0, + opacityRange = 255, + redRange = 255, + greenRange = 255, + blueRange = 255, + pathOpen = false, + mousePressed = false, + keyPressed = false, + curColorMode = p.RGB; + curTint = - 1, + curTextSize = 12, + curTextFont = "Arial", + getLoaded = false, + start = ( new Date ).getTime(); + + var firstX, + firstY, + secondX, + secondY, + prevX, + prevY; + + // Store a line for println(), print() handline + p.ln = ""; + + // Glyph path storage for textFonts + p.glyphTable = {}; + + // Global vars for tracking mouse position + p.pmouseX = 0; + p.pmouseY = 0; + p.mouseX = 0; + p.mouseY = 0; + p.mouseButton = 0; + p.mouseDown = false; + + // Undefined event handlers to be replaced by user when needed + p.mouseClicked = undefined; + p.mouseDragged = undefined; + p.mouseMoved = undefined; + p.mousePressed = undefined; + p.mouseReleased = undefined; + p.keyPressed = undefined; + p.keyReleased = undefined; + p.draw = undefined; + p.setup = undefined; + + // The height/width of the canvas + p.width = curElement.width - 0; + p.height = curElement.height - 0; + + // The current animation frame + p.frameCount = 0; + + + + //////////////////////////////////////////////////////////////////////////// + // Array handling + //////////////////////////////////////////////////////////////////////////// + + p.shorten = function( ary ){ + + var newary = new Array(); + + // copy array into new array + var len = ary.length; + for( var i = 0; i < len; i++ ){ + newary[ i ] = ary[ i ]; + } + + newary.pop(); + + return newary; + } + + + p.expand = function( ary, newSize ){ + + var newary = new Array(); + + var len = ary.length + for( var i = 0; i < len; i++ ){ + newary[ i ] = ary[ i ]; + } + + if( arguments.length == 1 ){ + + // double size of array + newary.length *= 2; + + }else if( arguments.length == 2 ){ + + // size is newSize + newary.length = newSize; + + } + + return newary; + } + + + + p.ArrayList = function ArrayList( size, size2, size3 ){ + + var array = new Array( 0 | size ); + + if( size2 ){ + + for( var i = 0; i < size; i++ ){ + + array[ i ] = []; + + for( var j = 0; j < size2; j++ ){ + var a = array[ i ][ j ] = size3 ? new Array( size3 ) : 0 ; + for( var k = 0; k < size3; k++ ){ a[ k ] = 0; } + } + + } + + }else{ + + for( var i = 0; i < size; i++ ){ array[ i ] = 0; } + } + + array.get = function( i ){ return this[ i ]; }; + array.add = function( item ){ return this.push( item ); }; + array.size = function( ){ return this.length; }; + array.clear = function( ){ this.length = 0; }; + array.remove = function( i ){ return this.splice( i, 1 ); }; + array.isEmpty = function( ){ return !this.length; }; + array.clone = function( ){ + var a = new ArrayList( size ); + for( var i = 0; i < size; i++ ){ + a[ i ] = this[ i ]; + } + return a; + }; + + return array; + }; + + + + //////////////////////////////////////////////////////////////////////////// + // Color functions + //////////////////////////////////////////////////////////////////////////// + + // In case I ever need to do HSV conversion: + // http://srufaculty.sru.edu/david.dailey/javascript/js/5rml.js + p.color = function color( aValue1, aValue2, aValue3, aValue4 ) { + var aColor = ""; + + if ( arguments.length == 3 ) { + + aColor = p.color( aValue1, aValue2, aValue3, opacityRange ); + } else if ( arguments.length == 4 ) { + var a = aValue4 / opacityRange; + a = isNaN(a) ? 1 : a; + + if ( curColorMode == p.HSB ) { + var rgb = HSBtoRGB(aValue1, aValue2, aValue3); + var r = rgb[0], g = rgb[1], b = rgb[2]; + } else { + var r = getColor(aValue1, redRange); + var g = getColor(aValue2, greenRange); + var b = getColor(aValue3, blueRange); + } + + aColor = "rgba(" + r + "," + g + "," + b + "," + a + ")"; + } else if ( typeof aValue1 == "string" ) { + aColor = aValue1; + + if ( arguments.length == 2 ) { + var c = aColor.split(","); + c[3] = (aValue2 / opacityRange) + ")"; + aColor = c.join(","); + } + } else if ( arguments.length == 2 ) { + aColor = p.color( aValue1, aValue1, aValue1, aValue2 ); + } else if ( typeof aValue1 == "number" && aValue1 < 256 && aValue1 >= 0) { + aColor = p.color( aValue1, aValue1, aValue1, opacityRange ); + } else if ( typeof aValue1 == "number" ) { + var intcolor = 0; + if( aValue1 < 0 ){ + intcolor = 4294967296 - ( aValue1 * -1 ); + }else{ + intcolor = aValue1; + } + var ac = Math.floor((intcolor % 4294967296) / 16777216); + var rc = Math.floor((intcolor % 16777216) / 65536); + var gc = Math.floor((intcolor % 65536) / 256); + var bc = intcolor % 256; + + aColor = p.color( rc, gc, bc, ac ); + } else { + aColor = p.color( redRange, greenRange, blueRange, opacityRange ); + } + + // HSB conversion function from Mootools, MIT Licensed + function HSBtoRGB(h, s, b) { + h = (h / redRange) * 360; + s = (s / greenRange) * 100; + b = (b / blueRange) * 100; + var br = Math.round(b / 100 * 255); + if (s == 0){ + return [br, br, br]; + } else { + var hue = h % 360; + var f = hue % 60; + var p = Math.round((b * (100 - s)) / 10000 * 255); + var q = Math.round((b * (6000 - s * f)) / 600000 * 255); + var t = Math.round((b * (6000 - s * (60 - f))) / 600000 * 255); + switch (Math.floor(hue / 60)){ + case 0: return [br, t, p]; + case 1: return [q, br, p]; + case 2: return [p, br, t]; + case 3: return [p, q, br]; + case 4: return [t, p, br]; + case 5: return [br, p, q]; + } + } + } + + function getColor( aValue, range ) { + return Math.round(255 * (aValue / range)); + } + + return aColor; + } + + p.red = function( aColor ){ return parseInt( verifyChannel( aColor ).slice( 5 ) ); }; + p.green = function( aColor ){ return parseInt( verifyChannel( aColor ).split( "," )[ 1 ] ); }; + p.blue = function( aColor ){ return parseInt( verifyChannel( aColor ).split( "," )[ 2 ] ); }; + p.alpha = function( aColor ){ return parseInt( parseFloat( verifyChannel( aColor ).split( "," )[ 3 ] ) * 255 ); }; + + function verifyChannel( aColor ){ + if( aColor.constructor == Array ){ + return aColor; + } else { + return p.color( aColor ); + } + } + + p.lerpColor = function lerpColor( c1, c2, amt ){ + + // Get RGBA values for Color 1 to floats + var colors1 = p.color( c1 ).split( "," ); + var r1 = parseInt( colors1[ 0 ].split( "(" )[ 1 ] ); + var g1 = parseInt( colors1[ 1 ] ); + var b1 = parseInt( colors1[ 2 ] ); + var a1 = parseFloat( colors1[ 3 ].split( ")" )[ 0 ] ); + + // Get RGBA values for Color 2 to floats + var colors2 = p.color( c2 ).split( "," ); + var r2 = parseInt( colors2[ 0 ].split( "(" )[ 1 ] ); + var g2 = parseInt( colors2[ 1 ] ); + var b2 = parseInt( colors2[ 2 ] ); + var a2 = parseFloat( colors2[ 3 ].split( ")" )[ 0 ] ); + + // Return lerp value for each channel, INT for color, Float for Alpha-range + var r = parseInt( p.lerp( r1, r2, amt ) ); + var g = parseInt( p.lerp( g1, g2, amt ) ); + var b = parseInt( p.lerp( b1, b2, amt ) ); + var a = parseFloat( p.lerp( a1, a2, amt ) ); + + return aColor = "rgba("+ r +","+ g +","+ b +","+ a +")"; + + } + + // Forced default color mode for #aaaaaa style + p.DefaultColor = function( aValue1, aValue2, aValue3 ){ + var tmpColorMode = curColorMode; + curColorMode = p.RGB; + var c = p.color(aValue1 / 255 * redRange, aValue2 / 255 * greenRange, aValue3 / 255 * blueRange ); + curColorMode = tmpColorMode; + return c; + } + + p.colorMode = function colorMode( mode, range1, range2, range3, range4 ){ + curColorMode = mode; + if( arguments.length >= 4 ){ redRange = range1; greenRange = range2; blueRange = range3; } + if( arguments.length == 5 ){ opacityRange = range4; } + if( arguments.length == 2 ){ p.colorMode( mode, range1, range1, range1, range1 ); } + }; + + + //////////////////////////////////////////////////////////////////////////// + // Canvas-Matrix manipulation + //////////////////////////////////////////////////////////////////////////// + + p.translate = function translate( x, y ){ curContext.translate( x, y ); }; + p.scale = function scale( x, y ) { curContext.scale( x, y || x ); }; + p.rotate = function rotate( aAngle ) { curContext.rotate( aAngle ); }; + p.pushMatrix = function pushMatrix() { curContext.save(); }; + p.popMatrix = function popMatrix() { curContext.restore(); }; + p.ortho = function ortho(){}; + + + + //////////////////////////////////////////////////////////////////////////// + //Time based functions + //////////////////////////////////////////////////////////////////////////// + + p.year = function year() { return ( new Date ).getYear() + 1900; }; + p.month = function month() { return ( new Date ).getMonth(); }; + p.day = function day() { return ( new Date ).getDay(); }; + p.hour = function hour() { return ( new Date ).getHours(); }; + p.minute = function minute(){ return ( new Date ).getMinutes(); }; + p.second = function second(){ return ( new Date ).getSeconds(); }; + p.millis = function millis(){ return ( new Date ) .getTime() - start; }; + + p.noLoop = function noLoop(){ doLoop = false; }; + + p.redraw = function redraw(){ + if( hasBackground ){ p.background(); } + p.frameCount++; + inDraw = true; + p.pushMatrix(); + p.draw(); + p.popMatrix(); + inDraw = false; + }; + + p.loop = function loop(){ + + if( loopStarted ){ return; } + + looping = setInterval( function(){ + + try { + p.redraw(); + } + catch( e ){ + clearInterval( looping ); + throw e; + } + }, curMsPerFrame ); + + loopStarted = true; + + }; + + p.frameRate = function frameRate( aRate ){ + curFrameRate = aRate; + curMsPerFrame = 1000 / curFrameRate; + }; + + p.exit = function exit(){ + clearInterval( looping ); + }; + + + + //////////////////////////////////////////////////////////////////////////// + // MISC functions + //////////////////////////////////////////////////////////////////////////// + p.cursor = function(mode){ document.body.style.cursor=mode; } + p.link = function( href, target ) { window.location = href; }; + p.beginDraw = function beginDraw(){}; + p.endDraw = function endDraw(){}; + + p.ajax = ajax; + + // Imports an external Processing.js library + p.Import = function Import( lib ){ + eval( p.ajax( lib ) ); + } + + + + //////////////////////////////////////////////////////////////////////////// + // String functions + //////////////////////////////////////////////////////////////////////////// + + p.nfs = function( num, left, right){ + var str; + // array handling + if (typeof num == "object"){ + str = new Array(); + len = num.length; + for(var i=0; i < len; i++){ + str[i] = p.nfs(num[i], left, right); + } + } + else if (arguments.length == 3){ + var negative = false; + if (num < 0) + negative = true; + + str = "" + Math.abs(num); + var digits = ("" + Math.floor(Math.abs(num))).length; + var count = left - digits; + while (count > 0){ + str = "0" + str; + count--; + } + // get the number of decimal places, if none will be -1 + var decimals = ("" + Math.abs(num)).length - digits - 1; + if (decimals == -1 && right > 0) + str = str + "."; + if (decimals != -1) + count = right - decimals; + else if (decimals == -1 && right > 0){ + count = right; + } + else + count = 0; + while (count > 0){ + str = str + "0"; + count--; + } + str = (negative ? "-" : " ") + str; + } + else if (arguments.length == 2){ + str = p.nfs(num, left, 0); + } + return str; + } + + + p.unhex = function( str ){ + var value = 0, + multiplier = 1, + num = 0; + + var len = str.length - 1; + for (var i = len ; i >= 0; i--){ + try{ + switch(str[i]){ + case "0": num = 0; break; + case "1": num = 1; break; + case "2": num = 2; break; + case "3": num = 3; break; + case "4": num = 4; break; + case "5": num = 5; break; + case "6": num = 6; break; + case "7": num = 7; break; + case "8": num = 8; break; + case "9": num = 9; break; + case "A": + case "a": num = 10; break; + case "B": + case "b": num = 11; break; + case "C": + case "c": num = 12; break; + case "D": + case "d": num = 13; break; + case "E": + case "e": num = 14; break; + case "F": + case "f": num = 15; break; + default:return 0; break; + } + value += num * multiplier; + multiplier *= 16; + }catch(e){;} + // correct for int overflow java expectation + if (value > 2147483647) + { + value -= 4294967296; + } + } + return value; + } + + + // Load a file or URL into strings + p.loadStrings = function loadStrings( url ){ + return p.ajax( url ).split( "\n" ); + }; + + p.nf = function( num, pad ){ + var str = "" + num; + while ( pad - str.length ){ + str = "0" + str; + } + return str; + }; + + String.prototype.replaceAll = function( re, replace ){ + return this.replace( new RegExp( re, "g" ), replace ); + }; + + // Returns a line to lnPrinted() for user handling + p.lnPrinted = function lnPrinted(){}; + p.printed = function printed() {}; + + // Event to send output to user control function print()/println() + p.println = function println(){ + + // Not working on Safari :( find work around! + if( arguments.callee.caller ){ + + var Caller = arguments.callee.caller.name.toString(); + + if( arguments.length > 1 ){ + + Caller != "print" ? + p.ln = arguments : + p.ln = arguments[ 0 ] ; + + }else{ + + p.ln = arguments[ 0 ] ; + } + + //Returns a line to lnPrinted() for user error handling/debugging + Caller == "print" ? + p.printed( arguments ) : + p.lnPrinted() ; + + } + + }; + + // Converts a number to a string + p.str = function str( aNumber ){ return aNumber+''; } + + p.print = function print(){ p.println(arguments[ 0 ] ) }; + + p.char = function char( key ){ return key; }; + + + + //////////////////////////////////////////////////////////////////////////// + // Math functions + //////////////////////////////////////////////////////////////////////////// + + p.sq = function sq ( aNumber ){ return aNumber * aNumber; }; + p.sqrt = function sqrt ( aNumber ){ return Math.sqrt( aNumber ); }; + p.int = function int ( aNumber ){ return Math.floor( aNumber ); }; + p.min = function min ( aNumber, aNumber2 ){ return Math.min( aNumber, aNumber2 ); }; + p.max = function max ( aNumber, aNumber2 ){ return Math.max( aNumber, aNumber2 ); }; + p.floor = function floor ( aNumber ){ return Math.floor( aNumber ); }; + p.float = function float ( aNumber ){ return parseFloat( aNumber ); }; + p.ceil = function ceil ( aNumber ){ return Math.ceil( aNumber ); }; + p.round = function round ( aNumber ){ return Math.round( aNumber ); }; + p.lerp = function lerp ( value1, value2, amt ){ return ( ( value2 - value1 ) * amt ) + value1; }; + p.abs = function abs ( aNumber ){ return Math.abs( aNumber ); }; + p.cos = function cos ( aNumber ){ return Math.cos( aNumber ); }; + p.sin = function sin ( aNumber ){ return Math.sin( aNumber ); }; + p.pow = function pow ( aNumber, aExponent ){ return Math.pow( aNumber, aExponent ); }; + p.sqrt = function sqrt ( aNumber ){ return Math.sqrt( aNumber ); }; + p.atan2 = function atan2 ( aNumber, aNumber2 ){ return Math.atan2( aNumber, aNumber2 ); }; + p.radians = function radians( aAngle ){ return ( aAngle / 180 ) * p.PI; }; + + p.dist = function dist( x1, y1, x2, y2 ){ + return Math.sqrt( Math.pow( x2 - x1, 2 ) + Math.pow( y2 - y1, 2 ) ); + }; + + p.map = function map( value, istart, istop, ostart, ostop ){ + return ostart + ( ostop - ostart ) * ( ( value - istart ) / ( istop - istart ) ); + }; + + p.Random = function(){ + + var haveNextNextGaussian = false, + nextNextGaussian; + + this.nextGaussian = function(){ + + if( haveNextNextGaussian ){ + + haveNextNextGaussian = false; + return nextNextGaussian; + + }else{ + + var v1, v2, s; + do{ + v1 = 2 * p.random( 1 ) - 1; // between -1.0 and 1.0 + v2 = 2 * p.random( 1 ) - 1; // between -1.0 and 1.0 + s = v1 * v1 + v2 * v2; + } + while( s >= 1 || s == 0 ); + + var multiplier = Math.sqrt( - 2 * Math.log( s ) / s ); + nextNextGaussian = v2 * multiplier; + haveNextNextGaussian = true; + + return v1 * multiplier; + + } + + }; + + }; + +//! This can't be right... right? + p.byte = function byte( aNumber ){ return aNumber || 0; }; + + p.norm = function norm( aNumber, low, high ){ + var range = high-low; + return ( ( 1 / range ) * aNumber ) - ( ( 1 / range ) * low ); + }; + + p.random = function random( aMin, aMax ) { + return arguments.length == 2 ? + aMin + ( Math.random() * ( aMax - aMin ) ) : + Math.random() * aMin ; + }; + + // From: http://freespace.virgin.net/hugo.elias/models/m_perlin.htm + p.noise = function( x, y, z ){ + return arguments.length >= 2 ? + PerlinNoise_2D( x, y, z ) : + PerlinNoise_3D( x, x, z ) ; + }; + + function Noise( x, y ){ + var n = x + y * 57; + n = ( n << 13 ) ^ n; + return Math.abs( 1.0 - ( ( ( n * ( ( n * n * 15731 ) + 789221 ) + 1376312589 ) & 0x7fffffff ) / 1073741824.0 ) ); + }; + + function SmoothedNoise( x, y ){ + var corners = ( Noise( x - 1, y - 1 ) + Noise( x + 1, y - 1 ) + Noise( x - 1, y + 1 ) + Noise( x + 1, y + 1 ) ) / 16, + sides = ( Noise( x - 1, y ) + Noise( x + 1, y ) + Noise( x, y - 1 ) + Noise( x, y + 1 ) ) / 8, + center = Noise( x, y ) / 4; + return corners + sides + center; + }; + + function InterpolatedNoise( x, y ){ + + var integer_X = Math.floor( x ); + var fractional_X = x - integer_X; + + var integer_Y = Math.floor( y ); + var fractional_Y = y - integer_Y; + + var v1 = SmoothedNoise( integer_X, integer_Y ), + v2 = SmoothedNoise( integer_X + 1, integer_Y ), + v3 = SmoothedNoise( integer_X, integer_Y + 1 ), + v4 = SmoothedNoise( integer_X + 1, integer_Y + 1 ); + + var i1 = Interpolate( v1, v2, fractional_X ), + i2 = Interpolate( v3, v4, fractional_X ); + + return Interpolate( i1, i2, fractional_Y ); + + } + + + function PerlinNoise_2D( x, y ){ + + var total = 0, + p = 0.25, + n = 3; + + for( var i = 0; i <= n; i++ ){ + var frequency = Math.pow( 2, i ); + var amplitude = Math.pow( p, i ); + total += InterpolatedNoise( x * frequency, y * frequency ) * amplitude; + } + + return total; + } + + function Interpolate( a, b, x ){ + var ft = x * p.PI; + var f = (1 - Math.cos( ft ) ) * .5; + return a * ( 1 - f ) + b * f; + } + + p.constrain = function constrain( aNumber, aMin, aMax ){ + return Math.min( Math.max( aNumber, aMin ), aMax ); + }; + + p.degrees = function degrees( aAngle ){ + aAngle = ( aAngle * 180 ) / p.PI; + if (aAngle < 0) {aAngle = 360 + aAngle} + return aAngle; + }; + + p.size = function size( aWidth, aHeight ){ + var fillStyle = curContext.fillStyle, + strokeStyle = curContext.strokeStyle; + + curElement.width = p.width = aWidth; + curElement.height = p.height = aHeight; + + curContext.fillStyle = fillStyle; + curContext.strokeStyle = strokeStyle; + }; + + + + //////////////////////////////////////////////////////////////////////////// + // Style functions + //////////////////////////////////////////////////////////////////////////// + + p.noStroke = function noStroke() { doStroke = false; }; + p.noFill = function noFill() { doFill = false; }; + p.smooth = function smooth() {}; + p.noSmooth = function noSmooth() {}; + + p.fill = function fill(){ + doFill = true; + curContext.fillStyle = p.color.apply( this, arguments ); + }; + + p.stroke = function stroke(){ + doStroke = true; + curContext.strokeStyle = p.color.apply( this, arguments ); + }; + + p.strokeWeight = function strokeWeight( w ){ + curContext.lineWidth = w; + }; + + + + //////////////////////////////////////////////////////////////////////////// + // Vector drawing functions + //////////////////////////////////////////////////////////////////////////// + + p.Point = function Point( x, y ){ + this.x = x; + this.y = y; + this.copy = function(){ + return new Point( x, y ); + } + }; + + p.point = function point( x, y ){ + var oldFill = curContext.fillStyle; + curContext.fillStyle = curContext.strokeStyle; + curContext.fillRect( Math.round( x ), Math.round( y ), 1, 1 ); + curContext.fillStyle = oldFill; + }; + + p.beginShape = function beginShape( type ){ + curShape = type; + curShapeCount = 0; + curvePoints = []; + }; + + p.endShape = function endShape( close ){ + + if( curShapeCount != 0 ){ + + if( close || doFill ){ curContext.lineTo( firstX, firstY ); } + if( doFill ){ curContext.fill(); } + if( doStroke ){ curContext.stroke(); } + + curContext.closePath(); + curShapeCount = 0; + pathOpen = false; + + } + + if( pathOpen ){ + + if ( doFill ){ curContext.fill(); } + if ( doStroke ){ curContext.stroke(); } + + curContext.closePath(); + curShapeCount = 0; + pathOpen = false; + + } + + }; + + p.vertex = function vertex( x, y, x2, y2, x3, y3 ){ + + if( curShapeCount == 0 && curShape != p.POINTS ){ + + pathOpen = true; + curContext.beginPath(); + curContext.moveTo( x, y ); + firstX = x; + firstY = y; + + }else{ + + if( curShape == p.POINTS ){ + + p.point( x, y ); + + }else if( arguments.length == 2 ){ + + if( curShape != p.QUAD_STRIP || curShapeCount != 2 ){ + + curContext.lineTo( x, y ); + + } + + if( curShape == p.TRIANGLE_STRIP ){ + + if( curShapeCount == 2 ){ + + // finish shape + p.endShape( p.CLOSE ); + pathOpen = true; + curContext.beginPath(); + + // redraw last line to start next shape + curContext.moveTo( prevX, prevY ); + curContext.lineTo( x, y ); + curShapeCount = 1; + + } + + firstX = prevX; + firstY = prevY; + + } + + if( curShape == p.TRIANGLE_FAN && curShapeCount == 2 ){ + + // finish shape + p.endShape( p.CLOSE) ; + pathOpen = true; + curContext.beginPath(); + + // redraw last line to start next shape + curContext.moveTo( firstX, firstY ); + curContext.lineTo( x, y ); + curShapeCount = 1; + + } + + if( curShape == p.QUAD_STRIP && curShapeCount == 3 ){ + + // finish shape + curContext.lineTo( prevX, prevY ); + p.endShape(p.CLOSE); + pathOpen = true; + curContext.beginPath(); + + // redraw lines to start next shape + curContext.moveTo( prevX, prevY ); + curContext.lineTo( x, y ); + curShapeCount = 1; + + } + + if( curShape == p.QUAD_STRIP ){ + + firstX = secondX; + firstY = secondY; + secondX = prevX; + secondY = prevY; + + } + + }else if( arguments.length == 4 ){ + + if( curShapeCount > 1 ){ + + curContext.moveTo( prevX, prevY ); + curContext.quadraticCurveTo( firstX, firstY, x, y ); + curShapeCount = 1; + + } + + }else if( arguments.length == 6 ){ + + curContext.bezierCurveTo( x, y, x2, y2, x3, y3 ); + + } + } + + prevX = x; + prevY = y; + curShapeCount ++; + + if( curShape == p.LINES && curShapeCount == 2 || + ( curShape == p.TRIANGLES ) && curShapeCount == 3 || + ( curShape == p.QUADS ) && curShapeCount == 4 + ){ + p.endShape( p.CLOSE ); + } + + }; + + p.curveVertex = function( x, y, x2, y2 ){ + + if( curvePoints.length < 3 ){ + + curvePoints.push( [ x, y ] ); + + }else{ + + var b = [], s = 1 - curTightness; + + /* + * Matrix to convert from Catmull-Rom to cubic Bezier + * where t = curTightness + * |0 1 0 0 | + * |(t-1)/6 1 (1-t)/6 0 | + * |0 (1-t)/6 1 (t-1)/6 | + * |0 0 0 0 | + */ + + curvePoints.push( [ x, y ] ); + + b[ 0 ] = [ curvePoints[ 1 ][ 0 ], curvePoints[ 1 ][ 1 ] ]; + b[ 1 ] = [ curvePoints[ 1 ][ 0 ] + ( s * curvePoints[ 2 ][ 0 ] - s * curvePoints[ 0 ][ 0 ] ) / 6, curvePoints[ 1 ][ 1 ] + ( s * curvePoints[ 2 ][ 1 ] - s * curvePoints[ 0 ][ 1 ] ) / 6 ]; + b[ 2 ] = [ curvePoints[ 2 ][ 0 ] + ( s * curvePoints[ 1 ][ 0 ] - s * curvePoints[ 3 ][ 0 ] ) / 6, curvePoints[ 2 ][ 1 ] + ( s * curvePoints[ 1 ][ 1 ] - s * curvePoints[ 3 ][ 1 ] ) / 6 ]; + b[ 3 ] = [ curvePoints[ 2 ][ 0 ], curvePoints[ 2 ][ 1 ] ]; + + if( !pathOpen ){ + p.vertex( b[ 0 ][ 0 ], b[ 0 ][ 1 ] ); + }else{ + curShapeCount = 1; + } + + p.vertex( + b[ 1 ][ 0 ], + b[ 1 ][ 1 ], + b[ 2 ][ 0 ], + b[ 2 ][ 1 ], + b[ 3 ][ 0 ], + b[ 3 ][ 1 ] + ); + + curvePoints.shift(); + } + + }; + + p.curveTightness = function( tightness ){ curTightness = tightness; }; + + p.bezierVertex = p.vertex; + + p.rectMode = function rectMode( aRectMode ){ curRectMode = aRectMode; }; + p.imageMode = function (){}; + p.ellipseMode = function ellipseMode( aEllipseMode ) { curEllipseMode = aEllipseMode; }; + + p.arc = function arc( x, y, width, height, start, stop ){ + + if( width <= 0 ){ return; } + + if( curEllipseMode == p.CORNER ){ + x += width / 2; + y += height / 2; + } + + curContext.moveTo( x, y ); + curContext.beginPath(); + curContext.arc( x, y, curEllipseMode == p.CENTER_RADIUS ? width : width/2, start, stop, false ); + + if( doStroke ){ curContext.stroke(); } + curContext.lineTo( x, y ); + + if( doFill ){ curContext.fill(); } + curContext.closePath(); + + }; + + p.line = function line( x1, y1, x2, y2 ){ + curContext.lineCap = "round"; + curContext.beginPath(); + curContext.moveTo( x1 || 0, y1 || 0 ); + curContext.lineTo( x2 || 0, y2 || 0 ); + curContext.stroke(); + curContext.closePath(); + }; + + p.bezier = function bezier( x1, y1, x2, y2, x3, y3, x4, y4 ){ + curContext.lineCap = "butt"; + curContext.beginPath(); + curContext.moveTo( x1, y1 ); + curContext.bezierCurveTo( x2, y2, x3, y3, x4, y4 ); + curContext.stroke(); + curContext.closePath(); + }; + + p.triangle = function triangle( x1, y1, x2, y2, x3, y3 ){ + p.beginShape(); + p.vertex( x1, y1 ); + p.vertex( x2, y2 ); + p.vertex( x3, y3 ); + p.endShape(); + }; + + p.quad = function quad( x1, y1, x2, y2, x3, y3, x4, y4 ){ + curContext.lineCap = "square"; + p.beginShape(); + p.vertex( x1, y1 ); + p.vertex( x2, y2 ); + p.vertex( x3, y3 ); + p.vertex( x4, y4 ); + p.endShape(); + }; + + p.rect = function rect( x, y, width, height ){ + + if( !( width + height ) ){ return; } + + curContext.beginPath(); + + var offsetStart = 0; + var offsetEnd = 0; + + if( curRectMode == p.CORNERS ){ + width -= x; + height -= y; + } + + if( curRectMode == p.RADIUS ){ + width *= 2; + height *= 2; + } + + if( curRectMode == p.CENTER || curRectMode == p.RADIUS ){ + x -= width / 2; + y -= height / 2; + } + + curContext.rect( + Math.round( x ) - offsetStart, + Math.round( y ) - offsetStart, + Math.round( width ) + offsetEnd, + Math.round( height ) + offsetEnd + ); + + if( doFill ){ curContext.fill(); } + if( doStroke ){ curContext.stroke() }; + + curContext.closePath(); + + }; + + p.ellipse = function ellipse( x, y, width, height ){ + + x = x || 0; + y = y || 0; + + if( width <= 0 && height <= 0 ){ return; } + + curContext.beginPath(); + + if( curEllipseMode == p.RADIUS ){ + width *= 2; + height *= 2; + } + + var offsetStart = 0; + + // Shortcut for drawing a circle + if( width == height ){ + + curContext.arc( x - offsetStart, y - offsetStart, width / 2, 0, p.TWO_PI, false ); + + }else{ + + var w = width/2, + h = height/2, + C = 0.5522847498307933; + var c_x = C * w, + c_y = C * h; + +//! Do we still need this? I hope the Canvas arc() more capable by now? + curContext.moveTo( x + w, y ); + curContext.bezierCurveTo( x+w , y-c_y , x+c_x , y-h , x , y-h ); + curContext.bezierCurveTo( x-c_x , y-h , x-w , y-c_y , x-w , y ); + curContext.bezierCurveTo( x-w , y+c_y , x-c_x , y+h, x, y+h ); + curContext.bezierCurveTo( x+c_x , y+h , x+w , y+c_y , x+w , y ); + + } + + if( doFill ){ curContext.fill(); } + if( doStroke ){ curContext.stroke(); } + + curContext.closePath(); + + }; + + + + //////////////////////////////////////////////////////////////////////////// + // Raster drawing functions + //////////////////////////////////////////////////////////////////////////// + + p.save = function save( file ){}; + + // Loads an image for display. Type is unused. Callback is fired on load. + p.loadImage = function loadImage( file, type, callback ){ + + var img = document.createElement( 'img' ); + img.src = file; + + img.onload = function(){ + + var h = this.height, + w = this.width; + + var canvas = document.createElement( "canvas" ); + canvas.width = w; + canvas.height = h; + var context = canvas.getContext( "2d" ); + + context.drawImage( this, 0, 0 ); + this.data = buildImageObject( context.getImageData( 0, 0, w, h ) ); + this.data.img = img; + + callback?callback():0; + + } + + return img; + + }; + + // Gets a single pixel or block of pixels from the current Canvas Context + p.get = function get( x, y ){ + + if( !arguments.length ){ + var c = p.createGraphics( p.width, p.height ); + c.image( curContext, 0, 0 ); + return c; + } + + if( !getLoaded ){ + getLoaded = buildImageObject( curContext.getImageData( 0, 0, p.width, p.height ) ); + } + + return getLoaded.get( x, y ); + + }; + + // Creates a new Processing instance and passes it back for... processing + p.createGraphics = function createGraphics( w, h ){ + + var canvas = document.createElement( "canvas" ); + var ret = buildProcessing( canvas ); + ret.size( w, h ); + ret.canvas = canvas; + return ret; + + }; + + // Paints a pixel array into the canvas + p.set = function set( x, y, obj ){ + + if( obj && obj.img ){ + + p.image( obj, x, y ); + + }else{ + + var oldFill = curContext.fillStyle, + color = obj; + + curContext.fillStyle = color; + curContext.fillRect( Math.round( x ), Math.round( y ), 1, 1 ); + curContext.fillStyle = oldFill; + + } + + }; + + // Gets a 1-Dimensional pixel array from Canvas + p.loadPixels = function(){ + p.pixels = buildImageObject( curContext.getImageData(0, 0, p.width, p.height) ).pixels; + }; + + // Draws a 1-Dimensional pixel array to Canvas + p.updatePixels = function() { + + var colors = /(\d+),(\d+),(\d+),(\d+)/, + pixels = {}; + + pixels.width = p.width; + pixels.height = p.height; + pixels.data = []; + + if( curContext.createImageData ){ + pixels = curContext.createImageData( p.width, p.height ); + } + + var data = pixels.data, + pos = 0; + + for( var i = 0, l = p.pixels.length; i < l; i++ ){ + + var c = ( p.pixels[i] || "rgba(0,0,0,1)" ).match( colors ); + + data[ pos + 0 ] = parseInt( c[ 1 ] ); + data[ pos + 1 ] = parseInt( c[ 2 ] ); + data[ pos + 2 ] = parseInt( c[ 3 ] ); + data[ pos + 3 ] = parseFloat( c[ 4 ] ) * 255; + + pos += 4; + + } + + curContext.putImageData( pixels, 0, 0 ); + + }; + + // Draw an image or a color to the background + p.background = function background( img ) { + + if( arguments.length ){ + + if( img.data && img.data.img ){ + curBackground = img.data; + }else{ + curBackground = p.color.apply( this, arguments ); + } + + } + + if( curBackground.img ){ + + p.image( img, 0, 0 ); + + }else{ + + var oldFill = curContext.fillStyle; + curContext.fillStyle = curBackground + ""; + curContext.fillRect( 0, 0, p.width, p.height ); + curContext.fillStyle = oldFill; + + } + + }; + + p.AniSprite = function( prefix, frames ){ + this.images = []; + this.pos = 0; + + for( var i = 0; i < frames; i++ ){ + this.images.push( prefix + p.nf( i, ( "" + frames ).length ) + ".gif" ); + } + + this.display = function( x, y ){ + p.image_old( this.images[ this.pos ], x, y ); + + if( ++this.pos >= frames ){ + this.pos = 0; + } + }; + + this.getWidth = function(){ return getImage_old( this.images[ 0 ] ).width; }; + this.getHeight = function(){ return getImage_old( this.images[ 0 ] ).height; }; + }; + + function buildImageObject( obj ){ + + var pixels = obj.data; + var data = p.createImage( obj.width, obj.height ); + + if( data.__defineGetter__ && data.__lookupGetter__ && !data.__lookupGetter__( "pixels" ) ){ + + var pixelsDone; + + data.__defineGetter__( "pixels", function(){ + + if( pixelsDone ){ + return pixelsDone; + } + pixelsDone = []; + + for( var i = 0; i < pixels.length; i += 4 ){ + pixelsDone.push( + p.color( + pixels[ i ], + pixels[ i + 1 ], + pixels[ i + 2 ], + pixels[ i + 3 ]) + ); + } + + return pixelsDone; + + }); + + }else{ + + data.pixels = []; + + for ( var i = 0; i < pixels.length; i += 4 ){ + data.pixels.push( p.color( + pixels[ i ], + pixels[ i + 1 ], + pixels[ i + 2 ], + pixels[ i + 3 ] + )); + } + + } + + return data; + } + + p.createImage = function createImage( w, h, mode ){ + + var data = {}; + data.width = w; + data.height = h; + data.data = []; + + if( curContext.createImageData ) { + data = curContext.createImageData( w, h ); + } + + data.pixels = new Array( w * h ); + + data.get = function( x, y ){ + return this.pixels[ w * y + x ]; + }; + + data._mask = null; + + data.mask = function( img ){ + this._mask = img; + }; + + data.loadPixels = function(){}; + data.updatePixels = function(){}; + + return data; + + }; + + function getImage( img ){ + + if( typeof img == "string" ){ + return document.getElementById( img ); + } + + if( img.img ){ + + return img.img; + + }else if( img.getContext || img.canvas ){ + + img.pixels = img.getContext( '2d' ).createImageData( img.width, img.height ); + } + + for( var i = 0, l = img.pixels.length; i < l; i++ ){ + + var pos = i * 4; + var c = ( img.pixels[ i ] || "rgba(0,0,0,1)" ).slice( 5, - 1 ).split( "," ); + + img.data[ pos + 0 ] = parseInt( c[ 0 ] ); + img.data[ pos + 1 ] = parseInt( c[ 1 ] ); + img.data[ pos + 2 ] = parseInt( c[ 2 ] ); + img.data[ pos + 3 ] = parseFloat( c[ 3 ] ) * 100; + + } + + var canvas = document.createElement( "canvas" ); + canvas.width = img.width; + canvas.height = img.height; + + var context = canvas.getContext( "2d" ); + context.putImageData( img.pixels, 0, 0 ); + + img.canvas = canvas; + + return img; + } + + // Depreciating "getImage_old" from PJS - currently here to support AniSprite + function getImage_old( img ){ + if( typeof img == "string" ){ + return document.getElementById( img ); + } + if( img.img || img.canvas ){ + return img.img || img.canvas; + } + for( var i = 0, l = img.pixels.length; i < l; i++ ){ + var pos = i * 4; + var c = ( img.pixels[ i ] || "rgba(0,0,0,1)" ).slice( 5, - 1 ).split( "," ); + img.data[ pos + 0 ] = parseInt( c[ 0 ] ); + img.data[ pos + 1 ] = parseInt( c[ 1 ] ); + img.data[ pos + 2 ] = parseInt( c[ 2 ] ); + img.data[ pos + 3 ] = parseFloat( c[ 3 ] ) * 100; + } + var canvas = document.createElement( "canvas" ); + canvas.width = img.width; + canvas.height = img.height; + var context = canvas.getContext( "2d" ); + context.putImageData( img, 0, 0 ); + img.canvas = canvas; + return canvas; + } + // Depreciating "getImage_old" from PJS - currently here to support AniSprite + p.image_old=function image_old(img,x,y,w,h){ + x = x || 0; + y = y || 0; + var obj = getImage( img ); + if( curTint >= 0 ){ + var oldAlpha = curContext.globalAlpha; + curContext.globalAlpha = curTint / opacityRange; + } + if( arguments.length == 3 ){ + curContext.drawImage( obj, x, y ); + }else{ + curContext.drawImage( obj, x, y, w, h ); + } + if( curTint >= 0 ){ + curContext.globalAlpha = oldAlpha; + } + if( img._mask ){ + var oldComposite = curContext.globalCompositeOperation; + curContext.globalCompositeOperation = "darker"; + p.image( img._mask, x, y ); + curContext.globalCompositeOperation = oldComposite; + } + }; + + // Draws an image to the Canvas + p.image = function image( img, x, y, w, h ){ + + if( img.data || img.canvas ){ + + x = x || 0; + y = y || 0; + + var obj = getImage( img.data || img.canvas ); + + if( curTint >= 0 ){ + var oldAlpha = curContext.globalAlpha; + curContext.globalAlpha = curTint / opacityRange; + } + + if( arguments.length == 3 ){ + curContext.drawImage( obj, x, y ); + }else{ + curContext.drawImage( obj, x, y, w, h ); + } + + if( curTint >= 0 ){ + curContext.globalAlpha = oldAlpha; + } + + if( img._mask ){ + var oldComposite = curContext.globalCompositeOperation; + curContext.globalCompositeOperation = "darker"; + p.image( img._mask, x, y ); + curContext.globalCompositeOperation = oldComposite; + } + + } + + if( typeof img == 'string' ){ + + } + + }; + + // Clears hole in the Canvas or the whole Canvas + p.clear = function clear ( x, y, width, height ) { + if( arguments.length == 0 ){ + curContext.clearRect( x, y, width, height ); + }else{ + curContext.clearRect( 0, 0, p.width, p.height ); + } + } + + p.tint = function tint( rgb, a ){ + curTint = a; + }; + + + + //////////////////////////////////////////////////////////////////////////// + // Font handling + //////////////////////////////////////////////////////////////////////////// + + // Loads a font from an SVG or Canvas API + p.loadFont = function loadFont( name ){ + + if( name.indexOf( ".svg" ) == - 1 ){ + + return { + name: name, + width: function( str ){ + if( curContext.mozMeasureText ){ + return curContext.mozMeasureText( + typeof str == "number" ? + String.fromCharCode( str ) : + str + ) / curTextSize; + }else{ + return 0; + } + } + }; + + }else{ + + // If the font is a glyph, calculate by SVG table + var font = p.loadGlyphs( name ); + + return { + name : name, + 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 ){ ; } + } + return width / p.glyphTable[ name ].units_per_em; + } + } + + } + + }; + + // Sets a 'current font' for use + p.textFont = function textFont( name, size ){ + curTextFont = name; + p.textSize( size ); + }; + + // Sets the font size + p.textSize = function textSize( size ){ +//! Was this meant to return textSize value if no arguments were passed? + if( size ){ + curTextSize = size; + } + }; + + p.textAlign = function textAlign(){}; + + // A lookup table for characters that can not be referenced by Object + p.glyphLook = function glyphLook( font, chr ){ + + try{ + switch( chr ){ + case "1" : return font[ "one" ]; break; + case "2" : return font[ "two" ]; break; + case "3" : return font[ "three" ]; break; + case "4" : return font[ "four" ]; break; + case "5" : return font[ "five" ]; break; + case "6" : return font[ "six" ]; break; + case "7" : return font[ "seven" ]; break; + case "8" : return font[ "eight" ]; break; + case "9" : return font[ "nine" ]; break; + case "0" : return font[ "zero" ]; break; + case " " : return font[ "space" ]; break; + case "$" : return font[ "dollar" ]; break; + case "!" : return font[ "exclam" ]; break; + case '"' : return font[ "quotedbl" ]; break; + case "#" : return font[ "numbersign" ]; break; + case "%" : return font[ "percent" ]; break; + case "&" : return font[ "ampersand" ]; break; + case "'" : return font[ "quotesingle" ]; break; + case "(" : return font[ "parenleft" ]; break; + case ")" : return font[ "parenright" ]; break; + case "*" : return font[ "asterisk" ]; break; + case "+" : return font[ "plus" ]; break; + case "," : return font[ "comma" ]; break; + case "-" : return font[ "hyphen" ]; break; + case "." : return font[ "period" ]; break; + case "/" : return font[ "slash" ]; break; + case "_" : return font[ "underscore" ]; break; + case ":" : return font[ "colon" ]; break; + case ";" : return font[ "semicolon" ]; break; + case "<" : return font[ "less" ]; break; + case "=" : return font[ "equal" ]; break; + case ">" : return font[ "greater" ]; break; + case "?" : return font[ "question" ]; break; + case "@" : return font[ "at" ]; break; + case "[" : return font[ "bracketleft" ]; break; + case "\\" : return font[ "backslash" ]; break; + case "]" : return font[ "bracketright" ]; break; + case "^" : return font[ "asciicircum" ]; break; + case "`" : return font[ "grave" ]; break; + case "{" : return font[ "braceleft" ]; break; + case "|" : return font[ "bar" ]; break; + case "}" : return font[ "braceright" ]; break; + case "~" : return font[ "asciitilde" ]; break; + // If the character is not 'special', access it by object reference + default : return font[ chr ]; break; + } + }catch( e ){ ; } + + } + + // Print some text to the Canvas + p.text = function text( str, x, y ){ + + // If the font is a standard Canvas font... + if( !curTextFont.glyph ){ + + if( str && curContext.mozDrawText ){ + + curContext.save(); + curContext.mozTextStyle = curTextSize + "px " + curTextFont.name; + curContext.translate( x, y ); + curContext.mozDrawText( + typeof str == "number" ? + String.fromCharCode( str ) : + str ) ; + curContext.restore(); + + } + + }else{ + + // If the font is a Batik SVG font... + var font = p.glyphTable[ curTextFont.name ]; + curContext.save(); + curContext.translate( x, y + curTextSize ); + + var upem = font[ "units_per_em" ], + newScale = 1 / upem * curTextSize; + + curContext.scale( newScale, newScale ); + + var len = str.length; + + for(var i = 0; i < len; i++ ){ + // Test character against glyph table + try{ p.glyphLook( font, str[ i ] ).draw(); } + catch( e ){ ; } + } + + curContext.restore(); + } + + }; + + // Load Batik SVG Fonts and parse to pre-def objects for quick rendering + p.loadGlyphs = function loadGlyph( url ){ + + // Load and parse Batik SVG font as XML into a Processing Glyph object + var loadXML = function loadXML(){ + + try{ + var xmlDoc = new ActiveXObject( "Microsoft.XMLDOM" ); + } + catch( e ){ + try{ + xmlDoc=document.implementation.createDocument( "", "", null ); + } + catch( e ){ + p.println( e.message ); + return; + } + }; + + try{ + xmlDoc.async = false; + xmlDoc.load( url ); + parse( xmlDoc.getElementsByTagName( "svg" )[ 0 ] ); + } + catch( e ){ + // Google Chrome, Safari etc. + try{ + p.println( e.message ); + var xmlhttp = new window.XMLHttpRequest(); + xmlhttp.open( "GET", url, false ); + xmlhttp.send( null ); + parse( xmlhttp.responseXML.documentElement ); + } + catch( e ){ ; } + } + }; + + // Return arrays of SVG commands and coords + var regex = function regex( needle, hay ){ + + var regexp = new RegExp( needle, "g" ), + results = [], + i = 0; + + while( results[ i ] = regexp.exec( hay ) ){ i++; } + return results; + + } + + // Parse SVG font-file into block of Canvas commands + var parse = function parse( svg ){ + + // Store font attributes + 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 getXY = "[0-9\-]+", + glyph = svg.getElementsByTagName( "glyph" ), + len = glyph.length; + + // Loop through each glyph in the SVG + for( var i = 0; i < len; i++ ){ + + // Store attributes for this glyph + var unicode = glyph[ i ].getAttribute( "unicode" ); + var name = glyph[ i ].getAttribute( "glyph-name" ); + var horiz_adv_x = glyph[ i ].getAttribute( "horiz-adv-x" ); + if( horiz_adv_x == null ){ var horiz_adv_x = p.glyphTable[ url ][ 'horiz_adv_x' ]; } + + var buildPath = function buildPath( d ){ + + var c = regex( "[A-Za-z][0-9\- ]+|Z", d ); + + // Begin storing path object + var path = "var path={draw:function(){curContext.beginPath();curContext.save();"; + + var x = 0, + y = 0, + cx = 0, + cy = 0, + nx = 0, + ny = 0, + d = 0, + a = 0, + lastCom = "", + lenC = c.length - 1; + + // Loop through SVG commands translating to canvas eqivs functions in path object + for( var j = 0; j < lenC; j++ ){ + + var com = c[ j ][ 0 ], + xy = regex( getXY, com ); + + switch( com[ 0 ] ){ + + case "M": //curContext.moveTo(x,-y); + x = parseFloat( xy[ 0 ][ 0 ] ); + y = parseFloat( xy[ 1 ][ 0 ] ); +//! Brackets needed on (-y)? + path += "curContext.moveTo("+ x +","+ (-y) +");"; + break; + + case "L": //curContext.lineTo(x,-y); + x = parseFloat( xy[ 0 ][ 0 ] ); + y = parseFloat( xy[ 1 ][ 0 ] ); + path += "curContext.lineTo("+ x +","+ (-y) +");"; + break; + + case "H"://curContext.lineTo(x,-y) + x = parseFloat( xy[ 0 ][ 0 ] ); + path += "curContext.lineTo("+ x +","+ (-y) +");"; + break; + + case "V"://curContext.lineTo(x,-y); + y = parseFloat( xy[ 0 ][ 0 ] ); + path += "curContext.lineTo("+ x +","+ (-y) +");"; + break; + + case "T"://curContext.quadraticCurveTo(cx,-cy,nx,-ny); + 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"://curContext.quadraticCurveTo(cx,-cy,nx,-ny); + 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"://curContext.closePath(); + path += "curContext.closePath();"; + break; + + } + + lastCom = com[ 0 ]; + + } + + path += "doStroke?curContext.stroke():0;"; + path += "doFill?curContext.fill():0;"; + path += "curContext.restore();"; + path += "curContext.translate("+ horiz_adv_x +",0);"; + path += "}}"; + + return path; + + } + + var d = glyph[ i ].getAttribute( "d" ); + + // Split path commands in glpyh + if( d !== undefined ){ + + var path = buildPath( d ); + eval( path ); + + // Store glyph data to table object + p.glyphTable[ url ][ name ] = { + name : name, + unicode : unicode, + horiz_adv_x : horiz_adv_x, + draw : path.draw + } + + } + + } // finished adding glyphs to table + + } + + // Create a new object in glyphTable to store this font + p.glyphTable[ url ] = {}; + + // Begin loading the Batik SVG font... + loadXML( url ); + + // Return the loaded font for attribute grabbing + return p.glyphTable[ url ]; + } + + + + //////////////////////////////////////////////////////////////////////////// + // Class methods + //////////////////////////////////////////////////////////////////////////// + + p.extendClass = function extendClass( obj, args, fn ){ + if( arguments.length == 3 ){ + fn.apply( obj, args ); + }else{ + args.call( obj ); + } + }; + + p.addMethod = function addMethod( object, name, fn ){ + + if( object[ name ] ){ + + var args = fn.length, + oldfn = object[ name ]; + + object[ name ] = function(){ + + if( arguments.length == args ){ + + return fn.apply( this, arguments ); + + }else{ + + return oldfn.apply( this, arguments ); + + } + + }; + + }else{ + + object[ name ] = fn; + + } + + }; + + + + //////////////////////////////////////////////////////////////////////////// + // Set up environment + //////////////////////////////////////////////////////////////////////////// + + p.init = function init(code){ + + p.stroke( 0 ); + p.fill( 255 ); + + // Canvas has trouble rendering single pixel stuff on whole-pixel + // counts, so we slightly offset it (this is super lame). + + curContext.translate( 0.5, 0.5 ); + + // The fun bit! + if( code ){ + (function( Processing ){ + with ( p ){ + eval(parse(code, p)); + } + })( p ); + } + + if( p.setup ){ + inSetup = true; + p.setup(); + } + + inSetup = false; + + if( p.draw ){ + if( !doLoop ){ + p.redraw(); + } else { + p.loop(); + } + } + + + ////////////////////////////////////////////////////////////////////////// + // Event handling + ////////////////////////////////////////////////////////////////////////// + + attach( curElement, "mousemove" , function(e){ + + var scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset; + var scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset; + + p.pmouseX = p.mouseX; + p.pmouseY = p.mouseY; + p.mouseX = e.clientX - curElement.offsetLeft + scrollX; + p.mouseY = e.clientY - curElement.offsetTop + scrollY; + + if( p.mouseMoved ){ p.mouseMoved(); } + if( mousePressed && p.mouseDragged ){ p.mouseDragged(); } + + }); + + attach( curElement, "mouseout" , function( e ){ p.cursor("auto"); }); + + attach( curElement, "mousedown", function( e ){ + mousePressed = true; + switch(e.which){ + case 1: p.mouseButton = p.LEFT; break; + case 2: p.mouseButton = p.CENTER; break; + case 3: p.mouseButton = p.RIGHT; break; + } + p.mouseDown = true; + if( typeof p.mousePressed == "function" ){ p.mousePressed(); } + else{ p.mousePressed = true; } + }); + + attach( curElement, "contextmenu", function( e ){ + e.preventDefault(); + e.stopPropagation(); + }); + + attach( curElement, "mouseup", function( e ){ + mousePressed = false; + if( p.mouseClicked ){ p.mouseClicked(); } + if( typeof p.mousePressed != "function" ){ p.mousePressed = false; } + if( p.mouseReleased ){ p.mouseReleased(); } + }); + + attach( document, "keydown", function( e ){ + keyPressed = true; + p.key = e.keyCode + 32; + var i, len = p.codedKeys.length; + for( i=0; i < len; i++ ){ + if( p.key == p.codedKeys[ i ] ){ + switch(p.key){ + case 70: p.keyCode = p.UP ; break; + case 71: p.keyCode = p.RIGHT ; break; + case 72: p.keyCode = p.DOWN ; break; + case 69: p.keyCode = p.LEFT ; break; + } + p.key=p.CODED; + } + } + if( e.shiftKey ){ p.key = String.fromCharCode(p.key).toUpperCase().charCodeAt( 0 ); } + if( typeof p.keyPressed == "function" ){ p.keyPressed(); } + else{ p.keyPressed = true; } + }); + + attach( document, "keyup", function( e ){ + keyPressed = false; + if( typeof p.keyPressed != "function" ){ p.keyPressed = false; } + if( p.keyReleased ){ p.keyReleased(); } + }); + + function attach(elem, type, fn) { + if( elem.addEventListener ){ elem.addEventListener( type, fn, false ); } + else{ elem.attachEvent( "on" + type, fn ); } + } + + }; + + return p; + + } + +})(); diff --git a/sagenb/data/graph_editor/processing.min.js b/sagenb/data/graph_editor/processing.min.js new file mode 100644 --- /dev/null +++ b/sagenb/data/graph_editor/processing.min.js @@ -0,0 +1,131 @@ +(function(){this.Processing=function Processing(aElement,aCode){if(typeof aElement=="string"){aElement=document.getElementById(aElement);} +var p=buildProcessing(aElement);if(aCode){p.init(aCode);} +return p;};var ajax=function(url){var AJAX;if(AJAX=new XMLHttpRequest()){AJAX.open("GET",url,false);AJAX.send(null);return AJAX.responseText;}else{return false;}};var init=function(){var canvas=document.getElementsByTagName('canvas'),datasrc=undefined;for(var i=0;l=i"+(typeof last=="string"?last:name+"(");} +var matchClasses=/(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?{\s*((?:.|\n)*?)\b\1\s*\(/g;var matchNoCon=/(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?{\s*((?:.|\n)*?)(Processing)/g;aCode=aCode.replace(matchClasses,ClassReplace);aCode=aCode.replace(matchNoCon,ClassReplace);var matchClass=//,m;while((m=aCode.match(matchClass))){var left=RegExp.leftContext,allRest=RegExp.rightContext,rest=nextBrace(allRest),className=m[1],staticVars=m[2]||"";allRest=allRest.slice(rest.length+1);rest=rest.replace(new RegExp("\\b"+className+"\\(([^\\)]*?)\\)\\s*{","g"),function(all,args){args=args.split(/,\s*?/);if(args[0].match(/^\s*$/)){args.shift();} +var fn="if ( arguments.length == "+args.length+" ) {\n";for(var i=0;i=4){redRange=range1;greenRange=range2;blueRange=range3;} +if(arguments.length==5){opacityRange=range4;} +if(arguments.length==2){p.colorMode(mode,range1,range1,range1,range1);}};p.translate=function translate(x,y){curContext.translate(x,y);};p.scale=function scale(x,y){curContext.scale(x,y||x);};p.rotate=function rotate(aAngle){curContext.rotate(aAngle);};p.pushMatrix=function pushMatrix(){curContext.save();};p.popMatrix=function popMatrix(){curContext.restore();};p.ortho=function ortho(){};p.year=function year(){return(new Date).getYear()+1900;};p.month=function month(){return(new Date).getMonth();};p.day=function day(){return(new Date).getDay();};p.hour=function hour(){return(new Date).getHours();};p.minute=function minute(){return(new Date).getMinutes();};p.second=function second(){return(new Date).getSeconds();};p.millis=function millis(){return(new Date).getTime()-start;};p.noLoop=function noLoop(){doLoop=false;};p.redraw=function redraw(){if(hasBackground){p.background();} +p.frameCount++;inDraw=true;p.pushMatrix();p.draw();p.popMatrix();inDraw=false;};p.loop=function loop(){if(loopStarted){return;} +looping=setInterval(function(){try{p.redraw();} +catch(e){clearInterval(looping);throw e;}},curMsPerFrame);loopStarted=true;};p.frameRate=function frameRate(aRate){curFrameRate=aRate;curMsPerFrame=1000/curFrameRate;};p.exit=function exit(){clearInterval(looping);};p.cursor=function(mode){document.body.style.cursor=mode;} +p.link=function(href,target){window.location=href;};p.beginDraw=function beginDraw(){};p.endDraw=function endDraw(){};p.ajax=ajax;p.Import=function Import(lib){eval(p.ajax(lib));} +p.loadStrings=function loadStrings(url){return p.ajax(url).split("\n");};p.nf=function(num,pad){var str=""+num;while(pad-str.length){str="0"+str;} +return str;};String.prototype.replaceAll=function(re,replace){return this.replace(new RegExp(re,"g"),replace);};p.lnPrinted=function lnPrinted(){};p.printed=function printed(){};p.println=function println(){if(arguments.callee.caller){var Caller=arguments.callee.caller.name.toString();if(arguments.length>1){Caller!="print"?p.ln=arguments:p.ln=arguments[0];}else{p.ln=arguments[0];} +Caller=="print"?p.printed(arguments):p.lnPrinted();}};p.str=function str(aNumber){return aNumber+'';} +p.print=function print(){p.println(arguments[0])};p.char=function char(key){return key;};p.sq=function sq(aNumber){return aNumber*aNumber;};p.sqrt=function sqrt(aNumber){return Math.sqrt(aNumber);};p.int=function int(aNumber){return Math.floor(aNumber);};p.min=function min(aNumber,aNumber2){return Math.min(aNumber,aNumber2);};p.max=function max(aNumber,aNumber2){return Math.max(aNumber,aNumber2);};p.floor=function floor(aNumber){return Math.floor(aNumber);};p.float=function float(aNumber){return parseFloat(aNumber);};p.ceil=function ceil(aNumber){return Math.ceil(aNumber);};p.round=function round(aNumber){return Math.round(aNumber);};p.lerp=function lerp(value1,value2,amt){return((value2-value1)*amt)+value1;};p.abs=function abs(aNumber){return Math.abs(aNumber);};p.cos=function cos(aNumber){return Math.cos(aNumber);};p.sin=function sin(aNumber){return Math.sin(aNumber);};p.pow=function pow(aNumber,aExponent){return Math.pow(aNumber,aExponent);};p.sqrt=function sqrt(aNumber){return Math.sqrt(aNumber);};p.atan2=function atan2(aNumber,aNumber2){return Math.atan2(aNumber,aNumber2);};p.radians=function radians(aAngle){return(aAngle/180)*p.PI;};p.dist=function dist(x1,y1,x2,y2){return Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));};p.map=function map(value,istart,istop,ostart,ostop){return ostart+(ostop-ostart)*((value-istart)/(istop-istart));};p.Random=function(){var haveNextNextGaussian=false,nextNextGaussian;this.nextGaussian=function(){if(haveNextNextGaussian){haveNextNextGaussian=false;return nextNextGaussian;}else{var v1,v2,s;do{v1=2*p.random(1)-1;v2=2*p.random(1)-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;}};};p.byte=function byte(aNumber){return aNumber||0;};p.norm=function norm(aNumber,low,high){var range=high-low;return((1/range)*aNumber)-((1/range)*low);};p.random=function random(aMin,aMax){return arguments.length==2?aMin+(Math.random()*(aMax-aMin)):Math.random()*aMin;};p.noise=function(x,y,z){return arguments.length>=2?PerlinNoise_2D(x,y,z):PerlinNoise_3D(x,x,z);};function Noise(x,y){var n=x+y*57;n=(n<<13)^n;return Math.abs(1.0-(((n*((n*n*15731)+789221)+1376312589)&0x7fffffff)/1073741824.0));};function SmoothedNoise(x,y){var corners=(Noise(x-1,y-1)+Noise(x+1,y-1)+Noise(x-1,y+1)+Noise(x+1,y+1))/16,sides=(Noise(x-1,y)+Noise(x+1,y)+Noise(x,y-1)+Noise(x,y+1))/8,center=Noise(x,y)/4;return corners+sides+center;};function InterpolatedNoise(x,y){var integer_X=Math.floor(x);var fractional_X=x-integer_X;var integer_Y=Math.floor(y);var fractional_Y=y-integer_Y;var v1=SmoothedNoise(integer_X,integer_Y),v2=SmoothedNoise(integer_X+1,integer_Y),v3=SmoothedNoise(integer_X,integer_Y+1),v4=SmoothedNoise(integer_X+1,integer_Y+1);var i1=Interpolate(v1,v2,fractional_X),i2=Interpolate(v3,v4,fractional_X);return Interpolate(i1,i2,fractional_Y);} +function PerlinNoise_2D(x,y){var total=0,p=0.25,n=3;for(var i=0;i<=n;i++){var frequency=Math.pow(2,i);var amplitude=Math.pow(p,i);total+=InterpolatedNoise(x*frequency,y*frequency)*amplitude;} +return total;} +function Interpolate(a,b,x){var ft=x*p.PI;var f=(1-Math.cos(ft))*.5;return a*(1-f)+b*f;} +p.constrain=function constrain(aNumber,aMin,aMax){return Math.min(Math.max(aNumber,aMin),aMax);};p.degrees=function degrees(aAngle){aAngle=(aAngle*180)/p.PI;if(aAngle<0){aAngle=360+aAngle} +return aAngle;};p.size=function size(aWidth,aHeight){var fillStyle=curContext.fillStyle,strokeStyle=curContext.strokeStyle;curElement.width=p.width=aWidth;curElement.height=p.height=aHeight;curContext.fillStyle=fillStyle;curContext.strokeStyle=strokeStyle;};p.noStroke=function noStroke(){doStroke=false;};p.noFill=function noFill(){doFill=false;};p.smooth=function smooth(){};p.noSmooth=function noSmooth(){};p.fill=function fill(){doFill=true;curContext.fillStyle=p.color.apply(this,arguments);};p.stroke=function stroke(){doStroke=true;curContext.strokeStyle=p.color.apply(this,arguments);};p.strokeWeight=function strokeWeight(w){curContext.lineWidth=w;};p.Point=function Point(x,y){this.x=x;this.y=y;this.copy=function(){return new Point(x,y);}};p.point=function point(x,y){var oldFill=curContext.fillStyle;curContext.fillStyle=curContext.strokeStyle;curContext.fillRect(Math.round(x),Math.round(y),1,1);curContext.fillStyle=oldFill;};p.beginShape=function beginShape(type){curShape=type;curShapeCount=0;curvePoints=[];};p.endShape=function endShape(close){if(curShapeCount!=0){if(close||doFill){curContext.lineTo(firstX,firstY);} +if(doFill){curContext.fill();} +if(doStroke){curContext.stroke();} +curContext.closePath();curShapeCount=0;pathOpen=false;} +if(pathOpen){if(doFill){curContext.fill();} +if(doStroke){curContext.stroke();} +curContext.closePath();curShapeCount=0;pathOpen=false;}};p.vertex=function vertex(x,y,x2,y2,x3,y3){if(curShapeCount==0&&curShape!=p.POINTS){pathOpen=true;curContext.beginPath();curContext.moveTo(x,y);firstX=x;firstY=y;}else{if(curShape==p.POINTS){p.point(x,y);}else if(arguments.length==2){if(curShape!=p.QUAD_STRIP||curShapeCount!=2){curContext.lineTo(x,y);} +if(curShape==p.TRIANGLE_STRIP){if(curShapeCount==2){p.endShape(p.CLOSE);pathOpen=true;curContext.beginPath();curContext.moveTo(prevX,prevY);curContext.lineTo(x,y);curShapeCount=1;} +firstX=prevX;firstY=prevY;} +if(curShape==p.TRIANGLE_FAN&&curShapeCount==2){p.endShape(p.CLOSE);pathOpen=true;curContext.beginPath();curContext.moveTo(firstX,firstY);curContext.lineTo(x,y);curShapeCount=1;} +if(curShape==p.QUAD_STRIP&&curShapeCount==3){curContext.lineTo(prevX,prevY);p.endShape(p.CLOSE);pathOpen=true;curContext.beginPath();curContext.moveTo(prevX,prevY);curContext.lineTo(x,y);curShapeCount=1;} +if(curShape==p.QUAD_STRIP){firstX=secondX;firstY=secondY;secondX=prevX;secondY=prevY;}}else if(arguments.length==4){if(curShapeCount>1){curContext.moveTo(prevX,prevY);curContext.quadraticCurveTo(firstX,firstY,x,y);curShapeCount=1;}}else if(arguments.length==6){curContext.bezierCurveTo(x,y,x2,y2,x3,y3);}} +prevX=x;prevY=y;curShapeCount++;if(curShape==p.LINES&&curShapeCount==2||(curShape==p.TRIANGLES)&&curShapeCount==3||(curShape==p.QUADS)&&curShapeCount==4){p.endShape(p.CLOSE);}};p.curveVertex=function(x,y,x2,y2){if(curvePoints.length<3){curvePoints.push([x,y]);}else{var b=[],s=1-curTightness;curvePoints.push([x,y]);b[0]=[curvePoints[1][0],curvePoints[1][1]];b[1]=[curvePoints[1][0]+(s*curvePoints[2][0]-s*curvePoints[0][0])/6,curvePoints[1][1]+(s*curvePoints[2][1]-s*curvePoints[0][1])/6];b[2]=[curvePoints[2][0]+(s*curvePoints[1][0]-s*curvePoints[3][0])/6,curvePoints[2][1]+(s*curvePoints[1][1]-s*curvePoints[3][1])/6];b[3]=[curvePoints[2][0],curvePoints[2][1]];if(!pathOpen){p.vertex(b[0][0],b[0][1]);}else{curShapeCount=1;} +p.vertex(b[1][0],b[1][1],b[2][0],b[2][1],b[3][0],b[3][1]);curvePoints.shift();}};p.curveTightness=function(tightness){curTightness=tightness;};p.bezierVertex=p.vertex;p.rectMode=function rectMode(aRectMode){curRectMode=aRectMode;};p.imageMode=function(){};p.ellipseMode=function ellipseMode(aEllipseMode){curEllipseMode=aEllipseMode;};p.arc=function arc(x,y,width,height,start,stop){if(width<=0){return;} +if(curEllipseMode==p.CORNER){x+=width/2;y+=height/2;} +curContext.moveTo(x,y);curContext.beginPath();curContext.arc(x,y,curEllipseMode==p.CENTER_RADIUS?width:width/2,start,stop,false);if(doStroke){curContext.stroke();} +curContext.lineTo(x,y);if(doFill){curContext.fill();} +curContext.closePath();};p.line=function line(x1,y1,x2,y2){curContext.lineCap="round";curContext.beginPath();curContext.moveTo(x1||0,y1||0);curContext.lineTo(x2||0,y2||0);curContext.stroke();curContext.closePath();};p.bezier=function bezier(x1,y1,x2,y2,x3,y3,x4,y4){curContext.lineCap="butt";curContext.beginPath();curContext.moveTo(x1,y1);curContext.bezierCurveTo(x2,y2,x3,y3,x4,y4);curContext.stroke();curContext.closePath();};p.triangle=function triangle(x1,y1,x2,y2,x3,y3){p.beginShape();p.vertex(x1,y1);p.vertex(x2,y2);p.vertex(x3,y3);p.endShape();};p.quad=function quad(x1,y1,x2,y2,x3,y3,x4,y4){curContext.lineCap="square";p.beginShape();p.vertex(x1,y1);p.vertex(x2,y2);p.vertex(x3,y3);p.vertex(x4,y4);p.endShape();};p.rect=function rect(x,y,width,height){if(!(width+height)){return;} +curContext.beginPath();var offsetStart=0;var offsetEnd=0;if(curRectMode==p.CORNERS){width-=x;height-=y;} +if(curRectMode==p.RADIUS){width*=2;height*=2;} +if(curRectMode==p.CENTER||curRectMode==p.RADIUS){x-=width/2;y-=height/2;} +curContext.rect(Math.round(x)-offsetStart,Math.round(y)-offsetStart,Math.round(width)+offsetEnd,Math.round(height)+offsetEnd);if(doFill){curContext.fill();} +if(doStroke){curContext.stroke()};curContext.closePath();};p.ellipse=function ellipse(x,y,width,height){x=x||0;y=y||0;if(width<=0&&height<=0){return;} +curContext.beginPath();if(curEllipseMode==p.RADIUS){width*=2;height*=2;} +var offsetStart=0;if(width==height){curContext.arc(x-offsetStart,y-offsetStart,width/2,0,p.TWO_PI,false);}else{var w=width/2,h=height/2,C=0.5522847498307933;var c_x=C*w,c_y=C*h;curContext.moveTo(x+w,y);curContext.bezierCurveTo(x+w,y-c_y,x+c_x,y-h,x,y-h);curContext.bezierCurveTo(x-c_x,y-h,x-w,y-c_y,x-w,y);curContext.bezierCurveTo(x-w,y+c_y,x-c_x,y+h,x,y+h);curContext.bezierCurveTo(x+c_x,y+h,x+w,y+c_y,x+w,y);} +if(doFill){curContext.fill();} +if(doStroke){curContext.stroke();} +curContext.closePath();};p.save=function save(file){};p.loadImage=function loadImage(file,type,callback){var img=document.createElement('img');img.src=file;img.onload=function(){var h=this.height,w=this.width;var canvas=document.createElement("canvas");canvas.width=w;canvas.height=h;var context=canvas.getContext("2d");context.drawImage(this,0,0);this.data=buildImageObject(context.getImageData(0,0,w,h));this.data.img=img;callback?callback():0;} +return img;};p.get=function get(x,y){if(!arguments.length){var c=p.createGraphics(p.width,p.height);c.image(curContext,0,0);return c;} +if(!getLoaded){getLoaded=buildImageObject(curContext.getImageData(0,0,p.width,p.height));} +return getLoaded.get(x,y);};p.createGraphics=function createGraphics(w,h){var canvas=document.createElement("canvas");var ret=buildProcessing(canvas);ret.size(w,h);ret.canvas=canvas;return ret;};p.set=function set(x,y,obj){if(obj&&obj.img){p.image(obj,x,y);}else{var oldFill=curContext.fillStyle,color=obj;curContext.fillStyle=color;curContext.fillRect(Math.round(x),Math.round(y),1,1);curContext.fillStyle=oldFill;}};p.loadPixels=function(){p.pixels=buildImageObject(curContext.getImageData(0,0,p.width,p.height)).pixels;};p.updatePixels=function(){var colors=/(\d+),(\d+),(\d+),(\d+)/,pixels={};pixels.width=p.width;pixels.height=p.height;pixels.data=[];if(curContext.createImageData){pixels=curContext.createImageData(p.width,p.height);} +var data=pixels.data,pos=0;for(var i=0,l=p.pixels.length;i=frames){this.pos=0;}};this.getWidth=function(){return getImage_old(this.images[0]).width;};this.getHeight=function(){return getImage_old(this.images[0]).height;};};function buildImageObject(obj){var pixels=obj.data;var data=p.createImage(obj.width,obj.height);if(data.__defineGetter__&&data.__lookupGetter__&&!data.__lookupGetter__("pixels")){var pixelsDone;data.__defineGetter__("pixels",function(){if(pixelsDone){return pixelsDone;} +pixelsDone=[];for(var i=0;i=0){var oldAlpha=curContext.globalAlpha;curContext.globalAlpha=curTint/opacityRange;} +if(arguments.length==3){curContext.drawImage(obj,x,y);}else{curContext.drawImage(obj,x,y,w,h);} +if(curTint>=0){curContext.globalAlpha=oldAlpha;} +if(img._mask){var oldComposite=curContext.globalCompositeOperation;curContext.globalCompositeOperation="darker";p.image(img._mask,x,y);curContext.globalCompositeOperation=oldComposite;}};p.image=function image(img,x,y,w,h){if(img.data||img.canvas){x=x||0;y=y||0;var obj=getImage(img.data||img.canvas);if(curTint>=0){var oldAlpha=curContext.globalAlpha;curContext.globalAlpha=curTint/opacityRange;} +if(arguments.length==3){curContext.drawImage(obj,x,y);}else{curContext.drawImage(obj,x,y,w,h);} +if(curTint>=0){curContext.globalAlpha=oldAlpha;} +if(img._mask){var oldComposite=curContext.globalCompositeOperation;curContext.globalCompositeOperation="darker";p.image(img._mask,x,y);curContext.globalCompositeOperation=oldComposite;}} +if(typeof img=='string'){}};p.clear=function clear(x,y,width,height){if(arguments.length==0){curContext.clearRect(x,y,width,height);}else{curContext.clearRect(0,0,p.width,p.height);}} +p.tint=function tint(rgb,a){curTint=a;};p.loadFont=function loadFont(name){if(name.indexOf(".svg")==-1){return{name:name,width:function(str){if(curContext.mozMeasureText){return curContext.mozMeasureText(typeof str=="number"?String.fromCharCode(str):str)/curTextSize;}else{return 0;}}};}else{var font=p.loadGlyphs(name);return{name:name,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":return font["greater"];break;case"?":return font["question"];break;case"@":return font["at"];break;case"[":return font["bracketleft"];break;case"\\":return font["backslash"];break;case"]":return font["bracketright"];break;case"^":return font["asciicircum"];break;case"`":return font["grave"];break;case"{":return font["braceleft"];break;case"|":return font["bar"];break;case"}":return font["braceright"];break;case"~":return font["asciitilde"];break;default:return font[chr];break;}}catch(e){;}} +p.text=function text(str,x,y){if(!curTextFont.glyph){if(str&&curContext.mozDrawText){curContext.save();curContext.mozTextStyle=curTextSize+"px "+curTextFont.name;curContext.translate(x,y);curContext.mozDrawText(typeof str=="number"?String.fromCharCode(str):str);curContext.restore();}}else{var font=p.glyphTable[curTextFont.name];curContext.save();curContext.translate(x,y+curTextSize);var upem=font["units_per_em"],newScale=1/upem*curTextSize;curContext.scale(newScale,newScale);var len=str.length;for(var i=0;i