Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
AroriaNetwork
GitHub Repository: AroriaNetwork/3kho-backup
Path: blob/main/projects/polybranch/js/libs/processing.js
1835 views
1
/***
2
3
P R O C E S S I N G . J S - 1.4.1
4
a port of the Processing visualization language
5
6
Processing.js is licensed under the MIT License, see LICENSE.
7
For a list of copyright holders, please refer to AUTHORS.
8
9
http://processingjs.org
10
11
***/
12
13
(function(window, document, Math, undef) {
14
var nop = function() {};
15
var debug = function() {
16
if ("console" in window) return function(msg) {
17
window.console.log("Processing.js: " + msg)
18
};
19
return nop
20
}();
21
var ajax = function(url) {
22
var xhr = new XMLHttpRequest;
23
xhr.open("GET", url, false);
24
if (xhr.overrideMimeType) xhr.overrideMimeType("text/plain");
25
xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT");
26
xhr.send(null);
27
if (xhr.status !== 200 && xhr.status !== 0) throw "XMLHttpRequest failed, status code " + xhr.status;
28
return xhr.responseText
29
};
30
var isDOMPresent = "document" in this && !("fake" in this.document);
31
document.head = document.head || document.getElementsByTagName("head")[0];
32
33
function setupTypedArray(name, fallback) {
34
if (name in window) return window[name];
35
if (typeof window[fallback] === "function") return window[fallback];
36
return function(obj) {
37
if (obj instanceof Array) return obj;
38
if (typeof obj === "number") {
39
var arr = [];
40
arr.length = obj;
41
return arr
42
}
43
}
44
}
45
if (document.documentMode >= 9 && !document.doctype) throw "The doctype directive is missing. The recommended doctype in Internet Explorer is the HTML5 doctype: <!DOCTYPE html>";
46
var Float32Array = setupTypedArray("Float32Array", "WebGLFloatArray"),
47
Int32Array = setupTypedArray("Int32Array", "WebGLIntArray"),
48
Uint16Array = setupTypedArray("Uint16Array", "WebGLUnsignedShortArray"),
49
Uint8Array = setupTypedArray("Uint8Array", "WebGLUnsignedByteArray");
50
var PConstants = {
51
X: 0,
52
Y: 1,
53
Z: 2,
54
R: 3,
55
G: 4,
56
B: 5,
57
A: 6,
58
U: 7,
59
V: 8,
60
NX: 9,
61
NY: 10,
62
NZ: 11,
63
EDGE: 12,
64
SR: 13,
65
SG: 14,
66
SB: 15,
67
SA: 16,
68
SW: 17,
69
TX: 18,
70
TY: 19,
71
TZ: 20,
72
VX: 21,
73
VY: 22,
74
VZ: 23,
75
VW: 24,
76
AR: 25,
77
AG: 26,
78
AB: 27,
79
DR: 3,
80
DG: 4,
81
DB: 5,
82
DA: 6,
83
SPR: 28,
84
SPG: 29,
85
SPB: 30,
86
SHINE: 31,
87
ER: 32,
88
EG: 33,
89
EB: 34,
90
BEEN_LIT: 35,
91
VERTEX_FIELD_COUNT: 36,
92
P2D: 1,
93
JAVA2D: 1,
94
WEBGL: 2,
95
P3D: 2,
96
OPENGL: 2,
97
PDF: 0,
98
DXF: 0,
99
OTHER: 0,
100
WINDOWS: 1,
101
MAXOSX: 2,
102
LINUX: 3,
103
EPSILON: 1.0E-4,
104
MAX_FLOAT: 3.4028235E38,
105
MIN_FLOAT: -3.4028235E38,
106
MAX_INT: 2147483647,
107
MIN_INT: -2147483648,
108
PI: Math.PI,
109
TWO_PI: 2 * Math.PI,
110
HALF_PI: Math.PI / 2,
111
THIRD_PI: Math.PI / 3,
112
QUARTER_PI: Math.PI / 4,
113
DEG_TO_RAD: Math.PI / 180,
114
RAD_TO_DEG: 180 / Math.PI,
115
WHITESPACE: " \t\n\r\u000c\u00a0",
116
RGB: 1,
117
ARGB: 2,
118
HSB: 3,
119
ALPHA: 4,
120
CMYK: 5,
121
TIFF: 0,
122
TARGA: 1,
123
JPEG: 2,
124
GIF: 3,
125
BLUR: 11,
126
GRAY: 12,
127
INVERT: 13,
128
OPAQUE: 14,
129
POSTERIZE: 15,
130
THRESHOLD: 16,
131
ERODE: 17,
132
DILATE: 18,
133
REPLACE: 0,
134
BLEND: 1 << 0,
135
ADD: 1 << 1,
136
SUBTRACT: 1 << 2,
137
LIGHTEST: 1 << 3,
138
DARKEST: 1 << 4,
139
DIFFERENCE: 1 << 5,
140
EXCLUSION: 1 << 6,
141
MULTIPLY: 1 << 7,
142
SCREEN: 1 << 8,
143
OVERLAY: 1 << 9,
144
HARD_LIGHT: 1 << 10,
145
SOFT_LIGHT: 1 << 11,
146
DODGE: 1 << 12,
147
BURN: 1 << 13,
148
ALPHA_MASK: 4278190080,
149
RED_MASK: 16711680,
150
GREEN_MASK: 65280,
151
BLUE_MASK: 255,
152
CUSTOM: 0,
153
ORTHOGRAPHIC: 2,
154
PERSPECTIVE: 3,
155
POINT: 2,
156
POINTS: 2,
157
LINE: 4,
158
LINES: 4,
159
TRIANGLE: 8,
160
TRIANGLES: 9,
161
TRIANGLE_STRIP: 10,
162
TRIANGLE_FAN: 11,
163
QUAD: 16,
164
QUADS: 16,
165
QUAD_STRIP: 17,
166
POLYGON: 20,
167
PATH: 21,
168
RECT: 30,
169
ELLIPSE: 31,
170
ARC: 32,
171
SPHERE: 40,
172
BOX: 41,
173
GROUP: 0,
174
PRIMITIVE: 1,
175
GEOMETRY: 3,
176
VERTEX: 0,
177
BEZIER_VERTEX: 1,
178
CURVE_VERTEX: 2,
179
BREAK: 3,
180
CLOSESHAPE: 4,
181
OPEN: 1,
182
CLOSE: 2,
183
CORNER: 0,
184
CORNERS: 1,
185
RADIUS: 2,
186
CENTER_RADIUS: 2,
187
CENTER: 3,
188
DIAMETER: 3,
189
CENTER_DIAMETER: 3,
190
BASELINE: 0,
191
TOP: 101,
192
BOTTOM: 102,
193
NORMAL: 1,
194
NORMALIZED: 1,
195
IMAGE: 2,
196
MODEL: 4,
197
SHAPE: 5,
198
SQUARE: "butt",
199
ROUND: "round",
200
PROJECT: "square",
201
MITER: "miter",
202
BEVEL: "bevel",
203
AMBIENT: 0,
204
DIRECTIONAL: 1,
205
SPOT: 3,
206
BACKSPACE: 8,
207
TAB: 9,
208
ENTER: 10,
209
RETURN: 13,
210
ESC: 27,
211
DELETE: 127,
212
CODED: 65535,
213
SHIFT: 16,
214
CONTROL: 17,
215
ALT: 18,
216
CAPSLK: 20,
217
PGUP: 33,
218
PGDN: 34,
219
END: 35,
220
HOME: 36,
221
LEFT: 37,
222
UP: 38,
223
RIGHT: 39,
224
DOWN: 40,
225
F1: 112,
226
F2: 113,
227
F3: 114,
228
F4: 115,
229
F5: 116,
230
F6: 117,
231
F7: 118,
232
F8: 119,
233
F9: 120,
234
F10: 121,
235
F11: 122,
236
F12: 123,
237
NUMLK: 144,
238
META: 157,
239
INSERT: 155,
240
ARROW: "default",
241
CROSS: "crosshair",
242
HAND: "pointer",
243
MOVE: "move",
244
TEXT: "text",
245
WAIT: "wait",
246
NOCURSOR: "url('data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='), auto",
247
DISABLE_OPENGL_2X_SMOOTH: 1,
248
ENABLE_OPENGL_2X_SMOOTH: -1,
249
ENABLE_OPENGL_4X_SMOOTH: 2,
250
ENABLE_NATIVE_FONTS: 3,
251
DISABLE_DEPTH_TEST: 4,
252
ENABLE_DEPTH_TEST: -4,
253
ENABLE_DEPTH_SORT: 5,
254
DISABLE_DEPTH_SORT: -5,
255
DISABLE_OPENGL_ERROR_REPORT: 6,
256
ENABLE_OPENGL_ERROR_REPORT: -6,
257
ENABLE_ACCURATE_TEXTURES: 7,
258
DISABLE_ACCURATE_TEXTURES: -7,
259
HINT_COUNT: 10,
260
SINCOS_LENGTH: 720,
261
PRECISIONB: 15,
262
PRECISIONF: 1 << 15,
263
PREC_MAXVAL: (1 << 15) - 1,
264
PREC_ALPHA_SHIFT: 24 - 15,
265
PREC_RED_SHIFT: 16 - 15,
266
NORMAL_MODE_AUTO: 0,
267
NORMAL_MODE_SHAPE: 1,
268
NORMAL_MODE_VERTEX: 2,
269
MAX_LIGHTS: 8
270
};
271
272
function virtHashCode(obj) {
273
if (typeof obj === "string") {
274
var hash = 0;
275
for (var i = 0; i < obj.length; ++i) hash = hash * 31 + obj.charCodeAt(i) & 4294967295;
276
return hash
277
}
278
if (typeof obj !== "object") return obj & 4294967295;
279
if (obj.hashCode instanceof Function) return obj.hashCode();
280
if (obj.$id === undef) obj.$id = Math.floor(Math.random() * 65536) - 32768 << 16 | Math.floor(Math.random() * 65536);
281
return obj.$id
282
}
283
function virtEquals(obj, other) {
284
if (obj === null || other === null) return obj === null && other === null;
285
if (typeof obj === "string") return obj === other;
286
if (typeof obj !== "object") return obj === other;
287
if (obj.equals instanceof Function) return obj.equals(other);
288
return obj === other
289
}
290
var ObjectIterator = function(obj) {
291
if (obj.iterator instanceof
292
Function) return obj.iterator();
293
if (obj instanceof Array) {
294
var index = -1;
295
this.hasNext = function() {
296
return ++index < obj.length
297
};
298
this.next = function() {
299
return obj[index]
300
}
301
} else throw "Unable to iterate: " + obj;
302
};
303
var ArrayList = function() {
304
function Iterator(array) {
305
var index = 0;
306
this.hasNext = function() {
307
return index < array.length
308
};
309
this.next = function() {
310
return array[index++]
311
};
312
this.remove = function() {
313
array.splice(index, 1)
314
}
315
}
316
function ArrayList(a) {
317
var array;
318
if (a instanceof ArrayList) array = a.toArray();
319
else {
320
array = [];
321
if (typeof a === "number") array.length = a > 0 ? a : 0
322
}
323
this.get = function(i) {
324
return array[i]
325
};
326
this.contains = function(item) {
327
return this.indexOf(item) > -1
328
};
329
this.indexOf = function(item) {
330
for (var i = 0, len = array.length; i < len; ++i) if (virtEquals(item, array[i])) return i;
331
return -1
332
};
333
this.lastIndexOf = function(item) {
334
for (var i = array.length - 1; i >= 0; --i) if (virtEquals(item, array[i])) return i;
335
return -1
336
};
337
this.add = function() {
338
if (arguments.length === 1) array.push(arguments[0]);
339
else if (arguments.length === 2) {
340
var arg0 = arguments[0];
341
if (typeof arg0 === "number") if (arg0 >= 0 && arg0 <= array.length) array.splice(arg0, 0, arguments[1]);
342
else throw arg0 + " is not a valid index";
343
else throw typeof arg0 + " is not a number";
344
} else throw "Please use the proper number of parameters.";
345
};
346
this.addAll = function(arg1, arg2) {
347
var it;
348
if (typeof arg1 === "number") {
349
if (arg1 < 0 || arg1 > array.length) throw "Index out of bounds for addAll: " + arg1 + " greater or equal than " + array.length;
350
it = new ObjectIterator(arg2);
351
while (it.hasNext()) array.splice(arg1++, 0, it.next())
352
} else {
353
it = new ObjectIterator(arg1);
354
while (it.hasNext()) array.push(it.next())
355
}
356
};
357
this.set = function() {
358
if (arguments.length === 2) {
359
var arg0 = arguments[0];
360
if (typeof arg0 === "number") if (arg0 >= 0 && arg0 < array.length) array.splice(arg0, 1, arguments[1]);
361
else throw arg0 + " is not a valid index.";
362
else throw typeof arg0 + " is not a number";
363
} else throw "Please use the proper number of parameters.";
364
};
365
this.size = function() {
366
return array.length
367
};
368
this.clear = function() {
369
array.length = 0
370
};
371
this.remove = function(item) {
372
if (typeof item === "number") return array.splice(item, 1)[0];
373
item = this.indexOf(item);
374
if (item > -1) {
375
array.splice(item, 1);
376
return true
377
}
378
return false
379
};
380
this.removeAll = function(c) {
381
var i, x, item, newList = new ArrayList;
382
newList.addAll(this);
383
this.clear();
384
for (i = 0, x = 0; i < newList.size(); i++) {
385
item = newList.get(i);
386
if (!c.contains(item)) this.add(x++, item)
387
}
388
if (this.size() < newList.size()) return true;
389
return false
390
};
391
this.isEmpty = function() {
392
return !array.length
393
};
394
this.clone = function() {
395
return new ArrayList(this)
396
};
397
this.toArray = function() {
398
return array.slice(0)
399
};
400
this.iterator = function() {
401
return new Iterator(array)
402
}
403
}
404
return ArrayList
405
}();
406
var HashMap = function() {
407
function HashMap() {
408
if (arguments.length === 1 && arguments[0] instanceof HashMap) return arguments[0].clone();
409
var initialCapacity = arguments.length > 0 ? arguments[0] : 16;
410
var loadFactor = arguments.length > 1 ? arguments[1] : 0.75;
411
var buckets = [];
412
buckets.length = initialCapacity;
413
var count = 0;
414
var hashMap = this;
415
416
function getBucketIndex(key) {
417
var index = virtHashCode(key) % buckets.length;
418
return index < 0 ? buckets.length + index : index
419
}
420
function ensureLoad() {
421
if (count <= loadFactor * buckets.length) return;
422
var allEntries = [];
423
for (var i = 0; i < buckets.length; ++i) if (buckets[i] !== undef) allEntries = allEntries.concat(buckets[i]);
424
var newBucketsLength = buckets.length * 2;
425
buckets = [];
426
buckets.length = newBucketsLength;
427
for (var j = 0; j < allEntries.length; ++j) {
428
var index = getBucketIndex(allEntries[j].key);
429
var bucket = buckets[index];
430
if (bucket === undef) buckets[index] = bucket = [];
431
bucket.push(allEntries[j])
432
}
433
}
434
function Iterator(conversion, removeItem) {
435
var bucketIndex = 0;
436
var itemIndex = -1;
437
var endOfBuckets = false;
438
var currentItem;
439
440
function findNext() {
441
while (!endOfBuckets) {
442
++itemIndex;
443
if (bucketIndex >= buckets.length) endOfBuckets = true;
444
else if (buckets[bucketIndex] === undef || itemIndex >= buckets[bucketIndex].length) {
445
itemIndex = -1;
446
++bucketIndex
447
} else return
448
}
449
}
450
this.hasNext = function() {
451
return !endOfBuckets
452
};
453
this.next = function() {
454
currentItem = conversion(buckets[bucketIndex][itemIndex]);
455
findNext();
456
return currentItem
457
};
458
this.remove = function() {
459
if (currentItem !== undef) {
460
removeItem(currentItem);
461
--itemIndex;
462
findNext()
463
}
464
};
465
findNext()
466
}
467
function Set(conversion, isIn, removeItem) {
468
this.clear = function() {
469
hashMap.clear()
470
};
471
this.contains = function(o) {
472
return isIn(o)
473
};
474
this.containsAll = function(o) {
475
var it = o.iterator();
476
while (it.hasNext()) if (!this.contains(it.next())) return false;
477
return true
478
};
479
this.isEmpty = function() {
480
return hashMap.isEmpty()
481
};
482
this.iterator = function() {
483
return new Iterator(conversion, removeItem)
484
};
485
this.remove = function(o) {
486
if (this.contains(o)) {
487
removeItem(o);
488
return true
489
}
490
return false
491
};
492
this.removeAll = function(c) {
493
var it = c.iterator();
494
var changed = false;
495
while (it.hasNext()) {
496
var item = it.next();
497
if (this.contains(item)) {
498
removeItem(item);
499
changed = true
500
}
501
}
502
return true
503
};
504
this.retainAll = function(c) {
505
var it = this.iterator();
506
var toRemove = [];
507
while (it.hasNext()) {
508
var entry = it.next();
509
if (!c.contains(entry)) toRemove.push(entry)
510
}
511
for (var i = 0; i < toRemove.length; ++i) removeItem(toRemove[i]);
512
return toRemove.length > 0
513
};
514
this.size = function() {
515
return hashMap.size()
516
};
517
this.toArray = function() {
518
var result = [];
519
var it = this.iterator();
520
while (it.hasNext()) result.push(it.next());
521
return result
522
}
523
}
524
function Entry(pair) {
525
this._isIn = function(map) {
526
return map === hashMap && pair.removed === undef
527
};
528
this.equals = function(o) {
529
return virtEquals(pair.key, o.getKey())
530
};
531
this.getKey = function() {
532
return pair.key
533
};
534
this.getValue = function() {
535
return pair.value
536
};
537
this.hashCode = function(o) {
538
return virtHashCode(pair.key)
539
};
540
this.setValue = function(value) {
541
var old = pair.value;
542
pair.value = value;
543
return old
544
}
545
}
546
this.clear = function() {
547
count = 0;
548
buckets = [];
549
buckets.length = initialCapacity
550
};
551
this.clone = function() {
552
var map = new HashMap;
553
map.putAll(this);
554
return map
555
};
556
this.containsKey = function(key) {
557
var index = getBucketIndex(key);
558
var bucket = buckets[index];
559
if (bucket === undef) return false;
560
for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) return true;
561
return false
562
};
563
this.containsValue = function(value) {
564
for (var i = 0; i < buckets.length; ++i) {
565
var bucket = buckets[i];
566
if (bucket === undef) continue;
567
for (var j = 0; j < bucket.length; ++j) if (virtEquals(bucket[j].value, value)) return true
568
}
569
return false
570
};
571
this.entrySet = function() {
572
return new Set(function(pair) {
573
return new Entry(pair)
574
},
575
576
577
function(pair) {
578
return pair instanceof Entry && pair._isIn(hashMap)
579
},
580
581
582
function(pair) {
583
return hashMap.remove(pair.getKey())
584
})
585
};
586
this.get = function(key) {
587
var index = getBucketIndex(key);
588
var bucket = buckets[index];
589
if (bucket === undef) return null;
590
for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) return bucket[i].value;
591
return null
592
};
593
this.isEmpty = function() {
594
return count === 0
595
};
596
this.keySet = function() {
597
return new Set(function(pair) {
598
return pair.key
599
},
600
601
602
function(key) {
603
return hashMap.containsKey(key)
604
},
605
606
607
function(key) {
608
return hashMap.remove(key)
609
})
610
};
611
this.values = function() {
612
return new Set(function(pair) {
613
return pair.value
614
},
615
616
617
function(value) {
618
return hashMap.containsValue(value)
619
},
620
621
function(value) {
622
return hashMap.removeByValue(value)
623
})
624
};
625
this.put = function(key, value) {
626
var index = getBucketIndex(key);
627
var bucket = buckets[index];
628
if (bucket === undef) {
629
++count;
630
buckets[index] = [{
631
key: key,
632
value: value
633
}];
634
ensureLoad();
635
return null
636
}
637
for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) {
638
var previous = bucket[i].value;
639
bucket[i].value = value;
640
return previous
641
}++count;
642
bucket.push({
643
key: key,
644
value: value
645
});
646
ensureLoad();
647
return null
648
};
649
this.putAll = function(m) {
650
var it = m.entrySet().iterator();
651
while (it.hasNext()) {
652
var entry = it.next();
653
this.put(entry.getKey(), entry.getValue())
654
}
655
};
656
this.remove = function(key) {
657
var index = getBucketIndex(key);
658
var bucket = buckets[index];
659
if (bucket === undef) return null;
660
for (var i = 0; i < bucket.length; ++i) if (virtEquals(bucket[i].key, key)) {
661
--count;
662
var previous = bucket[i].value;
663
bucket[i].removed = true;
664
if (bucket.length > 1) bucket.splice(i, 1);
665
else buckets[index] = undef;
666
return previous
667
}
668
return null
669
};
670
this.removeByValue = function(value) {
671
var bucket, i, ilen, pair;
672
for (bucket in buckets) if (buckets.hasOwnProperty(bucket)) for (i = 0, ilen = buckets[bucket].length; i < ilen; i++) {
673
pair = buckets[bucket][i];
674
if (pair.value === value) {
675
buckets[bucket].splice(i, 1);
676
return true
677
}
678
}
679
return false
680
};
681
this.size = function() {
682
return count
683
}
684
}
685
return HashMap
686
}();
687
var PVector = function() {
688
function PVector(x, y, z) {
689
this.x = x || 0;
690
this.y = y || 0;
691
this.z = z || 0
692
}
693
PVector.dist = function(v1, v2) {
694
return v1.dist(v2)
695
};
696
PVector.dot = function(v1, v2) {
697
return v1.dot(v2)
698
};
699
PVector.cross = function(v1, v2) {
700
return v1.cross(v2)
701
};
702
PVector.angleBetween = function(v1, v2) {
703
return Math.acos(v1.dot(v2) / (v1.mag() * v2.mag()))
704
};
705
PVector.prototype = {
706
set: function(v, y, z) {
707
if (arguments.length === 1) this.set(v.x || v[0] || 0, v.y || v[1] || 0, v.z || v[2] || 0);
708
else {
709
this.x = v;
710
this.y = y;
711
this.z = z
712
}
713
},
714
get: function() {
715
return new PVector(this.x, this.y, this.z)
716
},
717
mag: function() {
718
var x = this.x,
719
y = this.y,
720
z = this.z;
721
return Math.sqrt(x * x + y * y + z * z)
722
},
723
add: function(v, y, z) {
724
if (arguments.length === 1) {
725
this.x += v.x;
726
this.y += v.y;
727
this.z += v.z
728
} else {
729
this.x += v;
730
this.y += y;
731
this.z += z
732
}
733
},
734
sub: function(v, y, z) {
735
if (arguments.length === 1) {
736
this.x -= v.x;
737
this.y -= v.y;
738
this.z -= v.z
739
} else {
740
this.x -= v;
741
this.y -= y;
742
this.z -= z
743
}
744
},
745
mult: function(v) {
746
if (typeof v === "number") {
747
this.x *= v;
748
this.y *= v;
749
this.z *= v
750
} else {
751
this.x *= v.x;
752
this.y *= v.y;
753
this.z *= v.z
754
}
755
},
756
div: function(v) {
757
if (typeof v === "number") {
758
this.x /= v;
759
this.y /= v;
760
this.z /= v
761
} else {
762
this.x /= v.x;
763
this.y /= v.y;
764
this.z /= v.z
765
}
766
},
767
dist: function(v) {
768
var dx = this.x - v.x,
769
dy = this.y - v.y,
770
dz = this.z - v.z;
771
return Math.sqrt(dx * dx + dy * dy + dz * dz)
772
},
773
dot: function(v, y, z) {
774
if (arguments.length === 1) return this.x * v.x + this.y * v.y + this.z * v.z;
775
return this.x * v + this.y * y + this.z * z
776
},
777
cross: function(v) {
778
var x = this.x,
779
y = this.y,
780
z = this.z;
781
return new PVector(y * v.z - v.y * z, z * v.x - v.z * x, x * v.y - v.x * y)
782
},
783
normalize: function() {
784
var m = this.mag();
785
if (m > 0) this.div(m)
786
},
787
limit: function(high) {
788
if (this.mag() > high) {
789
this.normalize();
790
this.mult(high)
791
}
792
},
793
heading2D: function() {
794
return -Math.atan2(-this.y, this.x)
795
},
796
toString: function() {
797
return "[" + this.x + ", " + this.y + ", " + this.z + "]"
798
},
799
array: function() {
800
return [this.x, this.y, this.z]
801
}
802
};
803
804
function createPVectorMethod(method) {
805
return function(v1, v2) {
806
var v = v1.get();
807
v[method](v2);
808
return v
809
}
810
}
811
for (var method in PVector.prototype) if (PVector.prototype.hasOwnProperty(method) && !PVector.hasOwnProperty(method)) PVector[method] = createPVectorMethod(method);
812
return PVector
813
}();
814
815
function DefaultScope() {}
816
DefaultScope.prototype = PConstants;
817
var defaultScope = new DefaultScope;
818
defaultScope.ArrayList = ArrayList;
819
defaultScope.HashMap = HashMap;
820
defaultScope.PVector = PVector;
821
defaultScope.ObjectIterator = ObjectIterator;
822
defaultScope.PConstants = PConstants;
823
defaultScope.defineProperty = function(obj, name, desc) {
824
if ("defineProperty" in Object) Object.defineProperty(obj, name, desc);
825
else {
826
if (desc.hasOwnProperty("get")) obj.__defineGetter__(name, desc.get);
827
if (desc.hasOwnProperty("set")) obj.__defineSetter__(name, desc.set)
828
}
829
};
830
831
function overloadBaseClassFunction(object, name, basefn) {
832
if (!object.hasOwnProperty(name) || typeof object[name] !== "function") {
833
object[name] = basefn;
834
return
835
}
836
var fn = object[name];
837
if ("$overloads" in fn) {
838
fn.$defaultOverload = basefn;
839
return
840
}
841
if (! ("$overloads" in basefn) && fn.length === basefn.length) return;
842
var overloads, defaultOverload;
843
if ("$overloads" in basefn) {
844
overloads = basefn.$overloads.slice(0);
845
overloads[fn.length] = fn;
846
defaultOverload = basefn.$defaultOverload
847
} else {
848
overloads = [];
849
overloads[basefn.length] = basefn;
850
overloads[fn.length] = fn;
851
defaultOverload = fn
852
}
853
var hubfn = function() {
854
var fn = hubfn.$overloads[arguments.length] || ("$methodArgsIndex" in hubfn && arguments.length > hubfn.$methodArgsIndex ? hubfn.$overloads[hubfn.$methodArgsIndex] : null) || hubfn.$defaultOverload;
855
return fn.apply(this, arguments)
856
};
857
hubfn.$overloads = overloads;
858
if ("$methodArgsIndex" in basefn) hubfn.$methodArgsIndex = basefn.$methodArgsIndex;
859
hubfn.$defaultOverload = defaultOverload;
860
hubfn.name = name;
861
object[name] = hubfn
862
}
863
function extendClass(subClass, baseClass) {
864
function extendGetterSetter(propertyName) {
865
defaultScope.defineProperty(subClass, propertyName, {
866
get: function() {
867
return baseClass[propertyName]
868
},
869
set: function(v) {
870
baseClass[propertyName] = v
871
},
872
enumerable: true
873
})
874
}
875
var properties = [];
876
for (var propertyName in baseClass) if (typeof baseClass[propertyName] === "function") overloadBaseClassFunction(subClass, propertyName, baseClass[propertyName]);
877
else if (propertyName.charAt(0) !== "$" && !(propertyName in subClass)) properties.push(propertyName);
878
while (properties.length > 0) extendGetterSetter(properties.shift());
879
subClass.$super = baseClass
880
}
881
defaultScope.extendClassChain = function(base) {
882
var path = [base];
883
for (var self = base.$upcast; self; self = self.$upcast) {
884
extendClass(self, base);
885
path.push(self);
886
base = self
887
}
888
while (path.length > 0) path.pop().$self = base
889
};
890
defaultScope.extendStaticMembers = function(derived, base) {
891
extendClass(derived, base)
892
};
893
defaultScope.extendInterfaceMembers = function(derived, base) {
894
extendClass(derived, base)
895
};
896
defaultScope.addMethod = function(object, name, fn, hasMethodArgs) {
897
var existingfn = object[name];
898
if (existingfn || hasMethodArgs) {
899
var args = fn.length;
900
if ("$overloads" in existingfn) existingfn.$overloads[args] = fn;
901
else {
902
var hubfn = function() {
903
var fn = hubfn.$overloads[arguments.length] || ("$methodArgsIndex" in hubfn && arguments.length > hubfn.$methodArgsIndex ? hubfn.$overloads[hubfn.$methodArgsIndex] : null) || hubfn.$defaultOverload;
904
return fn.apply(this, arguments)
905
};
906
var overloads = [];
907
if (existingfn) overloads[existingfn.length] = existingfn;
908
overloads[args] = fn;
909
hubfn.$overloads = overloads;
910
hubfn.$defaultOverload = existingfn || fn;
911
if (hasMethodArgs) hubfn.$methodArgsIndex = args;
912
hubfn.name = name;
913
object[name] = hubfn
914
}
915
} else object[name] = fn
916
};
917
918
function isNumericalJavaType(type) {
919
if (typeof type !== "string") return false;
920
return ["byte", "int", "char", "color", "float", "long", "double"].indexOf(type) !== -1
921
}
922
defaultScope.createJavaArray = function(type, bounds) {
923
var result = null,
924
defaultValue = null;
925
if (typeof type === "string") if (type === "boolean") defaultValue = false;
926
else if (isNumericalJavaType(type)) defaultValue = 0;
927
if (typeof bounds[0] === "number") {
928
var itemsCount = 0 | bounds[0];
929
if (bounds.length <= 1) {
930
result = [];
931
result.length = itemsCount;
932
for (var i = 0; i < itemsCount; ++i) result[i] = defaultValue
933
} else {
934
result = [];
935
var newBounds = bounds.slice(1);
936
for (var j = 0; j < itemsCount; ++j) result.push(defaultScope.createJavaArray(type, newBounds))
937
}
938
}
939
return result
940
};
941
var colors = {
942
aliceblue: "#f0f8ff",
943
antiquewhite: "#faebd7",
944
aqua: "#00ffff",
945
aquamarine: "#7fffd4",
946
azure: "#f0ffff",
947
beige: "#f5f5dc",
948
bisque: "#ffe4c4",
949
black: "#000000",
950
blanchedalmond: "#ffebcd",
951
blue: "#0000ff",
952
blueviolet: "#8a2be2",
953
brown: "#a52a2a",
954
burlywood: "#deb887",
955
cadetblue: "#5f9ea0",
956
chartreuse: "#7fff00",
957
chocolate: "#d2691e",
958
coral: "#ff7f50",
959
cornflowerblue: "#6495ed",
960
cornsilk: "#fff8dc",
961
crimson: "#dc143c",
962
cyan: "#00ffff",
963
darkblue: "#00008b",
964
darkcyan: "#008b8b",
965
darkgoldenrod: "#b8860b",
966
darkgray: "#a9a9a9",
967
darkgreen: "#006400",
968
darkkhaki: "#bdb76b",
969
darkmagenta: "#8b008b",
970
darkolivegreen: "#556b2f",
971
darkorange: "#ff8c00",
972
darkorchid: "#9932cc",
973
darkred: "#8b0000",
974
darksalmon: "#e9967a",
975
darkseagreen: "#8fbc8f",
976
darkslateblue: "#483d8b",
977
darkslategray: "#2f4f4f",
978
darkturquoise: "#00ced1",
979
darkviolet: "#9400d3",
980
deeppink: "#ff1493",
981
deepskyblue: "#00bfff",
982
dimgray: "#696969",
983
dodgerblue: "#1e90ff",
984
firebrick: "#b22222",
985
floralwhite: "#fffaf0",
986
forestgreen: "#228b22",
987
fuchsia: "#ff00ff",
988
gainsboro: "#dcdcdc",
989
ghostwhite: "#f8f8ff",
990
gold: "#ffd700",
991
goldenrod: "#daa520",
992
gray: "#808080",
993
green: "#008000",
994
greenyellow: "#adff2f",
995
honeydew: "#f0fff0",
996
hotpink: "#ff69b4",
997
indianred: "#cd5c5c",
998
indigo: "#4b0082",
999
ivory: "#fffff0",
1000
khaki: "#f0e68c",
1001
lavender: "#e6e6fa",
1002
lavenderblush: "#fff0f5",
1003
lawngreen: "#7cfc00",
1004
lemonchiffon: "#fffacd",
1005
lightblue: "#add8e6",
1006
lightcoral: "#f08080",
1007
lightcyan: "#e0ffff",
1008
lightgoldenrodyellow: "#fafad2",
1009
lightgrey: "#d3d3d3",
1010
lightgreen: "#90ee90",
1011
lightpink: "#ffb6c1",
1012
lightsalmon: "#ffa07a",
1013
lightseagreen: "#20b2aa",
1014
lightskyblue: "#87cefa",
1015
lightslategray: "#778899",
1016
lightsteelblue: "#b0c4de",
1017
lightyellow: "#ffffe0",
1018
lime: "#00ff00",
1019
limegreen: "#32cd32",
1020
linen: "#faf0e6",
1021
magenta: "#ff00ff",
1022
maroon: "#800000",
1023
mediumaquamarine: "#66cdaa",
1024
mediumblue: "#0000cd",
1025
mediumorchid: "#ba55d3",
1026
mediumpurple: "#9370d8",
1027
mediumseagreen: "#3cb371",
1028
mediumslateblue: "#7b68ee",
1029
mediumspringgreen: "#00fa9a",
1030
mediumturquoise: "#48d1cc",
1031
mediumvioletred: "#c71585",
1032
midnightblue: "#191970",
1033
mintcream: "#f5fffa",
1034
mistyrose: "#ffe4e1",
1035
moccasin: "#ffe4b5",
1036
navajowhite: "#ffdead",
1037
navy: "#000080",
1038
oldlace: "#fdf5e6",
1039
olive: "#808000",
1040
olivedrab: "#6b8e23",
1041
orange: "#ffa500",
1042
orangered: "#ff4500",
1043
orchid: "#da70d6",
1044
palegoldenrod: "#eee8aa",
1045
palegreen: "#98fb98",
1046
paleturquoise: "#afeeee",
1047
palevioletred: "#d87093",
1048
papayawhip: "#ffefd5",
1049
peachpuff: "#ffdab9",
1050
peru: "#cd853f",
1051
pink: "#ffc0cb",
1052
plum: "#dda0dd",
1053
powderblue: "#b0e0e6",
1054
purple: "#800080",
1055
red: "#ff0000",
1056
rosybrown: "#bc8f8f",
1057
royalblue: "#4169e1",
1058
saddlebrown: "#8b4513",
1059
salmon: "#fa8072",
1060
sandybrown: "#f4a460",
1061
seagreen: "#2e8b57",
1062
seashell: "#fff5ee",
1063
sienna: "#a0522d",
1064
silver: "#c0c0c0",
1065
skyblue: "#87ceeb",
1066
slateblue: "#6a5acd",
1067
slategray: "#708090",
1068
snow: "#fffafa",
1069
springgreen: "#00ff7f",
1070
steelblue: "#4682b4",
1071
tan: "#d2b48c",
1072
teal: "#008080",
1073
thistle: "#d8bfd8",
1074
tomato: "#ff6347",
1075
turquoise: "#40e0d0",
1076
violet: "#ee82ee",
1077
wheat: "#f5deb3",
1078
white: "#ffffff",
1079
whitesmoke: "#f5f5f5",
1080
yellow: "#ffff00",
1081
yellowgreen: "#9acd32"
1082
};
1083
(function(Processing) {
1084
var unsupportedP5 = ("open() createOutput() createInput() BufferedReader selectFolder() " + "dataPath() createWriter() selectOutput() beginRecord() " + "saveStream() endRecord() selectInput() saveBytes() createReader() " + "beginRaw() endRaw() PrintWriter delay()").split(" "),
1085
count = unsupportedP5.length,
1086
prettyName, p5Name;
1087
1088
function createUnsupportedFunc(n) {
1089
return function() {
1090
throw "Processing.js does not support " + n + ".";
1091
}
1092
}
1093
while (count--) {
1094
prettyName = unsupportedP5[count];
1095
p5Name = prettyName.replace("()", "");
1096
Processing[p5Name] = createUnsupportedFunc(prettyName)
1097
}
1098
})(defaultScope);
1099
defaultScope.defineProperty(defaultScope, "screenWidth", {
1100
get: function() {
1101
return window.innerWidth
1102
}
1103
});
1104
defaultScope.defineProperty(defaultScope, "screenHeight", {
1105
get: function() {
1106
return window.innerHeight
1107
}
1108
});
1109
defaultScope.defineProperty(defaultScope, "online", {
1110
get: function() {
1111
return true
1112
}
1113
});
1114
var processingInstances = [];
1115
var processingInstanceIds = {};
1116
var removeInstance = function(id) {
1117
processingInstances.splice(processingInstanceIds[id], 1);
1118
delete processingInstanceIds[id]
1119
};
1120
var addInstance = function(processing) {
1121
if (processing.externals.canvas.id === undef || !processing.externals.canvas.id.length) processing.externals.canvas.id = "__processing" + processingInstances.length;
1122
processingInstanceIds[processing.externals.canvas.id] = processingInstances.length;
1123
processingInstances.push(processing)
1124
};
1125
1126
function computeFontMetrics(pfont) {
1127
var emQuad = 250,
1128
correctionFactor = pfont.size / emQuad,
1129
canvas = document.createElement("canvas");
1130
canvas.width = 2 * emQuad;
1131
canvas.height = 2 * emQuad;
1132
canvas.style.opacity = 0;
1133
var cfmFont = pfont.getCSSDefinition(emQuad + "px", "normal"),
1134
ctx = canvas.getContext("2d");
1135
ctx.font = cfmFont;
1136
var protrusions = "dbflkhyjqpg";
1137
canvas.width = ctx.measureText(protrusions).width;
1138
ctx.font = cfmFont;
1139
var leadDiv = document.createElement("div");
1140
leadDiv.style.position = "absolute";
1141
leadDiv.style.opacity = 0;
1142
leadDiv.style.fontFamily = '"' + pfont.name + '"';
1143
leadDiv.style.fontSize = emQuad + "px";
1144
leadDiv.innerHTML = protrusions + "<br/>" + protrusions;
1145
document.body.appendChild(leadDiv);
1146
var w = canvas.width,
1147
h = canvas.height,
1148
baseline = h / 2;
1149
ctx.fillStyle = "white";
1150
ctx.fillRect(0, 0, w, h);
1151
ctx.fillStyle = "black";
1152
ctx.fillText(protrusions, 0, baseline);
1153
var pixelData = ctx.getImageData(0, 0, w, h).data;
1154
var i = 0,
1155
w4 = w * 4,
1156
len = pixelData.length;
1157
while (++i < len && pixelData[i] === 255) nop();
1158
var ascent = Math.round(i / w4);
1159
i = len - 1;
1160
while (--i > 0 && pixelData[i] === 255) nop();
1161
var descent = Math.round(i / w4);
1162
pfont.ascent = correctionFactor * (baseline - ascent);
1163
pfont.descent = correctionFactor * (descent - baseline);
1164
if (document.defaultView.getComputedStyle) {
1165
var leadDivHeight = document.defaultView.getComputedStyle(leadDiv, null).getPropertyValue("height");
1166
leadDivHeight = correctionFactor * leadDivHeight.replace("px", "");
1167
if (leadDivHeight >= pfont.size * 2) pfont.leading = Math.round(leadDivHeight / 2)
1168
}
1169
document.body.removeChild(leadDiv);
1170
if (pfont.caching) return ctx
1171
}
1172
function PFont(name, size) {
1173
if (name === undef) name = "";
1174
this.name = name;
1175
if (size === undef) size = 0;
1176
this.size = size;
1177
this.glyph = false;
1178
this.ascent = 0;
1179
this.descent = 0;
1180
this.leading = 1.2 * size;
1181
var illegalIndicator = name.indexOf(" Italic Bold");
1182
if (illegalIndicator !== -1) name = name.substring(0, illegalIndicator);
1183
this.style = "normal";
1184
var italicsIndicator = name.indexOf(" Italic");
1185
if (italicsIndicator !== -1) {
1186
name = name.substring(0, italicsIndicator);
1187
this.style = "italic"
1188
}
1189
this.weight = "normal";
1190
var boldIndicator = name.indexOf(" Bold");
1191
if (boldIndicator !== -1) {
1192
name = name.substring(0, boldIndicator);
1193
this.weight = "bold"
1194
}
1195
this.family = "sans-serif";
1196
if (name !== undef) switch (name) {
1197
case "sans-serif":
1198
case "serif":
1199
case "monospace":
1200
case "fantasy":
1201
case "cursive":
1202
this.family = name;
1203
break;
1204
default:
1205
this.family = '"' + name + '", sans-serif';
1206
break
1207
}
1208
this.context2d = computeFontMetrics(this);
1209
this.css = this.getCSSDefinition();
1210
if (this.context2d) this.context2d.font = this.css
1211
}
1212
PFont.prototype.caching = true;
1213
PFont.prototype.getCSSDefinition = function(fontSize, lineHeight) {
1214
if (fontSize === undef) fontSize = this.size + "px";
1215
if (lineHeight === undef) lineHeight = this.leading + "px";
1216
var components = [this.style, "normal", this.weight, fontSize + "/" + lineHeight, this.family];
1217
return components.join(" ")
1218
};
1219
PFont.prototype.measureTextWidth = function(string) {
1220
return this.context2d.measureText(string).width
1221
};
1222
PFont.prototype.measureTextWidthFallback = function(string) {
1223
var canvas = document.createElement("canvas"),
1224
ctx = canvas.getContext("2d");
1225
ctx.font = this.css;
1226
return ctx.measureText(string).width
1227
};
1228
PFont.PFontCache = {
1229
length: 0
1230
};
1231
PFont.get = function(fontName, fontSize) {
1232
fontSize = (fontSize * 10 + 0.5 | 0) / 10;
1233
var cache = PFont.PFontCache,
1234
idx = fontName + "/" + fontSize;
1235
if (!cache[idx]) {
1236
cache[idx] = new PFont(fontName, fontSize);
1237
cache.length++;
1238
if (cache.length === 50) {
1239
PFont.prototype.measureTextWidth = PFont.prototype.measureTextWidthFallback;
1240
PFont.prototype.caching = false;
1241
var entry;
1242
for (entry in cache) if (entry !== "length") cache[entry].context2d = null;
1243
return new PFont(fontName, fontSize)
1244
}
1245
if (cache.length === 400) {
1246
PFont.PFontCache = {};
1247
PFont.get = PFont.getFallback;
1248
return new PFont(fontName, fontSize)
1249
}
1250
}
1251
return cache[idx]
1252
};
1253
PFont.getFallback = function(fontName, fontSize) {
1254
return new PFont(fontName, fontSize)
1255
};
1256
PFont.list = function() {
1257
return ["sans-serif", "serif", "monospace", "fantasy", "cursive"]
1258
};
1259
PFont.preloading = {
1260
template: {},
1261
initialized: false,
1262
initialize: function() {
1263
var generateTinyFont = function() {
1264
var encoded = "#E3KAI2wAgT1MvMg7Eo3VmNtYX7ABi3CxnbHlm" + "7Abw3kaGVhZ7ACs3OGhoZWE7A53CRobXR47AY3" + "AGbG9jYQ7G03Bm1heH7ABC3CBuYW1l7Ae3AgcG" + "9zd7AI3AE#B3AQ2kgTY18PPPUACwAg3ALSRoo3" + "#yld0xg32QAB77#E777773B#E3C#I#Q77773E#" + "Q7777777772CMAIw7AB77732B#M#Q3wAB#g3B#" + "E#E2BB//82BB////w#B7#gAEg3E77x2B32B#E#" + "Q#MTcBAQ32gAe#M#QQJ#E32M#QQJ#I#g32Q77#";
1265
var expand = function(input) {
1266
return "AAAAAAAA".substr(~~input ? 7 - input : 6)
1267
};
1268
return encoded.replace(/[#237]/g, expand)
1269
};
1270
var fontface = document.createElement("style");
1271
fontface.setAttribute("type", "text/css");
1272
fontface.innerHTML = "@font-face {\n" + ' font-family: "PjsEmptyFont";' + "\n" + " src: url('data:application/x-font-ttf;base64," + generateTinyFont() + "')\n" + " format('truetype');\n" + "}";
1273
document.head.appendChild(fontface);
1274
var element = document.createElement("span");
1275
element.style.cssText = 'position: absolute; top: 0; left: 0; opacity: 0; font-family: "PjsEmptyFont", fantasy;';
1276
element.innerHTML = "AAAAAAAA";
1277
document.body.appendChild(element);
1278
this.template = element;
1279
this.initialized = true
1280
},
1281
getElementWidth: function(element) {
1282
return document.defaultView.getComputedStyle(element, "").getPropertyValue("width")
1283
},
1284
timeAttempted: 0,
1285
pending: function(intervallength) {
1286
if (!this.initialized) this.initialize();
1287
var element, computedWidthFont, computedWidthRef = this.getElementWidth(this.template);
1288
for (var i = 0; i < this.fontList.length; i++) {
1289
element = this.fontList[i];
1290
computedWidthFont = this.getElementWidth(element);
1291
if (this.timeAttempted < 4E3 && computedWidthFont === computedWidthRef) {
1292
this.timeAttempted += intervallength;
1293
return true
1294
} else {
1295
document.body.removeChild(element);
1296
this.fontList.splice(i--, 1);
1297
this.timeAttempted = 0
1298
}
1299
}
1300
if (this.fontList.length === 0) return false;
1301
return true
1302
},
1303
fontList: [],
1304
addedList: {},
1305
add: function(fontSrc) {
1306
if (!this.initialized) this.initialize();
1307
var fontName = typeof fontSrc === "object" ? fontSrc.fontFace : fontSrc,
1308
fontUrl = typeof fontSrc === "object" ? fontSrc.url : fontSrc;
1309
if (this.addedList[fontName]) return;
1310
var style = document.createElement("style");
1311
style.setAttribute("type", "text/css");
1312
style.innerHTML = "@font-face{\n font-family: '" + fontName + "';\n src: url('" + fontUrl + "');\n}\n";
1313
document.head.appendChild(style);
1314
this.addedList[fontName] = true;
1315
var element = document.createElement("span");
1316
element.style.cssText = "position: absolute; top: 0; left: 0; opacity: 0;";
1317
element.style.fontFamily = '"' + fontName + '", "PjsEmptyFont", fantasy';
1318
element.innerHTML = "AAAAAAAA";
1319
document.body.appendChild(element);
1320
this.fontList.push(element)
1321
}
1322
};
1323
defaultScope.PFont = PFont;
1324
var Processing = this.Processing = function(aCanvas, aCode) {
1325
if (! (this instanceof
1326
Processing)) throw "called Processing constructor as if it were a function: missing 'new'.";
1327
var curElement, pgraphicsMode = aCanvas === undef && aCode === undef;
1328
if (pgraphicsMode) curElement = document.createElement("canvas");
1329
else curElement = typeof aCanvas === "string" ? document.getElementById(aCanvas) : aCanvas;
1330
if (! (curElement instanceof HTMLCanvasElement)) throw "called Processing constructor without passing canvas element reference or id.";
1331
1332
function unimplemented(s) {
1333
Processing.debug("Unimplemented - " + s)
1334
}
1335
var p = this;
1336
p.externals = {
1337
canvas: curElement,
1338
context: undef,
1339
sketch: undef
1340
};
1341
p.name = "Processing.js Instance";
1342
p.use3DContext = false;
1343
p.focused = false;
1344
p.breakShape = false;
1345
p.glyphTable = {};
1346
p.pmouseX = 0;
1347
p.pmouseY = 0;
1348
p.mouseX = 0;
1349
p.mouseY = 0;
1350
p.mouseButton = 0;
1351
p.mouseScroll = 0;
1352
p.mouseClicked = undef;
1353
p.mouseDragged = undef;
1354
p.mouseMoved = undef;
1355
p.mousePressed = undef;
1356
p.mouseReleased = undef;
1357
p.mouseScrolled = undef;
1358
p.mouseOver = undef;
1359
p.mouseOut = undef;
1360
p.touchStart = undef;
1361
p.touchEnd = undef;
1362
p.touchMove = undef;
1363
p.touchCancel = undef;
1364
p.key = undef;
1365
p.keyCode = undef;
1366
p.keyPressed = nop;
1367
p.keyReleased = nop;
1368
p.keyTyped = nop;
1369
p.draw = undef;
1370
p.setup = undef;
1371
p.__mousePressed = false;
1372
p.__keyPressed = false;
1373
p.__frameRate = 60;
1374
p.frameCount = 0;
1375
p.width = 100;
1376
p.height = 100;
1377
var curContext, curSketch, drawing, online = true,
1378
doFill = true,
1379
fillStyle = [1, 1, 1, 1],
1380
currentFillColor = 4294967295,
1381
isFillDirty = true,
1382
doStroke = true,
1383
strokeStyle = [0, 0, 0, 1],
1384
currentStrokeColor = 4278190080,
1385
isStrokeDirty = true,
1386
lineWidth = 1,
1387
loopStarted = false,
1388
renderSmooth = false,
1389
doLoop = true,
1390
looping = 0,
1391
curRectMode = 0,
1392
curEllipseMode = 3,
1393
normalX = 0,
1394
normalY = 0,
1395
normalZ = 0,
1396
normalMode = 0,
1397
curFrameRate = 60,
1398
curMsPerFrame = 1E3 / curFrameRate,
1399
curCursor = 'default',
1400
oldCursor = curElement.style.cursor,
1401
curShape = 20,
1402
curShapeCount = 0,
1403
curvePoints = [],
1404
curTightness = 0,
1405
curveDet = 20,
1406
curveInited = false,
1407
backgroundObj = -3355444,
1408
bezDetail = 20,
1409
colorModeA = 255,
1410
colorModeX = 255,
1411
colorModeY = 255,
1412
colorModeZ = 255,
1413
pathOpen = false,
1414
mouseDragging = false,
1415
pmouseXLastFrame = 0,
1416
pmouseYLastFrame = 0,
1417
curColorMode = 1,
1418
curTint = null,
1419
curTint3d = null,
1420
getLoaded = false,
1421
start = Date.now(),
1422
timeSinceLastFPS = start,
1423
framesSinceLastFPS = 0,
1424
textcanvas, curveBasisMatrix, curveToBezierMatrix, curveDrawMatrix, bezierDrawMatrix, bezierBasisInverse, bezierBasisMatrix, curContextCache = {
1425
attributes: {},
1426
locations: {}
1427
},
1428
programObject3D, programObject2D, programObjectUnlitShape, boxBuffer, boxNormBuffer, boxOutlineBuffer, rectBuffer, rectNormBuffer, sphereBuffer, lineBuffer, fillBuffer, fillColorBuffer, strokeColorBuffer, pointBuffer, shapeTexVBO, canTex, textTex, curTexture = {
1429
width: 0,
1430
height: 0
1431
},
1432
curTextureMode = 2,
1433
usingTexture = false,
1434
textBuffer, textureBuffer, indexBuffer, horizontalTextAlignment = 37,
1435
verticalTextAlignment = 0,
1436
textMode = 4,
1437
curFontName = "Arial",
1438
curTextSize = 12,
1439
curTextAscent = 9,
1440
curTextDescent = 2,
1441
curTextLeading = 14,
1442
curTextFont = PFont.get(curFontName, curTextSize),
1443
originalContext, proxyContext = null,
1444
isContextReplaced = false,
1445
setPixelsCached, maxPixelsCached = 1E3,
1446
pressedKeysMap = [],
1447
lastPressedKeyCode = null,
1448
codedKeys = [16,
1449
17, 18, 20, 33, 34, 35, 36, 37, 38, 39, 40, 144, 155, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 157];
1450
var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop;
1451
if (document.defaultView && document.defaultView.getComputedStyle) {
1452
stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(curElement, null)["paddingLeft"], 10) || 0;
1453
stylePaddingTop = parseInt(document.defaultView.getComputedStyle(curElement, null)["paddingTop"], 10) || 0;
1454
styleBorderLeft = parseInt(document.defaultView.getComputedStyle(curElement, null)["borderLeftWidth"], 10) || 0;
1455
styleBorderTop = parseInt(document.defaultView.getComputedStyle(curElement, null)["borderTopWidth"], 10) || 0
1456
}
1457
var lightCount = 0;
1458
var sphereDetailV = 0,
1459
sphereDetailU = 0,
1460
sphereX = [],
1461
sphereY = [],
1462
sphereZ = [],
1463
sinLUT = new Float32Array(720),
1464
cosLUT = new Float32Array(720),
1465
sphereVerts, sphereNorms;
1466
var cam, cameraInv, modelView, modelViewInv, userMatrixStack, userReverseMatrixStack, inverseCopy, projection, manipulatingCamera = false,
1467
frustumMode = false,
1468
cameraFOV = 60 * (Math.PI / 180),
1469
cameraX = p.width / 2,
1470
cameraY = p.height / 2,
1471
cameraZ = cameraY / Math.tan(cameraFOV / 2),
1472
cameraNear = cameraZ / 10,
1473
cameraFar = cameraZ * 10,
1474
cameraAspect = p.width / p.height;
1475
var vertArray = [],
1476
curveVertArray = [],
1477
curveVertCount = 0,
1478
isCurve = false,
1479
isBezier = false,
1480
firstVert = true;
1481
var curShapeMode = 0;
1482
var styleArray = [];
1483
var boxVerts = new Float32Array([0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5,
1484
0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5]);
1485
var boxOutlineVerts = new Float32Array([0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5]);
1486
var boxNorms = new Float32Array([0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0,
1487
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0]);
1488
var rectVerts = new Float32Array([0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0]);
1489
var rectNorms = new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]);
1490
var vertexShaderSrcUnlitShape = "varying vec4 vFrontColor;" + "attribute vec3 aVertex;" + "attribute vec4 aColor;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform float uPointSize;" + "void main(void) {" + " vFrontColor = aColor;" + " gl_PointSize = uPointSize;" + " gl_Position = uProjection * uView * vec4(aVertex, 1.0);" + "}";
1491
var fragmentShaderSrcUnlitShape = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 vFrontColor;" + "uniform bool uSmooth;" + "void main(void){" + " if(uSmooth == true){" + " float dist = distance(gl_PointCoord, vec2(0.5));" + " if(dist > 0.5){" + " discard;" + " }" + " }" + " gl_FragColor = vFrontColor;" + "}";
1492
var vertexShaderSrc2D = "varying vec4 vFrontColor;" + "attribute vec3 aVertex;" + "attribute vec2 aTextureCoord;" + "uniform vec4 uColor;" + "uniform mat4 uModel;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform float uPointSize;" + "varying vec2 vTextureCoord;" + "void main(void) {" + " gl_PointSize = uPointSize;" + " vFrontColor = uColor;" + " gl_Position = uProjection * uView * uModel * vec4(aVertex, 1.0);" + " vTextureCoord = aTextureCoord;" + "}";
1493
var fragmentShaderSrc2D = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 vFrontColor;" + "varying vec2 vTextureCoord;" + "uniform sampler2D uSampler;" + "uniform int uIsDrawingText;" + "uniform bool uSmooth;" + "void main(void){" + " if(uSmooth == true){" + " float dist = distance(gl_PointCoord, vec2(0.5));" + " if(dist > 0.5){" + " discard;" + " }" + " }" + " if(uIsDrawingText == 1){" + " float alpha = texture2D(uSampler, vTextureCoord).a;" + " gl_FragColor = vec4(vFrontColor.rgb * alpha, alpha);" + " }" + " else{" + " gl_FragColor = vFrontColor;" + " }" + "}";
1494
var webglMaxTempsWorkaround = /Windows/.test(navigator.userAgent);
1495
var vertexShaderSrc3D = "varying vec4 vFrontColor;" + "attribute vec3 aVertex;" + "attribute vec3 aNormal;" + "attribute vec4 aColor;" + "attribute vec2 aTexture;" + "varying vec2 vTexture;" + "uniform vec4 uColor;" + "uniform bool uUsingMat;" + "uniform vec3 uSpecular;" + "uniform vec3 uMaterialEmissive;" + "uniform vec3 uMaterialAmbient;" + "uniform vec3 uMaterialSpecular;" + "uniform float uShininess;" + "uniform mat4 uModel;" + "uniform mat4 uView;" + "uniform mat4 uProjection;" + "uniform mat4 uNormalTransform;" + "uniform int uLightCount;" + "uniform vec3 uFalloff;" + "struct Light {" + " int type;" + " vec3 color;" + " vec3 position;" + " vec3 direction;" + " float angle;" + " vec3 halfVector;" + " float concentration;" + "};" + "uniform Light uLights0;" + "uniform Light uLights1;" + "uniform Light uLights2;" + "uniform Light uLights3;" + "uniform Light uLights4;" + "uniform Light uLights5;" + "uniform Light uLights6;" + "uniform Light uLights7;" + "Light getLight(int index){" + " if(index == 0) return uLights0;" + " if(index == 1) return uLights1;" + " if(index == 2) return uLights2;" + " if(index == 3) return uLights3;" + " if(index == 4) return uLights4;" + " if(index == 5) return uLights5;" + " if(index == 6) return uLights6;" + " return uLights7;" + "}" + "void AmbientLight( inout vec3 totalAmbient, in vec3 ecPos, in Light light ) {" + " float d = length( light.position - ecPos );" + " float attenuation = 1.0 / ( uFalloff[0] + ( uFalloff[1] * d ) + ( uFalloff[2] * d * d ));" + " totalAmbient += light.color * attenuation;" + "}" + "void DirectionalLight( inout vec3 col, inout vec3 spec, in vec3 vertNormal, in vec3 ecPos, in Light light ) {" + " float powerFactor = 0.0;" + " float nDotVP = max(0.0, dot( vertNormal, normalize(-light.position) ));" + " float nDotVH = max(0.0, dot( vertNormal, normalize(-light.position-normalize(ecPos) )));" + " if( nDotVP != 0.0 ){" + " powerFactor = pow( nDotVH, uShininess );" + " }" + " col += light.color * nDotVP;" + " spec += uSpecular * powerFactor;" + "}" + "void PointLight( inout vec3 col, inout vec3 spec, in vec3 vertNormal, in vec3 ecPos, in Light light ) {" + " float powerFactor;" + " vec3 VP = light.position - ecPos;" + " float d = length( VP ); " + " VP = normalize( VP );" + " float attenuation = 1.0 / ( uFalloff[0] + ( uFalloff[1] * d ) + ( uFalloff[2] * d * d ));" + " float nDotVP = max( 0.0, dot( vertNormal, VP ));" + " vec3 halfVector = normalize( VP - normalize(ecPos) );" + " float nDotHV = max( 0.0, dot( vertNormal, halfVector ));" + " if( nDotVP == 0.0 ) {" + " powerFactor = 0.0;" + " }" + " else {" + " powerFactor = pow( nDotHV, uShininess );" + " }" + " spec += uSpecular * powerFactor * attenuation;" + " col += light.color * nDotVP * attenuation;" + "}" + "void SpotLight( inout vec3 col, inout vec3 spec, in vec3 vertNormal, in vec3 ecPos, in Light light ) {" + " float spotAttenuation;" + " float powerFactor = 0.0;" + " vec3 VP = light.position - ecPos;" + " vec3 ldir = normalize( -light.direction );" + " float d = length( VP );" + " VP = normalize( VP );" + " float attenuation = 1.0 / ( uFalloff[0] + ( uFalloff[1] * d ) + ( uFalloff[2] * d * d ) );" + " float spotDot = dot( VP, ldir );" + (webglMaxTempsWorkaround ? " spotAttenuation = 1.0; " : " if( spotDot > cos( light.angle ) ) {" + " spotAttenuation = pow( spotDot, light.concentration );" + " }" + " else{" + " spotAttenuation = 0.0;" + " }" + " attenuation *= spotAttenuation;" + "") + " float nDotVP = max( 0.0, dot( vertNormal, VP ) );" + " vec3 halfVector = normalize( VP - normalize(ecPos) );" + " float nDotHV = max( 0.0, dot( vertNormal, halfVector ) );" + " if( nDotVP != 0.0 ) {" + " powerFactor = pow( nDotHV, uShininess );" + " }" + " spec += uSpecular * powerFactor * attenuation;" + " col += light.color * nDotVP * attenuation;" + "}" + "void main(void) {" + " vec3 finalAmbient = vec3( 0.0 );" + " vec3 finalDiffuse = vec3( 0.0 );" + " vec3 finalSpecular = vec3( 0.0 );" + " vec4 col = uColor;" + " if ( uColor[0] == -1.0 ){" + " col = aColor;" + " }" + " vec3 norm = normalize(vec3( uNormalTransform * vec4( aNormal, 0.0 ) ));" + " vec4 ecPos4 = uView * uModel * vec4(aVertex, 1.0);" + " vec3 ecPos = (vec3(ecPos4))/ecPos4.w;" + " if( uLightCount == 0 ) {" + " vFrontColor = col + vec4(uMaterialSpecular, 1.0);" + " }" + " else {" + " for( int i = 0; i < 8; i++ ) {" + " Light l = getLight(i);" + " if( i >= uLightCount ){" + " break;" + " }" + " if( l.type == 0 ) {" + " AmbientLight( finalAmbient, ecPos, l );" + " }" + " else if( l.type == 1 ) {" + " DirectionalLight( finalDiffuse, finalSpecular, norm, ecPos, l );" + " }" + " else if( l.type == 2 ) {" + " PointLight( finalDiffuse, finalSpecular, norm, ecPos, l );" + " }" + " else {" + " SpotLight( finalDiffuse, finalSpecular, norm, ecPos, l );" + " }" + " }" + " if( uUsingMat == false ) {" + " vFrontColor = vec4(" + " vec3( col ) * finalAmbient +" + " vec3( col ) * finalDiffuse +" + " vec3( col ) * finalSpecular," + " col[3] );" + " }" + " else{" + " vFrontColor = vec4( " + " uMaterialEmissive + " + " (vec3(col) * uMaterialAmbient * finalAmbient ) + " + " (vec3(col) * finalDiffuse) + " + " (uMaterialSpecular * finalSpecular), " + " col[3] );" + " }" + " }" + " vTexture.xy = aTexture.xy;" + " gl_Position = uProjection * uView * uModel * vec4( aVertex, 1.0 );" + "}";
1496
var fragmentShaderSrc3D = "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "varying vec4 vFrontColor;" + "uniform sampler2D uSampler;" + "uniform bool uUsingTexture;" + "varying vec2 vTexture;" + "void main(void){" + " if( uUsingTexture ){" + " gl_FragColor = vec4(texture2D(uSampler, vTexture.xy)) * vFrontColor;" + " }" + " else{" + " gl_FragColor = vFrontColor;" + " }" + "}";
1497
1498
function uniformf(cacheId, programObj, varName, varValue) {
1499
var varLocation = curContextCache.locations[cacheId];
1500
if (varLocation === undef) {
1501
varLocation = curContext.getUniformLocation(programObj, varName);
1502
curContextCache.locations[cacheId] = varLocation
1503
}
1504
if (varLocation !== null) if (varValue.length === 4) curContext.uniform4fv(varLocation, varValue);
1505
else if (varValue.length === 3) curContext.uniform3fv(varLocation, varValue);
1506
else if (varValue.length === 2) curContext.uniform2fv(varLocation, varValue);
1507
else curContext.uniform1f(varLocation, varValue)
1508
}
1509
function uniformi(cacheId, programObj, varName, varValue) {
1510
var varLocation = curContextCache.locations[cacheId];
1511
if (varLocation === undef) {
1512
varLocation = curContext.getUniformLocation(programObj, varName);
1513
curContextCache.locations[cacheId] = varLocation
1514
}
1515
if (varLocation !== null) if (varValue.length === 4) curContext.uniform4iv(varLocation, varValue);
1516
else if (varValue.length === 3) curContext.uniform3iv(varLocation, varValue);
1517
else if (varValue.length === 2) curContext.uniform2iv(varLocation, varValue);
1518
else curContext.uniform1i(varLocation, varValue)
1519
}
1520
function uniformMatrix(cacheId, programObj, varName, transpose, matrix) {
1521
var varLocation = curContextCache.locations[cacheId];
1522
if (varLocation === undef) {
1523
varLocation = curContext.getUniformLocation(programObj, varName);
1524
curContextCache.locations[cacheId] = varLocation
1525
}
1526
if (varLocation !== -1) if (matrix.length === 16) curContext.uniformMatrix4fv(varLocation, transpose, matrix);
1527
else if (matrix.length === 9) curContext.uniformMatrix3fv(varLocation, transpose, matrix);
1528
else curContext.uniformMatrix2fv(varLocation, transpose, matrix)
1529
}
1530
function vertexAttribPointer(cacheId, programObj, varName, size, VBO) {
1531
var varLocation = curContextCache.attributes[cacheId];
1532
if (varLocation === undef) {
1533
varLocation = curContext.getAttribLocation(programObj, varName);
1534
curContextCache.attributes[cacheId] = varLocation
1535
}
1536
if (varLocation !== -1) {
1537
curContext.bindBuffer(curContext.ARRAY_BUFFER, VBO);
1538
curContext.vertexAttribPointer(varLocation, size, curContext.FLOAT, false, 0, 0);
1539
curContext.enableVertexAttribArray(varLocation)
1540
}
1541
}
1542
function disableVertexAttribPointer(cacheId, programObj, varName) {
1543
var varLocation = curContextCache.attributes[cacheId];
1544
if (varLocation === undef) {
1545
varLocation = curContext.getAttribLocation(programObj, varName);
1546
curContextCache.attributes[cacheId] = varLocation
1547
}
1548
if (varLocation !== -1) curContext.disableVertexAttribArray(varLocation)
1549
}
1550
var createProgramObject = function(curContext, vetexShaderSource, fragmentShaderSource) {
1551
var vertexShaderObject = curContext.createShader(curContext.VERTEX_SHADER);
1552
curContext.shaderSource(vertexShaderObject, vetexShaderSource);
1553
curContext.compileShader(vertexShaderObject);
1554
if (!curContext.getShaderParameter(vertexShaderObject, curContext.COMPILE_STATUS)) throw curContext.getShaderInfoLog(vertexShaderObject);
1555
var fragmentShaderObject = curContext.createShader(curContext.FRAGMENT_SHADER);
1556
curContext.shaderSource(fragmentShaderObject, fragmentShaderSource);
1557
curContext.compileShader(fragmentShaderObject);
1558
if (!curContext.getShaderParameter(fragmentShaderObject, curContext.COMPILE_STATUS)) throw curContext.getShaderInfoLog(fragmentShaderObject);
1559
var programObject = curContext.createProgram();
1560
curContext.attachShader(programObject, vertexShaderObject);
1561
curContext.attachShader(programObject, fragmentShaderObject);
1562
curContext.linkProgram(programObject);
1563
if (!curContext.getProgramParameter(programObject, curContext.LINK_STATUS)) throw "Error linking shaders.";
1564
return programObject
1565
};
1566
var imageModeCorner = function(x, y, w, h, whAreSizes) {
1567
return {
1568
x: x,
1569
y: y,
1570
w: w,
1571
h: h
1572
}
1573
};
1574
var imageModeConvert = imageModeCorner;
1575
var imageModeCorners = function(x, y, w, h, whAreSizes) {
1576
return {
1577
x: x,
1578
y: y,
1579
w: whAreSizes ? w : w - x,
1580
h: whAreSizes ? h : h - y
1581
}
1582
};
1583
var imageModeCenter = function(x, y, w, h, whAreSizes) {
1584
return {
1585
x: x - w / 2,
1586
y: y - h / 2,
1587
w: w,
1588
h: h
1589
}
1590
};
1591
var DrawingShared = function() {};
1592
var Drawing2D = function() {};
1593
var Drawing3D = function() {};
1594
var DrawingPre = function() {};
1595
Drawing2D.prototype = new DrawingShared;
1596
Drawing2D.prototype.constructor = Drawing2D;
1597
Drawing3D.prototype = new DrawingShared;
1598
Drawing3D.prototype.constructor = Drawing3D;
1599
DrawingPre.prototype = new DrawingShared;
1600
DrawingPre.prototype.constructor = DrawingPre;
1601
DrawingShared.prototype.a3DOnlyFunction = nop;
1602
var charMap = {};
1603
var Char = p.Character = function(chr) {
1604
if (typeof chr === "string" && chr.length === 1) this.code = chr.charCodeAt(0);
1605
else if (typeof chr === "number") this.code = chr;
1606
else if (chr instanceof Char) this.code = chr;
1607
else this.code = NaN;
1608
return charMap[this.code] === undef ? charMap[this.code] = this : charMap[this.code]
1609
};
1610
Char.prototype.toString = function() {
1611
return String.fromCharCode(this.code)
1612
};
1613
Char.prototype.valueOf = function() {
1614
return this.code
1615
};
1616
var PShape = p.PShape = function(family) {
1617
this.family = family || 0;
1618
this.visible = true;
1619
this.style = true;
1620
this.children = [];
1621
this.nameTable = [];
1622
this.params = [];
1623
this.name = "";
1624
this.image = null;
1625
this.matrix = null;
1626
this.kind = null;
1627
this.close = null;
1628
this.width = null;
1629
this.height = null;
1630
this.parent = null
1631
};
1632
PShape.prototype = {
1633
isVisible: function() {
1634
return this.visible
1635
},
1636
setVisible: function(visible) {
1637
this.visible = visible
1638
},
1639
disableStyle: function() {
1640
this.style = false;
1641
for (var i = 0, j = this.children.length; i < j; i++) this.children[i].disableStyle()
1642
},
1643
enableStyle: function() {
1644
this.style = true;
1645
for (var i = 0, j = this.children.length; i < j; i++) this.children[i].enableStyle()
1646
},
1647
getFamily: function() {
1648
return this.family
1649
},
1650
getWidth: function() {
1651
return this.width
1652
},
1653
getHeight: function() {
1654
return this.height
1655
},
1656
setName: function(name) {
1657
this.name = name
1658
},
1659
getName: function() {
1660
return this.name
1661
},
1662
draw: function(renderContext) {
1663
renderContext = renderContext || p;
1664
if (this.visible) {
1665
this.pre(renderContext);
1666
this.drawImpl(renderContext);
1667
this.post(renderContext)
1668
}
1669
},
1670
drawImpl: function(renderContext) {
1671
if (this.family === 0) this.drawGroup(renderContext);
1672
else if (this.family === 1) this.drawPrimitive(renderContext);
1673
else if (this.family === 3) this.drawGeometry(renderContext);
1674
else if (this.family === 21) this.drawPath(renderContext)
1675
},
1676
drawPath: function(renderContext) {
1677
var i, j;
1678
if (this.vertices.length === 0) return;
1679
renderContext.beginShape();
1680
if (this.vertexCodes.length === 0) if (this.vertices[0].length === 2) for (i = 0, j = this.vertices.length; i < j; i++) renderContext.vertex(this.vertices[i][0], this.vertices[i][1]);
1681
else for (i = 0, j = this.vertices.length; i < j; i++) renderContext.vertex(this.vertices[i][0], this.vertices[i][1], this.vertices[i][2]);
1682
else {
1683
var index = 0;
1684
if (this.vertices[0].length === 2) for (i = 0, j = this.vertexCodes.length; i < j; i++) if (this.vertexCodes[i] === 0) {
1685
renderContext.vertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index]["moveTo"]);
1686
renderContext.breakShape = false;
1687
index++
1688
} else if (this.vertexCodes[i] === 1) {
1689
renderContext.bezierVertex(this.vertices[index + 0][0], this.vertices[index + 0][1], this.vertices[index + 1][0], this.vertices[index + 1][1], this.vertices[index + 2][0], this.vertices[index + 2][1]);
1690
index += 3
1691
} else if (this.vertexCodes[i] === 2) {
1692
renderContext.curveVertex(this.vertices[index][0], this.vertices[index][1]);
1693
index++
1694
} else {
1695
if (this.vertexCodes[i] === 3) renderContext.breakShape = true
1696
} else for (i = 0, j = this.vertexCodes.length; i < j; i++) if (this.vertexCodes[i] === 0) {
1697
renderContext.vertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index][2]);
1698
if (this.vertices[index]["moveTo"] === true) vertArray[vertArray.length - 1]["moveTo"] = true;
1699
else if (this.vertices[index]["moveTo"] === false) vertArray[vertArray.length - 1]["moveTo"] = false;
1700
renderContext.breakShape = false
1701
} else if (this.vertexCodes[i] === 1) {
1702
renderContext.bezierVertex(this.vertices[index + 0][0], this.vertices[index + 0][1], this.vertices[index + 0][2], this.vertices[index + 1][0], this.vertices[index + 1][1], this.vertices[index + 1][2], this.vertices[index + 2][0], this.vertices[index + 2][1], this.vertices[index + 2][2]);
1703
index += 3
1704
} else if (this.vertexCodes[i] === 2) {
1705
renderContext.curveVertex(this.vertices[index][0], this.vertices[index][1], this.vertices[index][2]);
1706
index++
1707
} else if (this.vertexCodes[i] === 3) renderContext.breakShape = true
1708
}
1709
renderContext.endShape(this.close ? 2 : 1)
1710
},
1711
drawGeometry: function(renderContext) {
1712
var i, j;
1713
renderContext.beginShape(this.kind);
1714
if (this.style) for (i = 0, j = this.vertices.length; i < j; i++) renderContext.vertex(this.vertices[i]);
1715
else for (i = 0, j = this.vertices.length; i < j; i++) {
1716
var vert = this.vertices[i];
1717
if (vert[2] === 0) renderContext.vertex(vert[0], vert[1]);
1718
else renderContext.vertex(vert[0], vert[1], vert[2])
1719
}
1720
renderContext.endShape()
1721
},
1722
drawGroup: function(renderContext) {
1723
for (var i = 0, j = this.children.length; i < j; i++) this.children[i].draw(renderContext)
1724
},
1725
drawPrimitive: function(renderContext) {
1726
if (this.kind === 2) renderContext.point(this.params[0], this.params[1]);
1727
else if (this.kind === 4) if (this.params.length === 4) renderContext.line(this.params[0], this.params[1], this.params[2], this.params[3]);
1728
else renderContext.line(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]);
1729
else if (this.kind === 8) renderContext.triangle(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]);
1730
else if (this.kind === 16) renderContext.quad(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5], this.params[6], this.params[7]);
1731
else if (this.kind === 30) if (this.image !== null) {
1732
var imMode = imageModeConvert;
1733
renderContext.imageMode(0);
1734
renderContext.image(this.image, this.params[0], this.params[1], this.params[2], this.params[3]);
1735
imageModeConvert = imMode
1736
} else {
1737
var rcMode = curRectMode;
1738
renderContext.rectMode(0);
1739
renderContext.rect(this.params[0], this.params[1], this.params[2], this.params[3]);
1740
curRectMode = rcMode
1741
} else if (this.kind === 31) {
1742
var elMode = curEllipseMode;
1743
renderContext.ellipseMode(0);
1744
renderContext.ellipse(this.params[0], this.params[1], this.params[2], this.params[3]);
1745
curEllipseMode = elMode
1746
} else if (this.kind === 32) {
1747
var eMode = curEllipseMode;
1748
renderContext.ellipseMode(0);
1749
renderContext.arc(this.params[0], this.params[1], this.params[2], this.params[3], this.params[4], this.params[5]);
1750
curEllipseMode = eMode
1751
} else if (this.kind === 41) if (this.params.length === 1) renderContext.box(this.params[0]);
1752
else renderContext.box(this.params[0], this.params[1], this.params[2]);
1753
else if (this.kind === 40) renderContext.sphere(this.params[0])
1754
},
1755
pre: function(renderContext) {
1756
if (this.matrix) {
1757
renderContext.pushMatrix();
1758
renderContext.transform(this.matrix)
1759
}
1760
if (this.style) {
1761
renderContext.pushStyle();
1762
this.styles(renderContext)
1763
}
1764
},
1765
post: function(renderContext) {
1766
if (this.matrix) renderContext.popMatrix();
1767
if (this.style) renderContext.popStyle()
1768
},
1769
styles: function(renderContext) {
1770
if (this.stroke) {
1771
renderContext.stroke(this.strokeColor);
1772
renderContext.strokeWeight(this.strokeWeight);
1773
renderContext.strokeCap(this.strokeCap);
1774
renderContext.strokeJoin(this.strokeJoin)
1775
} else renderContext.noStroke();
1776
if (this.fill) renderContext.fill(this.fillColor);
1777
else renderContext.noFill()
1778
},
1779
getChild: function(child) {
1780
var i, j;
1781
if (typeof child === "number") return this.children[child];
1782
var found;
1783
if (child === "" || this.name === child) return this;
1784
if (this.nameTable.length > 0) {
1785
for (i = 0, j = this.nameTable.length; i < j || found; i++) if (this.nameTable[i].getName === child) {
1786
found = this.nameTable[i];
1787
break
1788
}
1789
if (found) return found
1790
}
1791
for (i = 0, j = this.children.length; i < j; i++) {
1792
found = this.children[i].getChild(child);
1793
if (found) return found
1794
}
1795
return null
1796
},
1797
getChildCount: function() {
1798
return this.children.length
1799
},
1800
addChild: function(child) {
1801
this.children.push(child);
1802
child.parent = this;
1803
if (child.getName() !== null) this.addName(child.getName(), child)
1804
},
1805
addName: function(name, shape) {
1806
if (this.parent !== null) this.parent.addName(name, shape);
1807
else this.nameTable.push([name, shape])
1808
},
1809
translate: function() {
1810
if (arguments.length === 2) {
1811
this.checkMatrix(2);
1812
this.matrix.translate(arguments[0], arguments[1])
1813
} else {
1814
this.checkMatrix(3);
1815
this.matrix.translate(arguments[0], arguments[1], 0)
1816
}
1817
},
1818
checkMatrix: function(dimensions) {
1819
if (this.matrix === null) if (dimensions === 2) this.matrix = new p.PMatrix2D;
1820
else this.matrix = new p.PMatrix3D;
1821
else if (dimensions === 3 && this.matrix instanceof p.PMatrix2D) this.matrix = new p.PMatrix3D
1822
},
1823
rotateX: function(angle) {
1824
this.rotate(angle, 1, 0, 0)
1825
},
1826
rotateY: function(angle) {
1827
this.rotate(angle, 0, 1, 0)
1828
},
1829
rotateZ: function(angle) {
1830
this.rotate(angle, 0, 0, 1)
1831
},
1832
rotate: function() {
1833
if (arguments.length === 1) {
1834
this.checkMatrix(2);
1835
this.matrix.rotate(arguments[0])
1836
} else {
1837
this.checkMatrix(3);
1838
this.matrix.rotate(arguments[0], arguments[1], arguments[2], arguments[3])
1839
}
1840
},
1841
scale: function() {
1842
if (arguments.length === 2) {
1843
this.checkMatrix(2);
1844
this.matrix.scale(arguments[0], arguments[1])
1845
} else if (arguments.length === 3) {
1846
this.checkMatrix(2);
1847
this.matrix.scale(arguments[0], arguments[1], arguments[2])
1848
} else {
1849
this.checkMatrix(2);
1850
this.matrix.scale(arguments[0])
1851
}
1852
},
1853
resetMatrix: function() {
1854
this.checkMatrix(2);
1855
this.matrix.reset()
1856
},
1857
applyMatrix: function(matrix) {
1858
if (arguments.length === 1) this.applyMatrix(matrix.elements[0], matrix.elements[1], 0, matrix.elements[2], matrix.elements[3], matrix.elements[4], 0, matrix.elements[5], 0, 0, 1, 0, 0, 0, 0, 1);
1859
else if (arguments.length === 6) {
1860
this.checkMatrix(2);
1861
this.matrix.apply(arguments[0], arguments[1], arguments[2], 0, arguments[3], arguments[4], arguments[5], 0, 0, 0, 1, 0, 0, 0, 0, 1)
1862
} else if (arguments.length === 16) {
1863
this.checkMatrix(3);
1864
this.matrix.apply(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11], arguments[12], arguments[13], arguments[14], arguments[15])
1865
}
1866
}
1867
};
1868
var PShapeSVG = p.PShapeSVG = function() {
1869
p.PShape.call(this);
1870
if (arguments.length === 1) {
1871
this.element = arguments[0];
1872
this.vertexCodes = [];
1873
this.vertices = [];
1874
this.opacity = 1;
1875
this.stroke = false;
1876
this.strokeColor = 4278190080;
1877
this.strokeWeight = 1;
1878
this.strokeCap = 'butt';
1879
this.strokeJoin = 'miter';
1880
this.strokeGradient = null;
1881
this.strokeGradientPaint = null;
1882
this.strokeName = null;
1883
this.strokeOpacity = 1;
1884
this.fill = true;
1885
this.fillColor = 4278190080;
1886
this.fillGradient = null;
1887
this.fillGradientPaint = null;
1888
this.fillName = null;
1889
this.fillOpacity = 1;
1890
if (this.element.getName() !== "svg") throw "root is not <svg>, it's <" + this.element.getName() + ">";
1891
} else if (arguments.length === 2) if (typeof arguments[1] === "string") {
1892
if (arguments[1].indexOf(".svg") > -1) {
1893
this.element = new p.XMLElement(p, arguments[1]);
1894
this.vertexCodes = [];
1895
this.vertices = [];
1896
this.opacity = 1;
1897
this.stroke = false;
1898
this.strokeColor = 4278190080;
1899
this.strokeWeight = 1;
1900
this.strokeCap = 'butt';
1901
this.strokeJoin = 'miter';
1902
this.strokeGradient = "";
1903
this.strokeGradientPaint = "";
1904
this.strokeName = "";
1905
this.strokeOpacity = 1;
1906
this.fill = true;
1907
this.fillColor = 4278190080;
1908
this.fillGradient = null;
1909
this.fillGradientPaint = null;
1910
this.fillOpacity = 1
1911
}
1912
} else if (arguments[0]) {
1913
this.element = arguments[1];
1914
this.vertexCodes = arguments[0].vertexCodes.slice();
1915
this.vertices = arguments[0].vertices.slice();
1916
this.stroke = arguments[0].stroke;
1917
this.strokeColor = arguments[0].strokeColor;
1918
this.strokeWeight = arguments[0].strokeWeight;
1919
this.strokeCap = arguments[0].strokeCap;
1920
this.strokeJoin = arguments[0].strokeJoin;
1921
this.strokeGradient = arguments[0].strokeGradient;
1922
this.strokeGradientPaint = arguments[0].strokeGradientPaint;
1923
this.strokeName = arguments[0].strokeName;
1924
this.fill = arguments[0].fill;
1925
this.fillColor = arguments[0].fillColor;
1926
this.fillGradient = arguments[0].fillGradient;
1927
this.fillGradientPaint = arguments[0].fillGradientPaint;
1928
this.fillName = arguments[0].fillName;
1929
this.strokeOpacity = arguments[0].strokeOpacity;
1930
this.fillOpacity = arguments[0].fillOpacity;
1931
this.opacity = arguments[0].opacity
1932
}
1933
this.name = this.element.getStringAttribute("id");
1934
var displayStr = this.element.getStringAttribute("display", "inline");
1935
this.visible = displayStr !== "none";
1936
var str = this.element.getAttribute("transform");
1937
if (str) this.matrix = this.parseMatrix(str);
1938
var viewBoxStr = this.element.getStringAttribute("viewBox");
1939
if (viewBoxStr !== null) {
1940
var viewBox = viewBoxStr.split(" ");
1941
this.width = viewBox[2];
1942
this.height = viewBox[3]
1943
}
1944
var unitWidth = this.element.getStringAttribute("width");
1945
var unitHeight = this.element.getStringAttribute("height");
1946
if (unitWidth !== null) {
1947
this.width = this.parseUnitSize(unitWidth);
1948
this.height = this.parseUnitSize(unitHeight)
1949
} else if (this.width === 0 || this.height === 0) {
1950
this.width = 1;
1951
this.height = 1;
1952
throw "The width and/or height is not " + "readable in the <svg> tag of this file.";
1953
}
1954
this.parseColors(this.element);
1955
this.parseChildren(this.element)
1956
};
1957
PShapeSVG.prototype = new PShape;
1958
PShapeSVG.prototype.parseMatrix = function() {
1959
function getCoords(s) {
1960
var m = [];
1961
s.replace(/\((.*?)\)/, function() {
1962
return function(all, params) {
1963
m = params.replace(/,+/g, " ").split(/\s+/)
1964
}
1965
}());
1966
return m
1967
}
1968
return function(str) {
1969
this.checkMatrix(2);
1970
var pieces = [];
1971
str.replace(/\s*(\w+)\((.*?)\)/g, function(all) {
1972
pieces.push(p.trim(all))
1973
});
1974
if (pieces.length === 0) return null;
1975
for (var i = 0, j = pieces.length; i < j; i++) {
1976
var m = getCoords(pieces[i]);
1977
if (pieces[i].indexOf("matrix") !== -1) this.matrix.set(m[0], m[2], m[4], m[1], m[3], m[5]);
1978
else if (pieces[i].indexOf("translate") !== -1) {
1979
var tx = m[0];
1980
var ty = m.length === 2 ? m[1] : 0;
1981
this.matrix.translate(tx, ty)
1982
} else if (pieces[i].indexOf("scale") !== -1) {
1983
var sx = m[0];
1984
var sy = m.length === 2 ? m[1] : m[0];
1985
this.matrix.scale(sx, sy)
1986
} else if (pieces[i].indexOf("rotate") !== -1) {
1987
var angle = m[0];
1988
if (m.length === 1) this.matrix.rotate(p.radians(angle));
1989
else if (m.length === 3) {
1990
this.matrix.translate(m[1], m[2]);
1991
this.matrix.rotate(p.radians(m[0]));
1992
this.matrix.translate(-m[1], -m[2])
1993
}
1994
} else if (pieces[i].indexOf("skewX") !== -1) this.matrix.skewX(parseFloat(m[0]));
1995
else if (pieces[i].indexOf("skewY") !== -1) this.matrix.skewY(m[0]);
1996
else if (pieces[i].indexOf("shearX") !== -1) this.matrix.shearX(m[0]);
1997
else if (pieces[i].indexOf("shearY") !== -1) this.matrix.shearY(m[0])
1998
}
1999
return this.matrix
2000
}
2001
}();
2002
PShapeSVG.prototype.parseChildren = function(element) {
2003
var newelement = element.getChildren();
2004
var children = new p.PShape;
2005
for (var i = 0, j = newelement.length; i < j; i++) {
2006
var kid = this.parseChild(newelement[i]);
2007
if (kid) children.addChild(kid)
2008
}
2009
this.children.push(children)
2010
};
2011
PShapeSVG.prototype.getName = function() {
2012
return this.name
2013
};
2014
PShapeSVG.prototype.parseChild = function(elem) {
2015
var name = elem.getName();
2016
var shape;
2017
if (name === "g") shape = new PShapeSVG(this, elem);
2018
else if (name === "defs") shape = new PShapeSVG(this, elem);
2019
else if (name === "line") {
2020
shape = new PShapeSVG(this, elem);
2021
shape.parseLine()
2022
} else if (name === "circle") {
2023
shape = new PShapeSVG(this, elem);
2024
shape.parseEllipse(true)
2025
} else if (name === "ellipse") {
2026
shape = new PShapeSVG(this, elem);
2027
shape.parseEllipse(false)
2028
} else if (name === "rect") {
2029
shape = new PShapeSVG(this, elem);
2030
shape.parseRect()
2031
} else if (name === "polygon") {
2032
shape = new PShapeSVG(this, elem);
2033
shape.parsePoly(true)
2034
} else if (name === "polyline") {
2035
shape = new PShapeSVG(this, elem);
2036
shape.parsePoly(false)
2037
} else if (name === "path") {
2038
shape = new PShapeSVG(this, elem);
2039
shape.parsePath()
2040
} else if (name === "radialGradient") unimplemented("PShapeSVG.prototype.parseChild, name = radialGradient");
2041
else if (name === "linearGradient") unimplemented("PShapeSVG.prototype.parseChild, name = linearGradient");
2042
else if (name === "text") unimplemented("PShapeSVG.prototype.parseChild, name = text");
2043
else if (name === "filter") unimplemented("PShapeSVG.prototype.parseChild, name = filter");
2044
else if (name === "mask") unimplemented("PShapeSVG.prototype.parseChild, name = mask");
2045
else nop();
2046
return shape
2047
};
2048
PShapeSVG.prototype.parsePath = function() {
2049
this.family = 21;
2050
this.kind = 0;
2051
var pathDataChars = [];
2052
var c;
2053
var pathData = p.trim(this.element.getStringAttribute("d").replace(/[\s,]+/g, " "));
2054
if (pathData === null) return;
2055
pathData = p.__toCharArray(pathData);
2056
var cx = 0,
2057
cy = 0,
2058
ctrlX = 0,
2059
ctrlY = 0,
2060
ctrlX1 = 0,
2061
ctrlX2 = 0,
2062
ctrlY1 = 0,
2063
ctrlY2 = 0,
2064
endX = 0,
2065
endY = 0,
2066
ppx = 0,
2067
ppy = 0,
2068
px = 0,
2069
py = 0,
2070
i = 0,
2071
valOf = 0;
2072
var str = "";
2073
var tmpArray = [];
2074
var flag = false;
2075
var lastInstruction;
2076
var command;
2077
var j, k;
2078
while (i < pathData.length) {
2079
valOf = pathData[i].valueOf();
2080
if (valOf >= 65 && valOf <= 90 || valOf >= 97 && valOf <= 122) {
2081
j = i;
2082
i++;
2083
if (i < pathData.length) {
2084
tmpArray = [];
2085
valOf = pathData[i].valueOf();
2086
while (! (valOf >= 65 && valOf <= 90 || valOf >= 97 && valOf <= 100 || valOf >= 102 && valOf <= 122) && flag === false) {
2087
if (valOf === 32) {
2088
if (str !== "") {
2089
tmpArray.push(parseFloat(str));
2090
str = ""
2091
}
2092
i++
2093
} else if (valOf === 45) if (pathData[i - 1].valueOf() === 101) {
2094
str += pathData[i].toString();
2095
i++
2096
} else {
2097
if (str !== "") tmpArray.push(parseFloat(str));
2098
str = pathData[i].toString();
2099
i++
2100
} else {
2101
str += pathData[i].toString();
2102
i++
2103
}
2104
if (i === pathData.length) flag = true;
2105
else valOf = pathData[i].valueOf()
2106
}
2107
}
2108
if (str !== "") {
2109
tmpArray.push(parseFloat(str));
2110
str = ""
2111
}
2112
command = pathData[j];
2113
valOf = command.valueOf();
2114
if (valOf === 77) {
2115
if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) {
2116
cx = tmpArray[0];
2117
cy = tmpArray[1];
2118
this.parsePathMoveto(cx, cy);
2119
if (tmpArray.length > 2) for (j = 2, k = tmpArray.length; j < k; j += 2) {
2120
cx = tmpArray[j];
2121
cy = tmpArray[j + 1];
2122
this.parsePathLineto(cx, cy)
2123
}
2124
}
2125
} else if (valOf === 109) {
2126
if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) {
2127
cx += tmpArray[0];
2128
cy += tmpArray[1];
2129
this.parsePathMoveto(cx, cy);
2130
if (tmpArray.length > 2) for (j = 2, k = tmpArray.length; j < k; j += 2) {
2131
cx += tmpArray[j];
2132
cy += tmpArray[j + 1];
2133
this.parsePathLineto(cx, cy)
2134
}
2135
}
2136
} else if (valOf === 76) {
2137
if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) {
2138
cx = tmpArray[j];
2139
cy = tmpArray[j + 1];
2140
this.parsePathLineto(cx, cy)
2141
}
2142
} else if (valOf === 108) {
2143
if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) {
2144
cx += tmpArray[j];
2145
cy += tmpArray[j + 1];
2146
this.parsePathLineto(cx, cy)
2147
}
2148
} else if (valOf === 72) for (j = 0, k = tmpArray.length; j < k; j++) {
2149
cx = tmpArray[j];
2150
this.parsePathLineto(cx, cy)
2151
} else if (valOf === 104) for (j = 0, k = tmpArray.length; j < k; j++) {
2152
cx += tmpArray[j];
2153
this.parsePathLineto(cx, cy)
2154
} else if (valOf === 86) for (j = 0, k = tmpArray.length; j < k; j++) {
2155
cy = tmpArray[j];
2156
this.parsePathLineto(cx, cy)
2157
} else if (valOf === 118) for (j = 0, k = tmpArray.length; j < k; j++) {
2158
cy += tmpArray[j];
2159
this.parsePathLineto(cx, cy)
2160
} else if (valOf === 67) {
2161
if (tmpArray.length >= 6 && tmpArray.length % 6 === 0) for (j = 0, k = tmpArray.length; j < k; j += 6) {
2162
ctrlX1 = tmpArray[j];
2163
ctrlY1 = tmpArray[j + 1];
2164
ctrlX2 = tmpArray[j + 2];
2165
ctrlY2 = tmpArray[j + 3];
2166
endX = tmpArray[j + 4];
2167
endY = tmpArray[j + 5];
2168
this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
2169
cx = endX;
2170
cy = endY
2171
}
2172
} else if (valOf === 99) {
2173
if (tmpArray.length >= 6 && tmpArray.length % 6 === 0) for (j = 0, k = tmpArray.length; j < k; j += 6) {
2174
ctrlX1 = cx + tmpArray[j];
2175
ctrlY1 = cy + tmpArray[j + 1];
2176
ctrlX2 = cx + tmpArray[j + 2];
2177
ctrlY2 = cy + tmpArray[j + 3];
2178
endX = cx + tmpArray[j + 4];
2179
endY = cy + tmpArray[j + 5];
2180
this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
2181
cx = endX;
2182
cy = endY
2183
}
2184
} else if (valOf === 83) {
2185
if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) {
2186
if (lastInstruction.toLowerCase() === "c" || lastInstruction.toLowerCase() === "s") {
2187
ppx = this.vertices[this.vertices.length - 2][0];
2188
ppy = this.vertices[this.vertices.length - 2][1];
2189
px = this.vertices[this.vertices.length - 1][0];
2190
py = this.vertices[this.vertices.length - 1][1];
2191
ctrlX1 = px + (px - ppx);
2192
ctrlY1 = py + (py - ppy)
2193
} else {
2194
ctrlX1 = this.vertices[this.vertices.length - 1][0];
2195
ctrlY1 = this.vertices[this.vertices.length - 1][1]
2196
}
2197
ctrlX2 = tmpArray[j];
2198
ctrlY2 = tmpArray[j + 1];
2199
endX = tmpArray[j + 2];
2200
endY = tmpArray[j + 3];
2201
this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
2202
cx = endX;
2203
cy = endY
2204
}
2205
} else if (valOf === 115) {
2206
if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) {
2207
if (lastInstruction.toLowerCase() === "c" || lastInstruction.toLowerCase() === "s") {
2208
ppx = this.vertices[this.vertices.length - 2][0];
2209
ppy = this.vertices[this.vertices.length - 2][1];
2210
px = this.vertices[this.vertices.length - 1][0];
2211
py = this.vertices[this.vertices.length - 1][1];
2212
ctrlX1 = px + (px - ppx);
2213
ctrlY1 = py + (py - ppy)
2214
} else {
2215
ctrlX1 = this.vertices[this.vertices.length - 1][0];
2216
ctrlY1 = this.vertices[this.vertices.length - 1][1]
2217
}
2218
ctrlX2 = cx + tmpArray[j];
2219
ctrlY2 = cy + tmpArray[j + 1];
2220
endX = cx + tmpArray[j + 2];
2221
endY = cy + tmpArray[j + 3];
2222
this.parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
2223
cx = endX;
2224
cy = endY
2225
}
2226
} else if (valOf === 81) {
2227
if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) {
2228
ctrlX = tmpArray[j];
2229
ctrlY = tmpArray[j + 1];
2230
endX = tmpArray[j + 2];
2231
endY = tmpArray[j + 3];
2232
this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);
2233
cx = endX;
2234
cy = endY
2235
}
2236
} else if (valOf === 113) {
2237
if (tmpArray.length >= 4 && tmpArray.length % 4 === 0) for (j = 0, k = tmpArray.length; j < k; j += 4) {
2238
ctrlX = cx + tmpArray[j];
2239
ctrlY = cy + tmpArray[j + 1];
2240
endX = cx + tmpArray[j + 2];
2241
endY = cy + tmpArray[j + 3];
2242
this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);
2243
cx = endX;
2244
cy = endY
2245
}
2246
} else if (valOf === 84) {
2247
if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) {
2248
if (lastInstruction.toLowerCase() === "q" || lastInstruction.toLowerCase() === "t") {
2249
ppx = this.vertices[this.vertices.length - 2][0];
2250
ppy = this.vertices[this.vertices.length - 2][1];
2251
px = this.vertices[this.vertices.length - 1][0];
2252
py = this.vertices[this.vertices.length - 1][1];
2253
ctrlX = px + (px - ppx);
2254
ctrlY = py + (py - ppy)
2255
} else {
2256
ctrlX = cx;
2257
ctrlY = cy
2258
}
2259
endX = tmpArray[j];
2260
endY = tmpArray[j + 1];
2261
this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);
2262
cx = endX;
2263
cy = endY
2264
}
2265
} else if (valOf === 116) {
2266
if (tmpArray.length >= 2 && tmpArray.length % 2 === 0) for (j = 0, k = tmpArray.length; j < k; j += 2) {
2267
if (lastInstruction.toLowerCase() === "q" || lastInstruction.toLowerCase() === "t") {
2268
ppx = this.vertices[this.vertices.length - 2][0];
2269
ppy = this.vertices[this.vertices.length - 2][1];
2270
px = this.vertices[this.vertices.length - 1][0];
2271
py = this.vertices[this.vertices.length - 1][1];
2272
ctrlX = px + (px - ppx);
2273
ctrlY = py + (py - ppy)
2274
} else {
2275
ctrlX = cx;
2276
ctrlY = cy
2277
}
2278
endX = cx + tmpArray[j];
2279
endY = cy + tmpArray[j + 1];
2280
this.parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);
2281
cx = endX;
2282
cy = endY
2283
}
2284
} else if (valOf === 90 || valOf === 122) this.close = true;
2285
lastInstruction = command.toString()
2286
} else i++
2287
}
2288
};
2289
PShapeSVG.prototype.parsePathQuadto = function(x1, y1, cx, cy, x2, y2) {
2290
if (this.vertices.length > 0) {
2291
this.parsePathCode(1);
2292
this.parsePathVertex(x1 + (cx - x1) * 2 / 3, y1 + (cy - y1) * 2 / 3);
2293
this.parsePathVertex(x2 + (cx - x2) * 2 / 3, y2 + (cy - y2) * 2 / 3);
2294
this.parsePathVertex(x2, y2)
2295
} else throw "Path must start with M/m";
2296
};
2297
PShapeSVG.prototype.parsePathCurveto = function(x1, y1, x2, y2, x3, y3) {
2298
if (this.vertices.length > 0) {
2299
this.parsePathCode(1);
2300
this.parsePathVertex(x1, y1);
2301
this.parsePathVertex(x2, y2);
2302
this.parsePathVertex(x3, y3)
2303
} else throw "Path must start with M/m";
2304
};
2305
PShapeSVG.prototype.parsePathLineto = function(px, py) {
2306
if (this.vertices.length > 0) {
2307
this.parsePathCode(0);
2308
this.parsePathVertex(px, py);
2309
this.vertices[this.vertices.length - 1]["moveTo"] = false
2310
} else throw "Path must start with M/m";
2311
};
2312
PShapeSVG.prototype.parsePathMoveto = function(px, py) {
2313
if (this.vertices.length > 0) this.parsePathCode(3);
2314
this.parsePathCode(0);
2315
this.parsePathVertex(px, py);
2316
this.vertices[this.vertices.length - 1]["moveTo"] = true
2317
};
2318
PShapeSVG.prototype.parsePathVertex = function(x, y) {
2319
var verts = [];
2320
verts[0] = x;
2321
verts[1] = y;
2322
this.vertices.push(verts)
2323
};
2324
PShapeSVG.prototype.parsePathCode = function(what) {
2325
this.vertexCodes.push(what)
2326
};
2327
PShapeSVG.prototype.parsePoly = function(val) {
2328
this.family = 21;
2329
this.close = val;
2330
var pointsAttr = p.trim(this.element.getStringAttribute("points").replace(/[,\s]+/g, " "));
2331
if (pointsAttr !== null) {
2332
var pointsBuffer = pointsAttr.split(" ");
2333
if (pointsBuffer.length % 2 === 0) for (var i = 0, j = pointsBuffer.length; i < j; i++) {
2334
var verts = [];
2335
verts[0] = pointsBuffer[i];
2336
verts[1] = pointsBuffer[++i];
2337
this.vertices.push(verts)
2338
} else throw "Error parsing polygon points: odd number of coordinates provided";
2339
}
2340
};
2341
PShapeSVG.prototype.parseRect = function() {
2342
this.kind = 30;
2343
this.family = 1;
2344
this.params = [];
2345
this.params[0] = this.element.getFloatAttribute("x");
2346
this.params[1] = this.element.getFloatAttribute("y");
2347
this.params[2] = this.element.getFloatAttribute("width");
2348
this.params[3] = this.element.getFloatAttribute("height");
2349
if (this.params[2] < 0 || this.params[3] < 0) throw "svg error: negative width or height found while parsing <rect>";
2350
};
2351
PShapeSVG.prototype.parseEllipse = function(val) {
2352
this.kind = 31;
2353
this.family = 1;
2354
this.params = [];
2355
this.params[0] = this.element.getFloatAttribute("cx") | 0;
2356
this.params[1] = this.element.getFloatAttribute("cy") | 0;
2357
var rx, ry;
2358
if (val) {
2359
rx = ry = this.element.getFloatAttribute("r");
2360
if (rx < 0) throw "svg error: negative radius found while parsing <circle>";
2361
} else {
2362
rx = this.element.getFloatAttribute("rx");
2363
ry = this.element.getFloatAttribute("ry");
2364
if (rx < 0 || ry < 0) throw "svg error: negative x-axis radius or y-axis radius found while parsing <ellipse>";
2365
}
2366
this.params[0] -= rx;
2367
this.params[1] -= ry;
2368
this.params[2] = rx * 2;
2369
this.params[3] = ry * 2
2370
};
2371
PShapeSVG.prototype.parseLine = function() {
2372
this.kind = 4;
2373
this.family = 1;
2374
this.params = [];
2375
this.params[0] = this.element.getFloatAttribute("x1");
2376
this.params[1] = this.element.getFloatAttribute("y1");
2377
this.params[2] = this.element.getFloatAttribute("x2");
2378
this.params[3] = this.element.getFloatAttribute("y2")
2379
};
2380
PShapeSVG.prototype.parseColors = function(element) {
2381
if (element.hasAttribute("opacity")) this.setOpacity(element.getAttribute("opacity"));
2382
if (element.hasAttribute("stroke")) this.setStroke(element.getAttribute("stroke"));
2383
if (element.hasAttribute("stroke-width")) this.setStrokeWeight(element.getAttribute("stroke-width"));
2384
if (element.hasAttribute("stroke-linejoin")) this.setStrokeJoin(element.getAttribute("stroke-linejoin"));
2385
if (element.hasAttribute("stroke-linecap")) this.setStrokeCap(element.getStringAttribute("stroke-linecap"));
2386
if (element.hasAttribute("fill")) this.setFill(element.getStringAttribute("fill"));
2387
if (element.hasAttribute("style")) {
2388
var styleText = element.getStringAttribute("style");
2389
var styleTokens = styleText.toString().split(";");
2390
for (var i = 0, j = styleTokens.length; i < j; i++) {
2391
var tokens = p.trim(styleTokens[i].split(":"));
2392
if (tokens[0] === "fill") this.setFill(tokens[1]);
2393
else if (tokens[0] === "fill-opacity") this.setFillOpacity(tokens[1]);
2394
else if (tokens[0] === "stroke") this.setStroke(tokens[1]);
2395
else if (tokens[0] === "stroke-width") this.setStrokeWeight(tokens[1]);
2396
else if (tokens[0] === "stroke-linecap") this.setStrokeCap(tokens[1]);
2397
else if (tokens[0] === "stroke-linejoin") this.setStrokeJoin(tokens[1]);
2398
else if (tokens[0] === "stroke-opacity") this.setStrokeOpacity(tokens[1]);
2399
else if (tokens[0] === "opacity") this.setOpacity(tokens[1])
2400
}
2401
}
2402
};
2403
PShapeSVG.prototype.setFillOpacity = function(opacityText) {
2404
this.fillOpacity = parseFloat(opacityText);
2405
this.fillColor = this.fillOpacity * 255 << 24 | this.fillColor & 16777215
2406
};
2407
PShapeSVG.prototype.setFill = function(fillText) {
2408
var opacityMask = this.fillColor & 4278190080;
2409
if (fillText === "none") this.fill = false;
2410
else if (fillText.indexOf("#") === 0) {
2411
this.fill = true;
2412
if (fillText.length === 4) fillText = fillText.replace(/#(.)(.)(.)/, "#$1$1$2$2$3$3");
2413
this.fillColor = opacityMask | parseInt(fillText.substring(1), 16) & 16777215
2414
} else if (fillText.indexOf("rgb") === 0) {
2415
this.fill = true;
2416
this.fillColor = opacityMask | this.parseRGB(fillText)
2417
} else if (fillText.indexOf("url(#") === 0) this.fillName = fillText.substring(5, fillText.length - 1);
2418
else if (colors[fillText]) {
2419
this.fill = true;
2420
this.fillColor = opacityMask | parseInt(colors[fillText].substring(1), 16) & 16777215
2421
}
2422
};
2423
PShapeSVG.prototype.setOpacity = function(opacity) {
2424
this.strokeColor = parseFloat(opacity) * 255 << 24 | this.strokeColor & 16777215;
2425
this.fillColor = parseFloat(opacity) * 255 << 24 | this.fillColor & 16777215
2426
};
2427
PShapeSVG.prototype.setStroke = function(strokeText) {
2428
var opacityMask = this.strokeColor & 4278190080;
2429
if (strokeText === "none") this.stroke = false;
2430
else if (strokeText.charAt(0) === "#") {
2431
this.stroke = true;
2432
if (strokeText.length === 4) strokeText = strokeText.replace(/#(.)(.)(.)/, "#$1$1$2$2$3$3");
2433
this.strokeColor = opacityMask | parseInt(strokeText.substring(1), 16) & 16777215
2434
} else if (strokeText.indexOf("rgb") === 0) {
2435
this.stroke = true;
2436
this.strokeColor = opacityMask | this.parseRGB(strokeText)
2437
} else if (strokeText.indexOf("url(#") === 0) this.strokeName = strokeText.substring(5, strokeText.length - 1);
2438
else if (colors[strokeText]) {
2439
this.stroke = true;
2440
this.strokeColor = opacityMask | parseInt(colors[strokeText].substring(1), 16) & 16777215
2441
}
2442
};
2443
PShapeSVG.prototype.setStrokeWeight = function(weight) {
2444
this.strokeWeight = this.parseUnitSize(weight)
2445
};
2446
PShapeSVG.prototype.setStrokeJoin = function(linejoin) {
2447
if (linejoin === "miter") this.strokeJoin = 'miter';
2448
else if (linejoin === "round") this.strokeJoin = 'round';
2449
else if (linejoin === "bevel") this.strokeJoin = 'bevel'
2450
};
2451
PShapeSVG.prototype.setStrokeCap = function(linecap) {
2452
if (linecap === "butt") this.strokeCap = 'butt';
2453
else if (linecap === "round") this.strokeCap = 'round';
2454
else if (linecap === "square") this.strokeCap = 'square'
2455
};
2456
PShapeSVG.prototype.setStrokeOpacity = function(opacityText) {
2457
this.strokeOpacity = parseFloat(opacityText);
2458
this.strokeColor = this.strokeOpacity * 255 << 24 | this.strokeColor & 16777215
2459
};
2460
PShapeSVG.prototype.parseRGB = function(color) {
2461
var sub = color.substring(color.indexOf("(") + 1, color.indexOf(")"));
2462
var values = sub.split(", ");
2463
return values[0] << 16 | values[1] << 8 | values[2]
2464
};
2465
PShapeSVG.prototype.parseUnitSize = function(text) {
2466
var len = text.length - 2;
2467
if (len < 0) return text;
2468
if (text.indexOf("pt") === len) return parseFloat(text.substring(0, len)) * 1.25;
2469
if (text.indexOf("pc") === len) return parseFloat(text.substring(0, len)) * 15;
2470
if (text.indexOf("mm") === len) return parseFloat(text.substring(0, len)) * 3.543307;
2471
if (text.indexOf("cm") === len) return parseFloat(text.substring(0, len)) * 35.43307;
2472
if (text.indexOf("in") === len) return parseFloat(text.substring(0, len)) * 90;
2473
if (text.indexOf("px") === len) return parseFloat(text.substring(0, len));
2474
return parseFloat(text)
2475
};
2476
p.shape = function(shape, x, y, width, height) {
2477
if (arguments.length >= 1 && arguments[0] !== null) if (shape.isVisible()) {
2478
p.pushMatrix();
2479
if (curShapeMode === 3) if (arguments.length === 5) {
2480
p.translate(x - width / 2, y - height / 2);
2481
p.scale(width / shape.getWidth(), height / shape.getHeight())
2482
} else if (arguments.length === 3) p.translate(x - shape.getWidth() / 2, -shape.getHeight() / 2);
2483
else p.translate(-shape.getWidth() / 2, -shape.getHeight() / 2);
2484
else if (curShapeMode === 0) if (arguments.length === 5) {
2485
p.translate(x, y);
2486
p.scale(width / shape.getWidth(), height / shape.getHeight())
2487
} else {
2488
if (arguments.length === 3) p.translate(x, y)
2489
} else if (curShapeMode === 1) if (arguments.length === 5) {
2490
width -= x;
2491
height -= y;
2492
p.translate(x, y);
2493
p.scale(width / shape.getWidth(), height / shape.getHeight())
2494
} else if (arguments.length === 3) p.translate(x, y);
2495
shape.draw(p);
2496
if (arguments.length === 1 && curShapeMode === 3 || arguments.length > 1) p.popMatrix()
2497
}
2498
};
2499
p.shapeMode = function(mode) {
2500
curShapeMode = mode
2501
};
2502
p.loadShape = function(filename) {
2503
if (arguments.length === 1) if (filename.indexOf(".svg") > -1) return new PShapeSVG(null, filename);
2504
return null
2505
};
2506
var XMLAttribute = function(fname, n, nameSpace, v, t) {
2507
this.fullName = fname || "";
2508
this.name = n || "";
2509
this.namespace = nameSpace || "";
2510
this.value = v;
2511
this.type = t
2512
};
2513
XMLAttribute.prototype = {
2514
getName: function() {
2515
return this.name
2516
},
2517
getFullName: function() {
2518
return this.fullName
2519
},
2520
getNamespace: function() {
2521
return this.namespace
2522
},
2523
getValue: function() {
2524
return this.value
2525
},
2526
getType: function() {
2527
return this.type
2528
},
2529
setValue: function(newval) {
2530
this.value = newval
2531
}
2532
};
2533
var XMLElement = p.XMLElement = function(selector, uri, sysid, line) {
2534
this.attributes = [];
2535
this.children = [];
2536
this.fullName = null;
2537
this.name = null;
2538
this.namespace = "";
2539
this.content = null;
2540
this.parent = null;
2541
this.lineNr = "";
2542
this.systemID = "";
2543
this.type = "ELEMENT";
2544
if (selector) if (typeof selector === "string") if (uri === undef && selector.indexOf("<") > -1) this.parse(selector);
2545
else {
2546
this.fullName = selector;
2547
this.namespace = uri;
2548
this.systemId = sysid;
2549
this.lineNr = line
2550
} else this.parse(uri)
2551
};
2552
XMLElement.prototype = {
2553
parse: function(textstring) {
2554
var xmlDoc;
2555
try {
2556
var extension = textstring.substring(textstring.length - 4);
2557
if (extension === ".xml" || extension === ".svg") textstring = ajax(textstring);
2558
xmlDoc = (new DOMParser).parseFromString(textstring, "text/xml");
2559
var elements = xmlDoc.documentElement;
2560
if (elements) this.parseChildrenRecursive(null, elements);
2561
else throw "Error loading document";
2562
return this
2563
} catch(e) {
2564
throw e;
2565
}
2566
},
2567
parseChildrenRecursive: function(parent, elementpath) {
2568
var xmlelement, xmlattribute, tmpattrib, l, m, child;
2569
if (!parent) {
2570
this.fullName = elementpath.localName;
2571
this.name = elementpath.nodeName;
2572
xmlelement = this
2573
} else {
2574
xmlelement = new XMLElement(elementpath.nodeName);
2575
xmlelement.parent = parent
2576
}
2577
if (elementpath.nodeType === 3 && elementpath.textContent !== "") return this.createPCDataElement(elementpath.textContent);
2578
if (elementpath.nodeType === 4) return this.createCDataElement(elementpath.textContent);
2579
if (elementpath.attributes) for (l = 0, m = elementpath.attributes.length; l < m; l++) {
2580
tmpattrib = elementpath.attributes[l];
2581
xmlattribute = new XMLAttribute(tmpattrib.getname, tmpattrib.nodeName, tmpattrib.namespaceURI, tmpattrib.nodeValue, tmpattrib.nodeType);
2582
xmlelement.attributes.push(xmlattribute)
2583
}
2584
if (elementpath.childNodes) for (l = 0, m = elementpath.childNodes.length; l < m; l++) {
2585
var node = elementpath.childNodes[l];
2586
child = xmlelement.parseChildrenRecursive(xmlelement, node);
2587
if (child !== null) xmlelement.children.push(child)
2588
}
2589
return xmlelement
2590
},
2591
createElement: function(fullname, namespaceuri, sysid, line) {
2592
if (sysid === undef) return new XMLElement(fullname, namespaceuri);
2593
return new XMLElement(fullname, namespaceuri, sysid, line)
2594
},
2595
createPCDataElement: function(content, isCDATA) {
2596
if (content.replace(/^\s+$/g, "") === "") return null;
2597
var pcdata = new XMLElement;
2598
pcdata.type = "TEXT";
2599
pcdata.content = content;
2600
return pcdata
2601
},
2602
createCDataElement: function(content) {
2603
var cdata = this.createPCDataElement(content);
2604
if (cdata === null) return null;
2605
cdata.type = "CDATA";
2606
var htmlentities = {
2607
"<": "&lt;",
2608
">": "&gt;",
2609
"'": "&apos;",
2610
'"': "&quot;"
2611
},
2612
entity;
2613
for (entity in htmlentities) if (!Object.hasOwnProperty(htmlentities, entity)) content = content.replace(new RegExp(entity, "g"), htmlentities[entity]);
2614
cdata.cdata = content;
2615
return cdata
2616
},
2617
hasAttribute: function() {
2618
if (arguments.length === 1) return this.getAttribute(arguments[0]) !== null;
2619
if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]) !== null
2620
},
2621
equals: function(other) {
2622
if (! (other instanceof XMLElement)) return false;
2623
var i, j;
2624
if (this.fullName !== other.fullName) return false;
2625
if (this.attributes.length !== other.getAttributeCount()) return false;
2626
if (this.attributes.length !== other.attributes.length) return false;
2627
var attr_name, attr_ns, attr_value, attr_type, attr_other;
2628
for (i = 0, j = this.attributes.length; i < j; i++) {
2629
attr_name = this.attributes[i].getName();
2630
attr_ns = this.attributes[i].getNamespace();
2631
attr_other = other.findAttribute(attr_name, attr_ns);
2632
if (attr_other === null) return false;
2633
if (this.attributes[i].getValue() !== attr_other.getValue()) return false;
2634
if (this.attributes[i].getType() !== attr_other.getType()) return false
2635
}
2636
if (this.children.length !== other.getChildCount()) return false;
2637
if (this.children.length > 0) {
2638
var child1, child2;
2639
for (i = 0, j = this.children.length; i < j; i++) {
2640
child1 = this.getChild(i);
2641
child2 = other.getChild(i);
2642
if (!child1.equals(child2)) return false
2643
}
2644
return true
2645
}
2646
return this.content === other.content
2647
},
2648
getContent: function() {
2649
if (this.type === "TEXT" || this.type === "CDATA") return this.content;
2650
var children = this.children;
2651
if (children.length === 1 && (children[0].type === "TEXT" || children[0].type === "CDATA")) return children[0].content;
2652
return null
2653
},
2654
getAttribute: function() {
2655
var attribute;
2656
if (arguments.length === 2) {
2657
attribute = this.findAttribute(arguments[0]);
2658
if (attribute) return attribute.getValue();
2659
return arguments[1]
2660
} else if (arguments.length === 1) {
2661
attribute = this.findAttribute(arguments[0]);
2662
if (attribute) return attribute.getValue();
2663
return null
2664
} else if (arguments.length === 3) {
2665
attribute = this.findAttribute(arguments[0], arguments[1]);
2666
if (attribute) return attribute.getValue();
2667
return arguments[2]
2668
}
2669
},
2670
getStringAttribute: function() {
2671
if (arguments.length === 1) return this.getAttribute(arguments[0]);
2672
if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]);
2673
return this.getAttribute(arguments[0], arguments[1], arguments[2])
2674
},
2675
getString: function(attributeName) {
2676
return this.getStringAttribute(attributeName)
2677
},
2678
getFloatAttribute: function() {
2679
if (arguments.length === 1) return parseFloat(this.getAttribute(arguments[0], 0));
2680
if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]);
2681
return this.getAttribute(arguments[0], arguments[1], arguments[2])
2682
},
2683
getFloat: function(attributeName) {
2684
return this.getFloatAttribute(attributeName)
2685
},
2686
getIntAttribute: function() {
2687
if (arguments.length === 1) return this.getAttribute(arguments[0], 0);
2688
if (arguments.length === 2) return this.getAttribute(arguments[0], arguments[1]);
2689
return this.getAttribute(arguments[0], arguments[1], arguments[2])
2690
},
2691
getInt: function(attributeName) {
2692
return this.getIntAttribute(attributeName)
2693
},
2694
hasChildren: function() {
2695
return this.children.length > 0
2696
},
2697
addChild: function(child) {
2698
if (child !== null) {
2699
child.parent = this;
2700
this.children.push(child)
2701
}
2702
},
2703
insertChild: function(child, index) {
2704
if (child) {
2705
if (child.getLocalName() === null && !this.hasChildren()) {
2706
var lastChild = this.children[this.children.length - 1];
2707
if (lastChild.getLocalName() === null) {
2708
lastChild.setContent(lastChild.getContent() + child.getContent());
2709
return
2710
}
2711
}
2712
child.parent = this;
2713
this.children.splice(index, 0, child)
2714
}
2715
},
2716
getChild: function(selector) {
2717
if (typeof selector === "number") return this.children[selector];
2718
if (selector.indexOf("/") !== -1) return this.getChildRecursive(selector.split("/"), 0);
2719
var kid, kidName;
2720
for (var i = 0, j = this.getChildCount(); i < j; i++) {
2721
kid = this.getChild(i);
2722
kidName = kid.getName();
2723
if (kidName !== null && kidName === selector) return kid
2724
}
2725
return null
2726
},
2727
getChildren: function() {
2728
if (arguments.length === 1) {
2729
if (typeof arguments[0] === "number") return this.getChild(arguments[0]);
2730
if (arguments[0].indexOf("/") !== -1) return this.getChildrenRecursive(arguments[0].split("/"), 0);
2731
var matches = [];
2732
var kid, kidName;
2733
for (var i = 0, j = this.getChildCount(); i < j; i++) {
2734
kid = this.getChild(i);
2735
kidName = kid.getName();
2736
if (kidName !== null && kidName === arguments[0]) matches.push(kid)
2737
}
2738
return matches
2739
}
2740
return this.children
2741
},
2742
getChildCount: function() {
2743
return this.children.length
2744
},
2745
getChildRecursive: function(items, offset) {
2746
if (offset === items.length) return this;
2747
var kid, kidName, matchName = items[offset];
2748
for (var i = 0, j = this.getChildCount(); i < j; i++) {
2749
kid = this.getChild(i);
2750
kidName = kid.getName();
2751
if (kidName !== null && kidName === matchName) return kid.getChildRecursive(items, offset + 1)
2752
}
2753
return null
2754
},
2755
getChildrenRecursive: function(items, offset) {
2756
if (offset === items.length - 1) return this.getChildren(items[offset]);
2757
var matches = this.getChildren(items[offset]);
2758
var kidMatches = [];
2759
for (var i = 0; i < matches.length; i++) kidMatches = kidMatches.concat(matches[i].getChildrenRecursive(items, offset + 1));
2760
return kidMatches
2761
},
2762
isLeaf: function() {
2763
return !this.hasChildren()
2764
},
2765
listChildren: function() {
2766
var arr = [];
2767
for (var i = 0, j = this.children.length; i < j; i++) arr.push(this.getChild(i).getName());
2768
return arr
2769
},
2770
removeAttribute: function(name, namespace) {
2771
this.namespace = namespace || "";
2772
for (var i = 0, j = this.attributes.length; i < j; i++) if (this.attributes[i].getName() === name && this.attributes[i].getNamespace() === this.namespace) {
2773
this.attributes.splice(i, 1);
2774
break
2775
}
2776
},
2777
removeChild: function(child) {
2778
if (child) for (var i = 0, j = this.children.length; i < j; i++) if (this.children[i].equals(child)) {
2779
this.children.splice(i, 1);
2780
break
2781
}
2782
},
2783
removeChildAtIndex: function(index) {
2784
if (this.children.length > index) this.children.splice(index, 1)
2785
},
2786
findAttribute: function(name, namespace) {
2787
this.namespace = namespace || "";
2788
for (var i = 0, j = this.attributes.length; i < j; i++) if (this.attributes[i].getName() === name && this.attributes[i].getNamespace() === this.namespace) return this.attributes[i];
2789
return null
2790
},
2791
setAttribute: function() {
2792
var attr;
2793
if (arguments.length === 3) {
2794
var index = arguments[0].indexOf(":");
2795
var name = arguments[0].substring(index + 1);
2796
attr = this.findAttribute(name, arguments[1]);
2797
if (attr) attr.setValue(arguments[2]);
2798
else {
2799
attr = new XMLAttribute(arguments[0], name, arguments[1], arguments[2], "CDATA");
2800
this.attributes.push(attr)
2801
}
2802
} else {
2803
attr = this.findAttribute(arguments[0]);
2804
if (attr) attr.setValue(arguments[1]);
2805
else {
2806
attr = new XMLAttribute(arguments[0], arguments[0], null, arguments[1], "CDATA");
2807
this.attributes.push(attr)
2808
}
2809
}
2810
},
2811
setString: function(attribute, value) {
2812
this.setAttribute(attribute, value)
2813
},
2814
setInt: function(attribute, value) {
2815
this.setAttribute(attribute, value)
2816
},
2817
setFloat: function(attribute, value) {
2818
this.setAttribute(attribute, value)
2819
},
2820
setContent: function(content) {
2821
if (this.children.length > 0) Processing.debug("Tried to set content for XMLElement with children");
2822
this.content = content
2823
},
2824
setName: function() {
2825
if (arguments.length === 1) {
2826
this.name = arguments[0];
2827
this.fullName = arguments[0];
2828
this.namespace = null
2829
} else {
2830
var index = arguments[0].indexOf(":");
2831
if (arguments[1] === null || index < 0) this.name = arguments[0];
2832
else this.name = arguments[0].substring(index + 1);
2833
this.fullName = arguments[0];
2834
this.namespace = arguments[1]
2835
}
2836
},
2837
getName: function() {
2838
return this.fullName
2839
},
2840
getLocalName: function() {
2841
return this.name
2842
},
2843
getAttributeCount: function() {
2844
return this.attributes.length
2845
},
2846
toString: function() {
2847
if (this.type === "TEXT") return this.content;
2848
if (this.type === "CDATA") return this.cdata;
2849
var tagstring = this.fullName;
2850
var xmlstring = "<" + tagstring;
2851
var a, c;
2852
for (a = 0; a < this.attributes.length; a++) {
2853
var attr = this.attributes[a];
2854
xmlstring += " " + attr.getName() + "=" + '"' + attr.getValue() + '"'
2855
}
2856
if (this.children.length === 0) if (this.content === "") xmlstring += "/>";
2857
else xmlstring += ">" + this.content + "</" + tagstring + ">";
2858
else {
2859
xmlstring += ">";
2860
for (c = 0; c < this.children.length; c++) xmlstring += this.children[c].toString();
2861
xmlstring += "</" + tagstring + ">"
2862
}
2863
return xmlstring
2864
}
2865
};
2866
XMLElement.parse = function(xmlstring) {
2867
var element = new XMLElement;
2868
element.parse(xmlstring);
2869
return element
2870
};
2871
var XML = p.XML = p.XMLElement;
2872
p.loadXML = function(uri) {
2873
return new XML(p, uri)
2874
};
2875
var printMatrixHelper = function(elements) {
2876
var big = 0;
2877
for (var i = 0; i < elements.length; i++) if (i !== 0) big = Math.max(big, Math.abs(elements[i]));
2878
else big = Math.abs(elements[i]);
2879
var digits = (big + "").indexOf(".");
2880
if (digits === 0) digits = 1;
2881
else if (digits === -1) digits = (big + "").length;
2882
return digits
2883
};
2884
var PMatrix2D = p.PMatrix2D = function() {
2885
if (arguments.length === 0) this.reset();
2886
else if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) this.set(arguments[0].array());
2887
else if (arguments.length === 6) this.set(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5])
2888
};
2889
PMatrix2D.prototype = {
2890
set: function() {
2891
if (arguments.length === 6) {
2892
var a = arguments;
2893
this.set([a[0], a[1], a[2], a[3], a[4], a[5]])
2894
} else if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) this.elements = arguments[0].array();
2895
else if (arguments.length === 1 && arguments[0] instanceof Array) this.elements = arguments[0].slice()
2896
},
2897
get: function() {
2898
var outgoing = new PMatrix2D;
2899
outgoing.set(this.elements);
2900
return outgoing
2901
},
2902
reset: function() {
2903
this.set([1, 0, 0, 0, 1, 0])
2904
},
2905
array: function array() {
2906
return this.elements.slice()
2907
},
2908
translate: function(tx, ty) {
2909
this.elements[2] = tx * this.elements[0] + ty * this.elements[1] + this.elements[2];
2910
this.elements[5] = tx * this.elements[3] + ty * this.elements[4] + this.elements[5]
2911
},
2912
invTranslate: function(tx, ty) {
2913
this.translate(-tx, -ty)
2914
},
2915
transpose: function() {},
2916
mult: function(source, target) {
2917
var x, y;
2918
if (source instanceof
2919
PVector) {
2920
x = source.x;
2921
y = source.y;
2922
if (!target) target = new PVector
2923
} else if (source instanceof Array) {
2924
x = source[0];
2925
y = source[1];
2926
if (!target) target = []
2927
}
2928
if (target instanceof Array) {
2929
target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2];
2930
target[1] = this.elements[3] * x + this.elements[4] * y + this.elements[5]
2931
} else if (target instanceof PVector) {
2932
target.x = this.elements[0] * x + this.elements[1] * y + this.elements[2];
2933
target.y = this.elements[3] * x + this.elements[4] * y + this.elements[5];
2934
target.z = 0
2935
}
2936
return target
2937
},
2938
multX: function(x, y) {
2939
return x * this.elements[0] + y * this.elements[1] + this.elements[2]
2940
},
2941
multY: function(x, y) {
2942
return x * this.elements[3] + y * this.elements[4] + this.elements[5]
2943
},
2944
skewX: function(angle) {
2945
this.apply(1, 0, 1, angle, 0, 0)
2946
},
2947
skewY: function(angle) {
2948
this.apply(1, 0, 1, 0, angle, 0)
2949
},
2950
shearX: function(angle) {
2951
this.apply(1, 0, 1, Math.tan(angle), 0, 0)
2952
},
2953
shearY: function(angle) {
2954
this.apply(1, 0, 1, 0, Math.tan(angle), 0)
2955
},
2956
determinant: function() {
2957
return this.elements[0] * this.elements[4] - this.elements[1] * this.elements[3]
2958
},
2959
invert: function() {
2960
var d = this.determinant();
2961
if (Math.abs(d) > -2147483648) {
2962
var old00 = this.elements[0];
2963
var old01 = this.elements[1];
2964
var old02 = this.elements[2];
2965
var old10 = this.elements[3];
2966
var old11 = this.elements[4];
2967
var old12 = this.elements[5];
2968
this.elements[0] = old11 / d;
2969
this.elements[3] = -old10 / d;
2970
this.elements[1] = -old01 / d;
2971
this.elements[4] = old00 / d;
2972
this.elements[2] = (old01 * old12 - old11 * old02) / d;
2973
this.elements[5] = (old10 * old02 - old00 * old12) / d;
2974
return true
2975
}
2976
return false
2977
},
2978
scale: function(sx, sy) {
2979
if (sx && !sy) sy = sx;
2980
if (sx && sy) {
2981
this.elements[0] *= sx;
2982
this.elements[1] *= sy;
2983
this.elements[3] *= sx;
2984
this.elements[4] *= sy
2985
}
2986
},
2987
invScale: function(sx, sy) {
2988
if (sx && !sy) sy = sx;
2989
this.scale(1 / sx, 1 / sy)
2990
},
2991
apply: function() {
2992
var source;
2993
if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) source = arguments[0].array();
2994
else if (arguments.length === 6) source = Array.prototype.slice.call(arguments);
2995
else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0];
2996
var result = [0, 0, this.elements[2], 0, 0, this.elements[5]];
2997
var e = 0;
2998
for (var row = 0; row < 2; row++) for (var col = 0; col < 3; col++, e++) result[e] += this.elements[row * 3 + 0] * source[col + 0] + this.elements[row * 3 + 1] * source[col + 3];
2999
this.elements = result.slice()
3000
},
3001
preApply: function() {
3002
var source;
3003
if (arguments.length === 1 && arguments[0] instanceof PMatrix2D) source = arguments[0].array();
3004
else if (arguments.length === 6) source = Array.prototype.slice.call(arguments);
3005
else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0];
3006
var result = [0, 0, source[2], 0, 0, source[5]];
3007
result[2] = source[2] + this.elements[2] * source[0] + this.elements[5] * source[1];
3008
result[5] = source[5] + this.elements[2] * source[3] + this.elements[5] * source[4];
3009
result[0] = this.elements[0] * source[0] + this.elements[3] * source[1];
3010
result[3] = this.elements[0] * source[3] + this.elements[3] * source[4];
3011
result[1] = this.elements[1] * source[0] + this.elements[4] * source[1];
3012
result[4] = this.elements[1] * source[3] + this.elements[4] * source[4];
3013
this.elements = result.slice()
3014
},
3015
rotate: function(angle) {
3016
var c = Math.cos(angle);
3017
var s = Math.sin(angle);
3018
var temp1 = this.elements[0];
3019
var temp2 = this.elements[1];
3020
this.elements[0] = c * temp1 + s * temp2;
3021
this.elements[1] = -s * temp1 + c * temp2;
3022
temp1 = this.elements[3];
3023
temp2 = this.elements[4];
3024
this.elements[3] = c * temp1 + s * temp2;
3025
this.elements[4] = -s * temp1 + c * temp2
3026
},
3027
rotateZ: function(angle) {
3028
this.rotate(angle)
3029
},
3030
invRotateZ: function(angle) {
3031
this.rotateZ(angle - Math.PI)
3032
},
3033
print: function() {
3034
var digits = printMatrixHelper(this.elements);
3035
var output = "" + p.nfs(this.elements[0], digits, 4) + " " + p.nfs(this.elements[1], digits, 4) + " " + p.nfs(this.elements[2], digits, 4) + "\n" + p.nfs(this.elements[3], digits, 4) + " " + p.nfs(this.elements[4], digits, 4) + " " + p.nfs(this.elements[5], digits, 4) + "\n\n";
3036
p.println(output)
3037
}
3038
};
3039
var PMatrix3D = p.PMatrix3D = function() {
3040
this.reset()
3041
};
3042
PMatrix3D.prototype = {
3043
set: function() {
3044
if (arguments.length === 16) this.elements = Array.prototype.slice.call(arguments);
3045
else if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) this.elements = arguments[0].array();
3046
else if (arguments.length === 1 && arguments[0] instanceof Array) this.elements = arguments[0].slice()
3047
},
3048
get: function() {
3049
var outgoing = new PMatrix3D;
3050
outgoing.set(this.elements);
3051
return outgoing
3052
},
3053
reset: function() {
3054
this.elements = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
3055
},
3056
array: function array() {
3057
return this.elements.slice()
3058
},
3059
translate: function(tx, ty, tz) {
3060
if (tz === undef) tz = 0;
3061
this.elements[3] += tx * this.elements[0] + ty * this.elements[1] + tz * this.elements[2];
3062
this.elements[7] += tx * this.elements[4] + ty * this.elements[5] + tz * this.elements[6];
3063
this.elements[11] += tx * this.elements[8] + ty * this.elements[9] + tz * this.elements[10];
3064
this.elements[15] += tx * this.elements[12] + ty * this.elements[13] + tz * this.elements[14]
3065
},
3066
transpose: function() {
3067
var temp = this.elements[4];
3068
this.elements[4] = this.elements[1];
3069
this.elements[1] = temp;
3070
temp = this.elements[8];
3071
this.elements[8] = this.elements[2];
3072
this.elements[2] = temp;
3073
temp = this.elements[6];
3074
this.elements[6] = this.elements[9];
3075
this.elements[9] = temp;
3076
temp = this.elements[3];
3077
this.elements[3] = this.elements[12];
3078
this.elements[12] = temp;
3079
temp = this.elements[7];
3080
this.elements[7] = this.elements[13];
3081
this.elements[13] = temp;
3082
temp = this.elements[11];
3083
this.elements[11] = this.elements[14];
3084
this.elements[14] = temp
3085
},
3086
mult: function(source, target) {
3087
var x, y, z, w;
3088
if (source instanceof
3089
PVector) {
3090
x = source.x;
3091
y = source.y;
3092
z = source.z;
3093
w = 1;
3094
if (!target) target = new PVector
3095
} else if (source instanceof Array) {
3096
x = source[0];
3097
y = source[1];
3098
z = source[2];
3099
w = source[3] || 1;
3100
if (!target || target.length !== 3 && target.length !== 4) target = [0, 0, 0]
3101
}
3102
if (target instanceof Array) if (target.length === 3) {
3103
target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3];
3104
target[1] = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7];
3105
target[2] = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11]
3106
} else if (target.length === 4) {
3107
target[0] = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3] * w;
3108
target[1] = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7] * w;
3109
target[2] = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] * w;
3110
target[3] = this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15] * w
3111
}
3112
if (target instanceof PVector) {
3113
target.x = this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3];
3114
target.y = this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7];
3115
target.z = this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11]
3116
}
3117
return target
3118
},
3119
preApply: function() {
3120
var source;
3121
if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) source = arguments[0].array();
3122
else if (arguments.length === 16) source = Array.prototype.slice.call(arguments);
3123
else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0];
3124
var result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
3125
var e = 0;
3126
for (var row = 0; row < 4; row++) for (var col = 0; col < 4; col++, e++) result[e] += this.elements[col + 0] * source[row * 4 + 0] + this.elements[col + 4] * source[row * 4 + 1] + this.elements[col + 8] * source[row * 4 + 2] + this.elements[col + 12] * source[row * 4 + 3];
3127
this.elements = result.slice()
3128
},
3129
apply: function() {
3130
var source;
3131
if (arguments.length === 1 && arguments[0] instanceof PMatrix3D) source = arguments[0].array();
3132
else if (arguments.length === 16) source = Array.prototype.slice.call(arguments);
3133
else if (arguments.length === 1 && arguments[0] instanceof Array) source = arguments[0];
3134
var result = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
3135
var e = 0;
3136
for (var row = 0; row < 4; row++) for (var col = 0; col < 4; col++, e++) result[e] += this.elements[row * 4 + 0] * source[col + 0] + this.elements[row * 4 + 1] * source[col + 4] + this.elements[row * 4 + 2] * source[col + 8] + this.elements[row * 4 + 3] * source[col + 12];
3137
this.elements = result.slice()
3138
},
3139
rotate: function(angle, v0, v1, v2) {
3140
if (!v1) this.rotateZ(angle);
3141
else {
3142
var c = p.cos(angle);
3143
var s = p.sin(angle);
3144
var t = 1 - c;
3145
this.apply(t * v0 * v0 + c, t * v0 * v1 - s * v2, t * v0 * v2 + s * v1, 0, t * v0 * v1 + s * v2, t * v1 * v1 + c, t * v1 * v2 - s * v0, 0, t * v0 * v2 - s * v1, t * v1 * v2 + s * v0, t * v2 * v2 + c, 0, 0, 0, 0, 1)
3146
}
3147
},
3148
invApply: function() {
3149
if (inverseCopy === undef) inverseCopy = new PMatrix3D;
3150
var a = arguments;
3151
inverseCopy.set(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);
3152
if (!inverseCopy.invert()) return false;
3153
this.preApply(inverseCopy);
3154
return true
3155
},
3156
rotateX: function(angle) {
3157
var c = p.cos(angle);
3158
var s = p.sin(angle);
3159
this.apply([1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1])
3160
},
3161
rotateY: function(angle) {
3162
var c = p.cos(angle);
3163
var s = p.sin(angle);
3164
this.apply([c,
3165
0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1])
3166
},
3167
rotateZ: function(angle) {
3168
var c = Math.cos(angle);
3169
var s = Math.sin(angle);
3170
this.apply([c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
3171
},
3172
scale: function(sx, sy, sz) {
3173
if (sx && !sy && !sz) sy = sz = sx;
3174
else if (sx && sy && !sz) sz = 1;
3175
if (sx && sy && sz) {
3176
this.elements[0] *= sx;
3177
this.elements[1] *= sy;
3178
this.elements[2] *= sz;
3179
this.elements[4] *= sx;
3180
this.elements[5] *= sy;
3181
this.elements[6] *= sz;
3182
this.elements[8] *= sx;
3183
this.elements[9] *= sy;
3184
this.elements[10] *= sz;
3185
this.elements[12] *= sx;
3186
this.elements[13] *= sy;
3187
this.elements[14] *= sz
3188
}
3189
},
3190
skewX: function(angle) {
3191
var t = Math.tan(angle);
3192
this.apply(1, t, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
3193
},
3194
skewY: function(angle) {
3195
var t = Math.tan(angle);
3196
this.apply(1, 0, 0, 0, t, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
3197
},
3198
shearX: function(angle) {
3199
var t = Math.tan(angle);
3200
this.apply(1, t, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
3201
},
3202
shearY: function(angle) {
3203
var t = Math.tan(angle);
3204
this.apply(1, 0, 0, 0, t, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
3205
},
3206
multX: function(x, y, z, w) {
3207
if (!z) return this.elements[0] * x + this.elements[1] * y + this.elements[3];
3208
if (!w) return this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3];
3209
return this.elements[0] * x + this.elements[1] * y + this.elements[2] * z + this.elements[3] * w
3210
},
3211
multY: function(x, y, z, w) {
3212
if (!z) return this.elements[4] * x + this.elements[5] * y + this.elements[7];
3213
if (!w) return this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7];
3214
return this.elements[4] * x + this.elements[5] * y + this.elements[6] * z + this.elements[7] * w
3215
},
3216
multZ: function(x, y, z, w) {
3217
if (!w) return this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11];
3218
return this.elements[8] * x + this.elements[9] * y + this.elements[10] * z + this.elements[11] * w
3219
},
3220
multW: function(x, y, z, w) {
3221
if (!w) return this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15];
3222
return this.elements[12] * x + this.elements[13] * y + this.elements[14] * z + this.elements[15] * w
3223
},
3224
invert: function() {
3225
var fA0 = this.elements[0] * this.elements[5] - this.elements[1] * this.elements[4];
3226
var fA1 = this.elements[0] * this.elements[6] - this.elements[2] * this.elements[4];
3227
var fA2 = this.elements[0] * this.elements[7] - this.elements[3] * this.elements[4];
3228
var fA3 = this.elements[1] * this.elements[6] - this.elements[2] * this.elements[5];
3229
var fA4 = this.elements[1] * this.elements[7] - this.elements[3] * this.elements[5];
3230
var fA5 = this.elements[2] * this.elements[7] - this.elements[3] * this.elements[6];
3231
var fB0 = this.elements[8] * this.elements[13] - this.elements[9] * this.elements[12];
3232
var fB1 = this.elements[8] * this.elements[14] - this.elements[10] * this.elements[12];
3233
var fB2 = this.elements[8] * this.elements[15] - this.elements[11] * this.elements[12];
3234
var fB3 = this.elements[9] * this.elements[14] - this.elements[10] * this.elements[13];
3235
var fB4 = this.elements[9] * this.elements[15] - this.elements[11] * this.elements[13];
3236
var fB5 = this.elements[10] * this.elements[15] - this.elements[11] * this.elements[14];
3237
var fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0;
3238
if (Math.abs(fDet) <= 1.0E-9) return false;
3239
var kInv = [];
3240
kInv[0] = +this.elements[5] * fB5 - this.elements[6] * fB4 + this.elements[7] * fB3;
3241
kInv[4] = -this.elements[4] * fB5 + this.elements[6] * fB2 - this.elements[7] * fB1;
3242
kInv[8] = +this.elements[4] * fB4 - this.elements[5] * fB2 + this.elements[7] * fB0;
3243
kInv[12] = -this.elements[4] * fB3 + this.elements[5] * fB1 - this.elements[6] * fB0;
3244
kInv[1] = -this.elements[1] * fB5 + this.elements[2] * fB4 - this.elements[3] * fB3;
3245
kInv[5] = +this.elements[0] * fB5 - this.elements[2] * fB2 + this.elements[3] * fB1;
3246
kInv[9] = -this.elements[0] * fB4 + this.elements[1] * fB2 - this.elements[3] * fB0;
3247
kInv[13] = +this.elements[0] * fB3 - this.elements[1] * fB1 + this.elements[2] * fB0;
3248
kInv[2] = +this.elements[13] * fA5 - this.elements[14] * fA4 + this.elements[15] * fA3;
3249
kInv[6] = -this.elements[12] * fA5 + this.elements[14] * fA2 - this.elements[15] * fA1;
3250
kInv[10] = +this.elements[12] * fA4 - this.elements[13] * fA2 + this.elements[15] * fA0;
3251
kInv[14] = -this.elements[12] * fA3 + this.elements[13] * fA1 - this.elements[14] * fA0;
3252
kInv[3] = -this.elements[9] * fA5 + this.elements[10] * fA4 - this.elements[11] * fA3;
3253
kInv[7] = +this.elements[8] * fA5 - this.elements[10] * fA2 + this.elements[11] * fA1;
3254
kInv[11] = -this.elements[8] * fA4 + this.elements[9] * fA2 - this.elements[11] * fA0;
3255
kInv[15] = +this.elements[8] * fA3 - this.elements[9] * fA1 + this.elements[10] * fA0;
3256
var fInvDet = 1 / fDet;
3257
kInv[0] *= fInvDet;
3258
kInv[1] *= fInvDet;
3259
kInv[2] *= fInvDet;
3260
kInv[3] *= fInvDet;
3261
kInv[4] *= fInvDet;
3262
kInv[5] *= fInvDet;
3263
kInv[6] *= fInvDet;
3264
kInv[7] *= fInvDet;
3265
kInv[8] *= fInvDet;
3266
kInv[9] *= fInvDet;
3267
kInv[10] *= fInvDet;
3268
kInv[11] *= fInvDet;
3269
kInv[12] *= fInvDet;
3270
kInv[13] *= fInvDet;
3271
kInv[14] *= fInvDet;
3272
kInv[15] *= fInvDet;
3273
this.elements = kInv.slice();
3274
return true
3275
},
3276
toString: function() {
3277
var str = "";
3278
for (var i = 0; i < 15; i++) str += this.elements[i] + ", ";
3279
str += this.elements[15];
3280
return str
3281
},
3282
print: function() {
3283
var digits = printMatrixHelper(this.elements);
3284
var output = "" + p.nfs(this.elements[0], digits, 4) + " " + p.nfs(this.elements[1], digits, 4) + " " + p.nfs(this.elements[2], digits, 4) + " " + p.nfs(this.elements[3], digits, 4) + "\n" + p.nfs(this.elements[4], digits, 4) + " " + p.nfs(this.elements[5], digits, 4) + " " + p.nfs(this.elements[6], digits, 4) + " " + p.nfs(this.elements[7], digits, 4) + "\n" + p.nfs(this.elements[8], digits, 4) + " " + p.nfs(this.elements[9], digits, 4) + " " + p.nfs(this.elements[10], digits, 4) + " " + p.nfs(this.elements[11], digits, 4) + "\n" + p.nfs(this.elements[12], digits, 4) + " " + p.nfs(this.elements[13], digits, 4) + " " + p.nfs(this.elements[14], digits, 4) + " " + p.nfs(this.elements[15], digits, 4) + "\n\n";
3285
p.println(output)
3286
},
3287
invTranslate: function(tx, ty, tz) {
3288
this.preApply(1, 0, 0, -tx, 0, 1, 0, -ty, 0, 0, 1, -tz, 0, 0, 0, 1)
3289
},
3290
invRotateX: function(angle) {
3291
var c = Math.cos(-angle);
3292
var s = Math.sin(-angle);
3293
this.preApply([1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1])
3294
},
3295
invRotateY: function(angle) {
3296
var c = Math.cos(-angle);
3297
var s = Math.sin(-angle);
3298
this.preApply([c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1])
3299
},
3300
invRotateZ: function(angle) {
3301
var c = Math.cos(-angle);
3302
var s = Math.sin(-angle);
3303
this.preApply([c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
3304
},
3305
invScale: function(x, y, z) {
3306
this.preApply([1 / x, 0, 0, 0, 0, 1 / y, 0, 0, 0, 0, 1 / z, 0, 0, 0, 0, 1])
3307
}
3308
};
3309
var PMatrixStack = p.PMatrixStack = function() {
3310
this.matrixStack = []
3311
};
3312
PMatrixStack.prototype.load = function() {
3313
var tmpMatrix = drawing.$newPMatrix();
3314
if (arguments.length === 1) tmpMatrix.set(arguments[0]);
3315
else tmpMatrix.set(arguments);
3316
this.matrixStack.push(tmpMatrix)
3317
};
3318
Drawing2D.prototype.$newPMatrix = function() {
3319
return new PMatrix2D
3320
};
3321
Drawing3D.prototype.$newPMatrix = function() {
3322
return new PMatrix3D
3323
};
3324
PMatrixStack.prototype.push = function() {
3325
this.matrixStack.push(this.peek())
3326
};
3327
PMatrixStack.prototype.pop = function() {
3328
return this.matrixStack.pop()
3329
};
3330
PMatrixStack.prototype.peek = function() {
3331
var tmpMatrix = drawing.$newPMatrix();
3332
tmpMatrix.set(this.matrixStack[this.matrixStack.length - 1]);
3333
return tmpMatrix
3334
};
3335
PMatrixStack.prototype.mult = function(matrix) {
3336
this.matrixStack[this.matrixStack.length - 1].apply(matrix)
3337
};
3338
p.split = function(str, delim) {
3339
return str.split(delim)
3340
};
3341
p.splitTokens = function(str, tokens) {
3342
if (tokens === undef) return str.split(/\s+/g);
3343
var chars = tokens.split(/()/g),
3344
buffer = "",
3345
len = str.length,
3346
i, c, tokenized = [];
3347
for (i = 0; i < len; i++) {
3348
c = str[i];
3349
if (chars.indexOf(c) > -1) {
3350
if (buffer !== "") tokenized.push(buffer);
3351
buffer = ""
3352
} else buffer += c
3353
}
3354
if (buffer !== "") tokenized.push(buffer);
3355
return tokenized
3356
};
3357
p.append = function(array, element) {
3358
array[array.length] = element;
3359
return array
3360
};
3361
p.concat = function(array1, array2) {
3362
return array1.concat(array2)
3363
};
3364
p.sort = function(array, numElem) {
3365
var ret = [];
3366
if (array.length > 0) {
3367
var elemsToCopy = numElem > 0 ? numElem : array.length;
3368
for (var i = 0; i < elemsToCopy; i++) ret.push(array[i]);
3369
if (typeof array[0] === "string") ret.sort();
3370
else ret.sort(function(a, b) {
3371
return a - b
3372
});
3373
if (numElem > 0) for (var j = ret.length; j < array.length; j++) ret.push(array[j])
3374
}
3375
return ret
3376
};
3377
p.splice = function(array, value, index) {
3378
if (value.length === 0) return array;
3379
if (value instanceof Array) for (var i = 0, j = index; i < value.length; j++, i++) array.splice(j, 0, value[i]);
3380
else array.splice(index, 0, value);
3381
return array
3382
};
3383
p.subset = function(array, offset, length) {
3384
var end = length !== undef ? offset + length : array.length;
3385
return array.slice(offset, end)
3386
};
3387
p.join = function(array, seperator) {
3388
return array.join(seperator)
3389
};
3390
p.shorten = function(ary) {
3391
var newary = [];
3392
var len = ary.length;
3393
for (var i = 0; i < len; i++) newary[i] = ary[i];
3394
newary.pop();
3395
return newary
3396
};
3397
p.expand = function(ary, targetSize) {
3398
var temp = ary.slice(0),
3399
newSize = targetSize || ary.length * 2;
3400
temp.length = newSize;
3401
return temp
3402
};
3403
p.arrayCopy = function() {
3404
var src, srcPos = 0,
3405
dest, destPos = 0,
3406
length;
3407
if (arguments.length === 2) {
3408
src = arguments[0];
3409
dest = arguments[1];
3410
length = src.length
3411
} else if (arguments.length === 3) {
3412
src = arguments[0];
3413
dest = arguments[1];
3414
length = arguments[2]
3415
} else if (arguments.length === 5) {
3416
src = arguments[0];
3417
srcPos = arguments[1];
3418
dest = arguments[2];
3419
destPos = arguments[3];
3420
length = arguments[4]
3421
}
3422
for (var i = srcPos, j = destPos; i < length + srcPos; i++, j++) if (dest[j] !== undef) dest[j] = src[i];
3423
else throw "array index out of bounds exception";
3424
};
3425
p.reverse = function(array) {
3426
return array.reverse()
3427
};
3428
p.mix = function(a, b, f) {
3429
return a + ((b - a) * f >> 8)
3430
};
3431
p.peg = function(n) {
3432
return n < 0 ? 0 : n > 255 ? 255 : n
3433
};
3434
p.modes = function() {
3435
var ALPHA_MASK = 4278190080,
3436
RED_MASK = 16711680,
3437
GREEN_MASK = 65280,
3438
BLUE_MASK = 255,
3439
min = Math.min,
3440
max = Math.max;
3441
3442
function applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb) {
3443
var a = min(((c1 & 4278190080) >>> 24) + f, 255) << 24;
3444
var r = ar + ((cr - ar) * f >> 8);
3445
r = (r < 0 ? 0 : r > 255 ? 255 : r) << 16;
3446
var g = ag + ((cg - ag) * f >> 8);
3447
g = (g < 0 ? 0 : g > 255 ? 255 : g) << 8;
3448
var b = ab + ((cb - ab) * f >> 8);
3449
b = b < 0 ? 0 : b > 255 ? 255 : b;
3450
return a | r | g | b
3451
}
3452
return {
3453
replace: function(c1, c2) {
3454
return c2
3455
},
3456
blend: function(c1, c2) {
3457
var f = (c2 & ALPHA_MASK) >>> 24,
3458
ar = c1 & RED_MASK,
3459
ag = c1 & GREEN_MASK,
3460
ab = c1 & BLUE_MASK,
3461
br = c2 & RED_MASK,
3462
bg = c2 & GREEN_MASK,
3463
bb = c2 & BLUE_MASK;
3464
return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | ar + ((br - ar) * f >> 8) & RED_MASK | ag + ((bg - ag) * f >> 8) & GREEN_MASK | ab + ((bb - ab) * f >> 8) & BLUE_MASK
3465
},
3466
add: function(c1, c2) {
3467
var f = (c2 & ALPHA_MASK) >>> 24;
3468
return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | min((c1 & RED_MASK) + ((c2 & RED_MASK) >> 8) * f, RED_MASK) & RED_MASK | min((c1 & GREEN_MASK) + ((c2 & GREEN_MASK) >> 8) * f, GREEN_MASK) & GREEN_MASK | min((c1 & BLUE_MASK) + ((c2 & BLUE_MASK) * f >> 8), BLUE_MASK)
3469
},
3470
subtract: function(c1, c2) {
3471
var f = (c2 & ALPHA_MASK) >>> 24;
3472
return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | max((c1 & RED_MASK) - ((c2 & RED_MASK) >> 8) * f, GREEN_MASK) & RED_MASK | max((c1 & GREEN_MASK) - ((c2 & GREEN_MASK) >> 8) * f, BLUE_MASK) & GREEN_MASK | max((c1 & BLUE_MASK) - ((c2 & BLUE_MASK) * f >> 8), 0)
3473
},
3474
lightest: function(c1, c2) {
3475
var f = (c2 & ALPHA_MASK) >>> 24;
3476
return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | max(c1 & RED_MASK, ((c2 & RED_MASK) >> 8) * f) & RED_MASK | max(c1 & GREEN_MASK, ((c2 & GREEN_MASK) >> 8) * f) & GREEN_MASK | max(c1 & BLUE_MASK, (c2 & BLUE_MASK) * f >> 8)
3477
},
3478
darkest: function(c1, c2) {
3479
var f = (c2 & ALPHA_MASK) >>> 24,
3480
ar = c1 & RED_MASK,
3481
ag = c1 & GREEN_MASK,
3482
ab = c1 & BLUE_MASK,
3483
br = min(c1 & RED_MASK, ((c2 & RED_MASK) >> 8) * f),
3484
bg = min(c1 & GREEN_MASK, ((c2 & GREEN_MASK) >> 8) * f),
3485
bb = min(c1 & BLUE_MASK, (c2 & BLUE_MASK) * f >> 8);
3486
return min(((c1 & ALPHA_MASK) >>> 24) + f, 255) << 24 | ar + ((br - ar) * f >> 8) & RED_MASK | ag + ((bg - ag) * f >> 8) & GREEN_MASK | ab + ((bb - ab) * f >> 8) & BLUE_MASK
3487
},
3488
difference: function(c1, c2) {
3489
var f = (c2 & ALPHA_MASK) >>> 24,
3490
ar = (c1 & RED_MASK) >> 16,
3491
ag = (c1 & GREEN_MASK) >> 8,
3492
ab = c1 & BLUE_MASK,
3493
br = (c2 & RED_MASK) >> 16,
3494
bg = (c2 & GREEN_MASK) >> 8,
3495
bb = c2 & BLUE_MASK,
3496
cr = ar > br ? ar - br : br - ar,
3497
cg = ag > bg ? ag - bg : bg - ag,
3498
cb = ab > bb ? ab - bb : bb - ab;
3499
return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
3500
},
3501
exclusion: function(c1, c2) {
3502
var f = (c2 & ALPHA_MASK) >>> 24,
3503
ar = (c1 & RED_MASK) >> 16,
3504
ag = (c1 & GREEN_MASK) >> 8,
3505
ab = c1 & BLUE_MASK,
3506
br = (c2 & RED_MASK) >> 16,
3507
bg = (c2 & GREEN_MASK) >> 8,
3508
bb = c2 & BLUE_MASK,
3509
cr = ar + br - (ar * br >> 7),
3510
cg = ag + bg - (ag * bg >> 7),
3511
cb = ab + bb - (ab * bb >> 7);
3512
return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
3513
},
3514
multiply: function(c1, c2) {
3515
var f = (c2 & ALPHA_MASK) >>> 24,
3516
ar = (c1 & RED_MASK) >> 16,
3517
ag = (c1 & GREEN_MASK) >> 8,
3518
ab = c1 & BLUE_MASK,
3519
br = (c2 & RED_MASK) >> 16,
3520
bg = (c2 & GREEN_MASK) >> 8,
3521
bb = c2 & BLUE_MASK,
3522
cr = ar * br >> 8,
3523
cg = ag * bg >> 8,
3524
cb = ab * bb >> 8;
3525
return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
3526
},
3527
screen: function(c1, c2) {
3528
var f = (c2 & ALPHA_MASK) >>> 24,
3529
ar = (c1 & RED_MASK) >> 16,
3530
ag = (c1 & GREEN_MASK) >> 8,
3531
ab = c1 & BLUE_MASK,
3532
br = (c2 & RED_MASK) >> 16,
3533
bg = (c2 & GREEN_MASK) >> 8,
3534
bb = c2 & BLUE_MASK,
3535
cr = 255 - ((255 - ar) * (255 - br) >> 8),
3536
cg = 255 - ((255 - ag) * (255 - bg) >> 8),
3537
cb = 255 - ((255 - ab) * (255 - bb) >> 8);
3538
return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
3539
},
3540
hard_light: function(c1, c2) {
3541
var f = (c2 & ALPHA_MASK) >>> 24,
3542
ar = (c1 & RED_MASK) >> 16,
3543
ag = (c1 & GREEN_MASK) >> 8,
3544
ab = c1 & BLUE_MASK,
3545
br = (c2 & RED_MASK) >> 16,
3546
bg = (c2 & GREEN_MASK) >> 8,
3547
bb = c2 & BLUE_MASK,
3548
cr = br < 128 ? ar * br >> 7 : 255 - ((255 - ar) * (255 - br) >> 7),
3549
cg = bg < 128 ? ag * bg >> 7 : 255 - ((255 - ag) * (255 - bg) >> 7),
3550
cb = bb < 128 ? ab * bb >> 7 : 255 - ((255 - ab) * (255 - bb) >> 7);
3551
return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
3552
},
3553
soft_light: function(c1, c2) {
3554
var f = (c2 & ALPHA_MASK) >>> 24,
3555
ar = (c1 & RED_MASK) >> 16,
3556
ag = (c1 & GREEN_MASK) >> 8,
3557
ab = c1 & BLUE_MASK,
3558
br = (c2 & RED_MASK) >> 16,
3559
bg = (c2 & GREEN_MASK) >> 8,
3560
bb = c2 & BLUE_MASK,
3561
cr = (ar * br >> 7) + (ar * ar >> 8) - (ar * ar * br >> 15),
3562
cg = (ag * bg >> 7) + (ag * ag >> 8) - (ag * ag * bg >> 15),
3563
cb = (ab * bb >> 7) + (ab * ab >> 8) - (ab * ab * bb >> 15);
3564
return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
3565
},
3566
overlay: function(c1, c2) {
3567
var f = (c2 & ALPHA_MASK) >>> 24,
3568
ar = (c1 & RED_MASK) >> 16,
3569
ag = (c1 & GREEN_MASK) >> 8,
3570
ab = c1 & BLUE_MASK,
3571
br = (c2 & RED_MASK) >> 16,
3572
bg = (c2 & GREEN_MASK) >> 8,
3573
bb = c2 & BLUE_MASK,
3574
cr = ar < 128 ? ar * br >> 7 : 255 - ((255 - ar) * (255 - br) >> 7),
3575
cg = ag < 128 ? ag * bg >> 7 : 255 - ((255 - ag) * (255 - bg) >> 7),
3576
cb = ab < 128 ? ab * bb >> 7 : 255 - ((255 - ab) * (255 - bb) >> 7);
3577
return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
3578
},
3579
dodge: function(c1, c2) {
3580
var f = (c2 & ALPHA_MASK) >>> 24,
3581
ar = (c1 & RED_MASK) >> 16,
3582
ag = (c1 & GREEN_MASK) >> 8,
3583
ab = c1 & BLUE_MASK,
3584
br = (c2 & RED_MASK) >> 16,
3585
bg = (c2 & GREEN_MASK) >> 8,
3586
bb = c2 & BLUE_MASK;
3587
var cr = 255;
3588
if (br !== 255) {
3589
cr = (ar << 8) / (255 - br);
3590
cr = cr < 0 ? 0 : cr > 255 ? 255 : cr
3591
}
3592
var cg = 255;
3593
if (bg !== 255) {
3594
cg = (ag << 8) / (255 - bg);
3595
cg = cg < 0 ? 0 : cg > 255 ? 255 : cg
3596
}
3597
var cb = 255;
3598
if (bb !== 255) {
3599
cb = (ab << 8) / (255 - bb);
3600
cb = cb < 0 ? 0 : cb > 255 ? 255 : cb
3601
}
3602
return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
3603
},
3604
burn: function(c1, c2) {
3605
var f = (c2 & ALPHA_MASK) >>> 24,
3606
ar = (c1 & RED_MASK) >> 16,
3607
ag = (c1 & GREEN_MASK) >> 8,
3608
ab = c1 & BLUE_MASK,
3609
br = (c2 & RED_MASK) >> 16,
3610
bg = (c2 & GREEN_MASK) >> 8,
3611
bb = c2 & BLUE_MASK;
3612
var cr = 0;
3613
if (br !== 0) {
3614
cr = (255 - ar << 8) / br;
3615
cr = 255 - (cr < 0 ? 0 : cr > 255 ? 255 : cr)
3616
}
3617
var cg = 0;
3618
if (bg !== 0) {
3619
cg = (255 - ag << 8) / bg;
3620
cg = 255 - (cg < 0 ? 0 : cg > 255 ? 255 : cg)
3621
}
3622
var cb = 0;
3623
if (bb !== 0) {
3624
cb = (255 - ab << 8) / bb;
3625
cb = 255 - (cb < 0 ? 0 : cb > 255 ? 255 : cb)
3626
}
3627
return applyMode(c1, f, ar, ag, ab, br, bg, bb, cr, cg, cb)
3628
}
3629
}
3630
}();
3631
3632
function color$4(aValue1, aValue2, aValue3, aValue4) {
3633
var r, g, b, a;
3634
if (curColorMode === 3) {
3635
var rgb = p.color.toRGB(aValue1, aValue2, aValue3);
3636
r = rgb[0];
3637
g = rgb[1];
3638
b = rgb[2]
3639
} else {
3640
r = Math.round(255 * (aValue1 / colorModeX));
3641
g = Math.round(255 * (aValue2 / colorModeY));
3642
b = Math.round(255 * (aValue3 / colorModeZ))
3643
}
3644
a = Math.round(255 * (aValue4 / colorModeA));
3645
r = r < 0 ? 0 : r;
3646
g = g < 0 ? 0 : g;
3647
b = b < 0 ? 0 : b;
3648
a = a < 0 ? 0 : a;
3649
r = r > 255 ? 255 : r;
3650
g = g > 255 ? 255 : g;
3651
b = b > 255 ? 255 : b;
3652
a = a > 255 ? 255 : a;
3653
return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255
3654
}
3655
function color$2(aValue1, aValue2) {
3656
var a;
3657
if (aValue1 & 4278190080) {
3658
a = Math.round(255 * (aValue2 / colorModeA));
3659
a = a > 255 ? 255 : a;
3660
a = a < 0 ? 0 : a;
3661
return aValue1 - (aValue1 & 4278190080) + (a << 24 & 4278190080)
3662
}
3663
if (curColorMode === 1) return color$4(aValue1, aValue1, aValue1, aValue2);
3664
if (curColorMode === 3) return color$4(0, 0, aValue1 / colorModeX * colorModeZ, aValue2)
3665
}
3666
function color$1(aValue1) {
3667
if (aValue1 <= colorModeX && aValue1 >= 0) {
3668
if (curColorMode === 1) return color$4(aValue1, aValue1, aValue1, colorModeA);
3669
if (curColorMode === 3) return color$4(0, 0, aValue1 / colorModeX * colorModeZ, colorModeA)
3670
}
3671
if (aValue1) {
3672
if (aValue1 > 2147483647) aValue1 -= 4294967296;
3673
return aValue1
3674
}
3675
}
3676
p.color = function(aValue1, aValue2, aValue3, aValue4) {
3677
if (aValue1 !== undef && aValue2 !== undef && aValue3 !== undef && aValue4 !== undef) return color$4(aValue1, aValue2, aValue3, aValue4);
3678
if (aValue1 !== undef && aValue2 !== undef && aValue3 !== undef) return color$4(aValue1, aValue2, aValue3, colorModeA);
3679
if (aValue1 !== undef && aValue2 !== undef) return color$2(aValue1, aValue2);
3680
if (typeof aValue1 === "number") return color$1(aValue1);
3681
return color$4(colorModeX, colorModeY, colorModeZ, colorModeA)
3682
};
3683
p.color.toString = function(colorInt) {
3684
return "rgba(" + ((colorInt >> 16) & 255) + "," + ((colorInt >> 8) & 255) + "," + (colorInt & 255) + "," + ((colorInt >> 24) & 255) / 255 + ")"
3685
};
3686
p.color.toInt = function(r, g, b, a) {
3687
return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255
3688
};
3689
p.color.toArray = function(colorInt) {
3690
return [(colorInt >> 16) & 255, (colorInt >> 8) & 255, colorInt & 255, (colorInt >> 24) & 255]
3691
};
3692
p.color.toGLArray = function(colorInt) {
3693
return [((colorInt & 16711680) >>> 16) / 255, ((colorInt >> 8) & 255) / 255, (colorInt & 255) / 255, ((colorInt >> 24) & 255) / 255]
3694
};
3695
p.color.toRGB = function(h, s, b) {
3696
h = h > colorModeX ? colorModeX : h;
3697
s = s > colorModeY ? colorModeY : s;
3698
b = b > colorModeZ ? colorModeZ : b;
3699
h = h / colorModeX * 360;
3700
s = s / colorModeY * 100;
3701
b = b / colorModeZ * 100;
3702
var br = Math.round(b / 100 * 255);
3703
if (s === 0) return [br, br, br];
3704
var hue = h % 360;
3705
var f = hue % 60;
3706
var p = Math.round(b * (100 - s) / 1E4 * 255);
3707
var q = Math.round(b * (6E3 - s * f) / 6E5 * 255);
3708
var t = Math.round(b * (6E3 - s * (60 - f)) / 6E5 * 255);
3709
switch (Math.floor(hue / 60)) {
3710
case 0:
3711
return [br, t, p];
3712
case 1:
3713
return [q, br, p];
3714
case 2:
3715
return [p, br, t];
3716
case 3:
3717
return [p, q, br];
3718
case 4:
3719
return [t, p, br];
3720
case 5:
3721
return [br, p, q]
3722
}
3723
};
3724
3725
function colorToHSB(colorInt) {
3726
var red, green, blue;
3727
red = ((colorInt >> 16) & 255) / 255;
3728
green = ((colorInt >> 8) & 255) / 255;
3729
blue = (colorInt & 255) / 255;
3730
var max = p.max(p.max(red, green), blue),
3731
min = p.min(p.min(red, green), blue),
3732
hue, saturation;
3733
if (min === max) return [0, 0, max * colorModeZ];
3734
saturation = (max - min) / max;
3735
if (red === max) hue = (green - blue) / (max - min);
3736
else if (green === max) hue = 2 + (blue - red) / (max - min);
3737
else hue = 4 + (red - green) / (max - min);
3738
hue /= 6;
3739
if (hue < 0) hue += 1;
3740
else if (hue > 1) hue -= 1;
3741
return [hue * colorModeX, saturation * colorModeY, max * colorModeZ]
3742
}
3743
p.brightness = function(colInt) {
3744
return colorToHSB(colInt)[2]
3745
};
3746
p.saturation = function(colInt) {
3747
return colorToHSB(colInt)[1]
3748
};
3749
p.hue = function(colInt) {
3750
return colorToHSB(colInt)[0]
3751
};
3752
p.red = function(aColor) {
3753
return ((aColor >> 16) & 255) / 255 * colorModeX
3754
};
3755
p.green = function(aColor) {
3756
return ((aColor & 65280) >>> 8) / 255 * colorModeY
3757
};
3758
p.blue = function(aColor) {
3759
return (aColor & 255) / 255 * colorModeZ
3760
};
3761
p.alpha = function(aColor) {
3762
return ((aColor >> 24) & 255) / 255 * colorModeA
3763
};
3764
p.lerpColor = function(c1, c2, amt) {
3765
var r, g, b, a, r1, g1, b1, a1, r2, g2, b2, a2;
3766
var hsb1, hsb2, rgb, h, s;
3767
var colorBits1 = p.color(c1);
3768
var colorBits2 = p.color(c2);
3769
if (curColorMode === 3) {
3770
hsb1 = colorToHSB(colorBits1);
3771
a1 = ((colorBits1 >> 24) & 255) / colorModeA;
3772
hsb2 = colorToHSB(colorBits2);
3773
a2 = ((colorBits2 & 4278190080) >>> 24) / colorModeA;
3774
h = p.lerp(hsb1[0], hsb2[0], amt);
3775
s = p.lerp(hsb1[1], hsb2[1], amt);
3776
b = p.lerp(hsb1[2], hsb2[2], amt);
3777
rgb = p.color.toRGB(h, s, b);
3778
a = p.lerp(a1, a2, amt) * colorModeA;
3779
return a << 24 & 4278190080 | (rgb[0] & 255) << 16 | (rgb[1] & 255) << 8 | rgb[2] & 255
3780
}
3781
r1 = (colorBits1 >> 16) & 255;
3782
g1 = (colorBits1 >> 8) & 255;
3783
b1 = colorBits1 & 255;
3784
a1 = ((colorBits1 >> 24) & 255) / colorModeA;
3785
r2 = (colorBits2 & 16711680) >>> 16;
3786
g2 = (colorBits2 >> 8) & 255;
3787
b2 = colorBits2 & 255;
3788
a2 = ((colorBits2 >> 24) & 255) / colorModeA;
3789
r = p.lerp(r1, r2, amt) | 0;
3790
g = p.lerp(g1, g2, amt) | 0;
3791
b = p.lerp(b1, b2, amt) | 0;
3792
a = p.lerp(a1, a2, amt) * colorModeA;
3793
return a << 24 & 4278190080 | r << 16 & 16711680 | g << 8 & 65280 | b & 255
3794
};
3795
p.colorMode = function() {
3796
curColorMode = arguments[0];
3797
if (arguments.length > 1) {
3798
colorModeX = arguments[1];
3799
colorModeY = arguments[2] || arguments[1];
3800
colorModeZ = arguments[3] || arguments[1];
3801
colorModeA = arguments[4] || arguments[1]
3802
}
3803
};
3804
p.blendColor = function(c1, c2, mode) {
3805
if (mode === 0) return p.modes.replace(c1, c2);
3806
else if (mode === 1) return p.modes.blend(c1, c2);
3807
else if (mode === 2) return p.modes.add(c1, c2);
3808
else if (mode === 4) return p.modes.subtract(c1, c2);
3809
else if (mode === 8) return p.modes.lightest(c1, c2);
3810
else if (mode === 16) return p.modes.darkest(c1, c2);
3811
else if (mode === 32) return p.modes.difference(c1, c2);
3812
else if (mode === 64) return p.modes.exclusion(c1, c2);
3813
else if (mode === 128) return p.modes.multiply(c1, c2);
3814
else if (mode === 256) return p.modes.screen(c1, c2);
3815
else if (mode === 1024) return p.modes.hard_light(c1, c2);
3816
else if (mode === 2048) return p.modes.soft_light(c1, c2);
3817
else if (mode === 512) return p.modes.overlay(c1, c2);
3818
else if (mode === 4096) return p.modes.dodge(c1, c2);
3819
else if (mode === 8192) return p.modes.burn(c1, c2)
3820
};
3821
3822
function saveContext() {
3823
curContext.save()
3824
}
3825
function restoreContext() {
3826
curContext.restore();
3827
isStrokeDirty = true;
3828
isFillDirty = true
3829
}
3830
p.printMatrix = function() {
3831
modelView.print()
3832
};
3833
Drawing2D.prototype.translate = function(x, y) {
3834
modelView.translate(x, y);
3835
modelViewInv.invTranslate(x, y);
3836
curContext.translate(x, y)
3837
};
3838
Drawing3D.prototype.translate = function(x, y, z) {
3839
modelView.translate(x, y, z);
3840
modelViewInv.invTranslate(x, y, z)
3841
};
3842
Drawing2D.prototype.scale = function(x, y) {
3843
modelView.scale(x, y);
3844
modelViewInv.invScale(x, y);
3845
curContext.scale(x, y || x)
3846
};
3847
Drawing3D.prototype.scale = function(x, y, z) {
3848
modelView.scale(x, y, z);
3849
modelViewInv.invScale(x, y, z)
3850
};
3851
Drawing2D.prototype.transform = function(pmatrix) {
3852
var e = pmatrix.array();
3853
curContext.transform(e[0], e[3], e[1], e[4], e[2], e[5])
3854
};
3855
Drawing3D.prototype.transformm = function(pmatrix3d) {
3856
throw "p.transform is currently not supported in 3D mode";
3857
};
3858
Drawing2D.prototype.pushMatrix = function() {
3859
userMatrixStack.load(modelView);
3860
userReverseMatrixStack.load(modelViewInv);
3861
saveContext()
3862
};
3863
Drawing3D.prototype.pushMatrix = function() {
3864
userMatrixStack.load(modelView);
3865
userReverseMatrixStack.load(modelViewInv)
3866
};
3867
Drawing2D.prototype.popMatrix = function() {
3868
modelView.set(userMatrixStack.pop());
3869
modelViewInv.set(userReverseMatrixStack.pop());
3870
restoreContext()
3871
};
3872
Drawing3D.prototype.popMatrix = function() {
3873
modelView.set(userMatrixStack.pop());
3874
modelViewInv.set(userReverseMatrixStack.pop())
3875
};
3876
Drawing2D.prototype.resetMatrix = function() {
3877
modelView.reset();
3878
modelViewInv.reset();
3879
curContext.setTransform(1, 0, 0, 1, 0, 0)
3880
};
3881
Drawing3D.prototype.resetMatrix = function() {
3882
modelView.reset();
3883
modelViewInv.reset()
3884
};
3885
DrawingShared.prototype.applyMatrix = function() {
3886
var a = arguments;
3887
modelView.apply(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);
3888
modelViewInv.invApply(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15])
3889
};
3890
Drawing2D.prototype.applyMatrix = function() {
3891
var a = arguments;
3892
for (var cnt = a.length; cnt < 16; cnt++) a[cnt] = 0;
3893
a[10] = a[15] = 1;
3894
DrawingShared.prototype.applyMatrix.apply(this, a)
3895
};
3896
p.rotateX = function(angleInRadians) {
3897
modelView.rotateX(angleInRadians);
3898
modelViewInv.invRotateX(angleInRadians)
3899
};
3900
Drawing2D.prototype.rotateZ = function() {
3901
throw "rotateZ() is not supported in 2D mode. Use rotate(float) instead.";
3902
};
3903
Drawing3D.prototype.rotateZ = function(angleInRadians) {
3904
modelView.rotateZ(angleInRadians);
3905
modelViewInv.invRotateZ(angleInRadians)
3906
};
3907
p.rotateY = function(angleInRadians) {
3908
modelView.rotateY(angleInRadians);
3909
modelViewInv.invRotateY(angleInRadians)
3910
};
3911
Drawing2D.prototype.rotate = function(angleInRadians) {
3912
modelView.rotateZ(angleInRadians);
3913
modelViewInv.invRotateZ(angleInRadians);
3914
curContext.rotate(angleInRadians)
3915
};
3916
Drawing3D.prototype.rotate = function(angleInRadians) {
3917
p.rotateZ(angleInRadians)
3918
};
3919
Drawing2D.prototype.shearX = function(angleInRadians) {
3920
modelView.shearX(angleInRadians);
3921
curContext.transform(1, 0, angleInRadians, 1, 0, 0)
3922
};
3923
Drawing3D.prototype.shearX = function(angleInRadians) {
3924
modelView.shearX(angleInRadians)
3925
};
3926
Drawing2D.prototype.shearY = function(angleInRadians) {
3927
modelView.shearY(angleInRadians);
3928
curContext.transform(1, angleInRadians, 0, 1, 0, 0)
3929
};
3930
Drawing3D.prototype.shearY = function(angleInRadians) {
3931
modelView.shearY(angleInRadians)
3932
};
3933
p.pushStyle = function() {
3934
saveContext();
3935
p.pushMatrix();
3936
var newState = {
3937
"doFill": doFill,
3938
"currentFillColor": currentFillColor,
3939
"doStroke": doStroke,
3940
"currentStrokeColor": currentStrokeColor,
3941
"curTint": curTint,
3942
"curRectMode": curRectMode,
3943
"curColorMode": curColorMode,
3944
"colorModeX": colorModeX,
3945
"colorModeZ": colorModeZ,
3946
"colorModeY": colorModeY,
3947
"colorModeA": colorModeA,
3948
"curTextFont": curTextFont,
3949
"horizontalTextAlignment": horizontalTextAlignment,
3950
"verticalTextAlignment": verticalTextAlignment,
3951
"textMode": textMode,
3952
"curFontName": curFontName,
3953
"curTextSize": curTextSize,
3954
"curTextAscent": curTextAscent,
3955
"curTextDescent": curTextDescent,
3956
"curTextLeading": curTextLeading
3957
};
3958
styleArray.push(newState)
3959
};
3960
p.popStyle = function() {
3961
var oldState = styleArray.pop();
3962
if (oldState) {
3963
restoreContext();
3964
p.popMatrix();
3965
doFill = oldState.doFill;
3966
currentFillColor = oldState.currentFillColor;
3967
doStroke = oldState.doStroke;
3968
currentStrokeColor = oldState.currentStrokeColor;
3969
curTint = oldState.curTint;
3970
curRectMode = oldState.curRectMode;
3971
curColorMode = oldState.curColorMode;
3972
colorModeX = oldState.colorModeX;
3973
colorModeZ = oldState.colorModeZ;
3974
colorModeY = oldState.colorModeY;
3975
colorModeA = oldState.colorModeA;
3976
curTextFont = oldState.curTextFont;
3977
curFontName = oldState.curFontName;
3978
curTextSize = oldState.curTextSize;
3979
horizontalTextAlignment = oldState.horizontalTextAlignment;
3980
verticalTextAlignment = oldState.verticalTextAlignment;
3981
textMode = oldState.textMode;
3982
curTextAscent = oldState.curTextAscent;
3983
curTextDescent = oldState.curTextDescent;
3984
curTextLeading = oldState.curTextLeading
3985
} else throw "Too many popStyle() without enough pushStyle()";
3986
};
3987
p.year = function() {
3988
return (new Date).getFullYear()
3989
};
3990
p.month = function() {
3991
return (new Date).getMonth() + 1
3992
};
3993
p.day = function() {
3994
return (new Date).getDate()
3995
};
3996
p.hour = function() {
3997
return (new Date).getHours()
3998
};
3999
p.minute = function() {
4000
return (new Date).getMinutes()
4001
};
4002
p.second = function() {
4003
return (new Date).getSeconds()
4004
};
4005
p.millis = function() {
4006
return Date.now() - start
4007
};
4008
4009
function redrawHelper() {
4010
var sec = (Date.now() - timeSinceLastFPS) / 1E3;
4011
framesSinceLastFPS++;
4012
var fps = framesSinceLastFPS / sec;
4013
if (sec > 0.5) {
4014
timeSinceLastFPS = Date.now();
4015
framesSinceLastFPS = 0;
4016
p.__frameRate = fps
4017
}
4018
p.frameCount++
4019
}
4020
Drawing2D.prototype.redraw = function() {
4021
redrawHelper();
4022
curContext.lineWidth = lineWidth;
4023
var pmouseXLastEvent = p.pmouseX,
4024
pmouseYLastEvent = p.pmouseY;
4025
p.pmouseX = pmouseXLastFrame;
4026
p.pmouseY = pmouseYLastFrame;
4027
saveContext();
4028
p.draw();
4029
restoreContext();
4030
pmouseXLastFrame = p.mouseX;
4031
pmouseYLastFrame = p.mouseY;
4032
p.pmouseX = pmouseXLastEvent;
4033
p.pmouseY = pmouseYLastEvent
4034
};
4035
Drawing3D.prototype.redraw = function() {
4036
redrawHelper();
4037
var pmouseXLastEvent = p.pmouseX,
4038
pmouseYLastEvent = p.pmouseY;
4039
p.pmouseX = pmouseXLastFrame;
4040
p.pmouseY = pmouseYLastFrame;
4041
curContext.clear(curContext.DEPTH_BUFFER_BIT);
4042
curContextCache = {
4043
attributes: {},
4044
locations: {}
4045
};
4046
p.noLights();
4047
p.lightFalloff(1, 0, 0);
4048
p.shininess(1);
4049
p.ambient(255, 255, 255);
4050
p.specular(0, 0, 0);
4051
p.emissive(0, 0, 0);
4052
p.camera();
4053
p.draw();
4054
pmouseXLastFrame = p.mouseX;
4055
pmouseYLastFrame = p.mouseY;
4056
p.pmouseX = pmouseXLastEvent;
4057
p.pmouseY = pmouseYLastEvent
4058
};
4059
p.noLoop = function() {
4060
doLoop = false;
4061
loopStarted = false;
4062
clearInterval(looping);
4063
curSketch.onPause()
4064
};
4065
p.loop = function() {
4066
if (loopStarted) return;
4067
timeSinceLastFPS = Date.now();
4068
framesSinceLastFPS = 0;
4069
looping = window.setInterval(function() {
4070
try {
4071
curSketch.onFrameStart();
4072
p.redraw();
4073
curSketch.onFrameEnd()
4074
} catch(e_loop) {
4075
window.clearInterval(looping);
4076
throw e_loop;
4077
}
4078
},
4079
curMsPerFrame);
4080
doLoop = true;
4081
loopStarted = true;
4082
curSketch.onLoop()
4083
};
4084
p.frameRate = function(aRate) {
4085
curFrameRate = aRate;
4086
curMsPerFrame = 1E3 / curFrameRate;
4087
if (doLoop) {
4088
p.noLoop();
4089
p.loop()
4090
}
4091
};
4092
var eventHandlers = [];
4093
4094
function attachEventHandler(elem, type, fn) {
4095
if (elem.addEventListener) elem.addEventListener(type, fn, false);
4096
else elem.attachEvent("on" + type, fn);
4097
eventHandlers.push({
4098
elem: elem,
4099
type: type,
4100
fn: fn
4101
})
4102
}
4103
function detachEventHandler(eventHandler) {
4104
var elem = eventHandler.elem,
4105
type = eventHandler.type,
4106
fn = eventHandler.fn;
4107
if (elem.removeEventListener) elem.removeEventListener(type, fn, false);
4108
else if (elem.detachEvent) elem.detachEvent("on" + type, fn)
4109
}
4110
p.exit = function() {
4111
window.clearInterval(looping);
4112
removeInstance(p.externals.canvas.id);
4113
delete curElement.onmousedown;
4114
for (var lib in Processing.lib) if (Processing.lib.hasOwnProperty(lib)) if (Processing.lib[lib].hasOwnProperty("detach")) Processing.lib[lib].detach(p);
4115
var i = eventHandlers.length;
4116
while (i--) detachEventHandler(eventHandlers[i]);
4117
curSketch.onExit()
4118
};
4119
p.cursor = function() {
4120
if (arguments.length > 1 || arguments.length === 1 && arguments[0] instanceof p.PImage) {
4121
var image = arguments[0],
4122
x, y;
4123
if (arguments.length >= 3) {
4124
x = arguments[1];
4125
y = arguments[2];
4126
if (x < 0 || y < 0 || y >= image.height || x >= image.width) throw "x and y must be non-negative and less than the dimensions of the image";
4127
} else {
4128
x = image.width >>> 1;
4129
y = image.height >>> 1
4130
}
4131
var imageDataURL = image.toDataURL();
4132
var style = 'url("' + imageDataURL + '") ' + x + " " + y + ", default";
4133
curCursor = curElement.style.cursor = style
4134
} else if (arguments.length === 1) {
4135
var mode = arguments[0];
4136
curCursor = curElement.style.cursor = mode
4137
} else curCursor = curElement.style.cursor = oldCursor
4138
};
4139
p.noCursor = function() {
4140
curCursor = curElement.style.cursor = PConstants.NOCURSOR
4141
};
4142
p.link = function(href, target) {
4143
if (target !== undef) window.open(href, target);
4144
else window.location = href
4145
};
4146
p.beginDraw = nop;
4147
p.endDraw = nop;
4148
Drawing2D.prototype.toImageData = function(x, y, w, h) {
4149
x = x !== undef ? x : 0;
4150
y = y !== undef ? y : 0;
4151
w = w !== undef ? w : p.width;
4152
h = h !== undef ? h : p.height;
4153
return curContext.getImageData(x, y, w, h)
4154
};
4155
Drawing3D.prototype.toImageData = function(x, y, w, h) {
4156
x = x !== undef ? x : 0;
4157
y = y !== undef ? y : 0;
4158
w = w !== undef ? w : p.width;
4159
h = h !== undef ? h : p.height;
4160
var c = document.createElement("canvas"),
4161
ctx = c.getContext("2d"),
4162
obj = ctx.createImageData(w, h),
4163
uBuff = new Uint8Array(w * h * 4);
4164
curContext.readPixels(x, y, w, h, curContext.RGBA, curContext.UNSIGNED_BYTE, uBuff);
4165
for (var i = 0, ul = uBuff.length, obj_data = obj.data; i < ul; i++) obj_data[i] = uBuff[(h - 1 - Math.floor(i / 4 / w)) * w * 4 + i % (w * 4)];
4166
return obj
4167
};
4168
p.status = function(text) {
4169
window.status = text
4170
};
4171
p.binary = function(num, numBits) {
4172
var bit;
4173
if (numBits > 0) bit = numBits;
4174
else if (num instanceof Char) {
4175
bit = 16;
4176
num |= 0
4177
} else {
4178
bit = 32;
4179
while (bit > 1 && !(num >>> bit - 1 & 1)) bit--
4180
}
4181
var result = "";
4182
while (bit > 0) result += num >>> --bit & 1 ? "1" : "0";
4183
return result
4184
};
4185
p.unbinary = function(binaryString) {
4186
var i = binaryString.length - 1,
4187
mask = 1,
4188
result = 0;
4189
while (i >= 0) {
4190
var ch = binaryString[i--];
4191
if (ch !== "0" && ch !== "1") throw "the value passed into unbinary was not an 8 bit binary number";
4192
if (ch === "1") result += mask;
4193
mask <<= 1
4194
}
4195
return result
4196
};
4197
4198
function nfCoreScalar(value, plus, minus, leftDigits, rightDigits, group) {
4199
var sign = value < 0 ? minus : plus;
4200
var autoDetectDecimals = rightDigits === 0;
4201
var rightDigitsOfDefault = rightDigits === undef || rightDigits < 0 ? 0 : rightDigits;
4202
var absValue = Math.abs(value);
4203
if (autoDetectDecimals) {
4204
rightDigitsOfDefault = 1;
4205
absValue *= 10;
4206
while (Math.abs(Math.round(absValue) - absValue) > 1.0E-6 && rightDigitsOfDefault < 7) {
4207
++rightDigitsOfDefault;
4208
absValue *= 10
4209
}
4210
} else if (rightDigitsOfDefault !== 0) absValue *= Math.pow(10, rightDigitsOfDefault);
4211
var number, doubled = absValue * 2;
4212
if (Math.floor(absValue) === absValue) number = absValue;
4213
else if (Math.floor(doubled) === doubled) {
4214
var floored = Math.floor(absValue);
4215
number = floored + floored % 2
4216
} else number = Math.round(absValue);
4217
var buffer = "";
4218
var totalDigits = leftDigits + rightDigitsOfDefault;
4219
while (totalDigits > 0 || number > 0) {
4220
totalDigits--;
4221
buffer = "" + number % 10 + buffer;
4222
number = Math.floor(number / 10)
4223
}
4224
if (group !== undef) {
4225
var i = buffer.length - 3 - rightDigitsOfDefault;
4226
while (i > 0) {
4227
buffer = buffer.substring(0, i) + group + buffer.substring(i);
4228
i -= 3
4229
}
4230
}
4231
if (rightDigitsOfDefault > 0) return sign + buffer.substring(0, buffer.length - rightDigitsOfDefault) + "." + buffer.substring(buffer.length - rightDigitsOfDefault, buffer.length);
4232
return sign + buffer
4233
}
4234
function nfCore(value, plus, minus, leftDigits, rightDigits, group) {
4235
if (value instanceof Array) {
4236
var arr = [];
4237
for (var i = 0, len = value.length; i < len; i++) arr.push(nfCoreScalar(value[i], plus, minus, leftDigits, rightDigits, group));
4238
return arr
4239
}
4240
return nfCoreScalar(value, plus, minus, leftDigits, rightDigits, group)
4241
}
4242
p.nf = function(value, leftDigits, rightDigits) {
4243
return nfCore(value, "", "-", leftDigits, rightDigits)
4244
};
4245
p.nfs = function(value, leftDigits, rightDigits) {
4246
return nfCore(value, " ", "-", leftDigits, rightDigits)
4247
};
4248
p.nfp = function(value, leftDigits, rightDigits) {
4249
return nfCore(value, "+", "-", leftDigits, rightDigits)
4250
};
4251
p.nfc = function(value, leftDigits, rightDigits) {
4252
return nfCore(value, "", "-", leftDigits, rightDigits, ",")
4253
};
4254
var decimalToHex = function(d, padding) {
4255
padding = padding === undef || padding === null ? padding = 8 : padding;
4256
if (d < 0) d = 4294967295 + d + 1;
4257
var hex = Number(d).toString(16).toUpperCase();
4258
while (hex.length < padding) hex = "0" + hex;
4259
if (hex.length >= padding) hex = hex.substring(hex.length - padding, hex.length);
4260
return hex
4261
};
4262
p.hex = function(value, len) {
4263
if (arguments.length === 1) if (value instanceof Char) len = 4;
4264
else len = 8;
4265
return decimalToHex(value, len)
4266
};
4267
4268
function unhexScalar(hex) {
4269
var value = parseInt("0x" + hex, 16);
4270
if (value > 2147483647) value -= 4294967296;
4271
return value
4272
}
4273
p.unhex = function(hex) {
4274
if (hex instanceof Array) {
4275
var arr = [];
4276
for (var i = 0; i < hex.length; i++) arr.push(unhexScalar(hex[i]));
4277
return arr
4278
}
4279
return unhexScalar(hex)
4280
};
4281
p.loadStrings = function(filename) {
4282
if (localStorage[filename]) return localStorage[filename].split("\n");
4283
var filecontent = ajax(filename);
4284
if (typeof filecontent !== "string" || filecontent === "") return [];
4285
filecontent = filecontent.replace(/(\r\n?)/g, "\n").replace(/\n$/, "");
4286
return filecontent.split("\n")
4287
};
4288
p.saveStrings = function(filename, strings) {
4289
localStorage[filename] = strings.join("\n")
4290
};
4291
p.loadBytes = function(url) {
4292
var string = ajax(url);
4293
var ret = [];
4294
for (var i = 0; i < string.length; i++) ret.push(string.charCodeAt(i));
4295
return ret
4296
};
4297
4298
function removeFirstArgument(args) {
4299
return Array.prototype.slice.call(args, 1)
4300
}
4301
p.matchAll = function(aString, aRegExp) {
4302
var results = [],
4303
latest;
4304
var regexp = new RegExp(aRegExp, "g");
4305
while ((latest = regexp.exec(aString)) !== null) {
4306
results.push(latest);
4307
if (latest[0].length === 0)++regexp.lastIndex
4308
}
4309
return results.length > 0 ? results : null
4310
};
4311
p.__contains = function(subject, subStr) {
4312
if (typeof subject !== "string") return subject.contains.apply(subject, removeFirstArgument(arguments));
4313
return subject !== null && subStr !== null && typeof subStr === "string" && subject.indexOf(subStr) > -1
4314
};
4315
p.__replaceAll = function(subject, regex, replacement) {
4316
if (typeof subject !== "string") return subject.replaceAll.apply(subject, removeFirstArgument(arguments));
4317
return subject.replace(new RegExp(regex, "g"), replacement)
4318
};
4319
p.__replaceFirst = function(subject, regex, replacement) {
4320
if (typeof subject !== "string") return subject.replaceFirst.apply(subject, removeFirstArgument(arguments));
4321
return subject.replace(new RegExp(regex, ""), replacement)
4322
};
4323
p.__replace = function(subject, what, replacement) {
4324
if (typeof subject !== "string") return subject.replace.apply(subject, removeFirstArgument(arguments));
4325
if (what instanceof RegExp) return subject.replace(what, replacement);
4326
if (typeof what !== "string") what = what.toString();
4327
if (what === "") return subject;
4328
var i = subject.indexOf(what);
4329
if (i < 0) return subject;
4330
var j = 0,
4331
result = "";
4332
do {
4333
result += subject.substring(j, i) + replacement;
4334
j = i + what.length
4335
} while ((i = subject.indexOf(what, j)) >= 0);
4336
return result + subject.substring(j)
4337
};
4338
p.__equals = function(subject, other) {
4339
if (subject.equals instanceof
4340
Function) return subject.equals.apply(subject, removeFirstArgument(arguments));
4341
return subject.valueOf() === other.valueOf()
4342
};
4343
p.__equalsIgnoreCase = function(subject, other) {
4344
if (typeof subject !== "string") return subject.equalsIgnoreCase.apply(subject, removeFirstArgument(arguments));
4345
return subject.toLowerCase() === other.toLowerCase()
4346
};
4347
p.__toCharArray = function(subject) {
4348
if (typeof subject !== "string") return subject.toCharArray.apply(subject, removeFirstArgument(arguments));
4349
var chars = [];
4350
for (var i = 0, len = subject.length; i < len; ++i) chars[i] = new Char(subject.charAt(i));
4351
return chars
4352
};
4353
p.__split = function(subject, regex, limit) {
4354
if (typeof subject !== "string") return subject.split.apply(subject, removeFirstArgument(arguments));
4355
var pattern = new RegExp(regex);
4356
if (limit === undef || limit < 1) return subject.split(pattern);
4357
var result = [],
4358
currSubject = subject,
4359
pos;
4360
while ((pos = currSubject.search(pattern)) !== -1 && result.length < limit - 1) {
4361
var match = pattern.exec(currSubject).toString();
4362
result.push(currSubject.substring(0, pos));
4363
currSubject = currSubject.substring(pos + match.length)
4364
}
4365
if (pos !== -1 || currSubject !== "") result.push(currSubject);
4366
return result
4367
};
4368
p.__codePointAt = function(subject, idx) {
4369
var code = subject.charCodeAt(idx),
4370
hi, low;
4371
if (55296 <= code && code <= 56319) {
4372
hi = code;
4373
low = subject.charCodeAt(idx + 1);
4374
return (hi - 55296) * 1024 + (low - 56320) + 65536
4375
}
4376
return code
4377
};
4378
p.match = function(str, regexp) {
4379
return str.match(regexp)
4380
};
4381
p.__matches = function(str, regexp) {
4382
return (new RegExp(regexp)).test(str)
4383
};
4384
p.__startsWith = function(subject, prefix, toffset) {
4385
if (typeof subject !== "string") return subject.startsWith.apply(subject, removeFirstArgument(arguments));
4386
toffset = toffset || 0;
4387
if (toffset < 0 || toffset > subject.length) return false;
4388
return prefix === "" || prefix === subject ? true : subject.indexOf(prefix) === toffset
4389
};
4390
p.__endsWith = function(subject, suffix) {
4391
if (typeof subject !== "string") return subject.endsWith.apply(subject, removeFirstArgument(arguments));
4392
var suffixLen = suffix ? suffix.length : 0;
4393
return suffix === "" || suffix === subject ? true : subject.indexOf(suffix) === subject.length - suffixLen
4394
};
4395
p.__hashCode = function(subject) {
4396
if (subject.hashCode instanceof
4397
Function) return subject.hashCode.apply(subject, removeFirstArgument(arguments));
4398
return virtHashCode(subject)
4399
};
4400
p.__printStackTrace = function(subject) {
4401
p.println("Exception: " + subject.toString())
4402
};
4403
var logBuffer = [];
4404
p.println = function(message) {
4405
var bufferLen = logBuffer.length;
4406
if (bufferLen) {
4407
Processing.logger.log(logBuffer.join(""));
4408
logBuffer.length = 0
4409
}
4410
if (arguments.length === 0 && bufferLen === 0) Processing.logger.log("");
4411
else if (arguments.length !== 0) Processing.logger.log(message)
4412
};
4413
p.print = function(message) {
4414
logBuffer.push(message)
4415
};
4416
p.str = function(val) {
4417
if (val instanceof Array) {
4418
var arr = [];
4419
for (var i = 0; i < val.length; i++) arr.push(val[i].toString() + "");
4420
return arr
4421
}
4422
return val.toString() + ""
4423
};
4424
p.trim = function(str) {
4425
if (str instanceof Array) {
4426
var arr = [];
4427
for (var i = 0; i < str.length; i++) arr.push(str[i].replace(/^\s*/, "").replace(/\s*$/, "").replace(/\r*$/, ""));
4428
return arr
4429
}
4430
return str.replace(/^\s*/, "").replace(/\s*$/, "").replace(/\r*$/, "")
4431
};
4432
4433
function booleanScalar(val) {
4434
if (typeof val === "number") return val !== 0;
4435
if (typeof val === "boolean") return val;
4436
if (typeof val === "string") return val.toLowerCase() === "true";
4437
if (val instanceof Char) return val.code === 49 || val.code === 84 || val.code === 116
4438
}
4439
p.parseBoolean = function(val) {
4440
if (val instanceof Array) {
4441
var ret = [];
4442
for (var i = 0; i < val.length; i++) ret.push(booleanScalar(val[i]));
4443
return ret
4444
}
4445
return booleanScalar(val)
4446
};
4447
p.parseByte = function(what) {
4448
if (what instanceof Array) {
4449
var bytes = [];
4450
for (var i = 0; i < what.length; i++) bytes.push(0 - (what[i] & 128) | what[i] & 127);
4451
return bytes
4452
}
4453
return 0 - (what & 128) | what & 127
4454
};
4455
p.parseChar = function(key) {
4456
if (typeof key === "number") return new Char(String.fromCharCode(key & 65535));
4457
if (key instanceof Array) {
4458
var ret = [];
4459
for (var i = 0; i < key.length; i++) ret.push(new Char(String.fromCharCode(key[i] & 65535)));
4460
return ret
4461
}
4462
throw "char() may receive only one argument of type int, byte, int[], or byte[].";
4463
};
4464
4465
function floatScalar(val) {
4466
if (typeof val === "number") return val;
4467
if (typeof val === "boolean") return val ? 1 : 0;
4468
if (typeof val === "string") return parseFloat(val);
4469
if (val instanceof Char) return val.code
4470
}
4471
p.parseFloat = function(val) {
4472
if (val instanceof
4473
Array) {
4474
var ret = [];
4475
for (var i = 0; i < val.length; i++) ret.push(floatScalar(val[i]));
4476
return ret
4477
}
4478
return floatScalar(val)
4479
};
4480
4481
function intScalar(val, radix) {
4482
if (typeof val === "number") return val & 4294967295;
4483
if (typeof val === "boolean") return val ? 1 : 0;
4484
if (typeof val === "string") {
4485
var number = parseInt(val, radix || 10);
4486
return number & 4294967295
4487
}
4488
if (val instanceof Char) return val.code
4489
}
4490
p.parseInt = function(val, radix) {
4491
if (val instanceof Array) {
4492
var ret = [];
4493
for (var i = 0; i < val.length; i++) if (typeof val[i] === "string" && !/^\s*[+\-]?\d+\s*$/.test(val[i])) ret.push(0);
4494
else ret.push(intScalar(val[i], radix));
4495
return ret
4496
}
4497
return intScalar(val, radix)
4498
};
4499
p.__int_cast = function(val) {
4500
return 0 | val
4501
};
4502
p.__instanceof = function(obj, type) {
4503
if (typeof type !== "function") throw "Function is expected as type argument for instanceof operator";
4504
if (typeof obj === "string") return type === Object || type === String;
4505
if (obj instanceof type) return true;
4506
if (typeof obj !== "object" || obj === null) return false;
4507
var objType = obj.constructor;
4508
if (type.$isInterface) {
4509
var interfaces = [];
4510
while (objType) {
4511
if (objType.$interfaces) interfaces = interfaces.concat(objType.$interfaces);
4512
objType = objType.$base
4513
}
4514
while (interfaces.length > 0) {
4515
var i = interfaces.shift();
4516
if (i === type) return true;
4517
if (i.$interfaces) interfaces = interfaces.concat(i.$interfaces)
4518
}
4519
return false
4520
}
4521
while (objType.hasOwnProperty("$base")) {
4522
objType = objType.$base;
4523
if (objType === type) return true
4524
}
4525
return false
4526
};
4527
p.abs = Math.abs;
4528
p.ceil = Math.ceil;
4529
p.constrain = function(aNumber, aMin, aMax) {
4530
return aNumber > aMax ? aMax : aNumber < aMin ? aMin : aNumber
4531
};
4532
p.dist = function() {
4533
var dx, dy, dz;
4534
if (arguments.length === 4) {
4535
dx = arguments[0] - arguments[2];
4536
dy = arguments[1] - arguments[3];
4537
return Math.sqrt(dx * dx + dy * dy)
4538
}
4539
if (arguments.length === 6) {
4540
dx = arguments[0] - arguments[3];
4541
dy = arguments[1] - arguments[4];
4542
dz = arguments[2] - arguments[5];
4543
return Math.sqrt(dx * dx + dy * dy + dz * dz)
4544
}
4545
};
4546
p.exp = Math.exp;
4547
p.floor = Math.floor;
4548
p.lerp = function(value1, value2, amt) {
4549
return (value2 - value1) * amt + value1
4550
};
4551
p.log = Math.log;
4552
p.mag = function(a, b, c) {
4553
if (c) return Math.sqrt(a * a + b * b + c * c);
4554
return Math.sqrt(a * a + b * b)
4555
};
4556
p.map = function(value, istart, istop, ostart, ostop) {
4557
return ostart + (ostop - ostart) * ((value - istart) / (istop - istart))
4558
};
4559
p.max = function() {
4560
if (arguments.length === 2) return arguments[0] < arguments[1] ? arguments[1] : arguments[0];
4561
var numbers = arguments.length === 1 ? arguments[0] : arguments;
4562
if (! ("length" in numbers && numbers.length > 0)) throw "Non-empty array is expected";
4563
var max = numbers[0],
4564
count = numbers.length;
4565
for (var i = 1; i < count; ++i) if (max < numbers[i]) max = numbers[i];
4566
return max
4567
};
4568
p.min = function() {
4569
if (arguments.length === 2) return arguments[0] < arguments[1] ? arguments[0] : arguments[1];
4570
var numbers = arguments.length === 1 ? arguments[0] : arguments;
4571
if (! ("length" in numbers && numbers.length > 0)) throw "Non-empty array is expected";
4572
var min = numbers[0],
4573
count = numbers.length;
4574
for (var i = 1; i < count; ++i) if (min > numbers[i]) min = numbers[i];
4575
return min
4576
};
4577
p.norm = function(aNumber, low, high) {
4578
return (aNumber - low) / (high - low)
4579
};
4580
p.pow = Math.pow;
4581
p.round = Math.round;
4582
p.sq = function(aNumber) {
4583
return aNumber * aNumber
4584
};
4585
p.sqrt = Math.sqrt;
4586
p.acos = Math.acos;
4587
p.asin = Math.asin;
4588
p.atan = Math.atan;
4589
p.atan2 = Math.atan2;
4590
p.cos = Math.cos;
4591
p.degrees = function(aAngle) {
4592
return aAngle * 180 / Math.PI
4593
};
4594
p.radians = function(aAngle) {
4595
return aAngle / 180 * Math.PI
4596
};
4597
p.sin = Math.sin;
4598
p.tan = Math.tan;
4599
var currentRandom = Math.random;
4600
p.random = function() {
4601
if (arguments.length === 0) return currentRandom();
4602
if (arguments.length === 1) return currentRandom() * arguments[0];
4603
var aMin = arguments[0],
4604
aMax = arguments[1];
4605
return currentRandom() * (aMax - aMin) + aMin
4606
};
4607
4608
function Marsaglia(i1, i2) {
4609
var z = i1 || 362436069,
4610
w = i2 || 521288629;
4611
var nextInt = function() {
4612
z = 36969 * (z & 65535) + (z >>> 16) & 4294967295;
4613
w = 18E3 * (w & 65535) + (w >>> 16) & 4294967295;
4614
return ((z & 65535) << 16 | w & 65535) & 4294967295
4615
};
4616
this.nextDouble = function() {
4617
var i = nextInt() / 4294967296;
4618
return i < 0 ? 1 + i : i
4619
};
4620
this.nextInt = nextInt
4621
}
4622
Marsaglia.createRandomized = function() {
4623
var now = new Date;
4624
return new Marsaglia(now / 6E4 & 4294967295, now & 4294967295)
4625
};
4626
p.randomSeed = function(seed) {
4627
currentRandom = (new Marsaglia(seed)).nextDouble
4628
};
4629
p.Random = function(seed) {
4630
var haveNextNextGaussian = false,
4631
nextNextGaussian, random;
4632
this.nextGaussian = function() {
4633
if (haveNextNextGaussian) {
4634
haveNextNextGaussian = false;
4635
return nextNextGaussian
4636
}
4637
var v1, v2, s;
4638
do {
4639
v1 = 2 * random() - 1;
4640
v2 = 2 * random() - 1;
4641
s = v1 * v1 + v2 * v2
4642
} while (s >= 1 || s === 0);
4643
var multiplier = Math.sqrt(-2 * Math.log(s) / s);
4644
nextNextGaussian = v2 * multiplier;
4645
haveNextNextGaussian = true;
4646
return v1 * multiplier
4647
};
4648
random = seed === undef ? Math.random : (new Marsaglia(seed)).nextDouble
4649
};
4650
4651
function PerlinNoise(seed) {
4652
var rnd = seed !== undef ? new Marsaglia(seed) : Marsaglia.createRandomized();
4653
var i, j;
4654
var perm = new Uint8Array(512);
4655
for (i = 0; i < 256; ++i) perm[i] = i;
4656
for (i = 0; i < 256; ++i) {
4657
var t = perm[j = rnd.nextInt() & 255];
4658
perm[j] = perm[i];
4659
perm[i] = t
4660
}
4661
for (i = 0; i < 256; ++i) perm[i + 256] = perm[i];
4662
4663
function grad3d(i, x, y, z) {
4664
var h = i & 15;
4665
var u = h < 8 ? x : y,
4666
v = h < 4 ? y : h === 12 || h === 14 ? x : z;
4667
return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v)
4668
}
4669
function grad2d(i, x, y) {
4670
var v = (i & 1) === 0 ? x : y;
4671
return (i & 2) === 0 ? -v : v
4672
}
4673
function grad1d(i, x) {
4674
return (i & 1) === 0 ? -x : x
4675
}
4676
function lerp(t, a, b) {
4677
return a + t * (b - a)
4678
}
4679
this.noise3d = function(x, y, z) {
4680
var X = Math.floor(x) & 255,
4681
Y = Math.floor(y) & 255,
4682
Z = Math.floor(z) & 255;
4683
x -= Math.floor(x);
4684
y -= Math.floor(y);
4685
z -= Math.floor(z);
4686
var fx = (3 - 2 * x) * x * x,
4687
fy = (3 - 2 * y) * y * y,
4688
fz = (3 - 2 * z) * z * z;
4689
var p0 = perm[X] + Y,
4690
p00 = perm[p0] + Z,
4691
p01 = perm[p0 + 1] + Z,
4692
p1 = perm[X + 1] + Y,
4693
p10 = perm[p1] + Z,
4694
p11 = perm[p1 + 1] + Z;
4695
return lerp(fz, lerp(fy, lerp(fx, grad3d(perm[p00], x, y, z), grad3d(perm[p10], x - 1, y, z)), lerp(fx, grad3d(perm[p01], x, y - 1, z), grad3d(perm[p11], x - 1, y - 1, z))), lerp(fy, lerp(fx, grad3d(perm[p00 + 1], x, y, z - 1), grad3d(perm[p10 + 1], x - 1, y, z - 1)), lerp(fx, grad3d(perm[p01 + 1], x, y - 1, z - 1), grad3d(perm[p11 + 1], x - 1, y - 1, z - 1))))
4696
};
4697
this.noise2d = function(x, y) {
4698
var X = Math.floor(x) & 255,
4699
Y = Math.floor(y) & 255;
4700
x -= Math.floor(x);
4701
y -= Math.floor(y);
4702
var fx = (3 - 2 * x) * x * x,
4703
fy = (3 - 2 * y) * y * y;
4704
var p0 = perm[X] + Y,
4705
p1 = perm[X + 1] + Y;
4706
return lerp(fy, lerp(fx, grad2d(perm[p0], x, y), grad2d(perm[p1], x - 1, y)), lerp(fx, grad2d(perm[p0 + 1], x, y - 1), grad2d(perm[p1 + 1], x - 1, y - 1)))
4707
};
4708
this.noise1d = function(x) {
4709
var X = Math.floor(x) & 255;
4710
x -= Math.floor(x);
4711
var fx = (3 - 2 * x) * x * x;
4712
return lerp(fx, grad1d(perm[X], x), grad1d(perm[X + 1], x - 1))
4713
}
4714
}
4715
var noiseProfile = {
4716
generator: undef,
4717
octaves: 4,
4718
fallout: 0.5,
4719
seed: undef
4720
};
4721
p.noise = function(x, y, z) {
4722
if (noiseProfile.generator === undef) noiseProfile.generator = new PerlinNoise(noiseProfile.seed);
4723
var generator = noiseProfile.generator;
4724
var effect = 1,
4725
k = 1,
4726
sum = 0;
4727
for (var i = 0; i < noiseProfile.octaves; ++i) {
4728
effect *= noiseProfile.fallout;
4729
switch (arguments.length) {
4730
case 1:
4731
sum += effect * (1 + generator.noise1d(k * x)) / 2;
4732
break;
4733
case 2:
4734
sum += effect * (1 + generator.noise2d(k * x, k * y)) / 2;
4735
break;
4736
case 3:
4737
sum += effect * (1 + generator.noise3d(k * x, k * y, k * z)) / 2;
4738
break
4739
}
4740
k *= 2
4741
}
4742
return sum
4743
};
4744
p.noiseDetail = function(octaves, fallout) {
4745
noiseProfile.octaves = octaves;
4746
if (fallout !== undef) noiseProfile.fallout = fallout
4747
};
4748
p.noiseSeed = function(seed) {
4749
noiseProfile.seed = seed;
4750
noiseProfile.generator = undef
4751
};
4752
DrawingShared.prototype.size = function(aWidth, aHeight, aMode) {
4753
if (doStroke) p.stroke(0);
4754
if (doFill) p.fill(255);
4755
var savedProperties = {
4756
fillStyle: curContext.fillStyle,
4757
strokeStyle: curContext.strokeStyle,
4758
lineCap: curContext.lineCap,
4759
lineJoin: curContext.lineJoin
4760
};
4761
if (curElement.style.length > 0) {
4762
curElement.style.removeProperty("width");
4763
curElement.style.removeProperty("height")
4764
}
4765
curElement.width = p.width = aWidth || 100;
4766
curElement.height = p.height = aHeight || 100;
4767
for (var prop in savedProperties) if (savedProperties.hasOwnProperty(prop)) curContext[prop] = savedProperties[prop];
4768
p.textFont(curTextFont);
4769
p.background();
4770
maxPixelsCached = Math.max(1E3, aWidth * aHeight * 0.05);
4771
p.externals.context = curContext;
4772
for (var i = 0; i < 720; i++) {
4773
sinLUT[i] = p.sin(i * (Math.PI / 180) * 0.5);
4774
cosLUT[i] = p.cos(i * (Math.PI / 180) * 0.5)
4775
}
4776
};
4777
Drawing2D.prototype.size = function(aWidth, aHeight, aMode) {
4778
if (curContext === undef) {
4779
curContext = curElement.getContext("2d");
4780
userMatrixStack = new PMatrixStack;
4781
userReverseMatrixStack = new PMatrixStack;
4782
modelView = new PMatrix2D;
4783
modelViewInv = new PMatrix2D
4784
}
4785
DrawingShared.prototype.size.apply(this, arguments)
4786
};
4787
Drawing3D.prototype.size = function() {
4788
var size3DCalled = false;
4789
return function size(aWidth, aHeight, aMode) {
4790
if (size3DCalled) throw "Multiple calls to size() for 3D renders are not allowed.";
4791
size3DCalled = true;
4792
4793
function getGLContext(canvas) {
4794
var ctxNames = ["experimental-webgl", "webgl", "webkit-3d"],
4795
gl;
4796
for (var i = 0, l = ctxNames.length; i < l; i++) {
4797
gl = canvas.getContext(ctxNames[i], {
4798
antialias: false,
4799
preserveDrawingBuffer: true
4800
});
4801
if (gl) break
4802
}
4803
return gl
4804
}
4805
try {
4806
curElement.width = p.width = aWidth || 100;
4807
curElement.height = p.height = aHeight || 100;
4808
curContext = getGLContext(curElement);
4809
canTex = curContext.createTexture();
4810
textTex = curContext.createTexture()
4811
} catch(e_size) {
4812
Processing.debug(e_size)
4813
}
4814
if (!curContext) throw "WebGL context is not supported on this browser.";
4815
curContext.viewport(0, 0, curElement.width, curElement.height);
4816
curContext.enable(curContext.DEPTH_TEST);
4817
curContext.enable(curContext.BLEND);
4818
curContext.blendFunc(curContext.SRC_ALPHA, curContext.ONE_MINUS_SRC_ALPHA);
4819
programObject2D = createProgramObject(curContext, vertexShaderSrc2D, fragmentShaderSrc2D);
4820
programObjectUnlitShape = createProgramObject(curContext, vertexShaderSrcUnlitShape, fragmentShaderSrcUnlitShape);
4821
p.strokeWeight(1);
4822
programObject3D = createProgramObject(curContext, vertexShaderSrc3D, fragmentShaderSrc3D);
4823
curContext.useProgram(programObject3D);
4824
uniformi("usingTexture3d", programObject3D, "usingTexture", usingTexture);
4825
p.lightFalloff(1, 0, 0);
4826
p.shininess(1);
4827
p.ambient(255, 255, 255);
4828
p.specular(0, 0, 0);
4829
p.emissive(0, 0, 0);
4830
boxBuffer = curContext.createBuffer();
4831
curContext.bindBuffer(curContext.ARRAY_BUFFER, boxBuffer);
4832
curContext.bufferData(curContext.ARRAY_BUFFER, boxVerts, curContext.STATIC_DRAW);
4833
boxNormBuffer = curContext.createBuffer();
4834
curContext.bindBuffer(curContext.ARRAY_BUFFER, boxNormBuffer);
4835
curContext.bufferData(curContext.ARRAY_BUFFER, boxNorms, curContext.STATIC_DRAW);
4836
boxOutlineBuffer = curContext.createBuffer();
4837
curContext.bindBuffer(curContext.ARRAY_BUFFER, boxOutlineBuffer);
4838
curContext.bufferData(curContext.ARRAY_BUFFER, boxOutlineVerts, curContext.STATIC_DRAW);
4839
rectBuffer = curContext.createBuffer();
4840
curContext.bindBuffer(curContext.ARRAY_BUFFER, rectBuffer);
4841
curContext.bufferData(curContext.ARRAY_BUFFER, rectVerts, curContext.STATIC_DRAW);
4842
rectNormBuffer = curContext.createBuffer();
4843
curContext.bindBuffer(curContext.ARRAY_BUFFER, rectNormBuffer);
4844
curContext.bufferData(curContext.ARRAY_BUFFER, rectNorms, curContext.STATIC_DRAW);
4845
sphereBuffer = curContext.createBuffer();
4846
lineBuffer = curContext.createBuffer();
4847
fillBuffer = curContext.createBuffer();
4848
fillColorBuffer = curContext.createBuffer();
4849
strokeColorBuffer = curContext.createBuffer();
4850
shapeTexVBO = curContext.createBuffer();
4851
pointBuffer = curContext.createBuffer();
4852
curContext.bindBuffer(curContext.ARRAY_BUFFER, pointBuffer);
4853
curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([0, 0, 0]), curContext.STATIC_DRAW);
4854
textBuffer = curContext.createBuffer();
4855
curContext.bindBuffer(curContext.ARRAY_BUFFER, textBuffer);
4856
curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0]), curContext.STATIC_DRAW);
4857
textureBuffer = curContext.createBuffer();
4858
curContext.bindBuffer(curContext.ARRAY_BUFFER, textureBuffer);
4859
curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]), curContext.STATIC_DRAW);
4860
indexBuffer = curContext.createBuffer();
4861
curContext.bindBuffer(curContext.ELEMENT_ARRAY_BUFFER, indexBuffer);
4862
curContext.bufferData(curContext.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 2, 3, 0]), curContext.STATIC_DRAW);
4863
cam = new PMatrix3D;
4864
cameraInv = new PMatrix3D;
4865
modelView = new PMatrix3D;
4866
modelViewInv = new PMatrix3D;
4867
projection = new PMatrix3D;
4868
p.camera();
4869
p.perspective();
4870
userMatrixStack = new PMatrixStack;
4871
userReverseMatrixStack = new PMatrixStack;
4872
curveBasisMatrix = new PMatrix3D;
4873
curveToBezierMatrix = new PMatrix3D;
4874
curveDrawMatrix = new PMatrix3D;
4875
bezierDrawMatrix = new PMatrix3D;
4876
bezierBasisInverse = new PMatrix3D;
4877
bezierBasisMatrix = new PMatrix3D;
4878
bezierBasisMatrix.set(-1, 3, -3, 1, 3, -6, 3, 0, -3, 3, 0, 0, 1, 0, 0, 0);
4879
DrawingShared.prototype.size.apply(this, arguments)
4880
}
4881
}();
4882
Drawing2D.prototype.ambientLight = DrawingShared.prototype.a3DOnlyFunction;
4883
Drawing3D.prototype.ambientLight = function(r, g, b, x, y, z) {
4884
if (lightCount === 8) throw "can only create " + 8 + " lights";
4885
var pos = new PVector(x, y, z);
4886
var view = new PMatrix3D;
4887
view.scale(1, -1, 1);
4888
view.apply(modelView.array());
4889
view.mult(pos, pos);
4890
var col = color$4(r, g, b, 0);
4891
var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];
4892
curContext.useProgram(programObject3D);
4893
uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol);
4894
uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array());
4895
uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 0);
4896
uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount)
4897
};
4898
Drawing2D.prototype.directionalLight = DrawingShared.prototype.a3DOnlyFunction;
4899
Drawing3D.prototype.directionalLight = function(r, g, b, nx, ny, nz) {
4900
if (lightCount === 8) throw "can only create " + 8 + " lights";
4901
curContext.useProgram(programObject3D);
4902
var mvm = new PMatrix3D;
4903
mvm.scale(1, -1, 1);
4904
mvm.apply(modelView.array());
4905
mvm = mvm.array();
4906
var dir = [mvm[0] * nx + mvm[4] * ny + mvm[8] * nz, mvm[1] * nx + mvm[5] * ny + mvm[9] * nz, mvm[2] * nx + mvm[6] * ny + mvm[10] * nz];
4907
var col = color$4(r, g, b, 0);
4908
var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];
4909
uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol);
4910
uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", dir);
4911
uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 1);
4912
uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount)
4913
};
4914
Drawing2D.prototype.lightFalloff = DrawingShared.prototype.a3DOnlyFunction;
4915
Drawing3D.prototype.lightFalloff = function(constant, linear, quadratic) {
4916
curContext.useProgram(programObject3D);
4917
uniformf("uFalloff3d", programObject3D, "uFalloff", [constant, linear, quadratic])
4918
};
4919
Drawing2D.prototype.lightSpecular = DrawingShared.prototype.a3DOnlyFunction;
4920
Drawing3D.prototype.lightSpecular = function(r, g, b) {
4921
var col = color$4(r, g, b, 0);
4922
var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];
4923
curContext.useProgram(programObject3D);
4924
uniformf("uSpecular3d", programObject3D, "uSpecular", normalizedCol)
4925
};
4926
p.lights = function() {
4927
p.ambientLight(128, 128, 128);
4928
p.directionalLight(128, 128, 128, 0, 0, -1);
4929
p.lightFalloff(1, 0, 0);
4930
p.lightSpecular(0, 0, 0)
4931
};
4932
Drawing2D.prototype.pointLight = DrawingShared.prototype.a3DOnlyFunction;
4933
Drawing3D.prototype.pointLight = function(r, g, b, x, y, z) {
4934
if (lightCount === 8) throw "can only create " + 8 + " lights";
4935
var pos = new PVector(x, y, z);
4936
var view = new PMatrix3D;
4937
view.scale(1, -1, 1);
4938
view.apply(modelView.array());
4939
view.mult(pos, pos);
4940
var col = color$4(r, g, b, 0);
4941
var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];
4942
curContext.useProgram(programObject3D);
4943
uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol);
4944
uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array());
4945
uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 2);
4946
uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount)
4947
};
4948
Drawing2D.prototype.noLights = DrawingShared.prototype.a3DOnlyFunction;
4949
Drawing3D.prototype.noLights = function() {
4950
lightCount = 0;
4951
curContext.useProgram(programObject3D);
4952
uniformi("uLightCount3d", programObject3D, "uLightCount", lightCount)
4953
};
4954
Drawing2D.prototype.spotLight = DrawingShared.prototype.a3DOnlyFunction;
4955
Drawing3D.prototype.spotLight = function(r, g, b, x, y, z, nx, ny, nz, angle, concentration) {
4956
if (lightCount === 8) throw "can only create " + 8 + " lights";
4957
curContext.useProgram(programObject3D);
4958
var pos = new PVector(x, y, z);
4959
var mvm = new PMatrix3D;
4960
mvm.scale(1, -1, 1);
4961
mvm.apply(modelView.array());
4962
mvm.mult(pos, pos);
4963
mvm = mvm.array();
4964
var dir = [mvm[0] * nx + mvm[4] * ny + mvm[8] * nz, mvm[1] *
4965
nx + mvm[5] * ny + mvm[9] * nz, mvm[2] * nx + mvm[6] * ny + mvm[10] * nz];
4966
var col = color$4(r, g, b, 0);
4967
var normalizedCol = [((col >> 16) & 255) / 255, ((col >> 8) & 255) / 255, (col & 255) / 255];
4968
uniformf("uLights.color.3d." + lightCount, programObject3D, "uLights" + lightCount + ".color", normalizedCol);
4969
uniformf("uLights.position.3d." + lightCount, programObject3D, "uLights" + lightCount + ".position", pos.array());
4970
uniformf("uLights.direction.3d." + lightCount, programObject3D, "uLights" + lightCount + ".direction", dir);
4971
uniformf("uLights.concentration.3d." + lightCount, programObject3D, "uLights" + lightCount + ".concentration", concentration);
4972
uniformf("uLights.angle.3d." + lightCount, programObject3D, "uLights" + lightCount + ".angle", angle);
4973
uniformi("uLights.type.3d." + lightCount, programObject3D, "uLights" + lightCount + ".type", 3);
4974
uniformi("uLightCount3d", programObject3D, "uLightCount", ++lightCount)
4975
};
4976
Drawing2D.prototype.beginCamera = function() {
4977
throw "beginCamera() is not available in 2D mode";
4978
};
4979
Drawing3D.prototype.beginCamera = function() {
4980
if (manipulatingCamera) throw "You cannot call beginCamera() again before calling endCamera()";
4981
manipulatingCamera = true;
4982
modelView = cameraInv;
4983
modelViewInv = cam
4984
};
4985
Drawing2D.prototype.endCamera = function() {
4986
throw "endCamera() is not available in 2D mode";
4987
};
4988
Drawing3D.prototype.endCamera = function() {
4989
if (!manipulatingCamera) throw "You cannot call endCamera() before calling beginCamera()";
4990
modelView.set(cam);
4991
modelViewInv.set(cameraInv);
4992
manipulatingCamera = false
4993
};
4994
p.camera = function(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ) {
4995
if (eyeX === undef) {
4996
cameraX = p.width / 2;
4997
cameraY = p.height / 2;
4998
cameraZ = cameraY / Math.tan(cameraFOV / 2);
4999
eyeX = cameraX;
5000
eyeY = cameraY;
5001
eyeZ = cameraZ;
5002
centerX = cameraX;
5003
centerY = cameraY;
5004
centerZ = 0;
5005
upX = 0;
5006
upY = 1;
5007
upZ = 0
5008
}
5009
var z = new PVector(eyeX - centerX, eyeY - centerY, eyeZ - centerZ);
5010
var y = new PVector(upX, upY, upZ);
5011
z.normalize();
5012
var x = PVector.cross(y, z);
5013
y = PVector.cross(z, x);
5014
x.normalize();
5015
y.normalize();
5016
var xX = x.x,
5017
xY = x.y,
5018
xZ = x.z;
5019
var yX = y.x,
5020
yY = y.y,
5021
yZ = y.z;
5022
var zX = z.x,
5023
zY = z.y,
5024
zZ = z.z;
5025
cam.set(xX, xY, xZ, 0, yX, yY, yZ, 0, zX, zY, zZ, 0, 0, 0, 0, 1);
5026
cam.translate(-eyeX, -eyeY, -eyeZ);
5027
cameraInv.reset();
5028
cameraInv.invApply(xX, xY, xZ, 0, yX, yY, yZ, 0, zX, zY, zZ, 0, 0, 0, 0, 1);
5029
cameraInv.translate(eyeX, eyeY, eyeZ);
5030
modelView.set(cam);
5031
modelViewInv.set(cameraInv)
5032
};
5033
p.perspective = function(fov, aspect, near, far) {
5034
if (arguments.length === 0) {
5035
cameraY = curElement.height / 2;
5036
cameraZ = cameraY / Math.tan(cameraFOV / 2);
5037
cameraNear = cameraZ / 10;
5038
cameraFar = cameraZ * 10;
5039
cameraAspect = p.width / p.height;
5040
fov = cameraFOV;
5041
aspect = cameraAspect;
5042
near = cameraNear;
5043
far = cameraFar
5044
}
5045
var yMax, yMin, xMax, xMin;
5046
yMax = near * Math.tan(fov / 2);
5047
yMin = -yMax;
5048
xMax = yMax * aspect;
5049
xMin = yMin * aspect;
5050
p.frustum(xMin, xMax, yMin, yMax, near, far)
5051
};
5052
Drawing2D.prototype.frustum = function() {
5053
throw "Processing.js: frustum() is not supported in 2D mode";
5054
};
5055
Drawing3D.prototype.frustum = function(left, right, bottom, top, near, far) {
5056
frustumMode = true;
5057
projection = new PMatrix3D;
5058
projection.set(2 * near / (right - left), 0, (right + left) / (right - left), 0, 0, 2 * near / (top - bottom), (top + bottom) / (top - bottom), 0, 0, 0, -(far + near) / (far - near), -(2 * far * near) / (far - near), 0, 0, -1, 0);
5059
var proj = new PMatrix3D;
5060
proj.set(projection);
5061
proj.transpose();
5062
curContext.useProgram(programObject2D);
5063
uniformMatrix("projection2d", programObject2D, "uProjection", false, proj.array());
5064
curContext.useProgram(programObject3D);
5065
uniformMatrix("projection3d", programObject3D, "uProjection", false, proj.array());
5066
curContext.useProgram(programObjectUnlitShape);
5067
uniformMatrix("uProjectionUS", programObjectUnlitShape, "uProjection", false, proj.array())
5068
};
5069
p.ortho = function(left, right, bottom, top, near, far) {
5070
if (arguments.length === 0) {
5071
left = 0;
5072
right = p.width;
5073
bottom = 0;
5074
top = p.height;
5075
near = -10;
5076
far = 10
5077
}
5078
var x = 2 / (right - left);
5079
var y = 2 / (top - bottom);
5080
var z = -2 / (far - near);
5081
var tx = -(right + left) / (right - left);
5082
var ty = -(top + bottom) / (top - bottom);
5083
var tz = -(far + near) / (far - near);
5084
projection = new PMatrix3D;
5085
projection.set(x, 0, 0, tx, 0, y, 0, ty, 0, 0, z, tz, 0, 0, 0, 1);
5086
var proj = new PMatrix3D;
5087
proj.set(projection);
5088
proj.transpose();
5089
curContext.useProgram(programObject2D);
5090
uniformMatrix("projection2d", programObject2D, "uProjection", false, proj.array());
5091
curContext.useProgram(programObject3D);
5092
uniformMatrix("projection3d", programObject3D, "uProjection", false, proj.array());
5093
curContext.useProgram(programObjectUnlitShape);
5094
uniformMatrix("uProjectionUS", programObjectUnlitShape, "uProjection", false, proj.array());
5095
frustumMode = false
5096
};
5097
p.printProjection = function() {
5098
projection.print()
5099
};
5100
p.printCamera = function() {
5101
cam.print()
5102
};
5103
Drawing2D.prototype.box = DrawingShared.prototype.a3DOnlyFunction;
5104
Drawing3D.prototype.box = function(w, h, d) {
5105
if (!h || !d) h = d = w;
5106
var model = new PMatrix3D;
5107
model.scale(w, h, d);
5108
var view = new PMatrix3D;
5109
view.scale(1, -1, 1);
5110
view.apply(modelView.array());
5111
view.transpose();
5112
if (doFill) {
5113
curContext.useProgram(programObject3D);
5114
uniformMatrix("model3d", programObject3D, "uModel", false, model.array());
5115
uniformMatrix("view3d", programObject3D, "uView", false, view.array());
5116
curContext.enable(curContext.POLYGON_OFFSET_FILL);
5117
curContext.polygonOffset(1, 1);
5118
uniformf("color3d", programObject3D, "uColor", fillStyle);
5119
if (lightCount > 0) {
5120
var v = new PMatrix3D;
5121
v.set(view);
5122
var m = new PMatrix3D;
5123
m.set(model);
5124
v.mult(m);
5125
var normalMatrix = new PMatrix3D;
5126
normalMatrix.set(v);
5127
normalMatrix.invert();
5128
normalMatrix.transpose();
5129
uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array());
5130
vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, boxNormBuffer)
5131
} else disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal");
5132
vertexAttribPointer("aVertex3d", programObject3D, "aVertex", 3, boxBuffer);
5133
disableVertexAttribPointer("aColor3d", programObject3D, "aColor");
5134
disableVertexAttribPointer("aTexture3d", programObject3D, "aTexture");
5135
curContext.drawArrays(curContext.TRIANGLES, 0, boxVerts.length / 3);
5136
curContext.disable(curContext.POLYGON_OFFSET_FILL)
5137
}
5138
if (lineWidth > 0 && doStroke) {
5139
curContext.useProgram(programObject2D);
5140
uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());
5141
uniformMatrix("uView2d", programObject2D, "uView", false, view.array());
5142
uniformf("uColor2d", programObject2D, "uColor", strokeStyle);
5143
uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false);
5144
vertexAttribPointer("vertex2d", programObject2D, "aVertex", 3, boxOutlineBuffer);
5145
disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");
5146
curContext.drawArrays(curContext.LINES, 0, boxOutlineVerts.length / 3)
5147
}
5148
};
5149
var initSphere = function() {
5150
var i;
5151
sphereVerts = [];
5152
for (i = 0; i < sphereDetailU; i++) {
5153
sphereVerts.push(0);
5154
sphereVerts.push(-1);
5155
sphereVerts.push(0);
5156
sphereVerts.push(sphereX[i]);
5157
sphereVerts.push(sphereY[i]);
5158
sphereVerts.push(sphereZ[i])
5159
}
5160
sphereVerts.push(0);
5161
sphereVerts.push(-1);
5162
sphereVerts.push(0);
5163
sphereVerts.push(sphereX[0]);
5164
sphereVerts.push(sphereY[0]);
5165
sphereVerts.push(sphereZ[0]);
5166
var v1, v11, v2;
5167
var voff = 0;
5168
for (i = 2; i < sphereDetailV; i++) {
5169
v1 = v11 = voff;
5170
voff += sphereDetailU;
5171
v2 = voff;
5172
for (var j = 0; j < sphereDetailU; j++) {
5173
sphereVerts.push(sphereX[v1]);
5174
sphereVerts.push(sphereY[v1]);
5175
sphereVerts.push(sphereZ[v1++]);
5176
sphereVerts.push(sphereX[v2]);
5177
sphereVerts.push(sphereY[v2]);
5178
sphereVerts.push(sphereZ[v2++])
5179
}
5180
v1 = v11;
5181
v2 = voff;
5182
sphereVerts.push(sphereX[v1]);
5183
sphereVerts.push(sphereY[v1]);
5184
sphereVerts.push(sphereZ[v1]);
5185
sphereVerts.push(sphereX[v2]);
5186
sphereVerts.push(sphereY[v2]);
5187
sphereVerts.push(sphereZ[v2])
5188
}
5189
for (i = 0; i < sphereDetailU; i++) {
5190
v2 = voff + i;
5191
sphereVerts.push(sphereX[v2]);
5192
sphereVerts.push(sphereY[v2]);
5193
sphereVerts.push(sphereZ[v2]);
5194
sphereVerts.push(0);
5195
sphereVerts.push(1);
5196
sphereVerts.push(0)
5197
}
5198
sphereVerts.push(sphereX[voff]);
5199
sphereVerts.push(sphereY[voff]);
5200
sphereVerts.push(sphereZ[voff]);
5201
sphereVerts.push(0);
5202
sphereVerts.push(1);
5203
sphereVerts.push(0);
5204
curContext.bindBuffer(curContext.ARRAY_BUFFER, sphereBuffer);
5205
curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(sphereVerts), curContext.STATIC_DRAW)
5206
};
5207
p.sphereDetail = function(ures, vres) {
5208
var i;
5209
if (arguments.length === 1) ures = vres = arguments[0];
5210
if (ures < 3) ures = 3;
5211
if (vres < 2) vres = 2;
5212
if (ures === sphereDetailU && vres === sphereDetailV) return;
5213
var delta = 720 / ures;
5214
var cx = new Float32Array(ures);
5215
var cz = new Float32Array(ures);
5216
for (i = 0; i < ures; i++) {
5217
cx[i] = cosLUT[i * delta % 720 | 0];
5218
cz[i] = sinLUT[i * delta % 720 | 0]
5219
}
5220
var vertCount = ures * (vres - 1) + 2;
5221
var currVert = 0;
5222
sphereX = new Float32Array(vertCount);
5223
sphereY = new Float32Array(vertCount);
5224
sphereZ = new Float32Array(vertCount);
5225
var angle_step = 720 * 0.5 / vres;
5226
var angle = angle_step;
5227
for (i = 1; i < vres; i++) {
5228
var curradius = sinLUT[angle % 720 | 0];
5229
var currY = -cosLUT[angle % 720 | 0];
5230
for (var j = 0; j < ures; j++) {
5231
sphereX[currVert] = cx[j] * curradius;
5232
sphereY[currVert] = currY;
5233
sphereZ[currVert++] = cz[j] * curradius
5234
}
5235
angle += angle_step
5236
}
5237
sphereDetailU = ures;
5238
sphereDetailV = vres;
5239
initSphere()
5240
};
5241
Drawing2D.prototype.sphere = DrawingShared.prototype.a3DOnlyFunction;
5242
Drawing3D.prototype.sphere = function() {
5243
var sRad = arguments[0];
5244
if (sphereDetailU < 3 || sphereDetailV < 2) p.sphereDetail(30);
5245
var model = new PMatrix3D;
5246
model.scale(sRad, sRad, sRad);
5247
var view = new PMatrix3D;
5248
view.scale(1, -1, 1);
5249
view.apply(modelView.array());
5250
view.transpose();
5251
if (doFill) {
5252
if (lightCount > 0) {
5253
var v = new PMatrix3D;
5254
v.set(view);
5255
var m = new PMatrix3D;
5256
m.set(model);
5257
v.mult(m);
5258
var normalMatrix = new PMatrix3D;
5259
normalMatrix.set(v);
5260
normalMatrix.invert();
5261
normalMatrix.transpose();
5262
uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array());
5263
vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, sphereBuffer)
5264
} else disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal");
5265
curContext.useProgram(programObject3D);
5266
disableVertexAttribPointer("aTexture3d", programObject3D, "aTexture");
5267
uniformMatrix("uModel3d", programObject3D, "uModel", false, model.array());
5268
uniformMatrix("uView3d", programObject3D, "uView", false, view.array());
5269
vertexAttribPointer("aVertex3d", programObject3D, "aVertex", 3, sphereBuffer);
5270
disableVertexAttribPointer("aColor3d", programObject3D, "aColor");
5271
curContext.enable(curContext.POLYGON_OFFSET_FILL);
5272
curContext.polygonOffset(1, 1);
5273
uniformf("uColor3d", programObject3D, "uColor", fillStyle);
5274
curContext.drawArrays(curContext.TRIANGLE_STRIP, 0, sphereVerts.length / 3);
5275
curContext.disable(curContext.POLYGON_OFFSET_FILL)
5276
}
5277
if (lineWidth > 0 && doStroke) {
5278
curContext.useProgram(programObject2D);
5279
uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());
5280
uniformMatrix("uView2d", programObject2D, "uView", false, view.array());
5281
vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, sphereBuffer);
5282
disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");
5283
uniformf("uColor2d", programObject2D, "uColor", strokeStyle);
5284
uniformi("uIsDrawingText", programObject2D, "uIsDrawingText", false);
5285
curContext.drawArrays(curContext.LINE_STRIP, 0, sphereVerts.length / 3)
5286
}
5287
};
5288
p.modelX = function(x, y, z) {
5289
var mv = modelView.array();
5290
var ci = cameraInv.array();
5291
var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
5292
var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
5293
var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
5294
var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
5295
var ox = ci[0] * ax + ci[1] * ay + ci[2] * az + ci[3] * aw;
5296
var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw;
5297
return ow !== 0 ? ox / ow : ox
5298
};
5299
p.modelY = function(x, y, z) {
5300
var mv = modelView.array();
5301
var ci = cameraInv.array();
5302
var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
5303
var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
5304
var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
5305
var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
5306
var oy = ci[4] * ax + ci[5] * ay + ci[6] * az + ci[7] * aw;
5307
var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw;
5308
return ow !== 0 ? oy / ow : oy
5309
};
5310
p.modelZ = function(x, y, z) {
5311
var mv = modelView.array();
5312
var ci = cameraInv.array();
5313
var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
5314
var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
5315
var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
5316
var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
5317
var oz = ci[8] * ax + ci[9] * ay + ci[10] * az + ci[11] * aw;
5318
var ow = ci[12] * ax + ci[13] * ay + ci[14] * az + ci[15] * aw;
5319
return ow !== 0 ? oz / ow : oz
5320
};
5321
Drawing2D.prototype.ambient = DrawingShared.prototype.a3DOnlyFunction;
5322
Drawing3D.prototype.ambient = function(v1, v2, v3) {
5323
curContext.useProgram(programObject3D);
5324
uniformi("uUsingMat3d", programObject3D, "uUsingMat", true);
5325
var col = p.color(v1, v2, v3);
5326
uniformf("uMaterialAmbient3d", programObject3D, "uMaterialAmbient", p.color.toGLArray(col).slice(0, 3))
5327
};
5328
Drawing2D.prototype.emissive = DrawingShared.prototype.a3DOnlyFunction;
5329
Drawing3D.prototype.emissive = function(v1, v2, v3) {
5330
curContext.useProgram(programObject3D);
5331
uniformi("uUsingMat3d", programObject3D, "uUsingMat", true);
5332
var col = p.color(v1, v2, v3);
5333
uniformf("uMaterialEmissive3d", programObject3D, "uMaterialEmissive", p.color.toGLArray(col).slice(0, 3))
5334
};
5335
Drawing2D.prototype.shininess = DrawingShared.prototype.a3DOnlyFunction;
5336
Drawing3D.prototype.shininess = function(shine) {
5337
curContext.useProgram(programObject3D);
5338
uniformi("uUsingMat3d", programObject3D, "uUsingMat", true);
5339
uniformf("uShininess3d", programObject3D, "uShininess", shine)
5340
};
5341
Drawing2D.prototype.specular = DrawingShared.prototype.a3DOnlyFunction;
5342
Drawing3D.prototype.specular = function(v1, v2, v3) {
5343
curContext.useProgram(programObject3D);
5344
uniformi("uUsingMat3d", programObject3D, "uUsingMat", true);
5345
var col = p.color(v1, v2, v3);
5346
uniformf("uMaterialSpecular3d", programObject3D, "uMaterialSpecular", p.color.toGLArray(col).slice(0, 3))
5347
};
5348
p.screenX = function(x, y, z) {
5349
var mv = modelView.array();
5350
if (mv.length === 16) {
5351
var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
5352
var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
5353
var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
5354
var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
5355
var pj = projection.array();
5356
var ox = pj[0] * ax + pj[1] * ay + pj[2] * az + pj[3] * aw;
5357
var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw;
5358
if (ow !== 0) ox /= ow;
5359
return p.width * (1 + ox) / 2
5360
}
5361
return modelView.multX(x, y)
5362
};
5363
p.screenY = function screenY(x, y, z) {
5364
var mv = modelView.array();
5365
if (mv.length === 16) {
5366
var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
5367
var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
5368
var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
5369
var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
5370
var pj = projection.array();
5371
var oy = pj[4] * ax + pj[5] * ay + pj[6] * az + pj[7] * aw;
5372
var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw;
5373
if (ow !== 0) oy /= ow;
5374
return p.height * (1 + oy) / 2
5375
}
5376
return modelView.multY(x, y)
5377
};
5378
p.screenZ = function screenZ(x, y, z) {
5379
var mv = modelView.array();
5380
if (mv.length !== 16) return 0;
5381
var pj = projection.array();
5382
var ax = mv[0] * x + mv[1] * y + mv[2] * z + mv[3];
5383
var ay = mv[4] * x + mv[5] * y + mv[6] * z + mv[7];
5384
var az = mv[8] * x + mv[9] * y + mv[10] * z + mv[11];
5385
var aw = mv[12] * x + mv[13] * y + mv[14] * z + mv[15];
5386
var oz = pj[8] * ax + pj[9] * ay + pj[10] * az + pj[11] * aw;
5387
var ow = pj[12] * ax + pj[13] * ay + pj[14] * az + pj[15] * aw;
5388
if (ow !== 0) oz /= ow;
5389
return (oz + 1) / 2
5390
};
5391
DrawingShared.prototype.fill = function() {
5392
var color = p.color(arguments[0], arguments[1], arguments[2], arguments[3]);
5393
if (color === currentFillColor && doFill) return;
5394
doFill = true;
5395
currentFillColor = color
5396
};
5397
Drawing2D.prototype.fill = function() {
5398
DrawingShared.prototype.fill.apply(this, arguments);
5399
isFillDirty = true
5400
};
5401
Drawing3D.prototype.fill = function() {
5402
DrawingShared.prototype.fill.apply(this, arguments);
5403
fillStyle = p.color.toGLArray(currentFillColor)
5404
};
5405
5406
function executeContextFill() {
5407
if (doFill) {
5408
if (isFillDirty) {
5409
curContext.fillStyle = p.color.toString(currentFillColor);
5410
isFillDirty = false
5411
}
5412
curContext.fill()
5413
}
5414
}
5415
p.noFill = function() {
5416
doFill = false
5417
};
5418
DrawingShared.prototype.stroke = function() {
5419
var color = p.color(arguments[0], arguments[1], arguments[2], arguments[3]);
5420
if (color === currentStrokeColor && doStroke) return;
5421
doStroke = true;
5422
currentStrokeColor = color
5423
};
5424
Drawing2D.prototype.stroke = function() {
5425
DrawingShared.prototype.stroke.apply(this, arguments);
5426
isStrokeDirty = true
5427
};
5428
Drawing3D.prototype.stroke = function() {
5429
DrawingShared.prototype.stroke.apply(this, arguments);
5430
strokeStyle = p.color.toGLArray(currentStrokeColor)
5431
};
5432
5433
function executeContextStroke() {
5434
if (doStroke) {
5435
if (isStrokeDirty) {
5436
curContext.strokeStyle = p.color.toString(currentStrokeColor);
5437
isStrokeDirty = false
5438
}
5439
curContext.stroke()
5440
}
5441
}
5442
p.noStroke = function() {
5443
doStroke = false
5444
};
5445
DrawingShared.prototype.strokeWeight = function(w) {
5446
lineWidth = w
5447
};
5448
Drawing2D.prototype.strokeWeight = function(w) {
5449
DrawingShared.prototype.strokeWeight.apply(this, arguments);
5450
curContext.lineWidth = w
5451
};
5452
Drawing3D.prototype.strokeWeight = function(w) {
5453
DrawingShared.prototype.strokeWeight.apply(this, arguments);
5454
curContext.useProgram(programObject2D);
5455
uniformf("pointSize2d", programObject2D, "uPointSize", w);
5456
curContext.useProgram(programObjectUnlitShape);
5457
uniformf("pointSizeUnlitShape", programObjectUnlitShape, "uPointSize", w);
5458
curContext.lineWidth(w)
5459
};
5460
p.strokeCap = function(value) {
5461
drawing.$ensureContext().lineCap = value
5462
};
5463
p.strokeJoin = function(value) {
5464
drawing.$ensureContext().lineJoin = value
5465
};
5466
Drawing2D.prototype.smooth = function() {
5467
renderSmooth = true;
5468
var style = curElement.style;
5469
style.setProperty("image-rendering", "optimizeQuality", "important");
5470
style.setProperty("-ms-interpolation-mode", "bicubic", "important");
5471
if (curContext.hasOwnProperty("mozImageSmoothingEnabled")) curContext.mozImageSmoothingEnabled = true
5472
};
5473
Drawing3D.prototype.smooth = function() {
5474
renderSmooth = true
5475
};
5476
Drawing2D.prototype.noSmooth = function() {
5477
renderSmooth = false;
5478
var style = curElement.style;
5479
style.setProperty("image-rendering", "optimizeSpeed", "important");
5480
style.setProperty("image-rendering", "-moz-crisp-edges", "important");
5481
style.setProperty("image-rendering", "-webkit-optimize-contrast", "important");
5482
style.setProperty("image-rendering", "optimize-contrast", "important");
5483
style.setProperty("-ms-interpolation-mode", "nearest-neighbor", "important");
5484
if (curContext.hasOwnProperty("mozImageSmoothingEnabled")) curContext.mozImageSmoothingEnabled = false
5485
};
5486
Drawing3D.prototype.noSmooth = function() {
5487
renderSmooth = false
5488
};
5489
Drawing2D.prototype.point = function(x, y) {
5490
if (!doStroke) return;
5491
x = Math.round(x);
5492
y = Math.round(y);
5493
curContext.fillStyle = p.color.toString(currentStrokeColor);
5494
isFillDirty = true;
5495
if (lineWidth > 1) {
5496
curContext.beginPath();
5497
curContext.arc(x, y, lineWidth / 2, 0, 6.283185307179586, false);
5498
curContext.fill()
5499
} else curContext.fillRect(x, y, 1, 1)
5500
};
5501
Drawing3D.prototype.point = function(x, y, z) {
5502
var model = new PMatrix3D;
5503
model.translate(x, y, z || 0);
5504
model.transpose();
5505
var view = new PMatrix3D;
5506
view.scale(1, -1, 1);
5507
view.apply(modelView.array());
5508
view.transpose();
5509
curContext.useProgram(programObject2D);
5510
uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());
5511
uniformMatrix("uView2d", programObject2D, "uView", false, view.array());
5512
if (lineWidth > 0 && doStroke) {
5513
uniformf("uColor2d", programObject2D, "uColor", strokeStyle);
5514
uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false);
5515
uniformi("uSmooth2d", programObject2D, "uSmooth", renderSmooth);
5516
vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, pointBuffer);
5517
disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");
5518
curContext.drawArrays(curContext.POINTS, 0, 1)
5519
}
5520
};
5521
p.beginShape = function(type) {
5522
curShape = type;
5523
curvePoints = [];
5524
vertArray = []
5525
};
5526
Drawing2D.prototype.vertex = function(x, y, moveTo) {
5527
var vert = [];
5528
if (firstVert) firstVert = false;
5529
vert["isVert"] = true;
5530
vert[0] = x;
5531
vert[1] = y;
5532
vert[2] = 0;
5533
vert[3] = 0;
5534
vert[4] = 0;
5535
vert[5] = currentFillColor;
5536
vert[6] = currentStrokeColor;
5537
vertArray.push(vert);
5538
if (moveTo) vertArray[vertArray.length - 1]["moveTo"] = moveTo
5539
};
5540
Drawing3D.prototype.vertex = function(x, y, z, u, v) {
5541
var vert = [];
5542
if (firstVert) firstVert = false;
5543
vert["isVert"] = true;
5544
if (v === undef && usingTexture) {
5545
v = u;
5546
u = z;
5547
z = 0
5548
}
5549
if (u !== undef && v !== undef) {
5550
if (curTextureMode === 2) {
5551
u /= curTexture.width;
5552
v /= curTexture.height
5553
}
5554
u = u > 1 ? 1 : u;
5555
u = u < 0 ? 0 : u;
5556
v = v > 1 ? 1 : v;
5557
v = v < 0 ? 0 : v
5558
}
5559
vert[0] = x;
5560
vert[1] = y;
5561
vert[2] = z || 0;
5562
vert[3] = u || 0;
5563
vert[4] = v || 0;
5564
vert[5] = fillStyle[0];
5565
vert[6] = fillStyle[1];
5566
vert[7] = fillStyle[2];
5567
vert[8] = fillStyle[3];
5568
vert[9] = strokeStyle[0];
5569
vert[10] = strokeStyle[1];
5570
vert[11] = strokeStyle[2];
5571
vert[12] = strokeStyle[3];
5572
vert[13] = normalX;
5573
vert[14] = normalY;
5574
vert[15] = normalZ;
5575
vertArray.push(vert)
5576
};
5577
var point3D = function(vArray, cArray) {
5578
var view = new PMatrix3D;
5579
view.scale(1, -1, 1);
5580
view.apply(modelView.array());
5581
view.transpose();
5582
curContext.useProgram(programObjectUnlitShape);
5583
uniformMatrix("uViewUS", programObjectUnlitShape, "uView", false, view.array());
5584
uniformi("uSmoothUS", programObjectUnlitShape, "uSmooth", renderSmooth);
5585
vertexAttribPointer("aVertexUS", programObjectUnlitShape, "aVertex", 3, pointBuffer);
5586
curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW);
5587
vertexAttribPointer("aColorUS", programObjectUnlitShape, "aColor", 4, fillColorBuffer);
5588
curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW);
5589
curContext.drawArrays(curContext.POINTS, 0, vArray.length / 3)
5590
};
5591
var line3D = function(vArray, mode, cArray) {
5592
var ctxMode;
5593
if (mode === "LINES") ctxMode = curContext.LINES;
5594
else if (mode === "LINE_LOOP") ctxMode = curContext.LINE_LOOP;
5595
else ctxMode = curContext.LINE_STRIP;
5596
var view = new PMatrix3D;
5597
view.scale(1, -1, 1);
5598
view.apply(modelView.array());
5599
view.transpose();
5600
curContext.useProgram(programObjectUnlitShape);
5601
uniformMatrix("uViewUS", programObjectUnlitShape, "uView", false, view.array());
5602
vertexAttribPointer("aVertexUS", programObjectUnlitShape, "aVertex", 3, lineBuffer);
5603
curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW);
5604
vertexAttribPointer("aColorUS", programObjectUnlitShape, "aColor", 4, strokeColorBuffer);
5605
curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW);
5606
curContext.drawArrays(ctxMode, 0, vArray.length / 3)
5607
};
5608
var fill3D = function(vArray, mode, cArray, tArray) {
5609
var ctxMode;
5610
if (mode === "TRIANGLES") ctxMode = curContext.TRIANGLES;
5611
else if (mode === "TRIANGLE_FAN") ctxMode = curContext.TRIANGLE_FAN;
5612
else ctxMode = curContext.TRIANGLE_STRIP;
5613
var view = new PMatrix3D;
5614
view.scale(1, -1, 1);
5615
view.apply(modelView.array());
5616
view.transpose();
5617
curContext.useProgram(programObject3D);
5618
uniformMatrix("model3d", programObject3D, "uModel", false, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
5619
uniformMatrix("view3d", programObject3D, "uView", false, view.array());
5620
curContext.enable(curContext.POLYGON_OFFSET_FILL);
5621
curContext.polygonOffset(1, 1);
5622
uniformf("color3d", programObject3D, "uColor", [-1, 0, 0, 0]);
5623
vertexAttribPointer("vertex3d", programObject3D, "aVertex", 3, fillBuffer);
5624
curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(vArray), curContext.STREAM_DRAW);
5625
if (usingTexture && curTint !== null) curTint3d(cArray);
5626
vertexAttribPointer("aColor3d", programObject3D, "aColor", 4, fillColorBuffer);
5627
curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(cArray), curContext.STREAM_DRAW);
5628
disableVertexAttribPointer("aNormal3d", programObject3D, "aNormal");
5629
if (usingTexture) {
5630
uniformi("uUsingTexture3d", programObject3D, "uUsingTexture", usingTexture);
5631
vertexAttribPointer("aTexture3d", programObject3D, "aTexture", 2, shapeTexVBO);
5632
curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(tArray), curContext.STREAM_DRAW)
5633
}
5634
curContext.drawArrays(ctxMode, 0, vArray.length / 3);
5635
curContext.disable(curContext.POLYGON_OFFSET_FILL)
5636
};
5637
5638
function fillStrokeClose() {
5639
executeContextFill();
5640
executeContextStroke();
5641
curContext.closePath()
5642
}
5643
Drawing2D.prototype.endShape = function(mode) {
5644
if (vertArray.length === 0) return;
5645
var closeShape = mode === 2;
5646
if (closeShape) vertArray.push(vertArray[0]);
5647
var lineVertArray = [];
5648
var fillVertArray = [];
5649
var colorVertArray = [];
5650
var strokeVertArray = [];
5651
var texVertArray = [];
5652
var cachedVertArray;
5653
firstVert = true;
5654
var i, j, k;
5655
var vertArrayLength = vertArray.length;
5656
for (i = 0; i < vertArrayLength; i++) {
5657
cachedVertArray = vertArray[i];
5658
for (j = 0; j < 3; j++) fillVertArray.push(cachedVertArray[j])
5659
}
5660
for (i = 0; i < vertArrayLength; i++) {
5661
cachedVertArray = vertArray[i];
5662
for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j])
5663
}
5664
for (i = 0; i < vertArrayLength; i++) {
5665
cachedVertArray = vertArray[i];
5666
for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j])
5667
}
5668
for (i = 0; i < vertArrayLength; i++) {
5669
cachedVertArray = vertArray[i];
5670
texVertArray.push(cachedVertArray[3]);
5671
texVertArray.push(cachedVertArray[4])
5672
}
5673
if (isCurve && (curShape === 20 || curShape === undef)) {
5674
if (vertArrayLength > 3) {
5675
var b = [],
5676
s = 1 - curTightness;
5677
curContext.beginPath();
5678
curContext.moveTo(vertArray[1][0], vertArray[1][1]);
5679
for (i = 1; i + 2 < vertArrayLength; i++) {
5680
cachedVertArray = vertArray[i];
5681
b[0] = [cachedVertArray[0], cachedVertArray[1]];
5682
b[1] = [cachedVertArray[0] + (s * vertArray[i + 1][0] - s * vertArray[i - 1][0]) / 6, cachedVertArray[1] + (s * vertArray[i + 1][1] - s * vertArray[i - 1][1]) / 6];
5683
b[2] = [vertArray[i + 1][0] + (s * vertArray[i][0] - s * vertArray[i + 2][0]) / 6, vertArray[i + 1][1] + (s * vertArray[i][1] - s * vertArray[i + 2][1]) / 6];
5684
b[3] = [vertArray[i + 1][0], vertArray[i + 1][1]];
5685
curContext.bezierCurveTo(b[1][0], b[1][1], b[2][0], b[2][1], b[3][0], b[3][1])
5686
}
5687
fillStrokeClose()
5688
}
5689
} else if (isBezier && (curShape === 20 || curShape === undef)) {
5690
curContext.beginPath();
5691
for (i = 0; i < vertArrayLength; i++) {
5692
cachedVertArray = vertArray[i];
5693
if (vertArray[i]["isVert"]) if (vertArray[i]["moveTo"]) curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);
5694
else curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);
5695
else curContext.bezierCurveTo(vertArray[i][0], vertArray[i][1], vertArray[i][2], vertArray[i][3], vertArray[i][4], vertArray[i][5])
5696
}
5697
fillStrokeClose()
5698
} else if (curShape === 2) for (i = 0; i < vertArrayLength; i++) {
5699
cachedVertArray = vertArray[i];
5700
if (doStroke) p.stroke(cachedVertArray[6]);
5701
p.point(cachedVertArray[0], cachedVertArray[1])
5702
} else if (curShape === 4) for (i = 0; i + 1 < vertArrayLength; i += 2) {
5703
cachedVertArray = vertArray[i];
5704
if (doStroke) p.stroke(vertArray[i + 1][6]);
5705
p.line(cachedVertArray[0], cachedVertArray[1], vertArray[i + 1][0], vertArray[i + 1][1])
5706
} else if (curShape === 9) for (i = 0; i + 2 < vertArrayLength; i += 3) {
5707
cachedVertArray = vertArray[i];
5708
curContext.beginPath();
5709
curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);
5710
curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1]);
5711
curContext.lineTo(vertArray[i + 2][0], vertArray[i + 2][1]);
5712
curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);
5713
if (doFill) {
5714
p.fill(vertArray[i + 2][5]);
5715
executeContextFill()
5716
}
5717
if (doStroke) {
5718
p.stroke(vertArray[i + 2][6]);
5719
executeContextStroke()
5720
}
5721
curContext.closePath()
5722
} else if (curShape === 10) for (i = 0; i + 1 < vertArrayLength; i++) {
5723
cachedVertArray = vertArray[i];
5724
curContext.beginPath();
5725
curContext.moveTo(vertArray[i + 1][0], vertArray[i + 1][1]);
5726
curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);
5727
if (doStroke) p.stroke(vertArray[i + 1][6]);
5728
if (doFill) p.fill(vertArray[i + 1][5]);
5729
if (i + 2 < vertArrayLength) {
5730
curContext.lineTo(vertArray[i + 2][0], vertArray[i + 2][1]);
5731
if (doStroke) p.stroke(vertArray[i + 2][6]);
5732
if (doFill) p.fill(vertArray[i + 2][5])
5733
}
5734
fillStrokeClose()
5735
} else if (curShape === 11) {
5736
if (vertArrayLength > 2) {
5737
curContext.beginPath();
5738
curContext.moveTo(vertArray[0][0], vertArray[0][1]);
5739
curContext.lineTo(vertArray[1][0], vertArray[1][1]);
5740
curContext.lineTo(vertArray[2][0], vertArray[2][1]);
5741
if (doFill) {
5742
p.fill(vertArray[2][5]);
5743
executeContextFill()
5744
}
5745
if (doStroke) {
5746
p.stroke(vertArray[2][6]);
5747
executeContextStroke()
5748
}
5749
curContext.closePath();
5750
for (i = 3; i < vertArrayLength; i++) {
5751
cachedVertArray = vertArray[i];
5752
curContext.beginPath();
5753
curContext.moveTo(vertArray[0][0], vertArray[0][1]);
5754
curContext.lineTo(vertArray[i - 1][0], vertArray[i - 1][1]);
5755
curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);
5756
if (doFill) {
5757
p.fill(cachedVertArray[5]);
5758
executeContextFill()
5759
}
5760
if (doStroke) {
5761
p.stroke(cachedVertArray[6]);
5762
executeContextStroke()
5763
}
5764
curContext.closePath()
5765
}
5766
}
5767
} else if (curShape === 16) for (i = 0; i + 3 < vertArrayLength; i += 4) {
5768
cachedVertArray = vertArray[i];
5769
curContext.beginPath();
5770
curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);
5771
for (j = 1; j < 4; j++) curContext.lineTo(vertArray[i + j][0], vertArray[i + j][1]);
5772
curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);
5773
if (doFill) {
5774
p.fill(vertArray[i + 3][5]);
5775
executeContextFill()
5776
}
5777
if (doStroke) {
5778
p.stroke(vertArray[i + 3][6]);
5779
executeContextStroke()
5780
}
5781
curContext.closePath()
5782
} else if (curShape === 17) {
5783
if (vertArrayLength > 3) for (i = 0; i + 1 < vertArrayLength; i += 2) {
5784
cachedVertArray = vertArray[i];
5785
curContext.beginPath();
5786
if (i + 3 < vertArrayLength) {
5787
curContext.moveTo(vertArray[i + 2][0], vertArray[i + 2][1]);
5788
curContext.lineTo(cachedVertArray[0], cachedVertArray[1]);
5789
curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1]);
5790
curContext.lineTo(vertArray[i + 3][0], vertArray[i + 3][1]);
5791
if (doFill) p.fill(vertArray[i + 3][5]);
5792
if (doStroke) p.stroke(vertArray[i + 3][6])
5793
} else {
5794
curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);
5795
curContext.lineTo(vertArray[i + 1][0], vertArray[i + 1][1])
5796
}
5797
fillStrokeClose()
5798
}
5799
} else {
5800
curContext.beginPath();
5801
curContext.moveTo(vertArray[0][0], vertArray[0][1]);
5802
for (i = 1; i < vertArrayLength; i++) {
5803
cachedVertArray = vertArray[i];
5804
if (cachedVertArray["isVert"]) if (cachedVertArray["moveTo"]) curContext.moveTo(cachedVertArray[0], cachedVertArray[1]);
5805
else curContext.lineTo(cachedVertArray[0], cachedVertArray[1])
5806
}
5807
fillStrokeClose()
5808
}
5809
isCurve = false;
5810
isBezier = false;
5811
curveVertArray = [];
5812
curveVertCount = 0;
5813
if (closeShape) vertArray.pop()
5814
};
5815
Drawing3D.prototype.endShape = function(mode) {
5816
if (vertArray.length === 0) return;
5817
var closeShape = mode === 2;
5818
var lineVertArray = [];
5819
var fillVertArray = [];
5820
var colorVertArray = [];
5821
var strokeVertArray = [];
5822
var texVertArray = [];
5823
var cachedVertArray;
5824
firstVert = true;
5825
var i, j, k;
5826
var vertArrayLength = vertArray.length;
5827
for (i = 0; i < vertArrayLength; i++) {
5828
cachedVertArray = vertArray[i];
5829
for (j = 0; j < 3; j++) fillVertArray.push(cachedVertArray[j])
5830
}
5831
for (i = 0; i < vertArrayLength; i++) {
5832
cachedVertArray = vertArray[i];
5833
for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j])
5834
}
5835
for (i = 0; i < vertArrayLength; i++) {
5836
cachedVertArray = vertArray[i];
5837
for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j])
5838
}
5839
for (i = 0; i < vertArrayLength; i++) {
5840
cachedVertArray = vertArray[i];
5841
texVertArray.push(cachedVertArray[3]);
5842
texVertArray.push(cachedVertArray[4])
5843
}
5844
if (closeShape) {
5845
fillVertArray.push(vertArray[0][0]);
5846
fillVertArray.push(vertArray[0][1]);
5847
fillVertArray.push(vertArray[0][2]);
5848
for (i = 5; i < 9; i++) colorVertArray.push(vertArray[0][i]);
5849
for (i = 9; i < 13; i++) strokeVertArray.push(vertArray[0][i]);
5850
texVertArray.push(vertArray[0][3]);
5851
texVertArray.push(vertArray[0][4])
5852
}
5853
if (isCurve && (curShape === 20 || curShape === undef)) {
5854
lineVertArray = fillVertArray;
5855
if (doStroke) line3D(lineVertArray, null, strokeVertArray);
5856
if (doFill) fill3D(fillVertArray, null, colorVertArray)
5857
} else if (isBezier && (curShape === 20 || curShape === undef)) {
5858
lineVertArray = fillVertArray;
5859
lineVertArray.splice(lineVertArray.length - 3);
5860
strokeVertArray.splice(strokeVertArray.length - 4);
5861
if (doStroke) line3D(lineVertArray, null, strokeVertArray);
5862
if (doFill) fill3D(fillVertArray, "TRIANGLES", colorVertArray)
5863
} else {
5864
if (curShape === 2) {
5865
for (i = 0; i < vertArrayLength; i++) {
5866
cachedVertArray = vertArray[i];
5867
for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j])
5868
}
5869
point3D(lineVertArray, strokeVertArray)
5870
} else if (curShape === 4) {
5871
for (i = 0; i < vertArrayLength; i++) {
5872
cachedVertArray = vertArray[i];
5873
for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j])
5874
}
5875
for (i = 0; i < vertArrayLength; i++) {
5876
cachedVertArray = vertArray[i];
5877
for (j = 5; j < 9; j++) colorVertArray.push(cachedVertArray[j])
5878
}
5879
line3D(lineVertArray, "LINES", strokeVertArray)
5880
} else if (curShape === 9) {
5881
if (vertArrayLength > 2) for (i = 0; i + 2 < vertArrayLength; i += 3) {
5882
fillVertArray = [];
5883
texVertArray = [];
5884
lineVertArray = [];
5885
colorVertArray = [];
5886
strokeVertArray = [];
5887
for (j = 0; j < 3; j++) for (k = 0; k < 3; k++) {
5888
lineVertArray.push(vertArray[i + j][k]);
5889
fillVertArray.push(vertArray[i + j][k])
5890
}
5891
for (j = 0; j < 3; j++) for (k = 3; k < 5; k++) texVertArray.push(vertArray[i + j][k]);
5892
for (j = 0; j < 3; j++) for (k = 5; k < 9; k++) {
5893
colorVertArray.push(vertArray[i + j][k]);
5894
strokeVertArray.push(vertArray[i + j][k + 4])
5895
}
5896
if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray);
5897
if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLES", colorVertArray, texVertArray)
5898
}
5899
} else if (curShape === 10) {
5900
if (vertArrayLength > 2) for (i = 0; i + 2 < vertArrayLength; i++) {
5901
lineVertArray = [];
5902
fillVertArray = [];
5903
strokeVertArray = [];
5904
colorVertArray = [];
5905
texVertArray = [];
5906
for (j = 0; j < 3; j++) for (k = 0; k < 3; k++) {
5907
lineVertArray.push(vertArray[i + j][k]);
5908
fillVertArray.push(vertArray[i + j][k])
5909
}
5910
for (j = 0; j < 3; j++) for (k = 3; k < 5; k++) texVertArray.push(vertArray[i + j][k]);
5911
for (j = 0; j < 3; j++) for (k = 5; k < 9; k++) {
5912
strokeVertArray.push(vertArray[i + j][k + 4]);
5913
colorVertArray.push(vertArray[i + j][k])
5914
}
5915
if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_STRIP", colorVertArray, texVertArray);
5916
if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray)
5917
}
5918
} else if (curShape === 11) {
5919
if (vertArrayLength > 2) {
5920
for (i = 0; i < 3; i++) {
5921
cachedVertArray = vertArray[i];
5922
for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j])
5923
}
5924
for (i = 0; i < 3; i++) {
5925
cachedVertArray = vertArray[i];
5926
for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j])
5927
}
5928
if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray);
5929
for (i = 2; i + 1 < vertArrayLength; i++) {
5930
lineVertArray = [];
5931
strokeVertArray = [];
5932
lineVertArray.push(vertArray[0][0]);
5933
lineVertArray.push(vertArray[0][1]);
5934
lineVertArray.push(vertArray[0][2]);
5935
strokeVertArray.push(vertArray[0][9]);
5936
strokeVertArray.push(vertArray[0][10]);
5937
strokeVertArray.push(vertArray[0][11]);
5938
strokeVertArray.push(vertArray[0][12]);
5939
for (j = 0; j < 2; j++) for (k = 0; k < 3; k++) lineVertArray.push(vertArray[i + j][k]);
5940
for (j = 0; j < 2; j++) for (k = 9; k < 13; k++) strokeVertArray.push(vertArray[i + j][k]);
5941
if (doStroke) line3D(lineVertArray, "LINE_STRIP", strokeVertArray)
5942
}
5943
if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray, texVertArray)
5944
}
5945
} else if (curShape === 16) for (i = 0; i + 3 < vertArrayLength; i += 4) {
5946
lineVertArray = [];
5947
for (j = 0; j < 4; j++) {
5948
cachedVertArray = vertArray[i + j];
5949
for (k = 0; k < 3; k++) lineVertArray.push(cachedVertArray[k])
5950
}
5951
if (doStroke) line3D(lineVertArray, "LINE_LOOP", strokeVertArray);
5952
if (doFill) {
5953
fillVertArray = [];
5954
colorVertArray = [];
5955
texVertArray = [];
5956
for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i][j]);
5957
for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i][j]);
5958
for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 1][j]);
5959
for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 1][j]);
5960
for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 3][j]);
5961
for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 3][j]);
5962
for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i + 2][j]);
5963
for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i + 2][j]);
5964
if (usingTexture) {
5965
texVertArray.push(vertArray[i + 0][3]);
5966
texVertArray.push(vertArray[i + 0][4]);
5967
texVertArray.push(vertArray[i + 1][3]);
5968
texVertArray.push(vertArray[i + 1][4]);
5969
texVertArray.push(vertArray[i + 3][3]);
5970
texVertArray.push(vertArray[i + 3][4]);
5971
texVertArray.push(vertArray[i + 2][3]);
5972
texVertArray.push(vertArray[i + 2][4])
5973
}
5974
fill3D(fillVertArray, "TRIANGLE_STRIP", colorVertArray, texVertArray)
5975
}
5976
} else if (curShape === 17) {
5977
var tempArray = [];
5978
if (vertArrayLength > 3) {
5979
for (i = 0; i < 2; i++) {
5980
cachedVertArray = vertArray[i];
5981
for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j])
5982
}
5983
for (i = 0; i < 2; i++) {
5984
cachedVertArray = vertArray[i];
5985
for (j = 9; j < 13; j++) strokeVertArray.push(cachedVertArray[j])
5986
}
5987
line3D(lineVertArray, "LINE_STRIP", strokeVertArray);
5988
if (vertArrayLength > 4 && vertArrayLength % 2 > 0) {
5989
tempArray = fillVertArray.splice(fillVertArray.length - 3);
5990
vertArray.pop()
5991
}
5992
for (i = 0; i + 3 < vertArrayLength; i += 2) {
5993
lineVertArray = [];
5994
strokeVertArray = [];
5995
for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 1][j]);
5996
for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 3][j]);
5997
for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 2][j]);
5998
for (j = 0; j < 3; j++) lineVertArray.push(vertArray[i + 0][j]);
5999
for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 1][j]);
6000
for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 3][j]);
6001
for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 2][j]);
6002
for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[i + 0][j]);
6003
if (doStroke) line3D(lineVertArray, "LINE_STRIP", strokeVertArray)
6004
}
6005
if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_LIST", colorVertArray, texVertArray)
6006
}
6007
} else if (vertArrayLength === 1) {
6008
for (j = 0; j < 3; j++) lineVertArray.push(vertArray[0][j]);
6009
for (j = 9; j < 13; j++) strokeVertArray.push(vertArray[0][j]);
6010
point3D(lineVertArray, strokeVertArray)
6011
} else {
6012
for (i = 0; i < vertArrayLength; i++) {
6013
cachedVertArray = vertArray[i];
6014
for (j = 0; j < 3; j++) lineVertArray.push(cachedVertArray[j]);
6015
for (j = 5; j < 9; j++) strokeVertArray.push(cachedVertArray[j])
6016
}
6017
if (doStroke && closeShape) line3D(lineVertArray, "LINE_LOOP", strokeVertArray);
6018
else if (doStroke && !closeShape) line3D(lineVertArray, "LINE_STRIP", strokeVertArray);
6019
if (doFill || usingTexture) fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray, texVertArray)
6020
}
6021
usingTexture = false;
6022
curContext.useProgram(programObject3D);
6023
uniformi("usingTexture3d", programObject3D, "uUsingTexture", usingTexture)
6024
}
6025
isCurve = false;
6026
isBezier = false;
6027
curveVertArray = [];
6028
curveVertCount = 0
6029
};
6030
var splineForward = function(segments, matrix) {
6031
var f = 1 / segments;
6032
var ff = f * f;
6033
var fff = ff * f;
6034
matrix.set(0, 0, 0, 1, fff, ff, f, 0, 6 * fff, 2 * ff, 0, 0, 6 * fff, 0, 0, 0)
6035
};
6036
var curveInit = function() {
6037
if (!curveDrawMatrix) {
6038
curveBasisMatrix = new PMatrix3D;
6039
curveDrawMatrix = new PMatrix3D;
6040
curveInited = true
6041
}
6042
var s = curTightness;
6043
curveBasisMatrix.set((s - 1) / 2, (s + 3) / 2, (-3 - s) / 2, (1 - s) / 2, 1 - s, (-5 - s) / 2, s + 2, (s - 1) / 2, (s - 1) / 2, 0, (1 - s) / 2, 0, 0, 1, 0, 0);
6044
splineForward(curveDet, curveDrawMatrix);
6045
if (!bezierBasisInverse) curveToBezierMatrix = new PMatrix3D;
6046
curveToBezierMatrix.set(curveBasisMatrix);
6047
curveToBezierMatrix.preApply(bezierBasisInverse);
6048
curveDrawMatrix.apply(curveBasisMatrix)
6049
};
6050
Drawing2D.prototype.bezierVertex = function() {
6051
isBezier = true;
6052
var vert = [];
6053
if (firstVert) throw "vertex() must be used at least once before calling bezierVertex()";
6054
for (var i = 0; i < arguments.length; i++) vert[i] = arguments[i];
6055
vertArray.push(vert);
6056
vertArray[vertArray.length - 1]["isVert"] = false
6057
};
6058
Drawing3D.prototype.bezierVertex = function() {
6059
isBezier = true;
6060
var vert = [];
6061
if (firstVert) throw "vertex() must be used at least once before calling bezierVertex()";
6062
if (arguments.length === 9) {
6063
if (bezierDrawMatrix === undef) bezierDrawMatrix = new PMatrix3D;
6064
var lastPoint = vertArray.length - 1;
6065
splineForward(bezDetail, bezierDrawMatrix);
6066
bezierDrawMatrix.apply(bezierBasisMatrix);
6067
var draw = bezierDrawMatrix.array();
6068
var x1 = vertArray[lastPoint][0],
6069
y1 = vertArray[lastPoint][1],
6070
z1 = vertArray[lastPoint][2];
6071
var xplot1 = draw[4] * x1 + draw[5] * arguments[0] + draw[6] * arguments[3] + draw[7] * arguments[6];
6072
var xplot2 = draw[8] * x1 + draw[9] * arguments[0] + draw[10] * arguments[3] + draw[11] * arguments[6];
6073
var xplot3 = draw[12] * x1 + draw[13] * arguments[0] + draw[14] * arguments[3] + draw[15] * arguments[6];
6074
var yplot1 = draw[4] * y1 + draw[5] * arguments[1] + draw[6] * arguments[4] + draw[7] * arguments[7];
6075
var yplot2 = draw[8] * y1 + draw[9] * arguments[1] + draw[10] * arguments[4] + draw[11] * arguments[7];
6076
var yplot3 = draw[12] * y1 + draw[13] * arguments[1] + draw[14] * arguments[4] + draw[15] * arguments[7];
6077
var zplot1 = draw[4] * z1 + draw[5] * arguments[2] + draw[6] * arguments[5] + draw[7] * arguments[8];
6078
var zplot2 = draw[8] * z1 + draw[9] * arguments[2] + draw[10] * arguments[5] + draw[11] * arguments[8];
6079
var zplot3 = draw[12] * z1 + draw[13] * arguments[2] + draw[14] * arguments[5] + draw[15] * arguments[8];
6080
for (var j = 0; j < bezDetail; j++) {
6081
x1 += xplot1;
6082
xplot1 += xplot2;
6083
xplot2 += xplot3;
6084
y1 += yplot1;
6085
yplot1 += yplot2;
6086
yplot2 += yplot3;
6087
z1 += zplot1;
6088
zplot1 += zplot2;
6089
zplot2 += zplot3;
6090
p.vertex(x1, y1, z1)
6091
}
6092
p.vertex(arguments[6], arguments[7], arguments[8])
6093
}
6094
};
6095
p.texture = function(pimage) {
6096
var curContext = drawing.$ensureContext();
6097
if (pimage.__texture) curContext.bindTexture(curContext.TEXTURE_2D, pimage.__texture);
6098
else if (pimage.localName === "canvas") {
6099
curContext.bindTexture(curContext.TEXTURE_2D, canTex);
6100
curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, pimage);
6101
curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR);
6102
curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR);
6103
curContext.generateMipmap(curContext.TEXTURE_2D);
6104
curTexture.width = pimage.width;
6105
curTexture.height = pimage.height
6106
} else {
6107
var texture = curContext.createTexture(),
6108
cvs = document.createElement("canvas"),
6109
cvsTextureCtx = cvs.getContext("2d"),
6110
pot;
6111
if (pimage.width & pimage.width - 1 === 0) cvs.width = pimage.width;
6112
else {
6113
pot = 1;
6114
while (pot < pimage.width) pot *= 2;
6115
cvs.width = pot
6116
}
6117
if (pimage.height & pimage.height - 1 === 0) cvs.height = pimage.height;
6118
else {
6119
pot = 1;
6120
while (pot < pimage.height) pot *= 2;
6121
cvs.height = pot
6122
}
6123
cvsTextureCtx.drawImage(pimage.sourceImg, 0, 0, pimage.width, pimage.height, 0, 0, cvs.width, cvs.height);
6124
curContext.bindTexture(curContext.TEXTURE_2D, texture);
6125
curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR_MIPMAP_LINEAR);
6126
curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR);
6127
curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_T, curContext.CLAMP_TO_EDGE);
6128
curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_S, curContext.CLAMP_TO_EDGE);
6129
curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, cvs);
6130
curContext.generateMipmap(curContext.TEXTURE_2D);
6131
pimage.__texture = texture;
6132
curTexture.width = pimage.width;
6133
curTexture.height = pimage.height
6134
}
6135
usingTexture = true;
6136
curContext.useProgram(programObject3D);
6137
uniformi("usingTexture3d", programObject3D, "uUsingTexture", usingTexture)
6138
};
6139
p.textureMode = function(mode) {
6140
curTextureMode = mode
6141
};
6142
var curveVertexSegment = function(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) {
6143
var x0 = x2;
6144
var y0 = y2;
6145
var z0 = z2;
6146
var draw = curveDrawMatrix.array();
6147
var xplot1 = draw[4] * x1 + draw[5] * x2 + draw[6] * x3 + draw[7] * x4;
6148
var xplot2 = draw[8] * x1 + draw[9] * x2 + draw[10] * x3 + draw[11] * x4;
6149
var xplot3 = draw[12] * x1 + draw[13] * x2 + draw[14] * x3 + draw[15] * x4;
6150
var yplot1 = draw[4] * y1 + draw[5] * y2 + draw[6] * y3 + draw[7] * y4;
6151
var yplot2 = draw[8] * y1 + draw[9] * y2 + draw[10] * y3 + draw[11] * y4;
6152
var yplot3 = draw[12] * y1 + draw[13] * y2 + draw[14] * y3 + draw[15] * y4;
6153
var zplot1 = draw[4] * z1 + draw[5] * z2 + draw[6] * z3 + draw[7] * z4;
6154
var zplot2 = draw[8] * z1 + draw[9] * z2 + draw[10] * z3 + draw[11] * z4;
6155
var zplot3 = draw[12] * z1 + draw[13] * z2 + draw[14] * z3 + draw[15] * z4;
6156
p.vertex(x0, y0, z0);
6157
for (var j = 0; j < curveDet; j++) {
6158
x0 += xplot1;
6159
xplot1 += xplot2;
6160
xplot2 += xplot3;
6161
y0 += yplot1;
6162
yplot1 += yplot2;
6163
yplot2 += yplot3;
6164
z0 += zplot1;
6165
zplot1 += zplot2;
6166
zplot2 += zplot3;
6167
p.vertex(x0, y0, z0)
6168
}
6169
};
6170
Drawing2D.prototype.curveVertex = function(x, y) {
6171
isCurve = true;
6172
p.vertex(x, y)
6173
};
6174
Drawing3D.prototype.curveVertex = function(x, y, z) {
6175
isCurve = true;
6176
if (!curveInited) curveInit();
6177
var vert = [];
6178
vert[0] = x;
6179
vert[1] = y;
6180
vert[2] = z;
6181
curveVertArray.push(vert);
6182
curveVertCount++;
6183
if (curveVertCount > 3) curveVertexSegment(curveVertArray[curveVertCount - 4][0], curveVertArray[curveVertCount - 4][1], curveVertArray[curveVertCount - 4][2], curveVertArray[curveVertCount - 3][0], curveVertArray[curveVertCount - 3][1], curveVertArray[curveVertCount - 3][2], curveVertArray[curveVertCount - 2][0], curveVertArray[curveVertCount - 2][1], curveVertArray[curveVertCount - 2][2], curveVertArray[curveVertCount - 1][0], curveVertArray[curveVertCount - 1][1], curveVertArray[curveVertCount - 1][2])
6184
};
6185
Drawing2D.prototype.curve = function(x1, y1, x2, y2, x3, y3, x4, y4) {
6186
p.beginShape();
6187
p.curveVertex(x1, y1);
6188
p.curveVertex(x2, y2);
6189
p.curveVertex(x3, y3);
6190
p.curveVertex(x4, y4);
6191
p.endShape()
6192
};
6193
Drawing3D.prototype.curve = function(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) {
6194
if (z4 !== undef) {
6195
p.beginShape();
6196
p.curveVertex(x1, y1, z1);
6197
p.curveVertex(x2, y2, z2);
6198
p.curveVertex(x3, y3, z3);
6199
p.curveVertex(x4, y4, z4);
6200
p.endShape();
6201
return
6202
}
6203
p.beginShape();
6204
p.curveVertex(x1, y1);
6205
p.curveVertex(z1, x2);
6206
p.curveVertex(y2, z2);
6207
p.curveVertex(x3, y3);
6208
p.endShape()
6209
};
6210
p.curveTightness = function(tightness) {
6211
curTightness = tightness
6212
};
6213
p.curveDetail = function(detail) {
6214
curveDet = detail;
6215
curveInit()
6216
};
6217
p.rectMode = function(aRectMode) {
6218
curRectMode = aRectMode
6219
};
6220
p.imageMode = function(mode) {
6221
switch (mode) {
6222
case 0:
6223
imageModeConvert = imageModeCorner;
6224
break;
6225
case 1:
6226
imageModeConvert = imageModeCorners;
6227
break;
6228
case 3:
6229
imageModeConvert = imageModeCenter;
6230
break;
6231
default:
6232
throw "Invalid imageMode";
6233
}
6234
};
6235
p.ellipseMode = function(aEllipseMode) {
6236
curEllipseMode = aEllipseMode
6237
};
6238
p.arc = function(x, y, width, height, start, stop) {
6239
if (width <= 0 || stop < start) return;
6240
if (curEllipseMode === 1) {
6241
width = width - x;
6242
height = height - y
6243
} else if (curEllipseMode === 2) {
6244
x = x - width;
6245
y = y - height;
6246
width = width * 2;
6247
height = height * 2
6248
} else if (curEllipseMode === 3) {
6249
x = x - width / 2;
6250
y = y - height / 2
6251
}
6252
while (start < 0) {
6253
start += 6.283185307179586;
6254
stop += 6.283185307179586
6255
}
6256
if (stop - start > 6.283185307179586) {
6257
start = 0;
6258
stop = 6.283185307179586
6259
}
6260
var hr = width / 2,
6261
vr = height / 2,
6262
centerX = x + hr,
6263
centerY = y + vr,
6264
startLUT = 0 | 0.5 + start * p.RAD_TO_DEG * 2,
6265
stopLUT = 0 | 0.5 + stop * p.RAD_TO_DEG * 2,
6266
i, j;
6267
if (doFill) {
6268
var savedStroke = doStroke;
6269
doStroke = false;
6270
p.beginShape();
6271
p.vertex(centerX, centerY);
6272
for (i = startLUT; i <= stopLUT; i++) {
6273
j = i % 720;
6274
p.vertex(centerX + cosLUT[j] * hr, centerY + sinLUT[j] * vr)
6275
}
6276
p.endShape(2);
6277
doStroke = savedStroke
6278
}
6279
if (doStroke) {
6280
var savedFill = doFill;
6281
doFill = false;
6282
p.beginShape();
6283
for (i = startLUT; i <= stopLUT; i++) {
6284
j = i % 720;
6285
p.vertex(centerX + cosLUT[j] * hr, centerY + sinLUT[j] * vr)
6286
}
6287
p.endShape();
6288
doFill = savedFill
6289
}
6290
};
6291
Drawing2D.prototype.line = function(x1, y1, x2, y2) {
6292
if (!doStroke) return;
6293
x1 = Math.round(x1);
6294
x2 = Math.round(x2);
6295
y1 = Math.round(y1);
6296
y2 = Math.round(y2);
6297
if (x1 === x2 && y1 === y2) {
6298
p.point(x1, y1);
6299
return
6300
}
6301
var swap = undef,
6302
lineCap = undef,
6303
drawCrisp = true,
6304
currentModelView = modelView.array(),
6305
identityMatrix = [1, 0, 0, 0, 1, 0];
6306
for (var i = 0; i < 6 && drawCrisp; i++) drawCrisp = currentModelView[i] === identityMatrix[i];
6307
if (drawCrisp) {
6308
if (x1 === x2) {
6309
if (y1 > y2) {
6310
swap = y1;
6311
y1 = y2;
6312
y2 = swap
6313
}
6314
y2++;
6315
if (lineWidth % 2 === 1) curContext.translate(0.5, 0)
6316
} else if (y1 === y2) {
6317
if (x1 > x2) {
6318
swap = x1;
6319
x1 = x2;
6320
x2 = swap
6321
}
6322
x2++;
6323
if (lineWidth % 2 === 1) curContext.translate(0, 0.5)
6324
}
6325
if (lineWidth === 1) {
6326
lineCap = curContext.lineCap;
6327
curContext.lineCap = "butt"
6328
}
6329
}
6330
curContext.beginPath();
6331
curContext.moveTo(x1 || 0, y1 || 0);
6332
curContext.lineTo(x2 || 0, y2 || 0);
6333
executeContextStroke();
6334
if (drawCrisp) {
6335
if (x1 === x2 && lineWidth % 2 === 1) curContext.translate(-0.5, 0);
6336
else if (y1 === y2 && lineWidth % 2 === 1) curContext.translate(0, -0.5);
6337
if (lineWidth === 1) curContext.lineCap = lineCap
6338
}
6339
};
6340
Drawing3D.prototype.line = function(x1, y1, z1, x2, y2, z2) {
6341
if (y2 === undef || z2 === undef) {
6342
z2 = 0;
6343
y2 = x2;
6344
x2 = z1;
6345
z1 = 0
6346
}
6347
if (x1 === x2 && y1 === y2 && z1 === z2) {
6348
p.point(x1, y1, z1);
6349
return
6350
}
6351
var lineVerts = [x1, y1, z1, x2, y2, z2];
6352
var view = new PMatrix3D;
6353
view.scale(1, -1, 1);
6354
view.apply(modelView.array());
6355
view.transpose();
6356
if (lineWidth > 0 && doStroke) {
6357
curContext.useProgram(programObject2D);
6358
uniformMatrix("uModel2d", programObject2D, "uModel", false, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
6359
uniformMatrix("uView2d", programObject2D, "uView", false, view.array());
6360
uniformf("uColor2d", programObject2D, "uColor", strokeStyle);
6361
uniformi("uIsDrawingText", programObject2D, "uIsDrawingText", false);
6362
vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, lineBuffer);
6363
disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");
6364
curContext.bufferData(curContext.ARRAY_BUFFER, new Float32Array(lineVerts), curContext.STREAM_DRAW);
6365
curContext.drawArrays(curContext.LINES, 0, 2)
6366
}
6367
};
6368
Drawing2D.prototype.bezier = function() {
6369
if (arguments.length !== 8) throw "You must use 8 parameters for bezier() in 2D mode";
6370
p.beginShape();
6371
p.vertex(arguments[0], arguments[1]);
6372
p.bezierVertex(arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7]);
6373
p.endShape()
6374
};
6375
Drawing3D.prototype.bezier = function() {
6376
if (arguments.length !== 12) throw "You must use 12 parameters for bezier() in 3D mode";
6377
p.beginShape();
6378
p.vertex(arguments[0], arguments[1], arguments[2]);
6379
p.bezierVertex(arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9], arguments[10], arguments[11]);
6380
p.endShape()
6381
};
6382
p.bezierDetail = function(detail) {
6383
bezDetail = detail
6384
};
6385
p.bezierPoint = function(a, b, c, d, t) {
6386
return (1 - t) * (1 - t) * (1 - t) * a + 3 * (1 - t) * (1 - t) * t * b + 3 * (1 - t) * t * t * c + t * t * t * d
6387
};
6388
p.bezierTangent = function(a, b, c, d, t) {
6389
return 3 * t * t * (-a + 3 * b - 3 * c + d) + 6 * t * (a - 2 * b + c) + 3 * (-a + b)
6390
};
6391
p.curvePoint = function(a, b, c, d, t) {
6392
return 0.5 * (2 * b + (-a + c) * t + (2 * a - 5 * b + 4 * c - d) * t * t + (-a + 3 * b - 3 * c + d) * t * t * t)
6393
};
6394
p.curveTangent = function(a, b, c, d, t) {
6395
return 0.5 * (-a + c + 2 * (2 * a - 5 * b + 4 * c - d) * t + 3 * (-a + 3 * b - 3 * c + d) * t * t)
6396
};
6397
p.triangle = function(x1, y1, x2, y2, x3, y3) {
6398
p.beginShape(9);
6399
p.vertex(x1, y1, 0);
6400
p.vertex(x2, y2, 0);
6401
p.vertex(x3, y3, 0);
6402
p.endShape()
6403
};
6404
p.quad = function(x1, y1, x2, y2, x3, y3, x4, y4) {
6405
p.beginShape(16);
6406
p.vertex(x1, y1, 0);
6407
p.vertex(x2, y2, 0);
6408
p.vertex(x3, y3, 0);
6409
p.vertex(x4, y4, 0);
6410
p.endShape()
6411
};
6412
var roundedRect$2d = function(x, y, width, height, tl, tr, br, bl) {
6413
if (bl === undef) {
6414
tr = tl;
6415
br = tl;
6416
bl = tl
6417
}
6418
var halfWidth = width / 2,
6419
halfHeight = height / 2;
6420
if (tl > halfWidth || tl > halfHeight) tl = Math.min(halfWidth, halfHeight);
6421
if (tr > halfWidth || tr > halfHeight) tr = Math.min(halfWidth, halfHeight);
6422
if (br > halfWidth || br > halfHeight) br = Math.min(halfWidth, halfHeight);
6423
if (bl > halfWidth || bl > halfHeight) bl = Math.min(halfWidth, halfHeight);
6424
if (!doFill || doStroke) curContext.translate(0.5, 0.5);
6425
curContext.beginPath();
6426
curContext.moveTo(x + tl, y);
6427
curContext.lineTo(x + width - tr, y);
6428
curContext.quadraticCurveTo(x + width, y, x + width, y + tr);
6429
curContext.lineTo(x + width, y + height - br);
6430
curContext.quadraticCurveTo(x + width, y + height, x + width - br, y + height);
6431
curContext.lineTo(x + bl, y + height);
6432
curContext.quadraticCurveTo(x, y + height, x, y + height - bl);
6433
curContext.lineTo(x, y + tl);
6434
curContext.quadraticCurveTo(x, y, x + tl, y);
6435
if (!doFill || doStroke) curContext.translate(-0.5, -0.5);
6436
executeContextFill();
6437
executeContextStroke()
6438
};
6439
Drawing2D.prototype.rect = function(x, y, width, height, tl, tr, br, bl) {
6440
if (!width && !height) return;
6441
if (curRectMode === 1) {
6442
width -= x;
6443
height -= y
6444
} else if (curRectMode === 2) {
6445
width *= 2;
6446
height *= 2;
6447
x -= width / 2;
6448
y -= height / 2
6449
} else if (curRectMode === 3) {
6450
x -= width / 2;
6451
y -= height / 2
6452
}
6453
x = Math.round(x);
6454
y = Math.round(y);
6455
width = Math.round(width);
6456
height = Math.round(height);
6457
if (tl !== undef) {
6458
roundedRect$2d(x, y, width, height, tl, tr, br, bl);
6459
return
6460
}
6461
if (doStroke && lineWidth % 2 === 1) curContext.translate(0.5, 0.5);
6462
curContext.beginPath();
6463
curContext.rect(x, y, width, height);
6464
executeContextFill();
6465
executeContextStroke();
6466
if (doStroke && lineWidth % 2 === 1) curContext.translate(-0.5, -0.5)
6467
};
6468
Drawing3D.prototype.rect = function(x, y, width, height, tl, tr, br, bl) {
6469
if (tl !== undef) throw "rect() with rounded corners is not supported in 3D mode";
6470
if (curRectMode === 1) {
6471
width -= x;
6472
height -= y
6473
} else if (curRectMode === 2) {
6474
width *= 2;
6475
height *= 2;
6476
x -= width / 2;
6477
y -= height / 2
6478
} else if (curRectMode === 3) {
6479
x -= width / 2;
6480
y -= height / 2
6481
}
6482
var model = new PMatrix3D;
6483
model.translate(x, y, 0);
6484
model.scale(width, height, 1);
6485
model.transpose();
6486
var view = new PMatrix3D;
6487
view.scale(1, -1, 1);
6488
view.apply(modelView.array());
6489
view.transpose();
6490
if (lineWidth > 0 && doStroke) {
6491
curContext.useProgram(programObject2D);
6492
uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());
6493
uniformMatrix("uView2d", programObject2D, "uView", false, view.array());
6494
uniformf("uColor2d", programObject2D, "uColor", strokeStyle);
6495
uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", false);
6496
vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, rectBuffer);
6497
disableVertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord");
6498
curContext.drawArrays(curContext.LINE_LOOP, 0, rectVerts.length / 3)
6499
}
6500
if (doFill) {
6501
curContext.useProgram(programObject3D);
6502
uniformMatrix("uModel3d", programObject3D, "uModel", false, model.array());
6503
uniformMatrix("uView3d", programObject3D, "uView", false, view.array());
6504
curContext.enable(curContext.POLYGON_OFFSET_FILL);
6505
curContext.polygonOffset(1, 1);
6506
uniformf("color3d", programObject3D, "uColor", fillStyle);
6507
if (lightCount > 0) {
6508
var v = new PMatrix3D;
6509
v.set(view);
6510
var m = new PMatrix3D;
6511
m.set(model);
6512
v.mult(m);
6513
var normalMatrix = new PMatrix3D;
6514
normalMatrix.set(v);
6515
normalMatrix.invert();
6516
normalMatrix.transpose();
6517
uniformMatrix("uNormalTransform3d", programObject3D, "uNormalTransform", false, normalMatrix.array());
6518
vertexAttribPointer("aNormal3d", programObject3D, "aNormal", 3, rectNormBuffer)
6519
} else disableVertexAttribPointer("normal3d", programObject3D, "aNormal");
6520
vertexAttribPointer("vertex3d", programObject3D, "aVertex", 3, rectBuffer);
6521
curContext.drawArrays(curContext.TRIANGLE_FAN, 0, rectVerts.length / 3);
6522
curContext.disable(curContext.POLYGON_OFFSET_FILL)
6523
}
6524
};
6525
Drawing2D.prototype.ellipse = function(x, y, width, height) {
6526
x = x || 0;
6527
y = y || 0;
6528
if (width <= 0 && height <= 0) return;
6529
if (curEllipseMode === 2) {
6530
width *= 2;
6531
height *= 2
6532
} else if (curEllipseMode === 1) {
6533
width = width - x;
6534
height = height - y;
6535
x += width / 2;
6536
y += height / 2
6537
} else if (curEllipseMode === 0) {
6538
x += width / 2;
6539
y += height / 2
6540
}
6541
if (width === height) {
6542
curContext.beginPath();
6543
curContext.arc(x, y, width / 2, 0, 6.283185307179586, false);
6544
executeContextFill();
6545
executeContextStroke()
6546
} else {
6547
var w = width / 2,
6548
h = height / 2,
6549
C = 0.5522847498307933,
6550
c_x = C * w,
6551
c_y = C * h;
6552
p.beginShape();
6553
p.vertex(x + w, y);
6554
p.bezierVertex(x + w, y - c_y, x + c_x, y - h, x, y - h);
6555
p.bezierVertex(x - c_x, y - h, x - w, y - c_y, x - w, y);
6556
p.bezierVertex(x - w, y + c_y, x - c_x, y + h, x, y + h);
6557
p.bezierVertex(x + c_x, y + h, x + w, y + c_y, x + w, y);
6558
p.endShape()
6559
}
6560
};
6561
Drawing3D.prototype.ellipse = function(x, y, width, height) {
6562
x = x || 0;
6563
y = y || 0;
6564
if (width <= 0 && height <= 0) return;
6565
if (curEllipseMode === 2) {
6566
width *= 2;
6567
height *= 2
6568
} else if (curEllipseMode === 1) {
6569
width = width - x;
6570
height = height - y;
6571
x += width / 2;
6572
y += height / 2
6573
} else if (curEllipseMode === 0) {
6574
x += width / 2;
6575
y += height / 2
6576
}
6577
var w = width / 2,
6578
h = height / 2,
6579
C = 0.5522847498307933,
6580
c_x = C * w,
6581
c_y = C * h;
6582
p.beginShape();
6583
p.vertex(x + w, y);
6584
p.bezierVertex(x + w, y - c_y, 0, x + c_x, y - h, 0, x, y - h, 0);
6585
p.bezierVertex(x - c_x, y - h, 0, x - w, y - c_y, 0, x - w, y, 0);
6586
p.bezierVertex(x - w, y + c_y, 0, x - c_x, y + h, 0, x, y + h, 0);
6587
p.bezierVertex(x + c_x, y + h, 0, x + w, y + c_y, 0, x + w, y, 0);
6588
p.endShape();
6589
if (doFill) {
6590
var xAv = 0,
6591
yAv = 0,
6592
i, j;
6593
for (i = 0; i < vertArray.length; i++) {
6594
xAv += vertArray[i][0];
6595
yAv += vertArray[i][1]
6596
}
6597
xAv /= vertArray.length;
6598
yAv /= vertArray.length;
6599
var vert = [],
6600
fillVertArray = [],
6601
colorVertArray = [];
6602
vert[0] = xAv;
6603
vert[1] = yAv;
6604
vert[2] = 0;
6605
vert[3] = 0;
6606
vert[4] = 0;
6607
vert[5] = fillStyle[0];
6608
vert[6] = fillStyle[1];
6609
vert[7] = fillStyle[2];
6610
vert[8] = fillStyle[3];
6611
vert[9] = strokeStyle[0];
6612
vert[10] = strokeStyle[1];
6613
vert[11] = strokeStyle[2];
6614
vert[12] = strokeStyle[3];
6615
vert[13] = normalX;
6616
vert[14] = normalY;
6617
vert[15] = normalZ;
6618
vertArray.unshift(vert);
6619
for (i = 0; i < vertArray.length; i++) {
6620
for (j = 0; j < 3; j++) fillVertArray.push(vertArray[i][j]);
6621
for (j = 5; j < 9; j++) colorVertArray.push(vertArray[i][j])
6622
}
6623
fill3D(fillVertArray, "TRIANGLE_FAN", colorVertArray)
6624
}
6625
};
6626
p.normal = function(nx, ny, nz) {
6627
if (arguments.length !== 3 || !(typeof nx === "number" && typeof ny === "number" && typeof nz === "number")) throw "normal() requires three numeric arguments.";
6628
normalX = nx;
6629
normalY = ny;
6630
normalZ = nz;
6631
if (curShape !== 0) if (normalMode === 0) normalMode = 1;
6632
else if (normalMode === 1) normalMode = 2
6633
};
6634
p.save = function(file, img) {
6635
if (img !== undef) return window.open(img.toDataURL(), "_blank");
6636
return window.open(p.externals.canvas.toDataURL(), "_blank")
6637
};
6638
var saveNumber = 0;
6639
p.saveFrame = function(file) {
6640
if (file === undef) file = "screen-####.png";
6641
var frameFilename = file.replace(/#+/, function(all) {
6642
var s = "" + saveNumber++;
6643
while (s.length < all.length) s = "0" + s;
6644
return s
6645
});
6646
p.save(frameFilename)
6647
};
6648
var utilityContext2d = document.createElement("canvas").getContext("2d");
6649
var canvasDataCache = [undef, undef, undef];
6650
6651
function getCanvasData(obj, w, h) {
6652
var canvasData = canvasDataCache.shift();
6653
if (canvasData === undef) {
6654
canvasData = {};
6655
canvasData.canvas = document.createElement("canvas");
6656
canvasData.context = canvasData.canvas.getContext("2d")
6657
}
6658
canvasDataCache.push(canvasData);
6659
var canvas = canvasData.canvas,
6660
context = canvasData.context,
6661
width = w || obj.width,
6662
height = h || obj.height;
6663
canvas.width = width;
6664
canvas.height = height;
6665
if (!obj) context.clearRect(0, 0, width, height);
6666
else if ("data" in obj) context.putImageData(obj, 0, 0);
6667
else {
6668
context.clearRect(0, 0, width, height);
6669
context.drawImage(obj, 0, 0, width, height)
6670
}
6671
return canvasData
6672
}
6673
function buildPixelsObject(pImage) {
6674
return {
6675
getLength: function(aImg) {
6676
return function() {
6677
if (aImg.isRemote) throw "Image is loaded remotely. Cannot get length.";
6678
else return aImg.imageData.data.length ? aImg.imageData.data.length / 4 : 0
6679
}
6680
}(pImage),
6681
getPixel: function(aImg) {
6682
return function(i) {
6683
var offset = i * 4,
6684
data = aImg.imageData.data;
6685
if (aImg.isRemote) throw "Image is loaded remotely. Cannot get pixels.";
6686
return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255
6687
}
6688
}(pImage),
6689
setPixel: function(aImg) {
6690
return function(i, c) {
6691
var offset = i * 4,
6692
data = aImg.imageData.data;
6693
if (aImg.isRemote) throw "Image is loaded remotely. Cannot set pixel.";
6694
data[offset + 0] = (c >> 16) & 255;
6695
data[offset + 1] = (c >> 8) & 255;
6696
data[offset + 2] = c & 255;
6697
data[offset + 3] = (c >> 24) & 255;
6698
aImg.__isDirty = true
6699
}
6700
}(pImage),
6701
toArray: function(aImg) {
6702
return function() {
6703
var arr = [],
6704
data = aImg.imageData.data,
6705
length = aImg.width * aImg.height;
6706
if (aImg.isRemote) throw "Image is loaded remotely. Cannot get pixels.";
6707
for (var i = 0, offset = 0; i < length; i++, offset += 4) arr.push((data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255);
6708
return arr
6709
}
6710
}(pImage),
6711
set: function(aImg) {
6712
return function(arr) {
6713
var offset, data, c;
6714
if (this.isRemote) throw "Image is loaded remotely. Cannot set pixels.";
6715
data = aImg.imageData.data;
6716
for (var i = 0, aL = arr.length; i < aL; i++) {
6717
c = arr[i];
6718
offset = i * 4;
6719
data[offset + 0] = (c >> 16) & 255;
6720
data[offset + 1] = (c >> 8) & 255;
6721
data[offset + 2] = c & 255;
6722
data[offset + 3] = (c >> 24) & 255
6723
}
6724
aImg.__isDirty = true
6725
}
6726
}(pImage)
6727
}
6728
}
6729
var PImage = function(aWidth, aHeight, aFormat) {
6730
this.__isDirty = false;
6731
if (aWidth instanceof HTMLImageElement) this.fromHTMLImageData(aWidth);
6732
else if (aHeight || aFormat) {
6733
this.width = aWidth || 1;
6734
this.height = aHeight || 1;
6735
var canvas = this.sourceImg = document.createElement("canvas");
6736
canvas.width = this.width;
6737
canvas.height = this.height;
6738
var imageData = this.imageData = canvas.getContext("2d").createImageData(this.width, this.height);
6739
this.format = aFormat === 2 || aFormat === 4 ? aFormat : 1;
6740
if (this.format === 1) for (var i = 3, data = this.imageData.data, len = data.length; i < len; i += 4) data[i] = 255;
6741
this.__isDirty = true;
6742
this.updatePixels()
6743
} else {
6744
this.width = 0;
6745
this.height = 0;
6746
this.imageData = utilityContext2d.createImageData(1, 1);
6747
this.format = 2
6748
}
6749
this.pixels = buildPixelsObject(this)
6750
};
6751
PImage.prototype = {
6752
__isPImage: true,
6753
updatePixels: function() {
6754
var canvas = this.sourceImg;
6755
if (canvas && canvas instanceof HTMLCanvasElement && this.__isDirty) canvas.getContext("2d").putImageData(this.imageData, 0, 0);
6756
this.__isDirty = false
6757
},
6758
fromHTMLImageData: function(htmlImg) {
6759
var canvasData = getCanvasData(htmlImg);
6760
try {
6761
var imageData = canvasData.context.getImageData(0, 0, htmlImg.width, htmlImg.height);
6762
this.fromImageData(imageData)
6763
} catch(e) {
6764
if (htmlImg.width && htmlImg.height) {
6765
this.isRemote = true;
6766
this.width = htmlImg.width;
6767
this.height = htmlImg.height
6768
}
6769
}
6770
this.sourceImg = htmlImg
6771
},
6772
"get": function(x, y, w, h) {
6773
if (!arguments.length) return p.get(this);
6774
if (arguments.length === 2) return p.get(x, y, this);
6775
if (arguments.length === 4) return p.get(x, y, w, h, this)
6776
},
6777
"set": function(x, y, c) {
6778
p.set(x, y, c, this);
6779
this.__isDirty = true
6780
},
6781
blend: function(srcImg, x, y, width, height, dx, dy, dwidth, dheight, MODE) {
6782
if (arguments.length === 9) p.blend(this, srcImg, x, y, width, height, dx, dy, dwidth, dheight, this);
6783
else if (arguments.length === 10) p.blend(srcImg, x, y, width, height, dx, dy, dwidth, dheight, MODE, this);
6784
delete this.sourceImg
6785
},
6786
copy: function(srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, dheight) {
6787
if (arguments.length === 8) p.blend(this, srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, 0, this);
6788
else if (arguments.length === 9) p.blend(srcImg, sx, sy, swidth, sheight, dx, dy, dwidth, dheight, 0, this);
6789
delete this.sourceImg
6790
},
6791
filter: function(mode, param) {
6792
if (arguments.length === 2) p.filter(mode, param, this);
6793
else if (arguments.length === 1) p.filter(mode, null, this);
6794
delete this.sourceImg
6795
},
6796
save: function(file) {
6797
p.save(file, this)
6798
},
6799
resize: function(w, h) {
6800
if (this.isRemote) throw "Image is loaded remotely. Cannot resize.";
6801
if (this.width !== 0 || this.height !== 0) {
6802
if (w === 0 && h !== 0) w = Math.floor(this.width / this.height * h);
6803
else if (h === 0 && w !== 0) h = Math.floor(this.height / this.width * w);
6804
var canvas = getCanvasData(this.imageData).canvas;
6805
var imageData = getCanvasData(canvas, w, h).context.getImageData(0, 0, w, h);
6806
this.fromImageData(imageData)
6807
}
6808
},
6809
mask: function(mask) {
6810
var obj = this.toImageData(),
6811
i, size;
6812
if (mask instanceof PImage || mask.__isPImage) if (mask.width === this.width && mask.height === this.height) {
6813
mask = mask.toImageData();
6814
for (i = 2, size = this.width * this.height * 4; i < size; i += 4) obj.data[i + 1] = mask.data[i]
6815
} else throw "mask must have the same dimensions as PImage.";
6816
else if (mask instanceof
6817
Array) if (this.width * this.height === mask.length) for (i = 0, size = mask.length; i < size; ++i) obj.data[i * 4 + 3] = mask[i];
6818
else throw "mask array must be the same length as PImage pixels array.";
6819
this.fromImageData(obj)
6820
},
6821
loadPixels: nop,
6822
toImageData: function() {
6823
if (this.isRemote) return this.sourceImg;
6824
if (!this.__isDirty) return this.imageData;
6825
var canvasData = getCanvasData(this.sourceImg);
6826
return canvasData.context.getImageData(0, 0, this.width, this.height)
6827
},
6828
toDataURL: function() {
6829
if (this.isRemote) throw "Image is loaded remotely. Cannot create dataURI.";
6830
var canvasData = getCanvasData(this.imageData);
6831
return canvasData.canvas.toDataURL()
6832
},
6833
fromImageData: function(canvasImg) {
6834
var w = canvasImg.width,
6835
h = canvasImg.height,
6836
canvas = document.createElement("canvas"),
6837
ctx = canvas.getContext("2d");
6838
this.width = canvas.width = w;
6839
this.height = canvas.height = h;
6840
ctx.putImageData(canvasImg, 0, 0);
6841
this.format = 2;
6842
this.imageData = canvasImg;
6843
this.sourceImg = canvas
6844
}
6845
};
6846
p.PImage = PImage;
6847
p.createImage = function(w, h, mode) {
6848
return new PImage(w, h, mode)
6849
};
6850
p.loadImage = function(file, type, callback) {
6851
if (type) file = file + "." + type;
6852
var pimg;
6853
if (curSketch.imageCache.images[file]) {
6854
pimg = new PImage(curSketch.imageCache.images[file]);
6855
pimg.loaded = true;
6856
return pimg
6857
}
6858
pimg = new PImage;
6859
var img = document.createElement("img");
6860
pimg.sourceImg = img;
6861
img.onload = function(aImage, aPImage, aCallback) {
6862
var image = aImage;
6863
var pimg = aPImage;
6864
var callback = aCallback;
6865
return function() {
6866
pimg.fromHTMLImageData(image);
6867
pimg.loaded = true;
6868
if (callback) callback()
6869
}
6870
}(img, pimg, callback);
6871
img.src = file;
6872
return pimg
6873
};
6874
p.requestImage = p.loadImage;
6875
6876
function get$2(x, y) {
6877
var data;
6878
if (x >= p.width || x < 0 || y < 0 || y >= p.height) return 0;
6879
if (isContextReplaced) {
6880
var offset = ((0 | x) + p.width * (0 | y)) * 4;
6881
data = p.imageData.data;
6882
return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255
6883
}
6884
data = p.toImageData(0 | x, 0 | y, 1, 1).data;
6885
return (data[3] & 255) << 24 | (data[0] & 255) << 16 | (data[1] & 255) << 8 | data[2] & 255
6886
}
6887
function get$3(x, y, img) {
6888
if (img.isRemote) throw "Image is loaded remotely. Cannot get x,y.";
6889
var offset = y * img.width * 4 + x * 4,
6890
data = img.imageData.data;
6891
return (data[offset + 3] & 255) << 24 | (data[offset] & 255) << 16 | (data[offset + 1] & 255) << 8 | data[offset + 2] & 255
6892
}
6893
function get$4(x, y, w, h) {
6894
var c = new PImage(w, h, 2);
6895
c.fromImageData(p.toImageData(x, y, w, h));
6896
return c
6897
}
6898
function get$5(x, y, w, h, img) {
6899
if (img.isRemote) throw "Image is loaded remotely. Cannot get x,y,w,h.";
6900
var c = new PImage(w, h, 2),
6901
cData = c.imageData.data,
6902
imgWidth = img.width,
6903
imgHeight = img.height,
6904
imgData = img.imageData.data;
6905
var startRow = Math.max(0, -y),
6906
startColumn = Math.max(0, -x),
6907
stopRow = Math.min(h, imgHeight - y),
6908
stopColumn = Math.min(w, imgWidth - x);
6909
for (var i = startRow; i < stopRow; ++i) {
6910
var sourceOffset = ((y + i) * imgWidth + (x + startColumn)) * 4;
6911
var targetOffset = (i * w + startColumn) * 4;
6912
for (var j = startColumn; j < stopColumn; ++j) {
6913
cData[targetOffset++] = imgData[sourceOffset++];
6914
cData[targetOffset++] = imgData[sourceOffset++];
6915
cData[targetOffset++] = imgData[sourceOffset++];
6916
cData[targetOffset++] = imgData[sourceOffset++]
6917
}
6918
}
6919
c.__isDirty = true;
6920
return c
6921
}
6922
p.get = function(x, y, w, h, img) {
6923
if (img !== undefined) return get$5(x, y, w, h, img);
6924
if (h !== undefined) return get$4(x, y, w, h);
6925
if (w !== undefined) return get$3(x, y, w);
6926
if (y !== undefined) return get$2(x, y);
6927
if (x !== undefined) return get$5(0, 0, x.width, x.height, x);
6928
return get$4(0, 0, p.width, p.height)
6929
};
6930
p.createGraphics = function(w, h, render) {
6931
var pg = new Processing;
6932
pg.size(w, h, render);
6933
pg.background(0, 0);
6934
return pg
6935
};
6936
6937
function resetContext() {
6938
if (isContextReplaced) {
6939
curContext = originalContext;
6940
isContextReplaced = false;
6941
p.updatePixels()
6942
}
6943
}
6944
6945
function SetPixelContextWrapper() {
6946
function wrapFunction(newContext, name) {
6947
function wrapper() {
6948
resetContext();
6949
curContext[name].apply(curContext, arguments)
6950
}
6951
newContext[name] = wrapper
6952
}
6953
function wrapProperty(newContext, name) {
6954
function getter() {
6955
resetContext();
6956
return curContext[name]
6957
}
6958
function setter(value) {
6959
resetContext();
6960
curContext[name] = value
6961
}
6962
p.defineProperty(newContext, name, {
6963
get: getter,
6964
set: setter
6965
})
6966
}
6967
for (var n in curContext) if (typeof curContext[n] === "function") wrapFunction(this, n);
6968
else wrapProperty(this, n)
6969
}
6970
function replaceContext() {
6971
if (isContextReplaced) return;
6972
p.loadPixels();
6973
if (proxyContext === null) {
6974
originalContext = curContext;
6975
proxyContext = new SetPixelContextWrapper
6976
}
6977
isContextReplaced = true;
6978
curContext = proxyContext;
6979
setPixelsCached = 0
6980
}
6981
function set$3(x, y, c) {
6982
if (x < p.width && x >= 0 && y >= 0 && y < p.height) {
6983
replaceContext();
6984
p.pixels.setPixel((0 | x) + p.width * (0 | y), c);
6985
if (++setPixelsCached > maxPixelsCached) resetContext()
6986
}
6987
}
6988
function set$4(x, y, obj, img) {
6989
if (img.isRemote) throw "Image is loaded remotely. Cannot set x,y.";
6990
var c = p.color.toArray(obj);
6991
var offset = y * img.width * 4 + x * 4;
6992
var data = img.imageData.data;
6993
data[offset] = c[0];
6994
data[offset + 1] = c[1];
6995
data[offset + 2] = c[2];
6996
data[offset + 3] = c[3]
6997
}
6998
p.set = function(x, y, obj, img) {
6999
var color, oldFill;
7000
if (arguments.length === 3) if (typeof obj === "number") set$3(x, y, obj);
7001
else {
7002
if (obj instanceof PImage || obj.__isPImage) p.image(obj, x, y)
7003
} else if (arguments.length === 4) set$4(x, y, obj, img)
7004
};
7005
p.imageData = {};
7006
p.pixels = {
7007
getLength: function() {
7008
return p.imageData.data.length ? p.imageData.data.length / 4 : 0
7009
},
7010
getPixel: function(i) {
7011
var offset = i * 4,
7012
data = p.imageData.data;
7013
return data[offset + 3] << 24 & 4278190080 | data[offset + 0] << 16 & 16711680 | data[offset + 1] << 8 & 65280 | data[offset + 2] & 255
7014
},
7015
setPixel: function(i, c) {
7016
var offset = i * 4,
7017
data = p.imageData.data;
7018
data[offset + 0] = (c & 16711680) >>> 16;
7019
data[offset + 1] = (c & 65280) >>> 8;
7020
data[offset + 2] = c & 255;
7021
data[offset + 3] = (c & 4278190080) >>> 24
7022
},
7023
toArray: function() {
7024
var arr = [],
7025
length = p.imageData.width * p.imageData.height,
7026
data = p.imageData.data;
7027
for (var i = 0, offset = 0; i < length; i++, offset += 4) arr.push(data[offset + 3] << 24 & 4278190080 | data[offset + 0] << 16 & 16711680 | data[offset + 1] << 8 & 65280 | data[offset + 2] & 255);
7028
return arr
7029
},
7030
set: function(arr) {
7031
for (var i = 0, aL = arr.length; i < aL; i++) this.setPixel(i, arr[i])
7032
}
7033
};
7034
p.loadPixels = function() {
7035
p.imageData = drawing.$ensureContext().getImageData(0, 0, p.width, p.height)
7036
};
7037
p.updatePixels = function() {
7038
if (p.imageData) drawing.$ensureContext().putImageData(p.imageData, 0, 0)
7039
};
7040
p.hint = function(which) {
7041
var curContext = drawing.$ensureContext();
7042
if (which === 4) {
7043
curContext.disable(curContext.DEPTH_TEST);
7044
curContext.depthMask(false);
7045
curContext.clear(curContext.DEPTH_BUFFER_BIT)
7046
} else if (which === -4) {
7047
curContext.enable(curContext.DEPTH_TEST);
7048
curContext.depthMask(true)
7049
} else if (which === -1 || which === 2) renderSmooth = true;
7050
else if (which === 1) renderSmooth = false
7051
};
7052
var backgroundHelper = function(arg1, arg2, arg3, arg4) {
7053
var obj;
7054
if (arg1 instanceof PImage || arg1.__isPImage) {
7055
obj = arg1;
7056
if (!obj.loaded) throw "Error using image in background(): PImage not loaded.";
7057
if (obj.width !== p.width || obj.height !== p.height) throw "Background image must be the same dimensions as the canvas.";
7058
} else obj = p.color(arg1, arg2, arg3, arg4);
7059
backgroundObj = obj
7060
};
7061
Drawing2D.prototype.background = function(arg1, arg2, arg3, arg4) {
7062
if (arg1 !== undef) backgroundHelper(arg1, arg2, arg3, arg4);
7063
if (backgroundObj instanceof PImage || backgroundObj.__isPImage) {
7064
saveContext();
7065
curContext.setTransform(1, 0, 0, 1, 0, 0);
7066
p.image(backgroundObj, 0, 0);
7067
restoreContext()
7068
} else {
7069
saveContext();
7070
curContext.setTransform(1, 0, 0, 1, 0, 0);
7071
if (p.alpha(backgroundObj) !== colorModeA) curContext.clearRect(0, 0, p.width, p.height);
7072
curContext.fillStyle = p.color.toString(backgroundObj);
7073
curContext.fillRect(0, 0, p.width, p.height);
7074
isFillDirty = true;
7075
restoreContext()
7076
}
7077
};
7078
Drawing3D.prototype.background = function(arg1, arg2, arg3, arg4) {
7079
if (arguments.length > 0) backgroundHelper(arg1, arg2, arg3, arg4);
7080
var c = p.color.toGLArray(backgroundObj);
7081
curContext.clearColor(c[0], c[1], c[2], c[3]);
7082
curContext.clear(curContext.COLOR_BUFFER_BIT | curContext.DEPTH_BUFFER_BIT)
7083
};
7084
Drawing2D.prototype.image = function(img, x, y, w, h) {
7085
x = Math.round(x);
7086
y = Math.round(y);
7087
if (img.width > 0) {
7088
var wid = w || img.width;
7089
var hgt = h || img.height;
7090
var bounds = imageModeConvert(x || 0, y || 0, w || img.width, h || img.height, arguments.length < 4);
7091
var fastImage = !!img.sourceImg && curTint === null;
7092
if (fastImage) {
7093
var htmlElement = img.sourceImg;
7094
if (img.__isDirty) img.updatePixels();
7095
curContext.drawImage(htmlElement, 0, 0, htmlElement.width, htmlElement.height, bounds.x, bounds.y, bounds.w, bounds.h)
7096
} else {
7097
var obj = img.toImageData();
7098
if (curTint !== null) {
7099
curTint(obj);
7100
img.__isDirty = true
7101
}
7102
curContext.drawImage(getCanvasData(obj).canvas, 0, 0, img.width, img.height, bounds.x, bounds.y, bounds.w, bounds.h)
7103
}
7104
}
7105
};
7106
Drawing3D.prototype.image = function(img, x, y, w, h) {
7107
if (img.width > 0) {
7108
x = Math.round(x);
7109
y = Math.round(y);
7110
w = w || img.width;
7111
h = h || img.height;
7112
p.beginShape(p.QUADS);
7113
p.texture(img);
7114
p.vertex(x, y, 0, 0, 0);
7115
p.vertex(x, y + h, 0, 0, h);
7116
p.vertex(x + w, y + h, 0, w, h);
7117
p.vertex(x + w, y, 0, w, 0);
7118
p.endShape()
7119
}
7120
};
7121
p.tint = function(a1, a2, a3, a4) {
7122
var tintColor = p.color(a1, a2, a3, a4);
7123
var r = p.red(tintColor) / colorModeX;
7124
var g = p.green(tintColor) / colorModeY;
7125
var b = p.blue(tintColor) / colorModeZ;
7126
var a = p.alpha(tintColor) / colorModeA;
7127
curTint = function(obj) {
7128
var data = obj.data,
7129
length = 4 * obj.width * obj.height;
7130
for (var i = 0; i < length;) {
7131
data[i++] *= r;
7132
data[i++] *= g;
7133
data[i++] *= b;
7134
data[i++] *= a
7135
}
7136
};
7137
curTint3d = function(data) {
7138
for (var i = 0; i < data.length;) {
7139
data[i++] = r;
7140
data[i++] = g;
7141
data[i++] = b;
7142
data[i++] = a
7143
}
7144
}
7145
};
7146
p.noTint = function() {
7147
curTint = null;
7148
curTint3d = null
7149
};
7150
p.copy = function(src, sx, sy, sw, sh, dx, dy, dw, dh) {
7151
if (dh === undef) {
7152
dh = dw;
7153
dw = dy;
7154
dy = dx;
7155
dx = sh;
7156
sh = sw;
7157
sw = sy;
7158
sy = sx;
7159
sx = src;
7160
src = p
7161
}
7162
p.blend(src, sx, sy, sw, sh, dx, dy, dw, dh, 0)
7163
};
7164
p.blend = function(src, sx, sy, sw, sh, dx, dy, dw, dh, mode, pimgdest) {
7165
if (src.isRemote) throw "Image is loaded remotely. Cannot blend image.";
7166
if (mode === undef) {
7167
mode = dh;
7168
dh = dw;
7169
dw = dy;
7170
dy = dx;
7171
dx = sh;
7172
sh = sw;
7173
sw = sy;
7174
sy = sx;
7175
sx = src;
7176
src = p
7177
}
7178
var sx2 = sx + sw,
7179
sy2 = sy + sh,
7180
dx2 = dx + dw,
7181
dy2 = dy + dh,
7182
dest = pimgdest || p;
7183
if (pimgdest === undef || mode === undef) p.loadPixels();
7184
src.loadPixels();
7185
if (src === p && p.intersect(sx, sy, sx2, sy2, dx, dy, dx2, dy2)) p.blit_resize(p.get(sx, sy, sx2 - sx, sy2 - sy), 0, 0, sx2 - sx - 1, sy2 - sy - 1, dest.imageData.data, dest.width, dest.height, dx, dy, dx2, dy2, mode);
7186
else p.blit_resize(src, sx, sy, sx2, sy2, dest.imageData.data, dest.width, dest.height, dx, dy, dx2, dy2, mode);
7187
if (pimgdest === undef) p.updatePixels()
7188
};
7189
var buildBlurKernel = function(r) {
7190
var radius = p.floor(r * 3.5),
7191
i, radiusi;
7192
radius = radius < 1 ? 1 : radius < 248 ? radius : 248;
7193
if (p.shared.blurRadius !== radius) {
7194
p.shared.blurRadius = radius;
7195
p.shared.blurKernelSize = 1 + (p.shared.blurRadius << 1);
7196
p.shared.blurKernel = new Float32Array(p.shared.blurKernelSize);
7197
var sharedBlurKernal = p.shared.blurKernel;
7198
var sharedBlurKernelSize = p.shared.blurKernelSize;
7199
var sharedBlurRadius = p.shared.blurRadius;
7200
for (i = 0; i < sharedBlurKernelSize; i++) sharedBlurKernal[i] = 0;
7201
var radiusiSquared = (radius - 1) * (radius - 1);
7202
for (i = 1; i < radius; i++) sharedBlurKernal[radius + i] = sharedBlurKernal[radiusi] = radiusiSquared;
7203
sharedBlurKernal[radius] = radius * radius
7204
}
7205
};
7206
var blurARGB = function(r, aImg) {
7207
var sum, cr, cg, cb, ca, c, m;
7208
var read, ri, ym, ymi, bk0;
7209
var wh = aImg.pixels.getLength();
7210
var r2 = new Float32Array(wh);
7211
var g2 = new Float32Array(wh);
7212
var b2 = new Float32Array(wh);
7213
var a2 = new Float32Array(wh);
7214
var yi = 0;
7215
var x, y, i, offset;
7216
buildBlurKernel(r);
7217
var aImgHeight = aImg.height;
7218
var aImgWidth = aImg.width;
7219
var sharedBlurKernelSize = p.shared.blurKernelSize;
7220
var sharedBlurRadius = p.shared.blurRadius;
7221
var sharedBlurKernal = p.shared.blurKernel;
7222
var pix = aImg.imageData.data;
7223
for (y = 0; y < aImgHeight; y++) {
7224
for (x = 0; x < aImgWidth; x++) {
7225
cb = cg = cr = ca = sum = 0;
7226
read = x - sharedBlurRadius;
7227
if (read < 0) {
7228
bk0 = -read;
7229
read = 0
7230
} else {
7231
if (read >= aImgWidth) break;
7232
bk0 = 0
7233
}
7234
for (i = bk0; i < sharedBlurKernelSize; i++) {
7235
if (read >= aImgWidth) break;
7236
offset = (read + yi) * 4;
7237
m = sharedBlurKernal[i];
7238
ca += m * pix[offset + 3];
7239
cr += m * pix[offset];
7240
cg += m * pix[offset + 1];
7241
cb += m * pix[offset + 2];
7242
sum += m;
7243
read++
7244
}
7245
ri = yi + x;
7246
a2[ri] = ca / sum;
7247
r2[ri] = cr / sum;
7248
g2[ri] = cg / sum;
7249
b2[ri] = cb / sum
7250
}
7251
yi += aImgWidth
7252
}
7253
yi = 0;
7254
ym = -sharedBlurRadius;
7255
ymi = ym * aImgWidth;
7256
for (y = 0; y < aImgHeight; y++) {
7257
for (x = 0; x < aImgWidth; x++) {
7258
cb = cg = cr = ca = sum = 0;
7259
if (ym < 0) {
7260
bk0 = ri = -ym;
7261
read = x
7262
} else {
7263
if (ym >= aImgHeight) break;
7264
bk0 = 0;
7265
ri = ym;
7266
read = x + ymi
7267
}
7268
for (i = bk0; i < sharedBlurKernelSize; i++) {
7269
if (ri >= aImgHeight) break;
7270
m = sharedBlurKernal[i];
7271
ca += m * a2[read];
7272
cr += m * r2[read];
7273
cg += m * g2[read];
7274
cb += m * b2[read];
7275
sum += m;
7276
ri++;
7277
read += aImgWidth
7278
}
7279
offset = (x + yi) * 4;
7280
pix[offset] = cr / sum;
7281
pix[offset + 1] = cg / sum;
7282
pix[offset + 2] = cb / sum;
7283
pix[offset + 3] = ca / sum
7284
}
7285
yi += aImgWidth;
7286
ymi += aImgWidth;
7287
ym++
7288
}
7289
};
7290
var dilate = function(isInverted, aImg) {
7291
var currIdx = 0;
7292
var maxIdx = aImg.pixels.getLength();
7293
var out = new Int32Array(maxIdx);
7294
var currRowIdx, maxRowIdx, colOrig, colOut, currLum;
7295
var idxRight, idxLeft, idxUp, idxDown, colRight, colLeft, colUp, colDown, lumRight, lumLeft, lumUp, lumDown;
7296
if (!isInverted) while (currIdx < maxIdx) {
7297
currRowIdx = currIdx;
7298
maxRowIdx = currIdx + aImg.width;
7299
while (currIdx < maxRowIdx) {
7300
colOrig = colOut = aImg.pixels.getPixel(currIdx);
7301
idxLeft = currIdx - 1;
7302
idxRight = currIdx + 1;
7303
idxUp = currIdx - aImg.width;
7304
idxDown = currIdx + aImg.width;
7305
if (idxLeft < currRowIdx) idxLeft = currIdx;
7306
if (idxRight >= maxRowIdx) idxRight = currIdx;
7307
if (idxUp < 0) idxUp = 0;
7308
if (idxDown >= maxIdx) idxDown = currIdx;
7309
colUp = aImg.pixels.getPixel(idxUp);
7310
colLeft = aImg.pixels.getPixel(idxLeft);
7311
colDown = aImg.pixels.getPixel(idxDown);
7312
colRight = aImg.pixels.getPixel(idxRight);
7313
currLum = 77 * (colOrig >> 16 & 255) + 151 * (colOrig >> 8 & 255) + 28 * (colOrig & 255);
7314
lumLeft = 77 * (colLeft >> 16 & 255) + 151 * (colLeft >> 8 & 255) + 28 * (colLeft & 255);
7315
lumRight = 77 * (colRight >> 16 & 255) + 151 * (colRight >> 8 & 255) + 28 * (colRight & 255);
7316
lumUp = 77 * (colUp >> 16 & 255) + 151 * (colUp >> 8 & 255) + 28 * (colUp & 255);
7317
lumDown = 77 * (colDown >> 16 & 255) + 151 * (colDown >> 8 & 255) + 28 * (colDown & 255);
7318
if (lumLeft > currLum) {
7319
colOut = colLeft;
7320
currLum = lumLeft
7321
}
7322
if (lumRight > currLum) {
7323
colOut = colRight;
7324
currLum = lumRight
7325
}
7326
if (lumUp > currLum) {
7327
colOut = colUp;
7328
currLum = lumUp
7329
}
7330
if (lumDown > currLum) {
7331
colOut = colDown;
7332
currLum = lumDown
7333
}
7334
out[currIdx++] = colOut
7335
}
7336
} else while (currIdx < maxIdx) {
7337
currRowIdx = currIdx;
7338
maxRowIdx = currIdx + aImg.width;
7339
while (currIdx < maxRowIdx) {
7340
colOrig = colOut = aImg.pixels.getPixel(currIdx);
7341
idxLeft = currIdx - 1;
7342
idxRight = currIdx + 1;
7343
idxUp = currIdx - aImg.width;
7344
idxDown = currIdx + aImg.width;
7345
if (idxLeft < currRowIdx) idxLeft = currIdx;
7346
if (idxRight >= maxRowIdx) idxRight = currIdx;
7347
if (idxUp < 0) idxUp = 0;
7348
if (idxDown >= maxIdx) idxDown = currIdx;
7349
colUp = aImg.pixels.getPixel(idxUp);
7350
colLeft = aImg.pixels.getPixel(idxLeft);
7351
colDown = aImg.pixels.getPixel(idxDown);
7352
colRight = aImg.pixels.getPixel(idxRight);
7353
currLum = 77 * (colOrig >> 16 & 255) + 151 * (colOrig >> 8 & 255) + 28 * (colOrig & 255);
7354
lumLeft = 77 * (colLeft >> 16 & 255) + 151 * (colLeft >> 8 & 255) + 28 * (colLeft & 255);
7355
lumRight = 77 * (colRight >> 16 & 255) + 151 * (colRight >> 8 & 255) + 28 * (colRight & 255);
7356
lumUp = 77 * (colUp >> 16 & 255) + 151 * (colUp >> 8 & 255) + 28 * (colUp & 255);
7357
lumDown = 77 * (colDown >> 16 & 255) + 151 * (colDown >> 8 & 255) + 28 * (colDown & 255);
7358
if (lumLeft < currLum) {
7359
colOut = colLeft;
7360
currLum = lumLeft
7361
}
7362
if (lumRight < currLum) {
7363
colOut = colRight;
7364
currLum = lumRight
7365
}
7366
if (lumUp < currLum) {
7367
colOut = colUp;
7368
currLum = lumUp
7369
}
7370
if (lumDown < currLum) {
7371
colOut = colDown;
7372
currLum = lumDown
7373
}
7374
out[currIdx++] = colOut
7375
}
7376
}
7377
aImg.pixels.set(out)
7378
};
7379
p.filter = function(kind, param, aImg) {
7380
var img, col, lum, i;
7381
if (arguments.length === 3) {
7382
aImg.loadPixels();
7383
img = aImg
7384
} else {
7385
p.loadPixels();
7386
img = p
7387
}
7388
if (param === undef) param = null;
7389
if (img.isRemote) throw "Image is loaded remotely. Cannot filter image.";
7390
var imglen = img.pixels.getLength();
7391
switch (kind) {
7392
case 11:
7393
var radius = param || 1;
7394
blurARGB(radius, img);
7395
break;
7396
case 12:
7397
if (img.format === 4) {
7398
for (i = 0; i < imglen; i++) {
7399
col = 255 - img.pixels.getPixel(i);
7400
img.pixels.setPixel(i, 4278190080 | col << 16 | col << 8 | col)
7401
}
7402
img.format = 1
7403
} else for (i = 0; i < imglen; i++) {
7404
col = img.pixels.getPixel(i);
7405
lum = 77 * (col >> 16 & 255) + 151 * (col >> 8 & 255) + 28 * (col & 255) >> 8;
7406
img.pixels.setPixel(i, col & 4278190080 | lum << 16 | lum << 8 | lum)
7407
}
7408
break;
7409
case 13:
7410
for (i = 0; i < imglen; i++) img.pixels.setPixel(i, img.pixels.getPixel(i) ^ 16777215);
7411
break;
7412
case 15:
7413
if (param === null) throw "Use filter(POSTERIZE, int levels) instead of filter(POSTERIZE)";
7414
var levels = p.floor(param);
7415
if (levels < 2 || levels > 255) throw "Levels must be between 2 and 255 for filter(POSTERIZE, levels)";
7416
var levels1 = levels - 1;
7417
for (i = 0; i < imglen; i++) {
7418
var rlevel = img.pixels.getPixel(i) >> 16 & 255;
7419
var glevel = img.pixels.getPixel(i) >> 8 & 255;
7420
var blevel = img.pixels.getPixel(i) & 255;
7421
rlevel = (rlevel * levels >> 8) * 255 / levels1;
7422
glevel = (glevel * levels >> 8) * 255 / levels1;
7423
blevel = (blevel * levels >> 8) * 255 / levels1;
7424
img.pixels.setPixel(i, 4278190080 & img.pixels.getPixel(i) | rlevel << 16 | glevel << 8 | blevel)
7425
}
7426
break;
7427
case 14:
7428
for (i = 0; i < imglen; i++) img.pixels.setPixel(i, img.pixels.getPixel(i) | 4278190080);
7429
img.format = 1;
7430
break;
7431
case 16:
7432
if (param === null) param = 0.5;
7433
if (param < 0 || param > 1) throw "Level must be between 0 and 1 for filter(THRESHOLD, level)";
7434
var thresh = p.floor(param * 255);
7435
for (i = 0; i < imglen; i++) {
7436
var max = p.max((img.pixels.getPixel(i) & 16711680) >> 16, p.max((img.pixels.getPixel(i) & 65280) >> 8, img.pixels.getPixel(i) & 255));
7437
img.pixels.setPixel(i, img.pixels.getPixel(i) & 4278190080 | (max < thresh ? 0 : 16777215))
7438
}
7439
break;
7440
case 17:
7441
dilate(true, img);
7442
break;
7443
case 18:
7444
dilate(false, img);
7445
break
7446
}
7447
img.updatePixels()
7448
};
7449
p.shared = {
7450
fracU: 0,
7451
ifU: 0,
7452
fracV: 0,
7453
ifV: 0,
7454
u1: 0,
7455
u2: 0,
7456
v1: 0,
7457
v2: 0,
7458
sX: 0,
7459
sY: 0,
7460
iw: 0,
7461
iw1: 0,
7462
ih1: 0,
7463
ul: 0,
7464
ll: 0,
7465
ur: 0,
7466
lr: 0,
7467
cUL: 0,
7468
cLL: 0,
7469
cUR: 0,
7470
cLR: 0,
7471
srcXOffset: 0,
7472
srcYOffset: 0,
7473
r: 0,
7474
g: 0,
7475
b: 0,
7476
a: 0,
7477
srcBuffer: null,
7478
blurRadius: 0,
7479
blurKernelSize: 0,
7480
blurKernel: null
7481
};
7482
p.intersect = function(sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2) {
7483
var sw = sx2 - sx1 + 1;
7484
var sh = sy2 - sy1 + 1;
7485
var dw = dx2 - dx1 + 1;
7486
var dh = dy2 - dy1 + 1;
7487
if (dx1 < sx1) {
7488
dw += dx1 - sx1;
7489
if (dw > sw) dw = sw
7490
} else {
7491
var w = sw + sx1 - dx1;
7492
if (dw > w) dw = w
7493
}
7494
if (dy1 < sy1) {
7495
dh += dy1 - sy1;
7496
if (dh > sh) dh = sh
7497
} else {
7498
var h = sh + sy1 - dy1;
7499
if (dh > h) dh = h
7500
}
7501
return ! (dw <= 0 || dh <= 0)
7502
};
7503
var blendFuncs = {};
7504
blendFuncs[1] = p.modes.blend;
7505
blendFuncs[2] = p.modes.add;
7506
blendFuncs[4] = p.modes.subtract;
7507
blendFuncs[8] = p.modes.lightest;
7508
blendFuncs[16] = p.modes.darkest;
7509
blendFuncs[0] = p.modes.replace;
7510
blendFuncs[32] = p.modes.difference;
7511
blendFuncs[64] = p.modes.exclusion;
7512
blendFuncs[128] = p.modes.multiply;
7513
blendFuncs[256] = p.modes.screen;
7514
blendFuncs[512] = p.modes.overlay;
7515
blendFuncs[1024] = p.modes.hard_light;
7516
blendFuncs[2048] = p.modes.soft_light;
7517
blendFuncs[4096] = p.modes.dodge;
7518
blendFuncs[8192] = p.modes.burn;
7519
p.blit_resize = function(img, srcX1, srcY1, srcX2, srcY2, destPixels, screenW, screenH, destX1, destY1, destX2, destY2, mode) {
7520
var x, y;
7521
if (srcX1 < 0) srcX1 = 0;
7522
if (srcY1 < 0) srcY1 = 0;
7523
if (srcX2 >= img.width) srcX2 = img.width - 1;
7524
if (srcY2 >= img.height) srcY2 = img.height - 1;
7525
var srcW = srcX2 - srcX1;
7526
var srcH = srcY2 - srcY1;
7527
var destW = destX2 - destX1;
7528
var destH = destY2 - destY1;
7529
if (destW <= 0 || destH <= 0 || srcW <= 0 || srcH <= 0 || destX1 >= screenW || destY1 >= screenH || srcX1 >= img.width || srcY1 >= img.height) return;
7530
var dx = Math.floor(srcW / destW * 32768);
7531
var dy = Math.floor(srcH / destH * 32768);
7532
var pshared = p.shared;
7533
pshared.srcXOffset = Math.floor(destX1 < 0 ? -destX1 * dx : srcX1 * 32768);
7534
pshared.srcYOffset = Math.floor(destY1 < 0 ? -destY1 * dy : srcY1 * 32768);
7535
if (destX1 < 0) {
7536
destW += destX1;
7537
destX1 = 0
7538
}
7539
if (destY1 < 0) {
7540
destH += destY1;
7541
destY1 = 0
7542
}
7543
destW = Math.min(destW, screenW - destX1);
7544
destH = Math.min(destH, screenH - destY1);
7545
var destOffset = destY1 * screenW + destX1;
7546
var destColor;
7547
pshared.srcBuffer = img.imageData.data;
7548
pshared.iw = img.width;
7549
pshared.iw1 = img.width - 1;
7550
pshared.ih1 = img.height - 1;
7551
var filterBilinear = p.filter_bilinear,
7552
filterNewScanline = p.filter_new_scanline,
7553
blendFunc = blendFuncs[mode],
7554
blendedColor, idx, cULoffset, cURoffset, cLLoffset, cLRoffset, ALPHA_MASK = 4278190080,
7555
RED_MASK = 16711680,
7556
GREEN_MASK = 65280,
7557
BLUE_MASK = 255,
7558
PREC_MAXVAL = 32767,
7559
PRECISIONB = 15,
7560
PREC_RED_SHIFT = 1,
7561
PREC_ALPHA_SHIFT = 9,
7562
srcBuffer = pshared.srcBuffer,
7563
min = Math.min;
7564
for (y = 0; y < destH; y++) {
7565
pshared.sX = pshared.srcXOffset;
7566
pshared.fracV = pshared.srcYOffset & PREC_MAXVAL;
7567
pshared.ifV = PREC_MAXVAL - pshared.fracV;
7568
pshared.v1 = (pshared.srcYOffset >> PRECISIONB) * pshared.iw;
7569
pshared.v2 = min((pshared.srcYOffset >> PRECISIONB) + 1, pshared.ih1) * pshared.iw;
7570
for (x = 0; x < destW; x++) {
7571
idx = (destOffset + x) * 4;
7572
destColor = destPixels[idx + 3] << 24 & ALPHA_MASK | destPixels[idx] << 16 & RED_MASK | destPixels[idx + 1] << 8 & GREEN_MASK | destPixels[idx + 2] & BLUE_MASK;
7573
pshared.fracU = pshared.sX & PREC_MAXVAL;
7574
pshared.ifU = PREC_MAXVAL - pshared.fracU;
7575
pshared.ul = pshared.ifU * pshared.ifV >> PRECISIONB;
7576
pshared.ll = pshared.ifU * pshared.fracV >> PRECISIONB;
7577
pshared.ur = pshared.fracU * pshared.ifV >> PRECISIONB;
7578
pshared.lr = pshared.fracU * pshared.fracV >> PRECISIONB;
7579
pshared.u1 = pshared.sX >> PRECISIONB;
7580
pshared.u2 = min(pshared.u1 + 1, pshared.iw1);
7581
cULoffset = (pshared.v1 + pshared.u1) * 4;
7582
cURoffset = (pshared.v1 + pshared.u2) * 4;
7583
cLLoffset = (pshared.v2 + pshared.u1) * 4;
7584
cLRoffset = (pshared.v2 + pshared.u2) * 4;
7585
pshared.cUL = srcBuffer[cULoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cULoffset] << 16 & RED_MASK | srcBuffer[cULoffset + 1] << 8 & GREEN_MASK | srcBuffer[cULoffset + 2] & BLUE_MASK;
7586
pshared.cUR = srcBuffer[cURoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cURoffset] << 16 & RED_MASK | srcBuffer[cURoffset + 1] << 8 & GREEN_MASK | srcBuffer[cURoffset + 2] & BLUE_MASK;
7587
pshared.cLL = srcBuffer[cLLoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cLLoffset] << 16 & RED_MASK | srcBuffer[cLLoffset + 1] << 8 & GREEN_MASK | srcBuffer[cLLoffset + 2] & BLUE_MASK;
7588
pshared.cLR = srcBuffer[cLRoffset + 3] << 24 & ALPHA_MASK | srcBuffer[cLRoffset] << 16 & RED_MASK | srcBuffer[cLRoffset + 1] << 8 & GREEN_MASK | srcBuffer[cLRoffset + 2] & BLUE_MASK;
7589
pshared.r = pshared.ul * ((pshared.cUL & RED_MASK) >> 16) + pshared.ll * ((pshared.cLL & RED_MASK) >> 16) + pshared.ur * ((pshared.cUR & RED_MASK) >> 16) + pshared.lr * ((pshared.cLR & RED_MASK) >> 16) << PREC_RED_SHIFT & RED_MASK;
7590
pshared.g = pshared.ul * (pshared.cUL & GREEN_MASK) + pshared.ll * (pshared.cLL & GREEN_MASK) + pshared.ur * (pshared.cUR & GREEN_MASK) + pshared.lr * (pshared.cLR & GREEN_MASK) >>> PRECISIONB & GREEN_MASK;
7591
pshared.b = pshared.ul * (pshared.cUL & BLUE_MASK) + pshared.ll * (pshared.cLL & BLUE_MASK) + pshared.ur * (pshared.cUR & BLUE_MASK) + pshared.lr * (pshared.cLR & BLUE_MASK) >>> PRECISIONB;
7592
pshared.a = pshared.ul * ((pshared.cUL & ALPHA_MASK) >>> 24) + pshared.ll * ((pshared.cLL & ALPHA_MASK) >>> 24) + pshared.ur * ((pshared.cUR & ALPHA_MASK) >>> 24) + pshared.lr * ((pshared.cLR & ALPHA_MASK) >>> 24) << PREC_ALPHA_SHIFT & ALPHA_MASK;
7593
blendedColor = blendFunc(destColor, pshared.a | pshared.r | pshared.g | pshared.b);
7594
destPixels[idx] = (blendedColor & RED_MASK) >>> 16;
7595
destPixels[idx + 1] = (blendedColor & GREEN_MASK) >>> 8;
7596
destPixels[idx + 2] = blendedColor & BLUE_MASK;
7597
destPixels[idx + 3] = (blendedColor & ALPHA_MASK) >>> 24;
7598
pshared.sX += dx
7599
}
7600
destOffset += screenW;
7601
pshared.srcYOffset += dy
7602
}
7603
};
7604
p.loadFont = function(name, size) {
7605
if (name === undef) throw "font name required in loadFont.";
7606
if (name.indexOf(".svg") === -1) {
7607
if (size === undef) size = curTextFont.size;
7608
return PFont.get(name, size)
7609
}
7610
var font = p.loadGlyphs(name);
7611
return {
7612
name: name,
7613
css: "12px sans-serif",
7614
glyph: true,
7615
units_per_em: font.units_per_em,
7616
horiz_adv_x: 1 / font.units_per_em * font.horiz_adv_x,
7617
ascent: font.ascent,
7618
descent: font.descent,
7619
width: function(str) {
7620
var width = 0;
7621
var len = str.length;
7622
for (var i = 0; i < len; i++) try {
7623
width += parseFloat(p.glyphLook(p.glyphTable[name], str[i]).horiz_adv_x)
7624
} catch(e) {
7625
Processing.debug(e)
7626
}
7627
return width / p.glyphTable[name].units_per_em
7628
}
7629
}
7630
};
7631
p.createFont = function(name, size) {
7632
return p.loadFont(name, size)
7633
};
7634
p.textFont = function(pfont, size) {
7635
if (size !== undef) {
7636
if (!pfont.glyph) pfont = PFont.get(pfont.name, size);
7637
curTextSize = size
7638
}
7639
curTextFont = pfont;
7640
curFontName = curTextFont.name;
7641
curTextAscent = curTextFont.ascent;
7642
curTextDescent = curTextFont.descent;
7643
curTextLeading = curTextFont.leading;
7644
var curContext = drawing.$ensureContext();
7645
curContext.font = curTextFont.css
7646
};
7647
p.textSize = function(size) {
7648
curTextFont = PFont.get(curFontName, size);
7649
curTextSize = size;
7650
curTextAscent = curTextFont.ascent;
7651
curTextDescent = curTextFont.descent;
7652
curTextLeading = curTextFont.leading;
7653
var curContext = drawing.$ensureContext();
7654
curContext.font = curTextFont.css
7655
};
7656
p.textAscent = function() {
7657
return curTextAscent
7658
};
7659
p.textDescent = function() {
7660
return curTextDescent
7661
};
7662
p.textLeading = function(leading) {
7663
curTextLeading = leading
7664
};
7665
p.textAlign = function(xalign, yalign) {
7666
horizontalTextAlignment = xalign;
7667
verticalTextAlignment = yalign || 0
7668
};
7669
7670
function toP5String(obj) {
7671
if (obj instanceof String) return obj;
7672
if (typeof obj === "number") {
7673
if (obj === (0 | obj)) return obj.toString();
7674
return p.nf(obj, 0, 3)
7675
}
7676
if (obj === null || obj === undef) return "";
7677
return obj.toString()
7678
}
7679
Drawing2D.prototype.textWidth = function(str) {
7680
var lines = toP5String(str).split(/\r?\n/g),
7681
width = 0;
7682
var i, linesCount = lines.length;
7683
curContext.font = curTextFont.css;
7684
for (i = 0; i < linesCount; ++i) width = Math.max(width, curTextFont.measureTextWidth(lines[i]));
7685
return width | 0
7686
};
7687
Drawing3D.prototype.textWidth = function(str) {
7688
var lines = toP5String(str).split(/\r?\n/g),
7689
width = 0;
7690
var i, linesCount = lines.length;
7691
if (textcanvas === undef) textcanvas = document.createElement("canvas");
7692
var textContext = textcanvas.getContext("2d");
7693
textContext.font = curTextFont.css;
7694
for (i = 0; i < linesCount; ++i) width = Math.max(width, textContext.measureText(lines[i]).width);
7695
return width | 0
7696
};
7697
p.glyphLook = function(font, chr) {
7698
try {
7699
switch (chr) {
7700
case "1":
7701
return font.one;
7702
case "2":
7703
return font.two;
7704
case "3":
7705
return font.three;
7706
case "4":
7707
return font.four;
7708
case "5":
7709
return font.five;
7710
case "6":
7711
return font.six;
7712
case "7":
7713
return font.seven;
7714
case "8":
7715
return font.eight;
7716
case "9":
7717
return font.nine;
7718
case "0":
7719
return font.zero;
7720
case " ":
7721
return font.space;
7722
case "$":
7723
return font.dollar;
7724
case "!":
7725
return font.exclam;
7726
case '"':
7727
return font.quotedbl;
7728
case "#":
7729
return font.numbersign;
7730
case "%":
7731
return font.percent;
7732
case "&":
7733
return font.ampersand;
7734
case "'":
7735
return font.quotesingle;
7736
case "(":
7737
return font.parenleft;
7738
case ")":
7739
return font.parenright;
7740
case "*":
7741
return font.asterisk;
7742
case "+":
7743
return font.plus;
7744
case ",":
7745
return font.comma;
7746
case "-":
7747
return font.hyphen;
7748
case ".":
7749
return font.period;
7750
case "/":
7751
return font.slash;
7752
case "_":
7753
return font.underscore;
7754
case ":":
7755
return font.colon;
7756
case ";":
7757
return font.semicolon;
7758
case "<":
7759
return font.less;
7760
case "=":
7761
return font.equal;
7762
case ">":
7763
return font.greater;
7764
case "?":
7765
return font.question;
7766
case "@":
7767
return font.at;
7768
case "[":
7769
return font.bracketleft;
7770
case "\\":
7771
return font.backslash;
7772
case "]":
7773
return font.bracketright;
7774
case "^":
7775
return font.asciicircum;
7776
case "`":
7777
return font.grave;
7778
case "{":
7779
return font.braceleft;
7780
case "|":
7781
return font.bar;
7782
case "}":
7783
return font.braceright;
7784
case "~":
7785
return font.asciitilde;
7786
default:
7787
return font[chr]
7788
}
7789
} catch(e) {
7790
Processing.debug(e)
7791
}
7792
};
7793
Drawing2D.prototype.text$line = function(str, x, y, z, align) {
7794
var textWidth = 0,
7795
xOffset = 0;
7796
if (!curTextFont.glyph) {
7797
if (str && "fillText" in curContext) {
7798
if (isFillDirty) {
7799
curContext.fillStyle = p.color.toString(currentFillColor);
7800
isFillDirty = false
7801
}
7802
if (align === 39 || align === 3) {
7803
textWidth = curTextFont.measureTextWidth(str);
7804
if (align === 39) xOffset = -textWidth;
7805
else xOffset = -textWidth / 2
7806
}
7807
curContext.fillText(str, x + xOffset, y)
7808
}
7809
} else {
7810
var font = p.glyphTable[curFontName];
7811
saveContext();
7812
curContext.translate(x, y + curTextSize);
7813
if (align === 39 || align === 3) {
7814
textWidth = font.width(str);
7815
if (align === 39) xOffset = -textWidth;
7816
else xOffset = -textWidth / 2
7817
}
7818
var upem = font.units_per_em,
7819
newScale = 1 / upem * curTextSize;
7820
curContext.scale(newScale, newScale);
7821
for (var i = 0, len = str.length; i < len; i++) try {
7822
p.glyphLook(font, str[i]).draw()
7823
} catch(e) {
7824
Processing.debug(e)
7825
}
7826
restoreContext()
7827
}
7828
};
7829
Drawing3D.prototype.text$line = function(str, x, y, z, align) {
7830
if (textcanvas === undef) textcanvas = document.createElement("canvas");
7831
var oldContext = curContext;
7832
curContext = textcanvas.getContext("2d");
7833
curContext.font = curTextFont.css;
7834
var textWidth = curTextFont.measureTextWidth(str);
7835
textcanvas.width = textWidth;
7836
textcanvas.height = curTextSize;
7837
curContext = textcanvas.getContext("2d");
7838
curContext.font = curTextFont.css;
7839
curContext.textBaseline = "top";
7840
Drawing2D.prototype.text$line(str, 0, 0, 0, 37);
7841
var aspect = textcanvas.width / textcanvas.height;
7842
curContext = oldContext;
7843
curContext.bindTexture(curContext.TEXTURE_2D, textTex);
7844
curContext.texImage2D(curContext.TEXTURE_2D, 0, curContext.RGBA, curContext.RGBA, curContext.UNSIGNED_BYTE, textcanvas);
7845
curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MAG_FILTER, curContext.LINEAR);
7846
curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_MIN_FILTER, curContext.LINEAR);
7847
curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_T, curContext.CLAMP_TO_EDGE);
7848
curContext.texParameteri(curContext.TEXTURE_2D, curContext.TEXTURE_WRAP_S, curContext.CLAMP_TO_EDGE);
7849
var xOffset = 0;
7850
if (align === 39) xOffset = -textWidth;
7851
else if (align === 3) xOffset = -textWidth / 2;
7852
var model = new PMatrix3D;
7853
var scalefactor = curTextSize * 0.5;
7854
model.translate(x + xOffset - scalefactor / 2, y - scalefactor, z);
7855
model.scale(-aspect * scalefactor, -scalefactor, scalefactor);
7856
model.translate(-1, -1, -1);
7857
model.transpose();
7858
var view = new PMatrix3D;
7859
view.scale(1, -1, 1);
7860
view.apply(modelView.array());
7861
view.transpose();
7862
curContext.useProgram(programObject2D);
7863
vertexAttribPointer("aVertex2d", programObject2D, "aVertex", 3, textBuffer);
7864
vertexAttribPointer("aTextureCoord2d", programObject2D, "aTextureCoord", 2, textureBuffer);
7865
uniformi("uSampler2d", programObject2D, "uSampler", [0]);
7866
uniformi("uIsDrawingText2d", programObject2D, "uIsDrawingText", true);
7867
uniformMatrix("uModel2d", programObject2D, "uModel", false, model.array());
7868
uniformMatrix("uView2d", programObject2D, "uView", false, view.array());
7869
uniformf("uColor2d", programObject2D, "uColor", fillStyle);
7870
curContext.bindBuffer(curContext.ELEMENT_ARRAY_BUFFER, indexBuffer);
7871
curContext.drawElements(curContext.TRIANGLES, 6, curContext.UNSIGNED_SHORT, 0)
7872
};
7873
7874
function text$4(str, x, y, z) {
7875
var lines, linesCount;
7876
if (str.indexOf("\n") < 0) {
7877
lines = [str];
7878
linesCount = 1
7879
} else {
7880
lines = str.split(/\r?\n/g);
7881
linesCount = lines.length
7882
}
7883
var yOffset = 0;
7884
if (verticalTextAlignment === 101) yOffset = curTextAscent + curTextDescent;
7885
else if (verticalTextAlignment === 3) yOffset = curTextAscent / 2 - (linesCount - 1) * curTextLeading / 2;
7886
else if (verticalTextAlignment === 102) yOffset = -(curTextDescent + (linesCount - 1) * curTextLeading);
7887
for (var i = 0; i < linesCount; ++i) {
7888
var line = lines[i];
7889
drawing.text$line(line, x, y + yOffset, z, horizontalTextAlignment);
7890
yOffset += curTextLeading
7891
}
7892
}
7893
function text$6(str, x, y, width, height, z) {
7894
if (str.length === 0 || width === 0 || height === 0) return;
7895
if (curTextSize > height) return;
7896
var spaceMark = -1;
7897
var start = 0;
7898
var lineWidth = 0;
7899
var drawCommands = [];
7900
for (var charPos = 0, len = str.length; charPos < len; charPos++) {
7901
var currentChar = str[charPos];
7902
var spaceChar = currentChar === " ";
7903
var letterWidth = curTextFont.measureTextWidth(currentChar);
7904
if (currentChar !== "\n" && lineWidth + letterWidth <= width) {
7905
if (spaceChar) spaceMark = charPos;
7906
lineWidth += letterWidth
7907
} else {
7908
if (spaceMark + 1 === start) if (charPos > 0) spaceMark = charPos;
7909
else return;
7910
if (currentChar === "\n") {
7911
drawCommands.push({
7912
text: str.substring(start, charPos),
7913
width: lineWidth
7914
});
7915
start = charPos + 1
7916
} else {
7917
drawCommands.push({
7918
text: str.substring(start, spaceMark + 1),
7919
width: lineWidth
7920
});
7921
start = spaceMark + 1
7922
}
7923
lineWidth = 0;
7924
charPos = start - 1
7925
}
7926
}
7927
if (start < len) drawCommands.push({
7928
text: str.substring(start),
7929
width: lineWidth
7930
});
7931
var xOffset = 1,
7932
yOffset = curTextAscent;
7933
if (horizontalTextAlignment === 3) xOffset = width / 2;
7934
else if (horizontalTextAlignment === 39) xOffset = width;
7935
var linesCount = drawCommands.length,
7936
visibleLines = Math.min(linesCount, Math.floor(height / curTextLeading));
7937
if (verticalTextAlignment === 101) yOffset = curTextAscent + curTextDescent;
7938
else if (verticalTextAlignment === 3) yOffset = height / 2 - curTextLeading * (visibleLines / 2 - 1);
7939
else if (verticalTextAlignment === 102) yOffset = curTextDescent + curTextLeading;
7940
var command, drawCommand, leading;
7941
for (command = 0; command < linesCount; command++) {
7942
leading = command * curTextLeading;
7943
if (yOffset + leading > height - curTextDescent) break;
7944
drawCommand = drawCommands[command];
7945
drawing.text$line(drawCommand.text, x + xOffset, y + yOffset + leading, z, horizontalTextAlignment)
7946
}
7947
}
7948
p.text = function() {
7949
if (textMode === 5) return;
7950
if (arguments.length === 3) text$4(toP5String(arguments[0]), arguments[1], arguments[2], 0);
7951
else if (arguments.length === 4) text$4(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3]);
7952
else if (arguments.length === 5) text$6(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3], arguments[4], 0);
7953
else if (arguments.length === 6) text$6(toP5String(arguments[0]), arguments[1], arguments[2], arguments[3], arguments[4], arguments[5])
7954
};
7955
p.textMode = function(mode) {
7956
textMode = mode
7957
};
7958
p.loadGlyphs = function(url) {
7959
var x, y, cx, cy, nx, ny, d, a, lastCom, lenC, horiz_adv_x, getXY = "[0-9\\-]+",
7960
path;
7961
var regex = function(needle, hay) {
7962
var i = 0,
7963
results = [],
7964
latest, regexp = new RegExp(needle, "g");
7965
latest = results[i] = regexp.exec(hay);
7966
while (latest) {
7967
i++;
7968
latest = results[i] = regexp.exec(hay)
7969
}
7970
return results
7971
};
7972
var buildPath = function(d) {
7973
var c = regex("[A-Za-z][0-9\\- ]+|Z", d);
7974
var beforePathDraw = function() {
7975
saveContext();
7976
return drawing.$ensureContext()
7977
};
7978
var afterPathDraw = function() {
7979
executeContextFill();
7980
executeContextStroke();
7981
restoreContext()
7982
};
7983
path = "return {draw:function(){var curContext=beforePathDraw();curContext.beginPath();";
7984
x = 0;
7985
y = 0;
7986
cx = 0;
7987
cy = 0;
7988
nx = 0;
7989
ny = 0;
7990
d = 0;
7991
a = 0;
7992
lastCom = "";
7993
lenC = c.length - 1;
7994
for (var j = 0; j < lenC; j++) {
7995
var com = c[j][0],
7996
xy = regex(getXY, com);
7997
switch (com[0]) {
7998
case "M":
7999
x = parseFloat(xy[0][0]);
8000
y = parseFloat(xy[1][0]);
8001
path += "curContext.moveTo(" + x + "," + -y + ");";
8002
break;
8003
case "L":
8004
x = parseFloat(xy[0][0]);
8005
y = parseFloat(xy[1][0]);
8006
path += "curContext.lineTo(" + x + "," + -y + ");";
8007
break;
8008
case "H":
8009
x = parseFloat(xy[0][0]);
8010
path += "curContext.lineTo(" + x + "," + -y + ");";
8011
break;
8012
case "V":
8013
y = parseFloat(xy[0][0]);
8014
path += "curContext.lineTo(" + x + "," + -y + ");";
8015
break;
8016
case "T":
8017
nx = parseFloat(xy[0][0]);
8018
ny = parseFloat(xy[1][0]);
8019
if (lastCom === "Q" || lastCom === "T") {
8020
d = Math.sqrt(Math.pow(x - cx, 2) + Math.pow(cy - y, 2));
8021
a = Math.PI + Math.atan2(cx - x, cy - y);
8022
cx = x + Math.sin(a) * d;
8023
cy = y + Math.cos(a) * d
8024
} else {
8025
cx = x;
8026
cy = y
8027
}
8028
path += "curContext.quadraticCurveTo(" + cx + "," + -cy + "," + nx + "," + -ny + ");";
8029
x = nx;
8030
y = ny;
8031
break;
8032
case "Q":
8033
cx = parseFloat(xy[0][0]);
8034
cy = parseFloat(xy[1][0]);
8035
nx = parseFloat(xy[2][0]);
8036
ny = parseFloat(xy[3][0]);
8037
path += "curContext.quadraticCurveTo(" + cx + "," + -cy + "," + nx + "," + -ny + ");";
8038
x = nx;
8039
y = ny;
8040
break;
8041
case "Z":
8042
path += "curContext.closePath();";
8043
break
8044
}
8045
lastCom = com[0]
8046
}
8047
path += "afterPathDraw();";
8048
path += "curContext.translate(" + horiz_adv_x + ",0);";
8049
path += "}}";
8050
return (new Function("beforePathDraw", "afterPathDraw", path))(beforePathDraw, afterPathDraw)
8051
};
8052
var parseSVGFont = function(svg) {
8053
var font = svg.getElementsByTagName("font");
8054
p.glyphTable[url].horiz_adv_x = font[0].getAttribute("horiz-adv-x");
8055
var font_face = svg.getElementsByTagName("font-face")[0];
8056
p.glyphTable[url].units_per_em = parseFloat(font_face.getAttribute("units-per-em"));
8057
p.glyphTable[url].ascent = parseFloat(font_face.getAttribute("ascent"));
8058
p.glyphTable[url].descent = parseFloat(font_face.getAttribute("descent"));
8059
var glyph = svg.getElementsByTagName("glyph"),
8060
len = glyph.length;
8061
for (var i = 0; i < len; i++) {
8062
var unicode = glyph[i].getAttribute("unicode");
8063
var name = glyph[i].getAttribute("glyph-name");
8064
horiz_adv_x = glyph[i].getAttribute("horiz-adv-x");
8065
if (horiz_adv_x === null) horiz_adv_x = p.glyphTable[url].horiz_adv_x;
8066
d = glyph[i].getAttribute("d");
8067
if (d !== undef) {
8068
path = buildPath(d);
8069
p.glyphTable[url][name] = {
8070
name: name,
8071
unicode: unicode,
8072
horiz_adv_x: horiz_adv_x,
8073
draw: path.draw
8074
}
8075
}
8076
}
8077
};
8078
var loadXML = function() {
8079
var xmlDoc;
8080
try {
8081
xmlDoc = document.implementation.createDocument("", "", null)
8082
} catch(e_fx_op) {
8083
Processing.debug(e_fx_op.message);
8084
return
8085
}
8086
try {
8087
xmlDoc.async = false;
8088
xmlDoc.load(url);
8089
parseSVGFont(xmlDoc.getElementsByTagName("svg")[0])
8090
} catch(e_sf_ch) {
8091
Processing.debug(e_sf_ch);
8092
try {
8093
var xmlhttp = new window.XMLHttpRequest;
8094
xmlhttp.open("GET", url, false);
8095
xmlhttp.send(null);
8096
parseSVGFont(xmlhttp.responseXML.documentElement)
8097
} catch(e) {
8098
Processing.debug(e_sf_ch)
8099
}
8100
}
8101
};
8102
p.glyphTable[url] = {};
8103
loadXML(url);
8104
return p.glyphTable[url]
8105
};
8106
p.param = function(name) {
8107
var attributeName = "data-processing-" + name;
8108
if (curElement.hasAttribute(attributeName)) return curElement.getAttribute(attributeName);
8109
for (var i = 0, len = curElement.childNodes.length; i < len; ++i) {
8110
var item = curElement.childNodes.item(i);
8111
if (item.nodeType !== 1 || item.tagName.toLowerCase() !== "param") continue;
8112
if (item.getAttribute("name") === name) return item.getAttribute("value")
8113
}
8114
if (curSketch.params.hasOwnProperty(name)) return curSketch.params[name];
8115
return null
8116
};
8117
8118
function wireDimensionalFunctions(mode) {
8119
if (mode === "3D") drawing = new Drawing3D;
8120
else if (mode === "2D") drawing = new Drawing2D;
8121
else drawing = new DrawingPre;
8122
for (var i in DrawingPre.prototype) if (DrawingPre.prototype.hasOwnProperty(i) && i.indexOf("$") < 0) p[i] = drawing[i];
8123
drawing.$init()
8124
}
8125
function createDrawingPreFunction(name) {
8126
return function() {
8127
wireDimensionalFunctions("2D");
8128
return drawing[name].apply(this, arguments)
8129
}
8130
}
8131
DrawingPre.prototype.translate = createDrawingPreFunction("translate");
8132
DrawingPre.prototype.transform = createDrawingPreFunction("transform");
8133
DrawingPre.prototype.scale = createDrawingPreFunction("scale");
8134
DrawingPre.prototype.pushMatrix = createDrawingPreFunction("pushMatrix");
8135
DrawingPre.prototype.popMatrix = createDrawingPreFunction("popMatrix");
8136
DrawingPre.prototype.resetMatrix = createDrawingPreFunction("resetMatrix");
8137
DrawingPre.prototype.applyMatrix = createDrawingPreFunction("applyMatrix");
8138
DrawingPre.prototype.rotate = createDrawingPreFunction("rotate");
8139
DrawingPre.prototype.rotateZ = createDrawingPreFunction("rotateZ");
8140
DrawingPre.prototype.shearX = createDrawingPreFunction("shearX");
8141
DrawingPre.prototype.shearY = createDrawingPreFunction("shearY");
8142
DrawingPre.prototype.redraw = createDrawingPreFunction("redraw");
8143
DrawingPre.prototype.toImageData = createDrawingPreFunction("toImageData");
8144
DrawingPre.prototype.ambientLight = createDrawingPreFunction("ambientLight");
8145
DrawingPre.prototype.directionalLight = createDrawingPreFunction("directionalLight");
8146
DrawingPre.prototype.lightFalloff = createDrawingPreFunction("lightFalloff");
8147
DrawingPre.prototype.lightSpecular = createDrawingPreFunction("lightSpecular");
8148
DrawingPre.prototype.pointLight = createDrawingPreFunction("pointLight");
8149
DrawingPre.prototype.noLights = createDrawingPreFunction("noLights");
8150
DrawingPre.prototype.spotLight = createDrawingPreFunction("spotLight");
8151
DrawingPre.prototype.beginCamera = createDrawingPreFunction("beginCamera");
8152
DrawingPre.prototype.endCamera = createDrawingPreFunction("endCamera");
8153
DrawingPre.prototype.frustum = createDrawingPreFunction("frustum");
8154
DrawingPre.prototype.box = createDrawingPreFunction("box");
8155
DrawingPre.prototype.sphere = createDrawingPreFunction("sphere");
8156
DrawingPre.prototype.ambient = createDrawingPreFunction("ambient");
8157
DrawingPre.prototype.emissive = createDrawingPreFunction("emissive");
8158
DrawingPre.prototype.shininess = createDrawingPreFunction("shininess");
8159
DrawingPre.prototype.specular = createDrawingPreFunction("specular");
8160
DrawingPre.prototype.fill = createDrawingPreFunction("fill");
8161
DrawingPre.prototype.stroke = createDrawingPreFunction("stroke");
8162
DrawingPre.prototype.strokeWeight = createDrawingPreFunction("strokeWeight");
8163
DrawingPre.prototype.smooth = createDrawingPreFunction("smooth");
8164
DrawingPre.prototype.noSmooth = createDrawingPreFunction("noSmooth");
8165
DrawingPre.prototype.point = createDrawingPreFunction("point");
8166
DrawingPre.prototype.vertex = createDrawingPreFunction("vertex");
8167
DrawingPre.prototype.endShape = createDrawingPreFunction("endShape");
8168
DrawingPre.prototype.bezierVertex = createDrawingPreFunction("bezierVertex");
8169
DrawingPre.prototype.curveVertex = createDrawingPreFunction("curveVertex");
8170
DrawingPre.prototype.curve = createDrawingPreFunction("curve");
8171
DrawingPre.prototype.line = createDrawingPreFunction("line");
8172
DrawingPre.prototype.bezier = createDrawingPreFunction("bezier");
8173
DrawingPre.prototype.rect = createDrawingPreFunction("rect");
8174
DrawingPre.prototype.ellipse = createDrawingPreFunction("ellipse");
8175
DrawingPre.prototype.background = createDrawingPreFunction("background");
8176
DrawingPre.prototype.image = createDrawingPreFunction("image");
8177
DrawingPre.prototype.textWidth = createDrawingPreFunction("textWidth");
8178
DrawingPre.prototype.text$line = createDrawingPreFunction("text$line");
8179
DrawingPre.prototype.$ensureContext = createDrawingPreFunction("$ensureContext");
8180
DrawingPre.prototype.$newPMatrix = createDrawingPreFunction("$newPMatrix");
8181
DrawingPre.prototype.size = function(aWidth, aHeight, aMode) {
8182
wireDimensionalFunctions(aMode === 2 ? "3D" : "2D");
8183
p.size(aWidth, aHeight, aMode)
8184
};
8185
DrawingPre.prototype.$init = nop;
8186
Drawing2D.prototype.$init = function() {
8187
p.size(p.width, p.height);
8188
curContext.lineCap = "round";
8189
p.noSmooth();
8190
p.disableContextMenu()
8191
};
8192
Drawing3D.prototype.$init = function() {
8193
p.use3DContext = true;
8194
p.disableContextMenu()
8195
};
8196
DrawingShared.prototype.$ensureContext = function() {
8197
return curContext
8198
};
8199
8200
function calculateOffset(curElement, event) {
8201
var element = curElement,
8202
offsetX = 0,
8203
offsetY = 0;
8204
p.pmouseX = p.mouseX;
8205
p.pmouseY = p.mouseY;
8206
if (element.offsetParent) {
8207
do {
8208
offsetX += element.offsetLeft;
8209
offsetY += element.offsetTop
8210
} while ( !! (element = element.offsetParent))
8211
}
8212
element = curElement;
8213
do {
8214
offsetX -= element.scrollLeft || 0;
8215
offsetY -= element.scrollTop || 0
8216
} while ( !! (element = element.parentNode));
8217
offsetX += stylePaddingLeft;
8218
offsetY += stylePaddingTop;
8219
offsetX += styleBorderLeft;
8220
offsetY += styleBorderTop;
8221
offsetX += window.pageXOffset;
8222
offsetY += window.pageYOffset;
8223
return {
8224
"X": offsetX,
8225
"Y": offsetY
8226
}
8227
}
8228
function updateMousePosition(curElement, event) {
8229
var offset = calculateOffset(curElement, event);
8230
p.mouseX = event.pageX - offset.X;
8231
p.mouseY = event.pageY - offset.Y
8232
}
8233
function addTouchEventOffset(t) {
8234
var offset = calculateOffset(t.changedTouches[0].target, t.changedTouches[0]),
8235
i;
8236
for (i = 0; i < t.touches.length; i++) {
8237
var touch = t.touches[i];
8238
touch.offsetX = touch.pageX - offset.X;
8239
touch.offsetY = touch.pageY - offset.Y
8240
}
8241
for (i = 0; i < t.targetTouches.length; i++) {
8242
var targetTouch = t.targetTouches[i];
8243
targetTouch.offsetX = targetTouch.pageX - offset.X;
8244
targetTouch.offsetY = targetTouch.pageY - offset.Y
8245
}
8246
for (i = 0; i < t.changedTouches.length; i++) {
8247
var changedTouch = t.changedTouches[i];
8248
changedTouch.offsetX = changedTouch.pageX - offset.X;
8249
changedTouch.offsetY = changedTouch.pageY - offset.Y
8250
}
8251
return t
8252
}
8253
attachEventHandler(curElement, "touchstart", function(t) {
8254
curElement.setAttribute("style", "-webkit-user-select: none");
8255
curElement.setAttribute("onclick", "void(0)");
8256
curElement.setAttribute("style", "-webkit-tap-highlight-color:rgba(0,0,0,0)");
8257
for (var i = 0, ehl = eventHandlers.length; i < ehl; i++) {
8258
var type = eventHandlers[i].type;
8259
if (type === "mouseout" || type === "mousemove" || type === "mousedown" || type === "mouseup" || type === "DOMMouseScroll" || type === "mousewheel" || type === "touchstart") detachEventHandler(eventHandlers[i])
8260
}
8261
if (p.touchStart !== undef || p.touchMove !== undef || p.touchEnd !== undef || p.touchCancel !== undef) {
8262
attachEventHandler(curElement, "touchstart", function(t) {
8263
if (p.touchStart !== undef) {
8264
t = addTouchEventOffset(t);
8265
p.touchStart(t)
8266
}
8267
});
8268
attachEventHandler(curElement, "touchmove", function(t) {
8269
if (p.touchMove !== undef) {
8270
t.preventDefault();
8271
t = addTouchEventOffset(t);
8272
p.touchMove(t)
8273
}
8274
});
8275
attachEventHandler(curElement, "touchend", function(t) {
8276
if (p.touchEnd !== undef) {
8277
t = addTouchEventOffset(t);
8278
p.touchEnd(t)
8279
}
8280
});
8281
attachEventHandler(curElement, "touchcancel", function(t) {
8282
if (p.touchCancel !== undef) {
8283
t = addTouchEventOffset(t);
8284
p.touchCancel(t)
8285
}
8286
})
8287
} else {
8288
attachEventHandler(curElement, "touchstart", function(e) {
8289
updateMousePosition(curElement, e.touches[0]);
8290
p.__mousePressed = true;
8291
p.mouseDragging = false;
8292
p.mouseButton = 37;
8293
if (typeof p.mousePressed === "function") p.mousePressed()
8294
});
8295
attachEventHandler(curElement, "touchmove", function(e) {
8296
e.preventDefault();
8297
updateMousePosition(curElement, e.touches[0]);
8298
if (typeof p.mouseMoved === "function" && !p.__mousePressed) p.mouseMoved();
8299
if (typeof p.mouseDragged === "function" && p.__mousePressed) {
8300
p.mouseDragged();
8301
p.mouseDragging = true
8302
}
8303
});
8304
attachEventHandler(curElement, "touchend", function(e) {
8305
p.__mousePressed = false;
8306
if (typeof p.mouseClicked === "function" && !p.mouseDragging) p.mouseClicked();
8307
if (typeof p.mouseReleased === "function") p.mouseReleased()
8308
})
8309
}
8310
curElement.dispatchEvent(t)
8311
});
8312
(function() {
8313
var enabled = true,
8314
contextMenu = function(e) {
8315
e.preventDefault();
8316
e.stopPropagation()
8317
};
8318
p.disableContextMenu = function() {
8319
if (!enabled) return;
8320
attachEventHandler(curElement, "contextmenu", contextMenu);
8321
enabled = false
8322
};
8323
p.enableContextMenu = function() {
8324
if (enabled) return;
8325
detachEventHandler({
8326
elem: curElement,
8327
type: "contextmenu",
8328
fn: contextMenu
8329
});
8330
enabled = true
8331
}
8332
})();
8333
attachEventHandler(curElement, "mousemove", function(e) {
8334
updateMousePosition(curElement, e);
8335
if (typeof p.mouseMoved === "function" && !p.__mousePressed) p.mouseMoved();
8336
if (typeof p.mouseDragged === "function" && p.__mousePressed) {
8337
p.mouseDragged();
8338
p.mouseDragging = true
8339
}
8340
});
8341
attachEventHandler(curElement, "mouseout", function(e) {
8342
if (typeof p.mouseOut === "function") p.mouseOut()
8343
});
8344
attachEventHandler(curElement, "mouseover", function(e) {
8345
updateMousePosition(curElement, e);
8346
if (typeof p.mouseOver === "function") p.mouseOver()
8347
});
8348
curElement.onmousedown = function() {
8349
curElement.focus();
8350
return false
8351
};
8352
attachEventHandler(curElement, "mousedown", function(e) {
8353
p.__mousePressed = true;
8354
p.mouseDragging = false;
8355
switch (e.which) {
8356
case 1:
8357
p.mouseButton = 37;
8358
break;
8359
case 2:
8360
p.mouseButton = 3;
8361
break;
8362
case 3:
8363
p.mouseButton = 39;
8364
break
8365
}
8366
if (typeof p.mousePressed === "function") p.mousePressed()
8367
});
8368
attachEventHandler(curElement, "mouseup", function(e) {
8369
p.__mousePressed = false;
8370
if (typeof p.mouseClicked === "function" && !p.mouseDragging) p.mouseClicked();
8371
if (typeof p.mouseReleased === "function") p.mouseReleased()
8372
});
8373
var mouseWheelHandler = function(e) {
8374
var delta = 0;
8375
if (e.wheelDelta) {
8376
delta = e.wheelDelta / 120;
8377
if (window.opera) delta = -delta
8378
} else if (e.detail) delta = -e.detail / 3;
8379
p.mouseScroll = delta;
8380
if (delta && typeof p.mouseScrolled === "function") p.mouseScrolled()
8381
};
8382
attachEventHandler(document, "DOMMouseScroll", mouseWheelHandler);
8383
attachEventHandler(document, "mousewheel", mouseWheelHandler);
8384
if (!curElement.getAttribute("tabindex")) curElement.setAttribute("tabindex", 0);
8385
8386
function getKeyCode(e) {
8387
var code = e.which || e.keyCode;
8388
switch (code) {
8389
case 13:
8390
return 10;
8391
case 91:
8392
case 93:
8393
case 224:
8394
return 157;
8395
case 57392:
8396
return 17;
8397
case 46:
8398
return 127;
8399
case 45:
8400
return 155
8401
}
8402
return code
8403
}
8404
function getKeyChar(e) {
8405
var c = e.which || e.keyCode;
8406
var anyShiftPressed = e.shiftKey || e.ctrlKey || e.altKey || e.metaKey;
8407
switch (c) {
8408
case 13:
8409
c = anyShiftPressed ? 13 : 10;
8410
break;
8411
case 8:
8412
c = anyShiftPressed ? 127 : 8;
8413
break
8414
}
8415
return new Char(c)
8416
}
8417
function suppressKeyEvent(e) {
8418
if (typeof e.preventDefault === "function") e.preventDefault();
8419
else if (typeof e.stopPropagation === "function") e.stopPropagation();
8420
return false
8421
}
8422
function updateKeyPressed() {
8423
var ch;
8424
for (ch in pressedKeysMap) if (pressedKeysMap.hasOwnProperty(ch)) {
8425
p.__keyPressed = true;
8426
return
8427
}
8428
p.__keyPressed = false
8429
}
8430
function resetKeyPressed() {
8431
p.__keyPressed = false;
8432
pressedKeysMap = [];
8433
lastPressedKeyCode = null
8434
}
8435
function simulateKeyTyped(code, c) {
8436
pressedKeysMap[code] = c;
8437
lastPressedKeyCode = null;
8438
p.key = c;
8439
p.keyCode = code;
8440
p.keyPressed();
8441
p.keyCode = 0;
8442
p.keyTyped();
8443
updateKeyPressed()
8444
}
8445
function handleKeydown(e) {
8446
var code = getKeyCode(e);
8447
if (code === 127) {
8448
simulateKeyTyped(code, new Char(127));
8449
return
8450
}
8451
if (codedKeys.indexOf(code) < 0) {
8452
lastPressedKeyCode = code;
8453
return
8454
}
8455
var c = new Char(65535);
8456
p.key = c;
8457
p.keyCode = code;
8458
pressedKeysMap[code] = c;
8459
p.keyPressed();
8460
lastPressedKeyCode = null;
8461
updateKeyPressed();
8462
return suppressKeyEvent(e)
8463
}
8464
function handleKeypress(e) {
8465
if (lastPressedKeyCode === null) return;
8466
var code = lastPressedKeyCode,
8467
c = getKeyChar(e);
8468
simulateKeyTyped(code, c);
8469
return suppressKeyEvent(e)
8470
}
8471
function handleKeyup(e) {
8472
var code = getKeyCode(e),
8473
c = pressedKeysMap[code];
8474
if (c === undef) return;
8475
p.key = c;
8476
p.keyCode = code;
8477
p.keyReleased();
8478
delete pressedKeysMap[code];
8479
updateKeyPressed()
8480
}
8481
if (!pgraphicsMode) {
8482
if (aCode instanceof Processing.Sketch) curSketch = aCode;
8483
else if (typeof aCode === "function") curSketch = new Processing.Sketch(aCode);
8484
else if (!aCode) curSketch = new Processing.Sketch(function() {});
8485
else curSketch = Processing.compile(aCode);
8486
p.externals.sketch = curSketch;
8487
wireDimensionalFunctions();
8488
curElement.onfocus = function() {
8489
p.focused = true
8490
};
8491
curElement.onblur = function() {
8492
p.focused = false;
8493
if (!curSketch.options.globalKeyEvents) resetKeyPressed()
8494
};
8495
if (curSketch.options.pauseOnBlur) {
8496
attachEventHandler(window, "focus", function() {
8497
if (doLoop) p.loop()
8498
});
8499
attachEventHandler(window, "blur", function() {
8500
if (doLoop && loopStarted) {
8501
p.noLoop();
8502
doLoop = true
8503
}
8504
resetKeyPressed()
8505
})
8506
}
8507
var keyTrigger = curSketch.options.globalKeyEvents ? window : curElement;
8508
attachEventHandler(keyTrigger, "keydown", handleKeydown);
8509
attachEventHandler(keyTrigger, "keypress", handleKeypress);
8510
attachEventHandler(keyTrigger, "keyup", handleKeyup);
8511
for (var i in Processing.lib) if (Processing.lib.hasOwnProperty(i)) if (Processing.lib[i].hasOwnProperty("attach")) Processing.lib[i].attach(p);
8512
else if (Processing.lib[i] instanceof Function) Processing.lib[i].call(this);
8513
var retryInterval = 100;
8514
var executeSketch = function(processing) {
8515
if (! (curSketch.imageCache.pending || PFont.preloading.pending(retryInterval))) {
8516
if (window.opera) {
8517
var link, element, operaCache = curSketch.imageCache.operaCache;
8518
for (link in operaCache) if (operaCache.hasOwnProperty(link)) {
8519
element = operaCache[link];
8520
if (element !== null) document.body.removeChild(element);
8521
delete operaCache[link]
8522
}
8523
}
8524
curSketch.attach(processing, defaultScope);
8525
curSketch.onLoad(processing);
8526
if (processing.setup) {
8527
processing.setup();
8528
processing.resetMatrix();
8529
curSketch.onSetup()
8530
}
8531
resetContext();
8532
if (processing.draw) if (!doLoop) processing.redraw();
8533
else processing.loop()
8534
} else window.setTimeout(function() {
8535
executeSketch(processing)
8536
},
8537
retryInterval)
8538
};
8539
addInstance(this);
8540
executeSketch(p)
8541
} else {
8542
curSketch = new Processing.Sketch;
8543
wireDimensionalFunctions();
8544
p.size = function(w, h, render) {
8545
if (render && render === 2) wireDimensionalFunctions("3D");
8546
else wireDimensionalFunctions("2D");
8547
p.size(w, h, render)
8548
}
8549
}
8550
};
8551
Processing.debug = debug;
8552
Processing.prototype = defaultScope;
8553
8554
function getGlobalMembers() {
8555
var names = ["abs", "acos", "alpha", "ambient", "ambientLight", "append",
8556
"applyMatrix", "arc", "arrayCopy", "asin", "atan", "atan2", "background", "beginCamera", "beginDraw", "beginShape", "bezier", "bezierDetail", "bezierPoint", "bezierTangent", "bezierVertex", "binary", "blend", "blendColor", "blit_resize", "blue", "box", "breakShape", "brightness", "camera", "ceil", "Character", "color", "colorMode", "concat", "constrain", "copy", "cos", "createFont", "createGraphics", "createImage", "cursor", "curve", "curveDetail", "curvePoint", "curveTangent", "curveTightness", "curveVertex", "day", "degrees", "directionalLight",
8557
"disableContextMenu", "dist", "draw", "ellipse", "ellipseMode", "emissive", "enableContextMenu", "endCamera", "endDraw", "endShape", "exit", "exp", "expand", "externals", "fill", "filter", "floor", "focused", "frameCount", "frameRate", "frustum", "get", "glyphLook", "glyphTable", "green", "height", "hex", "hint", "hour", "hue", "image", "imageMode", "intersect", "join", "key", "keyCode", "keyPressed", "keyReleased", "keyTyped", "lerp", "lerpColor", "lightFalloff", "lights", "lightSpecular", "line", "link", "loadBytes", "loadFont", "loadGlyphs",
8558
"loadImage", "loadPixels", "loadShape", "loadXML", "loadStrings", "log", "loop", "mag", "map", "match", "matchAll", "max", "millis", "min", "minute", "mix", "modelX", "modelY", "modelZ", "modes", "month", "mouseButton", "mouseClicked", "mouseDragged", "mouseMoved", "mouseOut", "mouseOver", "mousePressed", "mouseReleased", "mouseScroll", "mouseScrolled", "mouseX", "mouseY", "name", "nf", "nfc", "nfp", "nfs", "noCursor", "noFill", "noise", "noiseDetail", "noiseSeed", "noLights", "noLoop", "norm", "normal", "noSmooth", "noStroke", "noTint", "ortho",
8559
"param", "parseBoolean", "parseByte", "parseChar", "parseFloat", "parseInt", "peg", "perspective", "PImage", "pixels", "PMatrix2D", "PMatrix3D", "PMatrixStack", "pmouseX", "pmouseY", "point", "pointLight", "popMatrix", "popStyle", "pow", "print", "printCamera", "println", "printMatrix", "printProjection", "PShape", "PShapeSVG", "pushMatrix", "pushStyle", "quad", "radians", "random", "Random", "randomSeed", "rect", "rectMode", "red", "redraw", "requestImage", "resetMatrix", "reverse", "rotate", "rotateX", "rotateY", "rotateZ", "round", "saturation",
8560
"save", "saveFrame", "saveStrings", "scale", "screenX", "screenY", "screenZ", "second", "set", "setup", "shape", "shapeMode", "shared", "shearX", "shearY", "shininess", "shorten", "sin", "size", "smooth", "sort", "specular", "sphere", "sphereDetail", "splice", "split", "splitTokens", "spotLight", "sq", "sqrt", "status", "str", "stroke", "strokeCap", "strokeJoin", "strokeWeight", "subset", "tan", "text", "textAlign", "textAscent", "textDescent", "textFont", "textLeading", "textMode", "textSize", "texture", "textureMode", "textWidth", "tint", "toImageData",
8561
"touchCancel", "touchEnd", "touchMove", "touchStart", "translate", "transform", "triangle", "trim", "unbinary", "unhex", "updatePixels", "use3DContext", "vertex", "width", "XMLElement", "XML", "year", "__contains", "__equals", "__equalsIgnoreCase", "__frameRate", "__hashCode", "__int_cast", "__instanceof", "__keyPressed", "__mousePressed", "__printStackTrace", "__replace", "__replaceAll", "__replaceFirst", "__toCharArray", "__split", "__codePointAt", "__startsWith", "__endsWith", "__matches"];
8562
var members = {};
8563
var i, l;
8564
for (i = 0, l = names.length; i < l; ++i) members[names[i]] = null;
8565
for (var lib in Processing.lib) if (Processing.lib.hasOwnProperty(lib)) if (Processing.lib[lib].exports) {
8566
var exportedNames = Processing.lib[lib].exports;
8567
for (i = 0, l = exportedNames.length; i < l; ++i) members[exportedNames[i]] = null
8568
}
8569
return members
8570
}
8571
function parseProcessing(code) {
8572
var globalMembers = getGlobalMembers();
8573
8574
function splitToAtoms(code) {
8575
var atoms = [];
8576
var items = code.split(/([\{\[\(\)\]\}])/);
8577
var result = items[0];
8578
var stack = [];
8579
for (var i = 1; i < items.length; i += 2) {
8580
var item = items[i];
8581
if (item === "[" || item === "{" || item === "(") {
8582
stack.push(result);
8583
result = item
8584
} else if (item === "]" || item === "}" || item === ")") {
8585
var kind = item === "}" ? "A" : item === ")" ? "B" : "C";
8586
var index = atoms.length;
8587
atoms.push(result + item);
8588
result = stack.pop() + '"' + kind + (index + 1) + '"'
8589
}
8590
result += items[i + 1]
8591
}
8592
atoms.unshift(result);
8593
return atoms
8594
}
8595
function injectStrings(code, strings) {
8596
return code.replace(/'(\d+)'/g, function(all, index) {
8597
var val = strings[index];
8598
if (val.charAt(0) === "/") return val;
8599
return /^'((?:[^'\\\n])|(?:\\.[0-9A-Fa-f]*))'$/.test(val) ? "(new $p.Character(" + val + "))" : val
8600
})
8601
}
8602
function trimSpaces(string) {
8603
var m1 = /^\s*/.exec(string),
8604
result;
8605
if (m1[0].length === string.length) result = {
8606
left: m1[0],
8607
middle: "",
8608
right: ""
8609
};
8610
else {
8611
var m2 = /\s*$/.exec(string);
8612
result = {
8613
left: m1[0],
8614
middle: string.substring(m1[0].length, m2.index),
8615
right: m2[0]
8616
}
8617
}
8618
result.untrim = function(t) {
8619
return this.left + t + this.right
8620
};
8621
return result
8622
}
8623
function trim(string) {
8624
return string.replace(/^\s+/, "").replace(/\s+$/, "")
8625
}
8626
function appendToLookupTable(table, array) {
8627
for (var i = 0, l = array.length; i < l; ++i) table[array[i]] = null;
8628
return table
8629
}
8630
function isLookupTableEmpty(table) {
8631
for (var i in table) if (table.hasOwnProperty(i)) return false;
8632
return true
8633
}
8634
function getAtomIndex(templ) {
8635
return templ.substring(2, templ.length - 1)
8636
}
8637
var codeWoExtraCr = code.replace(/\r\n?|\n\r/g, "\n");
8638
var strings = [];
8639
var codeWoStrings = codeWoExtraCr.replace(/("(?:[^"\\\n]|\\.)*")|('(?:[^'\\\n]|\\.)*')|(([\[\(=|&!\^:?]\s*)(\/(?![*\/])(?:[^\/\\\n]|\\.)*\/[gim]*)\b)|(\/\/[^\n]*\n)|(\/\*(?:(?!\*\/)(?:.|\n))*\*\/)/g, function(all, quoted, aposed, regexCtx, prefix, regex, singleComment, comment) {
8640
var index;
8641
if (quoted || aposed) {
8642
index = strings.length;
8643
strings.push(all);
8644
return "'" + index + "'"
8645
}
8646
if (regexCtx) {
8647
index = strings.length;
8648
strings.push(regex);
8649
return prefix + "'" + index + "'"
8650
}
8651
return comment !== "" ? " " : "\n"
8652
});
8653
codeWoStrings = codeWoStrings.replace(/__x([0-9A-F]{4})/g, function(all, hexCode) {
8654
return "__x005F_x" + hexCode
8655
});
8656
codeWoStrings = codeWoStrings.replace(/\$/g, "__x0024");
8657
var genericsWereRemoved;
8658
var codeWoGenerics = codeWoStrings;
8659
var replaceFunc = function(all, before, types, after) {
8660
if ( !! before || !!after) return all;
8661
genericsWereRemoved = true;
8662
return ""
8663
};
8664
do {
8665
genericsWereRemoved = false;
8666
codeWoGenerics = codeWoGenerics.replace(/([<]?)<\s*((?:\?|[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\[\])*(?:\s+(?:extends|super)\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)?(?:\s*,\s*(?:\?|[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\[\])*(?:\s+(?:extends|super)\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)?)*)\s*>([=]?)/g, replaceFunc)
8667
} while (genericsWereRemoved);
8668
var atoms = splitToAtoms(codeWoGenerics);
8669
var replaceContext;
8670
var declaredClasses = {},
8671
currentClassId, classIdSeed = 0;
8672
8673
function addAtom(text, type) {
8674
var lastIndex = atoms.length;
8675
atoms.push(text);
8676
return '"' + type + lastIndex + '"'
8677
}
8678
function generateClassId() {
8679
return "class" + ++classIdSeed
8680
}
8681
function appendClass(class_, classId, scopeId) {
8682
class_.classId = classId;
8683
class_.scopeId = scopeId;
8684
declaredClasses[classId] = class_
8685
}
8686
var transformClassBody, transformInterfaceBody, transformStatementsBlock, transformStatements, transformMain, transformExpression;
8687
var classesRegex = /\b((?:(?:public|private|final|protected|static|abstract)\s+)*)(class|interface)\s+([A-Za-z_$][\w$]*\b)(\s+extends\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*\b)*)?(\s+implements\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*\b)*)?\s*("A\d+")/g;
8688
var methodsRegex = /\b((?:(?:public|private|final|protected|static|abstract|synchronized)\s+)*)((?!(?:else|new|return|throw|function|public|private|protected)\b)[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*"C\d+")*)\s*([A-Za-z_$][\w$]*\b)\s*("B\d+")(\s*throws\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)*)?\s*("A\d+"|;)/g;
8689
var fieldTest = /^((?:(?:public|private|final|protected|static)\s+)*)((?!(?:else|new|return|throw)\b)[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*"C\d+")*)\s*([A-Za-z_$][\w$]*\b)\s*(?:"C\d+"\s*)*([=,]|$)/;
8690
var cstrsRegex = /\b((?:(?:public|private|final|protected|static|abstract)\s+)*)((?!(?:new|return|throw)\b)[A-Za-z_$][\w$]*\b)\s*("B\d+")(\s*throws\s+[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*,\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)*)?\s*("A\d+")/g;
8691
var attrAndTypeRegex = /^((?:(?:public|private|final|protected|static)\s+)*)((?!(?:new|return|throw)\b)[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*(?:\s*"C\d+")*)\s*/;
8692
var functionsRegex = /\bfunction(?:\s+([A-Za-z_$][\w$]*))?\s*("B\d+")\s*("A\d+")/g;
8693
8694
function extractClassesAndMethods(code) {
8695
var s = code;
8696
s = s.replace(classesRegex, function(all) {
8697
return addAtom(all, "E")
8698
});
8699
s = s.replace(methodsRegex, function(all) {
8700
return addAtom(all, "D")
8701
});
8702
s = s.replace(functionsRegex, function(all) {
8703
return addAtom(all, "H")
8704
});
8705
return s
8706
}
8707
function extractConstructors(code, className) {
8708
var result = code.replace(cstrsRegex, function(all, attr, name, params, throws_, body) {
8709
if (name !== className) return all;
8710
return addAtom(all, "G")
8711
});
8712
return result
8713
}
8714
function AstParam(name) {
8715
this.name = name
8716
}
8717
AstParam.prototype.toString = function() {
8718
return this.name
8719
};
8720
8721
function AstParams(params, methodArgsParam) {
8722
this.params = params;
8723
this.methodArgsParam = methodArgsParam
8724
}
8725
AstParams.prototype.getNames = function() {
8726
var names = [];
8727
for (var i = 0, l = this.params.length; i < l; ++i) names.push(this.params[i].name);
8728
return names
8729
};
8730
AstParams.prototype.prependMethodArgs = function(body) {
8731
if (!this.methodArgsParam) return body;
8732
return "{\nvar " + this.methodArgsParam.name + " = Array.prototype.slice.call(arguments, " + this.params.length + ");\n" + body.substring(1)
8733
};
8734
AstParams.prototype.toString = function() {
8735
if (this.params.length === 0) return "()";
8736
var result = "(";
8737
for (var i = 0, l = this.params.length; i < l; ++i) result += this.params[i] + ", ";
8738
return result.substring(0, result.length - 2) + ")"
8739
};
8740
8741
function transformParams(params) {
8742
var paramsWoPars = trim(params.substring(1, params.length - 1));
8743
var result = [],
8744
methodArgsParam = null;
8745
if (paramsWoPars !== "") {
8746
var paramList = paramsWoPars.split(",");
8747
for (var i = 0; i < paramList.length; ++i) {
8748
var param = /\b([A-Za-z_$][\w$]*\b)(\s*"[ABC][\d]*")*\s*$/.exec(paramList[i]);
8749
if (i === paramList.length - 1 && paramList[i].indexOf("...") >= 0) {
8750
methodArgsParam = new AstParam(param[1]);
8751
break
8752
}
8753
result.push(new AstParam(param[1]))
8754
}
8755
}
8756
return new AstParams(result, methodArgsParam)
8757
}
8758
function preExpressionTransform(expr) {
8759
var s = expr;
8760
s = s.replace(/\bnew\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\s*"C\d+")+\s*("A\d+")/g, function(all, type, init) {
8761
return init
8762
});
8763
s = s.replace(/\bnew\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)(?:\s*"B\d+")\s*("A\d+")/g, function(all, type, init) {
8764
return addAtom(all, "F")
8765
});
8766
s = s.replace(functionsRegex, function(all) {
8767
return addAtom(all, "H")
8768
});
8769
s = s.replace(/\bnew\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)\s*("C\d+"(?:\s*"C\d+")*)/g, function(all, type, index) {
8770
var args = index.replace(/"C(\d+)"/g, function(all, j) {
8771
return atoms[j]
8772
}).replace(/\[\s*\]/g, "[null]").replace(/\s*\]\s*\[\s*/g, ", ");
8773
var arrayInitializer = "{" + args.substring(1, args.length - 1) + "}";
8774
var createArrayArgs = "('" + type + "', " + addAtom(arrayInitializer, "A") + ")";
8775
return "$p.createJavaArray" + addAtom(createArrayArgs, "B")
8776
});
8777
s = s.replace(/(\.\s*length)\s*"B\d+"/g, "$1");
8778
s = s.replace(/#([0-9A-Fa-f]{6})\b/g, function(all, digits) {
8779
return "0xFF" + digits
8780
});
8781
s = s.replace(/"B(\d+)"(\s*(?:[\w$']|"B))/g, function(all, index, next) {
8782
var atom = atoms[index];
8783
if (!/^\(\s*[A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*\s*(?:"C\d+"\s*)*\)$/.test(atom)) return all;
8784
if (/^\(\s*int\s*\)$/.test(atom)) return "(int)" + next;
8785
var indexParts = atom.split(/"C(\d+)"/g);
8786
if (indexParts.length > 1) if (!/^\[\s*\]$/.test(atoms[indexParts[1]])) return all;
8787
return "" + next
8788
});
8789
s = s.replace(/\(int\)([^,\]\)\}\?\:\*\+\-\/\^\|\%\&\~<\>\=]+)/g, function(all, arg) {
8790
var trimmed = trimSpaces(arg);
8791
return trimmed.untrim("__int_cast(" + trimmed.middle + ")")
8792
});
8793
s = s.replace(/\bsuper(\s*"B\d+")/g, "$$superCstr$1").replace(/\bsuper(\s*\.)/g, "$$super$1");
8794
s = s.replace(/\b0+((\d*)(?:\.[\d*])?(?:[eE][\-\+]?\d+)?[fF]?)\b/, function(all, numberWo0, intPart) {
8795
if (numberWo0 === intPart) return all;
8796
return intPart === "" ? "0" + numberWo0 : numberWo0
8797
});
8798
s = s.replace(/\b(\.?\d+\.?)[fF]\b/g, "$1");
8799
s = s.replace(/([^\s])%([^=\s])/g, "$1 % $2");
8800
s = s.replace(/\b(frameRate|keyPressed|mousePressed)\b(?!\s*"B)/g, "__$1");
8801
s = s.replace(/\b(boolean|byte|char|float|int)\s*"B/g, function(all, name) {
8802
return "parse" + name.substring(0, 1).toUpperCase() + name.substring(1) + '"B'
8803
});
8804
s = s.replace(/\bpixels\b\s*(("C(\d+)")|\.length)?(\s*=(?!=)([^,\]\)\}]+))?/g, function(all, indexOrLength, index, atomIndex, equalsPart, rightSide) {
8805
if (index) {
8806
var atom = atoms[atomIndex];
8807
if (equalsPart) return "pixels.setPixel" + addAtom("(" + atom.substring(1, atom.length - 1) + "," + rightSide + ")", "B");
8808
return "pixels.getPixel" + addAtom("(" + atom.substring(1, atom.length - 1) + ")", "B")
8809
}
8810
if (indexOrLength) return "pixels.getLength" + addAtom("()", "B");
8811
if (equalsPart) return "pixels.set" + addAtom("(" + rightSide + ")", "B");
8812
return "pixels.toArray" + addAtom("()", "B")
8813
});
8814
var repeatJavaReplacement;
8815
8816
function replacePrototypeMethods(all, subject, method, atomIndex) {
8817
var atom = atoms[atomIndex];
8818
repeatJavaReplacement = true;
8819
var trimmed = trimSpaces(atom.substring(1, atom.length - 1));
8820
return "__" + method + (trimmed.middle === "" ? addAtom("(" + subject.replace(/\.\s*$/, "") + ")", "B") : addAtom("(" + subject.replace(/\.\s*$/, "") + "," + trimmed.middle + ")", "B"))
8821
}
8822
do {
8823
repeatJavaReplacement = false;
8824
s = s.replace(/((?:'\d+'|\b[A-Za-z_$][\w$]*\s*(?:"[BC]\d+")*)\s*\.\s*(?:[A-Za-z_$][\w$]*\s*(?:"[BC]\d+"\s*)*\.\s*)*)(replace|replaceAll|replaceFirst|contains|equals|equalsIgnoreCase|hashCode|toCharArray|printStackTrace|split|startsWith|endsWith|codePointAt|matches)\s*"B(\d+)"/g, replacePrototypeMethods)
8825
} while (repeatJavaReplacement);
8826
8827
function replaceInstanceof(all, subject, type) {
8828
repeatJavaReplacement = true;
8829
return "__instanceof" + addAtom("(" + subject + ", " + type + ")", "B")
8830
}
8831
do {
8832
repeatJavaReplacement = false;
8833
s = s.replace(/((?:'\d+'|\b[A-Za-z_$][\w$]*\s*(?:"[BC]\d+")*)\s*(?:\.\s*[A-Za-z_$][\w$]*\s*(?:"[BC]\d+"\s*)*)*)instanceof\s+([A-Za-z_$][\w$]*\s*(?:\.\s*[A-Za-z_$][\w$]*)*)/g, replaceInstanceof)
8834
} while (repeatJavaReplacement);
8835
s = s.replace(/\bthis(\s*"B\d+")/g, "$$constr$1");
8836
return s
8837
}
8838
function AstInlineClass(baseInterfaceName, body) {
8839
this.baseInterfaceName = baseInterfaceName;
8840
this.body = body;
8841
body.owner = this
8842
}
8843
AstInlineClass.prototype.toString = function() {
8844
return "new (" + this.body + ")"
8845
};
8846
8847
function transformInlineClass(class_) {
8848
var m = (new RegExp(/\bnew\s*([A-Za-z_$][\w$]*\s*(?:\.\s*[A-Za-z_$][\w$]*)*)\s*"B\d+"\s*"A(\d+)"/)).exec(class_);
8849
var oldClassId = currentClassId,
8850
newClassId = generateClassId();
8851
currentClassId = newClassId;
8852
var uniqueClassName = m[1] + "$" + newClassId;
8853
var inlineClass = new AstInlineClass(uniqueClassName, transformClassBody(atoms[m[2]], uniqueClassName, "", "implements " + m[1]));
8854
appendClass(inlineClass, newClassId, oldClassId);
8855
currentClassId = oldClassId;
8856
return inlineClass
8857
}
8858
8859
function AstFunction(name, params, body) {
8860
this.name = name;
8861
this.params = params;
8862
this.body = body
8863
}
8864
AstFunction.prototype.toString = function() {
8865
var oldContext = replaceContext;
8866
var names = appendToLookupTable({
8867
"this": null
8868
},
8869
this.params.getNames());
8870
replaceContext = function(subject) {
8871
return names.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)
8872
};
8873
var result = "function";
8874
if (this.name) result += " " + this.name;
8875
var body = this.params.prependMethodArgs(this.body.toString());
8876
result += this.params + " " + body;
8877
replaceContext = oldContext;
8878
return result
8879
};
8880
8881
function transformFunction(class_) {
8882
var m = (new RegExp(/\b([A-Za-z_$][\w$]*)\s*"B(\d+)"\s*"A(\d+)"/)).exec(class_);
8883
return new AstFunction(m[1] !== "function" ? m[1] : null, transformParams(atoms[m[2]]), transformStatementsBlock(atoms[m[3]]))
8884
}
8885
function AstInlineObject(members) {
8886
this.members = members
8887
}
8888
AstInlineObject.prototype.toString = function() {
8889
var oldContext = replaceContext;
8890
replaceContext = function(subject) {
8891
return subject.name === "this" ? "this" : oldContext(subject)
8892
};
8893
var result = "";
8894
for (var i = 0, l = this.members.length; i < l; ++i) {
8895
if (this.members[i].label) result += this.members[i].label + ": ";
8896
result += this.members[i].value.toString() + ", "
8897
}
8898
replaceContext = oldContext;
8899
return result.substring(0, result.length - 2)
8900
};
8901
8902
function transformInlineObject(obj) {
8903
var members = obj.split(",");
8904
for (var i = 0; i < members.length; ++i) {
8905
var label = members[i].indexOf(":");
8906
if (label < 0) members[i] = {
8907
value: transformExpression(members[i])
8908
};
8909
else members[i] = {
8910
label: trim(members[i].substring(0, label)),
8911
value: transformExpression(trim(members[i].substring(label + 1)))
8912
}
8913
}
8914
return new AstInlineObject(members)
8915
}
8916
8917
function expandExpression(expr) {
8918
if (expr.charAt(0) === "(" || expr.charAt(0) === "[") return expr.charAt(0) + expandExpression(expr.substring(1, expr.length - 1)) + expr.charAt(expr.length - 1);
8919
if (expr.charAt(0) === "{") {
8920
if (/^\{\s*(?:[A-Za-z_$][\w$]*|'\d+')\s*:/.test(expr)) return "{" + addAtom(expr.substring(1, expr.length - 1), "I") + "}";
8921
return "[" + expandExpression(expr.substring(1, expr.length - 1)) + "]"
8922
}
8923
var trimmed = trimSpaces(expr);
8924
var result = preExpressionTransform(trimmed.middle);
8925
result = result.replace(/"[ABC](\d+)"/g, function(all, index) {
8926
return expandExpression(atoms[index])
8927
});
8928
return trimmed.untrim(result)
8929
}
8930
function replaceContextInVars(expr) {
8931
return expr.replace(/(\.\s*)?((?:\b[A-Za-z_]|\$)[\w$]*)(\s*\.\s*([A-Za-z_$][\w$]*)(\s*\()?)?/g, function(all, memberAccessSign, identifier, suffix, subMember, callSign) {
8932
if (memberAccessSign) return all;
8933
var subject = {
8934
name: identifier,
8935
member: subMember,
8936
callSign: !!callSign
8937
};
8938
return replaceContext(subject) + (suffix === undef ? "" : suffix)
8939
})
8940
}
8941
function AstExpression(expr, transforms) {
8942
this.expr = expr;
8943
this.transforms = transforms
8944
}
8945
AstExpression.prototype.toString = function() {
8946
var transforms = this.transforms;
8947
var expr = replaceContextInVars(this.expr);
8948
return expr.replace(/"!(\d+)"/g, function(all, index) {
8949
return transforms[index].toString()
8950
})
8951
};
8952
transformExpression = function(expr) {
8953
var transforms = [];
8954
var s = expandExpression(expr);
8955
s = s.replace(/"H(\d+)"/g, function(all, index) {
8956
transforms.push(transformFunction(atoms[index]));
8957
return '"!' + (transforms.length - 1) + '"'
8958
});
8959
s = s.replace(/"F(\d+)"/g, function(all, index) {
8960
transforms.push(transformInlineClass(atoms[index]));
8961
return '"!' + (transforms.length - 1) + '"'
8962
});
8963
s = s.replace(/"I(\d+)"/g, function(all, index) {
8964
transforms.push(transformInlineObject(atoms[index]));
8965
return '"!' + (transforms.length - 1) + '"'
8966
});
8967
return new AstExpression(s, transforms)
8968
};
8969
8970
function AstVarDefinition(name, value, isDefault) {
8971
this.name = name;
8972
this.value = value;
8973
this.isDefault = isDefault
8974
}
8975
AstVarDefinition.prototype.toString = function() {
8976
return this.name + " = " + this.value
8977
};
8978
8979
function transformVarDefinition(def, defaultTypeValue) {
8980
var eqIndex = def.indexOf("=");
8981
var name, value, isDefault;
8982
if (eqIndex < 0) {
8983
name = def;
8984
value = defaultTypeValue;
8985
isDefault = true
8986
} else {
8987
name = def.substring(0, eqIndex);
8988
value = transformExpression(def.substring(eqIndex + 1));
8989
isDefault = false
8990
}
8991
return new AstVarDefinition(trim(name.replace(/(\s*"C\d+")+/g, "")), value, isDefault)
8992
}
8993
function getDefaultValueForType(type) {
8994
if (type === "int" || type === "float") return "0";
8995
if (type === "boolean") return "false";
8996
if (type === "color") return "0x00000000";
8997
return "null"
8998
}
8999
function AstVar(definitions, varType) {
9000
this.definitions = definitions;
9001
this.varType = varType
9002
}
9003
AstVar.prototype.getNames = function() {
9004
var names = [];
9005
for (var i = 0, l = this.definitions.length; i < l; ++i) names.push(this.definitions[i].name);
9006
return names
9007
};
9008
AstVar.prototype.toString = function() {
9009
return "var " + this.definitions.join(",")
9010
};
9011
9012
function AstStatement(expression) {
9013
this.expression = expression
9014
}
9015
AstStatement.prototype.toString = function() {
9016
return this.expression.toString()
9017
};
9018
9019
function transformStatement(statement) {
9020
if (fieldTest.test(statement)) {
9021
var attrAndType = attrAndTypeRegex.exec(statement);
9022
var definitions = statement.substring(attrAndType[0].length).split(",");
9023
var defaultTypeValue = getDefaultValueForType(attrAndType[2]);
9024
for (var i = 0; i < definitions.length; ++i) definitions[i] = transformVarDefinition(definitions[i], defaultTypeValue);
9025
return new AstVar(definitions, attrAndType[2])
9026
}
9027
return new AstStatement(transformExpression(statement))
9028
}
9029
function AstForExpression(initStatement, condition, step) {
9030
this.initStatement = initStatement;
9031
this.condition = condition;
9032
this.step = step
9033
}
9034
AstForExpression.prototype.toString = function() {
9035
return "(" + this.initStatement + "; " + this.condition + "; " + this.step + ")"
9036
};
9037
9038
function AstForInExpression(initStatement, container) {
9039
this.initStatement = initStatement;
9040
this.container = container
9041
}
9042
AstForInExpression.prototype.toString = function() {
9043
var init = this.initStatement.toString();
9044
if (init.indexOf("=") >= 0) init = init.substring(0, init.indexOf("="));
9045
return "(" + init + " in " + this.container + ")"
9046
};
9047
9048
function AstForEachExpression(initStatement, container) {
9049
this.initStatement = initStatement;
9050
this.container = container
9051
}
9052
AstForEachExpression.iteratorId = 0;
9053
AstForEachExpression.prototype.toString = function() {
9054
var init = this.initStatement.toString();
9055
var iterator = "$it" + AstForEachExpression.iteratorId++;
9056
var variableName = init.replace(/^\s*var\s*/, "").split("=")[0];
9057
var initIteratorAndVariable = "var " + iterator + " = new $p.ObjectIterator(" + this.container + "), " + variableName + " = void(0)";
9058
var nextIterationCondition = iterator + ".hasNext() && ((" + variableName + " = " + iterator + ".next()) || true)";
9059
return "(" + initIteratorAndVariable + "; " + nextIterationCondition + ";)"
9060
};
9061
9062
function transformForExpression(expr) {
9063
var content;
9064
if (/\bin\b/.test(expr)) {
9065
content = expr.substring(1, expr.length - 1).split(/\bin\b/g);
9066
return new AstForInExpression(transformStatement(trim(content[0])), transformExpression(content[1]))
9067
}
9068
if (expr.indexOf(":") >= 0 && expr.indexOf(";") < 0) {
9069
content = expr.substring(1, expr.length - 1).split(":");
9070
return new AstForEachExpression(transformStatement(trim(content[0])), transformExpression(content[1]))
9071
}
9072
content = expr.substring(1, expr.length - 1).split(";");
9073
return new AstForExpression(transformStatement(trim(content[0])), transformExpression(content[1]), transformExpression(content[2]))
9074
}
9075
9076
function sortByWeight(array) {
9077
array.sort(function(a, b) {
9078
return b.weight - a.weight
9079
})
9080
}
9081
function AstInnerInterface(name, body, isStatic) {
9082
this.name = name;
9083
this.body = body;
9084
this.isStatic = isStatic;
9085
body.owner = this
9086
}
9087
AstInnerInterface.prototype.toString = function() {
9088
return "" + this.body
9089
};
9090
9091
function AstInnerClass(name, body, isStatic) {
9092
this.name = name;
9093
this.body = body;
9094
this.isStatic = isStatic;
9095
body.owner = this
9096
}
9097
AstInnerClass.prototype.toString = function() {
9098
return "" + this.body
9099
};
9100
9101
function transformInnerClass(class_) {
9102
var m = classesRegex.exec(class_);
9103
classesRegex.lastIndex = 0;
9104
var isStatic = m[1].indexOf("static") >= 0;
9105
var body = atoms[getAtomIndex(m[6])],
9106
innerClass;
9107
var oldClassId = currentClassId,
9108
newClassId = generateClassId();
9109
currentClassId = newClassId;
9110
if (m[2] === "interface") innerClass = new AstInnerInterface(m[3], transformInterfaceBody(body, m[3], m[4]), isStatic);
9111
else innerClass = new AstInnerClass(m[3], transformClassBody(body, m[3], m[4], m[5]), isStatic);
9112
appendClass(innerClass, newClassId, oldClassId);
9113
currentClassId = oldClassId;
9114
return innerClass
9115
}
9116
function AstClassMethod(name, params, body, isStatic) {
9117
this.name = name;
9118
this.params = params;
9119
this.body = body;
9120
this.isStatic = isStatic
9121
}
9122
AstClassMethod.prototype.toString = function() {
9123
var paramNames = appendToLookupTable({},
9124
this.params.getNames());
9125
var oldContext = replaceContext;
9126
replaceContext = function(subject) {
9127
return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)
9128
};
9129
var body = this.params.prependMethodArgs(this.body.toString());
9130
var result = "function " + this.methodId + this.params + " " + body + "\n";
9131
replaceContext = oldContext;
9132
return result
9133
};
9134
9135
function transformClassMethod(method) {
9136
var m = methodsRegex.exec(method);
9137
methodsRegex.lastIndex = 0;
9138
var isStatic = m[1].indexOf("static") >= 0;
9139
var body = m[6] !== ";" ? atoms[getAtomIndex(m[6])] : "{}";
9140
return new AstClassMethod(m[3], transformParams(atoms[getAtomIndex(m[4])]), transformStatementsBlock(body), isStatic)
9141
}
9142
function AstClassField(definitions, fieldType, isStatic) {
9143
this.definitions = definitions;
9144
this.fieldType = fieldType;
9145
this.isStatic = isStatic
9146
}
9147
AstClassField.prototype.getNames = function() {
9148
var names = [];
9149
for (var i = 0, l = this.definitions.length; i < l; ++i) names.push(this.definitions[i].name);
9150
return names
9151
};
9152
AstClassField.prototype.toString = function() {
9153
var thisPrefix = replaceContext({
9154
name: "[this]"
9155
});
9156
if (this.isStatic) {
9157
var className = this.owner.name;
9158
var staticDeclarations = [];
9159
for (var i = 0, l = this.definitions.length; i < l; ++i) {
9160
var definition = this.definitions[i];
9161
var name = definition.name,
9162
staticName = className + "." + name;
9163
var declaration = "if(" + staticName + " === void(0)) {\n" + " " + staticName + " = " + definition.value + "; }\n" + "$p.defineProperty(" + thisPrefix + ", " + "'" + name + "', { get: function(){return " + staticName + ";}, " + "set: function(val){" + staticName + " = val;} });\n";
9164
staticDeclarations.push(declaration)
9165
}
9166
return staticDeclarations.join("")
9167
}
9168
return thisPrefix + "." + this.definitions.join("; " + thisPrefix + ".")
9169
};
9170
9171
function transformClassField(statement) {
9172
var attrAndType = attrAndTypeRegex.exec(statement);
9173
var isStatic = attrAndType[1].indexOf("static") >= 0;
9174
var definitions = statement.substring(attrAndType[0].length).split(/,\s*/g);
9175
var defaultTypeValue = getDefaultValueForType(attrAndType[2]);
9176
for (var i = 0; i < definitions.length; ++i) definitions[i] = transformVarDefinition(definitions[i], defaultTypeValue);
9177
return new AstClassField(definitions, attrAndType[2], isStatic)
9178
}
9179
function AstConstructor(params, body) {
9180
this.params = params;
9181
this.body = body
9182
}
9183
AstConstructor.prototype.toString = function() {
9184
var paramNames = appendToLookupTable({},
9185
this.params.getNames());
9186
var oldContext = replaceContext;
9187
replaceContext = function(subject) {
9188
return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)
9189
};
9190
var prefix = "function $constr_" + this.params.params.length + this.params.toString();
9191
var body = this.params.prependMethodArgs(this.body.toString());
9192
if (!/\$(superCstr|constr)\b/.test(body)) body = "{\n$superCstr();\n" + body.substring(1);
9193
replaceContext = oldContext;
9194
return prefix + body + "\n"
9195
};
9196
9197
function transformConstructor(cstr) {
9198
var m = (new RegExp(/"B(\d+)"\s*"A(\d+)"/)).exec(cstr);
9199
var params = transformParams(atoms[m[1]]);
9200
return new AstConstructor(params, transformStatementsBlock(atoms[m[2]]))
9201
}
9202
function AstInterfaceBody(name, interfacesNames, methodsNames, fields, innerClasses, misc) {
9203
var i, l;
9204
this.name = name;
9205
this.interfacesNames = interfacesNames;
9206
this.methodsNames = methodsNames;
9207
this.fields = fields;
9208
this.innerClasses = innerClasses;
9209
this.misc = misc;
9210
for (i = 0, l = fields.length; i < l; ++i) fields[i].owner = this
9211
}
9212
AstInterfaceBody.prototype.getMembers = function(classFields, classMethods, classInners) {
9213
if (this.owner.base) this.owner.base.body.getMembers(classFields, classMethods, classInners);
9214
var i, j, l, m;
9215
for (i = 0, l = this.fields.length; i < l; ++i) {
9216
var fieldNames = this.fields[i].getNames();
9217
for (j = 0, m = fieldNames.length; j < m; ++j) classFields[fieldNames[j]] = this.fields[i]
9218
}
9219
for (i = 0, l = this.methodsNames.length; i < l; ++i) {
9220
var methodName = this.methodsNames[i];
9221
classMethods[methodName] = true
9222
}
9223
for (i = 0, l = this.innerClasses.length; i < l; ++i) {
9224
var innerClass = this.innerClasses[i];
9225
classInners[innerClass.name] = innerClass
9226
}
9227
};
9228
AstInterfaceBody.prototype.toString = function() {
9229
function getScopeLevel(p) {
9230
var i = 0;
9231
while (p) {
9232
++i;
9233
p = p.scope
9234
}
9235
return i
9236
}
9237
var scopeLevel = getScopeLevel(this.owner);
9238
var className = this.name;
9239
var staticDefinitions = "";
9240
var metadata = "";
9241
var thisClassFields = {},
9242
thisClassMethods = {},
9243
thisClassInners = {};
9244
this.getMembers(thisClassFields, thisClassMethods, thisClassInners);
9245
var i, l, j, m;
9246
if (this.owner.interfaces) {
9247
var resolvedInterfaces = [],
9248
resolvedInterface;
9249
for (i = 0, l = this.interfacesNames.length; i < l; ++i) {
9250
if (!this.owner.interfaces[i]) continue;
9251
resolvedInterface = replaceContext({
9252
name: this.interfacesNames[i]
9253
});
9254
resolvedInterfaces.push(resolvedInterface);
9255
staticDefinitions += "$p.extendInterfaceMembers(" + className + ", " + resolvedInterface + ");\n"
9256
}
9257
metadata += className + ".$interfaces = [" + resolvedInterfaces.join(", ") + "];\n"
9258
}
9259
metadata += className + ".$isInterface = true;\n";
9260
metadata += className + ".$methods = ['" + this.methodsNames.join("', '") + "'];\n";
9261
sortByWeight(this.innerClasses);
9262
for (i = 0, l = this.innerClasses.length; i < l; ++i) {
9263
var innerClass = this.innerClasses[i];
9264
if (innerClass.isStatic) staticDefinitions += className + "." + innerClass.name + " = " + innerClass + ";\n"
9265
}
9266
for (i = 0, l = this.fields.length; i < l; ++i) {
9267
var field = this.fields[i];
9268
if (field.isStatic) staticDefinitions += className + "." + field.definitions.join(";\n" + className + ".") + ";\n"
9269
}
9270
return "(function() {\n" + "function " + className + "() { throw 'Unable to create the interface'; }\n" + staticDefinitions + metadata + "return " + className + ";\n" + "})()"
9271
};
9272
transformInterfaceBody = function(body, name, baseInterfaces) {
9273
var declarations = body.substring(1, body.length - 1);
9274
declarations = extractClassesAndMethods(declarations);
9275
declarations = extractConstructors(declarations, name);
9276
var methodsNames = [],
9277
classes = [];
9278
declarations = declarations.replace(/"([DE])(\d+)"/g, function(all, type, index) {
9279
if (type === "D") methodsNames.push(index);
9280
else if (type === "E") classes.push(index);
9281
return ""
9282
});
9283
var fields = declarations.split(/;(?:\s*;)*/g);
9284
var baseInterfaceNames;
9285
var i, l;
9286
if (baseInterfaces !== undef) baseInterfaceNames = baseInterfaces.replace(/^\s*extends\s+(.+?)\s*$/g, "$1").split(/\s*,\s*/g);
9287
for (i = 0, l = methodsNames.length; i < l; ++i) {
9288
var method = transformClassMethod(atoms[methodsNames[i]]);
9289
methodsNames[i] = method.name
9290
}
9291
for (i = 0, l = fields.length - 1; i < l; ++i) {
9292
var field = trimSpaces(fields[i]);
9293
fields[i] = transformClassField(field.middle)
9294
}
9295
var tail = fields.pop();
9296
for (i = 0, l = classes.length; i < l; ++i) classes[i] = transformInnerClass(atoms[classes[i]]);
9297
return new AstInterfaceBody(name, baseInterfaceNames, methodsNames, fields, classes, {
9298
tail: tail
9299
})
9300
};
9301
9302
function AstClassBody(name, baseClassName, interfacesNames, functions, methods, fields, cstrs, innerClasses, misc) {
9303
var i, l;
9304
this.name = name;
9305
this.baseClassName = baseClassName;
9306
this.interfacesNames = interfacesNames;
9307
this.functions = functions;
9308
this.methods = methods;
9309
this.fields = fields;
9310
this.cstrs = cstrs;
9311
this.innerClasses = innerClasses;
9312
this.misc = misc;
9313
for (i = 0, l = fields.length; i < l; ++i) fields[i].owner = this
9314
}
9315
AstClassBody.prototype.getMembers = function(classFields, classMethods, classInners) {
9316
if (this.owner.base) this.owner.base.body.getMembers(classFields, classMethods, classInners);
9317
var i, j, l, m;
9318
for (i = 0, l = this.fields.length; i < l; ++i) {
9319
var fieldNames = this.fields[i].getNames();
9320
for (j = 0, m = fieldNames.length; j < m; ++j) classFields[fieldNames[j]] = this.fields[i]
9321
}
9322
for (i = 0, l = this.methods.length; i < l; ++i) {
9323
var method = this.methods[i];
9324
classMethods[method.name] = method
9325
}
9326
for (i = 0, l = this.innerClasses.length; i < l; ++i) {
9327
var innerClass = this.innerClasses[i];
9328
classInners[innerClass.name] = innerClass
9329
}
9330
};
9331
AstClassBody.prototype.toString = function() {
9332
function getScopeLevel(p) {
9333
var i = 0;
9334
while (p) {
9335
++i;
9336
p = p.scope
9337
}
9338
return i
9339
}
9340
var scopeLevel = getScopeLevel(this.owner);
9341
var selfId = "$this_" + scopeLevel;
9342
var className = this.name;
9343
var result = "var " + selfId + " = this;\n";
9344
var staticDefinitions = "";
9345
var metadata = "";
9346
var thisClassFields = {},
9347
thisClassMethods = {},
9348
thisClassInners = {};
9349
this.getMembers(thisClassFields, thisClassMethods, thisClassInners);
9350
var oldContext = replaceContext;
9351
replaceContext = function(subject) {
9352
var name = subject.name;
9353
if (name === "this") return subject.callSign || !subject.member ? selfId + ".$self" : selfId;
9354
if (thisClassFields.hasOwnProperty(name)) return thisClassFields[name].isStatic ? className + "." + name : selfId + "." + name;
9355
if (thisClassInners.hasOwnProperty(name)) return selfId + "." + name;
9356
if (thisClassMethods.hasOwnProperty(name)) return thisClassMethods[name].isStatic ? className + "." + name : selfId + ".$self." + name;
9357
return oldContext(subject)
9358
};
9359
var resolvedBaseClassName;
9360
if (this.baseClassName) {
9361
resolvedBaseClassName = oldContext({
9362
name: this.baseClassName
9363
});
9364
result += "var $super = { $upcast: " + selfId + " };\n";
9365
result += "function $superCstr(){" + resolvedBaseClassName + ".apply($super,arguments);if(!('$self' in $super)) $p.extendClassChain($super)}\n";
9366
metadata += className + ".$base = " + resolvedBaseClassName + ";\n"
9367
} else result += "function $superCstr(){$p.extendClassChain(" + selfId + ")}\n";
9368
if (this.owner.base) staticDefinitions += "$p.extendStaticMembers(" + className + ", " + resolvedBaseClassName + ");\n";
9369
var i, l, j, m;
9370
if (this.owner.interfaces) {
9371
var resolvedInterfaces = [],
9372
resolvedInterface;
9373
for (i = 0, l = this.interfacesNames.length; i < l; ++i) {
9374
if (!this.owner.interfaces[i]) continue;
9375
resolvedInterface = oldContext({
9376
name: this.interfacesNames[i]
9377
});
9378
resolvedInterfaces.push(resolvedInterface);
9379
staticDefinitions += "$p.extendInterfaceMembers(" + className + ", " + resolvedInterface + ");\n"
9380
}
9381
metadata += className + ".$interfaces = [" + resolvedInterfaces.join(", ") + "];\n"
9382
}
9383
if (this.functions.length > 0) result += this.functions.join("\n") + "\n";
9384
sortByWeight(this.innerClasses);
9385
for (i = 0, l = this.innerClasses.length; i < l; ++i) {
9386
var innerClass = this.innerClasses[i];
9387
if (innerClass.isStatic) {
9388
staticDefinitions += className + "." + innerClass.name + " = " + innerClass + ";\n";
9389
result += selfId + "." + innerClass.name + " = " + className + "." + innerClass.name + ";\n"
9390
} else result += selfId + "." + innerClass.name + " = " + innerClass + ";\n"
9391
}
9392
for (i = 0, l = this.fields.length; i < l; ++i) {
9393
var field = this.fields[i];
9394
if (field.isStatic) {
9395
staticDefinitions += className + "." + field.definitions.join(";\n" + className + ".") + ";\n";
9396
for (j = 0, m = field.definitions.length; j < m; ++j) {
9397
var fieldName = field.definitions[j].name,
9398
staticName = className + "." + fieldName;
9399
result += "$p.defineProperty(" + selfId + ", '" + fieldName + "', {" + "get: function(){return " + staticName + "}, " + "set: function(val){" + staticName + " = val}});\n"
9400
}
9401
} else result += selfId + "." + field.definitions.join(";\n" + selfId + ".") + ";\n"
9402
}
9403
var methodOverloads = {};
9404
for (i = 0, l = this.methods.length; i < l; ++i) {
9405
var method = this.methods[i];
9406
var overload = methodOverloads[method.name];
9407
var methodId = method.name + "$" + method.params.params.length;
9408
var hasMethodArgs = !!method.params.methodArgsParam;
9409
if (overload) {
9410
++overload;
9411
methodId += "_" + overload
9412
} else overload = 1;
9413
method.methodId = methodId;
9414
methodOverloads[method.name] = overload;
9415
if (method.isStatic) {
9416
staticDefinitions += method;
9417
staticDefinitions += "$p.addMethod(" + className + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n";
9418
result += "$p.addMethod(" + selfId + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n"
9419
} else {
9420
result += method;
9421
result += "$p.addMethod(" + selfId + ", '" + method.name + "', " + methodId + ", " + hasMethodArgs + ");\n"
9422
}
9423
}
9424
result += trim(this.misc.tail);
9425
if (this.cstrs.length > 0) result += this.cstrs.join("\n") + "\n";
9426
result += "function $constr() {\n";
9427
var cstrsIfs = [];
9428
for (i = 0, l = this.cstrs.length; i < l; ++i) {
9429
var paramsLength = this.cstrs[i].params.params.length;
9430
var methodArgsPresent = !!this.cstrs[i].params.methodArgsParam;
9431
cstrsIfs.push("if(arguments.length " + (methodArgsPresent ? ">=" : "===") + " " + paramsLength + ") { " + "$constr_" + paramsLength + ".apply(" + selfId + ", arguments); }")
9432
}
9433
if (cstrsIfs.length > 0) result += cstrsIfs.join(" else ") + " else ";
9434
result += "$superCstr();\n}\n";
9435
result += "$constr.apply(null, arguments);\n";
9436
replaceContext = oldContext;
9437
return "(function() {\n" + "function " + className + "() {\n" + result + "}\n" + staticDefinitions + metadata + "return " + className + ";\n" + "})()"
9438
};
9439
transformClassBody = function(body, name, baseName, interfaces) {
9440
var declarations = body.substring(1, body.length - 1);
9441
declarations = extractClassesAndMethods(declarations);
9442
declarations = extractConstructors(declarations, name);
9443
var methods = [],
9444
classes = [],
9445
cstrs = [],
9446
functions = [];
9447
declarations = declarations.replace(/"([DEGH])(\d+)"/g, function(all, type, index) {
9448
if (type === "D") methods.push(index);
9449
else if (type === "E") classes.push(index);
9450
else if (type === "H") functions.push(index);
9451
else cstrs.push(index);
9452
return ""
9453
});
9454
var fields = declarations.replace(/^(?:\s*;)+/, "").split(/;(?:\s*;)*/g);
9455
var baseClassName, interfacesNames;
9456
var i;
9457
if (baseName !== undef) baseClassName = baseName.replace(/^\s*extends\s+([A-Za-z_$][\w$]*\b(?:\s*\.\s*[A-Za-z_$][\w$]*\b)*)\s*$/g, "$1");
9458
if (interfaces !== undef) interfacesNames = interfaces.replace(/^\s*implements\s+(.+?)\s*$/g, "$1").split(/\s*,\s*/g);
9459
for (i = 0; i < functions.length; ++i) functions[i] = transformFunction(atoms[functions[i]]);
9460
for (i = 0; i < methods.length; ++i) methods[i] = transformClassMethod(atoms[methods[i]]);
9461
for (i = 0; i < fields.length - 1; ++i) {
9462
var field = trimSpaces(fields[i]);
9463
fields[i] = transformClassField(field.middle)
9464
}
9465
var tail = fields.pop();
9466
for (i = 0; i < cstrs.length; ++i) cstrs[i] = transformConstructor(atoms[cstrs[i]]);
9467
for (i = 0; i < classes.length; ++i) classes[i] = transformInnerClass(atoms[classes[i]]);
9468
return new AstClassBody(name, baseClassName, interfacesNames, functions, methods, fields, cstrs, classes, {
9469
tail: tail
9470
})
9471
};
9472
9473
function AstInterface(name, body) {
9474
this.name = name;
9475
this.body = body;
9476
body.owner = this
9477
}
9478
AstInterface.prototype.toString = function() {
9479
return "var " + this.name + " = " + this.body + ";\n" + "$p." + this.name + " = " + this.name + ";\n"
9480
};
9481
9482
function AstClass(name, body) {
9483
this.name = name;
9484
this.body = body;
9485
body.owner = this
9486
}
9487
AstClass.prototype.toString = function() {
9488
return "var " + this.name + " = " + this.body + ";\n" + "$p." + this.name + " = " + this.name + ";\n"
9489
};
9490
9491
function transformGlobalClass(class_) {
9492
var m = classesRegex.exec(class_);
9493
classesRegex.lastIndex = 0;
9494
var body = atoms[getAtomIndex(m[6])];
9495
var oldClassId = currentClassId,
9496
newClassId = generateClassId();
9497
currentClassId = newClassId;
9498
var globalClass;
9499
if (m[2] === "interface") globalClass = new AstInterface(m[3], transformInterfaceBody(body, m[3], m[4]));
9500
else globalClass = new AstClass(m[3], transformClassBody(body, m[3], m[4], m[5]));
9501
appendClass(globalClass, newClassId, oldClassId);
9502
currentClassId = oldClassId;
9503
return globalClass
9504
}
9505
function AstMethod(name, params, body) {
9506
this.name = name;
9507
this.params = params;
9508
this.body = body
9509
}
9510
AstMethod.prototype.toString = function() {
9511
var paramNames = appendToLookupTable({},
9512
this.params.getNames());
9513
var oldContext = replaceContext;
9514
replaceContext = function(subject) {
9515
return paramNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)
9516
};
9517
var body = this.params.prependMethodArgs(this.body.toString());
9518
var result = "function " + this.name + this.params + " " + body + "\n" + "$p." + this.name + " = " + this.name + ";";
9519
replaceContext = oldContext;
9520
return result
9521
};
9522
9523
function transformGlobalMethod(method) {
9524
var m = methodsRegex.exec(method);
9525
var result = methodsRegex.lastIndex = 0;
9526
return new AstMethod(m[3], transformParams(atoms[getAtomIndex(m[4])]), transformStatementsBlock(atoms[getAtomIndex(m[6])]))
9527
}
9528
function preStatementsTransform(statements) {
9529
var s = statements;
9530
s = s.replace(/\b(catch\s*"B\d+"\s*"A\d+")(\s*catch\s*"B\d+"\s*"A\d+")+/g, "$1");
9531
return s
9532
}
9533
function AstForStatement(argument, misc) {
9534
this.argument = argument;
9535
this.misc = misc
9536
}
9537
AstForStatement.prototype.toString = function() {
9538
return this.misc.prefix + this.argument.toString()
9539
};
9540
9541
function AstCatchStatement(argument, misc) {
9542
this.argument = argument;
9543
this.misc = misc
9544
}
9545
AstCatchStatement.prototype.toString = function() {
9546
return this.misc.prefix + this.argument.toString()
9547
};
9548
9549
function AstPrefixStatement(name, argument, misc) {
9550
this.name = name;
9551
this.argument = argument;
9552
this.misc = misc
9553
}
9554
AstPrefixStatement.prototype.toString = function() {
9555
var result = this.misc.prefix;
9556
if (this.argument !== undef) result += this.argument.toString();
9557
return result
9558
};
9559
9560
function AstSwitchCase(expr) {
9561
this.expr = expr
9562
}
9563
AstSwitchCase.prototype.toString = function() {
9564
return "case " + this.expr + ":"
9565
};
9566
9567
function AstLabel(label) {
9568
this.label = label
9569
}
9570
AstLabel.prototype.toString = function() {
9571
return this.label
9572
};
9573
transformStatements = function(statements, transformMethod, transformClass) {
9574
var nextStatement = new RegExp(/\b(catch|for|if|switch|while|with)\s*"B(\d+)"|\b(do|else|finally|return|throw|try|break|continue)\b|("[ADEH](\d+)")|\b(case)\s+([^:]+):|\b([A-Za-z_$][\w$]*\s*:)|(;)/g);
9575
var res = [];
9576
statements = preStatementsTransform(statements);
9577
var lastIndex = 0,
9578
m, space;
9579
while ((m = nextStatement.exec(statements)) !== null) {
9580
if (m[1] !== undef) {
9581
var i = statements.lastIndexOf('"B', nextStatement.lastIndex);
9582
var statementsPrefix = statements.substring(lastIndex, i);
9583
if (m[1] === "for") res.push(new AstForStatement(transformForExpression(atoms[m[2]]), {
9584
prefix: statementsPrefix
9585
}));
9586
else if (m[1] === "catch") res.push(new AstCatchStatement(transformParams(atoms[m[2]]), {
9587
prefix: statementsPrefix
9588
}));
9589
else res.push(new AstPrefixStatement(m[1], transformExpression(atoms[m[2]]), {
9590
prefix: statementsPrefix
9591
}))
9592
} else if (m[3] !== undef) res.push(new AstPrefixStatement(m[3], undef, {
9593
prefix: statements.substring(lastIndex, nextStatement.lastIndex)
9594
}));
9595
else if (m[4] !== undef) {
9596
space = statements.substring(lastIndex, nextStatement.lastIndex - m[4].length);
9597
if (trim(space).length !== 0) continue;
9598
res.push(space);
9599
var kind = m[4].charAt(1),
9600
atomIndex = m[5];
9601
if (kind === "D") res.push(transformMethod(atoms[atomIndex]));
9602
else if (kind === "E") res.push(transformClass(atoms[atomIndex]));
9603
else if (kind === "H") res.push(transformFunction(atoms[atomIndex]));
9604
else res.push(transformStatementsBlock(atoms[atomIndex]))
9605
} else if (m[6] !== undef) res.push(new AstSwitchCase(transformExpression(trim(m[7]))));
9606
else if (m[8] !== undef) {
9607
space = statements.substring(lastIndex, nextStatement.lastIndex - m[8].length);
9608
if (trim(space).length !== 0) continue;
9609
res.push(new AstLabel(statements.substring(lastIndex, nextStatement.lastIndex)))
9610
} else {
9611
var statement = trimSpaces(statements.substring(lastIndex, nextStatement.lastIndex - 1));
9612
res.push(statement.left);
9613
res.push(transformStatement(statement.middle));
9614
res.push(statement.right + ";")
9615
}
9616
lastIndex = nextStatement.lastIndex
9617
}
9618
var statementsTail = trimSpaces(statements.substring(lastIndex));
9619
res.push(statementsTail.left);
9620
if (statementsTail.middle !== "") {
9621
res.push(transformStatement(statementsTail.middle));
9622
res.push(";" + statementsTail.right)
9623
}
9624
return res
9625
};
9626
9627
function getLocalNames(statements) {
9628
var localNames = [];
9629
for (var i = 0, l = statements.length; i < l; ++i) {
9630
var statement = statements[i];
9631
if (statement instanceof AstVar) localNames = localNames.concat(statement.getNames());
9632
else if (statement instanceof AstForStatement && statement.argument.initStatement instanceof AstVar) localNames = localNames.concat(statement.argument.initStatement.getNames());
9633
else if (statement instanceof AstInnerInterface || statement instanceof AstInnerClass || statement instanceof AstInterface || statement instanceof AstClass || statement instanceof AstMethod || statement instanceof AstFunction) localNames.push(statement.name)
9634
}
9635
return appendToLookupTable({},
9636
localNames)
9637
}
9638
function AstStatementsBlock(statements) {
9639
this.statements = statements
9640
}
9641
AstStatementsBlock.prototype.toString = function() {
9642
var localNames = getLocalNames(this.statements);
9643
var oldContext = replaceContext;
9644
if (!isLookupTableEmpty(localNames)) replaceContext = function(subject) {
9645
return localNames.hasOwnProperty(subject.name) ? subject.name : oldContext(subject)
9646
};
9647
var result = "{\n" + this.statements.join("") + "\n}";
9648
replaceContext = oldContext;
9649
return result
9650
};
9651
transformStatementsBlock = function(block) {
9652
var content = trimSpaces(block.substring(1, block.length - 1));
9653
return new AstStatementsBlock(transformStatements(content.middle))
9654
};
9655
9656
function AstRoot(statements) {
9657
this.statements = statements
9658
}
9659
AstRoot.prototype.toString = function() {
9660
var classes = [],
9661
otherStatements = [],
9662
statement;
9663
for (var i = 0, len = this.statements.length; i < len; ++i) {
9664
statement = this.statements[i];
9665
if (statement instanceof AstClass || statement instanceof AstInterface) classes.push(statement);
9666
else otherStatements.push(statement)
9667
}
9668
sortByWeight(classes);
9669
var localNames = getLocalNames(this.statements);
9670
replaceContext = function(subject) {
9671
var name = subject.name;
9672
if (localNames.hasOwnProperty(name)) return name;
9673
if (globalMembers.hasOwnProperty(name) || PConstants.hasOwnProperty(name) || defaultScope.hasOwnProperty(name)) return "$p." + name;
9674
return name
9675
};
9676
var result = "// this code was autogenerated from PJS\n" + "(function($p) {\n" + classes.join("") + "\n" + otherStatements.join("") + "\n})";
9677
replaceContext = null;
9678
return result
9679
};
9680
transformMain = function() {
9681
var statements = extractClassesAndMethods(atoms[0]);
9682
statements = statements.replace(/\bimport\s+[^;]+;/g, "");
9683
return new AstRoot(transformStatements(statements, transformGlobalMethod, transformGlobalClass))
9684
};
9685
9686
function generateMetadata(ast) {
9687
var globalScope = {};
9688
var id, class_;
9689
for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) {
9690
class_ = declaredClasses[id];
9691
var scopeId = class_.scopeId,
9692
name = class_.name;
9693
if (scopeId) {
9694
var scope = declaredClasses[scopeId];
9695
class_.scope = scope;
9696
if (scope.inScope === undef) scope.inScope = {};
9697
scope.inScope[name] = class_
9698
} else globalScope[name] = class_
9699
}
9700
function findInScopes(class_, name) {
9701
var parts = name.split(".");
9702
var currentScope = class_.scope,
9703
found;
9704
while (currentScope) {
9705
if (currentScope.hasOwnProperty(parts[0])) {
9706
found = currentScope[parts[0]];
9707
break
9708
}
9709
currentScope = currentScope.scope
9710
}
9711
if (found === undef) found = globalScope[parts[0]];
9712
for (var i = 1, l = parts.length; i < l && found; ++i) found = found.inScope[parts[i]];
9713
return found
9714
}
9715
for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) {
9716
class_ = declaredClasses[id];
9717
var baseClassName = class_.body.baseClassName;
9718
if (baseClassName) {
9719
var parent = findInScopes(class_, baseClassName);
9720
if (parent) {
9721
class_.base = parent;
9722
if (!parent.derived) parent.derived = [];
9723
parent.derived.push(class_)
9724
}
9725
}
9726
var interfacesNames = class_.body.interfacesNames,
9727
interfaces = [],
9728
i, l;
9729
if (interfacesNames && interfacesNames.length > 0) {
9730
for (i = 0, l = interfacesNames.length; i < l; ++i) {
9731
var interface_ = findInScopes(class_, interfacesNames[i]);
9732
interfaces.push(interface_);
9733
if (!interface_) continue;
9734
if (!interface_.derived) interface_.derived = [];
9735
interface_.derived.push(class_)
9736
}
9737
if (interfaces.length > 0) class_.interfaces = interfaces
9738
}
9739
}
9740
}
9741
function setWeight(ast) {
9742
var queue = [],
9743
tocheck = {};
9744
var id, scopeId, class_;
9745
for (id in declaredClasses) if (declaredClasses.hasOwnProperty(id)) {
9746
class_ = declaredClasses[id];
9747
if (!class_.inScope && !class_.derived) {
9748
queue.push(id);
9749
class_.weight = 0
9750
} else {
9751
var dependsOn = [];
9752
if (class_.inScope) for (scopeId in class_.inScope) if (class_.inScope.hasOwnProperty(scopeId)) dependsOn.push(class_.inScope[scopeId]);
9753
if (class_.derived) dependsOn = dependsOn.concat(class_.derived);
9754
tocheck[id] = dependsOn
9755
}
9756
}
9757
function removeDependentAndCheck(targetId, from) {
9758
var dependsOn = tocheck[targetId];
9759
if (!dependsOn) return false;
9760
var i = dependsOn.indexOf(from);
9761
if (i < 0) return false;
9762
dependsOn.splice(i, 1);
9763
if (dependsOn.length > 0) return false;
9764
delete tocheck[targetId];
9765
return true
9766
}
9767
while (queue.length > 0) {
9768
id = queue.shift();
9769
class_ = declaredClasses[id];
9770
if (class_.scopeId && removeDependentAndCheck(class_.scopeId, class_)) {
9771
queue.push(class_.scopeId);
9772
declaredClasses[class_.scopeId].weight = class_.weight + 1
9773
}
9774
if (class_.base && removeDependentAndCheck(class_.base.classId, class_)) {
9775
queue.push(class_.base.classId);
9776
class_.base.weight = class_.weight + 1
9777
}
9778
if (class_.interfaces) {
9779
var i, l;
9780
for (i = 0, l = class_.interfaces.length; i < l; ++i) {
9781
if (!class_.interfaces[i] || !removeDependentAndCheck(class_.interfaces[i].classId, class_)) continue;
9782
queue.push(class_.interfaces[i].classId);
9783
class_.interfaces[i].weight = class_.weight + 1
9784
}
9785
}
9786
}
9787
}
9788
var transformed = transformMain();
9789
generateMetadata(transformed);
9790
setWeight(transformed);
9791
var redendered = transformed.toString();
9792
redendered = redendered.replace(/\s*\n(?:[\t ]*\n)+/g, "\n\n");
9793
redendered = redendered.replace(/__x([0-9A-F]{4})/g, function(all, hexCode) {
9794
return String.fromCharCode(parseInt(hexCode, 16))
9795
});
9796
return injectStrings(redendered, strings)
9797
}
9798
9799
function preprocessCode(aCode, sketch) {
9800
var dm = (new RegExp(/\/\*\s*@pjs\s+((?:[^\*]|\*+[^\*\/])*)\*\//g)).exec(aCode);
9801
if (dm && dm.length === 2) {
9802
var jsonItems = [],
9803
directives = dm.splice(1, 2)[0].replace(/\{([\s\S]*?)\}/g, function() {
9804
return function(all, item) {
9805
jsonItems.push(item);
9806
return "{" + (jsonItems.length - 1) + "}"
9807
}
9808
}()).replace("\n", "").replace("\r", "").split(";");
9809
var clean = function(s) {
9810
return s.replace(/^\s*["']?/, "").replace(/["']?\s*$/, "")
9811
};
9812
for (var i = 0, dl = directives.length; i < dl; i++) {
9813
var pair = directives[i].split("=");
9814
if (pair && pair.length === 2) {
9815
var key = clean(pair[0]),
9816
value = clean(pair[1]),
9817
list = [];
9818
if (key === "preload") {
9819
list = value.split(",");
9820
for (var j = 0, jl = list.length; j < jl; j++) {
9821
var imageName = clean(list[j]);
9822
sketch.imageCache.add(imageName)
9823
}
9824
} else if (key === "font") {
9825
list = value.split(",");
9826
for (var x = 0, xl = list.length; x < xl; x++) {
9827
var fontName = clean(list[x]),
9828
index = /^\{(\d*?)\}$/.exec(fontName);
9829
PFont.preloading.add(index ? JSON.parse("{" + jsonItems[index[1]] + "}") : fontName)
9830
}
9831
} else if (key === "pauseOnBlur") sketch.options.pauseOnBlur = value === "true";
9832
else if (key === "globalKeyEvents") sketch.options.globalKeyEvents = value === "true";
9833
else if (key.substring(0, 6) === "param-") sketch.params[key.substring(6)] = value;
9834
else sketch.options[key] = value
9835
}
9836
}
9837
}
9838
return aCode
9839
}
9840
Processing.compile = function(pdeCode) {
9841
var sketch = new Processing.Sketch;
9842
var code = preprocessCode(pdeCode, sketch);
9843
var compiledPde = parseProcessing(code);
9844
sketch.sourceCode = compiledPde;
9845
return sketch
9846
};
9847
var tinylogLite = function() {
9848
var tinylogLite = {},
9849
undef = "undefined",
9850
func = "function",
9851
False = !1,
9852
True = !0,
9853
logLimit = 512,
9854
log = "log";
9855
if (typeof tinylog !== undef && typeof tinylog[log] === func) tinylogLite[log] = tinylog[log];
9856
else if (typeof document !== undef && !document.fake)(function() {
9857
var doc = document,
9858
$div = "div",
9859
$style = "style",
9860
$title = "title",
9861
containerStyles = {
9862
zIndex: 1E4,
9863
position: "fixed",
9864
bottom: "0px",
9865
width: "100%",
9866
height: "15%",
9867
fontFamily: "sans-serif",
9868
color: "#ccc",
9869
backgroundColor: "black"
9870
},
9871
outputStyles = {
9872
position: "relative",
9873
fontFamily: "monospace",
9874
overflow: "auto",
9875
height: "100%",
9876
paddingTop: "5px"
9877
},
9878
resizerStyles = {
9879
height: "5px",
9880
marginTop: "-5px",
9881
cursor: "n-resize",
9882
backgroundColor: "darkgrey"
9883
},
9884
closeButtonStyles = {
9885
position: "absolute",
9886
top: "5px",
9887
right: "20px",
9888
color: "#111",
9889
MozBorderRadius: "4px",
9890
webkitBorderRadius: "4px",
9891
borderRadius: "4px",
9892
cursor: "pointer",
9893
fontWeight: "normal",
9894
textAlign: "center",
9895
padding: "3px 5px",
9896
backgroundColor: "#333",
9897
fontSize: "12px"
9898
},
9899
entryStyles = {
9900
minHeight: "16px"
9901
},
9902
entryTextStyles = {
9903
fontSize: "12px",
9904
margin: "0 8px 0 8px",
9905
maxWidth: "100%",
9906
whiteSpace: "pre-wrap",
9907
overflow: "auto"
9908
},
9909
view = doc.defaultView,
9910
docElem = doc.documentElement,
9911
docElemStyle = docElem[$style],
9912
setStyles = function() {
9913
var i = arguments.length,
9914
elemStyle, styles, style;
9915
while (i--) {
9916
styles = arguments[i--];
9917
elemStyle = arguments[i][$style];
9918
for (style in styles) if (styles.hasOwnProperty(style)) elemStyle[style] = styles[style]
9919
}
9920
},
9921
observer = function(obj, event, handler) {
9922
if (obj.addEventListener) obj.addEventListener(event, handler, False);
9923
else if (obj.attachEvent) obj.attachEvent("on" + event, handler);
9924
return [obj, event, handler]
9925
},
9926
unobserve = function(obj, event, handler) {
9927
if (obj.removeEventListener) obj.removeEventListener(event, handler, False);
9928
else if (obj.detachEvent) obj.detachEvent("on" + event, handler)
9929
},
9930
clearChildren = function(node) {
9931
var children = node.childNodes,
9932
child = children.length;
9933
while (child--) node.removeChild(children.item(0))
9934
},
9935
append = function(to, elem) {
9936
return to.appendChild(elem)
9937
},
9938
createElement = function(localName) {
9939
return doc.createElement(localName)
9940
},
9941
createTextNode = function(text) {
9942
return doc.createTextNode(text)
9943
},
9944
createLog = tinylogLite[log] = function(message) {
9945
var uninit, originalPadding = docElemStyle.paddingBottom,
9946
container = createElement($div),
9947
containerStyle = container[$style],
9948
resizer = append(container, createElement($div)),
9949
output = append(container, createElement($div)),
9950
closeButton = append(container, createElement($div)),
9951
resizingLog = False,
9952
previousHeight = False,
9953
previousScrollTop = False,
9954
messages = 0,
9955
updateSafetyMargin = function() {
9956
docElemStyle.paddingBottom = container.clientHeight + "px"
9957
},
9958
setContainerHeight = function(height) {
9959
var viewHeight = view.innerHeight,
9960
resizerHeight = resizer.clientHeight;
9961
if (height < 0) height = 0;
9962
else if (height + resizerHeight > viewHeight) height = viewHeight - resizerHeight;
9963
containerStyle.height = height / viewHeight * 100 + "%";
9964
updateSafetyMargin()
9965
},
9966
observers = [observer(doc, "mousemove", function(evt) {
9967
if (resizingLog) {
9968
setContainerHeight(view.innerHeight - evt.clientY);
9969
output.scrollTop = previousScrollTop
9970
}
9971
}), observer(doc, "mouseup", function() {
9972
if (resizingLog) resizingLog = previousScrollTop = False
9973
}), observer(resizer, "dblclick", function(evt) {
9974
evt.preventDefault();
9975
if (previousHeight) {
9976
setContainerHeight(previousHeight);
9977
previousHeight = False
9978
} else {
9979
previousHeight = container.clientHeight;
9980
containerStyle.height = "0px"
9981
}
9982
}), observer(resizer, "mousedown", function(evt) {
9983
evt.preventDefault();
9984
resizingLog = True;
9985
previousScrollTop = output.scrollTop
9986
}), observer(resizer, "contextmenu", function() {
9987
resizingLog = False
9988
}), observer(closeButton, "click", function() {
9989
uninit()
9990
})];
9991
uninit = function() {
9992
var i = observers.length;
9993
while (i--) unobserve.apply(tinylogLite, observers[i]);
9994
docElem.removeChild(container);
9995
docElemStyle.paddingBottom = originalPadding;
9996
clearChildren(output);
9997
clearChildren(container);
9998
tinylogLite[log] = createLog
9999
};
10000
setStyles(container, containerStyles, output, outputStyles, resizer, resizerStyles, closeButton, closeButtonStyles);
10001
closeButton[$title] = "Close Log";
10002
append(closeButton, createTextNode("\u2716"));
10003
resizer[$title] = "Double-click to toggle log minimization";
10004
docElem.insertBefore(container, docElem.firstChild);
10005
tinylogLite[log] = function(message) {
10006
if (messages === logLimit) output.removeChild(output.firstChild);
10007
else messages++;
10008
var entry = append(output, createElement($div)),
10009
entryText = append(entry, createElement($div));
10010
entry[$title] = (new Date).toLocaleTimeString();
10011
setStyles(entry, entryStyles, entryText, entryTextStyles);
10012
append(entryText, createTextNode(message));
10013
output.scrollTop = output.scrollHeight
10014
};
10015
tinylogLite[log](message);
10016
updateSafetyMargin()
10017
}
10018
})();
10019
else if (typeof print === func) tinylogLite[log] = print;
10020
return tinylogLite
10021
}();
10022
Processing.logger = tinylogLite;
10023
Processing.version = "1.4.1";
10024
Processing.lib = {};
10025
Processing.registerLibrary = function(name, desc) {
10026
Processing.lib[name] = desc;
10027
if (desc.hasOwnProperty("init")) desc.init(defaultScope)
10028
};
10029
Processing.instances = processingInstances;
10030
Processing.getInstanceById = function(name) {
10031
return processingInstances[processingInstanceIds[name]]
10032
};
10033
Processing.Sketch = function(attachFunction) {
10034
this.attachFunction = attachFunction;
10035
this.options = {
10036
pauseOnBlur: false,
10037
globalKeyEvents: false
10038
};
10039
this.onLoad = nop;
10040
this.onSetup = nop;
10041
this.onPause = nop;
10042
this.onLoop = nop;
10043
this.onFrameStart = nop;
10044
this.onFrameEnd = nop;
10045
this.onExit = nop;
10046
this.params = {};
10047
this.imageCache = {
10048
pending: 0,
10049
images: {},
10050
operaCache: {},
10051
add: function(href, img) {
10052
if (this.images[href]) return;
10053
if (!isDOMPresent) this.images[href] = null;
10054
if (!img) {
10055
img = new Image;
10056
img.onload = function(owner) {
10057
return function() {
10058
owner.pending--
10059
}
10060
}(this);
10061
this.pending++;
10062
img.src = href
10063
}
10064
this.images[href] = img;
10065
if (window.opera) {
10066
var div = document.createElement("div");
10067
div.appendChild(img);
10068
div.style.position = "absolute";
10069
div.style.opacity = 0;
10070
div.style.width = "1px";
10071
div.style.height = "1px";
10072
if (!this.operaCache[href]) {
10073
document.body.appendChild(div);
10074
this.operaCache[href] = div
10075
}
10076
}
10077
}
10078
};
10079
this.sourceCode = undefined;
10080
this.attach = function(processing) {
10081
if (typeof this.attachFunction === "function") this.attachFunction(processing);
10082
else if (this.sourceCode) {
10083
var func = (new Function("return (" + this.sourceCode + ");"))();
10084
func(processing);
10085
this.attachFunction = func
10086
} else throw "Unable to attach sketch to the processing instance";
10087
};
10088
this.toString = function() {
10089
var i;
10090
var code = "((function(Sketch) {\n";
10091
code += "var sketch = new Sketch(\n" + this.sourceCode + ");\n";
10092
for (i in this.options) if (this.options.hasOwnProperty(i)) {
10093
var value = this.options[i];
10094
code += "sketch.options." + i + " = " + (typeof value === "string" ? '"' + value + '"' : "" + value) + ";\n"
10095
}
10096
for (i in this.imageCache) if (this.options.hasOwnProperty(i)) code += 'sketch.imageCache.add("' + i + '");\n';
10097
code += "return sketch;\n})(Processing.Sketch))";
10098
return code
10099
}
10100
};
10101
var loadSketchFromSources = function(canvas, sources) {
10102
var code = [],
10103
errors = [],
10104
sourcesCount = sources.length,
10105
loaded = 0;
10106
10107
function ajaxAsync(url, callback) {
10108
var xhr = new XMLHttpRequest;
10109
xhr.onreadystatechange = function() {
10110
if (xhr.readyState === 4) {
10111
var error;
10112
if (xhr.status !== 200 && xhr.status !== 0) error = "Invalid XHR status " + xhr.status;
10113
else if (xhr.responseText === "") if ("withCredentials" in new XMLHttpRequest && (new XMLHttpRequest).withCredentials === false && window.location.protocol === "file:") error = "XMLHttpRequest failure, possibly due to a same-origin policy violation. You can try loading this page in another browser, or load it from http://localhost using a local webserver. See the Processing.js README for a more detailed explanation of this problem and solutions.";
10114
else error = "File is empty.";
10115
callback(xhr.responseText, error)
10116
}
10117
};
10118
xhr.open("GET", url, true);
10119
if (xhr.overrideMimeType) xhr.overrideMimeType("application/json");
10120
xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT");
10121
xhr.send(null)
10122
}
10123
function loadBlock(index, filename) {
10124
function callback(block, error) {
10125
code[index] = block;
10126
++loaded;
10127
if (error) errors.push(filename + " ==> " + error);
10128
if (loaded === sourcesCount) if (errors.length === 0) try {
10129
return new Processing(canvas, code.join("\n"))
10130
} catch(e) {
10131
throw "Processing.js: Unable to execute pjs sketch: " + e;
10132
} else throw "Processing.js: Unable to load pjs sketch files: " + errors.join("\n");
10133
}
10134
if (filename.charAt(0) === "#") {
10135
var scriptElement = document.getElementById(filename.substring(1));
10136
if (scriptElement) callback(scriptElement.text || scriptElement.textContent);
10137
else callback("", "Unable to load pjs sketch: element with id '" + filename.substring(1) + "' was not found");
10138
return
10139
}
10140
ajaxAsync(filename, callback)
10141
}
10142
for (var i = 0; i < sourcesCount; ++i) loadBlock(i, sources[i])
10143
};
10144
var init = function() {
10145
document.removeEventListener("DOMContentLoaded", init, false);
10146
processingInstances = [];
10147
var canvas = document.getElementsByTagName("canvas"),
10148
filenames;
10149
for (var i = 0, l = canvas.length; i < l; i++) {
10150
var processingSources = canvas[i].getAttribute("data-processing-sources");
10151
if (processingSources === null) {
10152
processingSources = canvas[i].getAttribute("data-src");
10153
if (processingSources === null) processingSources = canvas[i].getAttribute("datasrc")
10154
}
10155
if (processingSources) {
10156
filenames = processingSources.split(/\s+/g);
10157
for (var j = 0; j < filenames.length;) if (filenames[j]) j++;
10158
else filenames.splice(j, 1);
10159
loadSketchFromSources(canvas[i], filenames)
10160
}
10161
}
10162
var s, last, source, instance, nodelist = document.getElementsByTagName("script"),
10163
scripts = [];
10164
for (s = nodelist.length - 1; s >= 0; s--) scripts.push(nodelist[s]);
10165
for (s = 0, last = scripts.length; s < last; s++) {
10166
var script = scripts[s];
10167
if (!script.getAttribute) continue;
10168
var type = script.getAttribute("type");
10169
if (type && (type.toLowerCase() === "text/processing" || type.toLowerCase() === "application/processing")) {
10170
var target = script.getAttribute("data-processing-target");
10171
canvas = undef;
10172
if (target) canvas = document.getElementById(target);
10173
else {
10174
var nextSibling = script.nextSibling;
10175
while (nextSibling && nextSibling.nodeType !== 1) nextSibling = nextSibling.nextSibling;
10176
if (nextSibling && nextSibling.nodeName.toLowerCase() === "canvas") canvas = nextSibling
10177
}
10178
if (canvas) {
10179
if (script.getAttribute("src")) {
10180
filenames = script.getAttribute("src").split(/\s+/);
10181
loadSketchFromSources(canvas, filenames);
10182
continue
10183
}
10184
source = script.textContent || script.text;
10185
instance = new Processing(canvas, source)
10186
}
10187
}
10188
}
10189
};
10190
Processing.reload = function() {
10191
if (processingInstances.length > 0) for (var i = processingInstances.length - 1; i >= 0; i--) if (processingInstances[i]) processingInstances[i].exit();
10192
init()
10193
};
10194
Processing.loadSketchFromSources = loadSketchFromSources;
10195
Processing.disableInit = function() {
10196
if (isDOMPresent) document.removeEventListener("DOMContentLoaded", init, false)
10197
};
10198
if (isDOMPresent) {
10199
window["Processing"] = Processing;
10200
document.addEventListener("DOMContentLoaded", init, false)
10201
} else this.Processing = Processing
10202
})(window, window.document, Math);
10203
10204
10205