PageSourceSearch

https://time-and-effort.netlify.app/app.c3f9f951.js

js time-and-effort.netlify.app collected 2026-10-03 11:30:38 UTC 3,736,124 bytes, 97,290 lines download raw bytes

vendor: 4,306 bytes, lines 1-152
1// modules are defined as an array
2// [ module function, map of requires ]
3//
4// map of requires is short require name -> numeric require
5//
6// anything defined in a previous bundle is accessed via the
7// orig method which is the require for previous bundles
8parcelRequire = (function (modules, cache, entry, globalName) {
9  // Save the require from previous bundle to this closure if any
10  var previousRequire = typeof parcelRequire === 'function' && parcelRequire;
11  var nodeRequire = typeof require === 'function' && require;
12
13  function newRequire(name, jumped) {
14    if (!cache[name]) {
15      if (!modules[name]) {
16        // if we cannot find the module within our internal map or
17        // cache jump to the current global require ie. the last bundle
18        // that was added to the page.
19        var currentRequire = typeof parcelRequire === 'function' && parcelRequire;
20        if (!jumped && currentRequire) {
21          return currentRequire(name, true);
22        }
23
24        // If there are other bundles on this page the require from the
25        // previous one is saved to 'previousRequire'. Repeat this as
26        // many times as there are bundles until the module is found or
27        // we exhaust the require chain.
28        if (previousRequire) {
29          return previousRequire(name, true);
30        }
31
32        // Try the node require function if it exists.
33        if (nodeRequire && typeof name === 'string') {
34          return nodeRequire(name);
35        }
36
37        var err = new Error('Cannot find module \'' + name + '\'');
38        err.code = 'MODULE_NOT_FOUND';
39        throw err;
40      }
41
42      localRequire.resolve = resolve;
43      localRequire.cache = {};
44
45      var module = cache[name] = new newRequire.Module(name);
46
47      modules[name][0].call(module.exports, localRequire, module, module.exports, this);
48    }
49
50    return cache[name].exports;
51
52    function localRequire(x){
53      return newRequire(localRequire.resolve(x));
54    }
55
56    function resolve(x){
57      return modules[name][1][x] || x;
58    }
59  }
60
61  function Module(moduleName) {
62    this.id = moduleName;
63    this.bundle = newRequire;
64    this.exports = {};
65  }
66
67  newRequire.isParcelRequire = true;
68  newRequire.Module = Module;
69  newRequire.modules = modules;
70  newRequire.cache = cache;
71  newRequire.parent = previousRequire;
72  newRequire.register = function (id, exports) {
73    modules[id] = [function (require, module) {
74      module.exports = exports;
75    }, {}];
76  };
77
78  var error;
79  for (var i = 0; i < entry.length; i++) {
80    try {
81      newRequire(entry[i]);
82    } catch (e) {
83      // Save first error but execute all entries
84      if (!error) {
85        error = e;
86      }
87    }
88  }
89
90  if (entry.length) {
91    // Expose entry point to Node, AMD or browser globals
92    // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js
93    var mainExports = newRequire(entry[entry.length - 1]);
94
95    // CommonJS
96    if (typeof exports === "object" && typeof module !== "undefined") {
97      module.exports = mainExports;
98
99    // RequireJS
100    } else if (typeof define === "function" && define.amd) {
101     define(function () {
102       return mainExports;
103     });
104
105    // <script>
106    } else if (globalName) {
107      this[globalName] = mainExports;
108    }
109  }
110
111  // Override the current require with this new one
112  parcelRequire = newRequire;
113
114  if (error) {
115    // throw error from earlier, _after updating parcelRequire_
116    throw error;
117  }
118
119  return newRequire;
120})({"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/src/builtins/bundle-url.js":[function(require,module,exports) {
121var bundleURL = null;
122
123function getBundleURLCached() {
124  if (!bundleURL) {
125    bundleURL = getBundleURL();
126  }
127
128  return bundleURL;
129}
130
131function getBundleURL() {
132  // Attempt to find the URL of the current script and use that as the base URL
133  try {
134    throw new Error();
135  } catch (err) {
136    var matches = ('' + err.stack).match(/(https?|file|ftp|chrome-extension|moz-extension):\/\/[^)\n]+/g);
137
138    if (matches) {
139      return getBaseURL(matches[0]);
140    }
141  }
142
143  return '/';
144}
145
146function getBaseURL(url) {
147  return ('' + url).replace(/^((?:https?|file|ftp|chrome-extension|moz-extension):\/\/.+)\/[^/]+$/, '$1') + '/';
148}
149
150exports.getBundleURL = getBundleURLCached;
151exports.getBaseURL = getBaseURL;
152},{}
152],"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/src/builtins/css-loader.js":[function(require,module,exports) {
153var bundle = require('./bundle-url');
154
155function updateLink(link) {
156  var newLink = link.cloneNode();
157
158  newLink.onload = function () {
159    link.remove();
160  };
161
162  newLink.href = link.href.split('?')[0] + '?' + Date.now();
163  link.parentNode.insertBefore(newLink, link.nextSibling);
164}
165
166var cssTimeout = null;
167
168function reloadCSS() {
169  if (cssTimeout) {
170    return;
171  }
172
173  cssTimeout = setTimeout(function () {
174    var links = document.querySelectorAll('link[rel="stylesheet"]');
175
176    for (var i = 0; i < links.length; i++) {
177      if (bundle.getBaseURL(links[i].href) === bundle.getBundleURL()) {
178        updateLink(links[i]);
179      }
180    }
181
182    cssTimeout = null;
183  }, 50);
184}
185
186module.exports = reloadCSS;
187},{"./bundle-url":"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/src/builtins/bundle-url.js"}],"scss/style.scss":[function(require,module,exports) {
188var reloadCSS = require('_css_loader');
189
190module.hot.dispose(reloadCSS);
191module.hot.accept(reloadCSS);
192},{"_css_loader":"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/src/builtins/css-loader.js"}],"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/node_modules/base64-js/index.js":[function(require,module,exports) {
193'use strict'
194
195exports.byteLength = byteLength
196exports.toByteArray = toByteArray
197exports.fromByteArray = fromByteArray
198
199var lookup = []
200var revLookup = []
201var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
202
203var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
204for (var i = 0, len = code.length; i < len; ++i) {
205  lookup[i] = code[i]
206  revLookup[code.charCodeAt(i)] = i
207}
208
209// Support decoding URL-safe base64 strings, as Node.js does.
210// See: https://en.wikipedia.org/wiki/Base64#URL_applications
211revLookup['-'.charCodeAt(0)] = 62
212revLookup['_'.charCodeAt(0)] = 63
213
214function getLens (b64) {
215  var len = b64.length
216
217  if (len % 4 > 0) {
218    throw new Error('Invalid string. Length must be a multiple of 4')
219  }
220
221  // Trim off extra bytes after placeholder bytes are found
222  // See: https://github.com/beatgammit/base64-js/issues/42
223  var validLen = b64.indexOf('=')
224  if (validLen === -1) validLen = len
225
226  var placeHoldersLen = validLen === len
227    ? 0
228    : 4 - (validLen % 4)
229
230  return [validLen, placeHoldersLen]
231}
232
233// base64 is 4/3 + up to two characters of the original data
234function byteLength (b64) {
235  var lens = getLens(b64)
236  var validLen = lens[0]
237  var placeHoldersLen = lens[1]
238  return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
239}
240
241function _byteLength (b64, validLen, placeHoldersLen) {
242  return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
243}
244
245function toByteArray (b64) {
246  var tmp
247  var lens = getLens(b64)
248  var validLen = lens[0]
249  var placeHoldersLen = lens[1]
250
251  var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
252
253  var curByte = 0
254
255  // if there are placeholders, only get up to the last complete 4 chars
256  var len = placeHoldersLen > 0
257    ? validLen - 4
258    : validLen
259
260  for (var i = 0; i < len; i += 4) {
261    tmp =
262      (revLookup[b64.charCodeAt(i)] << 18) |
263      (revLookup[b64.charCodeAt(i + 1)] << 12) |
264      (revLookup[b64.charCodeAt(i + 2)] << 6) |
265      revLookup[b64.charCodeAt(i + 3)]
266    arr[curByte++] = (tmp >> 16) & 0xFF
267    arr[curByte++] = (tmp >> 8) & 0xFF
268    arr[curByte++] = tmp & 0xFF
269  }
270
271  if (placeHoldersLen === 2) {
272    tmp =
273      (revLookup[b64.charCodeAt(i)] << 2) |
274      (revLookup[b64.charCodeAt(i + 1)] >> 4)
275    arr[curByte++] = tmp & 0xFF
276  }
277
278  if (placeHoldersLen === 1) {
279    tmp =
280      (revLookup[b64.charCodeAt(i)] << 10) |
281      (revLookup[b64.charCodeAt(i + 1)] << 4) |
282      (revLookup[b64.charCodeAt(i + 2)] >> 2)
283    arr[curByte++] = (tmp >> 8) & 0xFF
284    arr[curByte++] = tmp & 0xFF
285  }
286
287  return arr
288}
289
290function tripletToBase64 (num) {
291  return lookup[num >> 18 & 0x3F] +
292    lookup[num >> 12 & 0x3F] +
293    lookup[num >> 6 & 0x3F] +
294    lookup[num & 0x3F]
295}
296
297function encodeChunk (uint8, start, end) {
298  var tmp
299  var output = []
300  for (var i = start; i < end; i += 3) {
301    tmp =
302      ((uint8[i] << 16) & 0xFF0000) +
303      ((uint8[i + 1] << 8) & 0xFF00) +
304      (uint8[i + 2] & 0xFF)
305    output.push(tripletToBase64(tmp))
306  }
307  return output.join('')
308}
309
310function fromByteArray (uint8) {
311  var tmp
312  var len = uint8.length
313  var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
314  var parts = []
315  var maxChunkLength = 16383 // must be multiple of 3
316
317  // go through the array every three bytes, we'll deal with trailing stuff later
318  for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
319    parts.push(encodeChunk(
320      uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)
321    ))
322  }
323
324  // pad the end with zeros, but make sure to not forget the extra bytes
325  if (extraBytes === 1) {
326    tmp = uint8[len - 1]
327    parts.push(
328      lookup[tmp >> 2] +
329      lookup[(tmp << 4) & 0x3F] +
330      '=='
331    )
332  } else if (extraBytes === 2) {
333    tmp = (uint8[len - 2] << 8) + uint8[len - 1]
334    parts.push(
335      lookup[tmp >> 10] +
336      lookup[(tmp >> 4) & 0x3F] +
337      lookup[(tmp << 2) & 0x3F] +
338      '='
339    )
340  }
341
342  return parts.join('')
343}
344
345},{}
vendor: 2,928 bytes, lines 345-453
345],"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/node_modules/ieee754/index.js":[function(require,module,exports) {
346exports.read = function (buffer, offset, isLE, mLen, nBytes) {
347  var e, m
348  var eLen = (nBytes * 8) - mLen - 1
349  var eMax = (1 << eLen) - 1
350  var eBias = eMax >> 1
351  var nBits = -7
352  var i = isLE ? (nBytes - 1) : 0
353  var d = isLE ? -1 : 1
354  var s = buffer[offset + i]
355
356  i += d
357
358  e = s & ((1 << (-nBits)) - 1)
359  s >>= (-nBits)
360  nBits += eLen
361  for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}
362
363  m = e & ((1 << (-nBits)) - 1)
364  e >>= (-nBits)
365  nBits += mLen
366  for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}
367
368  if (e === 0) {
369    e = 1 - eBias
370  } else if (e === eMax) {
371    return m ? NaN : ((s ? -1 : 1) * Infinity)
372  } else {
373    m = m + Math.pow(2, mLen)
374    e = e - eBias
375  }
376  return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
377}
378
379exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
380  var e, m, c
381  var eLen = (nBytes * 8) - mLen - 1
382  var eMax = (1 << eLen) - 1
383  var eBias = eMax >> 1
384  var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
385  var i = isLE ? 0 : (nBytes - 1)
386  var d = isLE ? 1 : -1
387  var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
388
389  value = Math.abs(value)
390
391  if (isNaN(value) || value === Infinity) {
392    m = isNaN(value) ? 1 : 0
393    e = eMax
394  } else {
395    e = Math.floor(Math.log(value) / Math.LN2)
396    if (value * (c = Math.pow(2, -e)) < 1) {
397      e--
398      c *= 2
399    }
400    if (e + eBias >= 1) {
401      value += rt / c
402    } else {
403      value += rt * Math.pow(2, 1 - eBias)
404    }
405    if (value * c >= 2) {
406      e++
407      c /= 2
408    }
409
410    if (e + eBias >= eMax) {
411      m = 0
412      e = eMax
413    } else if (e + eBias >= 1) {
414      m = ((value * c) - 1) * Math.pow(2, mLen)
415      e = e + eBias
416    } else {
417      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
418      e = 0
419    }
420  }
421
422  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
423
424  e = (e << mLen) | m
425  eLen += mLen
426  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
427
428  buffer[offset + i - d] |= s * 128
429}
430
431},{}],"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/node_modules/isarray/index.js":[function(require,module,exports) {
432var toString = {}.toString;
433
434module.exports = Array.isArray || function (arr) {
435  return toString.call(arr) == '[object Array]';
436};
437
438},{}],"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/node_modules/buffer/index.js":[function(require,module,exports) {
439
440var global = arguments[3];
441/*!
442 * The buffer module from node.js, for the browser.
443 *
444 * @author   Feross Aboukhadijeh <[email protected]> <http://feross.org>
445 * @license  MIT
446 */
447/* eslint-disable no-proto */
448
449'use strict'
450
451var base64 = require('base64-js')
452var ieee754 = require('ieee754')
453var isArray = require('isarray'
vendor: 48,315 bytes, lines 453-2230
453)
454
455exports.Buffer = Buffer
456exports.SlowBuffer = SlowBuffer
457exports.INSPECT_MAX_BYTES = 50
458
459/**
460 * If `Buffer.TYPED_ARRAY_SUPPORT`:
461 *   === true    Use Uint8Array implementation (fastest)
462 *   === false   Use Object implementation (most compatible, even IE6)
463 *
464 * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
465 * Opera 11.6+, iOS 4.2+.
466 *
467 * Due to various browser bugs, sometimes the Object implementation will be used even
468 * when the browser supports typed arrays.
469 *
470 * Note:
471 *
472 *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
473 *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
474 *
475 *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
476 *
477 *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
478 *     incorrect length in some situations.
479
480 * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
481 * get the Object implementation, which is slower but behaves correctly.
482 */
483Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
484  ? global.TYPED_ARRAY_SUPPORT
485  : typedArraySupport()
486
487/*
488 * Export kMaxLength after typed array support is determined.
489 */
490exports.kMaxLength = kMaxLength()
491
492function typedArraySupport () {
493  try {
494    var arr = new Uint8Array(1)
495    arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}
496    return arr.foo() === 42 && // typed array instances can be augmented
497        typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
498        arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
499  } catch (e) {
500    return false
501  }
502}
503
504function kMaxLength () {
505  return Buffer.TYPED_ARRAY_SUPPORT
506    ? 0x7fffffff
507    : 0x3fffffff
508}
509
510function createBuffer (that, length) {
511  if (kMaxLength() < length) {
512    throw new RangeError('Invalid typed array length')
513  }
514  if (Buffer.TYPED_ARRAY_SUPPORT) {
515    // Return an augmented `Uint8Array` instance, for best performance
516    that = new Uint8Array(length)
517    that.__proto__ = Buffer.prototype
518  } else {
519    // Fallback: Return an object instance of the Buffer class
520    if (that === null) {
521      that = new Buffer(length)
522    }
523    that.length = length
524  }
525
526  return that
527}
528
529/**
530 * The Buffer constructor returns instances of `Uint8Array` that have their
531 * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
532 * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
533 * and the `Uint8Array` methods. Square bracket notation works as expected -- it
534 * returns a single octet.
535 *
536 * The `Uint8Array` prototype remains unmodified.
537 */
538
539function Buffer (arg, encodingOrOffset, length) {
540  if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {
541    return new Buffer(arg, encodingOrOffset, length)
542  }
543
544  // Common case.
545  if (typeof arg === 'number') {
546    if (typeof encodingOrOffset === 'string') {
547      throw new Error(
548        'If encoding is specified then the first argument must be a string'
549      )
550    }
551    return allocUnsafe(this, arg)
552  }
553  return from(this, arg, encodingOrOffset, length)
554}
555
556Buffer.poolSize = 8192 // not used by this implementation
557
558// TODO: Legacy, not needed anymore. Remove in next major version.
559Buffer._augment = function (arr) {
560  arr.__proto__ = Buffer.prototype
561  return arr
562}
563
564function from (that, value, encodingOrOffset, length) {
565  if (typeof value === 'number') {
566    throw new TypeError('"value" argument must not be a number')
567  }
568
569  if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
570    return fromArrayBuffer(that, value, encodingOrOffset, length)
571  }
572
573  if (typeof value === 'string') {
574    return fromString(that, value, encodingOrOffset)
575  }
576
577  return fromObject(that, value)
578}
579
580/**
581 * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
582 * if value is a number.
583 * Buffer.from(str[, encoding])
584 * Buffer.from(array)
585 * Buffer.from(buffer)
586 * Buffer.from(arrayBuffer[, byteOffset[, length]])
587 **/
588Buffer.from = function (value, encodingOrOffset, length) {
589  return from(null, value, encodingOrOffset, length)
590}
591
592if (Buffer.TYPED_ARRAY_SUPPORT) {
593  Buffer.prototype.__proto__ = Uint8Array.prototype
594  Buffer.__proto__ = Uint8Array
595  if (typeof Symbol !== 'undefined' && Symbol.species &&
596      Buffer[Symbol.species] === Buffer) {
597    // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
598    Object.defineProperty(Buffer, Symbol.species, {
599      value: null,
600      configurable: true
601    })
602  }
603}
604
605function assertSize (size) {
606  if (typeof size !== 'number') {
607    throw new TypeError('"size" argument must be a number')
608  } else if (size < 0) {
609    throw new RangeError('"size" argument must not be negative')
610  }
611}
612
613function alloc (that, size, fill, encoding) {
614  assertSize(size)
615  if (size <= 0) {
616    return createBuffer(that, size)
617  }
618  if (fill !== undefined) {
619    // Only pay attention to encoding if it's a string. This
620    // prevents accidentally sending in a number that would
621    // be interpretted as a start offset.
622    return typeof encoding === 'string'
623      ? createBuffer(that, size).fill(fill, encoding)
624      : createBuffer(that, size).fill(fill)
625  }
626  return createBuffer(that, size)
627}
628
629/**
630 * Creates a new filled Buffer instance.
631 * alloc(size[, fill[, encoding]])
632 **/
633Buffer.alloc = function (size, fill, encoding) {
634  return alloc(null, size, fill, encoding)
635}
636
637function allocUnsafe (that, size) {
638  assertSize(size)
639  that = createBuffer(that, size < 0 ? 0 : checked(size) | 0)
640  if (!Buffer.TYPED_ARRAY_SUPPORT) {
641    for (var i = 0; i < size; ++i) {
642      that[i] = 0
643    }
644  }
645  return that
646}
647
648/**
649 * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
650 * */
651Buffer.allocUnsafe = function (size) {
652  return allocUnsafe(null, size)
653}
654/**
655 * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
656 */
657Buffer.allocUnsafeSlow = function (size) {
658  return allocUnsafe(null, size)
659}
660
661function fromString (that, string, encoding) {
662  if (typeof encoding !== 'string' || encoding === '') {
663    encoding = 'utf8'
664  }
665
666  if (!Buffer.isEncoding(encoding)) {
667    throw new TypeError('"encoding" must be a valid string encoding')
668  }
669
670  var length = byteLength(string, encoding) | 0
671  that = createBuffer(that, length)
672
673  var actual = that.write(string, encoding)
674
675  if (actual !== length) {
676    // Writing a hex string, for example, that contains invalid characters will
677    // cause everything after the first invalid character to be ignored. (e.g.
678    // 'abxxcd' will be treated as 'ab')
679    that = that.slice(0, actual)
680  }
681
682  return that
683}
684
685function fromArrayLike (that, array) {
686  var length = array.length < 0 ? 0 : checked(array.length) | 0
687  that = createBuffer(that, length)
688  for (var i = 0; i < length; i += 1) {
689    that[i] = array[i] & 255
690  }
691  return that
692}
693
694function fromArrayBuffer (that, array, byteOffset, length) {
695  array.byteLength // this throws if `array` is not a valid ArrayBuffer
696
697  if (byteOffset < 0 || array.byteLength < byteOffset) {
698    throw new RangeError('\'offset\' is out of bounds')
699  }
700
701  if (array.byteLength < byteOffset + (length || 0)) {
702    throw new RangeError('\'length\' is out of bounds')
703  }
704
705  if (byteOffset === undefined && length === undefined) {
706    array = new Uint8Array(array)
707  } else if (length === undefined) {
708    array = new Uint8Array(array, byteOffset)
709  } else {
710    array = new Uint8Array(array, byteOffset, length)
711  }
712
713  if (Buffer.TYPED_ARRAY_SUPPORT) {
714    // Return an augmented `Uint8Array` instance, for best performance
715    that = array
716    that.__proto__ = Buffer.prototype
717  } else {
718    // Fallback: Return an object instance of the Buffer class
719    that = fromArrayLike(that, array)
720  }
721  return that
722}
723
724function fromObject (that, obj) {
725  if (Buffer.isBuffer(obj)) {
726    var len = checked(obj.length) | 0
727    that = createBuffer(that, len)
728
729    if (that.length === 0) {
730      return that
731    }
732
733    obj.copy(that, 0, 0, len)
734    return that
735  }
736
737  if (obj) {
738    if ((typeof ArrayBuffer !== 'undefined' &&
739        obj.buffer instanceof ArrayBuffer) || 'length' in obj) {
740      if (typeof obj.length !== 'number' || isnan(obj.length)) {
741        return createBuffer(that, 0)
742      }
743      return fromArrayLike(that, obj)
744    }
745
746    if (obj.type === 'Buffer' && isArray(obj.data)) {
747      return fromArrayLike(that, obj.data)
748    }
749  }
750
751  throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
752}
753
754function checked (length) {
755  // Note: cannot use `length < kMaxLength()` here because that fails when
756  // length is NaN (which is otherwise coerced to zero.)
757  if (length >= kMaxLength()) {
758    throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
759                         'size: 0x' + kMaxLength().toString(16) + ' bytes')
760  }
761  return length | 0
762}
763
764function SlowBuffer (length) {
765  if (+length != length) { // eslint-disable-line eqeqeq
766    length = 0
767  }
768  return Buffer.alloc(+length)
769}
770
771Buffer.isBuffer = function isBuffer (b) {
772  return !!(b != null && b._isBuffer)
773}
774
775Buffer.compare = function compare (a, b) {
776  if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
777    throw new TypeError('Arguments must be Buffers')
778  }
779
780  if (a === b) return 0
781
782  var x = a.length
783  var y = b.length
784
785  for (var i = 0, len = Math.min(x, y); i < len; ++i) {
786    if (a[i] !== b[i]) {
787      x = a[i]
788      y = b[i]
789      break
790    }
791  }
792
793  if (x < y) return -1
794  if (y < x) return 1
795  return 0
796}
797
798Buffer.isEncoding = function isEncoding (encoding) {
799  switch (String(encoding).toLowerCase()) {
800    case 'hex':
801    case 'utf8':
802    case 'utf-8':
803    case 'ascii':
804    case 'latin1':
805    case 'binary':
806    case 'base64':
807    case 'ucs2':
808    case 'ucs-2':
809    case 'utf16le':
810    case 'utf-16le':
811      return true
812    default:
813      return false
814  }
815}
816
817Buffer.concat = function concat (list, length) {
818  if (!isArray(list)) {
819    throw new TypeError('"list" argument must be an Array of Buffers')
820  }
821
822  if (list.length === 0) {
823    return Buffer.alloc(0)
824  }
825
826  var i
827  if (length === undefined) {
828    length = 0
829    for (i = 0; i < list.length; ++i) {
830      length += list[i].length
831    }
832  }
833
834  var buffer = Buffer.allocUnsafe(length)
835  var pos = 0
836  for (i = 0; i < list.length; ++i) {
837    var buf = list[i]
838    if (!Buffer.isBuffer(buf)) {
839      throw new TypeError('"list" argument must be an Array of Buffers')
840    }
841    buf.copy(buffer, pos)
842    pos += buf.length
843  }
844  return buffer
845}
846
847function byteLength (string, encoding) {
848  if (Buffer.isBuffer(string)) {
849    return string.length
850  }
851  if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' &&
852      (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) {
853    return string.byteLength
854  }
855  if (typeof string !== 'string') {
856    string = '' + string
857  }
858
859  var len = string.length
860  if (len === 0) return 0
861
862  // Use a for loop to avoid recursion
863  var loweredCase = false
864  for (;;) {
865    switch (encoding) {
866      case 'ascii':
867      case 'latin1':
868      case 'binary':
869        return len
870      case 'utf8':
871      case 'utf-8':
872      case undefined:
873        return utf8ToBytes(string).length
874      case 'ucs2':
875      case 'ucs-2':
876      case 'utf16le':
877      case 'utf-16le':
878        return len * 2
879      case 'hex':
880        return len >>> 1
881      case 'base64':
882        return base64ToBytes(string).length
883      default:
884        if (loweredCase) return utf8ToBytes(string).length // assume utf8
885        encoding = ('' + encoding).toLowerCase()
886        loweredCase = true
887    }
888  }
889}
890Buffer.byteLength = byteLength
891
892function slowToString (encoding, start, end) {
893  var loweredCase = false
894
895  // No need to verify that "this.length <= MAX_UINT32" since it's a read-only
896  // property of a typed array.
897
898  // This behaves neither like String nor Uint8Array in that we set start/end
899  // to their upper/lower bounds if the value passed is out of range.
900  // undefined is handled specially as per ECMA-262 6th Edition,
901  // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
902  if (start === undefined || start < 0) {
903    start = 0
904  }
905  // Return early if start > this.length. Done here to prevent potential uint32
906  // coercion fail below.
907  if (start > this.length) {
908    return ''
909  }
910
911  if (end === undefined || end > this.length) {
912    end = this.length
913  }
914
915  if (end <= 0) {
916    return ''
917  }
918
919  // Force coersion to uint32. This will also coerce falsey/NaN values to 0.
920  end >>>= 0
921  start >>>= 0
922
923  if (end <= start) {
924    return ''
925  }
926
927  if (!encoding) encoding = 'utf8'
928
929  while (true) {
930    switch (encoding) {
931      case 'hex':
932        return hexSlice(this, start, end)
933
934      case 'utf8':
935      case 'utf-8':
936        return utf8Slice(this, start, end)
937
938      case 'ascii':
939        return asciiSlice(this, start, end)
940
941      case 'latin1':
942      case 'binary':
943        return latin1Slice(this, start, end)
944
945      case 'base64':
946        return base64Slice(this, start, end)
947
948      case 'ucs2':
949      case 'ucs-2':
950      case 'utf16le':
951      case 'utf-16le':
952        return utf16leSlice(this, start, end)
953
954      default:
955        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
956        encoding = (encoding + '').toLowerCase()
957        loweredCase = true
958    }
959  }
960}
961
962// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect
963// Buffer instances.
964Buffer.prototype._isBuffer = true
965
966function swap (b, n, m) {
967  var i = b[n]
968  b[n] = b[m]
969  b[m] = i
970}
971
972Buffer.prototype.swap16 = function swap16 () {
973  var len = this.length
974  if (len % 2 !== 0) {
975    throw new RangeError('Buffer size must be a multiple of 16-bits')
976  }
977  for (var i = 0; i < len; i += 2) {
978    swap(this, i, i + 1)
979  }
980  return this
981}
982
983Buffer.prototype.swap32 = function swap32 () {
984  var len = this.length
985  if (len % 4 !== 0) {
986    throw new RangeError('Buffer size must be a multiple of 32-bits')
987  }
988  for (var i = 0; i < len; i += 4) {
989    swap(this, i, i + 3)
990    swap(this, i + 1, i + 2)
991  }
992  return this
993}
994
995Buffer.prototype.swap64 = function swap64 () {
996  var len = this.length
997  if (len % 8 !== 0) {
998    throw new RangeError('Buffer size must be a multiple of 64-bits')
999  }
1000  for (var i = 0; i < len; i += 8) {
1001    swap(this, i, i + 7)
1002    swap(this, i + 1, i + 6)
1003    swap(this, i + 2, i + 5)
1004    swap(this, i + 3, i + 4)
1005  }
1006  return this
1007}
1008
1009Buffer.prototype.toString = function toString () {
1010  var length = this.length | 0
1011  if (length === 0) return ''
1012  if (arguments.length === 0) return utf8Slice(this, 0, length)
1013  return slowToString.apply(this, arguments)
1014}
1015
1016Buffer.prototype.equals = function equals (b) {
1017  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
1018  if (this === b) return true
1019  return Buffer.compare(this, b) === 0
1020}
1021
1022Buffer.prototype.inspect = function inspect () {
1023  var str = ''
1024  var max = exports.INSPECT_MAX_BYTES
1025  if (this.length > 0) {
1026    str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
1027    if (this.length > max) str += ' ... '
1028  }
1029  return '<Buffer ' + str + '>'
1030}
1031
1032Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
1033  if (!Buffer.isBuffer(target)) {
1034    throw new TypeError('Argument must be a Buffer')
1035  }
1036
1037  if (start === undefined) {
1038    start = 0
1039  }
1040  if (end === undefined) {
1041    end = target ? target.length : 0
1042  }
1043  if (thisStart === undefined) {
1044    thisStart = 0
1045  }
1046  if (thisEnd === undefined) {
1047    thisEnd = this.length
1048  }
1049
1050  if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
1051    throw new RangeError('out of range index')
1052  }
1053
1054  if (thisStart >= thisEnd && start >= end) {
1055    return 0
1056  }
1057  if (thisStart >= thisEnd) {
1058    return -1
1059  }
1060  if (start >= end) {
1061    return 1
1062  }
1063
1064  start >>>= 0
1065  end >>>= 0
1066  thisStart >>>= 0
1067  thisEnd >>>= 0
1068
1069  if (this === target) return 0
1070
1071  var x = thisEnd - thisStart
1072  var y = end - start
1073  var len = Math.min(x, y)
1074
1075  var thisCopy = this.slice(thisStart, thisEnd)
1076  var targetCopy = target.slice(start, end)
1077
1078  for (var i = 0; i < len; ++i) {
1079    if (thisCopy[i] !== targetCopy[i]) {
1080      x = thisCopy[i]
1081      y = targetCopy[i]
1082      break
1083    }
1084  }
1085
1086  if (x < y) return -1
1087  if (y < x) return 1
1088  return 0
1089}
1090
1091// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
1092// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
1093//
1094// Arguments:
1095// - buffer - a Buffer to search
1096// - val - a string, Buffer, or number
1097// - byteOffset - an index into `buffer`; will be clamped to an int32
1098// - encoding - an optional encoding, relevant is val is a string
1099// - dir - true for indexOf, false for lastIndexOf
1100function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
1101  // Empty buffer means no match
1102  if (buffer.length === 0) return -1
1103
1104  // Normalize byteOffset
1105  if (typeof byteOffset === 'string') {
1106    encoding = byteOffset
1107    byteOffset = 0
1108  } else if (byteOffset > 0x7fffffff) {
1109    byteOffset = 0x7fffffff
1110  } else if (byteOffset < -0x80000000) {
1111    byteOffset = -0x80000000
1112  }
1113  byteOffset = +byteOffset  // Coerce to Number.
1114  if (isNaN(byteOffset)) {
1115    // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
1116    byteOffset = dir ? 0 : (buffer.length - 1)
1117  }
1118
1119  // Normalize byteOffset: negative offsets start from the end of the buffer
1120  if (byteOffset < 0) byteOffset = buffer.length + byteOffset
1121  if (byteOffset >= buffer.length) {
1122    if (dir) return -1
1123    else byteOffset = buffer.length - 1
1124  } else if (byteOffset < 0) {
1125    if (dir) byteOffset = 0
1126    else return -1
1127  }
1128
1129  // Normalize val
1130  if (typeof val === 'string') {
1131    val = Buffer.from(val, encoding)
1132  }
1133
1134  // Finally, search either indexOf (if dir is true) or lastIndexOf
1135  if (Buffer.isBuffer(val)) {
1136    // Special case: looking for empty string/buffer always fails
1137    if (val.length === 0) {
1138      return -1
1139    }
1140    return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
1141  } else if (typeof val === 'number') {
1142    val = val & 0xFF // Search for a byte value [0-255]
1143    if (Buffer.TYPED_ARRAY_SUPPORT &&
1144        typeof Uint8Array.prototype.indexOf === 'function') {
1145      if (dir) {
1146        return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
1147      } else {
1148        return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
1149      }
1150    }
1151    return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)
1152  }
1153
1154  throw new TypeError('val must be string, number or Buffer')
1155}
1156
1157function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
1158  var indexSize = 1
1159  var arrLength = arr.length
1160  var valLength = val.length
1161
1162  if (encoding !== undefined) {
1163    encoding = String(encoding).toLowerCase()
1164    if (encoding === 'ucs2' || encoding === 'ucs-2' ||
1165        encoding === 'utf16le' || encoding === 'utf-16le') {
1166      if (arr.length < 2 || val.length < 2) {
1167        return -1
1168      }
1169      indexSize = 2
1170      arrLength /= 2
1171      valLength /= 2
1172      byteOffset /= 2
1173    }
1174  }
1175
1176  function read (buf, i) {
1177    if (indexSize === 1) {
1178      return buf[i]
1179    } else {
1180      return buf.readUInt16BE(i * indexSize)
1181    }
1182  }
1183
1184  var i
1185  if (dir) {
1186    var foundIndex = -1
1187    for (i = byteOffset; i < arrLength; i++) {
1188      if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
1189        if (foundIndex === -1) foundIndex = i
1190        if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
1191      } else {
1192        if (foundIndex !== -1) i -= i - foundIndex
1193        foundIndex = -1
1194      }
1195    }
1196  } else {
1197    if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
1198    for (i = byteOffset; i >= 0; i--) {
1199      var found = true
1200      for (var j = 0; j < valLength; j++) {
1201        if (read(arr, i + j) !== read(val, j)) {
1202          found = false
1203          break
1204        }
1205      }
1206      if (found) return i
1207    }
1208  }
1209
1210  return -1
1211}
1212
1213Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
1214  return this.indexOf(val, byteOffset, encoding) !== -1
1215}
1216
1217Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
1218  return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
1219}
1220
1221Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
1222  return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
1223}
1224
1225function hexWrite (buf, string, offset, length) {
1226  offset = Number(offset) || 0
1227  var remaining = buf.length - offset
1228  if (!length) {
1229    length = remaining
1230  } else {
1231    length = Number(length)
1232    if (length > remaining) {
1233      length = remaining
1234    }
1235  }
1236
1237  // must be an even number of digits
1238  var strLen = string.length
1239  if (strLen % 2 !== 0) throw new TypeError('Invalid hex string')
1240
1241  if (length > strLen / 2) {
1242    length = strLen / 2
1243  }
1244  for (var i = 0; i < length; ++i) {
1245    var parsed = parseInt(string.substr(i * 2, 2), 16)
1246    if (isNaN(parsed)) return i
1247    buf[offset + i] = parsed
1248  }
1249  return i
1250}
1251
1252function utf8Write (buf, string, offset, length) {
1253  return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
1254}
1255
1256function asciiWrite (buf, string, offset, length) {
1257  return blitBuffer(asciiToBytes(string), buf, offset, length)
1258}
1259
1260function latin1Write (buf, string, offset, length) {
1261  return asciiWrite(buf, string, offset, length)
1262}
1263
1264function base64Write (buf, string, offset, length) {
1265  return blitBuffer(base64ToBytes(string), buf, offset, length)
1266}
1267
1268function ucs2Write (buf, string, offset, length) {
1269  return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
1270}
1271
1272Buffer.prototype.write = function write (string, offset, length, encoding) {
1273  // Buffer#write(string)
1274  if (offset === undefined) {
1275    encoding = 'utf8'
1276    length = this.length
1277    offset = 0
1278  // Buffer#write(string, encoding)
1279  } else if (length === undefined && typeof offset === 'string') {
1280    encoding = offset
1281    length = this.length
1282    offset = 0
1283  // Buffer#write(string, offset[, length][, encoding])
1284  } else if (isFinite(offset)) {
1285    offset = offset | 0
1286    if (isFinite(length)) {
1287      length = length | 0
1288      if (encoding === undefined) encoding = 'utf8'
1289    } else {
1290      encoding = length
1291      length = undefined
1292    }
1293  // legacy write(string, encoding, offset, length) - remove in v0.13
1294  } else {
1295    throw new Error(
1296      'Buffer.write(string, encoding, offset[, length]) is no longer supported'
1297    )
1298  }
1299
1300  var remaining = this.length - offset
1301  if (length === undefined || length > remaining) length = remaining
1302
1303  if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
1304    throw new RangeError('Attempt to write outside buffer bounds')
1305  }
1306
1307  if (!encoding) encoding = 'utf8'
1308
1309  var loweredCase = false
1310  for (;;) {
1311    switch (encoding) {
1312      case 'hex':
1313        return hexWrite(this, string, offset, length)
1314
1315      case 'utf8':
1316      case 'utf-8':
1317        return utf8Write(this, string, offset, length)
1318
1319      case 'ascii':
1320        return asciiWrite(this, string, offset, length)
1321
1322      case 'latin1':
1323      case 'binary':
1324        return latin1Write(this, string, offset, length)
1325
1326      case 'base64':
1327        // Warning: maxLength not taken into account in base64Write
1328        return base64Write(this, string, offset, length)
1329
1330      case 'ucs2':
1331      case 'ucs-2':
1332      case 'utf16le':
1333      case 'utf-16le':
1334        return ucs2Write(this, string, offset, length)
1335
1336      default:
1337        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
1338        encoding = ('' + encoding).toLowerCase()
1339        loweredCase = true
1340    }
1341  }
1342}
1343
1344Buffer.prototype.toJSON = function toJSON () {
1345  return {
1346    type: 'Buffer',
1347    data: Array.prototype.slice.call(this._arr || this, 0)
1348  }
1349}
1350
1351function base64Slice (buf, start, end) {
1352  if (start === 0 && end === buf.length) {
1353    return base64.fromByteArray(buf)
1354  } else {
1355    return base64.fromByteArray(buf.slice(start, end))
1356  }
1357}
1358
1359function utf8Slice (buf, start, end) {
1360  end = Math.min(buf.length, end)
1361  var res = []
1362
1363  var i = start
1364  while (i < end) {
1365    var firstByte = buf[i]
1366    var codePoint = null
1367    var bytesPerSequence = (firstByte > 0xEF) ? 4
1368      : (firstByte > 0xDF) ? 3
1369      : (firstByte > 0xBF) ? 2
1370      : 1
1371
1372    if (i + bytesPerSequence <= end) {
1373      var secondByte, thirdByte, fourthByte, tempCodePoint
1374
1375      switch (bytesPerSequence) {
1376        case 1:
1377          if (firstByte < 0x80) {
1378            codePoint = firstByte
1379          }
1380          break
1381        case 2:
1382          secondByte = buf[i + 1]
1383          if ((secondByte & 0xC0) === 0x80) {
1384            tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
1385            if (tempCodePoint > 0x7F) {
1386              codePoint = tempCodePoint
1387            }
1388          }
1389          break
1390        case 3:
1391          secondByte = buf[i + 1]
1392          thirdByte = buf[i + 2]
1393          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
1394            tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
1395            if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
1396              codePoint = tempCodePoint
1397            }
1398          }
1399          break
1400        case 4:
1401          secondByte = buf[i + 1]
1402          thirdByte = buf[i + 2]
1403          fourthByte = buf[i + 3]
1404          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
1405            tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
1406            if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
1407              codePoint = tempCodePoint
1408            }
1409          }
1410      }
1411    }
1412
1413    if (codePoint === null) {
1414      // we did not generate a valid codePoint so insert a
1415      // replacement char (U+FFFD) and advance only 1 byte
1416      codePoint = 0xFFFD
1417      bytesPerSequence = 1
1418    } else if (codePoint > 0xFFFF) {
1419      // encode to utf16 (surrogate pair dance)
1420      codePoint -= 0x10000
1421      res.push(codePoint >>> 10 & 0x3FF | 0xD800)
1422      codePoint = 0xDC00 | codePoint & 0x3FF
1423    }
1424
1425    res.push(codePoint)
1426    i += bytesPerSequence
1427  }
1428
1429  return decodeCodePointsArray(res)
1430}
1431
1432// Based on http://stackoverflow.com/a/22747272/680742, the browser with
1433// the lowest limit is Chrome, with 0x10000 args.
1434// We go 1 magnitude less, for safety
1435var MAX_ARGUMENTS_LENGTH = 0x1000
1436
1437function decodeCodePointsArray (codePoints) {
1438  var len = codePoints.length
1439  if (len <= MAX_ARGUMENTS_LENGTH) {
1440    return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
1441  }
1442
1443  // Decode in chunks to avoid "call stack size exceeded".
1444  var res = ''
1445  var i = 0
1446  while (i < len) {
1447    res += String.fromCharCode.apply(
1448      String,
1449      codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
1450    )
1451  }
1452  return res
1453}
1454
1455function asciiSlice (buf, start, end) {
1456  var ret = ''
1457  end = Math.min(buf.length, end)
1458
1459  for (var i = start; i < end; ++i) {
1460    ret += String.fromCharCode(buf[i] & 0x7F)
1461  }
1462  return ret
1463}
1464
1465function latin1Slice (buf, start, end) {
1466  var ret = ''
1467  end = Math.min(buf.length, end)
1468
1469  for (var i = start; i < end; ++i) {
1470    ret += String.fromCharCode(buf[i])
1471  }
1472  return ret
1473}
1474
1475function hexSlice (buf, start, end) {
1476  var len = buf.length
1477
1478  if (!start || start < 0) start = 0
1479  if (!end || end < 0 || end > len) end = len
1480
1481  var out = ''
1482  for (var i = start; i < end; ++i) {
1483    out += toHex(buf[i])
1484  }
1485  return out
1486}
1487
1488function utf16leSlice (buf, start, end) {
1489  var bytes = buf.slice(start, end)
1490  var res = ''
1491  for (var i = 0; i < bytes.length; i += 2) {
1492    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
1493  }
1494  return res
1495}
1496
1497Buffer.prototype.slice = function slice (start, end) {
1498  var len = this.length
1499  start = ~~start
1500  end = end === undefined ? len : ~~end
1501
1502  if (start < 0) {
1503    start += len
1504    if (start < 0) start = 0
1505  } else if (start > len) {
1506    start = len
1507  }
1508
1509  if (end < 0) {
1510    end += len
1511    if (end < 0) end = 0
1512  } else if (end > len) {
1513    end = len
1514  }
1515
1516  if (end < start) end = start
1517
1518  var newBuf
1519  if (Buffer.TYPED_ARRAY_SUPPORT) {
1520    newBuf = this.subarray(start, end)
1521    newBuf.__proto__ = Buffer.prototype
1522  } else {
1523    var sliceLen = end - start
1524    newBuf = new Buffer(sliceLen, undefined)
1525    for (var i = 0; i < sliceLen; ++i) {
1526      newBuf[i] = this[i + start]
1527    }
1528  }
1529
1530  return newBuf
1531}
1532
1533/*
1534 * Need to make sure that buffer isn't trying to write out of bounds.
1535 */
1536function checkOffset (offset, ext, length) {
1537  if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
1538  if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
1539}
1540
1541Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
1542  offset = offset | 0
1543  byteLength = byteLength | 0
1544  if (!noAssert) checkOffset(offset, byteLength, this.length)
1545
1546  var val = this[offset]
1547  var mul = 1
1548  var i = 0
1549  while (++i < byteLength && (mul *= 0x100)) {
1550    val += this[offset + i] * mul
1551  }
1552
1553  return val
1554}
1555
1556Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
1557  offset = offset | 0
1558  byteLength = byteLength | 0
1559  if (!noAssert) {
1560    checkOffset(offset, byteLength, this.length)
1561  }
1562
1563  var val = this[offset + --byteLength]
1564  var mul = 1
1565  while (byteLength > 0 && (mul *= 0x100)) {
1566    val += this[offset + --byteLength] * mul
1567  }
1568
1569  return val
1570}
1571
1572Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
1573  if (!noAssert) checkOffset(offset, 1, this.length)
1574  return this[offset]
1575}
1576
1577Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
1578  if (!noAssert) checkOffset(offset, 2, this.length)
1579  return this[offset] | (this[offset + 1] << 8)
1580}
1581
1582Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
1583  if (!noAssert) checkOffset(offset, 2, this.length)
1584  return (this[offset] << 8) | this[offset + 1]
1585}
1586
1587Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
1588  if (!noAssert) checkOffset(offset, 4, this.length)
1589
1590  return ((this[offset]) |
1591      (this[offset + 1] << 8) |
1592      (this[offset + 2] << 16)) +
1593      (this[offset + 3] * 0x1000000)
1594}
1595
1596Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
1597  if (!noAssert) checkOffset(offset, 4, this.length)
1598
1599  return (this[offset] * 0x1000000) +
1600    ((this[offset + 1] << 16) |
1601    (this[offset + 2] << 8) |
1602    this[offset + 3])
1603}
1604
1605Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
1606  offset = offset | 0
1607  byteLength = byteLength | 0
1608  if (!noAssert) checkOffset(offset, byteLength, this.length)
1609
1610  var val = this[offset]
1611  var mul = 1
1612  var i = 0
1613  while (++i < byteLength && (mul *= 0x100)) {
1614    val += this[offset + i] * mul
1615  }
1616  mul *= 0x80
1617
1618  if (val >= mul) val -= Math.pow(2, 8 * byteLength)
1619
1620  return val
1621}
1622
1623Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
1624  offset = offset | 0
1625  byteLength = byteLength | 0
1626  if (!noAssert) checkOffset(offset, byteLength, this.length)
1627
1628  var i = byteLength
1629  var mul = 1
1630  var val = this[offset + --i]
1631  while (i > 0 && (mul *= 0x100)) {
1632    val += this[offset + --i] * mul
1633  }
1634  mul *= 0x80
1635
1636  if (val >= mul) val -= Math.pow(2, 8 * byteLength)
1637
1638  return val
1639}
1640
1641Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
1642  if (!noAssert) checkOffset(offset, 1, this.length)
1643  if (!(this[offset] & 0x80)) return (this[offset])
1644  return ((0xff - this[offset] + 1) * -1)
1645}
1646
1647Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
1648  if (!noAssert) checkOffset(offset, 2, this.length)
1649  var val = this[offset] | (this[offset + 1] << 8)
1650  return (val & 0x8000) ? val | 0xFFFF0000 : val
1651}
1652
1653Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
1654  if (!noAssert) checkOffset(offset, 2, this.length)
1655  var val = this[offset + 1] | (this[offset] << 8)
1656  return (val & 0x8000) ? val | 0xFFFF0000 : val
1657}
1658
1659Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
1660  if (!noAssert) checkOffset(offset, 4, this.length)
1661
1662  return (this[offset]) |
1663    (this[offset + 1] << 8) |
1664    (this[offset + 2] << 16) |
1665    (this[offset + 3] << 24)
1666}
1667
1668Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
1669  if (!noAssert) checkOffset(offset, 4, this.length)
1670
1671  return (this[offset] << 24) |
1672    (this[offset + 1] << 16) |
1673    (this[offset + 2] << 8) |
1674    (this[offset + 3])
1675}
1676
1677Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
1678  if (!noAssert) checkOffset(offset, 4, this.length)
1679  return ieee754.read(this, offset, true, 23, 4)
1680}
1681
1682Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
1683  if (!noAssert) checkOffset(offset, 4, this.length)
1684  return ieee754.read(this, offset, false, 23, 4)
1685}
1686
1687Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
1688  if (!noAssert) checkOffset(offset, 8, this.length)
1689  return ieee754.read(this, offset, true, 52, 8)
1690}
1691
1692Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
1693  if (!noAssert) checkOffset(offset, 8, this.length)
1694  return ieee754.read(this, offset, false, 52, 8)
1695}
1696
1697function checkInt (buf, value, offset, ext, max, min) {
1698  if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
1699  if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
1700  if (offset + ext > buf.length) throw new RangeError('Index out of range')
1701}
1702
1703Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
1704  value = +value
1705  offset = offset | 0
1706  byteLength = byteLength | 0
1707  if (!noAssert) {
1708    var maxBytes = Math.pow(2, 8 * byteLength) - 1
1709    checkInt(this, value, offset, byteLength, maxBytes, 0)
1710  }
1711
1712  var mul = 1
1713  var i = 0
1714  this[offset] = value & 0xFF
1715  while (++i < byteLength && (mul *= 0x100)) {
1716    this[offset + i] = (value / mul) & 0xFF
1717  }
1718
1719  return offset + byteLength
1720}
1721
1722Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
1723  value = +value
1724  offset = offset | 0
1725  byteLength = byteLength | 0
1726  if (!noAssert) {
1727    var maxBytes = Math.pow(2, 8 * byteLength) - 1
1728    checkInt(this, value, offset, byteLength, maxBytes, 0)
1729  }
1730
1731  var i = byteLength - 1
1732  var mul = 1
1733  this[offset + i] = value & 0xFF
1734  while (--i >= 0 && (mul *= 0x100)) {
1735    this[offset + i] = (value / mul) & 0xFF
1736  }
1737
1738  return offset + byteLength
1739}
1740
1741Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
1742  value = +value
1743  offset = offset | 0
1744  if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
1745  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
1746  this[offset] = (value & 0xff)
1747  return offset + 1
1748}
1749
1750function objectWriteUInt16 (buf, value, offset, littleEndian) {
1751  if (value < 0) value = 0xffff + value + 1
1752  for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) {
1753    buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
1754      (littleEndian ? i : 1 - i) * 8
1755  }
1756}
1757
1758Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
1759  value = +value
1760  offset = offset | 0
1761  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
1762  if (Buffer.TYPED_ARRAY_SUPPORT) {
1763    this[offset] = (value & 0xff)
1764    this[offset + 1] = (value >>> 8)
1765  } else {
1766    objectWriteUInt16(this, value, offset, true)
1767  }
1768  return offset + 2
1769}
1770
1771Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
1772  value = +value
1773  offset = offset | 0
1774  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
1775  if (Buffer.TYPED_ARRAY_SUPPORT) {
1776    this[offset] = (value >>> 8)
1777    this[offset + 1] = (value & 0xff)
1778  } else {
1779    objectWriteUInt16(this, value, offset, false)
1780  }
1781  return offset + 2
1782}
1783
1784function objectWriteUInt32 (buf, value, offset, littleEndian) {
1785  if (value < 0) value = 0xffffffff + value + 1
1786  for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) {
1787    buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
1788  }
1789}
1790
1791Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
1792  value = +value
1793  offset = offset | 0
1794  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
1795  if (Buffer.TYPED_ARRAY_SUPPORT) {
1796    this[offset + 3] = (value >>> 24)
1797    this[offset + 2] = (value >>> 16)
1798    this[offset + 1] = (value >>> 8)
1799    this[offset] = (value & 0xff)
1800  } else {
1801    objectWriteUInt32(this, value, offset, true)
1802  }
1803  return offset + 4
1804}
1805
1806Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
1807  value = +value
1808  offset = offset | 0
1809  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
1810  if (Buffer.TYPED_ARRAY_SUPPORT) {
1811    this[offset] = (value >>> 24)
1812    this[offset + 1] = (value >>> 16)
1813    this[offset + 2] = (value >>> 8)
1814    this[offset + 3] = (value & 0xff)
1815  } else {
1816    objectWriteUInt32(this, value, offset, false)
1817  }
1818  return offset + 4
1819}
1820
1821Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
1822  value = +value
1823  offset = offset | 0
1824  if (!noAssert) {
1825    var limit = Math.pow(2, 8 * byteLength - 1)
1826
1827    checkInt(this, value, offset, byteLength, limit - 1, -limit)
1828  }
1829
1830  var i = 0
1831  var mul = 1
1832  var sub = 0
1833  this[offset] = value & 0xFF
1834  while (++i < byteLength && (mul *= 0x100)) {
1835    if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
1836      sub = 1
1837    }
1838    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
1839  }
1840
1841  return offset + byteLength
1842}
1843
1844Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
1845  value = +value
1846  offset = offset | 0
1847  if (!noAssert) {
1848    var limit = Math.pow(2, 8 * byteLength - 1)
1849
1850    checkInt(this, value, offset, byteLength, limit - 1, -limit)
1851  }
1852
1853  var i = byteLength - 1
1854  var mul = 1
1855  var sub = 0
1856  this[offset + i] = value & 0xFF
1857  while (--i >= 0 && (mul *= 0x100)) {
1858    if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
1859      sub = 1
1860    }
1861    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
1862  }
1863
1864  return offset + byteLength
1865}
1866
1867Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
1868  value = +value
1869  offset = offset | 0
1870  if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
1871  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
1872  if (value < 0) value = 0xff + value + 1
1873  this[offset] = (value & 0xff)
1874  return offset + 1
1875}
1876
1877Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
1878  value = +value
1879  offset = offset | 0
1880  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
1881  if (Buffer.TYPED_ARRAY_SUPPORT) {
1882    this[offset] = (value & 0xff)
1883    this[offset + 1] = (value >>> 8)
1884  } else {
1885    objectWriteUInt16(this, value, offset, true)
1886  }
1887  return offset + 2
1888}
1889
1890Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
1891  value = +value
1892  offset = offset | 0
1893  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
1894  if (Buffer.TYPED_ARRAY_SUPPORT) {
1895    this[offset] = (value >>> 8)
1896    this[offset + 1] = (value & 0xff)
1897  } else {
1898    objectWriteUInt16(this, value, offset, false)
1899  }
1900  return offset + 2
1901}
1902
1903Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
1904  value = +value
1905  offset = offset | 0
1906  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
1907  if (Buffer.TYPED_ARRAY_SUPPORT) {
1908    this[offset] = (value & 0xff)
1909    this[offset + 1] = (value >>> 8)
1910    this[offset + 2] = (value >>> 16)
1911    this[offset + 3] = (value >>> 24)
1912  } else {
1913    objectWriteUInt32(this, value, offset, true)
1914  }
1915  return offset + 4
1916}
1917
1918Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
1919  value = +value
1920  offset = offset | 0
1921  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
1922  if (value < 0) value = 0xffffffff + value + 1
1923  if (Buffer.TYPED_ARRAY_SUPPORT) {
1924    this[offset] = (value >>> 24)
1925    this[offset + 1] = (value >>> 16)
1926    this[offset + 2] = (value >>> 8)
1927    this[offset + 3] = (value & 0xff)
1928  } else {
1929    objectWriteUInt32(this, value, offset, false)
1930  }
1931  return offset + 4
1932}
1933
1934function checkIEEE754 (buf, value, offset, ext, max, min) {
1935  if (offset + ext > buf.length) throw new RangeError('Index out of range')
1936  if (offset < 0) throw new RangeError('Index out of range')
1937}
1938
1939function writeFloat (buf, value, offset, littleEndian, noAssert) {
1940  if (!noAssert) {
1941    checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
1942  }
1943  ieee754.write(buf, value, offset, littleEndian, 23, 4)
1944  return offset + 4
1945}
1946
1947Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
1948  return writeFloat(this, value, offset, true, noAssert)
1949}
1950
1951Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
1952  return writeFloat(this, value, offset, false, noAssert)
1953}
1954
1955function writeDouble (buf, value, offset, littleEndian, noAssert) {
1956  if (!noAssert) {
1957    checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
1958  }
1959  ieee754.write(buf, value, offset, littleEndian, 52, 8)
1960  return offset + 8
1961}
1962
1963Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
1964  return writeDouble(this, value, offset, true, noAssert)
1965}
1966
1967Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
1968  return writeDouble(this, value, offset, false, noAssert)
1969}
1970
1971// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
1972Buffer.prototype.copy = function copy (target, targetStart, start, end) {
1973  if (!start) start = 0
1974  if (!end && end !== 0) end = this.length
1975  if (targetStart >= target.length) targetStart = target.length
1976  if (!targetStart) targetStart = 0
1977  if (end > 0 && end < start) end = start
1978
1979  // Copy 0 bytes; we're done
1980  if (end === start) return 0
1981  if (target.length === 0 || this.length === 0) return 0
1982
1983  // Fatal error conditions
1984  if (targetStart < 0) {
1985    throw new RangeError('targetStart out of bounds')
1986  }
1987  if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
1988  if (end < 0) throw new RangeError('sourceEnd out of bounds')
1989
1990  // Are we oob?
1991  if (end > this.length) end = this.length
1992  if (target.length - targetStart < end - start) {
1993    end = target.length - targetStart + start
1994  }
1995
1996  var len = end - start
1997  var i
1998
1999  if (this === target && start < targetStart && targetStart < end) {
2000    // descending copy from end
2001    for (i = len - 1; i >= 0; --i) {
2002      target[i + targetStart] = this[i + start]
2003    }
2004  } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
2005    // ascending copy from start
2006    for (i = 0; i < len; ++i) {
2007      target[i + targetStart] = this[i + start]
2008    }
2009  } else {
2010    Uint8Array.prototype.set.call(
2011      target,
2012      this.subarray(start, start + len),
2013      targetStart
2014    )
2015  }
2016
2017  return len
2018}
2019
2020// Usage:
2021//    buffer.fill(number[, offset[, end]])
2022//    buffer.fill(buffer[, offset[, end]])
2023//    buffer.fill(string[, offset[, end]][, encoding])
2024Buffer.prototype.fill = function fill (val, start, end, encoding) {
2025  // Handle string cases:
2026  if (typeof val === 'string') {
2027    if (typeof start === 'string') {
2028      encoding = start
2029      start = 0
2030      end = this.length
2031    } else if (typeof end === 'string') {
2032      encoding = end
2033      end = this.length
2034    }
2035    if (val.length === 1) {
2036      var code = val.charCodeAt(0)
2037      if (code < 256) {
2038        val = code
2039      }
2040    }
2041    if (encoding !== undefined && typeof encoding !== 'string') {
2042      throw new TypeError('encoding must be a string')
2043    }
2044    if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
2045      throw new TypeError('Unknown encoding: ' + encoding)
2046    }
2047  } else if (typeof val === 'number') {
2048    val = val & 255
2049  }
2050
2051  // Invalid ranges are not set to a default, so can range check early.
2052  if (start < 0 || this.length < start || this.length < end) {
2053    throw new RangeError('Out of range index')
2054  }
2055
2056  if (end <= start) {
2057    return this
2058  }
2059
2060  start = start >>> 0
2061  end = end === undefined ? this.length : end >>> 0
2062
2063  if (!val) val = 0
2064
2065  var i
2066  if (typeof val === 'number') {
2067    for (i = start; i < end; ++i) {
2068      this[i] = val
2069    }
2070  } else {
2071    var bytes = Buffer.isBuffer(val)
2072      ? val
2073      : utf8ToBytes(new Buffer(val, encoding).toString())
2074    var len = bytes.length
2075    for (i = 0; i < end - start; ++i) {
2076      this[i + start] = bytes[i % len]
2077    }
2078  }
2079
2080  return this
2081}
2082
2083// HELPER FUNCTIONS
2084// ================
2085
2086var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
2087
2088function base64clean (str) {
2089  // Node strips out invalid characters like \n and \t from the string, base64-js does not
2090  str = stringtrim(str).replace(INVALID_BASE64_RE, '')
2091  // Node converts strings with length < 2 to ''
2092  if (str.length < 2) return ''
2093  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
2094  while (str.length % 4 !== 0) {
2095    str = str + '='
2096  }
2097  return str
2098}
2099
2100function stringtrim (str) {
2101  if (str.trim) return str.trim()
2102  return str.replace(/^\s+|\s+$/g, '')
2103}
2104
2105function toHex (n) {
2106  if (n < 16) return '0' + n.toString(16)
2107  return n.toString(16)
2108}
2109
2110function utf8ToBytes (string, units) {
2111  units = units || Infinity
2112  var codePoint
2113  var length = string.length
2114  var leadSurrogate = null
2115  var bytes = []
2116
2117  for (var i = 0; i < length; ++i) {
2118    codePoint = string.charCodeAt(i)
2119
2120    // is surrogate component
2121    if (codePoint > 0xD7FF && codePoint < 0xE000) {
2122      // last char was a lead
2123      if (!leadSurrogate) {
2124        // no lead yet
2125        if (codePoint > 0xDBFF) {
2126          // unexpected trail
2127          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
2128          continue
2129        } else if (i + 1 === length) {
2130          // unpaired lead
2131          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
2132          continue
2133        }
2134
2135        // valid lead
2136        leadSurrogate = codePoint
2137
2138        continue
2139      }
2140
2141      // 2 leads in a row
2142      if (codePoint < 0xDC00) {
2143        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
2144        leadSurrogate = codePoint
2145        continue
2146      }
2147
2148      // valid surrogate pair
2149      codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
2150    } else if (leadSurrogate) {
2151      // valid bmp char, but last char was a lead
2152      if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
2153    }
2154
2155    leadSurrogate = null
2156
2157    // encode utf8
2158    if (codePoint < 0x80) {
2159      if ((units -= 1) < 0) break
2160      bytes.push(codePoint)
2161    } else if (codePoint < 0x800) {
2162      if ((units -= 2) < 0) break
2163      bytes.push(
2164        codePoint >> 0x6 | 0xC0,
2165        codePoint & 0x3F | 0x80
2166      )
2167    } else if (codePoint < 0x10000) {
2168      if ((units -= 3) < 0) break
2169      bytes.push(
2170        codePoint >> 0xC | 0xE0,
2171        codePoint >> 0x6 & 0x3F | 0x80,
2172        codePoint & 0x3F | 0x80
2173      )
2174    } else if (codePoint < 0x110000) {
2175      if ((units -= 4) < 0) break
2176      bytes.push(
2177        codePoint >> 0x12 | 0xF0,
2178        codePoint >> 0xC & 0x3F | 0x80,
2179        codePoint >> 0x6 & 0x3F | 0x80,
2180        codePoint & 0x3F | 0x80
2181      )
2182    } else {
2183      throw new Error('Invalid code point')
2184    }
2185  }
2186
2187  return bytes
2188}
2189
2190function asciiToBytes (str) {
2191  var byteArray = []
2192  for (var i = 0; i < str.length; ++i) {
2193    // Node's code seems to be doing this and not & 0x7F..
2194    byteArray.push(str.charCodeAt(i) & 0xFF)
2195  }
2196  return byteArray
2197}
2198
2199function utf16leToBytes (str, units) {
2200  var c, hi, lo
2201  var byteArray = []
2202  for (var i = 0; i < str.length; ++i) {
2203    if ((units -= 2) < 0) break
2204
2205    c = str.charCodeAt(i)
2206    hi = c >> 8
2207    lo = c % 256
2208    byteArray.push(lo)
2209    byteArray.push(hi)
2210  }
2211
2212  return byteArray
2213}
2214
2215function base64ToBytes (str) {
2216  return base64.toByteArray(base64clean(str))
2217}
2218
2219function blitBuffer (src, dst, offset, length) {
2220  for (var i = 0; i < length; ++i) {
2221    if ((i + offset >= dst.length) || (i >= src.length)) break
2222    dst[i + offset] = src[i]
2223  }
2224  return i
2225}
2226
2227function isnan (val) {
2228  return val !== val // eslint-disable-line no-self-compare
2229}
2230
vendor: 3,632 bytes, lines 2231-2326
2231},{"base64-js":"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/node_modules/base64-js/index.js","ieee754":"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/node_modules/ieee754/index.js","isarray":"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/node_modules/isarray/index.js","buffer":"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/node_modules/buffer/index.js"}],"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/node_modules/process/browser.js":[function(require,module,exports) {
2232
2233// shim for using process in browser
2234var process = module.exports = {}; // cached from whatever global is present so that test runners that stub it
2235// don't break things.  But we need to wrap it in a try catch in case it is
2236// wrapped in strict mode code which doesn't define any globals.  It's inside a
2237// function because try/catches deoptimize in certain engines.
2238
2239var cachedSetTimeout;
2240var cachedClearTimeout;
2241
2242function defaultSetTimout() {
2243  throw new Error('setTimeout has not been defined');
2244}
2245
2246function defaultClearTimeout() {
2247  throw new Error('clearTimeout has not been defined');
2248}
2249
2250(function () {
2251  try {
2252    if (typeof setTimeout === 'function') {
2253      cachedSetTimeout = setTimeout;
2254    } else {
2255      cachedSetTimeout = defaultSetTimout;
2256    }
2257  } catch (e) {
2258    cachedSetTimeout = defaultSetTimout;
2259  }
2260
2261  try {
2262    if (typeof clearTimeout === 'function') {
2263      cachedClearTimeout = clearTimeout;
2264    } else {
2265      cachedClearTimeout = defaultClearTimeout;
2266    }
2267  } catch (e) {
2268    cachedClearTimeout = defaultClearTimeout;
2269  }
2270})();
2271
2272function runTimeout(fun) {
2273  if (cachedSetTimeout === setTimeout) {
2274    //normal enviroments in sane situations
2275    return setTimeout(fun, 0);
2276  } // if setTimeout wasn't available but was latter defined
2277
2278
2279  if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
2280    cachedSetTimeout = setTimeout;
2281    return setTimeout(fun, 0);
2282  }
2283
2284  try {
2285    // when when somebody has screwed with setTimeout but no I.E. maddness
2286    return cachedSetTimeout(fun, 0);
2287  } catch (e) {
2288    try {
2289      // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
2290      return cachedSetTimeout.call(null, fun, 0);
2291    } catch (e) {
2292      // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
2293      return cachedSetTimeout.call(this, fun, 0);
2294    }
2295  }
2296}
2297
2298function runClearTimeout(marker) {
2299  if (cachedClearTimeout === clearTimeout) {
2300    //normal enviroments in sane situations
2301    return clearTimeout(marker);
2302  } // if clearTimeout wasn't available but was latter defined
2303
2304
2305  if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
2306    cachedClearTimeout = clearTimeout;
2307    return clearTimeout(marker);
2308  }
2309
2310  try {
2311    // when when somebody has screwed with setTimeout but no I.E. maddness
2312    return cachedClearTimeout(marker);
2313  } catch (e) {
2314    try {
2315      // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
2316      return cachedClearTimeout.call(null, marker);
2317    } catch (e) {
2318      // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
2319      // Some versions of I.E. have different rules for clearTimeout vs setTimeout
2320      return cachedClearTimeout.call(this, marker);
2321    }
2322  }
2323}
2324
2325var queue = [];
2326var draining = false;
vendor: 4,192 bytes, lines 2327-2514
2327var currentQueue;
2328var queueIndex = -1;
2329
2330function cleanUpNextTick() {
2331  if (!draining || !currentQueue) {
2332    return;
2333  }
2334
2335  draining = false;
2336
2337  if (currentQueue.length) {
2338    queue = currentQueue.concat(queue);
2339  } else {
2340    queueIndex = -1;
2341  }
2342
2343  if (queue.length) {
2344    drainQueue();
2345  }
2346}
2347
2348function drainQueue() {
2349  if (draining) {
2350    return;
2351  }
2352
2353  var timeout = runTimeout(cleanUpNextTick);
2354  draining = true;
2355  var len = queue.length;
2356
2357  while (len) {
2358    currentQueue = queue;
2359    queue = [];
2360
2361    while (++queueIndex < len) {
2362      if (currentQueue) {
2363        currentQueue[queueIndex].run();
2364      }
2365    }
2366
2367    queueIndex = -1;
2368    len = queue.length;
2369  }
2370
2371  currentQueue = null;
2372  draining = false;
2373  runClearTimeout(timeout);
2374}
2375
2376process.nextTick = function (fun) {
2377  var args = new Array(arguments.length - 1);
2378
2379  if (arguments.length > 1) {
2380    for (var i = 1; i < arguments.length; i++) {
2381      args[i - 1] = arguments[i];
2382    }
2383  }
2384
2385  queue.push(new Item(fun, args));
2386
2387  if (queue.length === 1 && !draining) {
2388    runTimeout(drainQueue);
2389  }
2390}; // v8 likes predictible objects
2391
2392
2393function Item(fun, array) {
2394  this.fun = fun;
2395  this.array = array;
2396}
2397
2398Item.prototype.run = function () {
2399  this.fun.apply(null, this.array);
2400};
2401
2402process.title = 'browser';
2403process.env = {};
2404process.argv = [];
2405process.version = ''; // empty string to avoid regexp issues
2406
2407process.versions = {};
2408
2409function noop() {}
2410
2411process.on = noop;
2412process.addListener = noop;
2413process.once = noop;
2414process.off = noop;
2415process.removeListener = noop;
2416process.removeAllListeners = noop;
2417process.emit = noop;
2418process.prependListener = noop;
2419process.prependOnceListener = noop;
2420
2421process.listeners = function (name) {
2422  return [];
2423};
2424
2425process.binding = function (name) {
2426  throw new Error('process.binding is not supported');
2427};
2428
2429process.cwd = function () {
2430  return '/';
2431};
2432
2433process.chdir = function (dir) {
2434  throw new Error('process.chdir is not supported');
2435};
2436
2437process.umask = function () {
2438  return 0;
2439};
2440},{}],"../node_modules/p5/lib/p5.js":[function(require,module,exports) {
2441var define;
2442var global = arguments[3];
2443var Buffer = require("buffer").Buffer;
2444var process = require("process");
2445/*! p5.js v0.7.3 January 20, 2019 */
2446(function (f) {
2447  if (typeof exports === "object" && typeof module !== "undefined") {
2448    module.exports = f();
2449  } else if (typeof define === "function" && define.amd) {
2450    define([], f);
2451  } else {
2452    var g;
2453
2454    if (typeof window !== "undefined") {
2455      g = window;
2456    } else if (typeof global !== "undefined") {
2457      g = global;
2458    } else if (typeof self !== "undefined") {
2459      g = self;
2460    } else {
2461      g = this;
2462    }
2463
2464    g.p5 = f();
2465  }
2466})(function () {
2467  var define, module, exports;
2468  return function () {
2469    function r(e, n, t) {
2470      function o(i, f) {
2471        if (!n[i]) {
2472          if (!e[i]) {
2473            var c = "function" == typeof require && require;
2474            if (!f && c) return c(i, !0);
2475            if (u) return u(i, !0);
2476            var a = new Error("Cannot find module '" + i + "'");
2477            throw a.code = "MODULE_NOT_FOUND", a;
2478          }
2479
2480          var p = n[i] = {
2481            exports: {}
2482          };
2483          e[i][0].call(p.exports, function (r) {
2484            var n = e[i][1][r];
2485            return o(n || r);
2486          }, p, p.exports, r, e, n, t);
2487        }
2488
2489        return n[i].exports;
2490      }
2491
2492      for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) o(t[i]);
2493
2494      return o;
2495    }
2496
2497    return r;
2498  }()({
2499    1: [function (_dereq_, module, exports) {
2500      module.exports = {
2501        "project": {
2502          "name": "p5",
2503          "description": "[![Build Status](https://travis-ci.org/processing/p5.js.svg?branch=master)](https://travis-ci.org/processing/p5.js) [![npm version](https://badge.fury.io/js/p5.svg)](https://www.npmjs.com/package/p5)",
2504          "version": "0.7.3",
2505          "url": "https://github.com/processing/p5.js#readme"
2506        },
2507        "files": {
2508          "src/color/color_conversion.js": {
2509            "name": "src/color/color_conversion.js",
2510            "modules": {
2511              "Color Conversion": 1
2512            },
2513            "classes": {},
2514            "fors": {
2515              "p5": 1
2516            },
2517            "namespaces": {}
2518          },
2519          "src/color/creating_reading.js": {
2520            "name": "src/color/creating_reading.js",
2521            "modules": {
2522              "Creating & Reading": 1
2523            },
2524            "classes": {},
2525            "fors": {
2526              "p5": 1
2527            },
2528            "namespaces": {}
2529          },
2530          "src/color/p5.Color.js": {
2531            "name": "src/color/p5.Color.js",
2532            "modules": {},
2533            "classes": {
2534              "p5.Color": 1
2535            },
2536            "fors": {
2537              "p5": 1
2538            },
2539            "namespaces": {}
2540          },
2541          "src/color/setting.js": {
2542            "name": "src/color/setting.js",
2543            "modules": {
2544              "Setting": 1
2545            },
2546            "classes": {},
2547            "fors": {
2548              "p5": 1
2549            },
2550            "namespaces": {}
2551          },
2552          "src/core/shape/2d_primitives.js": {
2553            "name": "src/core/shape/2d_primitives.js",
2554            "modules": {
2555              "2D Primitives": 1
2556            },
2557            "classes": {},
2558            "fors": {
2559              "p5": 1
2560            },
2561            "namespaces": {}
2562          },
2563          "src/core/shape/attributes.js": {
2564            "name": "src/core/shape/attributes.js",
2565            "modules": {
2566              "Attributes": 1
2567            },
2568            "classes": {},
2569            "fors": {
2570              "p5": 1
2571            },
2572            "namespaces": {}
2573          },
2574          "src/core/shape/curves.js": {
2575            "name": "src/core/shape/curves.js",
2576            "modules": {
2577              "Curves": 1
2578            },
2579            "classes": {},
2580            "fors": {
2581              "p5": 1
2582            },
2583            "namespaces": {}
2584          },
2585          "src/core/shape/vertex.js": {
2586            "name": "src/core/shape/vertex.js",
2587            "modules": {
2588              "Vertex": 1
2589            },
2590            "classes": {},
2591            "fors": {
2592              "p5": 1
2593            },
2594            "namespaces": {}
2595          },
2596          "src/core/constants.js": {
2597            "name": "src/core/constants.js",
2598            "modules": {
2599              "Constants": 1
2600            },
2601            "classes": {},
2602            "fors": {
2603              "p5": 1
2604            },
2605            "namespaces": {}
2606          },
2607          "src/core/environment.js": {
2608            "name": "src/core/environment.js",
2609            "modules": {
2610              "Environment": 1
2611            },
2612            "classes": {},
2613            "fors": {
2614              "p5": 1
2615            },
2616            "namespaces": {}
2617          },
2618          "src/core/error_helpers.js": {
2619            "name": "src/core/error_helpers.js",
2620            "modules": {},
2621            "classes": {},
2622            "fors": {
2623              "p5": 1
2624            },
2625            "namespaces": {}
2626          },
2627          "src/core/helpers.js": {
2628            "name": "src/core/helpers.js",
2629            "modules": {},
2630            "classes": {},
2631            "fors": {},
2632            "namespaces": {}
2633          },
2634          "src/core/init.js": {
2635            "name": "src/core/init.js",
2636            "modules": {},
2637            "classes": {},
2638            "fors": {},
2639            "namespaces": {}
2640          },
2641          "src/core/legacy.js": {
2642            "name": "src/core/legacy.js",
2643            "modules": {},
2644            "classes": {},
2645            "fors": {
2646              "p5": 1
2647            },
2648            "namespaces": {}
2649          },
2650          "src/core/main.js": {
2651            "name": "src/core/main.js",
2652            "modules": {
2653              "Structure": 1
2654            },
2655            "classes": {
2656              "p5": 1
2657            },
2658            "fors": {
2659              "p5": 1
2660            },
2661            "namespaces": {}
2662          },
2663          "src/core/p5.Element.js": {
2664            "name": "src/core/p5.Element.js",
2665            "modules": {
2666              "DOM": 1
2667            },
2668            "classes": {
2669              "p5.Element": 1
2670            },
2671            "fors": {
2672              "p5.Element": 1
2673            },
2674            "namespaces": {}
2675          },
2676          "src/core/p5.Graphics.js": {
2677            "name": "src/core/p5.Graphics.js",
2678            "modules": {
2679              "Rendering": 1
2680            },
2681            "classes": {
2682              "p5.Graphics": 1
2683            },
2684            "fors": {
2685              "p5": 1
2686            },
2687            "namespaces": {}
2688          },
2689          "src/core/p5.Renderer.js": {
2690            "name": "src/core/p5.Renderer.js",
2691            "modules": {},
2692            "classes": {
2693              "p5.Renderer": 1
2694            },
2695            "fors": {
2696              "p5": 1
2697            },
2698            "namespaces": {}
2699          },
2700          "src/core/p5.Renderer2D.js": {
2701            "name": "src/core/p5.Renderer2D.js",
2702            "modules": {},
2703            "classes": {},
2704            "fors": {},
2705            "namespaces": {}
2706          },
2707          "src/core/rendering.js": {
2708            "name": "src/core/rendering.js",
2709            "modules": {},
2710            "classes": {},
2711            "fors": {
2712              "p5": 1
2713            },
2714            "namespaces": {}
2715          },
2716          "src/core/shim.js": {
2717            "name": "src/core/shim.js",
2718            "modules": {},
2719            "classes": {},
2720            "fors": {},
2721            "namespaces": {}
2722          },
2723          "src/core/structure.js": {
2724            "name": "src/core/structure.js",
2725            "modules": {},
2726            "classes": {},
2727            "fors": {
2728              "p5": 1
2729            },
2730            "namespaces": {}
2731          },
2732          "src/core/transform.js": {
2733            "name": "src/core/transform.js",
2734            "modules": {
2735              "Transform": 1
2736            },
2737            "classes": {},
2738            "fors": {
2739              "p5": 1
2740            },
2741            "namespaces": {}
2742          },
2743          "src/data/p5.TypedDict.js": {
2744            "name": "src/data/p5.TypedDict.js",
2745            "modules": {
2746              "Dictionary": 1
2747            },
2748            "classes": {
2749              "p5.TypedDict": 1,
2750              "p5.StringDict": 1,
2751              "p5.NumberDict": 1
2752            },
2753            "fors": {
2754              "p5.TypedDict": 1,
2755              "p5": 1
2756            },
2757            "namespaces": {}
2758          },
2759          "src/events/acceleration.js": {
2760            "name": "src/events/acceleration.js",
2761            "modules": {
2762              "Acceleration": 1
2763            },
2764            "classes": {},
2765            "fors": {
2766              "p5": 1
2767            },
2768            "namespaces": {}
2769          },
2770          "src/events/keyboard.js": {
2771            "name": "src/events/keyboard.js",
2772            "modules": {
2773              "Keyboard": 1
2774            },
2775            "classes": {},
2776            "fors": {
2777              "p5": 1
2778            },
2779            "namespaces": {}
2780          },
2781          "src/events/mouse.js": {
2782            "name": "src/events/mouse.js",
2783            "modules": {
2784              "Mouse": 1
2785            },
2786            "classes": {},
2787            "fors": {
2788              "p5": 1
2789            },
2790            "namespaces": {}
2791          },
2792          "src/events/touch.js": {
2793            "name": "src/events/touch.js",
2794            "modules": {
2795              "Touch": 1
2796            },
2797            "classes": {},
2798            "fors": {
2799              "p5": 1
2800            },
2801            "namespaces": {}
2802          },
2803          "src/image/filters.js": {
2804            "name": "src/image/filters.js",
2805            "modules": {},
2806            "classes": {},
2807            "fors": {},
2808            "namespaces": {}
2809          },
2810          "src/image/image.js": {
2811            "name": "src/image/image.js",
2812            "modules": {
2813              "Image": 1
2814            },
2815            "classes": {},
2816            "fors": {
2817              "p5": 1
2818            },
2819            "namespaces": {}
2820          },
2821          "src/image/loading_displaying.js": {
2822            "name": "src/image/loading_displaying.js",
2823            "modules": {
2824              "Loading & Displaying": 1
2825            },
2826            "classes": {},
2827            "fors": {
2828              "p5": 1
2829            },
2830            "namespaces": {}
2831          },
2832          "src/image/p5.Image.js": {
2833            "name": "src/image/p5.Image.js",
2834            "modules": {},
2835            "classes": {
2836              "p5.Image": 1
2837            },
2838            "fors": {},
2839            "namespaces": {}
2840          },
2841          "src/image/pixels.js": {
2842            "name": "src/image/pixels.js",
2843            "modules": {
2844              "Pixels": 1
2845            },
2846            "classes": {},
2847            "fors": {
2848              "p5": 1
2849            },
2850            "namespaces": {}
2851          },
2852          "src/io/files.js": {
2853            "name": "src/io/files.js",
2854            "modules": {
2855              "Input": 1,
2856              "Output": 1
2857            },
2858            "classes": {
2859              "p5.PrintWriter": 1
2860            },
2861            "fors": {
2862              "p5": 1
2863            },
2864            "namespaces": {}
2865          },
2866          "src/io/p5.Table.js": {
2867            "name": "src/io/p5.Table.js",
2868            "modules": {
2869              "Table": 1
2870            },
2871            "classes": {
2872              "p5.Table": 1
2873            },
2874            "fors": {},
2875            "namespaces": {}
2876          },
2877          "src/io/p5.TableRow.js": {
2878            "name": "src/io/p5.TableRow.js",
2879            "modules": {},
2880            "classes": {
2881              "p5.TableRow": 1
2882            },
2883            "fors": {},
2884            "namespaces": {}
2885          },
2886          "src/io/p5.XML.js": {
2887            "name": "src/io/p5.XML.js",
2888            "modules": {
2889              "XML": 1
2890            },
2891            "classes": {
2892              "p5.XML": 1
2893            },
2894            "fors": {},
2895            "namespaces": {}
2896          },
2897          "src/math/calculation.js": {
2898            "name": "src/math/calculation.js",
2899            "modules": {
2900              "Calculation": 1
2901            },
2902            "classes": {},
2903            "fors": {
2904              "p5": 1
2905            },
2906            "namespaces": {}
2907          },
2908          "src/math/math.js": {
2909            "name": "src/math/math.js",
2910            "modules": {
2911              "Math": 1
2912            },
2913            "classes": {},
2914            "fors": {
2915              "p5": 1
2916            },
2917            "namespaces": {}
2918          },
2919          "src/math/noise.js": {
2920            "name": "src/math/noise.js",
2921            "modules": {
2922              "Noise": 1
2923            },
2924            "classes": {},
2925            "fors": {
2926              "p5": 1
2927            },
2928            "namespaces": {}
2929          },
2930          "src/math/p5.Vector.js": {
2931            "name": "src/math/p5.Vector.js",
2932            "modules": {},
2933            "classes": {
2934              "p5.Vector": 1
2935            },
2936            "fors": {},
2937            "namespaces": {}
2938          },
2939          "src/math/random.js": {
2940            "name": "src/math/random.js",
2941            "modules": {
2942              "Random": 1
2943            },
2944            "classes": {},
2945            "fors": {
2946              "p5": 1
2947            },
2948            "namespaces": {}
2949          },
2950          "src/math/trigonometry.js": {
2951            "name": "src/math/trigonometry.js",
2952            "modules": {
2953              "Trigonometry": 1
2954            },
2955            "classes": {},
2956            "fors": {
2957              "p5": 1
2958            },
2959            "namespaces": {}
2960          },
2961          "src/typography/attributes.js": {
2962            "name": "src/typography/attributes.js",
2963            "modules": {},
2964            "classes": {},
2965            "fors": {
2966              "p5": 1
2967            },
2968            "namespaces": {}
2969          },
2970          "src/typography/loading_displaying.js": {
2971            "name": "src/typography/loading_displaying.js",
2972            "modules": {},
2973            "classes": {},
2974            "fors": {
2975              "p5": 1
2976            },
2977            "namespaces": {}
2978          },
2979          "src/typography/p5.Font.js": {
2980            "name": "src/typography/p5.Font.js",
2981            "modules": {
2982              "Font": 1
2983            },
2984            "classes": {
2985              "p5.Font": 1
2986            },
2987            "fors": {},
2988            "namespaces": {}
2989          },
2990          "src/utilities/array_functions.js": {
2991            "name": "src/utilities/array_functions.js",
2992            "modules": {
2993              "Array Functions": 1
2994            },
2995            "classes": {},
2996            "fors": {
2997              "p5": 1
2998            },
2999            "namespaces": {}
3000          },
3001          "src/utilities/conversion.js": {
3002            "name": "src/utilities/conversion.js",
3003            "modules": {
3004              "Conversion": 1
3005            },
3006            "classes": {},
3007            "fors": {
3008              "p5": 1
3009            },
3010            "namespaces": {}
3011          },
3012          "src/utilities/string_functions.js": {
3013            "name": "src/utilities/string_functions.js",
3014            "modules": {
3015              "String Functions": 1
3016            },
3017            "classes": {},
3018            "fors": {
3019              "p5": 1
3020            },
3021            "namespaces": {}
3022          },
3023          "src/utilities/time_date.js": {
3024            "name": "src/utilities/time_date.js",
3025            "modules": {
3026              "Time & Date": 1
3027            },
3028            "classes": {},
3029            "fors": {
3030              "p5": 1
3031            },
3032            "namespaces": {}
3033          },
3034          "src/webgl/3d_primitives.js": {
3035            "name": "src/webgl/3d_primitives.js",
3036            "modules": {
3037              "3D Primitives": 1
3038            },
3039            "classes": {},
3040            "fors": {
3041              "p5": 1
3042            },
3043            "namespaces": {}
3044          },
3045          "src/webgl/interaction.js": {
3046            "name": "src/webgl/interaction.js",
3047            "modules": {
3048              "Interaction": 1
3049            },
3050            "classes": {},
3051            "fors": {
3052              "p5": 1
3053            },
3054            "namespaces": {}
3055          },
3056          "src/webgl/light.js": {
3057            "name": "src/webgl/light.js",
3058            "modules": {
3059              "Lights": 1
3060            },
3061            "classes": {},
3062            "fors": {
3063              "p5": 1
3064            },
3065            "namespaces": {}
3066          },
3067          "src/webgl/loading.js": {
3068            "name": "src/webgl/loading.js",
3069            "modules": {
3070              "3D Models": 1
3071            },
3072            "classes": {},
3073            "fors": {
3074              "p5": 1
3075            },
3076            "namespaces": {}
3077          },
3078          "src/webgl/material.js": {
3079            "name": "src/webgl/material.js",
3080            "modules": {
3081              "Material": 1
3082            },
3083            "classes": {},
3084            "fors": {
3085              "p5": 1
3086            },
3087            "namespaces": {}
3088          },
3089          "src/webgl/p5.Camera.js": {
3090            "name": "src/webgl/p5.Camera.js",
3091            "modules": {
3092              "Camera": 1
3093            },
3094            "classes": {
3095              "p5.Camera": 1
3096            },
3097            "fors": {
3098              "p5": 1,
3099              "p5.Camera": 1
3100            },
3101            "namespaces": {}
3102          },
3103          "src/webgl/p5.Geometry.js": {
3104            "name": "src/webgl/p5.Geometry.js",
3105            "modules": {},
3106            "classes": {
3107              "p5.Geometry": 1
3108            },
3109            "fors": {},
3110            "namespaces": {}
3111          },
3112          "src/webgl/p5.Matrix.js": {
3113            "name": "src/webgl/p5.Matrix.js",
3114            "modules": {},
3115            "classes": {
3116              "p5.Matrix": 1
3117            },
3118            "fors": {},
3119            "namespaces": {}
3120          },
3121          "src/webgl/p5.RendererGL.Immediate.js": {
3122            "name": "src/webgl/p5.RendererGL.Immediate.js",
3123            "modules": {},
3124            "classes": {},
3125            "fors": {},
3126            "namespaces": {}
3127          },
3128          "src/webgl/p5.RendererGL.Retained.js": {
3129            "name": "src/webgl/p5.RendererGL.Retained.js",
3130            "modules": {},
3131            "classes": {},
3132            "fors": {},
3133            "namespaces": {}
3134          },
3135          "src/webgl/p5.RendererGL.js": {
3136            "name": "src/webgl/p5.RendererGL.js",
3137            "modules": {},
3138            "classes": {
3139              "p5.RendererGL": 1
3140            },
3141            "fors": {
3142              "p5": 1
3143            },
3144            "namespaces": {}
3145          },
3146          "src/webgl/p5.Shader.js": {
3147            "name": "src/webgl/p5.Shader.js",
3148            "modules": {
3149              "Shaders": 1
3150            },
3151            "classes": {
3152              "p5.Shader": 1
3153            },
3154            "fors": {
3155              "p5": 1
3156            },
3157            "namespaces": {}
3158          },
3159          "src/webgl/p5.Texture.js": {
3160            "name": "src/webgl/p5.Texture.js",
3161            "modules": {},
3162            "classes": {
3163              "p5.Texture": 1
3164            },
3165            "fors": {
3166              "p5": 1
3167            },
3168            "namespaces": {}
3169          },
3170          "src/webgl/text.js": {
3171            "name": "src/webgl/text.js",
3172            "modules": {},
3173            "classes": {
3174              "ImageInfos": 1,
3175              "FontInfo": 1,
3176              "Cubic": 1
3177            },
3178            "fors": {},
3179            "namespaces": {}
3180          },
3181          "lib/addons/p5.dom.js": {
3182            "name": "lib/addons/p5.dom.js",
3183            "modules": {
3184              "p5.dom": 1
3185            },
3186            "classes": {
3187              "p5.MediaElement": 1,
3188              "p5.File": 1
3189            },
3190            "fors": {
3191              "p5": 1,
3192              "p5.Element": 1
3193            },
3194            "namespaces": {}
3195          },
3196          "lib/addons/p5.sound.js": {
3197            "name": "lib/addons/p5.sound.js",
3198            "modules": {
3199              "p5.sound": 1
3200            },
3201            "classes": {
3202              "p5.SoundFile": 1,
3203              "p5.Amplitude": 1,
3204              "p5.FFT": 1,
3205              "p5.Signal": 1,
3206              "p5.Oscillator": 1,
3207              "p5.SinOsc": 1,
3208              "p5.TriOsc": 1,
3209              "p5.SawOsc": 1,
3210              "p5.SqrOsc": 1,
3211              "p5.Envelope": 1,
3212              "p5.Pulse": 1,
3213              "p5.Noise": 1,
3214              "p5.AudioIn": 1,
3215              "p5.Effect": 1,
3216              "p5.Filter": 1,
3217              "p5.LowPass": 1,
3218              "p5.HighPass": 1,
3219              "p5.BandPass": 1,
3220              "p5.EQ": 1,
3221              "p5.Panner3D": 1,
3222              "p5.Delay": 1,
3223              "p5.Reverb": 1,
3224              "p5.Convolver": 1,
3225              "p5.Phrase": 1,
3226              "p5.Part": 1,
3227              "p5.Score": 1,
3228              "p5.SoundLoop": 1,
3229              "p5.Compressor": 1,
3230              "p5.SoundRecorder": 1,
3231              "p5.PeakDetect": 1,
3232              "p5.Gain": 1,
3233              "p5.AudioVoice": 1,
3234              "p5.MonoSynth": 1,
3235              "p5.PolySynth": 1,
3236              "p5.Distortion": 1
3237            },
3238            "fors": {
3239              "p5.sound": 1,
3240              "p5": 1
3241            },
3242            "namespaces": {}
3243          },
3244          "lib/addons/p5.sound.min.js": {
3245            "name": "lib/addons/p5.sound.min.js",
3246            "modules": {},
3247            "classes": {},
3248            "fors": {},
3249            "namespaces": {}
3250          }
3251        },
3252        "modules": {
3253          "Color": {
3254            "name": "Color",
3255            "submodules": {
3256              "Color Conversion": 1,
3257              "Creating & Reading": 1,
3258              "Setting": 1
3259            },
3260            "elements": {},
3261            "classes": {
3262              "p5.Color": 1
3263            },
3264            "fors": {
3265              "p5": 1
3266            },
3267            "namespaces": {},
3268            "file": "src/color/p5.Color.js",
3269            "line": 16
3270          },
3271          "Color Conversion": {
3272            "name": "Color Conversion",
3273            "submodules": {},
3274            "elements": {},
3275            "classes": {},
3276            "fors": {
3277              "p5": 1
3278            },
3279            "is_submodule": 1,
3280            "namespaces": {},
3281            "module": "Color",
3282            "namespace": "",
3283            "file": "src/color/color_conversion.js",
3284            "line": 1,
3285            "requires": ["core"]
3286          },
3287          "Creating & Reading": {
3288            "name": "Creating & Reading",
3289            "submodules": {},
3290            "elements": {},
3291            "classes": {
3292              "p5.Color": 1
3293            },
3294            "fors": {
3295              "p5": 1
3296            },
3297            "is_submodule": 1,
3298            "namespaces": {},
3299            "module": "Color",
3300            "namespace": "",
3301            "file": "src/color/p5.Color.js",
3302            "line": 16,
3303            "requires": ["core", "constants"],
3304            "description": "<p>Each color stores the color mode and level maxes that applied at the\ntime of its construction. These are used to interpret the input arguments\n(at construction and later for that instance of color) and to format the\noutput e.g. when <a href=\"#/p5/saturation\">saturation()</a> is requested.</p>\n<p>Internally we store an array representing the ideal RGBA values in floating\npoint form, normalized from 0 to 1. From this we calculate the closest\nscreen color (RGBA levels from 0 to 255) and expose this to the renderer.</p>\n<p>We also cache normalized, floating point components of the color in various\nrepresentations as they are calculated. This is done to prevent repeating a\nconversion that has already been performed.</p>\n"
3305          },
3306          "Setting": {
3307            "name": "Setting",
3308            "submodules": {},
3309            "elements": {},
3310            "classes": {},
3311            "fors": {
3312              "p5": 1
3313            },
3314            "is_submodule": 1,
3315            "namespaces": {},
3316            "module": "Color",
3317            "namespace": "",
3318            "file": "src/color/setting.js",
3319            "line": 1,
3320            "requires": ["core", "constants"]
3321          },
3322          "Shape": {
3323            "name": "Shape",
3324            "submodules": {
3325              "2D Primitives": 1,
3326              "Curves": 1,
3327              "Vertex": 1,
3328              "3D Primitives": 1,
3329              "3D Models": 1
3330            },
3331            "elements": {},
3332            "classes": {},
3333            "fors": {
3334              "p5": 1
3335            },
3336            "namespaces": {}
3337          },
3338          "2D Primitives": {
3339            "name": "2D Primitives",
3340            "submodules": {},
3341            "elements": {},
3342            "classes": {},
3343            "fors": {
3344              "p5": 1
3345            },
3346            "is_submodule": 1,
3347            "namespaces": {},
3348            "module": "Shape",
3349            "namespace": "",
3350            "file": "src/core/shape/2d_primitives.js",
3351            "line": 1,
3352            "requires": ["core", "constants"]
3353          },
3354          "Attributes": {
3355            "name": "Attributes",
3356            "submodules": {},
3357            "elements": {},
3358            "classes": {},
3359            "fors": {
3360              "p5": 1
3361            },
3362            "is_submodule": 1,
3363            "namespaces": {},
3364            "module": "Typography",
3365            "namespace": "",
3366            "file": "src/core/shape/attributes.js",
3367            "line": 1,
3368            "requires": ["core", "constants"]
3369          },
3370          "Curves": {
3371            "name": "Curves",
3372            "submodules": {},
3373            "elements": {},
3374            "classes": {},
3375            "fors": {
3376              "p5": 1
3377            },
3378            "is_submodule": 1,
3379            "namespaces": {},
3380            "module": "Shape",
3381            "namespace": "",
3382            "file": "src/core/shape/curves.js",
3383            "line": 1,
3384            "requires": ["core"]
3385          },
3386          "Vertex": {
3387            "name": "Vertex",
3388            "submodules": {},
3389            "elements": {},
3390            "classes": {},
3391            "fors": {
3392              "p5": 1
3393            },
3394            "is_submodule": 1,
3395            "namespaces": {},
3396            "module": "Shape",
3397            "namespace": "",
3398            "file": "src/core/shape/vertex.js",
3399            "line": 1,
3400            "requires": ["core", "constants"]
3401          },
3402          "Constants": {
3403            "name": "Constants",
3404            "submodules": {},
3405            "elements": {},
3406            "classes": {},
3407            "fors": {
3408              "p5": 1
3409            },
3410            "namespaces": {},
3411            "module": "Constants",
3412            "file": "src/core/constants.js",
3413            "line": 1
3414          },
3415          "Environment": {
3416            "name": "Environment",
3417            "submodules": {},
3418            "elements": {},
3419            "classes": {},
3420            "fors": {
3421              "p5": 1
3422            },
3423            "namespaces": {},
3424            "module": "Environment",
3425            "file": "src/core/environment.js",
3426            "line": 1,
3427            "requires": ["core", "constants"]
3428          },
3429          "Structure": {
3430            "name": "Structure",
3431            "submodules": {},
3432            "elements": {},
3433            "classes": {},
3434            "fors": {
3435              "p5": 1
3436            },
3437            "namespaces": {},
3438            "module": "IO",
3439            "file": "src/core/main.js",
3440            "line": 1,
3441            "requires": ["constants"]
3442          },
3443          "DOM": {
3444            "name": "DOM",
3445            "submodules": {},
3446            "elements": {},
3447            "classes": {
3448              "p5.Element": 1
3449            },
3450            "fors": {
3451              "p5.Element": 1
3452            },
3453            "namespaces": {},
3454            "module": "DOM",
3455            "file": "src/core/p5.Element.js",
3456            "line": 11,
3457            "description": "<p>Base class for all elements added to a sketch, including canvas,\ngraphics buffers, and other HTML elements. Methods in blue are\nincluded in the core functionality, methods in brown are added\nwith the <a href=\"http://p5js.org/reference/#/libraries/p5.dom\">p5.dom\nlibrary</a>.\nIt is not called directly, but <a href=\"#/p5.Element\">p5.Element</a>\nobjects are created by calling <a href=\"#/p5/createCanvas\">createCanvas</a>, <a href=\"#/p5/createGraphics\">createGraphics</a>,\nor in the p5.dom library, <a href=\"#/p5/createDiv\">createDiv</a>, <a href=\"#/p5/createImg\">createImg</a>, <a href=\"#/p5/createInput\">createInput</a>, etc.</p>\n"
3458          },
3459          "Rendering": {
3460            "name": "Rendering",
3461            "submodules": {
3462              "undefined": 1
3463            },
3464            "elements": {},
3465            "classes": {
3466              "p5.RendererGL": 1,
3467              "p5.Graphics": 1,
3468              "p5.Renderer": 1
3469            },
3470            "fors": {
3471              "p5": 1
3472            },
3473            "namespaces": {},
3474            "module": "Rendering",
3475            "file": "src/webgl/p5.RendererGL.js",
3476            "line": 428,
3477            "description": "<p>Thin wrapper around a renderer, to be used for creating a\ngraphics buffer object. Use this class if you need\nto draw into an off-screen graphics buffer. The two parameters define the\nwidth and height in pixels. The fields and methods for this class are\nextensive, but mirror the normal drawing API for p5.</p>\n"
3478          },
3479          "Transform": {
3480            "name": "Transform",
3481            "submodules": {},
3482            "elements": {},
3483            "classes": {},
3484            "fors": {
3485              "p5": 1
3486            },
3487            "namespaces": {},
3488            "module": "Transform",
3489            "file": "src/core/transform.js",
3490            "line": 1,
3491            "requires": ["core", "constants"]
3492          },
3493          "Data": {
3494            "name": "Data",
3495            "submodules": {
3496              "Dictionary": 1,
3497              "Array Functions": 1,
3498              "Conversion": 1,
3499              "String Functions": 1
3500            },
3501            "elements": {},
3502            "classes": {
3503              "p5.TypedDict": 1,
3504              "p5.StringDict": 1,
3505              "p5.NumberDict": 1
3506            },
3507            "fors": {
3508              "p5.TypedDict": 1,
3509              "p5": 1
3510            },
3511            "namespaces": {},
3512            "file": "src/data/p5.TypedDict.js",
3513            "line": 422
3514          },
3515          "Dictionary": {
3516            "name": "Dictionary",
3517            "submodules": {},
3518            "elements": {},
3519            "classes": {
3520              "p5.TypedDict": 1,
3521              "p5.StringDict": 1,
3522              "p5.NumberDict": 1
3523            },
3524            "fors": {
3525              "p5.TypedDict": 1,
3526              "p5": 1
3527            },
3528            "is_submodule": 1,
3529            "namespaces": {},
3530            "module": "Data",
3531            "namespace": "",
3532            "file": "src/data/p5.TypedDict.js",
3533            "line": 422,
3534            "requires": ["core\n\nThis module defines the p5 methods for the p5 Dictionary classes.\nThe classes StringDict and NumberDict are for storing and working\nwith key-value pairs."],
3535            "description": "<p>Base class for all p5.Dictionary types. Specifically\n typed Dictionary classes inherit from this class.</p>\n"
3536          },
3537          "Events": {
3538            "name": "Events",
3539            "submodules": {
3540              "Acceleration": 1,
3541              "Keyboard": 1,
3542              "Mouse": 1,
3543              "Touch": 1
3544            },
3545            "elements": {},
3546            "classes": {},
3547            "fors": {
3548              "p5": 1
3549            },
3550            "namespaces": {}
3551          },
3552          "Acceleration": {
3553            "name": "Acceleration",
3554            "submodules": {},
3555            "elements": {},
3556            "classes": {},
3557            "fors": {
3558              "p5": 1
3559            },
3560            "is_submodule": 1,
3561            "namespaces": {},
3562            "module": "Events",
3563            "namespace": "",
3564            "file": "src/events/acceleration.js",
3565            "line": 1,
3566            "requires": ["core"]
3567          },
3568          "Keyboard": {
3569            "name": "Keyboard",
3570            "submodules": {},
3571            "elements": {},
3572            "classes": {},
3573            "fors": {
3574              "p5": 1
3575            },
3576            "is_submodule": 1,
3577            "namespaces": {},
3578            "module": "Events",
3579            "namespace": "",
3580            "file": "src/events/keyboard.js",
3581            "line": 1,
3582            "requires": ["core"]
3583          },
3584          "Mouse": {
3585            "name": "Mouse",
3586            "submodules": {},
3587            "elements": {},
3588            "classes": {},
3589            "fors": {
3590              "p5": 1
3591            },
3592            "is_submodule": 1,
3593            "namespaces": {},
3594            "module": "Events",
3595            "namespace": "",
3596            "file": "src/events/mouse.js",
3597            "line": 1,
3598            "requires": ["core", "constants"]
3599          },
3600          "Touch": {
3601            "name": "Touch",
3602            "submodules": {},
3603            "elements": {},
3604            "classes": {},
3605            "fors": {
3606              "p5": 1
3607            },
3608            "is_submodule": 1,
3609            "namespaces": {},
3610            "module": "Events",
3611            "namespace": "",
3612            "file": "src/events/touch.js",
3613            "line": 1,
3614            "requires": ["core"]
3615          },
3616          "Image": {
3617            "name": "Image",
3618            "submodules": {
3619              "Pixels": 1
3620            },
3621            "elements": {},
3622            "classes": {
3623              "p5.Image": 1
3624            },
3625            "fors": {
3626              "p5": 1
3627            },
3628            "namespaces": {},
3629            "module": "Image",
3630            "file": "src/image/p5.Image.js",
3631            "line": 23,
3632            "requires": ["core"],
3633            "description": "<p>Creates a new <a href=\"#/p5.Image\">p5.Image</a>. A <a href=\"#/p5.Image\">p5.Image</a> is a canvas backed representation of an\nimage.\n<br><br>\np5 can display .gif, .jpg and .png images. Images may be displayed\nin 2D and 3D space. Before an image is used, it must be loaded with the\n<a href=\"#/p5/loadImage\">loadImage()</a> function. The <a href=\"#/p5.Image\">p5.Image</a> class contains fields for the width and\nheight of the image, as well as an array called <a href=\"#/p5.Image/pixels\">pixels[]</a> that contains the\nvalues for every pixel in the image.\n<br><br>\nThe methods described below allow easy access to the image&#39;s pixels and\nalpha channel and simplify the process of compositing.\n<br><br>\nBefore using the <a href=\"#/p5.Image/pixels\">pixels[]</a> array, be sure to use the <a href=\"#/p5.Image/loadPixels\">loadPixels()</a> method on\nthe image to make sure that the pixel data is properly loaded.</p>\n"
3634          },
3635          "Loading & Displaying": {
3636            "name": "Loading & Displaying",
3637            "submodules": {},
3638            "elements": {},
3639            "classes": {},
3640            "fors": {
3641              "p5": 1
3642            },
3643            "is_submodule": 1,
3644            "namespaces": {},
3645            "module": "Typography",
3646            "namespace": "",
3647            "file": "src/image/loading_displaying.js",
3648            "line": 1,
3649            "requires": ["core"]
3650          },
3651          "Pixels": {
3652            "name": "Pixels",
3653            "submodules": {},
3654            "elements": {},
3655            "classes": {},
3656            "fors": {
3657              "p5": 1
3658            },
3659            "is_submodule": 1,
3660            "namespaces": {},
3661            "module": "Image",
3662            "namespace": "",
3663            "file": "src/image/pixels.js",
3664            "line": 1,
3665            "requires": ["core"]
3666          },
3667          "IO": {
3668            "name": "IO",
3669            "submodules": {
3670              "Structure": 1,
3671              "Input": 1,
3672              "Output": 1,
3673              "Table": 1,
3674              "XML": 1,
3675              "Time & Date": 1
3676            },
3677            "elements": {},
3678            "classes": {
3679              "p5": 1,
3680              "p5.PrintWriter": 1,
3681              "p5.Table": 1,
3682              "p5.TableRow": 1,
3683              "p5.XML": 1
3684            },
3685            "fors": {
3686              "p5": 1
3687            },
3688            "namespaces": {},
3689            "file": "src/io/p5.XML.js",
3690            "line": 11
3691          },
3692          "Input": {
3693            "name": "Input",
3694            "submodules": {},
3695            "elements": {},
3696            "classes": {},
3697            "fors": {
3698              "p5": 1
3699            },
3700            "is_submodule": 1,
3701            "namespaces": {},
3702            "module": "IO",
3703            "namespace": "",
3704            "file": "src/io/files.js",
3705            "line": 1,
3706            "requires": ["core"]
3707          },
3708          "Output": {
3709            "name": "Output",
3710            "submodules": {},
3711            "elements": {},
3712            "classes": {
3713              "p5": 1,
3714              "p5.PrintWriter": 1
3715            },
3716            "fors": {
3717              "p5": 1
3718            },
3719            "is_submodule": 1,
3720            "namespaces": {},
3721            "module": "IO",
3722            "namespace": "",
3723            "file": "src/io/files.js",
3724            "line": 1228,
3725            "description": "<p>This is the p5 instance constructor.</p>\n<p>A p5 instance holds all the properties and methods related to\na p5 sketch.  It expects an incoming sketch closure and it can also\ntake an optional node parameter for attaching the generated p5 canvas\nto a node.  The sketch closure takes the newly created p5 instance as\nits s
3725ole argument and may optionally set <a href=\"#/p5/preload\">preload()</a>, <a href=\"#/p5/setup\">setup()</a>, and/or\n<a href=\"#/p5/draw\">draw()</a> properties on it for running a sketch.</p>\n<p>A p5 sketch can run in &quot;global&quot; or &quot;instance&quot; mode:\n&quot;global&quot;   - all properties and methods are attached to the window\n&quot;instance&quot; - all properties and methods are bound to this p5 object</p>\n"
3726          },
3727          "Table": {
3728            "name": "Table",
3729            "submodules": {},
3730            "elements": {},
3731            "classes": {
3732              "p5.Table": 1,
3733              "p5.TableRow": 1
3734            },
3735            "fors": {},
3736            "is_submodule": 1,
3737            "namespaces": {},
3738            "module": "IO",
3739            "namespace": "",
3740            "file": "src/io/p5.TableRow.js",
3741            "line": 11,
3742            "requires": ["core"],
3743            "description": "<p><a href=\"#/p5.Table\">Table</a> objects store data with multiple rows and columns, much\nlike in a traditional spreadsheet. Tables can be generated from\nscratch, dynamically, or using data from an existing file.</p>\n"
3744          },
3745          "XML": {
3746            "name": "XML",
3747            "submodules": {},
3748            "elements": {},
3749            "classes": {
3750              "p5.XML": 1
3751            },
3752            "fors": {},
3753            "is_submodule": 1,
3754            "namespaces": {},
3755            "module": "IO",
3756            "namespace": "",
3757            "file": "src/io/p5.XML.js",
3758            "line": 11,
3759            "requires": ["core"],
3760            "description": "<p>XML is a representation of an XML object, able to parse XML code. Use\n<a href=\"#/p5/loadXML\">loadXML()</a> to load external XML files and create XML objects.</p>\n"
3761          },
3762          "Math": {
3763            "name": "Math",
3764            "submodules": {
3765              "Calculation": 1,
3766              "Noise": 1,
3767              "Random": 1,
3768              "Trigonometry": 1
3769            },
3770            "elements": {},
3771            "classes": {
3772              "p5.Vector": 1
3773            },
3774            "fors": {
3775              "p5": 1
3776            },
3777            "namespaces": {},
3778            "module": "Math",
3779            "file": "src/math/p5.Vector.js",
3780            "line": 12,
3781            "requires": ["core"],
3782            "description": "<p>A class to describe a two or three dimensional vector, specifically\na Euclidean (also known as geometric) vector. A vector is an entity\nthat has both magnitude and direction. The datatype, however, stores\nthe components of the vector (x, y for 2D, and x, y, z for 3D). The magnitude\nand direction can be accessed via the methods <a href=\"#/p5/mag\">mag()</a> and <a href=\"#/p5/heading\">heading()</a>.\n<br><br>\nIn many of the p5.js examples, you will see <a href=\"#/p5.Vector\">p5.Vector</a> used to describe a\nposition, velocity, or acceleration. For example, if you consider a rectangle\nmoving across the screen, at any given instant it has a position (a vector\nthat points from the origin to its location), a velocity (the rate at which\nthe object&#39;s position changes per time unit, expressed as a vector), and\nacceleration (the rate at which the object&#39;s velocity changes per time\nunit, expressed as a vector).\n<br><br>\nSince vectors represent groupings of values, we cannot simply use\ntraditional addition/multiplication/etc. Instead, we&#39;ll need to do some\n&quot;vector&quot; math, which is made easy by the methods inside the <a href=\"#/p5.Vector\">p5.Vector</a> class.</p>\n"
3783          },
3784          "Calculation": {
3785            "name": "Calculation",
3786            "submodules": {},
3787            "elements": {},
3788            "classes": {},
3789            "fors": {
3790              "p5": 1
3791            },
3792            "is_submodule": 1,
3793            "namespaces": {},
3794            "module": "Math",
3795            "namespace": "",
3796            "file": "src/math/calculation.js",
3797            "line": 1,
3798            "requires": ["core"]
3799          },
3800          "Noise": {
3801            "name": "Noise",
3802            "submodules": {},
3803            "elements": {},
3804            "classes": {},
3805            "fors": {
3806              "p5": 1
3807            },
3808            "is_submodule": 1,
3809            "namespaces": {},
3810            "module": "Math",
3811            "namespace": "",
3812            "file": "src/math/noise.js",
3813            "line": 14,
3814            "requires": ["core"]
3815          },
3816          "Random": {
3817            "name": "Random",
3818            "submodules": {},
3819            "elements": {},
3820            "classes": {},
3821            "fors": {
3822              "p5": 1
3823            },
3824            "is_submodule": 1,
3825            "namespaces": {},
3826            "module": "Math",
3827            "namespace": "",
3828            "file": "src/math/random.js",
3829            "line": 1,
3830            "requires": ["core"]
3831          },
3832          "Trigonometry": {
3833            "name": "Trigonometry",
3834            "submodules": {},
3835            "elements": {},
3836            "classes": {},
3837            "fors": {
3838              "p5": 1
3839            },
3840            "is_submodule": 1,
3841            "namespaces": {},
3842            "module": "Math",
3843            "namespace": "",
3844            "file": "src/math/trigonometry.js",
3845            "line": 1,
3846            "requires": ["core", "constants"]
3847          },
3848          "Typography": {
3849            "name": "Typography",
3850            "submodules": {
3851              "Attributes": 1,
3852              "Loading & Displaying": 1,
3853              "Font": 1
3854            },
3855            "elements": {},
3856            "classes": {
3857              "p5.Font": 1
3858            },
3859            "fors": {
3860              "p5": 1
3861            },
3862            "namespaces": {},
3863            "file": "src/typography/p5.Font.js",
3864            "line": 15
3865          },
3866          "Font": {
3867            "name": "Font",
3868            "submodules": {},
3869            "elements": {},
3870            "classes": {
3871              "p5.Font": 1
3872            },
3873            "fors": {},
3874            "is_submodule": 1,
3875            "namespaces": {},
3876            "module": "Typography",
3877            "namespace": "",
3878            "file": "src/typography/p5.Font.js",
3879            "line": 15,
3880            "description": "<p>This module defines the <a href=\"#/p5.Font\">p5.Font</a> class and functions for\ndrawing text to the display canvas.</p>\n",
3881            "requires": ["core", "constants"]
3882          },
3883          "Array Functions": {
3884            "name": "Array Functions",
3885            "submodules": {},
3886            "elements": {},
3887            "classes": {},
3888            "fors": {
3889              "p5": 1
3890            },
3891            "is_submodule": 1,
3892            "namespaces": {},
3893            "module": "Data",
3894            "namespace": "",
3895            "file": "src/utilities/array_functions.js",
3896            "line": 1,
3897            "requires": ["core"]
3898          },
3899          "Conversion": {
3900            "name": "Conversion",
3901            "submodules": {},
3902            "elements": {},
3903            "classes": {},
3904            "fors": {
3905              "p5": 1
3906            },
3907            "is_submodule": 1,
3908            "namespaces": {},
3909            "module": "Data",
3910            "namespace": "",
3911            "file": "src/utilities/conversion.js",
3912            "line": 1,
3913            "requires": ["core"]
3914          },
3915          "String Functions": {
3916            "name": "String Functions",
3917            "submodules": {},
3918            "elements": {},
3919            "classes": {},
3920            "fors": {
3921              "p5": 1
3922            },
3923            "is_submodule": 1,
3924            "namespaces": {},
3925            "module": "Data",
3926            "namespace": "",
3927            "file": "src/utilities/string_functions.js",
3928            "line": 1,
3929            "requires": ["core"]
3930          },
3931          "Time & Date": {
3932            "name": "Time & Date",
3933            "submodules": {},
3934            "elements": {},
3935            "classes": {},
3936            "fors": {
3937              "p5": 1
3938            },
3939            "is_submodule": 1,
3940            "namespaces": {},
3941            "module": "IO",
3942            "namespace": "",
3943            "file": "src/utilities/time_date.js",
3944            "line": 1,
3945            "requires": ["core"]
3946          },
3947          "3D Primitives": {
3948            "name": "3D Primitives",
3949            "submodules": {},
3950            "elements": {},
3951            "classes": {},
3952            "fors": {
3953              "p5": 1
3954            },
3955            "is_submodule": 1,
3956            "namespaces": {},
3957            "module": "Shape",
3958            "namespace": "",
3959            "file": "src/webgl/3d_primitives.js",
3960            "line": 1,
3961            "requires": ["core", "p5.Geometry"]
3962          },
3963          "Lights, Camera": {
3964            "name": "Lights, Camera",
3965            "submodules": {
3966              "Interaction": 1,
3967              "Lights": 1,
3968              "Material": 1,
3969              "Camera": 1,
3970              "Shaders": 1
3971            },
3972            "elements": {},
3973            "classes": {
3974              "p5.Camera": 1,
3975              "p5.Geometry": 1,
3976              "p5.Matrix": 1,
3977              "p5.Shader": 1,
3978              "p5.Texture": 1,
3979              "ImageInfos": 1,
3980              "FontInfo": 1,
3981              "Cubic": 1
3982            },
3983            "fors": {
3984              "p5": 1,
3985              "p5.Camera": 1
3986            },
3987            "namespaces": {},
3988            "file": "src/webgl/text.js",
3989            "line": 259
3990          },
3991          "Interaction": {
3992            "name": "Interaction",
3993            "submodules": {},
3994            "elements": {},
3995            "classes": {},
3996            "fors": {
3997              "p5": 1
3998            },
3999            "is_submodule": 1,
4000            "namespaces": {},
4001            "module": "Lights, Camera",
4002            "namespace": "",
4003            "file": "src/webgl/interaction.js",
4004            "line": 1,
4005            "requires": ["core"]
4006          },
4007          "Lights": {
4008            "name": "Lights",
4009            "submodules": {},
4010            "elements": {},
4011            "classes": {},
4012            "fors": {
4013              "p5": 1
4014            },
4015            "is_submodule": 1,
4016            "namespaces": {},
4017            "module": "Lights, Camera",
4018            "namespace": "",
4019            "file": "src/webgl/light.js",
4020            "line": 1,
4021            "requires": ["core"]
4022          },
4023          "3D Models": {
4024            "name": "3D Models",
4025            "submodules": {},
4026            "elements": {},
4027            "classes": {},
4028            "fors": {
4029              "p5": 1
4030            },
4031            "is_submodule": 1,
4032            "namespaces": {},
4033            "module": "Shape",
4034            "namespace": "",
4035            "file": "src/webgl/loading.js",
4036            "line": 1,
4037            "requires": ["core", "p5.Geometry"]
4038          },
4039          "Material": {
4040            "name": "Material",
4041            "submodules": {},
4042            "elements": {},
4043            "classes": {
4044              "p5.Texture": 1
4045            },
4046            "fors": {
4047              "p5": 1
4048            },
4049            "is_submodule": 1,
4050            "namespaces": {},
4051            "module": "Lights, Camera",
4052            "namespace": "",
4053            "file": "src/webgl/p5.Texture.js",
4054            "line": 14,
4055            "requires": ["core"],
4056            "description": "<p>This module defines the p5.Texture class</p>\n"
4057          },
4058          "Camera": {
4059            "name": "Camera",
4060            "submodules": {},
4061            "elements": {},
4062            "classes": {
4063              "p5.Camera": 1
4064            },
4065            "fors": {
4066              "p5": 1,
4067              "p5.Camera": 1
4068            },
4069            "is_submodule": 1,
4070            "namespaces": {},
4071            "module": "Lights, Camera",
4072            "namespace": "",
4073            "file": "src/webgl/p5.Camera.js",
4074            "line": 209,
4075            "requires": ["core"],
4076            "description": "<p>This class describes a camera for use in p5&#39;s\n<a href=\"https://github.com/processing/p5.js/wiki/Getting-started-with-WebGL-in-p5\">\nWebGL mode</a>. It contains camera position, orientation, and projection\ninformation necessary for rendering a 3D scene.</p>\n<p>New p5.Camera objects can be made through the\n<a href=\"#/p5/createCamera\">createCamera()</a> function and controlled through\nthe methods described below. A camera created in this way will use a default\nposition in the scene and a default perspective projection until these\nproperties are changed through the various methods available. It is possible\nto create multiple cameras, in which case the current camera\ncan be set through the <a href=\"#/p5/setCamera\">setCamera()</a> method.</p>\n<p>Note:\nThe methods below operate in two coordinate systems: the &#39;world&#39; coordinate\nsystem describe positions in terms of their relationship to the origin along\nthe X, Y and Z axes whereas the camera&#39;s &#39;local&#39; coordinate system\ndescribes positions from the camera&#39;s point of view: left-right, up-down,\nand forward-backward. The <a href=\"#/p5.Camera/move\">move()</a> method,\nfor instance, moves the camera along its own axes, whereas the\n<a href=\"#/p5.Camera/setPosition\">setPosition()</a>\nmethod sets the camera&#39;s position in world-space.</p>\n"
4077          },
4078          "Shaders": {
4079            "name": "Shaders",
4080            "submodules": {},
4081            "elements": {},
4082            "classes": {
4083              "p5.Shader": 1
4084            },
4085            "fors": {
4086              "p5": 1
4087            },
4088            "is_submodule": 1,
4089            "namespaces": {},
4090            "module": "Lights, Camera",
4091            "namespace": "",
4092            "file": "src/webgl/p5.Shader.js",
4093            "line": 13,
4094            "description": "<p>This module defines the p5.Shader class</p>\n",
4095            "requires": ["core"]
4096          },
4097          "p5.dom": {
4098            "name": "p5.dom",
4099            "submodules": {},
4100            "elements": {},
4101            "classes": {
4102              "p5.MediaElement": 1,
4103              "p5.File": 1
4104            },
4105            "fors": {
4106              "p5": 1,
4107              "p5.Element": 1
4108            },
4109            "namespaces": {},
4110            "module": "p5.dom",
4111            "file": "lib/addons/p5.dom.js",
4112            "line": 3170,
4113            "description": "<p><p>The web is much more than just canvas and p5.dom makes it easy to interact\nwith other HTML5 objects, including text, hyperlink, image, input, video,\naudio, and webcam.</p></p>\n<p><p>There is a set of creation methods, DOM manipulation methods, and\nan extended <a href=\"#/p5.Element\">p5.Element</a> that supports a range of HTML elements. See the\n<a href='https://github.com/processing/p5.js/wiki/Beyond-the-canvas'>\nbeyond the canvas tutorial</a> for a full overview of how this addon works.</p>\n<p><p>Methods and properties shown in black are part of the p5.js core, items in\nblue are part of the p5.dom library. You will need to include an extra file\nin order to access the blue functions. See the\n<a href='http://p5js.org/libraries/#using-a-library'>using a library</a>\nsection for information on how to include this library. p5.dom comes with\n<a href='http://p5js.org/download'>p5 complete</a> or you can download the single file\n<a href='https://raw.githubusercontent.com/lmccart/p5.js/master/lib/addons/p5.dom.js'>\nhere</a>.</p></p>\n<p><p>See <a href='https://github.com/processing/p5.js/wiki/Beyond-the-canvas'>tutorial: beyond the canvas</a>\nfor more info on how to use this library.</a></p>\n",
4114            "tag": "main",
4115            "itemtype": "main"
4116          },
4117          "p5.sound": {
4118            "name": "p5.sound",
4119            "submodules": {},
4120            "elements": {},
4121            "classes": {
4122              "p5.sound": 1,
4123              "p5.SoundFile": 1,
4124              "p5.Amplitude": 1,
4125              "p5.FFT": 1,
4126              "p5.Signal": 1,
4127              "p5.Oscillator": 1,
4128              "p5.SinOsc": 1,
4129              "p5.TriOsc": 1,
4130              "p5.SawOsc": 1,
4131              "p5.SqrOsc": 1,
4132              "p5.Envelope": 1,
4133              "p5.Pulse": 1,
4134              "p5.Noise": 1,
4135              "p5.AudioIn": 1,
4136              "p5.Effect": 1,
4137              "p5.Filter": 1,
4138              "p5.LowPass": 1,
4139              "p5.HighPass": 1,
4140              "p5.BandPass": 1,
4141              "p5.EQ": 1,
4142              "p5.Panner3D": 1,
4143              "p5.Delay": 1,
4144              "p5.Reverb": 1,
4145              "p5.Convolver": 1,
4146              "p5.Phrase": 1,
4147              "p5.Part": 1,
4148              "p5.Score": 1,
4149              "p5.SoundLoop": 1,
4150              "p5.Compressor": 1,
4151              "p5.SoundRecorder": 1,
4152              "p5.PeakDetect": 1,
4153              "p5.Gain": 1,
4154              "p5.AudioVoice": 1,
4155              "p5.MonoSynth": 1,
4156              "p5.PolySynth": 1,
4157              "p5.Distortion": 1
4158            },
4159            "fors": {
4160              "p5.sound": 1,
4161              "p5": 1
4162            },
4163            "namespaces": {},
4164            "module": "p5.sound",
4165            "file": "lib/addons/p5.sound.js",
4166            "line": 12761,
4167            "description": "<p>p5.sound extends p5 with <a href=\"http://caniuse.com/audio-api\"\ntarget=\"_blank\">Web Audio</a> functionality including audio input,\nplayback, analysis and synthesis.\n<br/><br/>\n<a href=\"#/p5.SoundFile\"><b>p5.SoundFile</b></a>: Load and play sound files.<br/>\n<a href=\"#/p5.Amplitude\"><b>p5.Amplitude</b></a>: Get the current volume of a sound.<br/>\n<a href=\"#/p5.AudioIn\"><b>p5.AudioIn</b></a>: Get sound from an input source, typically\n  a computer microphone.<br/>\n<a href=\"#/p5.FFT\"><b>p5.FFT</b></a>: Analyze the frequency of sound. Returns\n  results from the frequency spectrum or time domain (waveform).<br/>\n<a href=\"#/p5.Oscillator\"><b>p5.Oscillator</b></a>: Generate Sine,\n  Triangle, Square and Sawtooth waveforms. Base class of\n  
4167<a href=\"#/p5.Noise\">p5.Noise</a> and <a href=\"#/p5.Pulse\">p5.Pulse</a>.\n  <br/>\n<a href=\"#/p5.Envelope\"><b>p5.Envelope</b></a>: An Envelope is a series\n  of fades over time. Often used to control an object&#39;s\n  output gain level as an &quot;ADSR Envelope&quot; (Attack, Decay,\n  Sustain, Release). Can also modulate other parameters.<br/>\n<a href=\"#/p5.Delay\"><b>p5.Delay</b></a>: A delay effect with\n  parameters for feedback, delayTime, and lowpass filter.<br/>\n<a href=\"#/p5.Filter\"><b>p5.Filter</b></a>: Filter the frequency range of a\n  sound.\n<br/>\n<a href=\"#/p5.Reverb\"><b>p5.Reverb</b></a>: Add reverb to a sound by specifying\n  duration and decay. <br/>\n<b><a href=\"#/p5.Convolver\">p5.Convolver</a>:</b> Extends\n<a href=\"#/p5.Reverb\">p5.Reverb</a> to simulate the sound of real\n  physical spaces through convolution.<br/>\n<b><a href=\"#/p5.SoundRecorder\">p5.SoundRecorder</a></b>: Record sound for playback\n  / save the .wav file.\n<b><a href=\"#/p5.Phrase\">p5.Phrase</a></b>, <b><a href=\"#/p5.Part\">p5.Part</a></b> and\n<b><a href=\"#/p5.Score\">p5.Score</a></b>: Compose musical sequences.\n<br/><br/>\np5.sound is on <a href=\"https://github.com/therewasaguy/p5.sound/\">GitHub</a>.\nDownload the latest version\n<a href=\"https://github.com/therewasaguy/p5.sound/blob/master/lib/p5.sound.js\">here</a>.</p>\n",
4168            "tag": "main",
4169            "itemtype": "main"
4170          }
4171        },
4172        "classes": {
4173          "p5": {
4174            "name": "p5",
4175            "shortname": "p5",
4176            "classitems": [],
4177            "plugins": [],
4178            "extensions": [],
4179            "plugin_for": [],
4180            "extension_for": [],
4181            "module": "IO",
4182            "submodule": "Output",
4183            "namespace": "",
4184            "file": "src/core/main.js",
4185            "line": 15,
4186            "description": "<p>This is the p5 instance constructor.</p>\n<p>A p5 instance holds all the properties and methods related to\na p5 sketch.  It expects an incoming sketch closure and it can also\ntake an optional node parameter for attaching the generated p5 canvas\nto a node.  The sketch closure takes the newly created p5 instance as\nits sole argument and may optionally set <a href=\"#/p5/preload\">preload()</a>, <a href=\"#/p5/setup\">setup()</a>, and/or\n<a href=\"#/p5/draw\">draw()</a> properties on it for running a sketch.</p>\n<p>A p5 sketch can run in &quot;global&quot; or &quot;instance&quot; mode:\n&quot;global&quot;   - all properties and methods are attached to the window\n&quot;instance&quot; - all properties and methods are bound to this p5 object</p>\n",
4187            "is_constructor": 1,
4188            "params": [{
4189              "name": "sketch",
4190              "description": "<p>a closure that can set optional <a href=\"#/p5/preload\">preload()</a>,\n                             <a href=\"#/p5/setup\">setup()</a>, and/or <a href=\"#/p5/draw\">draw()</a> properties on the\n                             given p5 instance</p>\n",
4191              "type": "Function"
4192            }, {
4193              "name": "node",
4194              "description": "<p>element to attach canvas to, if a\n                                     boolean is passed in use it as sync</p>\n",
4195              "type": "HTMLElement|Boolean",
4196              "optional": true
4197            }, {
4198              "name": "sync",
4199              "description": "<p>start synchronously (optional)</p>\n",
4200              "type": "Boolean",
4201              "optional": true
4202            }],
4203            "return": {
4204              "description": "a p5 instance",
4205              "type": "P5"
4206            }
4207          },
4208          "p5.Color": {
4209            "name": "p5.Color",
4210            "shortname": "p5.Color",
4211            "classitems": [],
4212            "plugins": [],
4213            "extensions": [],
4214            "plugin_for": [],
4215            "extension_for": [],
4216            "module": "Color",
4217            "submodule": "Creating & Reading",
4218            "namespace": "",
4219            "file": "src/color/p5.Color.js",
4220            "line": 16,
4221            "description": "<p>Each color stores the color mode and level maxes that applied at the\ntime of its construction. These are used to interpret the input arguments\n(at construction and later for that instance of color) and to format the\noutput e.g. when <a href=\"#/p5/saturation\">saturation()</a> is requested.</p>\n<p>Internally we store an array representing the ideal RGBA values in floating\npoint form, normalized from 0 to 1. From this we calculate the closest\nscreen color (RGBA levels from 0 to 255) and expose this to the renderer.</p>\n<p>We also cache normalized, floating point components of the color in various\nrepresentations as they are calculated. This is done to prevent repeating a\nconversion that has already been performed.</p>\n"
4222          },
4223          "p5.Element": {
4224            "name": "p5.Element",
4225            "shortname": "p5.Element",
4226            "classitems": [],
4227            "plugins": [],
4228            "extensions": [],
4229            "plugin_for": [],
4230            "extension_for": [],
4231            "module": "DOM",
4232            "submodule": "DOM",
4233            "namespace": "",
4234            "file": "src/core/p5.Element.js",
4235            "line": 11,
4236            "description": "<p>Base class for all elements added to a sketch, including canvas,\ngraphics buffers, and other HTML elements. Methods in blue are\nincluded in the core functionality, methods in brown are added\nwith the <a href=\"http://p5js.org/reference/#/libraries/p5.dom\">p5.dom\nlibrary</a>.\nIt is not called directly, but <a href=\"#/p5.Element\">p5.Element</a>\nobjects are created by calling <a href=\"#/p5/createCanvas\">createCanvas</a>, <a href=\"#/p5/createGraphics\">createGraphics</a>,\nor in the p5.dom library, <a href=\"#/p5/createDiv\">createDiv</a>, <a href=\"#/p5/createImg\">createImg</a>, <a href=\"#/p5/createInput\">createInput</a>, etc.</p>\n",
4237            "params": [{
4238              "name": "elt",
4239              "description": "<p>DOM node that is wrapped</p>\n",
4240              "type": "String"
4241            }, {
4242              "name": "pInst",
4243              "description": "<p>pointer to p5 instance</p>\n",
4244              "type": "P5",
4245              "optional": true
4246            }]
4247          },
4248          "p5.Graphics": {
4249            "name": "p5.Graphics",
4250            "shortname": "p5.Graphics",
4251            "classitems": [],
4252            "plugins": [],
4253            "extensions": [],
4254            "plugin_for": [],
4255            "extension_for": [],
4256            "module": "Rendering",
4257            "submodule": "Rendering",
4258            "namespace": "",
4259            "file": "src/core/p5.Graphics.js",
4260            "line": 12,
4261            "description": "<p>Thin wrapper around a renderer, to be used for creating a\ngraphics buffer object. Use this class if you need\nto draw into an off-screen graphics buffer. The two parameters define the\nwidth and height in pixels. The fields and methods for this class are\nextensive, but mirror the normal drawing API for p5.</p>\n",
4262            "extends": "p5.Element",
4263            "params": [{
4264              "name": "w",
4265              "description": "<p>width</p>\n",
4266              "type": "Number"
4267            }, {
4268              "name": "h",
4269              "description": "<p>height</p>\n",
4270              "type": "Number"
4271            }, {
4272              "name": "renderer",
4273              "description": "<p>the renderer to use, either P2D or WEBGL</p>\n",
4274              "type": "Constant"
4275            }, {
4276              "name": "pInst",
4277              "description": "<p>pointer to p5 instance</p>\n",
4278              "type": "P5",
4279              "optional": true
4280            }]
4281          },
4282          "p5.Renderer": {
4283            "name": "p5.Renderer",
4284            "shortname": "p5.Renderer",
4285            "classitems": [],
4286            "plugins": [],
4287            "extensions": [],
4288            "plugin_for": [],
4289            "extension_for": [],
4290            "module": "Rendering",
4291            "submodule": "Rendering",
4292            "namespace": "",
4293            "file": "src/core/p5.Renderer.js",
4294            "line": 12,
4295            "description": "<p>Main graphics and rendering context, as well as the base API\nimplementation for p5.js &quot;core&quot;. To be used as the superclass for\nRenderer2D and Renderer3D classes, respecitvely.</p>\n",
4296            "is_constructor": 1,
4297            "extends": "p5.Element",
4298            "params": [{
4299              "name": "elt",
4300              "description": "<p>DOM node that is wrapped</p>\n",
4301              "type": "String"
4302            }, {
4303              "name": "pInst",
4304              "description": "<p>pointer to p5 instance</p>\n",
4305              "type": "P5",
4306              "optional": true
4307            }, {
4308              "name": "isMainCanvas",
4309              "description": "<p>whether we&#39;re using it as main canvas</p>\n",
4310              "type": "Boolean",
4311              "optional": true
4312            }]
4313          },
4314          "p5.TypedDict": {
4315            "name": "p5.TypedDict",
4316            "shortname": "p5.TypedDict",
4317            "classitems": [],
4318            "plugins": [],
4319            "extensions": [],
4320            "plugin_for": [],
4321            "extension_for": [],
4322            "module": "Data",
4323            "submodule": "Dictionary",
4324            "namespace": "",
4325            "file": "src/data/p5.TypedDict.js",
4326            "line": 84,
4327            "description": "<p>Base class for all p5.Dictionary types. Specifically\n typed Dictionary classes inherit from this class.</p>\n"
4328          },
4329          "p5.StringDict": {
4330            "name": "p5.StringDict",
4331            "shortname": "p5.StringDict",
4332            "classitems": [],
4333            "plugins": [],
4334            "extensions": [],
4335            "plugin_for": [],
4336            "extension_for": [],
4337            "module": "Data",
4338            "submodule": "Dictionary",
4339            "namespace": "",
4340            "file": "src/data/p5.TypedDict.js",
4341            "line": 403,
4342            "description": "<p>A simple Dictionary class for Strings.</p>\n",
4343            "extends": "p5.TypedDict"
4344          },
4345          "p5.NumberDict": {
4346            "name": "p5.NumberDict",
4347            "shortname": "p5.NumberDict",
4348            "classitems": [],
4349            "plugins": [],
4350            "extensions": [],
4351            "plugin_for": [],
4352            "extension_for": [],
4353            "module": "Data",
4354            "submodule": "Dictionary",
4355            "namespace": "",
4356            "file": "src/data/p5.TypedDict.js",
4357            "line": 422,
4358            "description": "<p>A simple Dictionary class for Numbers.</p>\n",
4359            "extends": "p5.TypedDict"
4360          },
4361          "p5.Image": {
4362            "name": "p5.Image",
4363            "shortname": "p5.Image",
4364            "classitems": [],
4365            "plugins": [],
4366            "extensions": [],
4367            "plugin_for": [],
4368            "extension_for": [],
4369            "module": "Image",
4370            "submodule": "Image",
4371            "namespace": "",
4372            "file": "src/image/p5.Image.js",
4373            "line": 23,
4374            "description": "<p>Creates a new <a href=\"#/p5.Image\">p5.Image</a>. A <a href=\"#/p5.Image\">p5.Image</a> is a canvas backed representation of an\nimage.\n<br><br>\np5 can display .gif, .jpg and .png images. Images may be displayed\nin 2D and 3D space. Before an image is used, it must be loaded with the\n<a href=\"#/p5/loadImage\">loadImage()</a> function. The <a href=\"#/p5.Image\">p5.Image</a> class contains fields for the width and\nheight of the image, as well as an array called <a href=\"#/p5.Image/pixels\">pixels[]</a> that contains the\nvalues for every pixel in the image.\n<br><br>\nThe methods described below allow easy access to the image&#39;s pixels and\nalpha channel and simplify the process of compositing.\n<br><br>\nBefore using the <a href=\"#/p5.Image/pixels\">pixels[]</a> array, be sure to use the <a href=\"#/p5.Image/loadPixels\">loadPixels()</a> method on\nthe image to make sure that the pixel data is properly loaded.</p>\n",
4375            "example": ["\n<div><code>\nfunction setup() {\n  let img = createImage(100, 100); // same as new p5.Image(100, 100);\n  img.loadPixels();\n  createCanvas(100, 100);\n  background(0);\n\n  // helper for writing color to array\n  function writeColor(image, x, y, red, green, blue, alpha) {\n    let index = (x + y * width) * 4;\n    image.pixels[index] = red;\n    image.pixels[index + 1] = green;\n    image.pixels[index + 2] = blue;\n    image.pixels[index + 3] = alpha;\n  }\n\n  let x, y;\n  // fill with random colors\n  for (y = 0; y < img.height; y++) {\n    for (x = 0; x < img.width; x++) {\n      let red = random(255);\n      let green = random(255);\n      let blue = random(255);\n      let alpha = 255;\n      writeColor(img, x, y, red, green, blue, alpha);\n    }\n  }\n\n  // draw a red line\n  y = 0;\n  for (x = 0; x < img.width; x++) {\n    writeColor(img, x, y, 255, 0, 0, 255);\n  }\n\n  // draw a green line\n  y = img.height - 1;\n  for (x = 0; x < img.width; x++) {\n    writeColor(img, x, y, 0, 255, 0, 255);\n  }\n\n  img.updatePixels();\n  image(img, 0, 0);\n}\n</code></div>"],
4376            "params": [{
4377              "name": "width",
4378              "description": "",
4379              "type": "Number"
4380            }, {
4381              "name": "height",
4382              "description": "",
4383              "type": "Number"
4384            }]
4385          },
4386          "p5.PrintWriter": {
4387            "name": "p5.PrintWriter",
4388            "shortname": "p5.PrintWriter",
4389            "classitems": [],
4390            "plugins": [],
4391            "extensions": [],
4392            "plugin_for": [],
4393            "extension_for": [],
4394            "module": "IO",
4395            "submodule": "Output",
4396            "namespace": "",
4397            "file": "src/io/files.js",
4398            "line": 1228,
4399            "params": [{
4400              "name": "filename",
4401              "description": "",
4402              "type": "String"
4403            }, {
4404              "name": "extension",
4405              "description": "",
4406              "type": "String",
4407              "optional": true
4408            }]
4409          },
4410          "p5.Table": {
4411            "name": "p5.Table",
4412            "shortname": "p5.Table",
4413            "classitems": [],
4414            "plugins": [],
4415            "extensions": [],
4416            "plugin_for": [],
4417            "extension_for": [],
4418            "module": "IO",
4419            "submodule": "Table",
4420            "namespace": "",
4421            "file": "src/io/p5.Table.js",
4422            "line": 35,
4423            "description": "<p><a href=\"#/p5.Table\">Table</a> objects store data with multiple rows and columns, much\nlike in a traditional spreadsheet. Tables can be generated from\nscratch, dynamically, or using data from an existing file.</p>\n",
4424            "is_constructor": 1,
4425            "params": [{
4426              "name": "rows",
4427              "description": "<p>An array of p5.TableRow objects</p>\n",
4428              "type": "p5.TableRow[]",
4429              "optional": true
4430            }]
4431          },
4432          "p5.TableRow": {
4433            "name": "p5.TableRow",
4434            "shortname": "p5.TableRow",
4435            "classitems": [],
4436            "plugins": [],
4437            "extensions": [],
4438            "plugin_for": [],
4439            "extension_for": [],
4440            "module": "IO",
4441            "submodule": "Table",
4442            "namespace": "",
4443            "file": "src/io/p5.TableRow.js",
4444            "line": 11,
4445            "description": "<p>A TableRow object represents a single row of data values,\nstored in columns, from a table.</p>\n<p>A Table Row contains both an ordered array, and an unordered\nJSON object.</p>\n",
4446            "is_constructor": 1,
4447            "params": [{
4448              "name": "str",
4449              "description": "<p>optional: populate the row with a\n                            string of values, separated by the\n                            separator</p>\n",
4450              "type": "String",
4451              "optional": true
4452            }, {
4453              "name": "separator",
4454              "description": "<p>comma separated values (csv) by default</p>\n",
4455              "type": "String",
4456              "optional": true
4457            }]
4458          },
4459          "p5.XML": {
4460            "name": "p5.XML",
4461            "shortname": "p5.XML",
4462            "classitems": [],
4463            "plugins": [],
4464            "extensions": [],
4465            "plugin_for": [],
4466            "extension_for": [],
4467            "module": "IO",
4468            "submodule": "XML",
4469            "namespace": "",
4470            "file": "src/io/p5.XML.js",
4471            "line": 11,
4472            "description": "<p>XML is a representation of an XML object, able to parse XML code. Use\n<a href=\"#/p5/loadXML\">loadXML()</a> to load external XML files and create XML objects.</p>\n",
4473            "is_constructor": 1,
4474            "example": ["\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let children = xml.getChildren('animal');\n\n  for (let i = 0; i < children.length; i++) {\n    let id = children[i].getNum('id');
4474\n    let coloring = children[i].getString('species');\n    let name = children[i].getContent();\n    print(id + ', ' + coloring + ', ' + name);\n  }\n}\n\n// Sketch prints:\n// 0, Capra hircus, Goat\n// 1, Panthera pardus, Leopard\n// 2, Equus zebra, Zebra\n</code></div>"],
4475            "alt": "no image displayed"
4476          },
4477          "p5.Vector": {
4478            "name": "p5.Vector",
4479            "shortname": "p5.Vector",
4480            "classitems": [],
4481            "plugins": [],
4482            "extensions": [],
4483            "plugin_for": [],
4484            "extension_for": [],
4485            "module": "Math",
4486            "submodule": "Math",
4487            "namespace": "",
4488            "file": "src/math/p5.Vector.js",
4489            "line": 12,
4490            "description": "<p>A class to describe a two or three dimensional vector, specifically\na Euclidean (also known as geometric) vector. A vector is an entity\nthat has both magnitude and direction. The datatype, however, stores\nthe components of the vector (x, y for 2D, and x, y, z for 3D). The magnitude\nand direction can be accessed via the methods <a href=\"#/p5/mag\">mag()</a> and <a href=\"#/p5/heading\">heading()</a>.\n<br><br>\nIn many of the p5.js examples, you will see <a href=\"#/p5.Vector\">p5.Vector</a> used to describe a\nposition, velocity, or acceleration. For example, if you consider a rectangle\nmoving across the screen, at any given instant it has a position (a vector\nthat points from the origin to its location), a velocity (the rate at which\nthe object&#39;s position changes per time unit, expressed as a vector), and\nacceleration (the rate at which the object&#39;s velocity changes per time\nunit, expressed as a vector).\n<br><br>\nSince vectors represent groupings of values, we cannot simply use\ntraditional addition/multiplication/etc. Instead, we&#39;ll need to do some\n&quot;vector&quot; math, which is made easy by the methods inside the <a href=\"#/p5.Vector\">p5.Vector</a> class.</p>\n",
4491            "params": [{
4492              "name": "x",
4493              "description": "<p>x component of the vector</p>\n",
4494              "type": "Number",
4495              "optional": true
4496            }, {
4497              "name": "y",
4498              "description": "<p>y component of the vector</p>\n",
4499              "type": "Number",
4500              "optional": true
4501            }, {
4502              "name": "z",
4503              "description": "<p>z component of the vector</p>\n",
4504              "type": "Number",
4505              "optional": true
4506            }],
4507            "example": ["\n<div>\n<code>\nlet v1 = createVector(40, 50);\nlet v2 = createVector(40, 50);\n\nellipse(v1.x, v1.y, 50, 50);\nellipse(v2.x, v2.y, 50, 50);\nv1.add(v2);\nellipse(v1.x, v1.y, 50, 50);\n</code>\n</div>"],
4508            "alt": "2 white ellipses. One center-left the other bottom right and off canvas"
4509          },
4510          "p5.Font": {
4511            "name": "p5.Font",
4512            "shortname": "p5.Font",
4513            "classitems": [],
4514            "plugins": [],
4515            "extensions": [],
4516            "plugin_for": [],
4517            "extension_for": [],
4518            "module": "Typography",
4519            "submodule": "Font",
4520            "namespace": "",
4521            "file": "src/typography/p5.Font.js",
4522            "line": 15,
4523            "description": "<p>Base class for font handling</p>\n",
4524            "params": [{
4525              "name": "pInst",
4526              "description": "<p>pointer to p5 instance</p>\n",
4527              "type": "P5",
4528              "optional": true
4529            }]
4530          },
4531          "p5.Camera": {
4532            "name": "p5.Camera",
4533            "shortname": "p5.Camera",
4534            "classitems": [],
4535            "plugins": [],
4536            "extensions": [],
4537            "plugin_for": [],
4538            "extension_for": [],
4539            "module": "Lights, Camera",
4540            "submodule": "Camera",
4541            "namespace": "",
4542            "file": "src/webgl/p5.Camera.js",
4543            "line": 209,
4544            "description": "<p>This class describes a camera for use in p5&#39;s\n<a href=\"https://github.com/processing/p5.js/wiki/Getting-started-with-WebGL-in-p5\">\nWebGL mode</a>. It contains camera position, orientation, and projection\ninformation necessary for rendering a 3D scene.</p>\n<p>New p5.Camera objects can be made through the\n<a href=\"#/p5/createCamera\">createCamera()</a> function and controlled through\nthe methods described below. A camera created in this way will use a default\nposition in the scene and a default perspective projection until these\nproperties are changed through the various methods available. It is possible\nto create multiple cameras, in which case the current camera\ncan be set through the <a href=\"#/p5/setCamera\">setCamera()</a> method.</p>\n<p>Note:\nThe methods below operate in two coordinate systems: the &#39;world&#39; coordinate\nsystem describe positions in terms of their relationship to the origin along\nthe X, Y and Z axes whereas the camera&#39;s &#39;local&#39; coordinate system\ndescribes positions from the camera&#39;s point of view: left-right, up-down,\nand forward-backward. The <a href=\"#/p5.Camera/move\">move()</a> method,\nfor instance, moves the camera along its own axes, whereas the\n<a href=\"#/p5.Camera/setPosition\">setPosition()</a>\nmethod sets the camera&#39;s position in world-space.</p>\n",
4545            "params": [{
4546              "name": "rendererGL",
4547              "description": "<p>instance of WebGL renderer</p>\n",
4548              "type": "RendererGL"
4549            }],
4550            "example": ["\n<div>\n<code>\nlet cam;\nlet delta = 0.01;\n\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  normalMaterial();\n  cam = createCamera();\n  // set initial pan angle\n  cam.pan(-0.8);\n}\n\nfunction draw() {\n  background(200);\n\n  // pan camera according to angle 'delta'\n  cam.pan(delta);\n\n  // every 160 frames, switch direction\n  if (frameCount % 160 === 0) {\n    delta *= -1;\n  }\n\n  rotateX(frameCount * 0.01);\n  translate(-100, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n}\n</code>\n</div>"],
4551            "alt": "camera view pans left and right across a series of rotating 3D boxes."
4552          },
4553          "p5.Geometry": {
4554            "name": "p5.Geometry",
4555            "shortname": "p5.Geometry",
4556            "classitems": [],
4557            "plugins": [],
4558            "extensions": [],
4559            "plugin_for": [],
4560            "extension_for": [],
4561            "module": "Lights, Camera",
4562            "namespace": "",
4563            "file": "src/webgl/p5.Geometry.js",
4564            "line": 6,
4565            "description": "<p>p5 Geometry class</p>\n",
4566            "is_constructor": 1,
4567            "params": [{
4568              "name": "detailX",
4569              "description": "<p>number of vertices on horizontal surface</p>\n",
4570              "type": "Integer",
4571              "optional": true
4572            }, {
4573              "name": "detailY",
4574              "description": "<p>number of vertices on horizontal surface</p>\n",
4575              "type": "Integer",
4576              "optional": true
4577            }, {
4578              "name": "callback",
4579              "description": "<p>function to call upon object instantiation.</p>\n",
4580              "type": "Function",
4581              "optional": true
4582            }]
4583          },
4584          "p5.Shader": {
4585            "name": "p5.Shader",
4586            "shortname": "p5.Shader",
4587            "classitems": [],
4588            "plugins": [],
4589            "extensions": [],
4590            "plugin_for": [],
4591            "extension_for": [],
4592            "module": "Lights, Camera",
4593            "submodule": "Shaders",
4594            "namespace": "",
4595            "file": "src/webgl/p5.Shader.js",
4596            "line": 13,
4597            "description": "<p>Shader class for WEBGL Mode</p>\n",
4598            "params": [{
4599              "name": "renderer",
4600              "description": "<p>an instance of p5.RendererGL that\nwill provide the GL context for this new p5.Shader</p>\n",
4601              "type": "p5.RendererGL"
4602            }, {
4603              "name": "vertSrc",
4604              "description": "<p>source code for the vertex shader (as a string)</p>\n",
4605              "type": "String"
4606            }, {
4607              "name": "fragSrc",
4608              "description": "<p>source code for the fragment shader (as a string)</p>\n",
4609              "type": "String"
4610            }]
4611          },
4612          "p5.MediaElement": {
4613            "name": "p5.MediaElement",
4614            "shortname": "p5.MediaElement",
4615            "classitems": [],
4616            "plugins": [],
4617            "extensions": [],
4618            "plugin_for": [],
4619            "extension_for": [],
4620            "module": "p5.dom",
4621            "submodule": "p5.dom",
4622            "namespace": "",
4623            "file": "lib/addons/p5.dom.js",
4624            "line": 2062,
4625            "description": "<p>Extends <a href=\"#/p5.Element\">p5.Element</a> to handle audio and video. In addition to the methods\nof <a href=\"#/p5.Element\">p5.Element</a>, it also contains methods for controlling media. It is not\ncalled directly, but <a href=\"#/p5.MediaElement\">p5.MediaElement</a>s are created by calling <a href=\"#/p5/createVideo\">createVideo</a>,\n<a href=\"#/p5/createAudio\">createAudio</a>, and <a href=\"#/p5/createCapture\">createCapture</a>.</p>\n",
4626            "is_constructor": 1,
4627            "params": [{
4628              "name": "elt",
4629              "description": "<p>DOM node that is wrapped</p>\n",
4630              "type": "String"
4631            }]
4632          },
4633          "p5.File": {
4634            "name": "p5.File",
4635            "shortname": "p5.File",
4636            "classitems": [],
4637            "plugins": [],
4638            "extensions": [],
4639            "plugin_for": [],
4640            "extension_for": [],
4641            "module": "p5.dom",
4642            "submodule": "p5.dom",
4643            "namespace": "",
4644            "file": "lib/addons/p5.dom.js",
4645            "line": 3170,
4646            "description": "<p>Base class for a file\nUsing this for createFileInput</p>\n",
4647            "is_constructor": 1,
4648            "params": [{
4649              "name": "file",
4650              "description": "<p>File that is wrapped</p>\n",
4651              "type": "File"
4652            }]
4653          },
4654          "p5.sound": {
4655            "name": "p5.sound",
4656            "shortname": "p5.sound",
4657            "classitems": [],
4658            "plugins": [],
4659            "extensions": [],
4660            "plugin_for": [],
4661            "extension_for": [],
4662            "module": "p5.sound",
4663            "submodule": "p5.sound",
4664            "namespace": ""
4665          },
4666          "p5.SoundFile": {
4667            "name": "p5.SoundFile",
4668            "shortname": "p5.SoundFile",
4669            "classitems": [],
4670            "plugins": [],
4671            "extensions": [],
4672            "plugin_for": [],
4673            "extension_for": [],
4674            "module": "p5.sound",
4675            "submodule": "p5.sound",
4676            "namespace": "",
4677            "file": "lib/addons/p5.sound.js",
4678            "line": 1005,
4679            "description": "<p>SoundFile object with a path to a file.</p>\n\n<p>The p5.SoundFile may not be available immediately because\nit loads the file information asynchronously.</p>\n\n<p>To do something with the sound as soon as it loads\npass the name of a function as the second parameter.</p>\n\n<p>Only one file path is required. However, audio file formats\n(i.e. mp3, ogg, wav and m4a/aac) are not supported by all\nweb browsers. If you want to ensure compatability, instead of a single\nfile path, you may include an Array of filepaths, and the browser will\nchoose a format that works.</p>",
4680            "is_constructor": 1,
4681            "params": [{
4682              "name": "path",
4683              "description": "<p>path to a sound file (String). Optionally,\n                             you may include multiple file formats in\n                             an array. Alternately, accepts an object\n                             from the HTML5 File API, or a p5.File.</p>\n",
4684              "type": "String|Array"
4685            }, {
4686              "name": "successCallback",
4687              "description": "<p>Name of a function to call once file loads</p>\n",
4688              "type": "Function",
4689              "optional": true
4690            }, {
4691              "name": "errorCallback",
4692              "description": "<p>Name of a function to call if file fails to\n                                    load. This function will receive an error or\n                                   XMLHttpRequest object with information\n                                   about what went wrong.</p>\n",
4693              "type": "Function",
4694              "optional": true
4695            }, {
4696              "name": "whileLoadingCallback",
4697              "description": "<p>Name of a function to call while file\n                                           is loading. That function will\n                                           receive progress of the request to\n                                           load the sound file\n                                           (between 0 and 1) as its first\n                                           parameter. This progress\n                                           does not account for the additional\n                                           time needed to decode the audio data.</p>\n",
4698              "type": "Function",
4699              "optional": true
4700            }],
4701            "example": ["\n<div><code>\n\nfunction preload() {\n  soundFormats('mp3', 'ogg');\n  mySound = loadSound('assets/doorbell.mp3');\n}\n\nfunction setup() {\n  mySound.setVolume(0.1);\n  mySound.play();\n}\n\n </code></div>"]
4702          },
4703          "p5.Amplitude": {
4704            "name": "p5.Amplitude",
4705            "shortname": "p5.Amplitude",
4706            "classitems": [],
4707            "plugins": [],
4708            "extensions": [],
4709            "plugin_for": [],
4710            "extension_for": [],
4711            "module": "p5.sound",
4712            "submodule": "p5.sound",
4713            "namespace": "",
4714            "file": "lib/addons/p5.sound.js",
4715            "line": 2533,
4716            "description": "<p>Amplitude measures volume between 0.0 and 1.0.\nListens to all p5sound by default, or use setInput()\nto listen to a specific sound source. Accepts an optional\nsmoothing value, which defaults to 0.</p>\n",
4717            "is_constructor": 1,
4718            "params": [{
4719              "name": "smoothing",
4720              "description": "<p>between 0.0 and .999 to smooth\n                           amplitude readings (defaults to 0)</p>\n",
4721              "type": "Number",
4722              "optional": true
4723            }],
4724            "example": ["\n<div><code>\nvar sound, amplitude, cnv;\n\nfunction preload(){\n  sound = loadSound('assets/beat.mp3');\n}\nfunction setup() {\n  cnv = createCanvas(100,100);\n  amplitude = new p5.Amplitude();\n\n  // start / stop the sound when canvas is clicked\n  cnv.mouseClicked(function() {\
4724n    if (sound.isPlaying() ){\n      sound.stop();\n    } else {\n      sound.play();\n    }\n  });\n}\nfunction draw() {\n  background(0);\n  fill(255);\n  var level = amplitude.getLevel();\n  var size = map(level, 0, 1, 0, 200);\n  ellipse(width/2, height/2, size, size);\n}\n\n</code></div>"]
4725          },
4726          "p5.FFT": {
4727            "name": "p5.FFT",
4728            "shortname": "p5.FFT",
4729            "classitems": [],
4730            "plugins": [],
4731            "extensions": [],
4732            "plugin_for": [],
4733            "extension_for": [],
4734            "module": "p5.sound",
4735            "submodule": "p5.sound",
4736            "namespace": "",
4737            "file": "lib/addons/p5.sound.js",
4738            "line": 2812,
4739            "description": "<p>FFT (Fast Fourier Transform) is an analysis algorithm that\nisolates individual\n<a href=\"https://en.wikipedia.org/wiki/Audio_frequency\">\naudio frequencies</a> within a waveform.</p>\n\n<p>Once instantiated, a p5.FFT object can return an array based on\ntwo types of analyses: <br> • <code>FFT.waveform()</code> computes\namplitude values along the time domain. The array indices correspond\nto samples across a brief moment in time. Each value represents\namplitude of the waveform at that sample of time.<br>\n• <code>FFT.analyze() </code> computes amplitude values along the\nfrequency domain. The array indices correspond to frequencies (i.e.\npitches), from the lowest to the highest that humans can hear. Each\nvalue represents amplitude at that slice of the frequency spectrum.\nUse with <code>getEnergy()</code> to measure amplitude at specific\nfrequencies, or within a range of frequencies. </p>\n\n<p>FFT analyzes a very short snapshot of sound called a sample\nbuffer. It returns an array of amplitude measurements, referred\nto as <code>bins</code>. The array is 1024 bins long by default.\nYou can change the bin array length, but it must be a power of 2\nbetween 16 and 1024 in order for the FFT algorithm to function\ncorrectly. The actual size of the FFT buffer is twice the\nnumber of bins, so given a standard sample rate, the buffer is\n2048/44100 seconds long.</p>",
4740            "is_constructor": 1,
4741            "params": [{
4742              "name": "smoothing",
4743              "description": "<p>Smooth results of Freq Spectrum.\n                              0.0 &lt; smoothing &lt; 1.0.\n                              Defaults to 0.8.</p>\n",
4744              "type": "Number",
4745              "optional": true
4746            }, {
4747              "name": "bins",
4748              "description": "<p>Length of resulting array.\n                          Must be a power of two between\n                          16 and 1024. Defaults to 1024.</p>\n",
4749              "type": "Number",
4750              "optional": true
4751            }],
4752            "example": ["\n<div><code>\nfunction preload(){\n  sound = loadSound('assets/Damscray_DancingTiger.mp3');\n}\n\nfunction setup(){\n  var cnv = createCanvas(100,100);\n  cnv.mouseClicked(togglePlay);\n  fft = new p5.FFT();\n  sound.amp(0.2);\n}\n\nfunction draw(){\n  background(0);\n\n  var spectrum = fft.analyze();\n  noStroke();\n  fill(0,255,0); // spectrum is green\n  for (var i = 0; i< spectrum.length; i++){\n    var x = map(i, 0, spectrum.length, 0, width);\n    var h = -height + map(spectrum[i], 0, 255, height, 0);\n    rect(x, height, width / spectrum.length, h )\n  }\n\n  var waveform = fft.waveform();\n  noFill();\n  beginShape();\n  stroke(255,0,0); // waveform is red\n  strokeWeight(1);\n  for (var i = 0; i< waveform.length; i++){\n    var x = map(i, 0, waveform.length, 0, width);\n    var y = map( waveform[i], -1, 1, 0, height);\n    vertex(x,y);\n  }\n  endShape();\n\n  text('click to play/pause', 4, 10);\n}\n\n// fade sound if mouse is over canvas\nfunction togglePlay() {\n  if (sound.isPlaying()) {\n    sound.pause();\n  } else {\n    sound.loop();\n  }\n}\n</code></div>"]
4753          },
4754          "p5.Signal": {
4755            "name": "p5.Signal",
4756            "shortname": "p5.Signal",
4757            "classitems": [],
4758            "plugins": [],
4759            "extensions": [],
4760            "plugin_for": [],
4761            "extension_for": [],
4762            "module": "p5.sound",
4763            "submodule": "p5.sound",
4764            "namespace": "",
4765            "file": "lib/addons/p5.sound.js",
4766            "line": 5215,
4767            "description": "<p>p5.Signal is a constant audio-rate signal used by p5.Oscillator\nand p5.Envelope for modulation math.</p>\n\n<p>This is necessary because Web Audio is processed on a seprate clock.\nFor example, the p5 draw loop runs about 60 times per second. But\nthe audio clock must process samples 44100 times per second. If we\nwant to add a value to each of those samples, we can&#39;t do it in the\ndraw loop, but we can do it by adding a constant-rate audio signal.&lt;/p.\n\n<p>This class mostly functions behind the scenes in p5.sound, and returns\na Tone.Signal from the Tone.js library by Yotam Mann.\nIf you want to work directly with audio signals for modular\nsynthesis, check out\n<a href='http://bit.ly/1oIoEng' target=_'blank'>tone.js.</a></p>",
4768            "is_constructor": 1,
4769            "return": {
4770              "description": "A Signal object from the Tone.js library",
4771              "type": "Tone.Signal"
4772            },
4773            "example": ["\n<div><code>\nfunction setup() {\n  carrier = new p5.Oscillator('sine');\n  carrier.amp(1); // set amplitude\n  carrier.freq(220); // set frequency\n  carrier.start(); // start oscillating\n\n  modulator = new p5.Oscillator('sawtooth');\n  modulator.disconnect();\n  modulator.amp(1);\n  modulator.freq(4);\n  modulator.start();\n\n  // Modulator's default amplitude range is -1 to 1.\n  // Multiply it by -200, so the range is -200 to 200\n  // then add 220 s
4773o the range is 20 to 420\n  carrier.freq( modulator.mult(-200).add(220) );\n}\n</code></div>"]
4774          },
4775          "p5.Oscillator": {
4776            "name": "p5.Oscillator",
4777            "shortname": "p5.Oscillator",
4778            "classitems": [],
4779            "plugins": [],
4780            "extensions": [],
4781            "plugin_for": [],
4782            "extension_for": [],
4783            "module": "p5.sound",
4784            "submodule": "p5.sound",
4785            "namespace": "",
4786            "file": "lib/addons/p5.sound.js",
4787            "line": 5361,
4788            "description": "<p>Creates a signal that oscillates between -1.0 and 1.0.\nBy default, the oscillation takes the form of a sinusoidal\nshape (&#39;sine&#39;). Additional types include &#39;triangle&#39;,\n&#39;sawtooth&#39; and &#39;square&#39;. The frequency defaults to\n440 oscillations per second (440Hz, equal to the pitch of an\n&#39;A&#39; note).</p>\n\n<p>Set the type of oscillation with setType(), or by instantiating a\nspecific oscillator: <a href=\"/reference/#/p5.SinOsc\">p5.SinOsc</a>, <a\nhref=\"/reference/#/p5.TriOsc\">p5.TriOsc</a>, <a\nhref=\"/reference/#/p5.SqrOsc\">p5.SqrOsc</a>, or <a\nhref=\"/reference/#/p5.SawOsc\">p5.SawOsc</a>.\n</p>",
4789            "is_constructor": 1,
4790            "params": [{
4791              "name": "freq",
4792              "description": "<p>frequency defaults to 440Hz</p>\n",
4793              "type": "Number",
4794              "optional": true
4795            }, {
4796              "name": "type",
4797              "description": "<p>type of oscillator. Options:\n                       &#39;sine&#39; (default), &#39;triangle&#39;,\n                       &#39;sawtooth&#39;, &#39;square&#39;</p>\n",
4798              "type": "String",
4799              "optional": true
4800            }],
4801            "example": ["\n<div><code>\nvar osc;\nvar playing = false;\n\nfunction setup() {\n  backgroundColor = color(255,0,255);\n  textAlign(CENTER);\n\n  osc = new p5.Oscillator();\n  osc.setType('sine');\n  osc.freq(240);\n  osc.amp(0);\n  osc.start();\n}\n\nfunction draw() {\n  background(backgroundColor)\n  text('click to play', width/2, height/2);\n}\n\nfunction mouseClicked() {\n  if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {\n    if (!playing) {\n      // ramp amplitude to 0.5 over 0.05 seconds\n      osc.amp(0.5, 0.05);\n      playing = true;\n      backgroundColor = color(0,255,255);\n    } else {\n      // ramp amplitude to 0 over 0.5 seconds\n      osc.amp(0, 0.5);\n      playing = false;\n      backgroundColor = color(255,0,255);\n    }\n  }\n}\n</code> </div>"]
4802          },
4803          "p5.SinOsc": {
4804            "name": "p5.SinOsc",
4805            "shortname": "p5.SinOsc",
4806            "classitems": [],
4807            "plugins": [],
4808            "extensions": [],
4809            "plugin_for": [],
4810            "extension_for": [],
4811            "module": "p5.sound",
4812            "submodule": "p5.sound",
4813            "namespace": "",
4814            "file": "lib/addons/p5.sound.js",
4815            "line": 5802,
4816            "description": "<p>Constructor: <code>new p5.SinOsc()</code>.\nThis creates a Sine Wave Oscillator and is\nequivalent to <code> new p5.Oscillator(&#39;sine&#39;)\n</code> or creating a p5.Oscillator and then calling\nits method <code>setType(&#39;sine&#39;)</code>.\nSee p5.Oscillator for methods.</p>\n",
4817            "is_constructor": 1,
4818            "extends": "p5.Oscillator",
4819            "params": [{
4820              "name": "freq",
4821              "description": "<p>Set the frequency</p>\n",
4822              "type": "Number",
4823              "optional": true
4824            }]
4825          },
4826          "p5.TriOsc": {
4827            "name": "p5.TriOsc",
4828            "shortname": "p5.TriOsc",
4829            "classitems": [],
4830            "plugins": [],
4831            "extensions": [],
4832            "plugin_for": [],
4833            "extension_for": [],
4834            "module": "p5.sound",
4835            "submodule": "p5.sound",
4836            "namespace": "",
4837            "file": "lib/addons/p5.sound.js",
4838            "line": 5819,
4839            "description": "<p>Constructor: <code>new p5.TriOsc()</code>.\nThis creates a Triangle Wave Oscillator and is\nequivalent to <code>new p5.Oscillator(&#39;triangle&#39;)\n</code> or creating a p5.Oscillator and then calling\nits method <code>setType(&#39;triangle&#39;)</code>.\nSee p5.Oscillator for methods.</p>\n",
4840            "is_constructor": 1,
4841            "extends": "p5.Oscillator",
4842            "params": [{
4843              "name": "freq",
4844              "description": "<p>Set the frequency</p>\n",
4845              "type": "Number",
4846              "optional": true
4847            }]
4848          },
4849          "p5.SawOsc": {
4850            "name": "p5.SawOsc",
4851            "shortname": "p5.SawOsc",
4852            "classitems": [],
4853            "plugins": [],
4854            "extensions": [],
4855            "plugin_for": [],
4856            "extension_for": [],
4857            "module": "p5.sound",
4858            "submodule": "p5.sound",
4859            "namespace": "",
4860            "file": "lib/addons/p5.sound.js",
4861            "line": 5836,
4862            "description": "<p>Constructor: <code>new p5.SawOsc()</code>.\nThis creates a SawTooth Wave Oscillator and is\nequivalent to <code> new p5.Oscillator(&#39;sawtooth&#39;)\n</code> or creating a p5.Oscillator and then calling\nits method <code>setType(&#39;sawtooth&#39;)</code>.\nSee p5.Oscillator for methods.</p>\n",
4863            "is_constructor": 1,
4864            "extends": "p5.Oscillator",
4865            "params": [{
4866              "name": "freq",
4867              "description": "<p>Set the frequency</p>\n",
4868              "type": "Number",
4869              "optional": true
4870            }]
4871          },
4872          "p5.SqrOsc": {
4873            "name": "p5.SqrOsc",
4874            "shortname": "p5.SqrOsc",
4875            "classitems": [],
4876            "plugins": [],
4877            "extensions": [],
4878            "plugin_for": [],
4879            "extension_for": [],
4880            "module": "p5.sound",
4881            "submodule": "p5.sound",
4882            "namespace": "",
4883            "file": "lib/addons/p5.sound.js",
4884            "line": 5853,
4885            "description": "<p>Constructor: <code>new p5.SqrOsc()</code>.\nThis creates a Square Wave Oscillator and is\nequivalent to <code> new p5.Oscillator(&#39;square&#39;)\n</code> or creating a p5.Oscillator and then calling\nits method <code>setType(&#39;square&#39;)</code>.\nSee p5.Oscillator for methods.</p>\n",
4886            "is_constructor": 1,
4887            "extends": "p5.Oscillator",
4888            "params": [{
4889              "name": "freq",
4890              "description": "<p>Set the frequency</p>\n",
4891              "type": "Number",
4892              "optional": true
4893            }]
4894          },
4895          "p5.Envelope": {
4896            "name": "p5.Envelope",
4897            "shortname": "p5.Envelope",
4898            "classitems": [],
4899            "plugins": [],
4900            "extensions": [],
4901            "plugin_for": [],
4902            "extension_for": [],
4903            "module": "p5.sound",
4904            "submodule": "p5.sound",
4905            "namespace": "",
4906            "file": "lib/addons/p5.sound.js",
4907            "line": 6310,
4908            "description": "<p>Envelopes are pre-defined amplitude distribution over time.\nTypically, envelopes are used to control the output volume\nof an object, a series of fades referred to as Attack, Decay,\nSustain and Release (\n<a href=\"https://upload.wikimedia.org/wikipedia/commons/e/ea/ADSR_parameter.svg\">ADSR</a>\n). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can\ncontrol an Oscillator&#39;s frequency like this: <code>osc.freq(env)</code>.</p>\n<p>Use <code><a href=\"#/p5.Envelope/setRange\">setRange</a></code> to change the attack/release level.\nUse <code><a href=\"#/p5.Envelope/setADSR\">setADSR</a></code> to change attackTime, decayTime, sustainPercent and releaseTime.</p>\n<p>Use the <code><a href=\"#/p5.Envelope/play\">play</a></code> method to play the entire envelope,\nthe <code><a href=\"#/p5.Envelope/ramp\">ramp</a></code> method for a pingable trigger,\nor <code><a href=\"#/p5.Envelope/triggerAttack\">triggerAttack</a></code>/\n<code><a href=\"#/p5.Envelope/triggerRelease\">triggerRelease</a></code> to trigger noteOn/noteOff.</p>",
4909            "is_constructor": 1,
4910            "example": ["\n<div><code>\nvar attackLevel = 1.0;\nvar releaseLevel = 0;\n\nvar attackTime = 0.001;\nvar decayTime = 0.2;\nvar susPercent = 0.2;\nvar releaseTime = 0.5;\n\nvar env, triOsc;\n\nfunction setup() {\n  var cnv = createCanvas(100, 100);\n\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n\n  env = new p5.Envelope();\n  env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n  env.setRange(attackLevel, releaseLevel);\n\n  triOsc = new p5.Oscillator('triangle');\n  triOsc.amp(env);\n  triOsc.start();\n  triOsc.freq(220);\n\n  cnv.mousePressed(playEnv);\n}\n\nfunction playEnv()  {\n  env.play();\n}\n</code></div>"]
4911          },
4912          "p5.Pulse": {
4913            "name": "p5.Pulse",
4914            "shortname": "p5.Pulse",
4915            "classitems": [],
4916            "plugins": [],
4917            "extensions": [],
4918            "plugin_for": [],
4919            "extension_for": [],
4920            "module": "p5.sound",
4921            "submodule": "p5.sound",
4922            "namespace": "",
4923            "file": "lib/addons/p5.sound.js",
4924            "line": 7108,
4925            "description": "<p>Creates a Pulse object, an oscillator that implements\nPulse Width Modulation.\nThe pulse is created with two oscillators.\nAccepts a parameter for frequency, and to set the\nwidth between the pulses. See <a href=\"\nhttp://p5js.org/reference/#/p5.Oscillator\">\n<code>p5.Oscillator</code> for a full list of methods.</p>\n",
4926            "extends": "p5.Oscillator",
4927            "is_constructor": 1,
4928            "params": [{
4929              "name": "freq",
4930              "description": "<p>Frequency in oscillations per second (Hz)</p>\n",
4931              "type": "Number",
4932              "optional": true
4933            }, {
4934              "name": "w",
4935              "description": "<p>Width between the pulses (0 to 1.0,\n                       defaults to 0)</p>\n",
4936              "type": "Number",
4937              "optional": true
4938            }],
4939            "example": ["\n<div><code>\nvar pulse;\nfunction setup() {\n  background(0);\n\n  // Create and start the pulse wave oscillator\n  pulse = new p5.Pulse();\n  pulse.amp(0.5);\n  pulse.freq(220);\n  pulse.start();\n}\n\nfunction draw() {\n  var w = map(mouseX, 0, width, 0, 1);\n  w = constrain(w, 0, 1);\n  pulse.width(w)\n}\n</code></div>"]
4940          },
4941          "p5.Noise": {
4942            "name": "p5.Noise",
4943            "shortname": "p5.Noise",
4944            "classitems": [],
4945            "plugins": [],
4946            "extensions": [],
4947            "plugin_for": [],
4948            "extension_for": [],
4949            "module": "p5.sound",
4950            "submodule": "p5.sound",
4951            "namespace": "",
4952            "file": "lib/addons/p5.sound.js",
4953            "line": 7287,
4954            "description": "<p>Noise is a type of oscillator that generates a buffer with random values.</p>\n",
4955            "extends": "p5.Oscillator",
4956            "is_constructor": 1,
4957            "params": [{
4958              "name": "type",
4959              "description": "<p>Type of noise can be &#39;white&#39; (default),\n                     &#39;brown&#39; or &#39;pink&#39;.</p>\n",
4960              "type": "String"
4961            }]
4962          },
4963          "p5.AudioIn": {
4964            "name": "p5.AudioIn",
4965            "shortname": "p5.AudioIn",
4966            "classitems": [],
4967            "plugins": [],
4968            "extensions": [],
4969            "plugin_for": [],
4970            "extension_for": [],
4971            "module": "p5.sound",
4972            "submodule": "p5.sound",
4973            "namespace": "",
4974            "file": "lib/addons/p5.sound.js",
4975            "line": 7435,
4976            "description": "<p>Get audio from an input, i.e. your computer&#39;s microphone.</p>\n\n<p>Turn the mic on/off with the start() and stop() methods. When the mic\nis on, its volume can be measured with getLevel or by connecting an\nFFT object.</p>\n\n<p>If you want to hear the AudioIn, use the .connect() method.\nAudioIn does not connect to p5.sound output by default to prevent\nfeedback.</p>\n\n<p><em>Note: This uses the <a href=\"http://caniuse.com/stream\">getUserMedia/\nStream</a> API, which is not supported by certain browsers. Access in Chrome browser\nis limited to localhost and https, but access over http may be limited.</em></p>",
4977            "is_constructor": 1,
4978            "params": [{
4979              "name": "errorCallback",
4980              "description": "<p>A function to call if there is an error\n                                  accessing the AudioIn. For example,\n                                  Safari and iOS devices do not\n                                  currently allow microphone access.</p>\n",
4981              "type": "Function",
4982              "optional": true
4983            }],
4984            "example": ["\n<div><code>\nvar mic;\nfunction setup(){\n  mic = new p5.AudioIn()\n  mic.start();\n}\nfunction draw(){\n  background(0);\n  micLevel = mic.getLevel();\n  ellipse(width/2, constrain(height-micLevel*height*5, 0, height), 10, 10);\n}\n</code></div>"]
4985          },
4986          "p5.Effect": {
4987            "name": "p5.Effect",
4988            "shortname": "p5.Effect",
4989            "classitems": [],
4990            "plugins": [],
4991            "extensions": [],
4992            "plugin_for": [],
4993            "extension_for": [],
4994            "module": "p5.sound",
4995            "submodule": "p5.sound",
4996            "namespace": "",
4997            "file": "lib/addons/p5.sound.js",
4998            "line": 8351,
4999            "description": "<p>Effect is a base class for audio effects in p5. <br>\nThis module handles the nodes and methods that are \ncommon and useful for current and future effects.</p>\n<p>This class is extended by <a href=\"/reference/#/p5.Distortion\">p5.Distortion</a>, \n<a href=\"/reference/#/p5.Compressor\">p5.Compressor</a>,\n<a href=\"/reference/#/p5.Delay\">p5.Delay</a>, \n<a href=\"/reference/#/p5.Filter\">p5.Filter</a>, \n<a href=\"/reference/#/p5.Reverb\">p5.Reverb</a>.</p>\n",
5000            "is_constructor": 1,
5001            "params": [{
5002              "name": "ac",
5003              "description": "<p>Reference to the audio context of the p5 object</p>\n",
5004              "type": "Object",
5005              "optional": true
5006            }, {
5007              "name": "input",
5008              "description": "<p>Gain Node effect wrapper</p>\n",
5009              "type": "AudioNode",
5010              "optional": true
5011            }, {
5012              "name": "output",
5013              "description": "<p>Gain Node effect wrapper</p>\n",
5014              "type": "AudioNode",
5015              "optional": true
5016            }, {
5017              "name": "_drywet",
5018              "description": "<p>Tone.JS CrossFade node (defaults to value: 1)</p>\n",
5019              "type": "Object",
5020              "optional": true
5021            }, {
5022              "name": "wet",
5023              "description": "<p>Effects that extend this class should connect\n                             to the wet signal to this gain node, so that dry and wet \n                             signals are mixed properly.</p>\n",
5024              "type": "AudioNode",
5025              "optional": true
5026            }]
5027          },
5028          "p5.Filter": {
5029            "name": "p5.Filter",
5030            "shortname": "p5.Filter",
5031            "classitems": [],
5032            "plugins": [],
5033            "extensions": [],
5034            "plugin_for": [],
5035            "extension_for": [],
5036            "module": "p5.sound",
5037            "submodule": "p5.sound",
5038            "namespace": "",
5039            "file": "lib/addons/p5.sound.js",
5040            "line": 8493,
5041            "description": "<p><p>A p5.Filter uses a Web Audio Biquad Filter to filter\nthe frequency response of an input source. Subclasses\ninclude:</p></p>\n<ul>\n<li><a href=\"/reference/#/p5.LowPass\"><code>p5.LowPass</code></a>:\nAllows frequencies below the cutoff frequency to pass through,\nand attenuates frequencies above the cutoff.<br/></li>\n<li><a href=\"/reference/#/p5.HighPass\"><code>p5.HighPass</code></a>:\nThe opposite of a lowpass filter. <br/></li>\n<li><a href=\"/reference/#/p5.BandPass\"><code>p5.BandPass</code></a>:\nAllows a range of frequencies to pass through and attenuates\nthe frequencies below and above this frequency range.<br/></li>\n</ul>\n<p>The <code>.res()</code> method controls either width of the\nbandpass, or resonance of the low/highpass cutoff frequency.</p>\n<p>This class extends <a href = \"/reference/#/p5.Effect\">p5.Effect</a>.<br>Methods <a href = \"/reference/#/p5.Effect/amp\">amp()</a>, <a href = \"/reference/#/p5.Effect/chain\">chain()</a>, \n<a href = \"/reference/#/p5.Effect/drywet\">drywet()</a>, <a href = \"/reference/#/p5.Effect/connect\">connect()</a>, and \n<a href = \"/reference/#/p5.Effect/disconnect\">disconnect()</a> are available.</p>\n",
5042            "extends": "p5.Effect",
5043            "is_constructor": 1,
5044            "params": [{
5045              "name": "type",
5046              "description": "<p>&#39;lowpass&#39; (default), &#39;highpass&#39;, &#39;bandpass&#39;</p>\n",
5047              "type": "String",
5048              "optional": true
5049            }],
5050            "example": ["\n<div><code>\nvar fft, noise, filter;\n\nfunction setup() {\n  fill(255, 40, 255);\n\n  filter = new p5.BandPass();\n\n  noise = new p5.Noise();\n  // disconnect unfiltered noise,\n  // and connect to filter\n  noise.disconnect();\n  noise.connect(filter);\n  noise.start();\n\n  fft = new p5.FFT();\n}\n\nfunction draw() {\n  background(30);\n\n  // set the BandPass frequency based on mouseX\n  var freq = map(mouseX, 0, width, 20, 10000);\n  filter.freq(freq);\n  // give the filter a narrow band (lower res = wider bandpass)\n  filter.res(50);\n\n  // draw filtered spectrum\n  var spectrum = fft.analyze();\n  noStroke();\n  for (var i = 0; i < spectrum.length;
5050 i++) {\n    var x = map(i, 0, spectrum.length, 0, width);\n    var h = -height + map(spectrum[i], 0, 255, height, 0);\n    rect(x, height, width/spectrum.length, h);\n  }\n\n  isMouseOverCanvas();\n}\n\nfunction isMouseOverCanvas() {\n  var mX = mouseX, mY = mouseY;\n  if (mX > 0 && mX < width && mY < height && mY > 0) {\n    noise.amp(0.5, 0.2);\n  } else {\n    noise.amp(0, 0.2);\n  }\n}\n</code></div>"]
5051          },
5052          "p5.LowPass": {
5053            "name": "p5.LowPass",
5054            "shortname": "p5.LowPass",
5055            "classitems": [],
5056            "plugins": [],
5057            "extensions": [],
5058            "plugin_for": [],
5059            "extension_for": [],
5060            "module": "p5.sound",
5061            "submodule": "p5.sound",
5062            "namespace": "",
5063            "file": "lib/addons/p5.sound.js",
5064            "line": 8724,
5065            "description": "<p>Constructor: <code>new p5.LowPass()</code> Filter.\nThis is the same as creating a p5.Filter and then calling\nits method <code>setType(&#39;lowpass&#39;)</code>.\nSee p5.Filter for methods.</p>\n",
5066            "is_constructor": 1,
5067            "extends": "p5.Filter"
5068          },
5069          "p5.HighPass": {
5070            "name": "p5.HighPass",
5071            "shortname": "p5.HighPass",
5072            "classitems": [],
5073            "plugins": [],
5074            "extensions": [],
5075            "plugin_for": [],
5076            "extension_for": [],
5077            "module": "p5.sound",
5078            "submodule": "p5.sound",
5079            "namespace": "",
5080            "file": "lib/addons/p5.sound.js",
5081            "line": 8738,
5082            "description": "<p>Constructor: <code>new p5.HighPass()</code> Filter.\nThis is the same as creating a p5.Filter and then calling\nits method <code>setType(&#39;highpass&#39;)</code>.\nSee p5.Filter for methods.</p>\n",
5083            "is_constructor": 1,
5084            "extends": "p5.Filter"
5085          },
5086          "p5.BandPass": {
5087            "name": "p5.BandPass",
5088            "shortname": "p5.BandPass",
5089            "classitems": [],
5090            "plugins": [],
5091            "extensions": [],
5092            "plugin_for": [],
5093            "extension_for": [],
5094            "module": "p5.sound",
5095            "submodule": "p5.sound",
5096            "namespace": "",
5097            "file": "lib/addons/p5.sound.js",
5098            "line": 8752,
5099            "description": "<p>Constructor: <code>new p5.BandPass()</code> Filter.\nThis is the same as creating a p5.Filter and then calling\nits method <code>setType(&#39;bandpass&#39;)</code>.\nSee p5.Filter for methods.</p>\n",
5100            "is_constructor": 1,
5101            "extends": "p5.Filter"
5102          },
5103          "p5.EQ": {
5104            "name": "p5.EQ",
5105            "shortname": "p5.EQ",
5106            "classitems": [],
5107            "plugins": [],
5108            "extensions": [],
5109            "plugin_for": [],
5110            "extension_for": [],
5111            "module": "p5.sound",
5112            "submodule": "p5.sound",
5113            "namespace": "",
5114            "file": "lib/addons/p5.sound.js",
5115            "line": 8823,
5116            "description": "<p>p5.EQ is an audio effect that performs the function of a multiband\naudio equalizer. Equalization is used to adjust the balance of\nfrequency compoenents of an audio signal. This process is commonly used\nin sound production and recording to change the waveform before it reaches\na sound output device. EQ can also be used as an audio effect to create\ninteresting distortions by filtering out parts of the spectrum. p5.EQ is\nbuilt using a chain of Web Audio Biquad Filter Nodes and can be\ninstantiated with 3 or 8 bands. Bands can be added or removed from\nthe EQ by directly modifying p5.EQ.bands (the array that stores filters).</p>\n<p>This class extends <a href = \"/reference/#/p5.Effect\">p5.Effect</a>.\nMethods <a href = \"/reference/#/p5.Effect/amp\">amp()</a>, <a href = \"/reference/#/p5.Effect/chain\">chain()</a>,\n<a href = \"/reference/#/p5.Effect/drywet\">drywet()</a>, <a href = \"/reference/#/p5.Effect/connect\">connect()</a>, and\n<a href = \"/reference/#/p5.Effect/disconnect\">disconnect()</a> are available.</p>\n",
5117            "is_constructor": 1,
5118            "extends": "p5.Effect",
5119            "params": [{
5120              "name": "_eqsize",
5121              "description": "<p>Constructor will accept 3 or 8, defaults to 3</p>\n",
5122              "type": "Number",
5123              "optional": true
5124            }],
5125            "return": {
5126              "description": "p5.EQ object",
5127              "type": "Object"
5128            },
5129            "example": ["\n<div><code>\nvar eq;\nvar band_names;\nvar band_index;\n\nvar soundFile, play;\n\nfunction preload() {\n  soundFormats('mp3', 'ogg');\n  soundFile = loadSound('assets/beat');\n}\n\nfunction setup() {\n  eq = new p5.EQ(3);\n  soundFile.disconnect();\n  eq.process(soundFile);\n\n  band_names = ['lows','mids','highs'];\n  band_index = 0;\n  play = false;\n  textAlign(CENTER);\n}\n\nfunction draw() {\n  background(30);\n  noStroke();\n  fill(255);\n  text('click to kill',50,25);\n\n  fill(255, 40, 255);\n  textSize(26);\n  text(band_names[band_index],50,55);\n\n  fill(255);\n  textSize(9);\n  text('space = play/pause',50,80);\n}\n\n//If mouse is over canvas, cycle to the next band and kill the frequency\nfunction mouseClicked() {\n  for (var i = 0; i < eq.bands.length; i++) {\n    eq.bands[i].gain(0);\n  }\n  eq.bands[band_index].gain(-40);\n  if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {\n    band_index === 2 ? band_index = 0 : band_index++;\n  }\n}\n\n//use space bar to trigger play / pause\nfunction keyPressed() {\n  if (key===' ') {\n    play = !play\n    play ? soundFile.loop() : soundFile.pause();\n  }\n}\n</code></div>"]
5130          },
5131          "p5.Panner3D": {
5132            "name": "p5.Panner3D",
5133            "shortname": "p5.Panner3D",
5134            "classitems": [],
5135            "plugins": [],
5136            "extensions": [],
5137            "plugin_for": [],
5138            "extension_for": [],
5139            "module": "p5.sound",
5140            "submodule": "p5.sound",
5141            "namespace": "",
5142            "file": "lib/addons/p5.sound.js",
5143            "line": 9015,
5144            "description": "<p>Panner3D is based on the <a title=\"Web Audio Panner docs\"  href=\n\"https://developer.mozilla.org/en-US/docs/Web/API/PannerNode\">\nWeb Audio Spatial Panner Node</a>.\nThis panner is a spatial processing node that allows audio to be positioned\nand oriented in 3D space.</p>\n<p>The position is relative to an <a title=\"Web Audio Listener docs\" href=\n\"https://developer.mozilla.org/en-US/docs/Web/API/AudioListener\">\nAudio Context Listener</a>, which can be accessed\nby <code>p5.soundOut.audiocontext.listener</code></p>\n",
5145            "is_constructor": 1
5146          },
5147          "p5.Delay": {
5148            "name": "p5.Delay",
5149            "shortname": "p5.Delay",
5150            "classitems": [],
5151            "plugins": [],
5152            "extensions": [],
5153            "plugin_for": [],
5154            "extension_for": [],
5155            "module": "p5.sound",
5156            "submodule": "p5.sound",
5157            "namespace": "",
5158            "file": "lib/addons/p5.sound.js",
5159            "line": 9466,
5160            "description": "<p>Delay is an echo effect. It processes an existing sound source,\nand outputs a delayed version of that sound. The p5.Delay can\nproduce different effects depending on the delayTime, feedback,\nfilter, and type. In the example below, a feedback of 0.5 (the\ndefaul value) will produce a looping delay that decreases in\nvolume by 50% each repeat. A filter will cut out the high\nfrequencies so that the delay does not sound as piercing as the\noriginal source.</p>\n<p>This class extends <a href = \"/reference/#/p5.Effect\">p5.Effect</a>.<br>Methods <a href = \"/reference/#/p5.Effect/amp\">amp()</a>, <a href = \"/reference/#/p5.Effect/chain\">chain()</a>, \n<a href = \"/reference/#/p5.Effect/drywet\">drywet()</a>, <a href = \"/reference/#/p5.Effect/connect\">connect()</a>, and \n<a href = \"/reference/#/p5.Effect/disconnect\">disconnect()</a> are available.</p>\n",
5161            "extends": "p5.Effect",
5162            "is_constructor": 1,
5163            "example": ["\n<div><code>\nvar noise, env, delay;\n\nfunction setup() {\n  background(0);\n  noStroke();\n  fill(255);\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n\n  noise = new p5.Noise('brown');\n  noise.amp(0);\n  noise.start();\n\n  delay = new p5.Delay();\n\n  // delay.process() accepts 4 parameters:\n  // source, delayTime, feedback, filter frequency\n  // play with these numbers!!\n  delay.process(noise, .12, .7, 2300);\n\n  // play the noise with an envelope,\n  // a series of fades ( time / value pairs )\n  env = new p5.Envelope(.01, 0.2, .2, .1);\n}\n\n// mouseClick triggers envelope\nfunction mouseClicked() {\n  // is mouse over canvas?\n  if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n    env.play(noise);\n  }\n}\n</code></div>"]
5164          },
5165          "p5.Reverb": {
5166            "name": "p5.Reverb",
5167            "shortname": "p5.Reverb",
5168            "classitems": [],
5169            "plugins": [],
5170            "extensions": [],
5171            "plugin_for": [],
5172            "extension_for": [],
5173            "module": "p5.sound",
5174            "submodule": "p5.sound",
5175            "namespace": "",
5176            "file": "lib/addons/p5.sound.js",
5177            "line": 9743,
5178            "description": "<p>Reverb adds depth to a sound through a large number of decaying\nechoes. It creates the perception that sound is occurring in a\nphysical space. The p5.Reverb has paramters for Time (how long does the\nreverb last) and decayRate (how much the sound decays with each echo)\nthat can be set with the .set() or .process() methods. The p5.Convolver\nextends p5.Reverb allowing you to recreate the sound of actual physical\nspaces through convolution.</p>\n<p>This class extends <a href = \"/reference/#/p5.Effect\">p5.Effect</a>.\nMethods <a href = \"/reference/#/p5.Effect/amp\">amp()</a>, <a href = \"/reference/#/p5.Effect/chain\">chain()</a>,\n<a href = \"/reference/#/p5.Effect/drywet\">drywet()</a>, <a href = \"/reference/#/p5.Effect/connect\">connect()</a>, and\n<a href = \"/reference/#/p5.Effect/disconnect\">disconnect()</a> are available.</p>\n",
5179            "extends": "p5.Effect",
5180            "is_constructor": 1,
5181            "example": ["\n<div><code>\nvar soundFile, reverb;\nfunction preload() {\n  soundFile = loadSound('assets/Damscray_DancingTiger.mp3');\n}\n\nfunction setup() {\n  reverb = new p5.Reverb();\n  soundFile.disconnect(); // so we'll only hear reverb...\n\n  // connect soundFile to reverb, process w/\n  // 3 second reverbTime, decayRate of 2%\n  reverb.process(soundFile, 3, 2);\n  soundFile.play();\n}\n</code></div>"]
5182          },
5183          "p5.Convolver": {
5184            "name": "p5.Convolver",
5185            "shortname": "p5.Convolver",
5186            "classitems": [],
5187            "plugins": [],
5188            "extensions": [],
5189            "plugin_for": [],
5190            "extension_for": [],
5191            "module": "p5.sound",
5192            "submodule": "p5.sound",
5193            "namespace": "",
5194            "file": "lib/addons/p5.sound.js",
5195            "line": 9914,
5196            "description": "<p>p5.Convolver extends p5.Reverb. It can emulate the sound of real\nphysical spaces through a process called <a href=\"\nhttps://en.wikipedia.org/wiki/Convolution_reverb#Real_space_simulation\">\nconvolution</a>.</p>\n\n<p>Convolution multiplies any audio input by an &quot;impulse response&quot;\nto simulate the dispersion of sound over time. The impulse response is\ngenerated from an audio file that you provide. One way to\ngenerate an impulse response is to pop a balloon in a reverberant space\nand record the echo. Convolution can also be used to experiment with\nsound.</p>\n\n<p>Use the method <code>createConvolution(path)</code> to instantiate a\np5.Convolver with a path to your impulse response audio file.</p>",
5197            "extends": "p5.Effect",
5198            "is_constructor": 1,
5199            "params": [{
5200              "name": "path",
5201              "description": "<p>path to a sound file</p>\n",
5202              "type": "String"
5203            }, {
5204              "name": "callback",
5205              "description": "<p>function to call when loading succeeds</p>\n",
5206              "type": "Function",
5207              "optional": true
5208            }, {
5209              "name": "errorCallback",
5210              "description": "<p>function to call if loading fails.\n                                   This function will receive an error or\n                                   XMLHttpRequest object with information\n                                   about what went wrong.</p>\n",
5211              "type": "Function",
5212              "optional": true
5213            }],
5214            "example": ["\n<div><code>\nvar cVerb, sound;\nfunction preload() {\n  // We have both MP3 and OGG versions of all sound assets\n  soundFormats('ogg', 'mp3');\n\n  // Try replacing 'bx-spring' with other soundfiles like\n  // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n  
5214cVerb = createConvolver('assets/bx-spring.mp3');\n\n  // Try replacing 'Damscray_DancingTiger' with\n  // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n  sound = loadSound('assets/Damscray_DancingTiger.mp3');\n}\n\nfunction setup() {\n  // disconnect from master output...\n  sound.disconnect();\n\n  // ...and process with cVerb\n  // so that we only hear the convolution\n  cVerb.process(sound);\n\n  sound.play();\n}\n</code></div>"]
5215          },
5216          "p5.Phrase": {
5217            "name": "p5.Phrase",
5218            "shortname": "p5.Phrase",
5219            "classitems": [],
5220            "plugins": [],
5221            "extensions": [],
5222            "plugin_for": [],
5223            "extension_for": [],
5224            "module": "p5.sound",
5225            "submodule": "p5.sound",
5226            "namespace": "",
5227            "file": "lib/addons/p5.sound.js",
5228            "line": 10470,
5229            "description": "<p>A phrase is a pattern of musical events over time, i.e.\na series of notes and rests.</p>\n\n<p>Phrases must be added to a p5.Part for playback, and\neach part can play multiple phrases at the same time.\nFor example, one Phrase might be a kick drum, another\ncould be a snare, and another could be the bassline.</p>\n\n<p>The first parameter is a name so that the phrase can be\nmodified or deleted later. The callback is a a function that\nthis phrase will call at every step—for example it might be\ncalled <code>playNote(value){}</code>. The array determines\nwhich value is passed into the callback at each step of the\nphrase. It can be numbers, an object with multiple numbers,\nor a zero (0) indicates a rest so the callback won&#39;t be called).</p>",
5230            "is_constructor": 1,
5231            "params": [{
5232              "name": "name",
5233              "description": "<p>Name so that you can access the Phrase.</p>\n",
5234              "type": "String"
5235            }, {
5236              "name": "callback",
5237              "description": "<p>The name of a function that this phrase\n                           will call. Typically it will play a sound,\n                           and accept two parameters: a time at which\n                           to play the sound (in seconds from now),\n                           and a value from the sequence array. The\n                           time should be passed into the play() or\n                           start() method to ensure precision.</p>\n",
5238              "type": "Function"
5239            }, {
5240              "name": "sequence",
5241              "description": "<p>Array of values to pass into the callback\n                          at each step of the phrase.</p>\n",
5242              "type": "Array"
5243            }],
5244            "example": ["\n<div><code>\nvar mySound, myPhrase, myPart;\nvar pattern = [1,0,0,2,0,2,0,0];\nvar msg = 'click to play';\n\nfunction preload() {\n  mySound = loadSound('assets/beatbox.mp3');\n}\n\nfunction setup() {\n  noStroke();\n  fill(255);\n  textAlign(CENTER);\n  masterVolume(0.1);\n\n  myPhrase = new p5.Phrase('bbox', makeSound, pattern);\n  myPart = new p5.Part();\n  myPart.addPhrase(myPhrase);\n  myPart.setBPM(60);\n}\n\nfunction draw() {\n  background(0);\n  text(msg, width/2, height/2);\n}\n\nfunction makeSound(time, playbackRate) {\n  mySound.rate(playbackRate);\n  mySound.play(time);\n}\n\nfunction mouseClicked() {\n  if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n    myPart.start();\n    msg = 'playing pattern';\n  }\n}\n\n</code></div>"]
5245          },
5246          "p5.Part": {
5247            "name": "p5.Part",
5248            "shortname": "p5.Part",
5249            "classitems": [],
5250            "plugins": [],
5251            "extensions": [],
5252            "plugin_for": [],
5253            "extension_for": [],
5254            "module": "p5.sound",
5255            "submodule": "p5.sound",
5256            "namespace": "",
5257            "file": "lib/addons/p5.sound.js",
5258            "line": 10555,
5259            "description": "<p>A p5.Part plays back one or more p5.Phrases. Instantiate a part\nwith steps and tatums. By default, each step represents a 1/16th note.</p>\n\n<p>See p5.Phrase for more about musical timing.</p>",
5260            "is_constructor": 1,
5261            "params": [{
5262              "name": "steps",
5263              "description": "<p>Steps in the part</p>\n",
5264              "type": "Number",
5265              "optional": true
5266            }, {
5267              "name": "tatums",
5268              "description": "<p>Divisions of a beat, e.g. use 1/4, or 0.25 for a quater note (default is 1/16, a sixteenth note)</p>\n",
5269              "type": "Number",
5270              "optional": true
5271            }],
5272            "example": ["\n<div><code>\nvar box, drum, myPart;\nvar boxPat = [1,0,0,2,0,2,0,0];\nvar drumPat = [0,1,1,0,2,0,1,0];\nvar msg = 'click to play';\n\nfunction preload() {\n  box = loadSound('assets/beatbox.mp3');\n  drum = loadSound('assets/drum.mp3');\n}\n\nfunction setup() {\n  noStroke();\n  fill(255);\n  textAlign(CENTER);\n  masterVolume(0.1);\n\n  var boxPhrase = new p5.Phrase('box', playBox, boxPat);\n  var drumPhrase = new p5.Phrase('drum', playDrum, drumPat);\n  myPart = new p5.Part();\n  myPart.addPhrase(boxPhrase);\n  myPart.addPhrase(drumPhrase);\n  myPart.setBPM(60);\n  masterVolume(0.1);\n}\n\nfunction draw() {\n  background(0);\n  text(msg, width/2, height/2);\n}\n\nfunction playBox(time, playbackRate) {\n  box.rate(playbackRate);\n  box.play(time);\n}\n\nfunction playDrum(time, playbackRate) {\n  drum.rate(playbackRate);\n  drum.play(time);\n}\n\nfunction mouseClicked() {\n  if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n    myPart.start();\n    msg = 'playing part';\n  }\n}\n</code></div>"]
5273          },
5274          "p5.Score": {
5275            "name": "p5.Score",
5276            "shortname": "p5.Score",
5277            "classitems": [],
5278            "plugins": [],
5279            "extensions": [],
5280            "plugin_for": [],
5281            "extension_for": [],
5282            "module": "p5.sound",
5283            "submodule": "p5.sound",
5284            "namespace": "",
5285            "file": "lib/addons/p5.sound.js",
5286            "line": 10808,
5287            "description": "<p>A Score consists of a series of Parts. The parts will\nbe played back in order. For example, you could have an\nA part, a B part, and a C part, and play them back in this order\n<code>new p5.Score(a, a, b, a, c)</code></p>\n",
5288            "is_constructor": 1,
5289            "params": [{
5290              "name": "parts",
5291              "description": "<p>One or multiple parts, to be played in sequence.</p>\n",
5292              "type": "p5.Part",
5293              "optional": true,
5294              "multiple": true
5295            }]
5296          },
5297          "p5.SoundLoop": {
5298            "name": "p5.SoundLoop",
5299            "shortname": "p5.SoundLoop",
5300            "classitems": [],
5301            "plugins": [],
5302            "extensions": [],
5303            "plugin_for": [],
5304            "extension_for": [],
5305            "module": "p5.sound",
5306            "submodule": "p5.sound",
5307            "namespace": "",
5308            "file": "lib/addons/p5.sound.js",
5309            "line": 10939,
5310            "description": "<p>SoundLoop</p>\n",
5311            "is_constructor": 1,
5312            "params": [{
5313              "name": "callback",
5314              "description": "<p>this function will be called on each iteration of theloop</p>\n",
5315              "type": "Function"
5316            }, {
5317              "name": "interval",
5318              "description": "<p>amount of time or beats for each iteration of the loop\n                                      defaults to 1</p>\n",
5319              "type": "Number|String",
5320              "optional": true
5321            }],
5322            "example": ["\n<div><code>\nvar click;\nvar looper1;\n\nfunction preload() {\n  click = loadSound('assets/drum.mp3');\n}\n\nfunction setup() {\n  //the looper's callback is passed the timeFromNow\n  //this value should be used as a reference point from \n  //which to schedule sounds \n  looper1 = new p5.SoundLoop(function(timeFromNow){\n    click.play(timeFromNow);\n    background(255 * (looper1.iterations % 2));\n    }, 2);\n\n  //stop after 10 iteratios;\n  looper1.maxIterations = 10;\n  //start the loop\n  looper1.start();\n}\n</code></div>"]
5323          },
5324          "p5.Compressor": {
5325            "name": "p5.Compressor",
5326            "shortname": "p5.Compressor",
5327            "classitems": [],
5328            "plugins": [],
5329            "extensions": [],
5330            "plugin_for": [],
5331            "extension_for": [],
5332            "module": "p5.sound",
5333            "submodule": "p5.sound",
5334            "namespace": "",
5335            "file": "lib/addons/p5.sound.js",
5336            "line": 11199,
5337            "description": "<p>Compressor is an audio effect class that performs dynamics compression\non an audio input source. This is a very commonly used technique in music\nand sound production. Compression creates an overall louder, richer, \nand fuller sound by lowering the volume of louds and raising that of softs.\nCompression can be used to avoid clipping (sound distortion due to \npeaks in volume) and is especially useful when many sounds are played \nat once. Compression can be used on indivudal sound sources in addition\nto the master output.  </p>\n<p>This class extends <a href = \"/reference/#/p5.Effect\">p5.Effect</a>.<br>Methods <a href = \"/reference/#/p5.Effect/amp\">amp()</a>, <a href = \"/reference/#/p5.Effect/chain\">chain()</a>, \n<a href = \"/reference/#/p5.Effect/drywet\">drywet()</a>, <a href = \"/reference/#/p5.Effect/connect\">connect()</a>, and \n<a href = \"/reference/#/p5.Effect/disconnect\">disconnect()</a> are available.</p>\n",
5338            "is_constructor": 1,
5339            "extends": "p5.Effect"
5340          },
5341          "p5.SoundRecorder": {
5342            "name": "p5.SoundRecorder",
5343            "shortname": "p5.SoundRecorder",
5344            "classitems": [],
5345            "plugins": [],
5346            "extensions": [],
5347            "plugin_for": [],
5348            "extension_for": [],
5349            "module": "p5.sound",
5350            "submodule": "p5.sound",
5351            "namespace": "",
5352            "file": "lib/addons/p5.sound.js",
5353            "line": 11411,
5354            "description": "<p>
5354Record sounds for playback and/or to save as a .wav file.\nThe p5.SoundRecorder records all sound output from your sketch,\nor can be assigned a specific source with setInput().</p>\n<p>The record() method accepts a p5.SoundFile as a parameter.\nWhen playback is stopped (either after the given amount of time,\nor with the stop() method), the p5.SoundRecorder will send its\nrecording to that p5.SoundFile for playback.</p>",
5355            "is_constructor": 1,
5356            "example": ["\n<div><code>\nvar mic, recorder, soundFile;\nvar state = 0;\n\nfunction setup() {\n  background(200);\n  // create an audio in\n  mic = new p5.AudioIn();\n\n  // prompts user to enable their browser mic\n  mic.start();\n\n  // create a sound recorder\n  recorder = new p5.SoundRecorder();\n\n  // connect the mic to the recorder\n  recorder.setInput(mic);\n\n  // this sound file will be used to\n  // playback & save the recording\n  soundFile = new p5.SoundFile();\n\n  text('keyPress to record', 20, 20);\n}\n\nfunction keyPressed() {\n  // make sure user enabled the mic\n  if (state === 0 && mic.enabled) {\n\n    // record to our p5.SoundFile\n    recorder.record(soundFile);\n\n    background(255,0,0);\n    text('Recording!', 20, 20);\n    state++;\n  }\n  else if (state === 1) {\n    background(0,255,0);\n\n    // stop recorder and\n    // send result to soundFile\n    recorder.stop();\n\n    text('Stopped', 20, 20);\n    state++;\n  }\n\n  else if (state === 2) {\n    soundFile.play(); // play the result!\n    save(soundFile, 'mySound.wav');\n    state++;\n  }\n}\n</div></code>"]
5357          },
5358          "p5.PeakDetect": {
5359            "name": "p5.PeakDetect",
5360            "shortname": "p5.PeakDetect",
5361            "classitems": [],
5362            "plugins": [],
5363            "extensions": [],
5364            "plugin_for": [],
5365            "extension_for": [],
5366            "module": "p5.sound",
5367            "submodule": "p5.sound",
5368            "namespace": "",
5369            "file": "lib/addons/p5.sound.js",
5370            "line": 11649,
5371            "description": "<p>PeakDetect works in conjunction with p5.FFT to\nlook for onsets in some or all of the frequency spectrum.\n</p>\n<p>\nTo use p5.PeakDetect, call <code>update</code> in the draw loop\nand pass in a p5.FFT object.\n</p>\n<p>\nYou can listen for a specific part of the frequency spectrum by\nsetting the range between <code>freq1</code> and <code>freq2</code>.\n</p>\n\n<p><code>threshold</code> is the threshold for detecting a peak,\nscaled between 0 and 1. It is logarithmic, so 0.1 is half as loud\nas 1.0.</p>\n\n<p>\nThe update method is meant to be run in the draw loop, and\n<b>frames</b> determines how many loops must pass before\nanother peak can be detected.\nFor example, if the frameRate() = 60, you could detect the beat of a\n120 beat-per-minute song with this equation:\n<code> framesPerPeak = 60 / (estimatedBPM / 60 );</code>\n</p>\n\n<p>\nBased on example contribtued by @b2renger, and a simple beat detection\nexplanation by <a href=\"a\nhref=&quot;http://www.airtightinteractive.com/2013/10/making-audio-reactive-visuals/&quot;\ntarget=&quot;_blank&quot;\">a\nhref=&quot;http://www.airtightinteractive.com/2013/10/making-audio-reactive-visuals/&quot;\ntarget=&quot;_blank&quot;</a>Felix Turner</a>.\n</p>",
5372            "is_constructor": 1,
5373            "params": [{
5374              "name": "freq1",
5375              "description": "<p>lowFrequency - defaults to 20Hz</p>\n",
5376              "type": "Number",
5377              "optional": true
5378            }, {
5379              "name": "freq2",
5380              "description": "<p>highFrequency - defaults to 20000 Hz</p>\n",
5381              "type": "Number",
5382              "optional": true
5383            }, {
5384              "name": "threshold",
5385              "description": "<p>Threshold for detecting a beat between 0 and 1\n                          scaled logarithmically where 0.1 is 1/2 the loudness\n                          of 1.0. Defaults to 0.35.</p>\n",
5386              "type": "Number",
5387              "optional": true
5388            }, {
5389              "name": "framesPerPeak",
5390              "description": "<p>Defaults to 20.</p>\n",
5391              "type": "Number",
5392              "optional": true
5393            }],
5394            "example": ["\n<div><code>\n\nvar cnv, soundFile, fft, peakDetect;\nvar ellipseWidth = 10;\n\nfunction preload() {\n  soundFile = loadSound('assets/beat.mp3');\n}\n\nfunction setup() {\n  background(0);\n  noStroke();\n  fill(255);\n  textAlign(CENTER);\n\n  // p5.PeakDetect requires a p5.FFT\n  fft = new p5.FFT();\n  peakDetect = new p5.PeakDetect();\n}\n\nfunction draw() {\n  background(0);\n  text('click to play/pause', width/2, height/2);\n\n  // peakDetect accepts an fft post-analysis\n  fft.analyze();\n  peakDetect.update(fft);\n\n  if ( peakDetect.isDetected ) {\n    ellipseWidth = 50;\n  } else {\n    ellipseWidth *= 0.95;\n  }\n\n  ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\n}\n\n// toggle play/stop when canvas is clicked\nfunction mouseClicked() {\n  if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n    if (soundFile.isPlaying() ) {\n      soundFile.stop();\n    } else {\n      soundFile.play();\n    }\n  }\n}\n</code></div>"]
5395          },
5396          "p5.Gain": {
5397            "name": "p5.Gain",
5398            "shortname": "p5.Gain",
5399            "classitems": [],
5400            "plugins": [],
5401            "extensions": [],
5402            "plugin_for": [],
5403            "extension_for": [],
5404            "module": "p5.sound",
5405            "submodule": "p5.sound",
5406            "namespace": "",
5407            "file": "lib/addons/p5.sound.js",
5408            "line": 11873,
5409            "description": "<p>A gain node is usefull to set the relative volume of sound.\nIt&#39;s typically used to build mixers.</p>\n",
5410            "is_constructor": 1,
5411            "example": ["\n<div><code>\n\n // load two soundfile and crossfade beetween them\n var sound1,sound2;\n var gain1, gain2, gain3;\n\n function preload(){\n soundFormats('ogg', 'mp3');\n sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01');\n sound2 = loadSound('assets/beat.mp3');\n }\n\n function setup() {\n createCanvas(400,200);\n\n // create a 'master' gain to which we will connect both soundfiles\n gain3 = new p5.Gain();\n gain3.connect();\n\n // setup first sound for playing\n sound1.rate(1);\n sound1.loop();\n sound1.disconnect(); // diconnect from p5 output\n\n gain1 = new p5.Gain(); // setup a gain node\n gain1.setInput(sound1); // connect the first sound to its input\n gain1.connect(gain3); // connect its output to the 'master'\n\n sound2.rate(1);\n sound2.disconnect();\n sound2.loop();\n\n gain2 = new p5.Gain();\n gain2.setInput(sound2);\n gain2.connect(gain3);\n\n }\n\n function draw(){\n background(180);\n\n // calculate the horizontal distance beetween the mouse and the right of the screen\n var d = dist(mouseX,0,width,0);\n\n // map the horizontal position of the mouse to values useable for volume control of sound1\n var vol1 = map(mouseX,0,width,0,1);\n var vol2 = 1-vol1; // when sound1 is loud, sound2 is quiet and vice versa\n\n gain1.amp(vol1,0.5,0);\n gain2.amp(vol2,0.5,0);\n\n // map the vertical position of the mouse to values useable for 'master volume control'\n var vol3 = map(mouseY,0,height,0,1);\n gain3.amp(vol3,0.5,0);\n }\n</code></div>\n"]
5412          },
5413          "p5.AudioVoice": {
5414            "name": "p5.AudioVoice",
5415            "shortname": "p5.AudioVoice",
5416            "classitems": [],
5417            "plugins": [],
5418            "extensions": [],
5419            "plugin_for": [],
5420            "extension_for": [],
5421            "module": "p5.sound",
5422            "submodule": "p5.sound",
5423            "namespace": "",
5424            "file": "lib/addons/p5.sound.js",
5425            "line": 12014,
5426            "description": "<p>Base class for monophonic synthesizers. Any extensions of this class\nshould follow the API and implement the methods below in order to \nremain compatible with p5.PolySynth();</p>\n",
5427            "is_constructor": 1
5428          },
5429          "p5.MonoSynth": {
5430            "name": "p5.MonoSynth",
5431            "shortname": "p5.MonoSynth",
5432            "classitems": [],
5433            "plugins": [],
5434            "extensions": [],
5435            "plugin_for": [],
5436            "extension_for": [],
5437            "module": "p5.sound",
5438            "submodule": "p5.sound",
5439            "namespace": "",
5440            "file": "lib/addons/p5.sound.js",
5441            "line": 12067,
5442            "description": "<p>A MonoSynth is used as a single voice for sound synthesis.\nThis is a class to be used in conjunction with the PolySynth\nclass. Custom synthetisers should be built inheriting from\nthis class.</p>\n",
5443            "is_constructor": 1,
5444            "example": ["\n<div><code>\nvar monoSynth;\n\nfunction setup() {\n  var cnv = createCanvas(100, 100);\n  cnv.mousePressed(playSynth);\n\n  monoSynth = new p5.MonoSynth();\n\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n}\n\nfunction playSynth() {\n  // time from now (in seconds)\n  var time = 0;\n  // note duration (in seconds)\n  var dur = 0.25;\n  // velocity (volume, from 0 to 1)\n  var v = 0.2;\n\n  monoSynth.play(\"G3\", v, time, dur);\n  monoSynth.play(\"C4\", v, time += dur, dur);\n\n  background(random(255), random(255), 255);\n  text('click to play', width/2, height/2);\n}\n</code></div>"]
5445          },
5446          "p5.PolySynth": {
5447            "name": "p5.PolySynth",
5448            "shortname": "p5.PolySynth",
5449            "classitems": [],
5450            "plugins": [],
5451            "extensions": [],
5452            "plugin_for": [],
5453            "extension_for": [],
5454            "module": "p5.sound",
5455            "submodule": "p5.sound",
5456            "namespace": "",
5457            "file": "lib/addons/p5.sound.js",
5458            "line": 12356,
5459            "description": "<p>An AudioVoice is used as a single voice for sound synthesis.\nThe PolySynth class holds an array of AudioVoice, and deals\nwith voices allocations, with setting notes to be played, and\nparameters to be set.</p>\n",
5460            "is_constructor": 1,
5461            "params": [{
5462              "name": "synthVoice",
5463              "description": "<p>A monophonic synth voice inheriting\n                               the AudioVoice class. Defaults to p5.MonoSynth</p>\n",
5464              "type": "Number",
5465              "optional": true
5466            }, {
5467              "name": "maxVoices",
5468              "description": "<p>Number of voices, defaults to 8;</p>\n",
5469              "type": "Number",
5470              "optional": true
5471            }],
5472            "example": ["\n<div><code>\nvar polySynth;\n\nfunction setup() {\n  var cnv = createCanvas(100, 100);\n  cnv.mousePressed(playSynth);\n\n  polySynth = new p5.PolySynth();\n\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n}\n\nfunction playSynth() {\n  // note duration (in seconds)\n  var dur = 1.5;\n\n  // time from now (in seconds)\n  var time = 0;\n\n  // velocity (volume, from 0 to 1)\n  var vel = 0.1;\n\n  // notes can overlap with each other\n  polySynth.play(\"G2\", vel, 0, dur);\n  polySynth.play(\"C3\", vel, time += 1/3, dur);\n  polySynth.play(\"G3\", vel, time += 1/3, dur);\n\n  background(random(255), random(255), 255);\n  text('click to play', width/2, height/2);\n}\n</code></div>"]
5473          },
5474          "p5.Distortion": {
5475            "name": "p5.Distortion",
5476            "shortname": "p5.Distortion",
5477            "classitems": [],
5478            "plugins": [],
5479            "extensions": [],
5480            "plugin_for": [],
5481            "extension_for": [],
5482            "module": "p5.sound",
5483            "submodule": "p5.sound",
5484            "namespace": "",
5485            "file": "lib/addons/p5.sound.js",
5486            "line": 12761,
5487            "description": "<p>A Distortion effect created with a Waveshaper Node,\nwith an approach adapted from\n<a href=\"http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion\">Kevin Ennis</a></p>\n<p>This class extends <a href = \"/reference/#/p5.Effect\">p5.Effect</a>.<br>Methods <a href = \"/reference/#/p5.Effect/amp\">amp()</a>, <a href = \"/reference/#/p5.Effect/chain\">chain()</a>, \n<a href = \"/reference/#/p5.Effect/drywet\">drywet()</a>, <a href = \"/reference/#/p5.Effect/connect\">connect()</a>, and \n<a href = \"/reference/#/p5.Effect/disconnect\">disconnect()</a> are available.</p>\n",
5488            "extends": "p5.Effect",
5489            "is_constructor": 1,
5490            "params": [{
5491              "name": "amount",
5492              "description": "<p>Unbounded distortion amount.\n                               Normal values range from 0-1.</p>\n",
5493              "type": "Number",
5494              "optional": true,
5495              "optdefault": "0.25"
5496            }, {
5497              "name": "oversample",
5498              "description": "<p>&#39;none&#39;, &#39;2x&#39;, or &#39;4x&#39;.</p>\n",
5499              "type": "String",
5500              "optional": true,
5501              "optdefault": "'none'"
5502            }]
5503          }
5504        },
5505        "elements": {},
5506        "classitems": [{
5507          "file": "src/color/color_conversion.js",
5508          "line": 10,
5509          "description": "<p>Conversions adapted from <a href=\"http://www.easyrgb.com/en/math.php\">http://www.easyrgb.com/en/math.php</a>.</p>\n<p>In these functions, hue is always in the range [0, 1], just like all other\ncomponents are in the range [0, 1]. &#39;Brightness&#39; and &#39;value&#39; are used\ninterchangeably.</p>\n",
5510          "class": "p5",
5511          "module": "Color",
5512          "submodule": "Color Conversion"
5513        }, {
5514          "file": "src/color/color_conversion.js",
5515          "line": 21,
5516          "description": "<p>Convert an HSBA array to HSLA.</p>\n",
5517          "class": "p5",
5518          "module": "Color",
5519          "submodule": "Color Conversion"
5520        }, {
5521          "file": "src/color/color_conversion.js",
5522          "line": 47,
5523          "description": "<p>Convert an HSBA array to RGBA.</p>\n",
5524          "class": "p5",
5525          "module": "Color",
5526          "submodule": "Color Conversion"
5527        }, {
5528          "file": "src/color/color_conversion.js",
5529          "line": 102,
5530          "description": "<p>Convert an HSLA array to HSBA.</p>\n",
5531          "class": "p5",
5532          "module": "Color",
5533          "submodule": "Color Conversion"
5534        }, {
5535          "file": "src/color/color_conversion.js",
5536          "line": 125,
5537          "description": "<p>Convert an HSLA array to RGBA.</p>\n<p>We need to change basis from HSLA to something that can be more easily be\nprojected onto RGBA. We will choose hue and brightness as our first two\ncomponents, and pick a convenient third one (&#39;zest&#39;) so that we don&#39;t need\nto calculate formal HSBA saturation.</p>\n",
5538          "class": "p5",
5539          "module": "Color",
5540          "submodule": "Color Conversion"
5541        }, {
5542          "file": "src/color/color_conversion.js",
5543          "line": 189,
5544          "description": "<p>Convert an RGBA array to HSBA.</p>\n",
5545          "class": "p5",
5546          "module": "Color",
5547          "submodule": "Color Conversion"
5548        }, {
5549          "file": "src/color/color_conversion.js",
5550          "line": 228,
5551          "description": "<p>Convert an RGBA array to HSLA.</p>\n",
5552          "class": "p5",
5553          "module": "Color",
5554          "submodule": "Color Conversion"
5555        }, {
5556          "file": "src/color/creating_reading.js",
5557          "line": 16,
5558          "description": "<p>Extracts the alpha value from a color or pixel array.</p>\n",
5559          "itemtype": "method",
5560          "name": "alpha",
5561          "params": [{
5562            "name": "color",
5563            "description": "<p><a href=\"#/p5.Color\">p5.Color</a> object, color components,\n                                        or CSS color</p>\n",
5564            "type": "p5.Color|Number[]|String"
5565          }],
5566          "return": {
5567            "description": "the alpha value",
5568            "type": "Number"
5569          },
5570          "example": ["\n<div>\n<code>\nnoStroke();\nlet c = color(0, 126, 255, 102);\nfill(c);\nrect(15, 15, 35, 70);\nlet value = alpha(c); // Sets 'value' to 102\nfill(value);\nrect(50, 15, 35, 70);\n</code>\n</div>"],
5571          "alt": "Left half of canvas light blue and right half light charcoal grey.\nLeft half of canvas light purple and right half a royal blue.\nLeft half of canvas salmon pink and the right half white.\nYellow rect in middle right of canvas, with 55 pixel width and height.\nYellow ellipse in top left canvas, black ellipse in bottom right,both 80x80.\nBright fuschia rect in middle of canvas, 60 pixel width and height.\nTwo bright green rects on opposite sides of the canvas, both 45x80.\nFour blue rects in each corner of the canvas, each are 35x35.\nBright sea green rect on left and darker rect on right of canvas, both 45x80.\nDark green rect on left and light green rect on right of canvas, both 45x80.\nDark blue rect on left and light teal rect on right of canvas, both 45x80.\nblue rect on left and green on right, both with black outlines & 35x60.\nsalmon pink rect on left and black on right, both 35x60.\n4 rects, tan, brown, brownish purple and purple, with white outlines & 20x60.\nlight pastel green rect on left and dark grey rect on right, both 35x60.\nyellow rect on left and red rect on right, both with black outlines & 35x60.\ngrey canvas\ndeep pink rect on left and grey rect on right, both 35x60.",
5572          "class": "p5",
5573          "module": "Color",
5574          "submodule": "Creating & Reading"
5575        }, {
5576          "file": "src/color/creating_reading.js",
5577          "line": 61,
5578          "description": "<p>Extracts the blue value from a color or pixel array.</p>\n",
5579          "itemtype": "method",
5580          "name": "blue",
5581          "params": [{
5582            "name": "color",
5583            "description": "<p><a href=\"#/p5.Color\">p5.Color</a> object, color components,\n                                        or CSS color</p>\n",
5584            "type": "p5.Color|Number[]|String"
5585          }],
5586          "return": {
5587            "description": "the blue value",
5588            "type": "Number"
5589          },
5590          "example": ["\n<div>\n<code>\nlet c = color(175, 100, 220); // Define color 'c'\nfill(c); // Use color variable 'c' as fill color\nrect(15, 20, 35, 60); // Draw left rectangle\n\nlet blueValue = blue(c); // Get blue in 'c'\nprint(blueValue); // Prints \"220.0\"\nfill(0, 0, blueValue); // Use 'blueValue' in new fill\nrect(50, 20, 35, 60); // Draw right rectangle\n</code>\n</div>"],
5591          "alt": "Left half of canvas light purple and right half a royal blue.",
5592          "class": "p5",
5593          "module": "Color",
5594          "submodule": "Creating & Reading"
5595        }, {
5596          "file": "src/color/creating_reading.js",
5597          "line": 91,
5598          "description": "<p>Extracts the HSB brightness value from a color or pixel array.</p>\n",
5599          "itemtype": "method",
5600          "name": "brightness",
5601          "params": [{
5602            "name": "color",
5603            "description": "<p><a href=\"#/p5.Color\">p5.Color</a> object, color components,\n                                        or CSS color</p>\n",
5604            "type": "p5.Color|Number[]|String"
5605          }],
5606          "return": {
5607            "description": "the brightness value",
5608            "type": "Number"
5609          },
5610          "example": ["\n<div>\n<code>\nnoStroke();\ncolorMode(HSB, 255);\nlet c = color(0, 126, 255);\nfill(c);\nrect(15, 20, 35, 60);\nlet value = brightness(c); // Sets 'value' to 255\nfill(value);\nrect(50, 20, 35, 60);\n</code>\n</div>"],
5611          "alt": "Left half of canvas salmon pink and the right half white.",
5612          "class": "p5",
5613          "module": "Color",
5614          "submodule": "Creating & Reading"
5615        }, {
5616          "file": "src/color/creating_reading.js",
5617          "line": 121,
5618          "description": "<p>Creates colors for storing in variables of the color datatype. The\nparameters are interpreted as RGB or HSB values depending on the\ncurrent <a href=\"#/p5/colorMode\">colorMode()</a>. The default mode is RGB values from 0 to 255\nand, therefore, the function call color(255, 204, 0) will return a\nbright yellow color.\n<br><br>\nNote that if only one value is provided to <a href=\"#/p5/color\">color()</a>, it will be interpreted\nas a grayscale value. Add a second value, and it will be used for alpha\ntransparency. When three values are specified, they are interpreted as\neither RGB or HSB values. Adding a fourth value applies alpha\ntransparency.\n<br><br>
5618\nIf a single string argument is provided, RGB, RGBA and Hex CSS color\nstrings and all named color strings are supported. In this case, an alpha\nnumber value as a second argument is not supported, the RGBA form should be\nused.</p>\n",
5619          "itemtype": "method",
5620          "name": "color",
5621          "return": {
5622            "description": "resulting color",
5623            "type": "p5.Color"
5624          },
5625          "example": ["\n<div>\n<code>\nlet c = color(255, 204, 0); // Define color 'c'\nfill(c); // Use color variable 'c' as fill color\nnoStroke(); // Don't draw a stroke around shapes\nrect(30, 20, 55, 55); // Draw rectangle\n</code>\n</div>\n\n<div>\n<code>\nlet c = color(255, 204, 0); // Define color 'c'\nfill(c); // Use color variable 'c' as fill color\nnoStroke(); // Don't draw a stroke around shapes\nellipse(25, 25, 80, 80); // Draw left circle\n\n// Using only one value with color()\n// generates a grayscale value.\nc = color(65); // Update 'c' with grayscale value\nfill(c); // Use updated 'c' as fill color\nellipse(75, 75, 80, 80); // Draw right circle\n</code>\n</div>\n\n<div>\n<code>\n// Named SVG & CSS colors may be used,\nlet c = color('magenta');\nfill(c); // Use 'c' as fill color\nnoStroke(); // Don't draw a stroke around shapes\nrect(20, 20, 60, 60); // Draw rectangle\n</code>\n</div>\n\n<div>\n<code>\n// as can hex color codes:\nnoStroke(); // Don't draw a stroke around shapes\nlet c = color('#0f0');\nfill(c); // Use 'c' as fill color\nrect(0, 10, 45, 80); // Draw rectangle\n\nc = color('#00ff00');\nfill(c); // Use updated 'c' as fill color\nrect(55, 10, 45, 80); // Draw rectangle\n</code>\n</div>\n\n<div>\n<code>\n// RGB and RGBA color strings are also supported:\n// these all set to the same color (solid blue)\nlet c;\nnoStroke(); // Don't draw a stroke around shapes\nc = color('rgb(0,0,255)');\nfill(c); // Use 'c' as fill color\nrect(10, 10, 35, 35); // Draw rectangle\n\nc = color('rgb(0%, 0%, 100%)');\nfill(c); // Use updated 'c' as fill color\nrect(55, 10, 35, 35); // Draw rectangle\n\nc = color('rgba(0, 0, 255, 1)');\nfill(c); // Use updated 'c' as fill color\nrect(10, 55, 35, 35); // Draw rectangle\n\nc = color('rgba(0%, 0%, 100%, 1)');\nfill(c); // Use updated 'c' as fill color\nrect(55, 55, 35, 35); // Draw rectangle\n</code>\n</div>\n\n<div>\n<code>\n// HSL color is also supported and can be specified\n// by value\nlet c;\nnoStroke(); // Don't draw a stroke around shapes\nc = color('hsl(160, 100%, 50%)');\nfill(c); // Use 'c' as fill color\nrect(0, 10, 45, 80); // Draw rectangle\n\nc = color('hsla(160, 100%, 50%, 0.5)');\nfill(c); // Use updated 'c' as fill color\nrect(55, 10, 45, 80); // Draw rectangle\n</code>\n</div>\n\n<div>\n<code>\n// HSB color is also supported and can be specified\n// by value\nlet c;\nnoStroke(); // Don't draw a stroke around shapes\nc = color('hsb(160, 100%, 50%)');\nfill(c); // Use 'c' as fill color\nrect(0, 10, 45, 80); // Draw rectangle\n\nc = color('hsba(160, 100%, 50%, 0.5)');\nfill(c); // Use updated 'c' as fill color\nrect(55, 10, 45, 80); // Draw rectangle\n</code>\n</div>\n\n<div>\n<code>\nlet c; // Declare color 'c'\nnoStroke(); // Don't draw a stroke around shapes\n\n// If no colorMode is specified, then the\n// default of RGB with scale of 0-255 is used.\nc = color(50, 55, 100); // Create a color for 'c'\nfill(c); // Use color variable 'c' as fill color\nrect(0, 10, 45, 80); // Draw left rect\n\ncolorMode(HSB, 100); // Use HSB with scale of 0-100\nc = color(50, 55, 100); // Update 'c' with new color\nfill(c); // Use updated 'c' as fill color\nrect(55, 10, 45, 80); // Draw right rect\n</code>\n</div>"],
5626          "alt": "Yellow rect in middle right of canvas, with 55 pixel width and height.\nYellow ellipse in top left of canvas, black ellipse in bottom right,both 80x80.\nBright fuschia rect in middle of canvas, 60 pixel width and height.\nTwo bright green rects on opposite sides of the canvas, both 45x80.\nFour blue rects in each corner of the canvas, each are 35x35.\nBright sea green rect on left and darker rect on right of canvas, both 45x80.\nDark green rect on left and lighter green rect on right of canvas, both 45x80.\nDark blue rect on left and light teal rect on right of canvas, both 45x80.",
5627          "class": "p5",
5628          "module": "Color",
5629          "submodule": "Creating & Reading",
5630          "overloads": [{
5631            "line": 121,
5632            "params": [{
5633              "name": "gray",
5634              "description": "<p>number specifying value between white\n                                and black.</p>\n",
5635              "type": "Number"
5636            }, {
5637              "name": "alpha",
5638              "description": "<p>alpha value relative to current color range\n                                (default is 0-255)</p>\n",
5639              "type": "Number",
5640              "optional": true
5641            }],
5642            "return": {
5643              "description": "resulting color",
5644              "type": "p5.Color"
5645            }
5646          }, {
5647            "line": 280,
5648            "params": [{
5649              "name": "v1",
5650              "description": "<p>red or hue value relative to\n                                the current color range</p>\n",
5651              "type": "Number"
5652            }, {
5653              "name": "v2",
5654              "description": "<p>
5654green or saturation value\n                                relative to the current color range</p>\n",
5655              "type": "Number"
5656            }, {
5657              "name": "v3",
5658              "description": "<p>blue or brightness value\n                                relative to the current color range</p>\n",
5659              "type": "Number"
5660            }, {
5661              "name": "alpha",
5662              "description": "",
5663              "type": "Number",
5664              "optional": true
5665            }],
5666            "return": {
5667              "description": "",
5668              "type": "p5.Color"
5669            }
5670          }, {
5671            "line": 292,
5672            "params": [{
5673              "name": "value",
5674              "description": "<p>a color string</p>\n",
5675              "type": "String"
5676            }],
5677            "return": {
5678              "description": "",
5679              "type": "p5.Color"
5680            }
5681          }, {
5682            "line": 297,
5683            "params": [{
5684              "name": "values",
5685              "description": "<p>an array containing the red,green,blue &amp;\n                                and alpha components of the color</p>\n",
5686              "type": "Number[]"
5687            }],
5688            "return": {
5689              "description": "",
5690              "type": "p5.Color"
5691            }
5692          }, {
5693            "line": 303,
5694            "params": [{
5695              "name": "color",
5696              "description": "",
5697              "type": "p5.Color"
5698            }],
5699            "return": {
5700              "description": "",
5701              "type": "p5.Color"
5702            }
5703          }]
5704        }, {
5705          "file": "src/color/creating_reading.js",
5706          "line": 319,
5707          "description": "<p>Extracts the green value from a color or pixel array.</p>\n",
5708          "itemtype": "method",
5709          "name": "green",
5710          "params": [{
5711            "name": "color",
5712            "description": "<p><a href=\"#/p5.Color\">p5.Color</a> object, color components,\n                                        or CSS color</p>\n",
5713            "type": "p5.Color|Number[]|String"
5714          }],
5715          "return": {
5716            "description": "the green value",
5717            "type": "Number"
5718          },
5719          "example": ["\n<div>\n<code>\nlet c = color(20, 75, 200); // Define color 'c'\nfill(c); // Use color variable 'c' as fill color\nrect(15, 20, 35, 60); // Draw left rectangle\n\nlet greenValue = green(c); // Get green in 'c'\nprint(greenValue); // Print \"75.0\"\nfill(0, greenValue, 0); // Use 'greenValue' in new fill\nrect(50, 20, 35, 60); // Draw right rectangle\n</code>\n</div>"],
5720          "alt": "blue rect on left and green on right, both with black outlines & 35x60.",
5721          "class": "p5",
5722          "module": "Color",
5723          "submodule": "Creating & Reading"
5724        }, {
5725          "file": "src/color/creating_reading.js",
5726          "line": 350,
5727          "description": "<p>Extracts the hue value from a color or pixel array.</p>\n<p>Hue exists in both HSB and HSL. This function will return the\nHSB-normalized hue when supplied with an HSB color object (or when supplied\nwith a pixel array while the color mode is HSB), but will default to the\nHSL-normalized hue otherwise. (The values will only be different if the\nmaximum hue setting for each system is different.)</p>\n",
5728          "itemtype": "method",
5729          "name": "hue",
5730          "params": [{
5731            "name": "color",
5732            "description": "<p><a href=\"#/p5.Color\">p5.Color</a> object, color components,\n                                        or CSS color</p>\n",
5733            "type": "p5.Color|Number[]|String"
5734          }],
5735          "return": {
5736            "description": "the hue",
5737            "type": "Number"
5738          },
5739          "example": ["\n<div>\n<code>\nnoStroke();\ncolorMode(HSB, 255);\nlet c = color(0, 126, 255);\nfill(c);\nrect(15, 20, 35, 60);\nlet value = hue(c); // Sets 'value' to \"0\"\nfill(value);\nrect(50, 20, 35, 60);\n</code>\n</div>"],
5740          "alt": "salmon pink rect on left and black on right, both 35x60.",
5741          "class": "p5",
5742          "module": "Color",
5743          "submodule": "Creating & Reading"
5744        }, {
5745          "file": "src/color/creating_reading.js",
5746          "line": 387,
5747          "description": "<p>Blends two colors to find a third color somewhere between them. The amt\nparameter is the amount to interpolate between the two values where 0.0\nequal to the first color, 0.1 is very near the first color, 0.5 is halfway\nin between, etc. An amount below 0 will be treated as 0. Likewise, amounts\nabove 1 will be capped at 1. This is different from the behavior of <a href=\"#/p5/lerp\">lerp()</a>,\nbut necessary because otherwise numbers outside the range will produce\nstrange and unexpected colors.\n<br><br>\nThe way that colours are interpolated depends on the current color mode.</p>\n",
5748          "itemtype": "method",
5749          "name": "lerpColor",
5750          "params": [{
5751            "name": "c1",
5752            "description": "<p>interpolate from this color</p>\n",
5753            "type": "p5.Color"
5754          }, {
5755            "name": "c2",
5756            "description": "<p>interpolate to this color</p>\n",
5757            "type": "p5.Color"
5758          }, {
5759            "name": "amt",
5760            "description": "<p>number between 0 and 1</p>\n",
5761            "type": "Number"
5762          }],
5763          "return": {
5764            "description": "interpolated color",
5765            "type": "p5.Color"
5766          },
5767          "example": ["\n<div>\n<code>\ncolorMode(RGB);
5767\nstroke(255);\nbackground(51);\nlet from = color(218, 165, 32);\nlet to = color(72, 61, 139);\ncolorMode(RGB); // Try changing to HSB.\nlet interA = lerpColor(from, to, 0.33);\nlet interB = lerpColor(from, to, 0.66);\nfill(from);\nrect(10, 20, 20, 60);\nfill(interA);\nrect(30, 20, 20, 60);\nfill(interB);\nrect(50, 20, 20, 60);\nfill(to);\nrect(70, 20, 20, 60);\n</code>\n</div>"],
5768          "alt": "4 rects one tan, brown, brownish purple, purple, with white outlines & 20x60",
5769          "class": "p5",
5770          "module": "Color",
5771          "submodule": "Creating & Reading"
5772        }, {
5773          "file": "src/color/creating_reading.js",
5774          "line": 484,
5775          "description": "<p>Extracts the HSL lightness value from a color or pixel array.</p>\n",
5776          "itemtype": "method",
5777          "name": "lightness",
5778          "params": [{
5779            "name": "color",
5780            "description": "<p><a href=\"#/p5.Color\">p5.Color</a> object, color components,\n                                        or CSS color</p>\n",
5781            "type": "p5.Color|Number[]|String"
5782          }],
5783          "return": {
5784            "description": "the lightness",
5785            "type": "Number"
5786          },
5787          "example": ["\n<div>\n<code>\nnoStroke();\ncolorMode(HSL);\nlet c = color(156, 100, 50, 1);\nfill(c);\nrect(15, 20, 35, 60);\nlet value = lightness(c); // Sets 'value' to 50\nfill(value);\nrect(50, 20, 35, 60);\n</code>\n</div>"],
5788          "alt": "light pastel green rect on left and dark grey rect on right, both 35x60.",
5789          "class": "p5",
5790          "module": "Color",
5791          "submodule": "Creating & Reading"
5792        }, {
5793          "file": "src/color/creating_reading.js",
5794          "line": 514,
5795          "description": "<p>Extracts the red value from a color or pixel array.</p>\n",
5796          "itemtype": "method",
5797          "name": "red",
5798          "params": [{
5799            "name": "color",
5800            "description": "<p><a href=\"#/p5.Color\">p5.Color</a> object, color components,\n                                        or CSS color</p>\n",
5801            "type": "p5.Color|Number[]|String"
5802          }],
5803          "return": {
5804            "description": "the red value",
5805            "type": "Number"
5806          },
5807          "example": ["\n<div>\n<code>\nlet c = color(255, 204, 0); // Define color 'c'\nfill(c); // Use color variable 'c' as fill color\nrect(15, 20, 35, 60); // Draw left rectangle\n\nlet redValue = red(c); // Get red in 'c'\nprint(redValue); // Print \"255.0\"\nfill(redValue, 0, 0); // Use 'redValue' in new fill\nrect(50, 20, 35, 60); // Draw right rectangle\n</code>\n</div>\n\n<div>\n<code>\ncolorMode(RGB, 255);\nlet c = color(127, 255, 0);\ncolorMode(RGB, 1);\nlet myColor = red(c);\nprint(myColor);\n</code>\n</div>"],
5808          "alt": "yellow rect on left and red rect on right, both with black outlines and 35x60.\ngrey canvas",
5809          "class": "p5",
5810          "module": "Color",
5811          "submodule": "Creating & Reading"
5812        }, {
5813          "file": "src/color/creating_reading.js",
5814          "line": 554,
5815          "description": "<p>Extracts the saturation value from a color or pixel array.</p>\n<p>Saturation is scaled differently in HSB and HSL. This function will return\nthe HSB saturation when supplied with an HSB color object (or when supplied\nwith a pixel array while the color mode is HSB), but will default to the\nHSL saturation otherwise.</p>\n",
5816          "itemtype": "method",
5817          "name": "saturation",
5818          "params": [{
5819            "name": "color",
5820            "description": "<p><a href=\"#/p5.Color\">p5.Color</a> object, color components,\n                                        or CSS color</p>\n",
5821            "type": "p5.Color|Number[]|String"
5822          }],
5823          "return": {
5824            "description": "the saturation value",
5825            "type": "Number"
5826          },
5827          "example": ["\n<div>\n<code>\nnoStroke();\ncolorMode(HSB, 255);\nlet c = color(0, 126, 255);\nfill(c);\nrect(15, 20, 35, 60);\nlet value = saturation(c); // Sets 'value' to 126\nfill(value);\nrect(50, 20, 35, 60);\n</code>\n</div>"],
5828          "alt": "deep pink rect on left and grey rect on right, both 35x60.",
5829          "class": "p5",
5830          "module": "Color",
5831          "submodule": "Creating & Reading"
5832        }, {
5833          "file": "src/color/p5.Color.js",
5834          "line": 52,
5835          "description": "<p>This function returns the color formatted as a string. This can be useful\nfor debugging, or for using p5.js with other libraries.</p>\n",
5836          "itemtype": "method",
5837          "name": "toString",
5838          "params": [{
5839            "name": "format",
5840            "description": "<p>How the color string will be formatted.\nLeaving this empty formats the string as rgba(r, g, b, a).\n&#39;#rgb&#39; &#39;#rgba&#39; &#39;#rrggbb&#39; and &#39;#rrggbbaa&#39; format as hexadecimal color codes.\n&#39;rgb&#39; &#39;hsb&#39; and &#39;hsl&#39; return the color formatted in the specified color mode.\n&#39;rgba&#39; &#39;hsba&#39; and &#39;hsla&#39; are the same as above but with alpha channels.\n&#39;rgb%&#39; &#39;hsb%&#39; &#39;hsl%&#39; &#39;rgba%&#39; &#39;hsba%&#39; and &#39;hsla%&#39; format as percentages.</p>\n",
5841            "type": "String",
5842            "optional": true
5843          }],
5844          "return": {
5845            "description": "the formatted string",
5846            "type": "String"
5847          },
5848          "example": ["\n<div>\n<code>\nlet myColor;\nfunction setup() {\n  createCanvas(200, 200);
5848\n  stroke(255);\n  myColor = color(100, 100, 250);\n  fill(myColor);\n}\n\nfunction draw() {\n  rotate(HALF_PI);\n  text(myColor.toString(), 0, -5);\n  text(myColor.toString('#rrggbb'), 0, -30);\n  text(myColor.toString('rgba%'), 0, -55);\n}\n</code>\n</div>"],
5849          "alt": "canvas with text representation of color",
5850          "class": "p5.Color",
5851          "module": "Color",
5852          "submodule": "Creating & Reading"
5853        }, {
5854          "file": "src/color/p5.Color.js",
5855          "line": 248,
5856          "itemtype": "method",
5857          "name": "setRed",
5858          "params": [{
5859            "name": "red",
5860            "description": "<p>the new red value</p>\n",
5861            "type": "Number"
5862          }],
5863          "example": ["\n<div>\n<code>\nlet backgroundColor;\n\nfunction setup() {\n  backgroundColor = color(100, 50, 150);\n}\n\nfunction draw() {\n  backgroundColor.setRed(128 + 128 * sin(millis() / 1000));\n  background(backgroundColor);\n}\n</code>\n</div>"],
5864          "alt": "canvas with gradually changing background color",
5865          "class": "p5.Color",
5866          "module": "Color",
5867          "submodule": "Creating & Reading"
5868        }, {
5869          "file": "src/color/p5.Color.js",
5870          "line": 275,
5871          "itemtype": "method",
5872          "name": "setGreen",
5873          "params": [{
5874            "name": "green",
5875            "description": "<p>the new green value</p>\n",
5876            "type": "Number"
5877          }],
5878          "example": ["\n<div>\n<code>\nlet backgroundColor;\n\nfunction setup() {\n  backgroundColor = color(100, 50, 150);\n}\n\nfunction draw() {\n  backgroundColor.setGreen(128 + 128 * sin(millis() / 1000));\n  background(backgroundColor);\n}\n</code>\n</div>"],
5879          "alt": "canvas with gradually changing background color",
5880          "class": "p5.Color",
5881          "module": "Color",
5882          "submodule": "Creating & Reading"
5883        }, {
5884          "file": "src/color/p5.Color.js",
5885          "line": 302,
5886          "itemtype": "method",
5887          "name": "setBlue",
5888          "params": [{
5889            "name": "blue",
5890            "description": "<p>the new blue value</p>\n",
5891            "type": "Number"
5892          }],
5893          "example": ["\n<div>\n<code>\nlet backgroundColor;\n\nfunction setup() {\n  backgroundColor = color(100, 50, 150);\n}\n\nfunction draw() {\n  backgroundColor.setBlue(128 + 128 * sin(millis() / 1000));\n  background(backgroundColor);\n}\n</code>\n</div>"],
5894          "alt": "canvas with gradually changing background color",
5895          "class": "p5.Color",
5896          "module": "Color",
5897          "submodule": "Creating & Reading"
5898        }, {
5899          "file": "src/color/p5.Color.js",
5900          "line": 329,
5901          "itemtype": "method",
5902          "name": "setAlpha",
5903          "params": [{
5904            "name": "alpha",
5905            "description": "<p>the new alpha value</p>\n",
5906            "type": "Number"
5907          }],
5908          "example": ["\n<div>\n<code>\nlet squareColor;\n\nfunction setup() {\n  ellipseMode(CORNERS);\n  strokeWeight(4);\n  squareColor = color(100, 50, 150);\n}\n\nfunction draw() {\n  background(255);\n\n  noFill();\n  stroke(0);\n  ellipse(10, 10, width - 10, height - 10);\n\n  squareColor.setAlpha(128 + 128 * sin(millis() / 1000));\n  fill(squareColor);\n  noStroke();\n  rect(13, 13, width - 26, height - 26);\n}\n</code>\n</div>"],
5909          "alt": "circle behind a square with gradually changing opacity",
5910          "class": "p5.Color",
5911          "module": "Color",
5912          "submodule": "Creating & Reading"
5913        }, {
5914          "file": "src/color/p5.Color.js",
5915          "line": 410,
5916          "description": "<p>Hue is the same in HSB and HSL, but the maximum value may be different.\nThis function will return the HSB-normalized saturation when supplied with\nan HSB color object, but will default to the HSL-normalized saturation\notherwise.</p>\n",
5917          "class": "p5.Color",
5918          "module": "Color",
5919          "submodule": "Creating & Reading"
5920        }, {
5921          "file": "src/color/p5.Color.js",
5922          "line": 441,
5923          "description": "<p>Saturation is scaled differently in HSB and HSL. This function will return\nthe HSB saturation when supplied with an HSB color object, but will default\nto the HSL saturation otherwise.</p>\n",
5924          "class": "p5.Color",
5925          "module": "Color",
5926          "submodule": "Creating & Reading"
5927        }, {
5928          "file": "src/color/p5.Color.js",
5929          "line": 460,
5930          "description": "<p>CSS named colors.</p>\n",
5931          "class": "p5.Color",
5932          "module": "Color",
5933          "submodule": "Creating & Reading"
5934        }, {
5935          "file": "src/color/p5.Color.js",
5936          "line": 613,
5937          "description": "<p>These regular expressions are used to build up the patterns for matching\nviable CSS color strings: fragmenting the regexes in this way increases the\nlegibility and comprehensibility of the code.</p>\n<p>Note that RGB values of .9 are not parsed by IE, but are supported here for\ncolor string consistency.</p>\n",
5938          "class": "p5.Color",
5939          "module": "Color",
5940          "submodule": "Creating & Reading"
5941        }, {
5942          "file": "src/color/p5.Color.js",
5943          "line": 626,
5944          "description": "<p>Full color string patterns. The capture groups are necessary.</p>\n",
5945          "class": "p5.Color",
5946          "module": "Color",
5947          "submodule": "Creating & Reading"
5948        }, {
5949          "file": "src/color/p5.Color.js",
5950          "line": 989,
5951          "description": "<p>For HSB and HSL, interpret the gray level as a brightness/lightness\nvalue (they are equivalent when chroma is zero). For RGB, normalize the\ngray level according to the blue maximum.</p>\n",
5952          "class": "p5.Color",
5953          "module": "Color",
5954          "submodule": "Creating & Reading"
5955        }, {
5956          "file": "src/color/setting.js",
5957          "line": 15,
5958          "description": "<p>The <a href=\"#/p5/background\">background()</a> function sets the color used for the background of the\np5.js canvas. The default background is transparent. This function is\ntypically used within <a href=\"#/p5/draw\">draw()</a> to clear the display window at the beginning\nof each frame, but it can be used inside <a href=\"#/p5/setup\">setup()</a> to set the background on\nthe first frame of animation or if the background need only be set once.\n<br><br>\nThe color is either specified in terms of the RGB, HSB, or HSL color\ndepending on the current <a href=\"#/p5/colorMode\">
5958colorMode</a>. (The default color space is RGB, with\neach value in the range from 0 to 255). The alpha range by default is also 0 to 255.\n<br><br>\nIf a single string argument is provided, RGB, RGBA and Hex CSS color strings\nand all named color strings are supported. In this case, an alpha number\nvalue as a second argument is not supported, the RGBA form should be used.\n<br><br>\nA <a href=\"#/p5.Color\">p5.Color</a> object can also be provided to set the background color.\n<br><br>\nA <a href=\"#/p5.Image\">p5.Image</a> can also be provided to set the background image.</p>\n",
5959          "itemtype": "method",
5960          "name": "background",
5961          "chainable": 1,
5962          "example": ["\n<div>\n<code>\n// Grayscale integer value\nbackground(51);\n</code>\n</div>\n\n<div>\n<code>\n// R, G & B integer values\nbackground(255, 204, 0);\n</code>\n</div>\n\n<div>\n<code>\n// H, S & B integer values\ncolorMode(HSB);\nbackground(255, 204, 100);\n</code>\n</div>\n\n<div>\n<code>\n// Named SVG/CSS color string\nbackground('red');\n</code>\n</div>\n\n<div>\n<code>\n// three-digit hexadecimal RGB notation\nbackground('#fae');\n</code>\n</div>\n\n<div>\n<code>\n// six-digit hexadecimal RGB notation\nbackground('#222222');\n</code>\n</div>\n\n<div>\n<code>\n// integer RGB notation\nbackground('rgb(0,255,0)');\n</code>\n</div>\n\n<div>\n<code>\n// integer RGBA notation\nbackground('rgba(0,255,0, 0.25)');\n</code>\n</div>\n\n<div>\n<code>\n// percentage RGB notation\nbackground('rgb(100%,0%,10%)');\n</code>\n</div>\n\n<div>\n<code>\n// percentage RGBA notation\nbackground('rgba(100%,0%,100%,0.5)');\n</code>\n</div>\n\n<div>\n<code>\n// p5 Color object\nbackground(color(0, 0, 255));\n</code>\n</div>"],
5963          "alt": "canvas with darkest charcoal grey background.\ncanvas with yellow background.\ncanvas with royal blue background.\ncanvas with red background.\ncanvas with pink background.\ncanvas with black background.\ncanvas with bright green background.\ncanvas with soft green background.\ncanvas with red background.\ncanvas with light purple background.\ncanvas with blue background.",
5964          "class": "p5",
5965          "module": "Color",
5966          "submodule": "Setting",
5967          "overloads": [{
5968            "line": 15,
5969            "params": [{
5970              "name": "color",
5971              "description": "<p>any value created by the <a href=\"#/p5/color\">color()</a> function</p>\n",
5972              "type": "p5.Color"
5973            }],
5974            "chainable": 1
5975          }, {
5976            "line": 131,
5977            "params": [{
5978              "name": "colorstring",
5979              "description": "<p>color string, possible formats include: integer\n                        rgb() or rgba(), percentage rgb() or rgba(),\n                        3-digit hex, 6-digit hex</p>\n",
5980              "type": "String"
5981            }, {
5982              "name": "a",
5983              "description": "<p>opacity of the background relative to current\n                            color range (default is 0-255)</p>\n",
5984              "type": "Number",
5985              "optional": true
5986            }],
5987            "chainable": 1
5988          }, {
5989            "line": 141,
5990            "params": [{
5991              "name": "gray",
5992              "description": "<p>specifies a value between white and black</p>\n",
5993              "type": "Number"
5994            }, {
5995              "name": "a",
5996              "description": "",
5997              "type": "Number",
5998              "optional": true
5999            }],
6000            "chainable": 1
6001          }, {
6002            "line": 148,
6003            "params": [{
6004              "name": "v1",
6005              "description": "<p>red or hue value (depending on the current color\n                       mode)</p>\n",
6006              "type": "Number"
6007            }, {
6008              "name": "v2",
6009              "description": "<p>green or saturation value (depending on the current\n                       color mode)</p>\n",
6010              "type": "Number"
6011            }, {
6012              "name": "v3",
6013              "description": "<p>blue or brightness value (depending on the current\n                       color mode)</p>\n",
6014              "type": "Number"
6015            }, {
6016              "name": "a",
6017              "description": "",
6018              "type": "Number",
6019              "optional": true
6020            }],
6021            "chainable": 1
6022          }, {
6023            "line": 160,
6024            "params": [{
6025              "name": "values",
6026              "description": "<p>an array containing the red,green,blue &amp;\n                                and alpha components of the color</p>\n",
6027              "type": "Number[]"
6028            }],
6029            "chainable": 1
6030          }, {
6031            "line": 167,
6032            "params": [{
6033              "name": "image",
6034              "description": "<p>image created with <a href=\"#/p5/loadImage\">loadImage()</a> or <a href=\"#/p5/createImage\">createImage()</a>,\n                            to set as background\n                            (must be same size as the sketch window)</p>\n",
6035              "type": "p5.Image"
6036            }, {
6037              "name": "a",
6038              "description": "",
6039              "type": "Number",
6040              "optional": true
6041            }],
6042            "chainable": 1
6043          }]
6044        }, {
6045          "file": "src/color/setting.js",
6046          "line": 185,
6047          "description": "<p>Clears the pixels within a buffer. This function only works on p5.Canvas\nobjects created with the <a href=\"#/p5/createCanvas\">createCanvas()</a> function; it won&#39;t work with the\nmain display window. Unlike the main graphics context, pixels in\nadditional graphics areas created with <a href=\"#/p5/createGraphics\">createGraphics()</a> can be entirely\nor partially transparent. This function clears everything to make all of\nthe pixels 100% transparent.</p>\n",
6048          "itemtype": "method",
6049          "name": "clear",
6050          "chainable": 1,
6051          "example": ["\n<div>\n<code>\n// Clear the screen on mouse press.\nfunction setup() {\n  createCanvas(100, 100);\n}\n\nfunction draw() {\n  ellipse(mouseX, mouseY, 20, 20);\n}\n\nfunction mousePressed() {\n  clear();\n}\n</code>\n</div>"],
6052          "alt": "20x20 white ellipses are continually drawn at mouse x and y coordinates.",
6053          "class": "p5",
6054          "module": "Color",
6055          "submodule": "Setting"
6056        }, {
6057          "file": "src/color/setting.js",
6058          "line": 223,
6059          "description": "<p><a href=\"#/p5/colorMode\">colorMode()</a> changes the way p5.js interprets color data. By default, the\nparameters for <a href=\"#/p5/fill\">fill()</a>, <a href=\"#/p5/stroke\">stroke()</a>, <a href=\"#/p5/background\">background()</a>, and <a href=\"#/p5/color\">color()</a> are defined by\nvalues between 0 and 255 using the RGB color model. This is equivalent to\nsetting colorMode(RGB, 255). Setting colorMode(HSB) lets you use the HSB\nsystem instead. By default, this is colorMode(HSB, 360, 100, 100, 1). You\ncan also use HSL.\n<br><br>\nNote: existing color objects remember the mode that they were created in,\nso you can change modes as you like without affecting their appearance.</p>\n",
6060          "itemtype": "method",
6061          "name": "colorMode",
6062          "chainable": 1,
6063          "example": ["\n<div>\n<code>\nnoStroke();\ncolorMode(RGB, 100);\nfor (let i = 0; i < 100; i++) {\n  for (let j = 0; j < 100; j++) {\n    stroke(i, j, 0);\n    point(i, j);\n  }\n}\n</code>\n</div>\n\n<div>\n<code>\nnoStroke();\ncolorMode(HSB, 100);\nfor (let i = 0; i < 100; i++) {\n  for (let j = 0; j < 100; j++) {\n    stroke(i, j, 100);\n    point(i, j);\n  }\n}\n</code>\n</div>\n\n<div>\n<code>\ncolorMode(RGB, 255);\nlet c = color(127, 255, 0);\n\ncolorMode(RGB, 1);\nlet myColor = c._getRed();\ntext(myColor, 10, 10, 80, 80);\n</code>\n</div>\n\n<div>\n<code>\nnoFill();\ncolorMode(RGB, 255, 255, 255, 1);\nbackground(255);\n\nstrokeWeight(4);\nstroke(255, 0, 10, 0.3);\nellipse(40, 40, 50, 50);\nellipse(50, 50, 40, 40);\n</code>\n</div>"],
6064          "alt": "Green to red gradient from bottom L to top R. shading originates from top left.\nRainbow gradient from left to right. Brightness increasing to white at top.\nunknown image.\n50x50 ellipse at middle L & 40x40 ellipse at center. Transluscent pink outlines.",
6065          "class": "p5",
6066          "module": "Color",
6067          "submodule": "Setting",
6068          "overloads": [{
6069            "line": 223,
6070            "params": [{
6071              "name": "mode",
6072              "description": "<p>either RGB, HSB or HSL, corresponding to\n                         Red/Green/Blue and Hue/Saturation/Brightness\n                         (or Lightness)</p>\n",
6073              "type": "Constant"
6074            }, {
6075              "name": "max",
6076              "description": "<p>range for all values</p>\n",
6077              "type": "Number",
6078              "optional": true
6079            }],
6080            "chainable": 1
6081          }, {
6082            "line": 300,
6083            "params": [{
6084              "name": "mode",
6085              "description": "",
6086              "type": "Constant"
6087            }, {
6088              "name": "max1",
6089              "description": "<p>range for the red or hue depending on the\n                             current color mode</p>\n",
6090              "type": "Number"
6091            }, {
6092              "name": "max2",
6093              "description": "<p>range for the green or saturation depending\n                             on the current color mode</p>\n",
6094              "type": "Number"
6095            }, {
6096              "name": "max3",
6097              "description": "<p>range for the blue or brightness/lighntess\n                             depending on the current color mode</p>\n",
6098              "type": "Number"
6099            }, {
6100              "name": "maxA",
6101              "description": "<p>range for the alpha</p>\n",
6102              "type": "Number",
6103              "optional": true
6104            }],
6105            "chainable": 1
6106          }]
6107        }, {
6108          "file": "src/color/setting.js",
6109          "line": 344,
6110          "description": "<p>Sets the color used to fill shapes. For example, if you run\nfill(204, 102, 0), all subsequent shapes will be filled with orange. This\ncolor is either specified in terms of the RGB or HSB color depending on\nthe current <a href=\"#/p5/colorMode\">colorMode()</a>. (The default color space is RGB, with each value\nin the range from 0 to 255). The alpha range by default is also 0 to 255.\n<br><br>
6110\nIf a single string argument is provided, RGB, RGBA and Hex CSS color strings\nand all named color strings are supported. In this case, an alpha number\nvalue as a second argument is not supported, the RGBA form should be used.\n<br><br>\nA p5 <a href=\"#/p5.Color\">Color</a> object can also be provided to set the fill color.</p>\n",
6111          "itemtype": "method",
6112          "name": "fill",
6113          "chainable": 1,
6114          "example": ["\n<div>\n<code>\n// Grayscale integer value\nfill(51);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// R, G & B integer values\nfill(255, 204, 0);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// H, S & B integer values\ncolorMode(HSB);\nfill(255, 204, 100);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// Named SVG/CSS color string\nfill('red');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// three-digit hexadecimal RGB notation\nfill('#fae');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// six-digit hexadecimal RGB notation\nfill('#222222');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// integer RGB notation\nfill('rgb(0,255,0)');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// integer RGBA notation\nfill('rgba(0,255,0, 0.25)');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// percentage RGB notation\nfill('rgb(100%,0%,10%)');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// percentage RGBA notation\nfill('rgba(100%,0%,100%,0.5)');\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// p5 Color object\nfill(color(0, 0, 255));\nrect(20, 20, 60, 60);\n</code>\n</div>"],
6115          "alt": "60x60 dark charcoal grey rect with black outline in center of canvas.\n60x60 yellow rect with black outline in center of canvas.\n60x60 royal blue rect with black outline in center of canvas.\n60x60 red rect with black outline in center of canvas.\n60x60 pink rect with black outline in center of canvas.\n60x60 black rect with black outline in center of canvas.\n60x60 light green rect with black outline in center of canvas.\n60x60 soft green rect with black outline in center of canvas.\n60x60 red rect with black outline in center of canvas.\n60x60 dark fushcia rect with black outline in center of canvas.\n60x60 blue rect with black outline in center of canvas.",
6116          "class": "p5",
6117          "module": "Color",
6118          "submodule": "Setting",
6119          "overloads": [{
6120            "line": 344,
6121            "params": [{
6122              "name": "v1",
6123              "description": "<p>red or hue value relative to\n                                the current color range</p>\n",
6124              "type": "Number"
6125            }, {
6126              "name": "v2",
6127              "description": "<p>green or saturation value\n                                relative to the current color range</p>\n",
6128              "type": "Number"
6129            }, {
6130              "name": "v3",
6131              "description": "<p>blue or brightness value\n                                relative to the current color range</p>\n",
6132              "type": "Number"
6133            }, {
6134              "name": "alpha",
6135              "description": "",
6136              "type": "Number",
6137              "optional": true
6138            }],
6139            "chainable": 1
6140          }, {
6141            "line": 469,
6142            "params": [{
6143              "name": "value",
6144              "description": "<p>a color string</p>\n",
6145              "type": "String"
6146            }],
6147            "chainable": 1
6148          }, {
6149            "line": 475,
6150            "params": [{
6151              "name": "gray",
6152              "description": "<p>a gray value</p>\n",
6153              "type": "Number"
6154            }, {
6155              "name": "alpha",
6156              "description": "",
6157              "type": "Number",
6158              "optional": true
6159            }],
6160            "chainable": 1
6161          }, {
6162            "line": 482,
6163            "params": [{
6164              "name": "values",
6165              "description": "<p>an array containing the red,green,blue &amp;\n                                and alpha components of the color</p>\n",
6166              "type": "Number[]"
6167            }],
6168            "chainable": 1
6169          }, {
6170            "line": 489,
6171            "params": [{
6172              "name": "color",
6173              "description": "<p>the fill color</p>\n",
6174              "type": "p5.Color"
6175            }],
6176            "chainable": 1
6177          }]
6178        }, {
6179          "file": "src/color/setting.js",
6180          "line": 501,
6181          "description": "<p>Disables filling geometry. If both <a href=\"#/p5/noStroke\">noStroke()</a> and <a href=\"#/p5/noFill\">noFill()</a> are called,\nnothing will be drawn to the screen.</p>\n",
6182          "itemtype": "method",
6183          "name": "noFill",
6184          "chainable": 1,
6185          "example": ["\n<div>\n<code>\nrect(15, 10, 55, 55);\nnoFill();\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(0);\n  noFill();\n  stroke(100, 100, 240);\n  rotateX(frameCount * 0.01);\n  rotateY(frameCount * 0.01);\n  box(45, 45, 45);\n}\n</code>\n</div>"],
6186          "alt": "white rect top middle and noFill rect center. Both 60x60 with black outlines.\nblack canvas with purple cube wireframe spinning",
6187          "class": "p5",
6188          "module": "Color",
6189          "submodule": "Setting"
6190        }, {
6191          "file": "src/color/setting.js",
6192          "line": 542,
6193          "description": "<p>Disables drawing the stroke (outline). If both <a href=\"#/p5/noStroke\">noStroke()</a> and <a href=\"#/p5/noFill\">noFill()</a>
6193\nare called, nothing will be drawn to the screen.</p>\n",
6194          "itemtype": "method",
6195          "name": "noStroke",
6196          "chainable": 1,
6197          "example": ["\n<div>\n<code>\nnoStroke();\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(0);\n  noStroke();\n  fill(240, 150, 150);\n  rotateX(frameCount * 0.01);\n  rotateY(frameCount * 0.01);\n  box(45, 45, 45);\n}\n</code>\n</div>"],
6198          "alt": "60x60 white rect at center. no outline.\nblack canvas with pink cube spinning",
6199          "class": "p5",
6200          "module": "Color",
6201          "submodule": "Setting"
6202        }, {
6203          "file": "src/color/setting.js",
6204          "line": 582,
6205          "description": "<p>Sets the color used to draw lines and borders around shapes. This color\nis either specified in terms of the RGB or HSB color depending on the\ncurrent <a href=\"#/p5/colorMode\">colorMode()</a> (the default color space is RGB, with each value in\nthe range from 0 to 255). The alpha range by default is also 0 to 255.\n<br><br>\nIf a single string argument is provided, RGB, RGBA and Hex CSS color\nstrings and all named color strings are supported. In this case, an alpha\nnumber value as a second argument is not supported, the RGBA form should be\nused.\n<br><br>\nA p5 <a href=\"#/p5.Color\">Color</a> object can also be provided to set the stroke color.</p>\n",
6206          "itemtype": "method",
6207          "name": "stroke",
6208          "chainable": 1,
6209          "example": ["\n<div>\n<code>\n// Grayscale integer value\nstrokeWeight(4);\nstroke(51);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// R, G & B integer values\nstroke(255, 204, 0);\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// H, S & B integer values\ncolorMode(HSB);\nstrokeWeight(4);\nstroke(255, 204, 100);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// Named SVG/CSS color string\nstroke('red');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// three-digit hexadecimal RGB notation\nstroke('#fae');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// six-digit hexadecimal RGB notation\nstroke('#222222');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// integer RGB notation\nstroke('rgb(0,255,0)');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// integer RGBA notation\nstroke('rgba(0,255,0,0.25)');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// percentage RGB notation\nstroke('rgb(100%,0%,10%)');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// percentage RGBA notation\nstroke('rgba(100%,0%,100%,0.5)');\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>\n\n<div>\n<code>\n// p5 Color object\nstroke(color(0, 0, 255));\nstrokeWeight(4);\nrect(20, 20, 60, 60);\n</code>\n</div>"],
6210          "alt": "60x60 white rect at center. Dark charcoal grey outline.\n60x60 white rect at center. Yellow outline.\n60x60 white rect at center. Royal blue outline.\n60x60 white rect at center. Red outline.\n60x60 white rect at center. Pink outline.\n60x60 white rect at center. Black outline.\n60x60 white rect at center. Bright green outline.\n60x60 white rect at center. Soft green outline.\n60x60 white rect at center. Red outline.\n60x60 white rect at center. Dark fushcia outline.\n60x60 white rect at center. Blue outline.",
6211          "class": "p5",
6212          "module": "Color",
6213          "submodule": "Setting",
6214          "overloads": [{
6215            "line": 582,
6216            "params": [{
6217              "name": "v1",
6218              "description": "<p>red or hue value relative to\n                                the current color range</p>\n",
6219              "type": "Number"
6220            }, {
6221              "name": "v2",
6222              "description": "<p>green or saturation value\n                                relative to the current color range</p>\n",
6223              "type": "Number"
6224            }, {
6225              "name": "v3",
6226              "description": "<p>
6226blue or brightness value\n                                relative to the current color range</p>\n",
6227              "type": "Number"
6228            }, {
6229              "name": "alpha",
6230              "description": "",
6231              "type": "Number",
6232              "optional": true
6233            }],
6234            "chainable": 1
6235          }, {
6236            "line": 721,
6237            "params": [{
6238              "name": "value",
6239              "description": "<p>a color string</p>\n",
6240              "type": "String"
6241            }],
6242            "chainable": 1
6243          }, {
6244            "line": 727,
6245            "params": [{
6246              "name": "gray",
6247              "description": "<p>a gray value</p>\n",
6248              "type": "Number"
6249            }, {
6250              "name": "alpha",
6251              "description": "",
6252              "type": "Number",
6253              "optional": true
6254            }],
6255            "chainable": 1
6256          }, {
6257            "line": 734,
6258            "params": [{
6259              "name": "values",
6260              "description": "<p>an array containing the red,green,blue &amp;\n                                and alpha components of the color</p>\n",
6261              "type": "Number[]"
6262            }],
6263            "chainable": 1
6264          }, {
6265            "line": 741,
6266            "params": [{
6267              "name": "color",
6268              "description": "<p>the stroke color</p>\n",
6269              "type": "p5.Color"
6270            }],
6271            "chainable": 1
6272          }]
6273        }, {
6274          "file": "src/core/shape/2d_primitives.js",
6275          "line": 16,
6276          "description": "<p>Draw an arc to the screen. If called with only x, y, w, h, start, and\nstop, the arc will be drawn and filled as an open pie segment. If a mode parameter is provided, the arc\nwill be filled like an open semi-circle (OPEN) , a closed semi-circle (CHORD), or as a closed pie segment (PIE). The\norigin may be changed with the <a href=\"#/p5/ellipseMode\">ellipseMode()</a> function.<br><br>\nNote that drawing a full circle (ex: 0 to TWO_PI) will appear blank\nbecause 0 and TWO_PI are the same position on the unit circle. The\nbest way to handle this is by using the <a href=\"#/p5/ellipse\">ellipse()</a> function instead\nto create a closed ellipse, and to use the <a href=\"#/p5/arc\">arc()</a> function\nonly to draw parts of an ellipse.</p>\n",
6277          "itemtype": "method",
6278          "name": "arc",
6279          "params": [{
6280            "name": "x",
6281            "description": "<p>x-coordinate of the arc&#39;s ellipse</p>\n",
6282            "type": "Number"
6283          }, {
6284            "name": "y",
6285            "description": "<p>y-coordinate of the arc&#39;s ellipse</p>\n",
6286            "type": "Number"
6287          }, {
6288            "name": "w",
6289            "description": "<p>width of the arc&#39;s ellipse by default</p>\n",
6290            "type": "Number"
6291          }, {
6292            "name": "h",
6293            "description": "<p>height of the arc&#39;s ellipse by default</p>\n",
6294            "type": "Number"
6295          }, {
6296            "name": "start",
6297            "description": "<p>angle to start the arc, specified in radians</p>\n",
6298            "type": "Number"
6299          }, {
6300            "name": "stop",
6301            "description": "<p>angle to stop the arc, specified in radians</p>\n",
6302            "type": "Number"
6303          }, {
6304            "name": "mode",
6305            "description": "<p>optional parameter to determine the way of drawing\n                        the arc. either CHORD, PIE or OPEN</p>\n",
6306            "type": "Constant",
6307            "optional": true
6308          }, {
6309            "name": "detail",
6310            "description": "<p>optional parameter for WebGL mode only. This is to\n                        specify the number of vertices that makes up the\n                        perimeter of the arc. Default value is 25.</p>\n",
6311            "type": "Number",
6312            "optional": true
6313          }],
6314          "chainable": 1,
6315          "example": ["\n<div>\n<code>\narc(50, 55, 50, 50, 0, HALF_PI);\nnoFill();\narc(50, 55, 60, 60, HALF_PI, PI);\narc(50, 55, 70, 70, PI, PI + QUARTER_PI);\narc(50, 55, 80, 80, PI + QUARTER_PI, TWO_PI);\n</code>\n</div>\n\n<div>\n<code>\narc(50, 50, 80, 80, 0, PI + QUARTER_PI);\n</code>\n</div>\n\n<div>\n<code>\narc(50, 50, 80, 80, 0, PI + QUARTER_PI, OPEN);\n</code>\n</div>\n\n<div>\n<code>\narc(50, 50, 80, 80, 0, PI + QUARTER_PI, CHORD);\n</code>\n</div>\n\n<div>\n<code>\narc(50, 50, 80, 80, 0, PI + QUARTER_PI, PIE);\n</code>\n</div>"],
6316          "alt": "shattered outline of an ellipse with a quarter of a white circle bottom-right.\nwhite ellipse with top right quarter missing.\nwhite ellipse with black outline with top right missing.\nwhite ellipse with top right missing with black outline around shape.\nwhite ellipse with top right quarter missing with black outline around the shape.",
6317          "class": "p5",
6318          "module": "Shape",
6319          "submodule": "2D Primitives"
6320        }, {
6321          "file": "src/core/shape/2d_primitives.js",
6322          "line": 149,
6323          "description": "<p>Draws an ellipse (oval) to the screen. An ellipse with equal width and\nheight is a circle. By default, the first two parameters set the location,\nand the third and fourth parameters set the shape&#39;
6323s width and height. If\nno height is specified, the value of width is used for both the width and\nheight. If a negative height or width is specified, the absolute value is taken.\nThe origin may be changed with the <a href=\"#/p5/ellipseMode\">ellipseMode()</a> function.</p>\n",
6324          "itemtype": "method",
6325          "name": "ellipse",
6326          "chainable": 1,
6327          "example": ["\n<div>\n<code>\nellipse(56, 46, 55, 55);\n</code>\n</div>"],
6328          "alt": "white ellipse with black outline in middle-right of canvas that is 55x55.",
6329          "class": "p5",
6330          "module": "Shape",
6331          "submodule": "2D Primitives",
6332          "overloads": [{
6333            "line": 149,
6334            "params": [{
6335              "name": "x",
6336              "description": "<p>x-coordinate of the ellipse.</p>\n",
6337              "type": "Number"
6338            }, {
6339              "name": "y",
6340              "description": "<p>y-coordinate of the ellipse.</p>\n",
6341              "type": "Number"
6342            }, {
6343              "name": "w",
6344              "description": "<p>width of the ellipse.</p>\n",
6345              "type": "Number"
6346            }, {
6347              "name": "h",
6348              "description": "<p>height of the ellipse.</p>\n",
6349              "type": "Number",
6350              "optional": true
6351            }],
6352            "chainable": 1
6353          }, {
6354            "line": 174,
6355            "params": [{
6356              "name": "x",
6357              "description": "",
6358              "type": "Number"
6359            }, {
6360              "name": "y",
6361              "description": "",
6362              "type": "Number"
6363            }, {
6364              "name": "w",
6365              "description": "",
6366              "type": "Number"
6367            }, {
6368              "name": "h",
6369              "description": "",
6370              "type": "Number"
6371            }, {
6372              "name": "detail",
6373              "description": "<p>number of radial sectors to draw (for WebGL mode)</p>\n",
6374              "type": "Integer"
6375            }]
6376          }]
6377        }, {
6378          "file": "src/core/shape/2d_primitives.js",
6379          "line": 209,
6380          "description": "<p>Draws a circle to the screen. A circle is a simple closed shape.\nIt is the set of all points in a plane that are at a given distance from a given point, the centre.\nThis function is a special case of the ellipse() function, where the width and height of the ellipse are the same.\nHeight and width of the ellipse is equal to twice the radius of the circle..\nBy default, the first two parameters set the location of the centre of the circle, the third sets the radius of the circle.</p>\n",
6381          "itemtype": "method",
6382          "name": "circle",
6383          "params": [{
6384            "name": "x",
6385            "description": "<p>x-coordinate of the centre of the circle.</p>\n",
6386            "type": "Number"
6387          }, {
6388            "name": "y",
6389            "description": "<p>y-coordinate of the centre of the circle.</p>\n",
6390            "type": "Number"
6391          }, {
6392            "name": "r",
6393            "description": "<p>radius of the circle.</p>\n",
6394            "type": "Number"
6395          }],
6396          "chainable": 1,
6397          "example": ["\n<div>\n<code>\n// Draw a circle at location (30, 30) with a radius of 20.\ncircle(30, 30, 20);\n</code>\n</div>"],
6398          "alt": "white circle with black outline in mid of canvas that is 55x55.",
6399          "class": "p5",
6400          "module": "Shape",
6401          "submodule": "2D Primitives"
6402        }, {
6403          "file": "src/core/shape/2d_primitives.js",
6404          "line": 239,
6405          "description": "<p>Draws a line (a direct path between two points) to the screen. The version\nof <a href=\"#/p5/line\">line()</a> with four parameters draws the line in 2D. To color a line, use\nthe <a href=\"#/p5/stroke\">stroke()</a> function. A line cannot be filled, therefore the <a href=\"#/p5/fill\">fill()</a>\nfunction will not affect the color of a line. 2D lines are drawn with a\nwidth of one pixel by default, but this can be changed with the\n<a href=\"#/p5/strokeWeight\">
6405strokeWeight()</a> function.</p>\n",
6406          "itemtype": "method",
6407          "name": "line",
6408          "chainable": 1,
6409          "example": ["\n<div>\n<code>\nline(30, 20, 85, 75);\n</code>\n</div>\n\n<div>\n<code>\nline(30, 20, 85, 20);\nstroke(126);\nline(85, 20, 85, 75);\nstroke(255);\nline(85, 75, 30, 75);\n</code>\n</div>"],
6410          "alt": "line 78 pixels long running from mid-top to bottom-right of canvas.\n3 lines of various stroke sizes. Form top, bottom and right sides of a square.",
6411          "class": "p5",
6412          "module": "Shape",
6413          "submodule": "2D Primitives",
6414          "overloads": [{
6415            "line": 239,
6416            "params": [{
6417              "name": "x1",
6418              "description": "<p>the x-coordinate of the first point</p>\n",
6419              "type": "Number"
6420            }, {
6421              "name": "y1",
6422              "description": "<p>the y-coordinate of the first point</p>\n",
6423              "type": "Number"
6424            }, {
6425              "name": "x2",
6426              "description": "<p>the x-coordinate of the second point</p>\n",
6427              "type": "Number"
6428            }, {
6429              "name": "y2",
6430              "description": "<p>the y-coordinate of the second point</p>\n",
6431              "type": "Number"
6432            }],
6433            "chainable": 1
6434          }, {
6435            "line": 275,
6436            "params": [{
6437              "name": "x1",
6438              "description": "",
6439              "type": "Number"
6440            }, {
6441              "name": "y1",
6442              "description": "",
6443              "type": "Number"
6444            }, {
6445              "name": "z1",
6446              "description": "<p>the z-coordinate of the first point</p>\n",
6447              "type": "Number"
6448            }, {
6449              "name": "x2",
6450              "description": "",
6451              "type": "Number"
6452            }, {
6453              "name": "y2",
6454              "description": "",
6455              "type": "Number"
6456            }, {
6457              "name": "z2",
6458              "description": "<p>the z-coordinate of the second point</p>\n",
6459              "type": "Number"
6460            }],
6461            "chainable": 1
6462          }]
6463        }, {
6464          "file": "src/core/shape/2d_primitives.js",
6465          "line": 295,
6466          "description": "<p>Draws a point, a coordinate in space at the dimension of one pixel.\nThe first parameter is the horizontal value for the point, the second\nvalue is the vertical value for the point. The color of the point is\ndetermined by the current stroke.</p>\n",
6467          "itemtype": "method",
6468          "name": "point",
6469          "params": [{
6470            "name": "x",
6471            "description": "<p>the x-coordinate</p>\n",
6472            "type": "Number"
6473          }, {
6474            "name": "y",
6475            "description": "<p>the y-coordinate</p>\n",
6476            "type": "Number"
6477          }, {
6478            "name": "z",
6479            "description": "<p>the z-coordinate (for WebGL mode)</p>\n",
6480            "type": "Number",
6481            "optional": true
6482          }],
6483          "chainable": 1,
6484          "example": ["\n<div>\n<code>\npoint(30, 20);\npoint(85, 20);\npoint(85, 75);\npoint(30, 75);\n</code>\n</div>"],
6485          "alt": "4 points centered in the middle-right of the canvas.",
6486          "class": "p5",
6487          "module": "Shape",
6488          "submodule": "2D Primitives"
6489        }, {
6490          "file": "src/core/shape/2d_primitives.js",
6491          "line": 330,
6492          "description": "<p>Draw a quad. A quad is a quadrilateral, a four sided polygon. It is\nsimilar to a rectangle, but the angles between its edges are not\nconstrained to ninety degrees. The first pair of parameters (x1,y1)\nsets the first vertex and the subsequent pairs should proceed\nclockwise or counter-clockwise around the defined shape.</p>\n",
6493          "itemtype": "method",
6494          "name": "quad",
6495          "chainable": 1,
6496          "example": ["\n<div>\n<code>\nquad(38, 31, 86, 20, 69, 63, 30, 76);\n</code>\n</div>"],
6497          "alt": "irregular white quadrilateral shape with black outline mid-right of canvas.",
6498          "class": "p5",
6499          "module": "Shape",
6500          "submodule": "2D Primitives",
6501          "overloads": [{
6502            "line": 330,
6503            "params": [{
6504              "name": "x1",
6505              "description": "<p>the x-coordinate of the first point</p>\n",
6506              "type": "Number"
6507            }, {
6508              "name": "y1",
6509              "description": "<p>the y-coordinate of the first point</p>\n",
6510              "type": "Number"
6511            }, {
6512              "name": "x2",
6513              "description": "<p>the x-coordinate of the second point</p>\n",
6514              "type": "Number"
6515            }, {
6516              "name": "y2",
6517              "description": "<p>the y-coordinate of the second point</p>\n",
6518              "type": "Number"
6519            }, {
6520              "name": "x3",
6521              "description": "<p>the x-coordinate of the third point</p>\n",
6522              "type": "Number"
6523            }, {
6524              "name": "y3",
6525              "description": "<p>the y-coordinate of the third point</p>\n",
6526              "type": "Number"
6527            }, {
6528              "name": "x4",
6529              "description": "<p>the x-coordinate of the fourth point</p>\n",
6530              "type": "Number"
6531            }, {
6532              "name": "y4",
6533              "description": "<p>the y-coordinate of the fourth point</p>\n",
6534              "type": "Number"
6535            }],
6536            "chainable": 1
6537          }, {
6538            "line": 358,
6539            "params": [{
6540              "name": "x1",
6541              "description": "",
6542              "type": "Number"
6543            }, {
6544              "name": "y1",
6545              "description": "",
6546              "type": "Number"
6547            }, {
6548              "name": "z1",
6549              "description": "<p>the z-coordinate of the first point</p>\n",
6550              "type": "Number"
6551            }, {
6552              "name": "x2",
6553              "description": "",
6554              "type": "Number"
6555            }, {
6556              "name": "y2",
6557              "description": "",
6558              "type": "Number"
6559            }, {
6560              "name": "z2",
6561              "description": "<p>the z-coordinate of the second point</p>\n",
6562              "type": "Number"
6563            }, {
6564              "name": "x3",
6565              "description": "",
6566              "type": "Number"
6567            }, {
6568              "name": "y3",
6569              "description": "",
6570              "type": "Number"
6571            }, {
6572              "name": "z3",
6573              "description": "<p>the z-coordinate of the third point</p>\n",
6574              "type": "Number"
6575            }, {
6576              "name": "x4",
6577              "description": "",
6578              "type": "Number"
6579            }, {
6580              "name": "y4",
6581              "description": "",
6582              "type": "Number"
6583            }, {
6584              "name": "z4",
6585              "description": "<p>the z-coordinate of the fourth point</p>\n",
6586              "type": "Number"
6587            }],
6588            "chainable": 1
6589          }]
6590        }, {
6591          "file": "src/core/shape/2d_primitives.js",
6592          "line": 384,
6593          "description": "<p>Draws a rectangle to the screen. A rectangle is a four-sided shape with\nevery angle at ninety degrees. By default, the first two parameters set\nthe location of the upper-left corner, the third sets the width, and the\nfourth sets the height. The way these parameters are interpreted, however,\nmay be changed with the <a href=\"#/p5/rectMode\">rectMode()</a> function.\n<br><br>\nThe fifth, sixth, seventh and eighth parameters, if specified,\ndetermine corner radius for the top-left, top-right, lower-right and\nlower-left corners, respectively. An omitted corner radius parameter is set\nto the value of the previously specified radius value in the parameter list.</p>\n",
6594          "itemtype": "method",
6595          "name": "rect",
6596          "chainable": 1,
6597          "example": ["\n<div>\n<code>\n// Draw a rectangle at location (30, 20) with a width and height of 55.\nrect(30, 20, 55, 55);\n</code>\n</div>\n\n<div>\n<code>\n// Draw a rectangle with rounded corners, each having a radius of 20.\nrect(30, 20, 55, 55, 20);\n</code>\n</div>\n\n<div>\n<code>\n// Draw a rectangle with rounded corners having the following radii:\n// top-left = 20, top-right = 15, bottom-right = 10, bottom-left = 5.\nrect(30, 20, 55, 55, 20, 15, 10, 5);\n</code>\n</div>"],
6598          "alt": "55x55 white rect with black outline in mid-right of canvas.\n55x55 white rect with black outline and rounded edges in mid-right of canvas.\n55x55 white rect with black outline and rounded edges of different radii.",
6599          "class": "p5",
6600          "module": "Shape",
6601          "submodule": "2D Primitives",
6602          "overloads": [{
6603            "line": 384,
6604            "params": [{
6605              "name": "x",
6606              "description": "<p>x-coordinate of the rectangle.</p>\n",
6607              "type": "Number"
6608            }, {
6609              "name": "y",
6610              "description": "<p>y-coordinate of the rectangle.</p>\n",
6611              "type": "Number"
6612            }, {
6613              "name": "w",
6614              "description": "<p>width of the rectangle.</p>\n",
6615              "type": "Number"
6616            }, {
6617              "name": "h",
6618              "description": "<p>height of the rectangle.</p>\n",
6619              "type": "Number"
6620            }, {
6621              "name": "tl",
6622              "description": "<p>optional radius of top-left corner.</p>\n",
6623              "type": "Number",
6624              "optional": true
6625            }, {
6626              "name": "tr",
6627              "description": "<p>optional radius of top-right corner.</p>\n",
6628              "type": "Number",
6629              "optional": true
6630            }, {
6631              "name": "br",
6632              "description": "<p>optional radius of bottom-right corner.</p>\n",
6633              "type": "Number",
6634              "optional": true
6635            }, {
6636              "name": "bl",
6637              "description": "<p>optional radius of bottom-left corner.</p>\n",
6638              "type": "Number",
6639              "optional": true
6640            }],
6641            "chainable": 1
6642          }, {
6643            "line": 434,
6644            "params": [{
6645              "name": "x",
6646              "description": "",
6647              "type": "Number"
6648            }, {
6649              "name": "y",
6650              "description": "",
6651              "type": "Number"
6652            }, {
6653              "name": "w",
6654              "description": "",
6655              "type": "Number"
6656            }, {
6657              "name": "h",
6658              "description": "",
6659              "type": "Number"
6660            }, {
6661              "name": "detailX",
6662              "description": "<p>number of segments in the x-direction (for WebGL mode)</p>\n",
6663              "type": "Integer",
6664              "optional": true
6665            }, {
6666              "name": "detailY",
6667              "description": "<p>number of segments in the y-direction (for WebGL mode)</p>\n",
6668              "type": "Integer",
6669              "optional": true
6670            }],
6671            "chainable": 1
6672          }]
6673        }, {
6674          "file": "src/core/shape/2d_primitives.js",
6675          "line": 467,
6676          "description": "<p>Draws a square to the screen. A square is a four-sided shape with\nevery angle at ninety degrees, and equal side size.\nThis function is a special case of the rect() function, where the width and height are the same, and the parameter is called &quot;s&quot; for side size.\nBy default, the first two parameters set the location of the upper-left corner, the third sets the side size of the square.\nThe way these parameters are interpreted, however,\nmay be changed with the <a href=\"#/p5/rectMode\">rectMode()</a> function.\n<br><br>\nThe fourth, fifth, sixth and seventh parameters, if specified,\ndetermine corner radius for the top-left, top-right, lower-right and\nlower-left corners, respectively. An omitted corner radius parameter is set\nto the value of the previously specified radius value in the parameter list.</p>\n",
6677          "itemtype": "method",
6678          "name": "square",
6679          "params": [{
6680            "name": "x",
6681            "description": "<p>x-coordinate of the square.</p>\n",
6682            "type": "Number"
6683          }, {
6684            "name": "y",
6685            "description": "<p>y-coordinate of the square.</p>\n",
6686            "type": "Number"
6687          }, {
6688            "name": "s",
6689            "description": "<p>side size of the square.</p>\n",
6690            "type": "Number"
6691          }, {
6692            "name": "tl",
6693            "description": "<p>optional radius of top-left corner.</p>\n",
6694            "type": "Number",
6695            "optional": true
6696          }, {
6697            "name": "tr",
6698            "description": "<p>optional radius of top-right corner.</p>\n",
6699            "type": "Number",
6700            "optional": true
6701          }, {
6702            "name": "br",
6703            "description": "<p>optional radius of bottom-right corner.</p>\n",
6704            "type": "Number",
6705            "optional": true
6706          }, {
6707            "name": "bl",
6708            "description": "<p>optional radius of bottom-left corner.</p>\n",
6709            "type": "Number",
6710            "optional": true
6711          }],
6712          "chainable": 1,
6713          "example": ["\n<div>\n<code>\n// Draw a square at location (30, 20) with a side size of 55.\nsquare(30, 20, 55);\n</code>\n</div>\n\n<div>\n<code>\n// Draw a square with rounded corners, each having a radius of 20.\nsquare(30, 20, 55, 20);\n</code>\n</div>\n\n<div>\n<code>\n// Draw a square with rounded corners having the following radii:\n// top-left = 20, top-right = 15, bottom-right = 10, bottom-left = 5.\nsquare(30, 20, 55, 20, 15, 10, 5);\n</code>\n</div>"],
6714          "alt": "55x55 white square with black outline in mid-right of canvas.\n55x55 white square with black outline and rounded edges in mid-right of canvas.\n55x55 white square with black outline and rounded edges of different radii.",
6715          "class": "p5",
6716          "module": "Shape",
6717          "submodule": "2D Primitives"
6718        }, {
6719          "file": "src/core/shape/2d_primitives.js",
6720          "line": 524,
6721          "description": "<p>A triangle is a plane created by connecting three points. The first two\narguments specify the first point, the middle two arguments specify the\nsecond point, and the last two arguments specify the third point.</p>\n",
6722          "itemtype": "method",
6723          "name": "triangle",
6724          "params": [{
6725            "name": "x1",
6726            "description": "<p>x-coordinate of the first point</p>\n",
6727            "type": "Number"
6728          }, {
6729            "name": "y1",
6730            "description": "<p>y-coordinate of the first point</p>\n",
6731            "type": "Number"
6732          }, {
6733            "name": "x2",
6734            "description": "<p>x-coordinate of the second point</p>\n",
6735            "type": "Number"
6736          }, {
6737            "name": "y2",
6738            "description": "<p>y-coordinate of the second point</p>\n",
6739            "type": "Number"
6740          }, {
6741            "name": "x3",
6742            "description": "<p>x-coordinate of the third point</p>\n",
6743            "type": "Number"
6744          }, {
6745            "name": "y3",
6746            "description": "<p>y-coordinate of the third point</p>\n",
6747            "type": "Number"
6748          }],
6749          "chainable": 1,
6750          "example": ["\n<div>\n<code>\ntriangle(30, 75, 58, 20, 86, 75);\n</code>\n</div>"],
6751          "alt": "white triangle with black outline in mid-right of canvas.",
6752          "class": "p5",
6753          "module": "Shape",
6754          "submodule": "2D Primitives"
6755        }, {
6756          "file": "src/core/shape/attributes.js",
6757          "line": 14,
6758          "description": "<p>Modifies the location from which ellipses are drawn by changing the way\nin which parameters given to <a href=\"#/p5/ellipse\">ellipse()</a> are interpreted.\n<br><br>\nThe default mode is ellipseMode(CENTER), which interprets the first two\nparameters of <a href=\"#/p5/ellipse\">ellipse()</a> as the shape&#39;s center point, while the third and\nfourth parameters are its width and height.\n<br><br>\nellipseMode(RADIUS) also uses the first two parameters of <a href=\"#/p5/ellipse\">ellipse()</a> as\nthe shape&#39;s center point, but uses the
6758 third and fourth parameters to\nspecify half of the shapes&#39;s width and height.\n<br><br>\nellipseMode(CORNER) interprets the first two parameters of <a href=\"#/p5/ellipse\">ellipse()</a> as\nthe upper-left corner of the shape, while the third and fourth parameters\nare its width and height.\n<br><br>\nellipseMode(CORNERS) interprets the first two parameters of <a href=\"#/p5/ellipse\">ellipse()</a> as\nthe location of one corner of the ellipse&#39;s bounding box, and the third\nand fourth parameters as the location of the opposite corner.\n<br><br>\nThe parameter must be written in ALL CAPS because Javascript is a\ncase-sensitive language.</p>\n",
6759          "itemtype": "method",
6760          "name": "ellipseMode",
6761          "params": [{
6762            "name": "mode",
6763            "description": "<p>either CENTER, RADIUS, CORNER, or CORNERS</p>\n",
6764            "type": "Constant"
6765          }],
6766          "chainable": 1,
6767          "example": ["\n<div>\n<code>\nellipseMode(RADIUS); // Set ellipseMode to RADIUS\nfill(255); // Set fill to white\nellipse(50, 50, 30, 30); // Draw white ellipse using RADIUS mode\n\nellipseMode(CENTER); // Set ellipseMode to CENTER\nfill(100); // Set fill to gray\nellipse(50, 50, 30, 30); // Draw gray ellipse using CENTER mode\n</code>\n</div>\n\n<div>\n<code>\nellipseMode(CORNER); // Set ellipseMode is CORNER\nfill(255); // Set fill to white\nellipse(25, 25, 50, 50); // Draw white ellipse using CORNER mode\n\nellipseMode(CORNERS); // Set ellipseMode to CORNERS\nfill(100); // Set fill to gray\nellipse(25, 25, 50, 50); // Draw gray ellipse using CORNERS mode\n</code>\n</div>"],
6768          "alt": "60x60 white ellipse and 30x30 grey ellipse with black outlines at center.\n60x60 white ellipse @center and 30x30 grey ellipse top-right, black outlines.",
6769          "class": "p5",
6770          "module": "Shape",
6771          "submodule": "Attributes"
6772        }, {
6773          "file": "src/core/shape/attributes.js",
6774          "line": 83,
6775          "description": "<p>Draws all geometry with jagged (aliased) edges. Note that <a href=\"#/p5/smooth\">smooth()</a> is\nactive by default in 2D mode, so it is necessary to call <a href=\"#/p5/noSmooth\">noSmooth()</a> to disable\nsmoothing of geometry, images, and fonts. In 3D mode, <a href=\"#/p5/noSmooth\">noSmooth()</a> is enabled\nby default, so it is necessary to call <a href=\"#/p5/smooth\">smooth()</a> if you would like\nsmooth (antialiased) edges on your geometry.</p>\n",
6776          "itemtype": "method",
6777          "name": "noSmooth",
6778          "chainable": 1,
6779          "example": ["\n<div>\n<code>\nbackground(0);\nnoStroke();\nsmooth();\nellipse(30, 48, 36, 36);\nnoSmooth();\nellipse(70, 48, 36, 36);\n</code>\n</div>"],
6780          "alt": "2 pixelated 36x36 white ellipses to left & right of center, black background",
6781          "class": "p5",
6782          "module": "Shape",
6783          "submodule": "Attributes"
6784        }, {
6785          "file": "src/core/shape/attributes.js",
6786          "line": 113,
6787          "description": "<p>Modifies the location from which rectangles are drawn by changing the way\nin which parameters given to <a href=\"#/p5/rect\">rect()</a> are interpreted.\n<br><br>\nThe default mode is rectMode(CORNER), which interprets the first two\nparameters of <a href=\"#/p5/rect\">rect()</a> as the upper-left corner of the shape, while the\nthird and fourth parameters are its width and height.\n<br><br>\nrectMode(CORNERS) interprets the first two parameters of <a href=\"#/p5/rect\">rect()</a> as the\nlocation of one corner, and the third and fourth parameters as the\nlocation of the opposite corner.\n<br><br>\nrectMode(CENTER) interprets the first two parameters of <a href=\"#/p5/rect\">rect()</a> as the\nshape&#39;s center point, while the third and fourth parameters are its\nwidth and height.\n<br><br>\nrectMode(RADIUS) also uses the first two parameters of <a href=\"#/p5/rect\">rect()</a> as the\nshape&#39;s center point, but uses the third and fourth parameters to specify\nhalf of the shapes&#39;s width and height.\n<br><br>\nThe parameter must be written in ALL CAPS because Javascript is a\ncase-sensitive language.</p>\n",
6788          "itemtype": "method",
6789          "name": "rectMode",
6790          "params": [{
6791            "name": "mode",
6792            "description": "<p>either CORNER, CORNERS, CENTER, or RADIUS</p>\n",
6793            "type": "Constant"
6794          }],
6795          "chainable": 1,
6796          "example": ["\n<div>\n<code>\nrectMode(CORNER); // Default rectMode is CORNER\nfill(255); // Set fill to white\nrect(25, 25, 50, 50); // Draw white rect using CORNER mode\n\nrectMode(CORNERS); // Set rectMode to CORNERS\nfill(100); // Set fill to gray\nrect(25, 25, 50, 50); // Draw gray rect using CORNERS mode\n</code>\n</div>\n\n<div>\n<code>\nrectMode(RADIUS); // Set rectMode to RADIUS\nfill(255); // Set fill to white\nrect(50, 50, 30, 30); // Draw white rect using RADIUS mode\n\nrectMode(CENTER); // Set rectMode to CENTER\nfill(100); // Set fill to gray\nrect(50, 50, 30, 30); // Draw gray rect using CENTER mode\n</code>\n</div>"],
6797          "alt": "50x50 white rect at center and 25x25 grey rect in the top left of the other.\n50x50 white rect at center and 25x25 grey rect in the center of the other.",
6798          "class": "p5",
6799          "module": "Shape",
6800          "submodule": "Attributes"
6801        }, {
6802          "file": "src/core/shape/attributes.js",
6803          "line": 182,
6804          "description": "<p>Draws all geometry with smooth (anti-aliased) edges. <a href=\"#/p5/smooth\">smooth()</a> will also\nimprove image quality of resized images. Note that <a href=\"#/p5/smooth\">smooth()</a> is active by\ndefault in 2D mode; <a href=\"#/p5/noSmooth\">noSmooth()</a> can be used to disable smoothing of geometry,\nimages, and fonts. In 3D mode, <a href=\"#/p5/noSmooth\">noSmooth()</a> is enabled\nby default, so it is necessary to call <a href=\"#/p5/smooth\">smooth()</a> if you would like\nsmooth (antialiased) edges on your geometry.</p>\n",
6805          "itemtype": "method",
6806          "name": "smooth",
6807          "chainable": 1,
6808          "example": ["\n<div>\n<code>\nbackground(0);\nnoStroke();\nsmooth();\nellipse(30, 48, 36, 36);\nnoSmooth();\nellipse(70, 48, 36, 36);\n</code>\n</div>"],
6809          "alt": "2 pixelated 36x36 white ellipses one left one right of center. On black.",
6810          "class": "p5",
6811          "module": "Shape",
6812          "submodule": "Attributes"
6813        }, {
6814          "file": "src/core/shape/attributes.js",
6815          "line": 213,
6816          "description": "<p>Sets the style for rendering line endings. These ends are either squared,\nextended, or rounded, each of which specified with the corresponding\nparameters: SQUARE, PROJECT, and ROUND. The default cap is ROUND.</p>\n",
6817          "itemtype": "method",
6818          "name": "strokeCap",
6819          "params": [{
6820            "name": "cap",
6821            "description": "<p>either SQUARE, PROJECT, or ROUND</p>\n",
6822            "type": "Constant"
6823          }],
6824          "chainable": 1,
6825          "example": ["\n<div>\n<code>\nstrokeWeight(12.0);\nstrokeCap(ROUND);\nline(20, 30, 80, 30);\nstrokeCap(SQUARE);\nline(20, 50, 80, 50);\nstrokeCap(PROJECT);\nline(20, 70, 80, 70);\n</code>\n</div>"],
6826          "alt": "3 lines. Top line: rounded ends, mid: squared, bottom:longer squared ends.",
6827          "class": "p5",
6828          "module": "Shape",
6829          "submodule": "Attributes"
6830        }, {
6831          "file": "src/core/shape/attributes.js",
6832          "line": 250,
6833          "description": "<p>Sets the style of the joints which connect line segments. These joints\nare either mitered, beveled, or rounded and specified with the\ncorresponding parameters MITER, BEVEL, and ROUND. The default joint is\nMITER.</p>\n",
6834          "itemtype": "method",
6835          "name": "strokeJoin",
6836          "params": [{
6837            "name": "join",
6838            "description": "<p>either MITER, BEVEL, ROUND</p>\n",
6839            "type": "Constant"
6840          }],
6841          "chainable": 1,
6842          "example": ["\n<div>\n<code>\nnoFill();\nstrokeWeight(10.0);\nstrokeJoin(MITER);\nbeginShape();\nvertex(35, 20);\nvertex(65, 50);\nvertex(35, 80);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nnoFill();\nstrokeWeight(10.0);\nstrokeJoin(BEVEL);\nbeginShape();\nvertex(35, 20);\nvertex(65, 50);\nvertex(35, 80);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nnoFill();\nstrokeWeight(10.0);\nstrokeJoin(ROUND);\nbeginShape();\nvertex(35, 20);\nvertex(65, 50);\nvertex(35, 80);\nendShape();\n</code>\n</div>"],
6843          "alt": "Right-facing arrowhead shape with pointed tip in center of canvas.\nRight-facing arrowhead shape with flat tip in center of canvas.\nRight-facing arrowhead shape with rounded tip in center of canvas.",
6844          "class": "p5",
6845          "module": "Shape",
6846          "submodule": "Attributes"
6847        }, {
6848          "file": "src/core/shape/attributes.js",
6849          "line": 317,
6850          "description": "<p>Sets the width of the stroke used for lines, points, and the border\naround shapes. All widths are set in units of pixels.</p>\n",
6851          "itemtype": "method",
6852          "name": "strokeWeight",
6853          "params": [{
6854            "name": "weight",
6855            "description": "<p>the weight (in pixels) of the stroke</p>\n",
6856            "type": "Number"
6857          }],
6858          "chainable": 1,
6859          "example": ["\n<div>\n<code>\nstrokeWeight(1); // Default\nline(20, 20, 80, 20);\nstrokeWeight(4); // Thicker\nline(20, 40, 80, 40);\nstrokeWeight(10); // Beastly\nline(20, 70, 80, 70);\n</code>\n</div>"],
6860          "alt": "3 horizontal black lines. Top line: thin, mid: medium, bottom:thick.",
6861          "class": "p5",
6862          "module": "Shape",
6863          "submodule": "Attributes"
6864        }, {
6865          "file": "src/core/shape/curves.js",
6866          "line": 13,
6867          "description": "<p>Draws a cubic Bezier curve on the screen. These curves are defined by a\nseries of anchor and control points. The first two parameters specify\nthe first anchor point and the last two parameters specify the other\nanchor point, which become the first and last points on the curve. The\nmiddle parameters specify the two control points which define the shape\nof the curve. Approximately speaking, control points &quot;pull&quot; the curve\ntowards them.<br /><br />Bezier curves were developed by French\nautomotive engineer Pierre Bezier, and are commonly used in computer\ngraphics to define gently sloping curves. See also <a href=\"#/p5/curve\">curve()</a>.</p>\n",
6868          "itemtype": "method",
6869          "name": "bezier",
6870          "chainable": 1,
6871          "example": ["\n<div>\n<code>\nnoFill();\nstroke(255, 102, 0);\nline(85, 20, 10, 10);\nline(90, 90, 15, 80);\nstroke(0, 0, 0);\nbezier(85, 20, 10, 10, 90, 90, 15, 80);\n</code>\n</div>\n\n<div>\n<code>\nbackground(0, 0, 0);\nnoFill();\nstroke(255);\nbezier(250, 250, 0, 100, 100, 0, 100, 0, 0, 0, 100, 0);\n</code>\n</div>"],
6872          "alt": "stretched black s-shape in center with orange lines extending from end points.\nstretched black s-shape with 10 5x5 white ellipses along the shape.\nstretched black s-shape with 7 5x5 ellipses and orange lines along the shape.\nstretched black s-shape with 17 small orange lines extending from under shape.\nhorseshoe shape with orange ends facing left and black curved center.\nhorseshoe shape with orange ends facing left and black curved center.\nLine shaped like right-facing arrow,points move with mouse-x and warp shape.\nhorizontal line that hooks downward on the right and 13 5x5 ellipses along it.\nright curving line mid-right of canvas with 7 short lines radiating from it.",
6873          "class": "p5",
6874          "module": "Shape",
6875          "submodule": "Curves",
6876          "overloads": [{
6877            "line": 13,
6878            "params": [{
6879              "name": "x1",
6880              "description": "<p>x-coordinate for the first anchor point</p>\n",
6881              "type": "Number"
6882            }, {
6883              "name": "y1",
6884              "description": "<p>y-coordinate for the first anchor point</p>\n",
6885              "type": "Number"
6886            }, {
6887              "name": "x2",
6888              "description": "<p>x-coordinate for the first control point</p>\n",
6889              "type": "Number"
6890            }, {
6891              "name": "y2",
6892              "description": "<p>y-coordinate for the first control point</p>\n",
6893              "type": "Number"
6894            }, {
6895              "name": "x3",
6896              "description": "<p>x-coordinate for the second control point</p>\n",
6897              "type": "Number"
6898            }, {
6899              "name": "y3",
6900              "description": "<p>y-coordinate for the second control point</p>\n",
6901              "type": "Number"
6902            }, {
6903              "name": "x4",
6904              "description": "<p>x-coordinate for the second anchor point</p>\n",
6905              "type": "Number"
6906            }, {
6907              "name": "y4",
6908              "description": "<p>y-coordinate for the second anchor point</p>\n",
6909              "type": "Number"
6910            }],
6911            "chainable": 1
6912          }, {
6913            "line": 66,
6914            "params": [{
6915              "name": "x1",
6916              "description": "",
6917              "type": "Number"
6918            }, {
6919              "name": "y1",
6920              "description": "",
6921              "type": "Number"
6922            }, {
6923              "name": "z1",
6924              "description": "<p>z-coordinate for the first anchor point</p>\n",
6925              "type": "Number"
6926            }, {
6927              "name": "x2",
6928              "description": "",
6929              "type": "Number"
6930            }, {
6931              "name": "y2",
6932              "description": "",
6933              "type": "Number"
6934            }, {
6935              "name": "z2",
6936              "description": "<p>z-coordinate for the first control point</p>\n",
6937              "type": "Number"
6938            }, {
6939              "name": "x3",
6940              "description": "",
6941              "type": "Number"
6942            }, {
6943              "name": "y3",
6944              "description": "",
6945              "type": "Number"
6946            }, {
6947              "name": "z3",
6948              "description": "<p>z-coordinate for the second control point</p>\n",
6949              "type": "Number"
6950            }, {
6951              "name": "x4",
6952              "description": "",
6953              "type": "Number"
6954            }, {
6955              "name": "y4",
6956              "description": "",
6957              "type": "Number"
6958            }, {
6959              "name": "z4",
6960              "description": "<p>z-coordinate for the second anchor point</p>\n",
6961              "type": "Number"
6962            }],
6963            "chainable": 1
6964          }]
6965        }, {
6966          "file": "src/core/shape/curves.js",
6967          "line": 96,
6968          "description": "<p>Sets the resolution at which Beziers display.</p>\n<p>The default value is 20.</p>\n<p>This function is only useful when using the WEBGL renderer\nas the default canvas renderer does not use this information.</p>\n",
6969          "itemtype": "method",
6970          "name": "bezierDetail",
6971          "params": [{
6972            "name": "detail",
6973            "description": "<p>resolution of the curves</p>\n",
6974            "type": "Number"
6975          }],
6976          "chainable": 1,
6977          "example": ["\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  noFill();\n\n  bezierDetail(5);\n}\n\nfunction draw() {\n  background(200);\n\n  // prettier-ignore\n  bezier(-40, -40, 0,\n          90, -40, 0,\n         -90,  40, 0,\n          40,  40, 0);\n}\n</code>\n</div>"],
6978          "alt": "stretched black s-shape with a low level of bezier detail",
6979          "class": "p5",
6980          "module": "Shape",
6981          "submodule": "Curves"
6982        }, {
6983          "file": "src/core/shape/curves.js",
6984          "line": 139,
6985          "description": "<p>Evaluates the Bezier at position t for points a, b, c, d.\nThe parameters a and d are the first and last points\non the curve, and b and c are the control points.\
6985nThe final parameter t varies between 0 and 1.\nThis can be done once with the x coordinates and a second time\nwith the y coordinates to get the location of a bezier curve at t.</p>\n",
6986          "itemtype": "method",
6987          "name": "bezierPoint",
6988          "params": [{
6989            "name": "a",
6990            "description": "<p>coordinate of first point on the curve</p>\n",
6991            "type": "Number"
6992          }, {
6993            "name": "b",
6994            "description": "<p>coordinate of first control point</p>\n",
6995            "type": "Number"
6996          }, {
6997            "name": "c",
6998            "description": "<p>coordinate of second control point</p>\n",
6999            "type": "Number"
7000          }, {
7001            "name": "d",
7002            "description": "<p>coordinate of second point on the curve</p>\n",
7003            "type": "Number"
7004          }, {
7005            "name": "t",
7006            "description": "<p>value between 0 and 1</p>\n",
7007            "type": "Number"
7008          }],
7009          "return": {
7010            "description": "the value of the Bezier at position t",
7011            "type": "Number"
7012          },
7013          "example": ["\n<div>\n<code>\nnoFill();\nlet x1 = 85,\n x2 = 10,\n x3 = 90,\n x4 = 15;\nlet y1 = 20,\n y2 = 10,\n y3 = 90,\n y4 = 80;\nbezier(x1, y1, x2, y2, x3, y3, x4, y4);\nfill(255);\nlet steps = 10;\nfor (let i = 0; i <= steps; i++) {\n  let t = i / steps;\n  let x = bezierPoint(x1, x2, x3, x4, t);\n  let y = bezierPoint(y1, y2, y3, y4, t);\n  ellipse(x, y, 5, 5);\n}\n</code>\n</div>"],
7014          "alt": "stretched black s-shape with 17 small orange lines extending from under shape.",
7015          "class": "p5",
7016          "module": "Shape",
7017          "submodule": "Curves"
7018        }, {
7019          "file": "src/core/shape/curves.js",
7020          "line": 194,
7021          "description": "<p>Evaluates the tangent to the Bezier at position t for points a, b, c, d.\nThe parameters a and d are the first and last points\non the curve, and b and c are the control points.\nThe final parameter t varies between 0 and 1.</p>\n",
7022          "itemtype": "method",
7023          "name": "bezierTangent",
7024          "params": [{
7025            "name": "a",
7026            "description": "<p>coordinate of first point on the curve</p>\n",
7027            "type": "Number"
7028          }, {
7029            "name": "b",
7030            "description": "<p>coordinate of first control point</p>\n",
7031            "type": "Number"
7032          }, {
7033            "name": "c",
7034            "description": "<p>coordinate of second control point</p>\n",
7035            "type": "Number"
7036          }, {
7037            "name": "d",
7038            "description": "<p>coordinate of second point on the curve</p>\n",
7039            "type": "Number"
7040          }, {
7041            "name": "t",
7042            "description": "<p>value between 0 and 1</p>\n",
7043            "type": "Number"
7044          }],
7045          "return": {
7046            "description": "the tangent at position t",
7047            "type": "Number"
7048          },
7049          "example": ["\n<div>\n<code>\nnoFill();\nbezier(85, 20, 10, 10, 90, 90, 15, 80);\nlet steps = 6;\nfill(255);\nfor (let i = 0; i <= steps; i++) {\n  let t = i / steps;\n  // Get the location of the point\n  let x = bezierPoint(85, 10, 90, 15, t);\n  let y = bezierPoint(20, 10, 90, 80, t);\n  // Get the tangent points\n  let tx = bezierTangent(85, 10, 90, 15, t);\n  let ty = bezierTangent(20, 10, 90, 80, t);\n  // Calculate an angle from the tangent points\n  let a = atan2(ty, tx);\n  a += PI;\n  stroke(255, 102, 0);\n  line(x, y, cos(a) * 30 + x, sin(a) * 30 + y);\n  // The following line of code makes a line\n  // inverse of the above line\n  //line(x, y, cos(a)*-30 + x, sin(a)*-30 + y);\n  stroke(0);\n  ellipse(x, y, 5, 5);\n}\n</code>\n</div>\n\n<div>\n<code>\nnoFill();\nbezier(85, 20, 10, 10, 90, 90, 15, 80);\nstroke(255, 102, 0);\nlet steps = 16;\nfor (let i = 0; i <= steps; i++) {\n  let t = i / steps;\n  let x = bezierPoint(85, 10, 90, 15, t);\n  let y = bezierPoint(20, 10, 90, 80, t);\n  let tx = bezierTangent(85, 10, 90, 15, t);\n  let ty = bezierTangent(20, 10, 90, 80, t);\n  let a = atan2(ty, tx);\n  a -= HALF_PI;\n  line(x, y, cos(a) * 8 + x, sin(a) * 8 + y);\n}\n</code>\n</div>"],
7050          "alt": "s-shaped line with 17 short orange lines extending from underside of shape",
7051          "class": "p5",
7052          "module": "Shape",
7053          "submodule": "Curves"
7054        }, {
7055          "file": "src/core/shape/curves.js",
7056          "line": 273,
7057          "description": "<p>Draws a curved line on the screen between two points, given as the\nmiddle four parameters. The first two parameters are a control point, as\nif the curve came from this point even though it&#39;
7057s not drawn. The last\ntwo parameters similarly describe the other control point. <br /><br />\nLonger curves can be created by putting a series of <a href=\"#/p5/curve\">curve()</a> functions\ntogether or using <a href=\"#/p5/curveVertex\">curveVertex()</a>. An additional function called\n<a href=\"#/p5/curveTightness\">curveTightness()</a> provides control for the visual quality of the curve.\nThe <a href=\"#/p5/curve\">curve()</a> function is an implementation of Catmull-Rom splines.</p>\n",
7058          "itemtype": "method",
7059          "name": "curve",
7060          "chainable": 1,
7061          "example": ["\n<div>\n<code>\nnoFill();\nstroke(255, 102, 0);\ncurve(5, 26, 5, 26, 73, 24, 73, 61);\nstroke(0);\ncurve(5, 26, 73, 24, 73, 61, 15, 65);\nstroke(255, 102, 0);\ncurve(73, 24, 73, 61, 15, 65, 15, 65);\n</code>\n</div>\n<div>\n<code>\n// Define the curve points as JavaScript objects\nlet p1 = { x: 5, y: 26 },\n p2 = { x: 73, y: 24 };\nlet p3 = { x: 73, y: 61 },\n p4 = { x: 15, y: 65 };\nnoFill();\nstroke(255, 102, 0);\ncurve(p1.x, p1.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);\nstroke(0);\ncurve(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);\nstroke(255, 102, 0);\ncurve(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, p4.x, p4.y);\n</code>\n</div>\n<div>\n<code>\nnoFill();\nstroke(255, 102, 0);\ncurve(5, 26, 0, 5, 26, 0, 73, 24, 0, 73, 61, 0);\nstroke(0);\ncurve(5, 26, 0, 73, 24, 0, 73, 61, 0, 15, 65, 0);\nstroke(255, 102, 0);\ncurve(73, 24, 0, 73, 61, 0, 15, 65, 0, 15, 65, 0);\n</code>\n</div>"],
7062          "alt": "horseshoe shape with orange ends facing left and black curved center.\nhorseshoe shape with orange ends facing left and black curved center.\ncurving black and orange lines.",
7063          "class": "p5",
7064          "module": "Shape",
7065          "submodule": "Curves",
7066          "overloads": [{
7067            "line": 273,
7068            "params": [{
7069              "name": "x1",
7070              "description": "<p>x-coordinate for the beginning control point</p>\n",
7071              "type": "Number"
7072            }, {
7073              "name": "y1",
7074              "description": "<p>y-coordinate for the beginning control point</p>\n",
7075              "type": "Number"
7076            }, {
7077              "name": "x2",
7078              "description": "<p>x-coordinate for the first point</p>\n",
7079              "type": "Number"
7080            }, {
7081              "name": "y2",
7082              "description": "<p>y-coordinate for the first point</p>\n",
7083              "type": "Number"
7084            }, {
7085              "name": "x3",
7086              "description": "<p>x-coordinate for the second point</p>\n",
7087              "type": "Number"
7088            }, {
7089              "name": "y3",
7090              "description": "<p>y-coordinate for the second point</p>\n",
7091              "type": "Number"
7092            }, {
7093              "name": "x4",
7094              "description": "<p>x-coordinate for the ending control point</p>\n",
7095              "type": "Number"
7096            }, {
7097              "name": "y4",
7098              "description": "<p>y-coordinate for the ending control point</p>\n",
7099              "type": "Number"
7100            }],
7101            "chainable": 1
7102          }, {
7103            "line": 338,
7104            "params": [{
7105              "name": "x1",
7106              "description": "",
7107              "type": "Number"
7108            }, {
7109              "name": "y1",
7110              "description": "",
7111              "type": "Number"
7112            }, {
7113              "name": "z1",
7114              "description": "<p>z-coordinate for the beginning control point</p>\n",
7115              "type": "Number"
7116            }, {
7117              "name": "x2",
7118              "description": "",
7119              "type": "Number"
7120            }, {
7121              "name": "y2",
7122              "description": "",
7123              "type": "Number"
7124            }, {
7125              "name": "z2",
7126              "description": "<p>z-coordinate for the first point</p>\n",
7127              "type": "Number"
7128            }, {
7129              "name": "x3",
7130              "description": "",
7131              "type": "Number"
7132            }, {
7133              "name": "y3",
7134              "description": "",
7135              "type": "Number"
7136            }, {
7137              "name": "z3",
7138              "description": "<p>z-coordinate for the second point</p>\n",
7139              "type": "Number"
7140            }, {
7141              "name": "x4",
7142              "description": "",
7143              "type": "Number"
7144            }, {
7145              "name": "y4",
7146              "description": "",
7147              "type": "Number"
7148            }, {
7149              "name": "z4",
7150              "description": "<p>z-coordinate for the ending control point</p>\n",
7151              "type": "Number"
7152            }],
7153            "chainable": 1
7154          }]
7155        }, {
7156          "file": "src/core/shape/curves.js",
7157          "line": 364,
7158          "description": "<p>Sets the resolution at which curves display.</p>\n<p>The default value is 20 while the minimum value is 3.</p>\n<p>This function is only useful when using the WEBGL renderer\nas the default canvas renderer does not use this\ninformation.</p>\n",
7159          "itemtype": "method",
7160          "name": "curveDetail",
7161          "params": [{
7162            "name": "resolution",
7163            "description": "<p>resolution of the curves</p>\n",
7164            "type": "Number"
7165          }],
7166          "chainable": 1,
7167          "example": ["\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n\n  curveDetail(5);\n}\nfunction draw() {\n  background(200);\n\n  curve(250, 600, 0, -30, 40, 0, 30, 30, 0, -250, 600, 0);\n}\n</code>\n</div>"],
7168          "alt": "white arch shape with a low level of curve detail.",
7169          "class": "p5",
7170          "module": "Shape",
7171          "submodule": "Curves"
7172        }, {
7173          "file": "src/core/shape/curves.js",
7174          "line": 406,
7175          "description": "<p>Modifies the quality of forms created with <a href=\"#/p5/curve\">curve()</a> and <a href=\"#/p5/curveVertex\">curveVertex()</a>.\nThe parameter tightness determines how the curve fits to the vertex\npoints. The value 0.0 is the default value for tightness (this value\
7175ndefines the curves to be Catmull-Rom splines) and the value 1.0 connects\nall the points with straight lines. Values within the range -5.0 and 5.0\nwill deform the curves but will leave them recognizable and as values\nincrease in magnitude, they will continue to deform.</p>\n",
7176          "itemtype": "method",
7177          "name": "curveTightness",
7178          "params": [{
7179            "name": "amount",
7180            "description": "<p>amount of deformation from the original vertices</p>\n",
7181            "type": "Number"
7182          }],
7183          "chainable": 1,
7184          "example": ["\n<div>\n<code>\n// Move the mouse left and right to see the curve change\n\nfunction setup() {\n  createCanvas(100, 100);\n  noFill();\n}\n\nfunction draw() {\n  background(204);\n  let t = map(mouseX, 0, width, -5, 5);\n  curveTightness(t);\n  beginShape();\n  curveVertex(10, 26);\n  curveVertex(10, 26);\n  curveVertex(83, 24);\n  curveVertex(83, 61);\n  curveVertex(25, 65);\n  curveVertex(25, 65);\n  endShape();\n}\n</code>\n</div>"],
7185          "alt": "Line shaped like right-facing arrow,points move with mouse-x and warp shape.",
7186          "class": "p5",
7187          "module": "Shape",
7188          "submodule": "Curves"
7189        }, {
7190          "file": "src/core/shape/curves.js",
7191          "line": 453,
7192          "description": "<p>Evaluates the curve at position t for points a, b, c, d.\nThe parameter t varies between 0 and 1, a and d are control points\nof the curve, and b and c are the start and end points of the curve.\nThis can be done once with the x coordinates and a second time\nwith the y coordinates to get the location of a curve at t.</p>\n",
7193          "itemtype": "method",
7194          "name": "curvePoint",
7195          "params": [{
7196            "name": "a",
7197            "description": "<p>coordinate of first control point of the curve</p>\n",
7198            "type": "Number"
7199          }, {
7200            "name": "b",
7201            "description": "<p>coordinate of first point</p>\n",
7202            "type": "Number"
7203          }, {
7204            "name": "c",
7205            "description": "<p>coordinate of second point</p>\n",
7206            "type": "Number"
7207          }, {
7208            "name": "d",
7209            "description": "<p>coordinate of second control point</p>\n",
7210            "type": "Number"
7211          }, {
7212            "name": "t",
7213            "description": "<p>value between 0 and 1</p>\n",
7214            "type": "Number"
7215          }],
7216          "return": {
7217            "description": "bezier value at position t",
7218            "type": "Number"
7219          },
7220          "example": ["\n<div>\n<code>\nnoFill();\ncurve(5, 26, 5, 26, 73, 24, 73, 61);\ncurve(5, 26, 73, 24, 73, 61, 15, 65);\nfill(255);\nellipseMode(CENTER);\nlet steps = 6;\nfor (let i = 0; i <= steps; i++) {\n  let t = i / steps;\n  let x = curvePoint(5, 5, 73, 73, t);\n  let y = curvePoint(26, 26, 24, 61, t);\n  ellipse(x, y, 5, 5);\n  x = curvePoint(5, 73, 73, 15, t);\n  y = curvePoint(26, 24, 61, 65, t);\n  ellipse(x, y, 5, 5);\n}\n</code>\n</div>\n\nline hooking down to right-bottom with 13 5x5 white ellipse points"],
7221          "class": "p5",
7222          "module": "Shape",
7223          "submodule": "Curves"
7224        }, {
7225          "file": "src/core/shape/curves.js",
7226          "line": 502,
7227          "description": "<p>Evaluates the tangent to the curve at position t for points a, b, c, d.\nThe parameter t varies between 0 and 1, a and d are points on the curve,\nand b and c are the control points.</p>\n",
7228          "itemtype": "method",
7229          "name": "curveTangent",
7230          "params": [{
7231            "name": "a",
7232            "description": "<p>coordinate of first point on the curve</p>\n",
7233            "type": "Number"
7234          }, {
7235            "name": "b",
7236            "description": "<p>coordinate of first control point</p>\n",
7237            "type": "Number"
7238          }, {
7239            "name": "c",
7240            "description": "<p>coordinate of second control point</p>\n",
7241            "type": "Number"
7242          }, {
7243            "name": "d",
7244            "description": "<p>coordinate of second point on the curve</p>\n",
7245            "type": "Number"
7246          }, {
7247            "name": "t",
7248            "description": "<p>value between 0 and 1</p>\n",
7249            "type": "Number"
7250          }],
7251          "return": {
7252            "description": "the tangent at position t",
7253            "type": "Number"
7254          },
7255          "example": ["\n<div>\n<code>\nnoFill();\ncurve(5, 26, 73, 24, 73, 61, 15, 65);\nlet steps = 6;\nfor (let i = 0; i <= steps;
7255 i++) {\n  let t = i / steps;\n  let x = curvePoint(5, 73, 73, 15, t);\n  let y = curvePoint(26, 24, 61, 65, t);\n  //ellipse(x, y, 5, 5);\n  let tx = curveTangent(5, 73, 73, 15, t);\n  let ty = curveTangent(26, 24, 61, 65, t);\n  let a = atan2(ty, tx);\n  a -= PI / 2.0;\n  line(x, y, cos(a) * 8 + x, sin(a) * 8 + y);\n}\n</code>\n</div>"],
7256          "alt": "right curving line mid-right of canvas with 7 short lines radiating from it.",
7257          "class": "p5",
7258          "module": "Shape",
7259          "submodule": "Curves"
7260        }, {
7261          "file": "src/core/shape/vertex.js",
7262          "line": 22,
7263          "description": "<p>Use the <a href=\"#/p5/beginContour\">beginContour()</a> and <a href=\"#/p5/endContour\">endContour()</a> functions to create negative\nshapes within shapes such as the center of the letter &#39;O&#39;. <a href=\"#/p5/beginContour\">beginContour()</a>\nbegins recording vertices for the shape and <a href=\"#/p5/endContour\">endContour()</a> stops recording.\nThe vertices that define a negative shape must &quot;wind&quot; in the opposite\ndirection from the exterior shape. First draw vertices for the exterior\nclockwise order, then for internal shapes, draw vertices\nshape in counter-clockwise.\n<br><br>\nThese functions can only be used within a <a href=\"#/p5/beginShape\">beginShape()</a>/<a href=\"#/p5/endShape\">endShape()</a> pair and\ntransformations such as <a href=\"#/p5/translate\">translate()</a>, <a href=\"#/p5/rotate\">rotate()</a>, and <a href=\"#/p5/scale\">scale()</a> do not work\nwithin a <a href=\"#/p5/beginContour\">beginContour()</a>/<a href=\"#/p5/endContour\">endContour()</a> pair. It is also not possible to use\nother shapes, such as <a href=\"#/p5/ellipse\">ellipse()</a> or <a href=\"#/p5/rect\">rect()</a> within.</p>\n",
7264          "itemtype": "method",
7265          "name": "beginContour",
7266          "chainable": 1,
7267          "example": ["\n<div>\n<code>\ntranslate(50, 50);\nstroke(255, 0, 0);\nbeginShape();\n// Exterior part of shape, clockwise winding\nvertex(-40, -40);\nvertex(40, -40);\nvertex(40, 40);\nvertex(-40, 40);\n// Interior part of shape, counter-clockwise winding\nbeginContour();\nvertex(-20, -20);\nvertex(-20, 20);\nvertex(20, 20);\nvertex(20, -20);\nendContour();\nendShape(CLOSE);\n</code>\n</div>"],
7268          "alt": "white rect and smaller grey rect with red outlines in center of canvas.",
7269          "class": "p5",
7270          "module": "Shape",
7271          "submodule": "Vertex"
7272        }, {
7273          "file": "src/core/shape/vertex.js",
7274          "line": 70,
7275          "description": "<p>Using the <a href=\"#/p5/beginShape\">beginShape()</a> and <a href=\"#/p5/endShape\">endShape()</a> functions allow creating more\ncomplex forms. <a href=\"#/p5/beginShape\">beginShape()</a> begins recording vertices for a shape and\n<a href=\"#/p5/endShape\">endShape()</a> stops recording. The value of the kind parameter tells it which\ntypes of shapes to create from the provided vertices. With no mode\nspecified, the shape can be any irregular polygon.\n<br><br>\nThe parameters available for <a href=\"#/p5/beginShape\">beginShape()</a> are POINTS, LINES, TRIANGLES,\nTRIANGLE_FAN, TRIANGLE_STRIP, QUADS, and QUAD_STRIP. After calling the\n<a href=\"#/p5/beginShape\">beginShape()</a> function, a series of <a href=\"#/p5/vertex\">vertex()</a> commands must follow. To stop\ndrawing the shape, call <a href=\"#/p5/endShape\">endShape()</a>. Each shape will be outlined with the\ncurrent stroke color and filled with the fill color.\n<br><br>\nTransformations such as <a href=\"#/p5/translate\">translate()</a>, <a href=\"#/p5/rotate\">rotate()</a>, and <a href=\"#/p5/scale\">scale()</a> do not work\nwithin <a href=\"#/p5/beginShape\">beginShape()</a>. It is also not possible to use other shapes, such as\n<a href=\"#/p5/ellipse\">ellipse()</a> or <a href=\"#/p5/rect\">rect()</a> within <a href=\"#/p5/beginShape\">beginShape()</a>.</p>\n",
7276          "itemtype": "method",
7277          "name": "beginShape",
7278          "params": [{
7279            "name": "kind",
7280            "description": "<p>either POINTS, LINES, TRIANGLES, TRIANGLE_FAN\n                               TRIANGLE_STRIP, QUADS, or QUAD_STRIP</p>\n",
7281            "type": "Constant",
7282            "optional": true
7283          }],
7284          "chainable": 1,
7285          "example": ["\n<div>\n<code>\nbeginShape();\nvertex(30, 20);\nvertex(85, 20);
7285\nvertex(85, 75);\nvertex(30, 75);\nendShape(CLOSE);\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(POINTS);\nvertex(30, 20);\nvertex(85, 20);\nvertex(85, 75);\nvertex(30, 75);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(LINES);\nvertex(30, 20);\nvertex(85, 20);\nvertex(85, 75);\nvertex(30, 75);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nnoFill();\nbeginShape();\nvertex(30, 20);\nvertex(85, 20);\nvertex(85, 75);\nvertex(30, 75);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nnoFill();\nbeginShape();\nvertex(30, 20);\nvertex(85, 20);\nvertex(85, 75);\nvertex(30, 75);\nendShape(CLOSE);\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(TRIANGLES);\nvertex(30, 75);\nvertex(40, 20);\nvertex(50, 75);\nvertex(60, 20);\nvertex(70, 75);\nvertex(80, 20);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(TRIANGLE_STRIP);\nvertex(30, 75);\nvertex(40, 20);\nvertex(50, 75);\nvertex(60, 20);\nvertex(70, 75);\nvertex(80, 20);\nvertex(90, 75);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(TRIANGLE_FAN);\nvertex(57.5, 50);\nvertex(57.5, 15);\nvertex(92, 50);\nvertex(57.5, 85);\nvertex(22, 50);\nvertex(57.5, 15);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(QUADS);\nvertex(30, 20);\nvertex(30, 75);\nvertex(50, 75);\nvertex(50, 20);\nvertex(65, 20);\nvertex(65, 75);\nvertex(85, 75);\nvertex(85, 20);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nbeginShape(QUAD_STRIP);\nvertex(30, 20);\nvertex(30, 75);\nvertex(50, 20);\nvertex(50, 75);\nvertex(65, 20);\nvertex(65, 75);\nvertex(85, 20);\nvertex(85, 75);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nbeginShape();\nvertex(20, 20);\nvertex(40, 20);\nvertex(40, 40);\nvertex(60, 40);\nvertex(60, 60);\nvertex(20, 60);\nendShape(CLOSE);\n</code>\n</div>"],
7286          "alt": "white square-shape with black outline in middle-right of canvas.\n4 black points in a square shape in middle-right of canvas.\n2 horizontal black lines. In the top-right and bottom-right of canvas.\n3 line shape with horizontal on top, vertical in middle and horizontal bottom.\nsquare line shape in middle-right of canvas.\n2 white triangle shapes mid-right canvas. left one pointing up and right down.\n5 horizontal interlocking and alternating white triangles in mid-right canvas.\n4 interlocking white triangles in 45 degree rotated square-shape.\n2 white rectangle shapes in mid-right canvas. Both 20x55.\n3 side-by-side white rectangles center rect is smaller in mid-right canvas.\nThick white l-shape with black outline mid-top-left of canvas.",
7287          "class": "p5",
7288          "module": "Shape",
7289          "submodule": "Vertex"
7290        }, {
7291          "file": "src/core/shape/vertex.js",
7292          "line": 270,
7293          "description": "<p>Specifies vertex coordinates for Bezier curves. Each call to\nbezierVertex() defines the position of two control points and\none anchor point of a Bezier curve, adding a new segment to a\nline or shape. For WebGL mode bezierVertex() can be used in 2D\nas well as 3D mode. 2D mode expects 6 parameters, while 3D mode\nexpects 9 parameters (including z coordinates).\n<br><br>\nThe first time bezierVertex() is used within a <a href=\"#/p5/beginShape\">beginShape()</a>\ncall, it must be prefaced with a call to <a href=\"#/p5/vertex\">vertex()</a> to set the first anchor\npoint. This function must be used between <a href=\"#/p5/beginShape\">beginShape()</a> and <a href=\"#/p5/endShape\">endShape()</a>\nand only when there is no MODE or POINTS parameter specified to\n<a href=\"#/p5/beginShape\">beginShape()</a>.</p>\n",
7294          "itemtype": "method",
7295          "name": "bezierVertex",
7296          "chainable": 1,
7297          "example": ["\n<div>\n<code>\nnoFill();\nbeginShape();\nvertex(30, 20);\nbezierVertex(80, 0, 80, 75, 30, 75);\nendShape();\n</code>\n</div>", "\n<div>\n<code>\nbeginShape();\nvertex(30, 20);\nbezierVertex(80, 0, 80, 75, 30, 75);\nbezierVertex(50, 80, 60, 25, 30, 20);\nendShape();\n</code>\n</div>", "\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  setAttributes('antialias', true);\n}\nfunction draw() {\n  orbitControl();\n  background(50);\n  strokeWeight(4);
7297\n  stroke(255);\n  point(-25, 30);\n  point(25, 30);\n  point(25, -30);\n  point(-25, -30);\n\n  strokeWeight(1);\n  noFill();\n\n  beginShape();\n  vertex(-25, 30);\n  bezierVertex(25, 30, 25, -30, -25, -30);\n  endShape();\n\n  beginShape();\n  vertex(-25, 30, 20);\n  bezierVertex(25, 30, 20, 25, -30, 20, -25, -30, 20);\n  endShape();\n}\n</code>\n</div>"],
7298          "alt": "crescent shape in middle of canvas with another crescent shape on positive z-axis.",
7299          "class": "p5",
7300          "module": "Shape",
7301          "submodule": "Vertex",
7302          "overloads": [{
7303            "line": 270,
7304            "params": [{
7305              "name": "x2",
7306              "description": "<p>x-coordinate for the first control point</p>\n",
7307              "type": "Number"
7308            }, {
7309              "name": "y2",
7310              "description": "<p>y-coordinate for the first control point</p>\n",
7311              "type": "Number"
7312            }, {
7313              "name": "x3",
7314              "description": "<p>x-coordinate for the second control point</p>\n",
7315              "type": "Number"
7316            }, {
7317              "name": "y3",
7318              "description": "<p>y-coordinate for the second control point</p>\n",
7319              "type": "Number"
7320            }, {
7321              "name": "x4",
7322              "description": "<p>x-coordinate for the anchor point</p>\n",
7323              "type": "Number"
7324            }, {
7325              "name": "y4",
7326              "description": "<p>y-coordinate for the anchor point</p>\n",
7327              "type": "Number"
7328            }],
7329            "chainable": 1
7330          }, {
7331            "line": 358,
7332            "params": [{
7333              "name": "x2",
7334              "description": "",
7335              "type": "Number"
7336            }, {
7337              "name": "y2",
7338              "description": "",
7339              "type": "Number"
7340            }, {
7341              "name": "z2",
7342              "description": "<p>z-coordinate for the first control point (for WebGL mode)</p>\n",
7343              "type": "Number"
7344            }, {
7345              "name": "x3",
7346              "description": "",
7347              "type": "Number"
7348            }, {
7349              "name": "y3",
7350              "description": "",
7351              "type": "Number"
7352            }, {
7353              "name": "z3",
7354              "description": "<p>z-coordinate for the second control point (for WebGL mode)</p>\n",
7355              "type": "Number"
7356            }, {
7357              "name": "x4",
7358              "description": "",
7359              "type": "Number"
7360            }, {
7361              "name": "y4",
7362              "description": "",
7363              "type": "Number"
7364            }, {
7365              "name": "z4",
7366              "description": "<p>z-coordinate for the anchor point (for WebGL mode)</p>\n",
7367              "type": "Number"
7368            }],
7369            "chainable": 1
7370          }]
7371        }, {
7372          "file": "src/core/shape/vertex.js",
7373          "line": 398,
7374          "description": "<p>Specifies vertex coordinates for curves. This function may only\nbe used between <a href=\"#/p5/beginShape\">beginShape()</a> and <a href=\"#/p5/endShape\">endShape()</a> and only when there\nis no MODE parameter specified to <a href=\"#/p5/beginShape\">beginShape()</a>.\nFor WebGL mode curveVertex() can be used in 2D as well as 3D mode.\n2D mode expects 2 parameters, while 3D mode expects 3 parameters.\n<br><br>\nThe first and last points in a series of curveVertex() lines will be used to\nguide the beginning and end of a the curve. A minimum of four\npoints is required to draw a tiny curve between the second and\nthird points. Adding a fifth point with curveVertex() will draw\nthe curve between the second, third, and fourth points. The\ncurveVertex() function is an implementation of Catmull-Rom\nsplines.</p>\n",
7375          "itemtype": "method",
7376          "name": "curveVertex",
7377          "chainable": 1,
7378          "example": ["\n<div>\n<code>\nstrokeWeight(5);\npoint(84, 91);\npoint(68, 19);\npoint(21, 17);\npoint(32, 91);\nstrokeWeight(1);\n\nnoFill();\nbeginShape();\ncurveVertex(84, 91);\ncurveVertex(84, 91);
7378\ncurveVertex(68, 19);\ncurveVertex(21, 17);\ncurveVertex(32, 91);\ncurveVertex(32, 91);\nendShape();\n</code>\n</div>"],
7379          "alt": "Upside-down u-shape line, mid canvas. left point extends beyond canvas view.",
7380          "class": "p5",
7381          "module": "Shape",
7382          "submodule": "Vertex",
7383          "overloads": [{
7384            "line": 398,
7385            "params": [{
7386              "name": "x",
7387              "description": "<p>x-coordinate of the vertex</p>\n",
7388              "type": "Number"
7389            }, {
7390              "name": "y",
7391              "description": "<p>y-coordinate of the vertex</p>\n",
7392              "type": "Number"
7393            }],
7394            "chainable": 1
7395          }, {
7396            "line": 443,
7397            "params": [{
7398              "name": "x",
7399              "description": "",
7400              "type": "Number"
7401            }, {
7402              "name": "y",
7403              "description": "",
7404              "type": "Number"
7405            }, {
7406              "name": "z",
7407              "description": "<p>z-coordinate of the vertex (for WebGL mode)</p>\n",
7408              "type": "Number",
7409              "optional": true
7410            }],
7411            "chainable": 1
7412          }]
7413        }, {
7414          "file": "src/core/shape/vertex.js",
7415          "line": 508,
7416          "description": "<p>Use the <a href=\"#/p5/beginContour\">beginContour()</a> and <a href=\"#/p5/endContour\">endContour()</a> functions to create negative\nshapes within shapes such as the center of the letter &#39;O&#39;. <a href=\"#/p5/beginContour\">beginContour()</a>\nbegins recording vertices for the shape and <a href=\"#/p5/endContour\">endContour()</a> stops recording.\nThe vertices that define a negative shape must &quot;wind&quot; in the opposite\ndirection from the exterior shape. First draw vertices for the exterior\nclockwise order, then for internal shapes, draw vertices\nshape in counter-clockwise.\n<br><br>\nThese functions can only be used within a <a href=\"#/p5/beginShape\">beginShape()</a>/<a href=\"#/p5/endShape\">endShape()</a> pair and\ntransformations such as <a href=\"#/p5/translate\">translate()</a>, <a href=\"#/p5/rotate\">rotate()</a>, and <a href=\"#/p5/scale\">scale()</a> do not work\nwithin a <a href=\"#/p5/beginContour\">beginContour()</a>/<a href=\"#/p5/endContour\">endContour()</a> pair. It is also not possible to use\nother shapes, such as <a href=\"#/p5/ellipse\">ellipse()</a> or <a href=\"#/p5/rect\">rect()</a> within.</p>\n",
7417          "itemtype": "method",
7418          "name": "endContour",
7419          "chainable": 1,
7420          "example": ["\n<div>\n<code>\ntranslate(50, 50);\nstroke(255, 0, 0);\nbeginShape();\n// Exterior part of shape, clockwise winding\nvertex(-40, -40);\nvertex(40, -40);\nvertex(40, 40);\nvertex(-40, 40);\n// Interior part of shape, counter-clockwise winding\nbeginContour();\nvertex(-20, -20);\nvertex(-20, 20);\nvertex(20, 20);\nvertex(20, -20);\nendContour();\nendShape(CLOSE);\n</code>\n</div>"],
7421          "alt": "white rect and smaller grey rect with red outlines in center of canvas.",
7422          "class": "p5",
7423          "module": "Shape",
7424          "submodule": "Vertex"
7425        }, {
7426          "file": "src/core/shape/vertex.js",
7427          "line": 568,
7428          "description": "<p>The <a href=\"#/p5/endShape\">endShape()</a> function is the companion to <a href=\"#/p5/beginShape\">beginShape()</a> and may only be\ncalled after <a href=\"#/p5/beginShape\">beginShape()</a>. When <a href=\"#/p5/endshape\">endshape()</a> is called, all of image data\ndefined since the previous call to <a href=\"#/p5/beginShape\">beginShape()</a> is written into the image\nbuffer. The constant CLOSE as the value for the MODE parameter to close\nthe shape (to connect the beginning and the end).</p>\n",
7429          "itemtype": "method",
7430          "name": "endShape",
7431          "params": [{
7432            "name": "mode",
7433            "description": "<p>use CLOSE to close the shape</p>\n",
7434            "type": "Constant",
7435            "optional": true
7436          }],
7437          "chainable": 1,
7438          "example": ["\n<div>\n<code>\nnoFill();\n\nbeginShape();\nvertex(20, 20);\nvertex(45, 20);\nvertex(45, 80);\nendShape(CLOSE);\n\nbeginShape();\nvertex(50, 20);\nvertex(75, 20);\nvertex(75, 80);\nendShape();\n</code>\n</div>"],
7439          "alt": "Triangle line shape with smallest interior angle on bottom and upside-
7439down L.",
7440          "class": "p5",
7441          "module": "Shape",
7442          "submodule": "Vertex"
7443        }, {
7444          "file": "src/core/shape/vertex.js",
7445          "line": 654,
7446          "description": "<p>Specifies vertex coordinates for quadratic Bezier curves. Each call to\nquadraticVertex() defines the position of one control points and one\nanchor point of a Bezier curve, adding a new segment to a line or shape.\nThe first time quadraticVertex() is used within a <a href=\"#/p5/beginShape\">beginShape()</a> call, it\nmust be prefaced with a call to <a href=\"#/p5/vertex\">vertex()</a> to set the first anchor point.\nFor WebGL mode quadraticVertex() can be used in 2D as well as 3D mode.\n2D mode expects 4 parameters, while 3D mode expects 6 parameters\n(including z coordinates).\n<br><br>\nThis function must be used between <a href=\"#/p5/beginShape\">beginShape()</a> and <a href=\"#/p5/endShape\">endShape()</a>\nand only when there is no MODE or POINTS parameter specified to\n<a href=\"#/p5/beginShape\">beginShape()</a>.</p>\n",
7447          "itemtype": "method",
7448          "name": "quadraticVertex",
7449          "chainable": 1,
7450          "example": ["\n<div>\n<code>\nstrokeWeight(5);\npoint(20, 20);\npoint(80, 20);\npoint(50, 50);\n\nnoFill();\nstrokeWeight(1);\nbeginShape();\nvertex(20, 20);\nquadraticVertex(80, 20, 50, 50);\nendShape();\n</code>\n</div>\n\n<div>\n<code>\nstrokeWeight(5);\npoint(20, 20);\npoint(80, 20);\npoint(50, 50);\n\npoint(20, 80);\npoint(80, 80);\npoint(80, 60);\n\nnoFill();\nstrokeWeight(1);\nbeginShape();\nvertex(20, 20);\nquadraticVertex(80, 20, 50, 50);\nquadraticVertex(20, 80, 80, 80);\nvertex(80, 60);\nendShape();\n</code>\n</div>"],
7451          "alt": "arched-shaped black line with 4 pixel thick stroke weight.\nbackwards s-shaped black line with 4 pixel thick stroke weight.",
7452          "class": "p5",
7453          "module": "Shape",
7454          "submodule": "Vertex",
7455          "overloads": [{
7456            "line": 654,
7457            "params": [{
7458              "name": "cx",
7459              "description": "<p>x-coordinate for the control point</p>\n",
7460              "type": "Number"
7461            }, {
7462              "name": "cy",
7463              "description": "<p>y-coordinate for the control point</p>\n",
7464              "type": "Number"
7465            }, {
7466              "name": "x3",
7467              "description": "<p>x-coordinate for the anchor point</p>\n",
7468              "type": "Number"
7469            }, {
7470              "name": "y3",
7471              "description": "<p>y-coordinate for the anchor point</p>\n",
7472              "type": "Number"
7473            }],
7474            "chainable": 1
7475          }, {
7476            "line": 720,
7477            "params": [{
7478              "name": "cx",
7479              "description": "",
7480              "type": "Number"
7481            }, {
7482              "name": "cy",
7483              "description": "",
7484              "type": "Number"
7485            }, {
7486              "name": "cz",
7487              "description": "<p>z-coordinate for the control point (for WebGL mode)</p>\n",
7488              "type": "Number"
7489            }, {
7490              "name": "x3",
7491              "description": "",
7492              "type": "Number"
7493            }, {
7494              "name": "y3",
7495              "description": "",
7496              "type": "Number"
7497            }, {
7498              "name": "z3",
7499              "description": "<p>z-coordinate for the anchor point (for WebGL mode)</p>\n",
7500              "type": "Number"
7501            }],
7502            "chainable": 1
7503          }]
7504        }, {
7505          "file": "src/core/shape/vertex.js",
7506          "line": 813,
7507          "description": "<p>All shapes are constructed by connecting a series of vertices. <a href=\"#/p5/vertex\">vertex()</a>\nis used to specify the vertex coordinates for points, lines, triangles,\nquads, and polygons. It is used exclusively within the <a href=\"#/p5/beginShape\">beginShape()</a> and\n<a href=\"#/p5/endShape\">endShape()</a> functions.</p>\n",
7508          "itemtype": "method",
7509          "name": "vertex",
7510          "chainable": 1,
7511          "example": ["\n<div>\n<code>\nstrokeWeight(3);\nbeginShape(POINTS);\nvertex(30, 20);\nvertex(85, 20);
7511\nvertex(85, 75);\nvertex(30, 75);\nendShape();\n</code>\n</div>"],
7512          "alt": "8 points making 4 lines",
7513          "class": "p5",
7514          "module": "Shape",
7515          "submodule": "Vertex",
7516          "overloads": [{
7517            "line": 813,
7518            "params": [{
7519              "name": "x",
7520              "description": "<p>x-coordinate of the vertex</p>\n",
7521              "type": "Number"
7522            }, {
7523              "name": "y",
7524              "description": "<p>y-coordinate of the vertex</p>\n",
7525              "type": "Number"
7526            }],
7527            "chainable": 1
7528          }, {
7529            "line": 900,
7530            "params": [{
7531              "name": "x",
7532              "description": "",
7533              "type": "Number"
7534            }, {
7535              "name": "y",
7536              "description": "",
7537              "type": "Number"
7538            }, {
7539              "name": "z",
7540              "description": "<p>z-coordinate of the vertex</p>\n",
7541              "type": "Number"
7542            }, {
7543              "name": "u",
7544              "description": "<p>the vertex&#39;s texture u-coordinate</p>\n",
7545              "type": "Number",
7546              "optional": true
7547            }, {
7548              "name": "v",
7549              "description": "<p>the vertex&#39;s texture v-coordinate</p>\n",
7550              "type": "Number",
7551              "optional": true
7552            }],
7553            "chainable": 1
7554          }]
7555        }, {
7556          "file": "src/core/constants.js",
7557          "line": 13,
7558          "itemtype": "property",
7559          "name": "P2D",
7560          "type": "String",
7561          "final": 1,
7562          "class": "p5",
7563          "module": "Constants",
7564          "submodule": "Constants"
7565        }, {
7566          "file": "src/core/constants.js",
7567          "line": 18,
7568          "itemtype": "property",
7569          "name": "WEBGL",
7570          "type": "String",
7571          "final": 1,
7572          "class": "p5",
7573          "module": "Constants",
7574          "submodule": "Constants"
7575        }, {
7576          "file": "src/core/constants.js",
7577          "line": 25,
7578          "itemtype": "property",
7579          "name": "ARROW",
7580          "type": "String",
7581          "final": 1,
7582          "class": "p5",
7583          "module": "Constants",
7584          "submodule": "Constants"
7585        }, {
7586          "file": "src/core/constants.js",
7587          "line": 30,
7588          "itemtype": "property",
7589          "name": "CROSS",
7590          "type": "String",
7591          "final": 1,
7592          "class": "p5",
7593          "module": "Constants",
7594          "submodule": "Constants"
7595        }, {
7596          "file": "src/core/constants.js",
7597          "line": 35,
7598          "itemtype": "property",
7599          "name": "HAND",
7600          "type": "String",
7601          "final": 1,
7602          "class": "p5",
7603          "module": "Constants",
7604          "submodule": "Constants"
7605        }, {
7606          "file": "src/core/constants.js",
7607          "line": 40,
7608          "itemtype": "property",
7609          "name": "MOVE",
7610          "type": "String",
7611          "final": 1,
7612          "class": "p5",
7613          "module": "Constants",
7614          "submodule": "Constants"
7615        }, {
7616          "file": "src/core/constants.js",
7617          "line": 45,
7618          "itemtype": "property",
7619          "name": "TEXT",
7620          "type": "String",
7621          "final": 1,
7622          "class": "p5",
7623          "module": "Constants",
7624          "submodule": "Constants"
7625        }, {
7626          "file": "src/core/constants.js",
7627          "line": 50,
7628          "itemtype": "property",
7629          "name": "WAIT",
7630          "type": "String",
7631          "final": 1,
7632          "class": "p5",
7633          "module": "Constants",
7634          "submodule": "Constants"
7635        }, {
7636          "file": "src/core/constants.js",
7637          "line": 58,
7638          "description": "<p>HALF_PI is a mathematical constant with the value\n1.57079632679489661923. It is half the ratio of the\ncircumference of a circle to its diameter. It is useful in\ncombination with the trigonometric functions <a href=\"#/p5/sin\">sin()</a> and <a href=\"#/p5/cos\">cos()</a>.</p>\n",
7639          "itemtype": "property",
7640          "name": "HALF_PI",
7641          "type": "Number",
7642          "final": 1,
7643          "example": ["\n<div><code>\narc(50, 50, 80, 80, 0, HALF_PI);\n</code></div>"],
7644          "alt": "80x80 white quarter-circle with curve toward bottom right of canvas.",
7645          "class": "p5",
7646          "module": "Constants",
7647          "submodule": "Constants"
7648        }, {
7649          "file": "src/core/constants.js",
7650          "line": 77,
7651          "description": "<p>PI is a mathematical constant with the value\n3.14159265358979323846. It is the ratio of the circumference\nof a circle to its diameter. It is useful in combination with\nthe trigonometric functions <a href=\"#/p5/sin\">sin()</a> and <a href=\"#/p5/cos\">cos()</a>.</p>\n",
7652          "itemtype": "property",
7653          "name": "PI",
7654          "type": "Number",
7655          "final": 1,
7656          "example": ["\n<div><code>\narc(50, 50, 80, 80, 0, PI);\n</code></div>"],
7657          "alt": "white half-circle with curve toward bottom of canvas.",
7658          "class": "p5",
7659          "module": "Constants",
7660          "submodule": "Constants"
7661        }, {
7662          "file": "src/core/constants.js",
7663          "line": 96,
7664          "description": "<p>QUARTER_PI is a mathematical constant with the value 0.7853982.\nIt is one quarter the ratio of the circumference of a circle to\nits diameter. It is useful in combination with the trigonometric\nfunctions <a href=\"#/p5/sin\">sin()</a> and <a href=\"#/p5/cos\">cos()</a>.</p>\n",
7665          "itemtype": "property",
7666          "name": "QUARTER_PI",
7667          "type": "Number",
7668          "final": 1,
7669          "example": ["\n<div><code>\narc(50, 50, 80, 80, 0, QUARTER_PI);\n</code></div>"],
7670          "alt": "white eighth-circle rotated about 40 degrees with curve bottom right canvas.",
7671          "class": "p5",
7672          "module": "Constants",
7673          "submodule": "Constants"
7674        }, {
7675          "file": "src/core/constants.js",
7676          "line": 115,
7677          "description": "<p>TAU is an alias for TWO_PI, a mathematical constant with the\nvalue 6.28318530717958647693. It is twice the ratio of the\ncircumference of a circle to its diameter. It is useful in\ncombination with the trigonometric functions <a href=\"#/p5/sin\">sin()</a> and <a href=\"#/p5/cos\">cos()</a>.</p>\n",
7678          "itemtype": "property",
7679          "name": "TAU",
7680          "type": "Number",
7681          "final": 1,
7682          "example": ["\n<div><code>\narc(50, 50, 80, 80, 0, TAU);\n</code></div>"],
7683          "alt": "80x80 white ellipse shape in center of canvas.",
7684          "class": "p5",
7685          "module": "Constants",
7686          "submodule": "Constants"
7687        }, {
7688          "file": "src/core/constants.js",
7689          "line": 134,
7690          "description": "<p>TWO_PI is a mathematical constant with the value\n6.28318530717958647693. It is twice the ratio of the\ncircumference of a circle to its diameter. It is useful in\ncombination with the trigonometric functions <a href=\"#/p5/sin\">sin()</a> and <a href=\"#/p5/cos\">cos()</a>.</p>\n",
7691          "itemtype": "property",
7692          "name": "TWO_PI",
7693          "type": "Number",
7694          "final": 1,
7695          "example": ["\n<div><code>\narc(50, 50, 80, 80, 0, TWO_PI);\n</code></div>"],
7696          "alt": "80x80 white ellipse shape in center of canvas.",
7697          "class": "p5",
7698          "module": "Constants",
7699          "submodule": "Constants"
7700        }, {
7701          "file": "src/core/constants.js",
7702          "line": 153,
7703          "description": "<p>Constant to be used with <a href=\"#/p5/angleMode\">angleMode()</a> function, to set the mode which\np5.js interprates and calculates angles (either DEGREES or RADIANS).</p>\n",
7704          "itemtype": "property",
7705          "name": "DEGREES",
7706          "type": "String",
7707          "final": 1,
7708          "example": ["\n<div class='norender'><code>\nfunction setup() {\n  angleMode(DEGREES);\n}\n</code></div>"],
7709          "class": "p5",
7710          "module": "Constants",
7711          "submodule": "Constants"
7712        }, {
7713          "file": "src/core/constants.js",
7714          "line": 167,
7715          "description": "<p>Constant to be used with <a href=\"#/p5/angleMode\">angleMode()</a> function, to set the mode which\np5.js interprates and calculates angles (either RADIANS or DEGREES).</p>\n",
7716          "itemtype": "property",
7717          "name": "RADIANS",
7718          "type": "String",
7719          "final": 1,
7720          "example": ["\n<div class='norender'><code>\nfunction setup() {\n  angleMode(RADIANS);\n}\n</code></div>"],
7721          "class": "p5",
7722          "module": "Constants",
7723          "submodule": "Constants"
7724        }, {
7725          "file": "src/core/constants.js",
7726          "line": 185,
7727          "itemtype": "property",
7728          "name": "CORNER",
7729          "type": "String",
7730          "final": 1,
7731          "class": "p5",
7732          "module": "Constants",
7733          "submodule": "Constants"
7734        }, {
7735          "file": "src/core/constants.js",
7736          "line": 190,
7737          "itemtype": "property",
7738          "name": "CORNERS",
7739          "type": "String",
7740          "final": 1,
7741          "class": "p5",
7742          "module": "Constants",
7743          "submodule": "Constants"
7744        }, {
7745          "file": "src/core/constants.js",
7746          "line": 195,
7747          "itemtype": "property",
7748          "name": "RADIUS",
7749          "type": "String",
7750          "final": 1,
7751          "class": "p5",
7752          "module": "Constants",
7753          "submodule": "Constants"
7754        }, {
7755          "file": "src/core/constants.js",
7756          "line": 200,
7757          "itemtype": "property",
7758          "name": "RIGHT",
7759          "type": "String",
7760          "final": 1,
7761          "class": "p5",
7762          "module": "Constants",
7763          "submodule": "Constants"
7764        }, {
7765          "file": "src/core/constants.js",
7766          "line": 205,
7767          "itemtype": "property",
7768          "name": "LEFT",
7769          "type": "String",
7770          "final": 1,
7771          "class": "p5",
7772          "module": "Constants",
7773          "submodule": "Constants"
7774        }, {
7775          "file": "src/core/constants.js",
7776          "line": 210,
7777          "itemtype": "property",
7778          "name": "CENTER",
7779          "type": "String",
7780          "final": 1,
7781          "class": "p5",
7782          "module": "Constants",
7783          "submodule": "Constants"
7784        }, {
7785          "file": "src/core/constants.js",
7786          "line": 215,
7787          "itemtype": "property",
7788          "name": "TOP",
7789          "type": "String",
7790          "final": 1,
7791          "class": "p5",
7792          "module": "Constants",
7793          "submodule": "Constants"
7794        }, {
7795          "file": "src/core/constants.js",
7796          "line": 220,
7797          "itemtype": "property",
7798          "name": "BOTTOM",
7799          "type": "String",
7800          "final": 1,
7801          "class": "p5",
7802          "module": "Constants",
7803          "submodule": "Constants"
7804        }, {
7805          "file": "src/core/constants.js",
7806          "line": 225,
7807          "itemtype": "property",
7808          "name": "BASELINE",
7809          "type": "String",
7810          "final": 1,
7811          "default": "alphabetic",
7812          "class": "p5",
7813          "module": "Constants",
7814          "submodule": "Constants"
7815        }, {
7816          "file": "src/core/constants.js",
7817          "line": 231,
7818          "itemtype": "property",
7819          "name": "POINTS",
7820          "type": "Number",
7821          "final": 1,
7822          "default": "0x0000",
7823          "class": "p5",
7824          "module": "Constants",
7825          "submodule": "Constants"
7826        }, {
7827          "file": "src/core/constants.js",
7828          "line": 237,
7829          "itemtype": "property",
7830          "name": "LINES",
7831          "type": "Number",
7832          "final": 1,
7833          "default": "0x0001",
7834          "class": "p5",
7835          "module": "Constants",
7836          "submodule": "Constants"
7837        }, {
7838          "file": "src/core/constants.js",
7839          "line": 243,
7840          "itemtype": "property",
7841          "name": "LINE_STRIP",
7842          "type": "Number",
7843          "final": 1,
7844          "default": "0x0003",
7845          "class": "p5",
7846          "module": "Constants",
7847          "submodule": "Constants"
7848        }, {
7849          "file": "src/core/constants.js",
7850          "line": 249,
7851          "itemtype": "property",
7852          "name": "LINE_LOOP",
7853          "type": "Number",
7854          "final": 1,
7855          "default": "0x0002",
7856          "class": "p5",
7857          "module": "Constants",
7858          "submodule": "Constants"
7859        }, {
7860          "file": "src/core/constants.js",
7861          "line": 255,
7862          "itemtype": "property",
7863          "name": "TRIANGLES",
7864          "type": "Number",
7865          "final": 1,
7866          "default": "0x0004",
7867          "class": "p5",
7868          "module": "Constants",
7869          "submodule": "Constants"
7870        }, {
7871          "file": "src/core/constants.js",
7872          "line": 261,
7873          "itemtype": "property",
7874          "name": "TRIANGLE_FAN",
7875          "type": "Number",
7876          "final": 1,
7877          "default": "0x0006",
7878          "class": "p5",
7879          "module": "Constants",
7880          "submodule": "Constants"
7881        }, {
7882          "file": "src/core/constants.js",
7883          "line": 267,
7884          "itemtype": "property",
7885          "name": "TRIANGLE_STRIP",
7886          "type": "Number",
7887          "final": 1,
7888          "default": "0x0005",
7889          "class": "p5",
7890          "module": "Constants",
7891          "submodule": "Constants"
7892        }, {
7893          "file": "src/core/constants.js",
7894          "line": 273,
7895          "itemtype": "property",
7896          "name": "QUADS",
7897          "type": "String",
7898          "final": 1,
7899          "class": "p5",
7900          "module": "Constants",
7901          "submodule": "Constants"
7902        }, {
7903          "file": "src/core/constants.js",
7904          "line": 278,
7905          "itemtype": "property",
7906          "name": "QUAD_STRIP",
7907          "type": "String",
7908          "final": 1,
7909          "default": "quad_strip",
7910          "class": "p5",
7911          "module": "Constants",
7912          "submodule": "Constants"
7913        }, {
7914          "file": "src/core/constants.js",
7915          "line": 284,
7916          "itemtype": "property",
7917          "name": "CLOSE",
7918          "type": "String",
7919          "final": 1,
7920          "class": "p5",
7921          "module": "Constants",
7922          "submodule": "Constants"
7923        }, {
7924          "file": "src/core/constants.js",
7925          "line": 289,
7926          "itemtype": "property",
7927          "name": "OPEN",
7928          "type": "String",
7929          "final": 1,
7930          "class": "p5",
7931          "module": "Constants",
7932          "submodule": "Constants"
7933        }, {
7934          "file": "src/core/constants.js",
7935          "line": 294,
7936          "itemtype": "property",
7937          "name": "CHORD",
7938          "type": "String",
7939          "final": 1,
7940          "class": "p5",
7941          "module": "Constants",
7942          "submodule": "Constants"
7943        }, {
7944          "file": "src/core/constants.js",
7945          "line": 299,
7946          "itemtype": "property",
7947          "name": "PIE",
7948          "type": "String",
7949          "final": 1,
7950          "class": "p5",
7951          "module": "Constants",
7952          "submodule": "Constants"
7953        }, {
7954          "file": "src/core/constants.js",
7955          "line": 304,
7956          "itemtype": "property",
7957          "name": "PROJECT",
7958          "type": "String",
7959          "final": 1,
7960          "default": "square",
7961          "class": "p5",
7962          "module": "Constants",
7963          "submodule": "Constants"
7964        }, {
7965          "file": "src/core/constants.js",
7966          "line": 310,
7967          "itemtype": "property",
7968          "name": "SQUARE",
7969          "type": "String",
7970          "final": 1,
7971          "default": "butt",
7972          "class": "p5",
7973          "module": "Constants",
7974          "submodule": "Constants"
7975        }, {
7976          "file": "src/core/constants.js",
7977          "line": 316,
7978          "itemtype": "property",
7979          "name": "ROUND",
7980          "type": "String",
7981          "final": 1,
7982          "class": "p5",
7983          "module": "Constants",
7984          "submodule": "Constants"
7985        }, {
7986          "file": "src/core/constants.js",
7987          "line": 321,
7988          "itemtype": "property",
7989          "name": "BEVEL",
7990          "type": "String",
7991          "final": 1,
7992          "class": "p5
7992",
7993          "module": "Constants",
7994          "submodule": "Constants"
7995        }, {
7996          "file": "src/core/constants.js",
7997          "line": 326,
7998          "itemtype": "property",
7999          "name": "MITER",
8000          "type": "String",
8001          "final": 1,
8002          "class": "p5",
8003          "module": "Constants",
8004          "submodule": "Constants"
8005        }, {
8006          "file": "src/core/constants.js",
8007          "line": 333,
8008          "itemtype": "property",
8009          "name": "RGB",
8010          "type": "String",
8011          "final": 1,
8012          "class": "p5",
8013          "module": "Constants",
8014          "submodule": "Constants"
8015        }, {
8016          "file": "src/core/constants.js",
8017          "line": 338,
8018          "itemtype": "property",
8019          "name": "HSB",
8020          "type": "String",
8021          "final": 1,
8022          "class": "p5",
8023          "module": "Constants",
8024          "submodule": "Constants"
8025        }, {
8026          "file": "src/core/constants.js",
8027          "line": 343,
8028          "itemtype": "property",
8029          "name": "HSL",
8030          "type": "String",
8031          "final": 1,
8032          "class": "p5",
8033          "module": "Constants",
8034          "submodule": "Constants"
8035        }, {
8036          "file": "src/core/constants.js",
8037          "line": 350,
8038          "itemtype": "property",
8039          "name": "AUTO",
8040          "type": "String",
8041          "final": 1,
8042          "class": "p5",
8043          "module": "Constants",
8044          "submodule": "Constants"
8045        }, {
8046          "file": "src/core/constants.js",
8047          "line": 373,
8048          "itemtype": "property",
8049          "name": "BLEND",
8050          "type": "String",
8051          "final": 1,
8052          "default": "source-over",
8053          "class": "p5",
8054          "module": "Constants",
8055          "submodule": "Constants"
8056        }, {
8057          "file": "src/core/constants.js",
8058          "line": 379,
8059          "itemtype": "property",
8060          "name": "ADD",
8061          "type": "String",
8062          "final": 1,
8063          "default": "lighter",
8064          "class": "p5",
8065          "module": "Constants",
8066          "submodule": "Constants"
8067        }, {
8068          "file": "src/core/constants.js",
8069          "line": 387,
8070          "itemtype": "property",
8071          "name": "DARKEST",
8072          "type": "String",
8073          "final": 1,
8074          "class": "p5",
8075          "module": "Constants",
8076          "submodule": "Constants"
8077        }, {
8078          "file": "src/core/constants.js",
8079          "line": 392,
8080          "itemtype": "property",
8081          "name": "LIGHTEST",
8082          "type": "String",
8083          "final": 1,
8084          "default": "lighten",
8085          "class": "p5",
8086          "module": "Constants",
8087          "submodule": "Constants"
8088        }, {
8089          "file": "src/core/constants.js",
8090          "line": 398,
8091          "itemtype": "property",
8092          "name": "DIFFERENCE",
8093          "type": "String",
8094          "final": 1,
8095          "class": "p5",
8096          "module": "Constants",
8097          "submodule": "Constants"
8098        }, {
8099          "file": "src/core/constants.js",
8100          "line": 403,
8101          "itemtype": "property",
8102          "name": "EXCLUSION",
8103          "type": "String",
8104          "final": 1,
8105          "class": "p5",
8106          "module": "Constants",
8107          "submodule": "Constants"
8108        }, {
8109          "file": "src/core/constants.js",
8110          "line": 408,
8111          "itemtype": "property",
8112          "name": "MULTIPLY",
8113          "type": "String",
8114          "final": 1,
8115          "class": "p5",
8116          "module": "Constants",
8117          "submodule": "Constants"
8118        }, {
8119          "file": "src/core/constants.js",
8120          "line": 413,
8121          "itemtype": "property",
8122          "name": "SCREEN",
8123          "type": "String",
8124          "final": 1,
8125          "class": "p5",
8126          "module": "Constants",
8127          "submodule": "Constants"
8128        }, {
8129          "file": "src/core/constants.js",
8130          "line": 418,
8131          "itemtype": "property",
8132          "name": "REPLACE",
8133          "type": "String",
8134          "final": 1,
8135          "default": "copy",
8136          "class": "p5",
8137          "module": "Constants",
8138          "submodule": "Constants"
8139        }, {
8140          "file": "src/core/constants.js",
8141          "line": 424,
8142          "itemtype": "property",
8143          "name": "OVERLAY",
8144          "type": "String",
8145          "final": 1,
8146          "class": "p5",
8147          "module": "Constants",
8148          "submodule": "Constants"
8149        }, {
8150          "file": "src/core/constants.js",
8151          "line": 429,
8152          "itemtype": "property",
8153          "name": "HARD_LIGHT",
8154          "type": "String",
8155          "final": 1,
8156          "class": "p5",
8157          "module": "Constants",
8158          "submodule": "Constants"
8159        }, {
8160          "file": "src/core/constants.js",
8161          "line": 434,
8162          "itemtype": "property",
8163          "name": "SOFT_LIGHT",
8164          "type": "String",
8165          "final": 1,
8166          "class": "p5",
8167          "module": "Constants",
8168          "submodule": "Constants"
8169        }, {
8170          "file": "src/core/constants.js",
8171          "line": 439,
8172          "itemtype": "property",
8173          "name": "DODGE",
8174          "type": "String",
8175          "final": 1,
8176          "default": "color-dodge",
8177          "class": "p5",
8178          "module": "Constants",
8179          "submodule": "Constants"
8180        }, {
8181          "file": "src/core/constants.js",
8182          "line": 445,
8183          "itemtype": "property",
8184          "name": "BURN",
8185          "type": "String",
8186          "final": 1,
8187          "default": "color-burn",
8188          "class": "p5",
8189          "module": "Constants",
8190          "submodule": "Constants"
8191        }, {
8192          "file": "src/core/constants.js",
8193          "line": 453,
8194          "itemtype": "property",
8195          "name": "THRESHOLD",
8196          "type": "String",
8197          "final": 1,
8198          "class": "p5",
8199          "module": "Constants",
8200          "submodule": "Constants"
8201        }, {
8202          "file": "src/core/constants.js",
8203          "line": 458,
8204          "itemtype": "property",
8205          "name": "GRAY",
8206          "type": "String",
8207          "final": 1,
8208          "class": "p5",
8209          "module": "Constants",
8210          "submodule": "Constants"
8211        }, {
8212          "file": "src/core/constants.js",
8213          "line": 463,
8214          "itemtype": "property",
8215          "name": "OPAQUE",
8216          "type": "String",
8217          "final": 1,
8218          "class": "p5",
8219          "module": "Constants",
8220          "submodule": "Constants"
8221        }, {
8222          "file": "src/core/constants.js",
8223          "line": 468,
8224          "itemtype": "property",
8225          "name": "INVERT",
8226          "type": "String",
8227          "final": 1,
8228          "class": "p5",
8229          "module": "Constants",
8230          "submodule": "Constants"
8231        }, {
8232          "file": "src/core/constants.js",
8233          "line": 473,
8234          "itemtype": "property",
8235          "name": "POSTERIZE",
8236          "type": "String",
8237          "final": 1,
8238          "class": "p5",
8239          "module": "Constants",
8240          "submodule": "Constants"
8241        }, {
8242          "file": "src/core/constants.js",
8243          "line": 478,
8244          "itemtype": "property",
8245          "name": "DILATE",
8246          "type": "String",
8247          "final": 1,
8248          "class": "p5",
8249          "module": "Constants",
8250          "submodule": "Constants"
8251        }, {
8252          "file": "src/core/constants.js",
8253          "line": 483,
8254          "itemtype": "property",
8255          "name": "ERODE",
8256          "type": "String",
8257          "final": 1,
8258          "class": "p5",
8259          "module": "Constants",
8260          "submodule": "Constants"
8261        }, {
8262          "file": "src/core/constants.js",
8263          "line": 488,
8264          "itemtype": "property",
8265          "name": "BLUR",
8266          "type": "String",
8267          "final": 1,
8268          "class": "p5",
8269          "module": "Constants",
8270          "submodule": "Constants"
8271        }, {
8272          "file": "src/core/constants.js",
8273          "line": 495,
8274          "itemtype": "property",
8275          "name": "NORMAL",
8276          "type": "String",
8277          "final": 1,
8278          "class": "p5",
8279          "module": "Constants",
8280          "submodule": "Constants"
8281        }, {
8282          "file": "src/core/constants.js",
8283          "line": 500,
8284          "itemtype": "property",
8285          "name": "ITALIC",
8286          "type": "String",
8287          "final": 1,
8288          "class": "p5",
8289          "module": "Constants",
8290          "submodule": "Constants"
8291        }, {
8292          "file": "src/core/constants.js",
8293          "line": 505,
8294          "itemtype": "property",
8295          "name": "BOLD",
8296          "type": "String",
8297          "final": 1,
8298          "class": "p5",
8299          "module": "Constants",
8300          "submodule": "Constants"
8301        }, {
8302          "file": "src/core/constants.js",
8303          "line": 510,
8304          "itemtype": "property",
8305          "name": "BOLDITALIC",
8306          "type": "String",
8307          "final": 1,
8308          "class": "p5",
8309          "module": "Constants",
8310          "submodule": "Constants"
8311        }, {
8312          "file": "src/core/constants.js",
8313          "line": 545,
8314          "itemtype": "property",
8315          "name": "LANDSCAPE",
8316          "type": "String",
8317          "final": 1,
8318          "class": "p5",
8319          "module": "Constants",
8320          "submodule": "Constants"
8321        }, {
8322          "file": "src/core/constants.js",
8323          "line": 550,
8324          "itemtype": "property",
8325          "name": "PORTRAIT",
8326          "type": "String",
8327          "final": 1,
8328          "class": "p5",
8329          "module": "Constants",
8330          "submodule": "Constants"
8331        }, {
8332          "file": "src/core/constants.js",
8333          "line": 560,
8334          "itemtype": "property",
8335          "name": "GRID",
8336          "type": "String",
8337          "final": 1,
8338          "class": "p5",
8339          "module": "Constants",
8340          "submodule": "Constants"
8341        }, {
8342          "file": "src/core/constants.js",
8343          "line": 566,
8344          "itemtype": "property",
8345          "name": "AXES",
8346          "type": "String",
8347          "final": 1,
8348          "class": "p5",
8349          "module": "Constants",
8350          "submodule": "Constants"
8351        }, {
8352          "file": "src/core/environment.js",
8353          "line": 22,
8354          "description": "<p>The <a href=\"#/p5/print\">print()</a> function writes to the console area of your browser.\nThis function is often helpful for looking at the data a program is\nproducing. This function creates a new line of text for each call to\nthe function. Individual elements can be\nseparated with quotes (&quot;&quot;) and joined with the addition operator (+).</p>\n<p>Note that calling print() without any arguments invokes the window.print()\nfunction which opens the browser&#39;s print dialog. To print a blank line\nto console you can write print(&#39;\\n&#39;).</p>\n",
8355          "itemtype": "method",
8356          "name": "print",
8357          "params": [{
8358            "name": "contents",
8359            "description": "<p>any combination of Number, String, Object, Boolean,\n                      Array to print</p>\n",
8360            "type": "Any"
8361          }],
8362          "example": ["\n<div><code class='norender'>\nlet x = 10;\nprint('The value of x is ' + x);\n// prints \"The value of x is 10\"\n</code></div>"],
8363          "alt": "default grey canvas",
8364          "class": "p5",
8365          "module": "Environment",
8366          "submodule": "Environment"
8367        }, {
8368          "file": "src/core/environment.js",
8369          "line": 53,
8370          "description": "<p>The system variable <a href=\"#/p5/frameCount\">frameCount</a> contains the number of frames that have\nbeen displayed since the program started. Inside <a href=\"#/p5/setup\">setup()</a> the value is 0,\nafter the first iteration of draw it is 1, etc.</p>\n",
8371          "itemtype": "property",
8372          "name": "frameCount",
8373          "type": "Integer",
8374          "readonly": "",
8375          "example": ["\n  <div><code>\nfunction setup() {\n  frameRate(30);\n  textSize(30);\n  textAlign(CENTER);\n}\n\nfunction draw() {\n  background(200);\n  text(frameCount, width / 2, height / 2);\n}\n</code></div>"],
8376          "alt": "numbers rapidly counting upward with frame count set to 30.",
8377          "class": "p5",
8378          "module": "Environment",
8379          "submodule": "Environment"
8380        }, {
8381          "file": "src/core/environment.js",
8382          "line": 80,
8383          "description": "<p>Confirms if the window a p5.js program is in is &quot;focused,&quot; meaning that\nthe sketch will accept mouse or keyboard input. This variable is\n&quot;true&quot; if the window is focused and &quot;false&quot; if not.</p>\n",
8384          "itemtype": "property",
8385          "name": "focused",
8386          "type": "Boolean",
8387          "readonly": "",
8388          "example": ["\n<div><code>\n// To demonstrate, put two windows side by side.\n// Click on the window that the p5 sketch isn't in!\nfunction draw() {\n  background(200);\n  noStroke();\n  fill(0, 200, 0);\n  ellipse(25, 25, 50, 50);\n\n  if (!focused) {\n   // or \"if (focused === false)\"\n    stroke(200, 0, 0);\n    line(0, 0, 100, 100);\n    line(100, 0, 0, 100);\n  }\n}\n</code></div>"],
8389          "alt": "green 50x50 ellipse at top left. Red X covers canvas when page focus changes",
8390          "class": "p5",
8391          "module": "Environment",
8392          "submodule": "Environment"
8393        }, {
8394          "file": "src/core/environment.js",
8395          "line": 112,
8396          "description": "<p>Sets the cursor to a predefined symbol or an image, or makes it visible\nif already hidden. If you are trying to set an image as the cursor, the\nrecommended size is 16x16 or 32x32 pixels. The values for parameters x and y\nmust be less than the dimensions of the image.</p>\n",
8397          "itemtype": "method",
8398          "name": "cursor",
8399          "params": [{
8400            "name": "type",
8401            "description": "<p>Built-In: either ARROW, CROSS, HAND, MOVE, TEXT and WAIT\n                              Native CSS properties: &#39;grab&#39;, &#39;progress&#39;, &#39;cell&#39; etc.\n                              External: path for cursor&#39;s images\n                              (Allowed File extensions: .cur, .gif, .jpg, .jpeg, .png)\n                              For more information on Native CSS cursors and url visit:\n                              <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/cursor\">https://developer.mozilla.org/en-US/docs/Web/CSS/cursor</a></p>\n",
8402            "type": "String|Constant"
8403          }, {
8404            "name": "x",
8405            "description": "<p>the horizontal active spot of the cursor (must be less than 32)</p>\n",
8406            "type": "Number",
8407            "optional": true
8408          }, {
8409            "name": "y",
8410            "description": "<p>the vertical active spot of the cursor (must be less than 32)</p>\n",
8411            "type": "Number",
8412            "optional": true
8413          }],
8414          "example": ["\n<div><code>
8414\n// Move the mouse across the quadrants\n// to see the cursor change\nfunction draw() {\n  line(width / 2, 0, width / 2, height);\n  line(0, height / 2, width, height / 2);\n  if (mouseX < 50 && mouseY < 50) {\n    cursor(CROSS);\n  } else if (mouseX > 50 && mouseY < 50) {\n    cursor('progress');\n  } else if (mouseX > 50 && mouseY > 50) {\n    cursor('https://s3.amazonaws.com/mupublicdata/cursor.cur');\n  } else {\n    cursor('grab');\n  }\n}\n</code></div>"],
8415          "alt": "canvas is divided into four quadrants. cursor on first is a cross, second is a progress,\nthird is a custom cursor using path to the cursor and fourth is a grab.",
8416          "class": "p5",
8417          "module": "Environment",
8418          "submodule": "Environment"
8419        }, {
8420          "file": "src/core/environment.js",
8421          "line": 181,
8422          "description": "<p>Specifies the number of frames to be displayed every second. For example,\nthe function call frameRate(30) will attempt to refresh 30 times a second.\nIf the processor is not fast enough to maintain the specified rate, the\nframe rate will not be achieved. Setting the frame rate within <a href=\"#/p5/setup\">setup()</a> is\nrecommended. The default frame rate is based on the frame rate of the display\n(here also called &quot;refresh rate&quot;), which is set to 60 frames per second on most\ncomputers. A frame rate of 24 frames per second (usual for movies) or above\nwill be enough for smooth animations\nThis is the same as setFrameRate(val).\n<br><br>\nCalling <a href=\"#/p5/frameRate\">frameRate()</a> with no arguments returns the current framerate. The\ndraw function must run at least once before it will return a value. This\nis the same as <a href=\"#/p5/getFrameRate\">getFrameRate()</a>.\n<br><br>\nCalling <a href=\"#/p5/frameRate\">frameRate()</a> with arguments that are not of the type numbers\nor are non positive also returns current framerate.</p>\n",
8423          "itemtype": "method",
8424          "name": "frameRate",
8425          "chainable": 1,
8426          "example": ["\n\n<div><code>\nlet rectX = 0;\nlet fr = 30; //starting FPS\nlet clr;\n\nfunction setup() {\n  background(200);\n  frameRate(fr); // Attempt to refresh at starting FPS\n  clr = color(255, 0, 0);\n}\n\nfunction draw() {\n  background(200);\n  rectX = rectX += 1; // Move Rectangle\n\n  if (rectX >= width) {\n   // If you go off screen.\n    if (fr === 30) {\n      clr = color(0, 0, 255);\n      fr = 10;\n      frameRate(fr); // make frameRate 10 FPS\n    } else {\n      clr = color(255, 0, 0);\n      fr = 30;\n      frameRate(fr); // make frameRate 30 FPS\n    }\n    rectX = 0;\n  }\n  fill(clr);\n  rect(rectX, 40, 20, 20);\n}\n</code></div>"],
8427          "alt": "blue rect moves left to right, followed by red rect moving faster. Loops.",
8428          "class": "p5",
8429          "module": "Environment",
8430          "submodule": "Environment",
8431          "overloads": [{
8432            "line": 181,
8433            "params": [{
8434              "name": "fps",
8435              "description": "<p>number of frames to be displayed every second</p>\n",
8436              "type": "Number"
8437            }],
8438            "chainable": 1
8439          }, {
8440            "line": 242,
8441            "params": [],
8442            "return": {
8443              "description": "current frameRate",
8444              "type": "Number"
8445            }
8446          }]
8447        }, {
8448          "file": "src/core/environment.js",
8449          "line": 281,
8450          "description": "<p>Hides the cursor from view.</p>\n",
8451          "itemtype": "method",
8452          "name": "noCursor",
8453          "example": ["\n<div><code>\nfunction setup() {\n  noCursor();\n}\n\nfunction draw() {\n  background(200);\n  ellipse(mouseX, mouseY, 10, 10);\n}\n</code></div>"],
8454          "alt": "cursor becomes 10x 10 white ellipse the moves with mouse x and y.",
8455          "class": "p5",
8456          "module": "Environment",
8457          "submodule": "Environment"
8458        }, {
8459          "file": "src/core/environment.js",
8460          "line": 306,
8461          "description": "<p>System variable that stores the width of the screen display according to The\ndefault <a href=\"#/p5/pixelDensity\">pixelDensity</a>. This is used to run a\nfull-screen program on any display size. To return actual screen size,\nmultiply this by pixelDensity.</p>\n",
8462          "itemtype": "property",
8463          "name": "displayWidth",
8464          "type": "Number",
8465          "readonly": "",
8466          "example": ["\n<div class=\"norender\"><code>\ncreateCanvas(displayWidth, displayHeight);\n</code></div>"],
8467          "alt": "cursor becomes 10x 10 white ellipse the moves with mouse x and y.",
8468          "class": "p5",
8469          "module": "Environment",
8470          "submodule": "Environment"
8471        }, {
8472          "file": "src/core/environment.js",
8473          "line": 325,
8474          "description": "<p>System variable that stores the height of the screen display according to The\ndefault <a href=\"#/p5/pixelDensity\">pixelDensity</a>. This is used to run a\nfull-screen program on any display size. To return actual screen size,\nmultiply this by pixelDensity.</p>\n",
8475          "itemtype": "property",
8476          "name": "displayHeight",
8477          "type": "Number",
8478          "readonly": "",
8479          "example": ["\n<div class=\"norender\"><code>\ncreateCanvas(displayWidth, displayHeight);\n</code></div>"],
8480          "alt": "no display.",
8481          "class": "p5",
8482          "module": "Environment",
8483          "submodule": "Environment"
8484        }, {
8485          "file": "src/core/environment.js",
8486          "line": 344,
8487          "description": "<p>System variable that stores the width of the inner window, it maps to\nwindow.innerWidth.</p>\n",
8488          "itemtype": "property",
8489          "name": "windowWidth",
8490          "type": "Number",
8491          "readonly": "",
8492          "example": ["\n<div class=\"norender\"><code>\ncreateCanvas(windowWidth, windowHeight);\n</code></div>"],
8493          "alt": "no display.",
8494          "class": "p5",
8495          "module": "Environment",
8496          "submodule": "Environment"
8497        }, {
8498          "file": "src/core/environment.js",
8499          "line": 360,
8500          "description": "<p>System variable that stores the height of the inner window, it maps to\nwindow.innerHeight.</p>\n",
8501          "itemtype": "property",
8502          "name": "windowHeight",
8503          "type": "Number",
8504          "readonly": "",
8505          "example": ["\n<div class=\"norender\"><code>\ncreateCanvas(windowWidth, windowHeight);\n</code></div>"],
8506          "alt": "no display.",
8507          "class": "p5",
8508          "module": "Environment",
8509          "submodule": "Environment"
8510        }, {
8511          "file": "src/core/environment.js",
8512          "line": 376,
8513          "description": "<p>The <a href=\"#/p5/windowResized\">windowResized()</a> function is called once every time the browser window\nis resized. This is a good place to resize the canvas or do any other\nadjustments to accommodate the new window size.</p>\n",
8514          "itemtype": "method",
8515          "name": "windowResized",
8516          "example": ["\n<div class=\"norender\"><code>\nfunction setup() {\n  createCanvas(windowWidth, windowHeight);\n}\n\nfunction draw() {\n  background(0, 100, 200);\n}\n\nfunction windowResized() {\n  resizeCanvas(windowWidth, windowHeight);\n}\n</code></div>"],
8517          "alt": "no display.",
8518          "class": "p5",
8519          "module": "Environment",
8520          "submodule": "Environment"
8521        }, {
8522          "file": "src/core/environment.js",
8523          "line": 430,
8524          "description": "<p>System variable that stores the width of the drawing canvas. This value\nis set by the first parameter of the <a href=\"#/p5/createCanvas\">createCanvas()</a> function.\nFor example, the function call createCanvas(320, 240) sets the width\nvariable to the value 320. The value of width defaults to 100 if\n<a href=\"#/p5/createCanvas\">createCanvas()</a> is not used in a program.</p>\n",
8525          "itemtype": "property",
8526          "name": "width",
8527          "type": "Number",
8528          "readonly": "",
8529          "class": "p5",
8530          "module": "Environment",
8531          "submodule": "Environment"
8532        }, {
8533          "file": "src/core/environment.js",
8534          "line": 442,
8535          "description": "<p>System variable that stores the height of the drawing canvas. This value\nis set by the second parameter of the <a href=\"#/p5/createCanvas\">createCanvas()</a> function. For\nexample, the function call createCanvas(320, 240) sets the height\nvariable to the value 240. The value of height defaults to 100 if\n<a href=\"#/p5/createCanvas\">createCanvas()</a> is not used in a program.</p>\n",
8536          "itemtype": "property",
8537          "name": "height",
8538          "type": "Number",
8539          "readonly": "",
8540          "class": "p5",
8541          "module": "Environment",
8542          "submodule": "Environment"
8543        }, {
8544          "file": "src/core/environment.js",
8545          "line": 454,
8546          "description": "<p>If argument is given, sets the sketch to fullscreen or not based on the\nvalue of the argument. If no argument is given, returns the current\nfullscreen state. Note that due to browser restrictions this can only\nbe called on user input, for example, on mouse press like the example\nbelow.</p>\n",
8547          "itemtype": "method",
8548          "name": "fullscreen",
8549          "params": [{
8550            "name": "val",
8551            "description": "<p>whether the sketch should be in fullscreen mode\nor not</p>\n",
8552            "type": "Boolean",
8553            "optional": true
8554          }],
8555          "return": {
8556            "description": "current fullscreen state",
8557            "type": "Boolean"
8558          },
8559          "example": ["\n<div>\n<code>\n// Clicking in the box toggles fullscreen on and off.\nfunction setup() {\n  background(200);\n}\nfunction mousePressed() {\n  if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {\n    let fs = fullscreen();\n    fullscreen(!fs);\n  }\n}\n</code>\n</div>"],
8560          "alt": "no display.",
8561          "class": "p5",
8562          "module": "Environment",
8563          "submodule": "Environment"
8564        }, {
8565          "file": "src/core/environment.js",
8566          "line": 505,
8567          "description": "<p>Sets the pixel scaling for high pixel density displays. By default\npixel density is set to match display density, call pixelDensity(1)\nto turn this off. Calling <a href=\"#/p5/pixelDensity\">pixelDensity()</a> with no arguments returns\nthe current pixel density of the sketch.</p>\n",
8568          "itemtype": "method",
8569          "name": "pixelDensity",
8570          "chainable": 1,
8571          "example": ["\n<div>\n<code>\nfunction setup() {\n  pixelDensity(1);\n  createCanvas(100, 100);\n  background(200);\n  ellipse(width / 2, height / 2, 50, 50);\n}\n</code>\n</div>\n<div>\n<code>\nfunction setup() {\n  pixelDensity(3.0);\n  createCanvas(100, 100);\n  background(200);\n  ellipse(width / 2, height / 2, 50, 50);\n}\n</code>\n</div>"],
8572          "alt": "fuzzy 50x50 white ellipse with black outline in center of canvas.\nsharp 50x50 white ellipse with black outline in center of canvas.",
8573          "class": "p5",
8574          "module": "Environment",
8575          "submodule": "Environment",
8576          "overloads": [{
8577            "line": 505,
8578            "params": [{
8579              "name": "val",
8580              "description": "<p>whether or how much the sketch should scale</p>\n",
8581              "type": "Number"
8582            }],
8583            "chainable": 1
8584          }, {
8585            "line": 540,
8586            "params": [],
8587            "return": {
8588              "description": "current pixel density of the sketch",
8589              "type": "Number"
8590            }
8591          }]
8592        }, {
8593          "file": "src/core/environment.js",
8594          "line": 560,
8595          "description": "<p>Returns the pixel density of the current display the sketch is running on.</p>\n",
8596          "itemtype": "method",
8597          "name": "displayDensity",
8598          "return": {
8599            "description": "current pixel density of the display",
8600            "type": "Number"
8601          },
8602          "example": ["\n<div>\n<code>\nfunction setup() {\n  let density = displayDensity();\n  pixelDensity(density);\n  createCanvas(100, 100);\n  background(200);\n  ellipse(width / 2, height / 2, 50, 50);\n}\n</code>\n</div>"],
8603          "alt": "50x50 white ellipse with black outline in center of canvas.",
8604          "class": "p5",
8605          "module": "Environment",
8606          "submodule": "Environment"
8607        }, {
8608          "file": "src/core/environment.js",
8609          "line": 617,
8610          "description": "<p>Gets the current URL.</p>\n",
8611          "itemtype": "method",
8612          "name": "getURL",
8613          "return": {
8614            "description": "url",
8615            "type": "String"
8616          },
8617          "example": ["\n<div>\n<code>\nlet url;\nlet x = 100;\n\nfunction setup() {\n  fill(0);\n  noStroke();\n  url = getURL();\n}\n\nfunction draw() {\n  background(200);\n  text(url, x, height / 2);\n  x--;\n}\n</code>\n</div>"],
8618          "alt": "current url (http://p5js.org/reference/#/p5/getURL) moves right to left.",
8619          "class": "p5",
8620          "module": "Environment",
8621          "submodule": "Environment"
8622        }, {
8623          "file": "src/core/environment.js",
8624          "line": 648,
8625          "description": "<p>Gets the current URL path as an array.</p>\n",
8626          "itemtype": "method",
8627          "name": "getURLPath",
8628          "return": {
8629            "description": "path components",
8630            "type": "String[]"
8631          },
8632          "example": ["\n<div class='norender'><code>\nfunction setup() {\n  let urlPath = getURLPath();\n  for (let i = 0; i < urlPath.length; i++) {\n    text(urlPath[i], 10, i * 20 + 20);\n  }\n}\n</code></div>"],
8633          "alt": "no display",
8634          "class": "p5",
8635          "module": "Environment",
8636          "submodule": "Environment"
8637        }, {
8638          "file": "src/core/environment.js",
8639          "line": 671,
8640          "description": "<p>Gets the current URL params as an Object.</p>\n",
8641          "itemtype": "method",
8642          "name": "getURLParams",
8643          "return": {
8644            "description": "URL params",
8645            "type": "Object"
8646          },
8647          "example": ["\n<div class='norender notest'>\n<code>\n// Example: http://p5js.org?year=2014&month=May&day=15\n\nfunction setup() {\n  let params = getURLParams();\n  text(params.day, 10, 20);\n  text(params.month, 10, 40);\n  text(params.year, 10, 60);\n}\n</code>\n</div>"],
8648          "alt": "no display.",
8649          "class": "p5",
8650          "module": "Environment",
8651          "submodule": "Environment"
8652        }, {
8653          "file": "src/core/error_helpers.js",
8654          "line": 1,
8655          "requires": ["core"],
8656          "class": "p5",
8657          "module": "Environment"
8658        }, {
8659          "file": "src/core/error_helpers.js",
8660          "line": 584,
8661          "description": "<p>Validates parameters\nparam  {String}               func    the name of the function\nparam  {Array}                args    user input arguments</p>\n<p>example:\n var a;\n ellipse(10,10,a,5);\nconsole ouput:\n &quot;It looks like ellipse received an empty variable in spot #2.&quot;</p>\n<p>example:\n ellipse(10,&quot;foo&quot;,5,5);\nconsole output:\n &quot;ellipse was expecting a number for parameter #1,\n          received &quot;foo&quot; instead.&quot;</p>\n",
8662          "class": "p5",
8663          "module": "Environment"
8664        }, {
8665          "file": "src/core/error_helpers.js",
8666          "line": 645,
8667          "description": "<p>Prints out all the colors in the color pallete with white text.\nFor color blindness testing.</p>\n",
8668          "class": "p5",
8669          "module": "Environment"
8670        }, {
8671          "file": "src/core/helpers.js",
8672          "line": 1,
8673          "requires": ["constants"],
8674          "class": "p5",
8675          "module": "Environment"
8676        }, {
8677          "file": "src/core/legacy.js",
8678          "line": 1,
8679          "requires": ["core\nThese are functions that are part of the Processing API but are not part of\nthe p5.js API. In some cases they have a new name", "in others", "they are\nremoved completely. Not all unsupported Processing functions are listed here\nbut we try to include ones that a user coming from Processing might likely\ncall."],
8680          "class": "p5",
8681          "module": "Environment"
8682        }, {
8683          "file": "src/core/main.js",
8684          "line": 49,
8685          "description": "<p>Called directly before <a href=\"#/p5/setup\">setup()</a>, the <a href=\"#/p5/preload\">preload()</a> function is used to handle\nasynchronous loading of external files in a blocking way. If a preload\nfunction is defined, <a href=\"#/p5/setup\">setup()</a> will wait until any load calls within have\nfinished. Nothing besides load calls (<a href=\"#/p5/loadImage\">loadImage</a>, <a href=\"#/p5/loadJSON\">loadJSON</a>, <a href=\"#/p5/loadFont\">loadFont</a>,\n<a href=\"#/p5/loadStrings\">loadStrings</a>, etc.) should be inside the preload function. If asynchronous\nloading is preferred, the load methods can instead be called in <a href=\"#/p5/setup\">setup()</a>\nor anywhere else with the use of a callback parameter.\n<br><br>\nBy default the text &quot;loading...&quot; will be displayed. To make your own\nloading page, include an HTML element with id &quot;p5_loading&quot; in your\npage. More information <a href=\"http://bit.ly/2kQ6Nio\">here</a>.</p>\n",
8686          "itemtype": "method",
8687          "name": "preload",
8688          "example": ["\n<div><code>\nlet img;\nlet c;\nfunction preload() {\n  // preload() runs once\n  img = loadImage('assets/laDefense.jpg');\n}\n\nfunction setup() {\n  // setup() waits until preload() is done\n  img.loadPixels();\n  // get color of middle pixel\n  c = img.get(img.width / 2, img.height / 2);\n}\n\nfunction draw() {\n  background(c);\n  image(img, 25, 25, 50, 50);\n}\n</code></div>"],
8689          "alt": "nothing displayed",
8690          "class": "p5",
8691          "module": "Structure",
8692          "submodule": "Structure"
8693        }, {
8694          "file": "src/core/main.js",
8695          "line": 90,
8696          "description": "<p>The <a href=\"#/p5/setup\">setup()</a> function is called once when the program starts. It&#39;s used to\ndefine initial environment properties such as screen size and background\ncolor and to load media such as images and fonts as the program starts.\nThere can only be one <a href=\"#/p5/setup\">setup()</a> function for each program and it shouldn&#39;t\nbe called again after its initial execution.\n<br><br>\nNote: Variables declared within <a href=\"#/p5/setup\">setup()</a> are not accessible within other\nfunctions, including <a href=\"#/p5/draw\">draw()</a>.</p>\n",
8697          "itemtype": "method",
8698          "name": "setup",
8699          "example": ["\n<div><code>\nlet a = 0;\n\nfunction setup() {\n  background(0);\n  noStroke();\n  fill(102);\n}\n\nfunction draw() {\n  rect(a++ % width, 10, 2, 80);\n}\n</code></div>"],
8700          "alt": "nothing displayed",
8701          "class": "p5",
8702          "module": "Structure",
8703          "submodule": "Structure"
8704        }, {
8705          "file": "src/core/main.js",
8706          "line": 121,
8707          "description": "<p>Called directly after <a href=\"#/p5/setup\">setup()</a>, the <a href=\"#/p5/draw\">draw()</a> function continuously executes\nthe lines of code contained inside its block until the program is stopped\nor <a href=\"#/p5/noLoop\">noLoop()</a> is called. Note if <a href=\"#/p5/noLoop\">noLoop()</a>
8707 is called in <a href=\"#/p5/setup\">setup()</a>, <a href=\"#/p5/draw\">draw()</a> will\nstill be executed once before stopping. <a href=\"#/p5/draw\">draw()</a> is called automatically and\nshould never be called explicitly.\n<br><br>\nIt should always be controlled with <a href=\"#/p5/noLoop\">noLoop()</a>, <a href=\"#/p5/redraw\">redraw()</a> and <a href=\"#/p5/loop\">loop()</a>. After\n<a href=\"#/p5/noLoop\">noLoop()</a> stops the code in <a href=\"#/p5/draw\">draw()</a> from executing, <a href=\"#/p5/redraw\">redraw()</a> causes the\ncode inside <a href=\"#/p5/draw\">draw()</a> to execute once, and <a href=\"#/p5/loop\">loop()</a> will cause the code\ninside <a href=\"#/p5/draw\">draw()</a> to resume executing continuously.\n<br><br>\nThe number of times <a href=\"#/p5/draw\">draw()</a> executes in each second may be controlled with\nthe <a href=\"#/p5/frameRate\">frameRate()</a> function.\n<br><br>\nThere can only be one <a href=\"#/p5/draw\">draw()</a> function for each sketch, and <a href=\"#/p5/draw\">draw()</a> must\nexist if you want the code to run continuously, or to process events such\nas <a href=\"#/p5/mousePressed\">mousePressed()</a>. Sometimes, you might have an empty call to <a href=\"#/p5/draw\">draw()</a> in\nyour program, as shown in the above example.\n<br><br>\nIt is important to note that the drawing coordinate system will be reset\nat the beginning of each <a href=\"#/p5/draw\">draw()</a> call. If any transformations are performed\nwithin <a href=\"#/p5/draw\">draw()</a> (ex: scale, rotate, translate), their effects will be\nundone at the beginning of <a href=\"#/p5/draw\">draw()</a>, so transformations will not accumulate\nover time. On the other hand, styling applied (ex: fill, stroke, etc) will\nremain in effect.</p>\n",
8708          "itemtype": "method",
8709          "name": "draw",
8710          "example": ["\n<div><code>\nlet yPos = 0;\nfunction setup() {\n  // setup() runs once\n  frameRate(30);\n}\nfunction draw() {\n  // draw() loops forever, until stopped\n  background(204);\n  yPos = yPos - 1;\n  if (yPos < 0) {\n    yPos = height;\n  }\n  line(0, yPos, width, yPos);\n}\n</code></div>"],
8711          "alt": "nothing displayed",
8712          "class": "p5",
8713          "module": "Structure",
8714          "submodule": "Structure"
8715        }, {
8716          "file": "src/core/main.js",
8717          "line": 400,
8718          "description": "<p>Removes the entire p5 sketch. This will remove the canvas and any\nelements created by p5.js. It will also stop the draw loop and unbind\nany properties or methods from the window global scope. It will\nleave a variable p5 in case you wanted to create a new p5 sketch.\nIf you like, you can set p5 = null to erase it. While all functions and\nvariables and objects created by the p5 library will be removed, any\nother global variables created by your code will remain.</p>\n",
8719          "itemtype": "method",
8720          "name": "remove",
8721          "example": ["\n<div class='norender'><code>\nfunction draw() {\n  ellipse(50, 50, 10, 10);\n}\n\nfunction mousePressed() {\n  remove(); // remove whole sketch on mouse press\n}\n</code></div>"],
8722          "alt": "nothing displayed",
8723          "class": "p5",
8724          "module": "Structure",
8725          "submodule": "Structure"
8726        }, {
8727          "file": "src/core/p5.Element.js",
8728          "line": 26,
8729          "description": "<p>Underlying HTML element. All normal HTML methods can be called on this.</p>\n",
8730          "example": ["\n<div>\n<code>\nfunction setup() {\n  var c = createCanvas(50, 50);\n  c.elt.style.border = '5px solid red';\n}\n\nfunction draw() {\n  background(220);\n}\n</code>\n</div>"],
8731          "itemtype": "property",
8732          "name": "elt",
8733          "readonly": "",
8734          "class": "p5.Element",
8735          "module": "DOM",
8736          "submodule": "DOM"
8737        }, {
8738          "file": "src/core/p5.Element.js",
8739          "line": 52,
8740          "description": "<p>Attaches the element to the parent specified. A way of setting\n the container for the element. Accepts either a string ID, DOM\n node, or <a href=\"#/p5.Element\">p5.Element</a>. If no arguments given, parent node is returned.\n For more ways to position the canvas, see the\n <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>\n positioning the canvas</a> wiki page.\nAll above examples except for the first one require the inclusion of\n the p5.dom library in your index.html. See the\n <a href='http://p5js.org/libraries/#using-a-library'>using a library</a>\n section for information on how to include this library.</p>\n",
8741          "itemtype": "method",
8742          "name": "parent",
8743          "chainable": 1,
8744          "example": ["\n <div class=\"norender notest\"><code>\n // in the html file:\n // &lt;div id=\"myContainer\">&lt;/div>\n// in the js file:\n var cnv = createCanvas(100, 100);\n cnv.parent('myContainer');\n </code></div>\n <div class='norender'><code>\n var div0 = createDiv('this is the parent');\n var div1 = createDiv('this is the child');\n div1.parent(div0); // use p5.Element\n </code></div>\n <div class='norender'><code>\n var div0 = createDiv('this is the parent');\n div0.id('apples');\n var div1 = createDiv('this is the child');\n div1.parent('apples'); // use id\n </code></div>\n <div class='norender notest'><code>\n var elt = document.getElementById('myParentDiv');\n var div1 = createDiv('this is the child');\n div1.parent(elt);
8744 // use element from page\n </code></div>"],
8745          "alt": "no display.",
8746          "class": "p5.Element",
8747          "module": "DOM",
8748          "submodule": "DOM",
8749          "overloads": [{
8750            "line": 52,
8751            "params": [{
8752              "name": "parent",
8753              "description": "<p>the ID, DOM node, or <a href=\"#/p5.Element\">p5.Element</a>\n                         of desired parent element</p>\n",
8754              "type": "String|p5.Element|Object"
8755            }],
8756            "chainable": 1
8757          }, {
8758            "line": 100,
8759            "params": [],
8760            "return": {
8761              "description": "",
8762              "type": "p5.Element"
8763            }
8764          }]
8765        }, {
8766          "file": "src/core/p5.Element.js",
8767          "line": 122,
8768          "description": "<p>Sets the ID of the element. If no ID argument is passed in, it instead\n returns the current ID of the element.</p>\n",
8769          "itemtype": "method",
8770          "name": "id",
8771          "chainable": 1,
8772          "example": ["\n <div class='norender'><code>\n function setup() {\n   var cnv = createCanvas(100, 100);\n   // Assigns a CSS selector ID to\n   // the canvas element.\n   cnv.id('mycanvas');\n }\n </code></div>"],
8773          "alt": "no display.",
8774          "class": "p5.Element",
8775          "module": "DOM",
8776          "submodule": "DOM",
8777          "overloads": [{
8778            "line": 122,
8779            "params": [{
8780              "name": "id",
8781              "description": "<p>ID of the element</p>\n",
8782              "type": "String"
8783            }],
8784            "chainable": 1
8785          }, {
8786            "line": 144,
8787            "params": [],
8788            "return": {
8789              "description": "the id of the element",
8790              "type": "String"
8791            }
8792          }]
8793        }, {
8794          "file": "src/core/p5.Element.js",
8795          "line": 159,
8796          "description": "<p>Adds given class to the element. If no class argument is passed in, it\n instead returns a string containing the current class(es) of the element.</p>\n",
8797          "itemtype": "method",
8798          "name": "class",
8799          "chainable": 1,
8800          "example": ["\n <div class='norender'><code>\n function setup() {\n   var cnv = createCanvas(100, 100);\n   // Assigns a CSS selector class 'small'\n   // to the canvas element.\n   cnv.class('small');\n }\n </code></div>"],
8801          "alt": "no display.",
8802          "class": "p5.Element",
8803          "module": "DOM",
8804          "submodule": "DOM",
8805          "overloads": [{
8806            "line": 159,
8807            "params": [{
8808              "name": "class",
8809              "description": "<p>class to add</p>\n",
8810              "type": "String"
8811            }],
8812            "chainable": 1
8813          }, {
8814            "line": 181,
8815            "params": [],
8816            "return": {
8817              "description": "the class of the element",
8818              "type": "String"
8819            }
8820          }]
8821        }, {
8822          "file": "src/core/p5.Element.js",
8823          "line": 194,
8824          "description": "<p>The .<a href=\"#/p5.Element/mousePressed\">mousePressed()</a> function is called once after every time a\nmouse button is pressed over the element.\nSome mobile browsers may also trigger this event on a touch screen,\nif the user performs a quick tap.\nThis can be used to attach element specific event listeners.</p>\n",
8825          "itemtype": "method",
8826          "name": "mousePressed",
8827          "params": [{
8828            "name": "fxn",
8829            "description": "<p>function to be fired when mouse is\n                               pressed over the element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
8830            "type": "Function|Boolean"
8831          }],
8832          "chainable": 1,
8833          "example": ["\n<div class='norender'><code>\nvar cnv;\nvar d;\nvar g;\nfunction setup() {\n  cnv = createCanvas(100, 100);\n  cnv.mousePressed(changeGray); // attach listener for\n  // canvas click only\n  d = 10;\n  g = 100;\n}\n\nfunction draw() {\n  background(g);\n  ellipse(width / 2, height / 2, d, d);\n}
8833\n\n// this function fires with any click anywhere\nfunction mousePressed() {\n  d = d + 10;\n}\n\n// this function fires only when cnv is clicked\nfunction changeGray() {\n  g = random(0, 255);\n}\n</code></div>"],
8834          "alt": "no display.",
8835          "class": "p5.Element",
8836          "module": "DOM",
8837          "submodule": "DOM"
8838        }, {
8839          "file": "src/core/p5.Element.js",
8840          "line": 255,
8841          "description": "<p>The .<a href=\"#/p5.Element/doubleClicked\">doubleClicked()</a> function is called once after every time a\nmouse button is pressed twice over the element. This can be used to\nattach element and action specific event listeners.</p>\n",
8842          "itemtype": "method",
8843          "name": "doubleClicked",
8844          "params": [{
8845            "name": "fxn",
8846            "description": "<p>function to be fired when mouse is\n                               double clicked over the element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
8847            "type": "Function|Boolean"
8848          }],
8849          "return": {
8850            "description": "",
8851            "type": "p5.Element"
8852          },
8853          "example": ["\n<div class='norender'><code>\nvar cnv;\nvar d;\nvar g;\nfunction setup() {\n  cnv = createCanvas(100, 100);\n  cnv.doubleClicked(changeGray); // attach listener for\n  // canvas double click only\n  d = 10;\n  g = 100;\n}\n\nfunction draw() {\n  background(g);\n  ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires with any double click anywhere\nfunction doubleClicked() {\n  d = d + 10;\n}\n\n// this function fires only when cnv is double clicked\nfunction changeGray() {\n  g = random(0, 255);\n}\n</code></div>"],
8854          "alt": "no display.",
8855          "class": "p5.Element",
8856          "module": "DOM",
8857          "submodule": "DOM"
8858        }, {
8859          "file": "src/core/p5.Element.js",
8860          "line": 304,
8861          "description": "<p>The .<a href=\"#/p5.Element/mouseWheel\">mouseWheel()</a> function is called once after every time a\nmouse wheel is scrolled over the element. This can be used to\nattach element specific event listeners.\n<br><br>\nThe function accepts a callback function as argument which will be executed\nwhen the <code>wheel</code> event is triggered on the element, the callback function is\npassed one argument <code>event</code>. The <code>event.deltaY</code> property returns negative\nvalues if the mouse wheel is rotated up or away from the user and positive\nin the other direction. The <code>event.deltaX</code> does the same as <code>event.deltaY</code>\nexcept it reads the horizontal wheel scroll of the mouse wheel.\n<br><br>\nOn OS X with &quot;natural&quot; scrolling enabled, the <code>event.deltaY</code> values are\nreversed.</p>\n",
8862          "itemtype": "method",
8863          "name": "mouseWheel",
8864          "params": [{
8865            "name": "fxn",
8866            "description": "<p>function to be fired when mouse is\n                               scrolled over the element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
8867            "type": "Function|Boolean"
8868          }],
8869          "chainable": 1,
8870          "example": ["\n<div class='norender'><code>\nvar cnv;\nvar d;\nvar g;\nfunction setup() {\n  cnv = createCanvas(100, 100);\n  cnv.mouseWheel(changeSize); // attach listener for\n  // activity on canvas only\n  d = 10;\n  g = 100;\n}\n\nfunction draw() {\n  background(g);\n  ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires with mousewheel movement\n// anywhere on screen\nfunction mouseWheel() {\n  g = g + 10;\n}\n\n// this function fires with mousewheel movement\n// over canvas only\nfunction changeSize(event) {\n  if (event.deltaY > 0) {\n    d = d + 10;\n  } else {\n    d = d - 10;\n  }\n}\n</code></div>"],
8871          "alt": "no display.",
8872          "class": "p5.Element",
8873          "module": "DOM",
8874          "submodule": "DOM"
8875        }, {
8876          "file": "src/core/p5.Element.js",
8877          "line": 370,
8878          "description": "<p>The .<a href=\"#/p5.Element/mouseReleased\">mouseReleased()</a> function is called once after every time a\nmouse button is released over the element.\nSome mobile browsers may also trigger this event on a touch screen,\nif the user performs a quick tap.\nThis can be used to attach element specific event listeners.</p>\n",
8879          "itemtype": "method",
8880          "name": "mouseReleased",
8881          "params": [{
8882            "name": "fxn",
8883            "description": "<p>function to be fired when mouse is\n                               released over the element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
8884            "type": "Function|Boolean"
8885          }],
8886          "chainable": 1,
8887          "example": ["\n<div class='norender'><code>\nvar cnv;\nvar d;\nvar g;\nfunction setup() {\n  cnv = createCanvas(100, 100);\n  cnv.mouseReleased(changeGray); // attach listener for\n  // activity on canvas only\n  d = 10;\n  g = 100;\n}\n\nfunction draw() {\n  background(g);\n  ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires after the mouse has been\n// released\nfunction mouseReleased() {\n  d = d + 10;\n}\n\n// this function fires after the mouse has been\n// released while on canvas\nfunction changeGray() {\n  g = random(0, 255);\n}\n</code></div>"],
8888          "alt": "no display.",
8889          "class": "p5.Element",
8890          "module": "DOM",
8891          "submodule": "DOM"
8892        }, {
8893          "file": "src/core/p5.Element.js",
8894          "line": 424,
8895          "description": "<p>The .<a href=\"#/p5.Element/mouseClicked\">mouseClicked()</a> function is called once after a mouse button is\npressed and released over the element.\nSome mobile browsers may also trigger this event on a touch screen,\nif the user performs a quick tap.\nThis can be used to attach element specific event listeners.</p>\n",
8896          "itemtype": "method",
8897          "name": "mouseClicked",
8898          "params": [{
8899            "name": "fxn",
8900            "description": "<p>function to be fired when mouse is\n                               clicked over the element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
8901            "type": "Function|Boolean"
8902          }],
8903          "chainable": 1,
8904          "example": ["\n<div class=\"norender\">\n<code>\nvar cnv;\nvar d;\nvar g;\n\nfunction setup() {\n  cnv = createCanvas(100, 100);\n  cnv.mouseClicked(changeGray); // attach listener for\n  // activity on canvas only\n  d = 10;\n  g = 100;\n}\n\nfunction draw() {\n  background(g);\n  ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires after the mouse has been\n// clicked anywhere\nfunction mouseClicked() {\n  d = d + 10;\n}\n\n// this function fires after the mouse has been\n// clicked on canvas\nfunction changeGray() {\n  g = random(0, 255);\n}\n</code>\n</div>"],
8905          "alt": "no display.",
8906          "class": "p5.Element",
8907          "module": "DOM",
8908          "submodule": "DOM"
8909        }, {
8910          "file": "src/core/p5.Element.js",
8911          "line": 480,
8912          "description": "<p>The .<a href=\"#/p5.Element/mouseMoved\">mouseMoved()</a> function is called once every time a\nmouse moves over the element. This can be used to attach an\nelement specific event listener.</p>\n",
8913          "itemtype": "method",
8914          "name": "mouseMoved",
8915          "params": [{
8916            "name": "fxn",
8917            "description": "<p>function to be fired when a mouse moves\n                               over the element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
8918            "type": "Function|Boolean"
8919          }],
8920          "chainable": 1,
8921          "example": ["\n<div class='norender'><code>\nvar cnv;\nvar d = 30;\nvar g;\nfunction setup() {\n  cnv = createCanvas(100, 100);\n  cnv.mouseMoved(changeSize); // attach listener for\n  // activity on canvas only\n  d = 10;\n  g = 100;\n}\n\nfunction draw() {\n  background(g);\n  fill(200);\n  ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires when mouse moves anywhere on\n// page\nfunction mouseMoved() {\n  g = g + 5;\n  if (g > 255) {\n    g = 0;\n  }\n}\n\n// this function fires when mouse moves over canvas\nfunction changeSize() {\n  d = d + 2;\n  if (d > 100) {\n    d = 0;\n  }\n}\n</code></div>"],
8922          "alt": "no display.",
8923          "class": "p5.Element",
8924          "module": "DOM",
8925          "submodule": "DOM"
8926        }, {
8927          "file": "src/core/p5.Element.js",
8928          "line": 538,
8929          "description": "<p>The .<a href=\"#/p5.Element/mouseOver\">mouseOver()</a> function is called once after every time a\nmouse moves onto the element. This can be used to attach an\nelement specific event listener.</p>\n",
8930          "itemtype": "method",
8931          "name": "mouseOver",
8932          "params": [{
8933            "name": "fxn",
8934            "description": "<p>function to be fired when a mouse moves\n                               onto the element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
8935            "type": "Function|Boolean"
8936          }],
8937          "chainable": 1,
8938          "example": ["\n<div class='norender'><code>\nvar cnv;\nvar d;\nfunction setup() {\n  cnv = createCanvas(100, 100);\n  cnv.mouseOver(changeGray);\n  d = 10;\n}\n\nfunction draw() {\n  ellipse(width / 2, height / 2, d, d);\n}\n\nfunction changeGray() {\n  d = d + 10;\n  if (d > 100) {\n    d = 0;\n  }\n}\n</code></div>"],
8939          "alt": "no display.",
8940          "class": "p5.Element",
8941          "module": "DOM",
8942          "submodule": "DOM"
8943        }, {
8944          "file": "src/core/p5.Element.js",
8945          "line": 581,
8946          "description": "<p>The .<a href=\"#/p5.Element/mouseOut\">mouseOut()</a> function is called once after every time a\nmouse moves off the element. This can be used to attach an\nelement specific event listener.</p>\n",
8947          "itemtype": "method",
8948          "name": "mouseOut",
8949          "params": [{
8950            "name": "fxn",
8951            "description": "<p>function to be fired when a mouse\n                               moves off of an element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
8952            "type": "Function|Boolean"
8953          }],
8954          "chainable": 1,
8955          "example": ["\n<div class='norender'><code>\nvar cnv;\nvar d;\nfunction setup() {\n  cnv = createCanvas(100, 100);\n  cnv.mouseOut(changeGray);\n  d = 10;\n}\n\nfunction draw() {\n  ellipse(width / 2, height / 2, d, d);\n}\n\nfunction changeGray() {\n  d = d + 10;\n  if (d > 100) {\n    d = 0;\n  }\n}\n</code></div>"],
8956          "alt": "no display.",
8957          "class": "p5.Element",
8958          "module": "DOM",
8959          "submodule": "DOM"
8960        }, {
8961          "file": "src/core/p5.Element.js",
8962          "line": 623,
8963          "description": "<p>The .<a href=\"#/p5.Element/touchStarted\">touchStarted()</a> function is called once after every time a touch is\nregistered. This can be used to attach element specific event listeners.</p>\n",
8964          "itemtype": "method",
8965          "name": "touchStarted",
8966          "params": [{
8967            "name": "fxn",
8968            "description": "<p>function to be fired when a touch\n                               starts over the element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
8969            "type": "Function|Boolean"
8970          }],
8971          "chainable": 1,
8972          "example": ["\n<div class='norender'><code>\nvar cnv;\nvar d;\nvar g;\nfunction setup() {\n  cnv = createCanvas(100, 100);\n  cnv.touchStarted(changeGray); // attach listener for\n  // canvas click only\n  d = 10;\n  g = 100;\n}\n\nfunction draw() {\n  background(g);\n  ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires with any touch anywhere\nfunction touchStarted() {\n  d = d + 10;\n}\n\n// this function fires only when cnv is clicked\nfunction changeGray() {\n  g = random(0, 255);\n}\n</code></div>"],
8973          "alt": "no display.",
8974          "class": "p5.Element",
8975          "module": "DOM",
8976          "submodule": "DOM"
8977        }, {
8978          "file": "src/core/p5.Element.js",
8979          "line": 671,
8980          "description": "<p>The .<a href=\"#/p5.Element/touchMoved\">touchMoved()</a> function is called once after every time a touch move is\nregistered. This can be used to attach element specific event listeners.</p>\n",
8981          "itemtype": "method",
8982          "name": "touchMoved",
8983          "params": [{
8984            "name": "fxn",
8985            "description": "<p>function to be fired when a touch moves over\n                               the element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
8986            "type": "Function|Boolean"
8987          }],
8988          "chainable": 1,
8989          "example": ["\n<div class='norender'><code>\nvar cnv;\nvar g;\nfunction setup() {\n  cnv = createCanvas(100, 100);\n  cnv.touchMoved(changeGray); // attach listener for\n  // canvas click only\n  g = 100;\n}\n\nfunction draw() {\n  background(g);\n}\n\n// this function fires only when cnv is clicked\nfunction changeGray() {\n  g = random(0, 255);\n}\n</code></div>"],
8990          "alt": "no display.",
8991          "class": "p5.Element",
8992          "module": "DOM",
8993          "submodule": "DOM"
8994        }, {
8995          "file": "src/core/p5.Element.js",
8996          "line": 711,
8997          "description": "<p>The .<a href=\"#/p5.Element/touchEnded\">touchEnded()</a> function is called once after every time a touch is\nregistered. This can be used to attach element specific event listeners.</p>\n",
8998          "itemtype": "method",
8999          "name": "touchEnded",
9000          "params": [{
9001            "name": "fxn",
9002            "description": "<p>function to be fired when a touch ends\n                               over the element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
9003            "type": "Function|Boolean"
9004          }],
9005          "chainable": 1,
9006          "example": ["\n<div class='norender'><code>\nvar cnv;\nvar d;\nvar g;\nfunction setup() {\n  cnv = createCanvas(100, 100);\n  cnv.touchEnded(changeGray); // attach listener for\n  // canvas click only\n  d = 10;\n  g = 100;\n}\n\nfunction draw() {\n  background(g);\n  ellipse(width / 2, height / 2, d, d);\n}\n\n// this function fires with any touch anywhere\nfunction touchEnded() {\n  d = d + 10;\n}\n\n// this function fires only when cnv is clicked\nfunction changeGray() {\n  g = random(0, 255);\n}\n</code></div>"],
9007          "alt": "no display.",
9008          "class": "p5.Element",
9009          "module": "DOM",
9010          "submodule": "DOM"
9011        }, {
9012          "file": "src/core/p5.Element.js",
9013          "line": 760,
9014          "description": "<p>The .<a href=\"#/p5.Element/dragOver\">dragOver()</a> function is called once after every time a\nfile is dragged over the element. This can be used to attach an\nelement specific event listener.</p>\n",
9015          "itemtype": "method",
9016          "name": "dragOver",
9017          "params": [{
9018            "name": "fxn",
9019            "description": "<p>function to be fired when a file is\n                               dragged over the element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
9020            "type": "Function|Boolean"
9021          }],
9022          "chainable": 1,
9023          "example": ["\n<div><code>\n// To test this sketch, simply drag a\n// file over the canvas\nfunction setup() {\n  var c = createCanvas(100, 100);\n  background(200);\n  textAlign(CENTER);\n  text('Drag file', width / 2, height / 2);\n  c.dragOver(dragOverCallback);\n}\n\n// This function will be called whenever\n// a file is dragged over the canvas\nfunction dragOverCallback() {\n  background(240);\n  text('Dragged over', width / 2, height / 2);\n}\n</code></div>"],
9024          "alt": "nothing displayed",
9025          "class": "p5.Element",
9026          "module": "DOM",
9027          "submodule": "DOM"
9028        }, {
9029          "file": "src/core/p5.Element.js",
9030          "line": 798,
9031          "description": "<p>The .dragLeave() function is called once after every time a\ndragged file leaves the element area. This can be used to attach an\nelement specific event listener.</p>\n",
9032          "itemtype": "method",
9033          "name": "dragLeave",
9034          "params": [{
9035            "name": "fxn",
9036            "description": "<p>function to be fired when a file is\n                               dragged off the element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
9037            "type": "Function|Boolean"
9038          }],
9039          "chainable": 1,
9040          "example": ["\n<div><code>\n// To test this sketch, simply drag a file\n// over and then out of the canvas area\nfunction setup() {\n  var c = createCanvas(100, 100);\n  background(200);\n  textAlign(CENTER);\n  text('Drag file', width / 2, height / 2);\n  c.dragLeave(dragLeaveCallback);\n}\n\n// This function will be called whenever\n// a file is dragged out of the canvas\nfunction dragLeaveCallback() {\n  background(240);\n  text('Dragged off', width / 2, height / 2);\n}\n</code></div>"],
9041          "alt": "nothing displayed",
9042          "class": "p5.Element",
9043          "module": "DOM",
9044          "submodule": "DOM"
9045        }, {
9046          "file": "src/core/p5.Element.js",
9047          "line": 836,
9048          "description": "<p>Registers a callback that gets called every time a file that is\ndropped on the element has been loaded.\np5 will load every dropped file into memory and pass it as a p5.File object to the callback.\nMultiple files dropped at the same time will result in multiple calls to the callback.</p>\n<p>You can optionally pass a second callback which will be registered to the raw\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/Events/drop\">drop</a> event.\nThe callback will thus be provided the original\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/DragEvent\">DragEvent</a>.\nDropping multiple files at the same time will trigger the second callback once per drop,\nwhereas the first callback will trigger for each loaded file.</p>\n",
9049          "itemtype": "method",
9050          "name": "drop",
9051          "params": [{
9052            "name": "callback",
9053            "description": "<p>callback to receive loaded file.</p>\n",
9054            "type": "Function"
9055          }, {
9056            "name": "fxn",
9057            "description": "<p>callback triggered when files are dropped.</p>\n",
9058            "type": "Function",
9059            "optional": true
9060          }],
9061          "chainable": 1,
9062          "example": ["\n<div><code>\nfunction setup() {\n  var c = createCanvas(100, 100);\n  background(200);\n  textAlign(CENTER);\n  text('drop file', width / 2, height / 2);\n  c.drop(gotFile);\n}\n\nfunction gotFile(file) {\n  background(200);\n  text('received file:', width / 2, height / 2);\n  text(file.name, width / 2, height / 2 + 50);\n}\n</code></div>\n\n<div><code>\nvar img;\n\nfunction setup() {\n  var c = createCanvas(100, 100);\n  background(200);\n  textAlign(CENTER);\n  text('drop image', width / 2, height / 2);\n  c.drop(gotFile);\n}\n\nfunction draw() {\n  if (img) {\n    image(img, 0, 0, width, height);\n  }\n}\n\nfunction gotFile(file) {\n  img = createImg(file.data).hide();\n}\n</code></div>"],
9063          "alt": "Canvas turns into whatever image is dragged/dropped onto it.",
9064          "class": "p5.Element",
9065          "module": "DOM",
9066          "submodule": "DOM"
9067        }, {
9068          "file": "src/core/p5.Element.js",
9069          "line": 969,
9070          "description": "<p>Helper fxn for sharing pixel methods</p>\n",
9071          "class": "p5.Element",
9072          "module": "DOM",
9073          "submodule": "DOM"
9074        }, {
9075          "file": "src/core/p5.Graphics.js",
9076          "line": 65,
9077          "description": "<p>Removes a Graphics object from the page and frees any resources\nassociated with it.</p>\n",
9078          "itemtype": "method",
9079          "name": "remove",
9080          "example": ["\n<div class='norender'><code>\nlet bg;\nfunction setup() {\n  bg = createCanvas(100, 100);\n  bg.background(0);\n  image(bg, 0, 0);\n  bg.remove();\n}\n</code></div>\n\n<div><code>\nlet bg;\nfunction setup() {\n  pixelDensity(1);\n  createCanvas(100, 100);
9080\n  stroke(255);\n  fill(0);\n\n  // create and draw the background image\n  bg = createGraphics(100, 100);\n  bg.background(200);\n  bg.ellipse(50, 50, 80, 80);\n}\nfunction draw() {\n  let t = millis() / 1000;\n  // draw the background\n  if (bg) {\n    image(bg, frameCount % 100, 0);\n    image(bg, frameCount % 100 - 100, 0);\n  }\n  // draw the foreground\n  let p = p5.Vector.fromAngle(t, 35).add(50, 50);\n  ellipse(p.x, p.y, 30);\n}\nfunction mouseClicked() {\n  // remove the background\n  if (bg) {\n    bg.remove();\n    bg = null;\n  }\n}\n</code></div>"],
9081          "alt": "no image\na multi-colored circle moving back and forth over a scrolling background.",
9082          "class": "p5.Graphics",
9083          "module": "Rendering",
9084          "submodule": "Rendering"
9085        }, {
9086          "file": "src/core/p5.Renderer.js",
9087          "line": 96,
9088          "description": "<p>Resize our canvas element.</p>\n",
9089          "class": "p5.Renderer",
9090          "module": "Rendering",
9091          "submodule": "Rendering"
9092        }, {
9093          "file": "src/core/p5.Renderer.js",
9094          "line": 301,
9095          "description": "<p>Helper fxn to check font type (system or otf)</p>\n",
9096          "class": "p5.Renderer",
9097          "module": "Rendering",
9098          "submodule": "Rendering"
9099        }, {
9100          "file": "src/core/p5.Renderer.js",
9101          "line": 354,
9102          "description": "<p>Helper fxn to measure ascent and descent.\nAdapted from <a href=\"http://stackoverflow.com/a/25355178\">http://stackoverflow.com/a/25355178</a></p>\n",
9103          "class": "p5.Renderer",
9104          "module": "Rendering",
9105          "submodule": "Rendering"
9106        }, {
9107          "file": "src/core/p5.Renderer2D.js",
9108          "line": 9,
9109          "description": "<p>p5.Renderer2D\nThe 2D graphics canvas renderer class.\nextends p5.Renderer</p>\n",
9110          "class": "p5",
9111          "module": "Rendering"
9112        }, {
9113          "file": "src/core/p5.Renderer2D.js",
9114          "line": 392,
9115          "description": "<p>Generate a cubic Bezier representing an arc on the unit circle of total\nangle <code>size</code> radians, beginning <code>start</code> radians above the x-axis. Up to\nfour of these curves are combined to make a full arc.</p>\n<p>See www.joecridge.me/bezier.pdf for an explanation of the method.</p>\n",
9116          "class": "p5",
9117          "module": "Rendering"
9118        }, {
9119          "file": "src/core/rendering.js",
9120          "line": 17,
9121          "description": "<p>Creates a canvas element in the document, and sets the dimensions of it\nin pixels. This method should be called only once at the start of setup.\nCalling <a href=\"#/p5/createCanvas\">createCanvas</a> more than once in a sketch will result in very\nunpredictable behavior. If you want more than one drawing canvas\nyou could use <a href=\"#/p5/createGraphics\">createGraphics</a> (hidden by default but it can be shown).\n<br><br>\nThe system variables width and height are set by the parameters passed\nto this function. If <a href=\"#/p5/createCanvas\">createCanvas()</a> is not used, the window will be\ngiven a default size of 100x100 pixels.\n<br><br>\nFor more ways to position the canvas, see the\n<a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>\npositioning the canvas</a> wiki page.</p>\n",
9122          "itemtype": "method",
9123          "name": "createCanvas",
9124          "params": [{
9125            "name": "w",
9126            "description": "<p>width of the canvas</p>\n",
9127            "type": "Number"
9128          }, {
9129            "name": "h",
9130            "description": "<p>height of the canvas</p>\n",
9131            "type": "Number"
9132          }, {
9133            "name": "renderer",
9134            "description": "<p>either P2D or WEBGL</p>\n",
9135            "type": "Constant",
9136            "optional": true
9137          }],
9138          "return": {
9139            "description": "",
9140            "type": "p5.Renderer"
9141          },
9142          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 50);\n  background(153);\n  line(0, 0, width, height);\n}\n</code>\n</div>"],
9143          "alt": "Black line extending from top-left of canvas to bottom right.",
9144          "class": "p5",
9145          "module": "Rendering",
9146          "submodule": "Rendering"
9147        }, {
9148          "file": "src/core/rendering.js",
9149          "line": 119,
9150          "description": "<p>Resizes the canvas to given width and height. The canvas will be cleared\nand draw will be called immediately, allowing the sketch to re-render itself\nin the resized canvas.</p>\n",
9151          "itemtype": "method",
9152          "name": "resizeCanvas",
9153          "params": [{
9154            "name": "w",
9155            "description": "<p>width of the canvas</p>\n",
9156            "type": "Number"
9157          }, {
9158            "name": "h",
9159            "description": "<p>height of the canvas</p>\n",
9160            "type": "Number"
9161          }, {
9162            "name": "noRedraw",
9163            "description": "<p>don&#39;t redraw the canvas immediately</p>\n",
9164            "type": "Boolean",
9165            "optional": true
9166          }],
9167          "example": ["\n<div class=\"norender\"><code>\nfunction setup() {\n  createCanvas(windowWidth, windowHeight);\n}\n\nfunction draw() {\n  background(0, 100, 200);\n}\n\nfunction windowResized() {\n  resizeCanvas(windowWidth, windowHeight);\n}\n</code></div>"],
9168          "alt": "No image displayed.",
9169          "class": "p5",
9170          "module": "Rendering",
9171          "submodule": "Rendering"
9172        }, {
9173          "file": "src/core/rendering.js",
9174          "line": 174,
9175          "description": "<p>Removes the default canvas for a p5 sketch that doesn&#39;t\nrequire a canvas</p>\n",
9176          "itemtype": "method",
9177          "name": "noCanvas",
9178          "example": ["\n<div>\n<code>\nfunction setup() {\n  noCanvas();\n}\n</code>\n</div>"],
9179          "alt": "no image displayed",
9180          "class": "p5",
9181          "module": "Rendering",
9182          "submodule": "Rendering"
9183        }, {
9184          "file": "src/core/rendering.js",
9185          "line": 197,
9186          "description": "<p>Creates and returns a new p5.Renderer object. Use this class if you need\nto draw into an off-screen graphics buffer. The two parameters define the\nwidth and height in pixels.</p>\n",
9187          "itemtype": "method",
9188          "name": "createGraphics",
9189          "params": [{
9190            "name": "w",
9191            "description": "<p>width of the offscreen graphics buffer</p>\n",
9192            "type": "Number"
9193          }, {
9194            "name": "h",
9195            "description": "<p>height of the offscreen graphics buffer</p>\n",
9196            "type": "Number"
9197          }, {
9198            "name": "renderer",
9199            "description": "<p>either P2D or WEBGL\nundefined defaults to p2d</p>\n",
9200            "type": "Constant",
9201            "optional": true
9202          }],
9203          "return": {
9204            "description": "offscreen graphics buffer",
9205            "type": "p5.Graphics"
9206          },
9207          "example": ["\n<div>\n<code>\nlet pg;\nfunction setup() {\n  createCanvas(100, 100);\n  pg = createGraphics(100, 100);\n}\nfunction draw() {\n  background(200);\n  pg.background(100);\n  pg.noStroke();\n  pg.ellipse(pg.width / 2, pg.height / 2, 50, 50);\n  image(pg, 50, 50);\n  image(pg, 0, 0, 50, 50);\n}\n</code>\n</div>"],
9208          "alt": "4 grey squares alternating light and dark grey. White quarter circle mid-left.",
9209          "class": "p5",
9210          "module": "Rendering",
9211          "submodule": "Rendering"
9212        }, {
9213          "file": "src/core/rendering.js",
9214          "line": 236,
9215          "description": "<p>Blends the pixels in the display window according to the defined mode.\nThere is a choice of the following modes to blend the source pixels (A)\nwith the ones of pixels already in the display window (B):</p>\n<ul>\n<li><code>BLEND</code> - linear interpolation of colours: C =\nA*factor + B. This is the default blending mode.</li>\n<li><code>ADD</code> - sum of A and B</li>\n<li><code>DARKEST</code> - only the darkest colour succeeds: C =\nmin(A*factor, B).</li>\n<li><code>LIGHTEST</code> - only the lightest colour succeeds: C =\nmax(A*factor, B).</li>\n<li><code>DIFFERENCE</code> - subtract colors from underlying image.</li>\n<li><code>EXCLUSION</code> - similar to <code>DIFFERENCE</code>, but less\nextreme.</li>\n<li><code>MULTIPLY</code> - multiply the colors, result will always be\ndarker.</li>\n<li><code>SCREEN</code> - opposite multiply, uses inverse values of the\ncolors.</li>\n<li><code>REPLACE</code> - the pixels entirely replace the others and\ndon&#39;
9215t utilize alpha (transparency) values.</li>\n<li><code>OVERLAY</code> - mix of <code>MULTIPLY</code> and <code>SCREEN\n</code>. Multiplies dark values, and screens light values.</li>\n<li><code>HARD_LIGHT</code> - <code>SCREEN</code> when greater than 50%\ngray, <code>MULTIPLY</code> when lower.</li>\n<li><code>SOFT_LIGHT</code> - mix of <code>DARKEST</code> and\n<code>LIGHTEST</code>. Works like <code>OVERLAY</code>, but not as harsh.\n</li>\n<li><code>DODGE</code> - lightens light tones and increases contrast,\nignores darks.</li>\n<li><code>BURN</code> - darker areas are applied, increasing contrast,\nignores lights.</li>\n</ul>",
9216          "itemtype": "method",
9217          "name": "blendMode",
9218          "params": [{
9219            "name": "mode",
9220            "description": "<p>blend mode to set for canvas.\n               either BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY,\n               EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,\n               SOFT_LIGHT, DODGE, BURN, ADD or NORMAL</p>\n",
9221            "type": "Constant"
9222          }],
9223          "example": ["\n<div>\n<code>\nblendMode(LIGHTEST);\nstrokeWeight(30);\nstroke(80, 150, 255);\nline(25, 25, 75, 75);\nstroke(255, 50, 50);\nline(75, 25, 25, 75);\n</code>\n</div>\n<div>\n<code>\nblendMode(MULTIPLY);\nstrokeWeight(30);\nstroke(80, 150, 255);\nline(25, 25, 75, 75);\nstroke(255, 50, 50);\nline(75, 25, 25, 75);\n</code>\n</div>"],
9224          "alt": "translucent image thick red & blue diagonal rounded lines intersecting center\nThick red & blue diagonal rounded lines intersecting center. dark at overlap",
9225          "class": "p5",
9226          "module": "Rendering",
9227          "submodule": "Rendering"
9228        }, {
9229          "file": "src/core/shim.js",
9230          "line": 23,
9231          "description": "<p>shim for Uint8ClampedArray.slice\n(allows arrayCopy to work with pixels[])\nwith thanks to <a href=\"http://halfpapstudios.com/blog/tag/html5-canvas/\">http://halfpapstudios.com/blog/tag/html5-canvas/</a>\nEnumerable set to false to protect for...in from\nUint8ClampedArray.prototype pollution.</p>\n",
9232          "class": "p5",
9233          "module": "Rendering"
9234        }, {
9235          "file": "src/core/shim.js",
9236          "line": 45,
9237          "description": "<p>this is implementation of Object.assign() which is unavailable in\nIE11 and (non-Chrome) Android browsers.\nThe assign() method is used to copy the values of all enumerable\nown properties from one or more source objects to a target object.\nIt will return the target object.\nModified from <a href=\"https://github.com/ljharb/object.assign\">https://github.com/ljharb/object.assign</a></p>\n",
9238          "class": "p5",
9239          "module": "Rendering"
9240        }, {
9241          "file": "src/core/structure.js",
9242          "line": 12,
9243          "description": "<p>Stops p5.js from continuously executing the code within <a href=\"#/p5/draw\">draw()</a>.\nIf <a href=\"#/p5/loop\">loop()</a> is called, the code in <a href=\"#/p5/draw\">draw()</a>
9243 begins to run continuously again.\nIf using <a href=\"#/p5/noLoop\">noLoop()</a> in <a href=\"#/p5/setup\">setup()</a>, it should be the last line inside the block.\n<br><br>\nWhen <a href=\"#/p5/noLoop\">noLoop()</a> is used, it&#39;s not possible to manipulate or access the\nscreen inside event handling functions such as <a href=\"#/p5/mousePressed\">mousePressed()</a> or\n<a href=\"#/p5/keyPressed\">keyPressed()</a>. Instead, use those functions to call <a href=\"#/p5/redraw\">redraw()</a> or <a href=\"#/p5/loop\">loop()</a>,\nwhich will run <a href=\"#/p5/draw\">draw()</a>, which can update the screen properly. This means\nthat when <a href=\"#/p5/noLoop\">noLoop()</a> has been called, no drawing can happen, and functions\nlike <a href=\"#/p5/saveFrame\">saveFrame()</a> or <a href=\"#/p5/loadPixels\">loadPixels()</a> may not be used.\n<br><br>\nNote that if the sketch is resized, <a href=\"#/p5/redraw\">redraw()</a> will be called to update\nthe sketch, even after <a href=\"#/p5/noLoop\">noLoop()</a> has been specified. Otherwise, the sketch\nwould enter an odd state until <a href=\"#/p5/loop\">loop()</a> was called.</p>\n",
9244          "itemtype": "method",
9245          "name": "noLoop",
9246          "example": ["\n<div><code>\nfunction setup() {\n  createCanvas(100, 100);\n  background(200);\n  noLoop();\n}\n\nfunction draw() {\n  line(10, 10, 90, 90);\n}\n</code></div>\n\n<div><code>\nlet x = 0;\nfunction setup() {\n  createCanvas(100, 100);\n}\n\nfunction draw() {\n  background(204);\n  x = x + 0.1;\n  if (x > width) {\n    x = 0;\n  }\n  line(x, 0, x, height);\n}\n\nfunction mousePressed() {\n  noLoop();\n}\n\nfunction mouseReleased() {\n  loop();\n}\n</code></div>"],
9247          "alt": "113 pixel long line extending from top-left to bottom right of canvas.\nhorizontal line moves slowly from left. Loops but stops on mouse press.",
9248          "class": "p5",
9249          "module": "Structure",
9250          "submodule": "Structure"
9251        }, {
9252          "file": "src/core/structure.js",
9253          "line": 74,
9254          "description": "<p>By default, p5.js loops through draw() continuously, executing the code\nwithin it. However, the <a href=\"#/p5/draw\">draw()</a> loop may be stopped by calling <a href=\"#/p5/noLoop\">noLoop()</a>.\nIn that case, the <a href=\"#/p5/draw\">draw()</a> loop can be resumed with loop().</p>\n",
9255          "itemtype": "method",
9256          "name": "loop",
9257          "example": ["\n<div><code>\nlet x = 0;\nfunction setup() {\n  createCanvas(100, 100);\n  noLoop();\n}\n\nfunction draw() {\n  background(204);\n  x = x + 0.1;\n  if (x > width) {\n    x = 0;\n  }\n  line(x, 0, x, height);\n}\n\nfunction mousePressed() {\n  loop();\n}\n\nfunction mouseReleased() {\n  noLoop();\n}\n</code></div>"],
9258          "alt": "horizontal line moves slowly from left. Loops but stops on mouse press.",
9259          "class": "p5",
9260          "module": "Structure",
9261          "submodule": "Structure"
9262        }, {
9263          "file": "src/core/structure.js",
9264          "line": 116,
9265          "description": "<p>The <a href=\"#/p5/push\">push()</a> function saves the current drawing style settings and\ntransformations, while <a href=\"#/p5/pop\">pop()</a> restores these settings. Note that these\nfunctions are always used together. They allow you to change the style\nand transformation settings and later return to what you had. When a new\nstate is started with <a href=\"#/p5/push\">push()</a>, it builds on the current style and transform\ninformation. The <a href=\"#/p5/push\">push()</a> and <a href=\"#/p5/pop\">pop()</a> functions can be embedded to provide\nmore control. (See the second example for a demonstration.)\n<br><br>\n<a href=\"#/p5/push\">push()</a> stores information related to the current transformation state\nand style settings controlled by the following functions: <a href=\"#/p5/fill\">fill()</a>,\n<a href=\"#/p5/stroke\">stroke()</a>, <a href=\"#/p5/tint\">tint()</a>, <a href=\"#/p5/strokeWeight\">
9265strokeWeight()</a>, <a href=\"#/p5/strokeCap\">strokeCap()</a>, <a href=\"#/p5/strokeJoin\">strokeJoin()</a>,\n<a href=\"#/p5/imageMode\">imageMode()</a>, <a href=\"#/p5/rectMode\">rectMode()</a>, <a href=\"#/p5/ellipseMode\">ellipseMode()</a>, <a href=\"#/p5/colorMode\">colorMode()</a>, <a href=\"#/p5/textAlign\">textAlign()</a>,\n<a href=\"#/p5/textFont\">textFont()</a>, <a href=\"#/p5/textMode\">textMode()</a>, <a href=\"#/p5/textSize\">textSize()</a>, <a href=\"#/p5/textLeading\">textLeading()</a>.</p>\n",
9266          "itemtype": "method",
9267          "name": "push",
9268          "example": ["\n<div>\n<code>\nellipse(0, 50, 33, 33); // Left circle\n\npush(); // Start a new drawing state\nstrokeWeight(10);\nfill(204, 153, 0);\ntranslate(50, 0);\nellipse(0, 50, 33, 33); // Middle circle\npop(); // Restore original state\n\nellipse(100, 50, 33, 33); // Right circle\n</code>\n</div>\n<div>\n<code>\nellipse(0, 50, 33, 33); // Left circle\n\npush(); // Start a new drawing state\nstrokeWeight(10);\nfill(204, 153, 0);\nellipse(33, 50, 33, 33); // Left-middle circle\n\npush(); // Start another new drawing state\nstroke(0, 102, 153);\nellipse(66, 50, 33, 33); // Right-middle circle\npop(); // Restore previous state\n\npop(); // Restore original state\n\nellipse(100, 50, 33, 33); // Right circle\n</code>\n</div>"],
9269          "alt": "Gold ellipse + thick black outline @center 2 white ellipses on left and right.\n2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right.",
9270          "class": "p5",
9271          "module": "Structure",
9272          "submodule": "Structure"
9273        }, {
9274          "file": "src/core/structure.js",
9275          "line": 181,
9276          "description": "<p>The <a href=\"#/p5/push\">push()</a> function saves the current drawing style settings and\ntransformations, while <a href=\"#/p5/pop\">pop()</a> restores these settings. Note that these\nfunctions are always used together. They allow you to change the style\nand transformation settings and later return to what you had. When a new\nstate is started with <a href=\"#/p5/push\">push()</a>, it builds on the current style and transform\ninformation. The <a href=\"#/p5/push\">push()</a> and <a href=\"#/p5/pop\">pop()</a> functions can be embedded to provide\nmore control. (See the second example for a demonstration.)\n<br><br>\n<a href=\"#/p5/push\">push()</a> stores information related to the current transformation state\nand style settings controlled by the following functions: <a href=\"#/p5/fill\">fill()</a>,\n<a href=\"#/p5/stroke\">stroke()</a>, <a href=\"#/p5/tint\">tint()</a>, <a href=\"#/p5/strokeWeight\">
9276strokeWeight()</a>, <a href=\"#/p5/strokeCap\">strokeCap()</a>, <a href=\"#/p5/strokeJoin\">strokeJoin()</a>,\n<a href=\"#/p5/imageMode\">imageMode()</a>, <a href=\"#/p5/rectMode\">rectMode()</a>, <a href=\"#/p5/ellipseMode\">ellipseMode()</a>, <a href=\"#/p5/colorMode\">colorMode()</a>, <a href=\"#/p5/textAlign\">textAlign()</a>,\n<a href=\"#/p5/textFont\">textFont()</a>, <a href=\"#/p5/textMode\">textMode()</a>, <a href=\"#/p5/textSize\">textSize()</a>, <a href=\"#/p5/textLeading\">textLeading()</a>.</p>\n",
9277          "itemtype": "method",
9278          "name": "pop",
9279          "example": ["\n<div>\n<code>\nellipse(0, 50, 33, 33); // Left circle\n\npush(); // Start a new drawing state\ntranslate(50, 0);\nstrokeWeight(10);\nfill(204, 153, 0);\nellipse(0, 50, 33, 33); // Middle circle\npop(); // Restore original state\n\nellipse(100, 50, 33, 33); // Right circle\n</code>\n</div>\n<div>\n<code>\nellipse(0, 50, 33, 33); // Left circle\n\npush(); // Start a new drawing state\nstrokeWeight(10);\nfill(204, 153, 0);\nellipse(33, 50, 33, 33); // Left-middle circle\n\npush(); // Start another new drawing state\nstroke(0, 102, 153);\nellipse(66, 50, 33, 33); // Right-middle circle\npop(); // Restore previous state\n\npop(); // Restore original state\n\nellipse(100, 50, 33, 33); // Right circle\n</code>\n</div>"],
9280          "alt": "Gold ellipse + thick black outline @center 2 white ellipses on left and right.\n2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right.",
9281          "class": "p5",
9282          "module": "Structure",
9283          "submodule": "Structure"
9284        }, {
9285          "file": "src/core/structure.js",
9286          "line": 247,
9287          "description": "<p>Executes the code within <a href=\"#/p5/draw\">draw()</a> one time. This functions allows the\n program to update the display window only when necessary, for example\n when an event registered by <a href=\"#/p5/mousePressed\">mousePressed()</a> or <a href=\"#/p5/keyPressed\">keyPressed()</a> occurs.\n <br><br>\n In structuring a program, it only makes sense to call <a href=\"#/p5/redraw\">redraw()</a> within\n events such as <a href=\"#/p5/mousePressed\">mousePressed()</a>. This is because <a href=\"#/p5/redraw\">redraw()</a> does not run\n <a href=\"#/p5/draw\">draw()</a> immediately (it only sets a flag that indicates an update is\n needed).\n <br><br>\n The <a href=\"#/p5/redraw\">redraw()</a> function does not work properly when called inside <a href=\"#/p5/draw\">draw()</a>.\n To enable/disable animations, use <a href=\"#/p5/loop\">loop()</a> and <a href=\"#/p5/noLoop\">noLoop()</a>.\n <br><br>\n In addition you can set the number of redraws per method call. Just\n add an integer as single parameter for the number of redraws.</p>\n",
9288          "itemtype": "method",
9289          "name": "redraw",
9290          "params": [{
9291            "name": "n",
9292            "description": "<p>Redraw for n-times. The default value is 1.</p>\n",
9293            "type": "Integer",
9294            "optional": true
9295          }],
9296          "example": ["\n <div><code>\n let x = 0;\nfunction setup() {\n   createCanvas(100, 100);\n   noLoop();\n }\nfunction draw() {\n   background(204);\n   line(x, 0, x, height);\n }\nfunction mousePressed() {\n   x += 1;\n   redraw();\n }\n </code></div>\n<div class='norender'><code>\n let x = 0;\nfunction setup() {\n   createCanvas(100, 100);\n   noLoop();\n }\nfunction draw() {\n   background(204);\n   x += 1;\n   line(x, 0, x, height);\n }\nfunction mousePressed() {\n   redraw(5);\n }\n </code></div>"],
9297          "alt": "black line on far left of canvas\n black line on far left of canvas",
9298          "class": "p5",
9299          "module": "Structure",
9300          "submodule": "Structure"
9301        }, {
9302          "file": "src/core/transform.js",
9303          "line": 13,
9304          "description": "<p>Multiplies the current matrix by the one specified through the parameters.\nThis is a powerful operation that can perform the equivalent of translate,\nscale, shear and rotate all at once. You can learn more about transformation\nmatrices on <a href=\"https://en.wikipedia.org/wiki/Transformation_matrix\">\nWikipedia</a>.</p>\n<p>The naming of the arguments here follows the naming of the <a href=\n\"https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform\">\nWHATWG specification</a> and corresponds to a\ntransformation matrix of the\nform:</p>\n<blockquote>\n<p><img style=\"max-width: 150px\" src=\"assets/transformation-matrix.png\"\nalt=\"The transformation matrix used when applyM
9304atrix is called\"/></p>\n</blockquote>\n",
9305          "itemtype": "method",
9306          "name": "applyMatrix",
9307          "params": [{
9308            "name": "a",
9309            "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n",
9310            "type": "Number"
9311          }, {
9312            "name": "b",
9313            "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n",
9314            "type": "Number"
9315          }, {
9316            "name": "c",
9317            "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n",
9318            "type": "Number"
9319          }, {
9320            "name": "d",
9321            "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n",
9322            "type": "Number"
9323          }, {
9324            "name": "e",
9325            "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n",
9326            "type": "Number"
9327          }, {
9328            "name": "f",
9329            "description": "<p>numbers which define the 2x3 matrix to be multiplied</p>\n",
9330            "type": "Number"
9331          }],
9332          "chainable": 1,
9333          "example": ["\n<div>\n<code>\nfunction setup() {\n  frameRate(10);\n  rectMode(CENTER);\n}\n\nfunction draw() {\n  var step = frameCount % 20;\n  background(200);\n  // Equivalent to translate(x, y);\n  applyMatrix(1, 0, 0, 1, 40 + step, 50);\n  rect(0, 0, 50, 50);\n}\n</code>\n</div>\n<div>\n<code>\nfunction setup() {\n  frameRate(10);\n  rectMode(CENTER);\n}\n\nfunction draw() {\n  var step = frameCount % 20;\n  background(200);\n  translate(50, 50);\n  // Equivalent to scale(x, y);\n  applyMatrix(1 / step, 0, 0, 1 / step, 0, 0);\n  rect(0, 0, 50, 50);\n}\n</code>\n</div>\n<div>\n<code>\nfunction setup() {\n  frameRate(10);\n  rectMode(CENTER);\n}\n\nfunction draw() {\n  var step = frameCount % 20;\n  var angle = map(step, 0, 20, 0, TWO_PI);\n  var cos_a = cos(angle);\n  var sin_a = sin(angle);\n  background(200);\n  translate(50, 50);\n  // Equivalent to rotate(angle);\n  applyMatrix(cos_a, sin_a, -sin_a, cos_a, 0, 0);\n  rect(0, 0, 50, 50);\n}\n</code>\n</div>\n<div>\n<code>\nfunction setup() {\n  frameRate(10);\n  rectMode(CENTER);\n}\n\nfunction draw() {\n  var step = frameCount % 20;\n  var angle = map(step, 0, 20, -PI / 4, PI / 4);\n  background(200);\n  translate(50, 50);\n  // equivalent to shearX(angle);\n  var shear_factor = 1 / tan(PI / 2 - angle);\n  applyMatrix(1, 0, shear_factor, 1, 0, 0);\n  rect(0, 0, 50, 50);\n}\n</code>\n</div>"],
9334          "alt": "A rectangle translating to the right\nA rectangle shrinking to the center\nA rectangle rotating clockwise about the center\nA rectangle shearing",
9335          "class": "p5",
9336          "module": "Transform",
9337          "submodule": "Transform"
9338        }, {
9339          "file": "src/core/transform.js",
9340          "line": 135,
9341          "description": "<p>Replaces the current matrix with the identity matrix.</p>\n",
9342          "itemtype": "method",
9343          "name": "resetMatrix",
9344          "chainable": 1,
9345          "example": ["\n<div>\n<code>\ntranslate(50, 50);\napplyMatrix(0.5, 0.5, -0.5, 0.5, 0, 0);\nrect(0, 0, 20, 20);\n// Note that the translate is also reset.\nresetMatrix();\nrect(0, 0, 20, 20);\n</code>\n</div>"],
9346          "alt": "A rotated retangle in the center with another at the top left corner",
9347          "class": "p5",
9348          "module": "Transform",
9349          "submodule": "Transform"
9350        }, {
9351          "file": "src/core/transform.js",
9352          "line": 161,
9353          "description": "<p>Rotates a shape the amount specified by the angle parameter. This\nfunction accounts for <a href=\"#/p5/angleMode\">angleMode</a>, so angles can be entered in either\nRADIANS or DEGREES.\n<br><br>\nObjects are always rotated around their relative position to the\norigin and positive numbers rotate objects in a clockwise direction.\nTransformations apply to everything that happens after and subsequent\ncalls to the function accumulates the effect. For example, calling\nrotate(HALF_PI) and then rotate(HALF_PI) is the same as rotate(PI).\nAll tranformations are reset when <a href=\"#/p5/draw\">draw()</a> begins again.\n<br><br>
9353\nTechnically, <a href=\"#/p5/rotate\">rotate()</a> multiplies the current transformation matrix\nby a rotation matrix. This function can be further controlled by\nthe <a href=\"#/p5/push\">push()</a> and <a href=\"#/p5/pop\">pop()</a>.</p>\n",
9354          "itemtype": "method",
9355          "name": "rotate",
9356          "params": [{
9357            "name": "angle",
9358            "description": "<p>the angle of rotation, specified in radians\n                       or degrees, depending on current angleMode</p>\n",
9359            "type": "Number"
9360          }, {
9361            "name": "axis",
9362            "description": "<p>(in 3d) the axis to rotate around</p>\n",
9363            "type": "p5.Vector|Number[]",
9364            "optional": true
9365          }],
9366          "chainable": 1,
9367          "example": ["\n<div>\n<code>\ntranslate(width / 2, height / 2);\nrotate(PI / 3.0);\nrect(-26, -26, 52, 52);\n</code>\n</div>"],
9368          "alt": "white 52x52 rect with black outline at center rotated counter 45 degrees",
9369          "class": "p5",
9370          "module": "Transform",
9371          "submodule": "Transform"
9372        }, {
9373          "file": "src/core/transform.js",
9374          "line": 201,
9375          "description": "<p>Rotates around X axis.</p>\n",
9376          "itemtype": "method",
9377          "name": "rotateX",
9378          "params": [{
9379            "name": "angle",
9380            "description": "<p>the angle of rotation, specified in radians\n                       or degrees, depending on current angleMode</p>\n",
9381            "type": "Number"
9382          }],
9383          "chainable": 1,
9384          "example": ["\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n  background(255);\n  rotateX(millis() / 1000);\n  box();\n}\n</code>\n</div>"],
9385          "alt": "3d box rotating around the x axis.",
9386          "class": "p5",
9387          "module": "Transform",
9388          "submodule": "Transform"
9389        }, {
9390          "file": "src/core/transform.js",
9391          "line": 231,
9392          "description": "<p>Rotates around Y axis.</p>\n",
9393          "itemtype": "method",
9394          "name": "rotateY",
9395          "params": [{
9396            "name": "angle",
9397            "description": "<p>the angle of rotation, specified in radians\n                       or degrees, depending on current angleMode</p>\n",
9398            "type": "Number"
9399          }],
9400          "chainable": 1,
9401          "example": ["\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n  background(255);\n  rotateY(millis() / 1000);\n  box();\n}\n</code>\n</div>"],
9402          "alt": "3d box rotating around the y axis.",
9403          "class": "p5",
9404          "module": "Transform",
9405          "submodule": "Transform"
9406        }, {
9407          "file": "src/core/transform.js",
9408          "line": 261,
9409          "description": "<p>Rotates around Z axis. Webgl mode only.</p>\n",
9410          "itemtype": "method",
9411          "name": "rotateZ",
9412          "params": [{
9413            "name": "angle",
9414            "description": "<p>the angle of rotation, specified in radians\n                       or degrees, depending on current angleMode</p>\n",
9415            "type": "Number"
9416          }],
9417          "chainable": 1,
9418          "example": ["\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n  background(255);\n  rotateZ(millis() / 1000);\n  box();\n}\n</code>\n</div>"],
9419          "alt": "3d box rotating around the z axis.",
9420          "class": "p5",
9421          "module": "Transform",
9422          "submodule": "Transform"
9423        }, {
9424          "file": "src/core/transform.js",
9425          "line": 291,
9426          "description": "<p>Increases or decreases the size of a shape by expanding and contracting\nvertices. Objects always scale from their relative origin to the\ncoordinate system. Scale values are specified as decimal percentages.\nFor example, the function call scale(2.0) increases the dimension of a\nshape by 200%.\n<br><br>\nTransformations apply to everything that happens after and subsequent\ncalls to the function multiply the effect. For example, calling scale(2.0)\nand then scale(1.5) is the same as scale(3.0). If <a href=\"#/p5/scale\">scale()</a> is called\nwithin <a href=\"#/p5/draw\">draw()</a>, the transformation is reset when the loop begins again.\n<br><br>\nUsing this function with the z parameter is only available in WEBGL mode.\nThis function can be further controlled with <a href=\"#/p5/push\">push()</a> and <a href=\"#/p5/pop\">pop()</a>.</p>\n",
9427          "itemtype": "method",
9428          "name": "scale",
9429          "chainable": 1,
9430          "example": ["\n<div>\n<code>\nrect(30, 20, 50, 50);\nscale(0.5);\nrect(30, 20, 50, 50);\n</code>\n</div>\n\n<div>\n<code>\nrect(30, 20, 50, 50);\nscale(0.5, 1.3);\nrect(30, 20, 50, 50);\n</code>\n</div>"],
9431          "alt": "white 52x52 rect with black outline at center rotated counter 45 degrees\n2 white rects with black outline- 1 50x50 at center. other 25x65 bottom left",
9432          "class": "p5",
9433          "module": "Transform",
9434          "submodule": "Transform",
9435          "overloads": [{
9436            "line": 291,
9437            "params": [{
9438              "name": "s",
9439              "description": "<p>percent to scale the object, or percentage to\n                     scale the object in the x-axis if multiple arguments\n                     are given</p>\n",
9440              "type": "Number|p5.Vector|Number[]"
9441            }, {
9442              "name": "y",
9443              "description": "<p>percent to scale the object in the y-axis</p>\n",
9444              "type": "Number",
9445              "optional": true
9446            }, {
9447              "name": "z",
9448              "description": "<p>percent to scale the object in the z-axis (webgl only)</p>\n",
9449              "type": "Number",
9450              "optional": true
9451            }],
9452            "chainable": 1
9453          }, {
9454            "line": 336,
9455            "params": [{
9456              "name": "scales",
9457              "description": "<p>per-axis percents to scale the object</p>\n",
9458              "type": "p5.Vector|Number[]"
9459            }],
9460            "chainable": 1
9461          }]
9462        }, {
9463          "file": "src/core/transform.js",
9464          "line": 366,
9465          "description": "<p>Shears a shape around the x-axis the amount specified by the angle\nparameter. Angles should be specified in the current angleMode.\nObjects are always sheared around their relative position to the origin\nand positive numbers shear objects in a clockwise direction.\n<br><br>\nTransformations apply to everything that happens after and subsequent\ncalls to the function accumulates the effect. For example, calling\nshearX(PI/2) and then shearX(PI/2) is the same as shearX(PI).\nIf <a href=\"#/p5/shearX\">shearX()</a> is called within the <a href=\"#/p5/draw\">draw()</a>, the transformation is reset when\nthe loop begins again.\n<br><br>
9465\nTechnically, <a href=\"#/p5/shearX\">shearX()</a> multiplies the current transformation matrix by a\nrotation matrix. This function can be further controlled by the\n<a href=\"#/p5/push\">push()</a> and <a href=\"#/p5/pop\">pop()</a> functions.</p>\n",
9466          "itemtype": "method",
9467          "name": "shearX",
9468          "params": [{
9469            "name": "angle",
9470            "description": "<p>angle of shear specified in radians or degrees,\n                       depending on current angleMode</p>\n",
9471            "type": "Number"
9472          }],
9473          "chainable": 1,
9474          "example": ["\n<div>\n<code>\ntranslate(width / 4, height / 4);\nshearX(PI / 4.0);\nrect(0, 0, 30, 30);\n</code>\n</div>"],
9475          "alt": "white irregular quadrilateral with black outline at top middle.",
9476          "class": "p5",
9477          "module": "Transform",
9478          "submodule": "Transform"
9479        }, {
9480          "file": "src/core/transform.js",
9481          "line": 405,
9482          "description": "<p>Shears a shape around the y-axis the amount specified by the angle\nparameter. Angles should be specified in the current angleMode. Objects\nare always sheared around their relative position to the origin and\npositive numbers shear objects in a clockwise direction.\n<br><br>\nTransformations apply to everything that happens after and subsequent\ncalls to the function accumulates the effect. For example, calling\nshearY(PI/2) and then shearY(PI/2) is the same as shearY(PI). If\n<a href=\"#/p5/shearY\">shearY()</a> is called within the <a href=\"#/p5/draw\">draw()</a>, the transformation is reset when\nthe loop begins again.\n<br><br>\nTechnically, <a href=\"#/p5/shearY\">shearY()</a> multiplies the current transformation matrix by a\nrotation matrix. This function can be further controlled by the\n<a href=\"#/p5/push\">push()</a> and <a href=\"#/p5/pop\">pop()</a> functions.</p>\n",
9483          "itemtype": "method",
9484          "name": "shearY",
9485          "params": [{
9486            "name": "angle",
9487            "description": "<p>angle of shear specified in radians or degrees,\n                       depending on current angleMode</p>\n",
9488            "type": "Number"
9489          }],
9490          "chainable": 1,
9491          "example": ["\n<div>\n<code>\ntranslate(width / 4, height / 4);\nshearY(PI / 4.0);\nrect(0, 0, 30, 30);\n</code>\n</div>"],
9492          "alt": "white irregular quadrilateral with black outline at middle bottom.",
9493          "class": "p5",
9494          "module": "Transform",
9495          "submodule": "Transform"
9496        }, {
9497          "file": "src/core/transform.js",
9498          "line": 444,
9499          "description": "<p>Specifies an amount to displace objects within the display window.\nThe x parameter specifies left/right translation, the y parameter\nspecifies up/down translation.\n<br><br>\nTransformations are cumulative and apply to everything that happens after\nand subsequent calls to the function accumulates the effect. For example,\ncalling translate(50, 0) and then translate(20, 0) is the same as\ntranslate(70, 0). If <a href=\"#/p5/translate\">translate()</a> is called within <a href=\"#/p5/draw\">draw()</a>, the\ntransformation is reset when the loop begins again. This function can be\nfurther controlled by using <a href=\"#/p5/push\">push()</a> and <a href=\"#/p5/pop\">pop()</a>.</p>\n",
9500          "itemtype": "method",
9501          "name": "translate",
9502          "chainable": 1,
9503          "example": ["\n<div>\n<code>\ntranslate(30, 20);\nrect(0, 0, 55, 55);\n</code>\n</div>\n\n<div>\n<code>\nrect(0, 0, 55, 55); // Draw rect at original 0,0\ntranslate(30, 20);\nrect(0, 0, 55, 55); // Draw rect at new 0,0\ntranslate(14, 14);\nrect(0, 0, 55, 55); // Draw rect at new 0,0\n</code>\n</div>\n\n\n<div>\n<code>\nfunction draw() {\n  background(200);\n  rectMode(CENTER);\n  translate(width / 2, height / 2);\n  translate(p5.Vector.fromAngle(millis() / 1000, 40));\n  rect(0, 0, 20, 20);\n}\n</code>\n</div>"],
9504          "alt": "white 55x55 rect with black outline at center right.\n3 white 55x55 rects with black outlines at top-l, center-r and bottom-r.\na 20x20 white rect moving in a circle around the canvas",
9505          "class": "p5",
9506          "module": "Transform",
9507          "submodule": "Transform",
9508          "overloads": [{
9509            "line": 444,
9510            "params": [{
9511              "name": "x",
9512              "description": "<p>left/right translation</p>\n",
9513              "type": "Number"
9514            }, {
9515              "name": "y",
9516              "description": "<p>up/down translation</p>\n",
9517              "type": "Number"
9518            }, {
9519              "name": "z",
9520              "description": "<p>forward/backward translation (webgl only)</p>\n",
9521              "type": "Number",
9522              "optional": true
9523            }],
9524            "chainable": 1
9525          }, {
9526            "line": 498,
9527            "params": [{
9528              "name": "vector",
9529              "description": "<p>the vector to translate by</p>\n",
9530              "type": "p5.Vector"
9531            }],
9532            "chainable": 1
9533          }]
9534        }, {
9535          "file": "src/data/p5.TypedDict.js",
9536          "line": 16,
9537          "description": "<p>Creates a new instance of p5.StringDict using the key-value pair\n or the object you provide.</p>\n",
9538          "itemtype": "method",
9539          "name": "createStringDict",
9540          "return": {
9541            "description": "",
9542            "type": "p5.StringDict"
9543          },
9544          "example": ["\n <div class=\"norender\">\n <code>\n function setup() {\n   var myDictionary = createStringDict('p5', 'js');\n   print(myDictionary.hasKey('p5')); // logs true to console\n  var anotherDictionary = createStringDict({ happy: 'coding' });\n   print(anotherDictionary.hasKey('happy')); // logs true to console\n }\n </code></div>"],
9545          "class": "p5",
9546          "module": "Data",
9547          "submodule": "Dictionary",
9548          "overloads": [{
9549            "line": 16,
9550            "params": [{
9551              "name": "key",
9552              "description": "",
9553              "type": "String"
9554            }, {
9555              "name": "value",
9556              "description": "",
9557              "type": "String"
9558            }],
9559            "return": {
9560              "description": "",
9561              "type": "p5.StringDict"
9562            }
9563          }, {
9564            "line": 39,
9565            "params": [{
9566              "name": "object",
9567              "description": "<p>object</p>\n",
9568              "type": "Object"
9569            }],
9570            "return": {
9571              "description": "",
9572              "type": "p5.StringDict"
9573            }
9574          }]
9575        }, {
9576          "file": "src/data/p5.TypedDict.js",
9577          "line": 50,
9578          "description": "<p>Creates a new instance of <a href=\"#/p5.NumberDict\">p5.NumberDict</a> using the key-value pair\n or object you provide.</p>\n",
9579          "itemtype": "method",
9580          "name": "createNumberDict",
9581          "return": {
9582            "description": "",
9583            "type": "p5.NumberDict"
9584          },
9585          "example": ["\n <div class=\"norender\">\n <code>\n function setup() {\n   var myDictionary = createNumberDict(100, 42);\n   print(myDictionary.hasKey(100)); // logs true to console\n  var anotherDictionary = createNumberDict({ 200: 84 });\n   print(anotherDictionary.hasKey(200)); // logs true to console\n }\n </code></div>"],
9586          "class": "p5",
9587          "module": "Data",
9588          "submodule": "Dictionary",
9589          "overloads": [{
9590            "line": 50,
9591            "params": [{
9592              "name": "key",
9593              "description": "",
9594              "type": "Number"
9595            }, {
9596              "name": "value",
9597              "description": "",
9598              "type": "Number"
9599            }],
9600            "return": {
9601              "description": "",
9602              "type": "p5.NumberDict"
9603            }
9604          }, {
9605            "line": 73,
9606            "params": [{
9607              "name": "object",
9608              "description": "<p>object</p>\n",
9609              "type": "Object"
9610            }],
9611            "return": {
9612              "description": "",
9613              "type": "p5.NumberDict"
9614            }
9615          }]
9616        }, {
9617          "file": "src/data/p5.TypedDict.js",
9618          "line": 103,
9619          "description": "<p>Returns the number of key-value pairs currently stored in the Dictionary.</p>\n",
9620          "itemtype": "method",
9621          "name": "size",
9622          "return": {
9623            "description": "the number of key-value pairs in the Dictionary",
9624            "type": "Integer"
9625          },
9626          "example": ["\n<div class=\"norender\">\n<code>\nfunction setup() {\n  var myDictionary = createNumberDict(1, 10);\n  myDictionary.create(2, 20);\n  myDictionary.create(3, 30);\n  print(myDictionary.size()); // logs 3 to the console\n}\n</code></div>\n"],
9627          "class": "p5.TypedDict",
9628          "module": "Data",
9629          "submodule": "Dictionary"
9630        }, {
9631          "file": "src/data/p5.TypedDict.js",
9632          "line": 125,
9633          "description": "<p>Returns true if the given key exists in the Dictionary,\notherwise returns false.</p>\n",
9634          "itemtype": "method",
9635          "name": "hasKey",
9636          "params": [{
9637            "name": "key",
9638            "description": "<p>that you want to look up</p>\n",
9639            "type": "Number|String"
9640          }],
9641          "return": {
9642            "description": "whether that key exists in Dictionary",
9643            "type": "Boolean"
9644          },
9645          "example": ["\n<div class=\"norender\">\n<code>\nfunction setup() {\n  var myDictionary = createStringDict('p5', 'js');\n  print(myDictionary.hasKey('p5')); // logs true to console\n}\n</code></div>\n"],
9646          "class": "p5.TypedDict",
9647          "module": "Data",
9648          "submodule": "Dictionary"
9649        }, {
9650          "file": "src/data/p5.TypedDict.js",
9651          "line": 148,
9652          "description": "<p>Returns the value stored at the given key.</p>\n",
9653          "itemtype": "method",
9654          "name": "get",
9655          "params": [{
9656            "name": "the",
9657            "description": "<p>key you want to access</p>\n",
9658            "type": "Number|String"
9659          }],
9660          "return": {
9661            "description": "the value stored at that key",
9662            "type": "Number|String"
9663          },
9664          "example": ["\n<div class=\"norender\">\n<code>\nfunction setup() {\n  var myDictionary = createStringDict('p5', 'js');\n  var myValue = myDictionary.get('p5');\n  print(myValue === 'js'); // logs true to console\n}\n</code></div>\n"],
9665          "class": "p5.TypedDict",
9666          "module": "Data",
9667          "submodule": "Dictionary"
9668        }, {
9669          "file": "src/data/p5.TypedDict.js",
9670          "line": 175,
9671          "description": "<p>Updates the value associated with the given key in case it already exists\nin the Dictionary. Otherwise a new key-value pair is added.</p>\n",
9672          "itemtype": "method",
9673          "name": "set",
9674          "params": [{
9675            "name": "key",
9676            "description": "",
9677            "type": "Number|String"
9678          }, {
9679            "name": "value",
9680            "description": "",
9681            "type": "Number|String"
9682          }],
9683          "example": ["\n<div class=\"norender\">\n<code>\nfunction setup() {\n  var myDictionary = createStringDict('p5', 'js');\n  myDictionary.set('p5', 'JS');\n  myDictionary.print(); // logs \"key: p5 - value: JS\" to console\n}\n</code></div>\n"],
9684          "class": "p5.TypedDict",
9685          "module": "Data",
9686          "submodule": "Dictionary"
9687        }, {
9688          "file": "src/data/p5.TypedDict.js",
9689          "line": 203,
9690          "description": "<p>private helper function to handle the user passing in objects\nduring construction or calls to create()</p>\n",
9691          "class": "p5.TypedDict",
9692          "module": "Data",
9693          "submodule": "Dictionary"
9694        }, {
9695          "file": "src/data/p5.TypedDict.js",
9696          "line": 214,
9697          "description": "<p>Creates a new key-value pair in the Dictionary.</p>\n",
9698          "itemtype": "method",
9699          "name": "create",
9700          "example": ["\n<div class=\"norender\">\n<code>\nfunction setup() {\n  var myDictionary = createStringDict('p5', 'js');\n  myDictionary.create('happy', 'coding');\n  myDictionary.print();\n  // above logs \"key: p5 - value: js, key: happy - value: coding\" to console\n}\n</code></div>"],
9701          "class": "p5.TypedDict",
9702          "module": "Data",
9703          "submodule": "Dictionary",
9704          "overloads": [{
9705            "line": 214,
9706            "params": [{
9707              "name": "key",
9708              "description": "",
9709              "type": "Number|String"
9710            }, {
9711              "name": "value",
9712              "description": "",
9713              "type": "Number|String"
9714            }]
9715          }, {
9716            "line": 232,
9717            "params": [{
9718              "name": "obj",
9719              "description": "<p>key/value pair</p>\n",
9720              "type": "Object"
9721            }]
9722          }]
9723        }, {
9724          "file": "src/data/p5.TypedDict.js",
9725          "line": 250,
9726          "description": "<p>Removes all previously stored key-value pairs from the Dictionary.</p>\n",
9727          "itemtype": "method",
9728          "name": "clear",
9729          "example": ["\n<div class=\"norender\">\n<code>\nfunction setup() {\n  var myDictionary = createStringDict('p5', 'js');\n  print(myDictionary.hasKey('p5')); // prints 'true'\n  myDictionary.clear();\n  print(myDictionary.hasKey('p5')); // prints 'false'\n}\n</code>\n</div>"],
9730          "class": "p5.TypedDict",
9731          "module": "Data",
9732          "submodule": "Dictionary"
9733        }, {
9734          "file": "src/data/p5.TypedDict.js",
9735          "line": 271,
9736          "description": "<p>Removes the key-value pair stored at the given key from the Dictionary.</p>\n",
9737          "itemtype": "method",
9738          "name": "remove",
9739          "params": [{
9740            "name": "key",
9741            "description": "<p>for the pair to remove</p>\n",
9742            "type": "Number|String"
9743          }],
9744          "example": ["\n<div class=\"norender\">\n<code>\nfunction setup() {\n  var myDictionary = createStringDict('p5', 'js');\n  myDictionary.create('happy', 'coding');\n  myDictionary.print();\n  // above logs \"key: p5 - value: js, key: happy - value: coding\" to console\n  myDictionary.remove('p5');\n  myDictionary.print();\n  // above logs \"key: happy value: coding\" to console\n}\n</code></div>\n"],
9745          "class": "p5.TypedDict",
9746          "module": "Data",
9747          "submodule": "Dictionary"
9748        }, {
9749          "file": "src/data/p5.TypedDict.js",
9750          "line": 301,
9751          "description": "<p>Logs the set of items currently stored in the Dictionary to the console.</p>\n",
9752          "itemtype": "method",
9753          "name": "print",
9754          "example": ["\n<div class=\"norender\">\n<code>\nfunction setup() {\n  var myDictionary = createStringDict('p5', 'js');\n  myDictionary.create('happy', 'coding');\n  myDictionary.print();\n  // above logs \"key: p5 - value: js, key: happy - value: coding\" to console\n}\n</code>\n</div>"],
9755          "class": "p5.TypedDict",
9756          "module": "Data",
9757          "submodule": "Dictionary"
9758        }, {
9759          "file": "src/data/p5.TypedDict.js",
9760          "line": 325,
9761          "description": "<p>Converts the Dictionary into a CSV file for local download.</p>\n",
9762          "itemtype": "method",
9763          "name": "saveTable",
9764          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100);\n  background(200);\n  text('click here to save', 10, 10, 70, 80);\n}\n\nfunction mousePressed() {\n  if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n    createStringDict({\n      john: 1940,\n      paul: 1942,\n      george: 1943,\n      ringo: 1940\n    }).saveTable('beatles');\n  }\n}\n</code>\n</div>"],
9765          "class": "p5.TypedDict",
9766          "module": "Data",
9767          "submodule": "Dictionary"
9768        }, {
9769          "file": "src/data/p5.TypedDict.js",
9770          "line": 363,
9771          "description": "<p>Converts the Dictionary into a JSON file for local download.</p>\n",
9772          "itemtype": "method",
9773          "name": "saveJSON",
9774          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100);\n  background(200);\n  text('click here to save', 10, 10,
9774 70, 80);\n}\n\nfunction mousePressed() {\n  if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n    createStringDict({\n      john: 1940,\n      paul: 1942,\n      george: 1943,\n      ringo: 1940\n    }).saveJSON('beatles');\n  }\n}\n</code>\n</div>"],
9775          "class": "p5.TypedDict",
9776          "module": "Data",
9777          "submodule": "Dictionary"
9778        }, {
9779          "file": "src/data/p5.TypedDict.js",
9780          "line": 394,
9781          "description": "<p>private helper function to ensure that the user passed in valid\nvalues for the Dictionary type</p>\n",
9782          "class": "p5.TypedDict",
9783          "module": "Data",
9784          "submodule": "Dictionary"
9785        }, {
9786          "file": "src/data/p5.TypedDict.js",
9787          "line": 437,
9788          "description": "<p>private helper function to ensure that the user passed in valid\nvalues for the Dictionary type</p>\n",
9789          "class": "p5.NumberDict",
9790          "module": "Data",
9791          "submodule": "Dictionary"
9792        }, {
9793          "file": "src/data/p5.TypedDict.js",
9794          "line": 446,
9795          "description": "<p>Add the given number to the value currently stored at the given key.\nThe sum then replaces the value previously stored in the Dictionary.</p>\n",
9796          "itemtype": "method",
9797          "name": "add",
9798          "params": [{
9799            "name": "Key",
9800            "description": "<p>for the value you wish to add to</p>\n",
9801            "type": "Number"
9802          }, {
9803            "name": "Number",
9804            "description": "<p>to add to the value</p>\n",
9805            "type": "Number"
9806          }],
9807          "example": ["\n<div class='norender'>\n<code>\nfunction setup() {\n  var myDictionary = createNumberDict(2, 5);\n  myDictionary.add(2, 2);\n  print(myDictionary.get(2)); // logs 7 to console.\n}\n</code></div>\n\n"],
9808          "class": "p5.NumberDict",
9809          "module": "Data",
9810          "submodule": "Dictionary"
9811        }, {
9812          "file": "src/data/p5.TypedDict.js",
9813          "line": 474,
9814          "description": "<p>Subtract the given number from the value currently stored at the given key.\nThe difference then replaces the value previously stored in the Dictionary.</p>\n",
9815          "itemtype": "method",
9816          "name": "sub",
9817          "params": [{
9818            "name": "Key",
9819            "description": "<p>for the value you wish to subtract from</p>\n",
9820            "type": "Number"
9821          }, {
9822            "name": "Number",
9823            "description": "<p>to subtract from the value</p>\n",
9824            "type": "Number"
9825          }],
9826          "example": ["\n<div class='norender'>\n<code>\nfunction setup() {\n  var myDictionary = createNumberDict(2, 5);\n  myDictionary.sub(2, 2);\n  print(myDictionary.get(2)); // logs 3 to console.\n}\n</code></div>\n\n"],
9827          "class": "p5.NumberDict",
9828          "module": "Data",
9829          "submodule": "Dictionary"
9830        }, {
9831          "file": "src/data/p5.TypedDict.js",
9832          "line": 498,
9833          "description": "<p>Multiply the given number with the value currently stored at the given key.\nThe product then replaces the value previously stored in the Dictionary.</p>\n",
9834          "itemtype": "method",
9835          "name": "mult",
9836          "params": [{
9837            "name": "Key",
9838            "description": "<p>for value you wish to multiply</p>\n",
9839            "type": "Number"
9840          }, {
9841            "name": "Amount",
9842            "description": "<p>to multiply the value by</p>\n",
9843            "type": "Number"
9844          }],
9845          "example": ["\n<div class='norender'>\n<code>\nfunction setup() {\n  var myDictionary = createNumberDict(2, 4);\n  myDictionary.mult(2, 2);\n  print(myDictionary.get(2)); // logs 8 to console.\n}\n</code></div>\n\n"],
9846          "class": "p5.NumberDict",
9847          "module": "Data",
9848          "submodule": "Dictionary"
9849        }, {
9850          "file": "src/data/p5.TypedDict.js",
9851          "line": 526,
9852          "description": "<p>Divide the given number with the value currently stored at the given key.\nThe quotient then replaces the value previously stored in the Dictionary.</p>\n",
9853          "itemtype": "method",
9854          "name": "div",
9855          "params": [{
9856            "name": "Key",
9857            "description": "<p>for value you wish to divide</p>\n",
9858            "type": "Number"
9859          }, {
9860            "name": "Amount",
9861            "description": "<p>to divide the value by</p>\n",
9862            "type": "Number"
9863          }],
9864          "example": ["\n<div class='norender'>\n<code>\nfunction setup() {\n  var myDictionary = createNumberDict(2, 8);\n  myDictionary.div(2, 2);\n  print(myDictionary.get(2)); // logs 4 to console.\n}\n</code></div>\n\n"],
9865          "class": "p5.NumberDict",
9866          "module": "Data",
9867          "submodule": "Dictionary"
9868        }, {
9869          "file": "src/data/p5.TypedDict.js",
9870          "line": 554,
9871          "description": "<p>private helper function for finding lowest or highest value\nthe argument &#39;flip&#39; is used to flip the comparison arrow\nfrom &#39;less than&#39; to &#39;greater than&#39;</p>\n",
9872          "class": "p5.NumberDict",
9873          "module": "Data",
9874          "submodule": "Dictionary"
9875        }, {
9876          "file": "src/data/p5.TypedDict.js",
9877          "line": 579,
9878          "description": "<p>Return the lowest number currently stored in the Dictionary.</p>\n",
9879          "itemtype": "method",
9880          "name": "minValue",
9881          "return": {
9882            "description": "",
9883            "type": "Number"
9884          },
9885          "example": ["\n<div class='norender'>\n<code>\nfunction setup() {\n  var myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 });\n  var lowestValue = myDictionary.minValue(); // value is -10\n  print(lowestValue);\n}\n</code></div>\n"],
9886          "class": "p5.NumberDict",
9887          "module": "Data",
9888          "submodule": "Dictionary"
9889        }, {
9890          "file": "src/data/p5.TypedDict.js",
9891          "line": 600,
9892          "description": "<p>Return the highest number currently stored in the Dictionary.</p>\n",
9893          "itemtype": "method",
9894          "name": "maxValue",
9895          "return": {
9896            "description": "",
9897            "type": "Number"
9898          },
9899          "example": ["\n<div class='norender'>\n<code>\nfunction setup() {\n  var myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 });\n  var highestValue = myDictionary.maxValue(); // value is 3\n  print(highestValue);\n}\n</code></div>\n"],
9900          "class": "p5.NumberDict",
9901          "module": "Data",
9902          "submodule": "Dictionary"
9903        }, {
9904          "file": "src/data/p5.TypedDict.js",
9905          "line": 621,
9906          "description": "<p>private helper function for finding lowest or highest key\nthe argument &#39;flip&#39; is used to flip the comparison arrow\nfrom &#39;less than&#39; to &#39;greater than&#39;</p>\n",
9907          "class": "p5.NumberDict",
9908          "module": "Data",
9909          "submodule": "Dictionary"
9910        }, {
9911          "file": "src/data/p5.TypedDict.js",
9912          "line": 644,
9913          "description": "<p>Return the lowest key currently used in the Dictionary.</p>\n",
9914          "itemtype": "method",
9915          "name": "minKey",
9916          "return": {
9917            "description": "",
9918            "type": "Number"
9919          },
9920          "example": ["\n<div class='norender'>\n<code>\nfunction setup() {\n  var myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 });\n  var lowestKey = myDictionary.minKey(); // value is 1.2\n  print(lowestKey);\n}\n</code></div>\n"],
9921          "class": "p5.NumberDict",
9922          "module": "Data",
9923          "submodule": "Dictionary"
9924        }, {
9925          "file": "src/data/p5.TypedDict.js",
9926          "line": 665,
9927          "description": "<p>Return the highest key currently used in the Dictionary.</p>\n",
9928          "itemtype": "method",
9929          "name": "maxKey",
9930          "return": {
9931            "description": "",
9932            "type": "Number"
9933          },
9934          "example": ["\n<div class='norender'>\n<code>\nfunction setup() {\n  var myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 });\n  var highestKey = myDictionary.maxKey(); // value is 4\n  print(highestKey);\n}\n</code></div>\n"],
9935          "class": "p5.NumberDict",
9936          "module": "Data",
9937          "submodule": "Dictionary"
9938        }, {
9939          "file": "src/events/acceleration.js",
9940          "line": 12,
9941          "description": "<p>The system variable deviceOrientation always contains the orientation of\nthe device. The value of this variable will either be set &#39;landscape&#39;
9941\nor &#39;portrait&#39;. If no data is available it will be set to &#39;undefined&#39;.\neither LANDSCAPE or PORTRAIT.</p>\n",
9942          "itemtype": "property",
9943          "name": "deviceOrientation",
9944          "type": "Constant",
9945          "readonly": "",
9946          "class": "p5",
9947          "module": "Events",
9948          "submodule": "Acceleration"
9949        }, {
9950          "file": "src/events/acceleration.js",
9951          "line": 23,
9952          "description": "<p>The system variable accelerationX always contains the acceleration of the\ndevice along the x axis. Value is represented as meters per second squared.</p>\n",
9953          "itemtype": "property",
9954          "name": "accelerationX",
9955          "type": "Number",
9956          "readonly": "",
9957          "example": ["\n<div>\n<code>\n// Move a touchscreen device to register\n// acceleration changes.\nfunction draw() {\n  background(220, 50);\n  fill('magenta');\n  ellipse(width / 2, height / 2, accelerationX);\n}\n</code>\n</div>"],
9958          "alt": "Magnitude of device acceleration is displayed as ellipse size",
9959          "class": "p5",
9960          "module": "Events",
9961          "submodule": "Acceleration"
9962        }, {
9963          "file": "src/events/acceleration.js",
9964          "line": 46,
9965          "description": "<p>The system variable accelerationY always contains the acceleration of the\ndevice along the y axis. Value is represented as meters per second squared.</p>\n",
9966          "itemtype": "property",
9967          "name": "accelerationY",
9968          "type": "Number",
9969          "readonly": "",
9970          "example": ["\n<div>\n<code>\n// Move a touchscreen device to register\n// acceleration changes.\nfunction draw() {\n  background(220, 50);\n  fill('magenta');\n  ellipse(width / 2, height / 2, accelerationY);\n}\n</code>\n</div>"],
9971          "alt": "Magnitude of device acceleration is displayed as ellipse size",
9972          "class": "p5",
9973          "module": "Events",
9974          "submodule": "Acceleration"
9975        }, {
9976          "file": "src/events/acceleration.js",
9977          "line": 69,
9978          "description": "<p>The system variable accelerationZ always contains the acceleration of the\ndevice along the z axis. Value is represented as meters per second squared.</p>\n",
9979          "itemtype": "property",
9980          "name": "accelerationZ",
9981          "type": "Number",
9982          "readonly": "",
9983          "example": ["\n<div>\n<code>\n// Move a touchscreen device to register\n// acceleration changes.\nfunction draw() {\n  background(220, 50);\n  fill('magenta');\n  ellipse(width / 2, height / 2, accelerationZ);\n}\n</code>\n</div>"],
9984          "alt": "Magnitude of device acceleration is displayed as ellipse size",
9985          "class": "p5",
9986          "module": "Events",
9987          "submodule": "Acceleration"
9988        }, {
9989          "file": "src/events/acceleration.js",
9990          "line": 94,
9991          "description": "<p>The system variable pAccelerationX always contains the acceleration of the\ndevice along the x axis in the frame previous to the current frame. Value\nis represented as meters per second squared.</p>\n",
9992          "itemtype": "property",
9993          "name": "pAccelerationX",
9994          "type": "Number",
9995          "readonly": "",
9996          "class": "p5",
9997          "module": "Events",
9998          "submodule": "Acceleration"
9999        }, {
10000          "file": "src/events/acceleration.js",
10001          "line": 104,
10002          "description": "<p>The system variable pAccelerationY always contains the acceleration of the\ndevice along the y axis in the frame previous to the current frame. Value\nis represented as meters per second squared.</p>\n",
10003          "itemtype": "property",
10004          "name": "pAccelerationY",
10005          "type": "Number",
10006          "readonly": "",
10007          "class": "p5",
10008          "module": "Events",
10009          "submodule": "Acceleration"
10010        }, {
10011          "file": "src/events/acceleration.js",
10012          "line": 114,
10013          "description": "<p>The system variable pAccelerationZ always contains the acceleration of the\ndevice along the z axis in the frame previous to the current frame. Value\nis represented as meters per second squared.</p>\n",
10014          "itemtype": "property",
10015          "name": "pAccelerationZ",
10016          "type": "Number",
10017          "readonly": "",
10018          "class": "p5",
10019          "module": "Events",
10020          "submodule": "Acceleration"
10021        }, {
10022          "file": "src/events/acceleration.js",
10023          "line": 135,
10024          "description": "<p>The system variable rotationX always contains the rotation of the\ndevice along the x axis. V
10024alue is represented as 0 to +/-180 degrees.\n<br><br>\nNote: The order the rotations are called is important, ie. if used\ntogether, it must be called in the order Z-X-Y or there might be\nunexpected behaviour.</p>\n",
10025          "itemtype": "property",
10026          "name": "rotationX",
10027          "type": "Number",
10028          "readonly": "",
10029          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  //rotateZ(radians(rotationZ));\n  rotateX(radians(rotationX));\n  //rotateY(radians(rotationY));\n  box(200, 200, 200);\n}\n</code>\n</div>"],
10030          "alt": "red horizontal line right, green vertical line bottom. black background.",
10031          "class": "p5",
10032          "module": "Events",
10033          "submodule": "Acceleration"
10034        }, {
10035          "file": "src/events/acceleration.js",
10036          "line": 166,
10037          "description": "<p>The system variable rotationY always contains the rotation of the\ndevice along the y axis. Value is represented as 0 to +/-90 degrees.\n<br><br>\nNote: The order the rotations are called is important, ie. if used\ntogether, it must be called in the order Z-X-Y or there might be\nunexpected behaviour.</p>\n",
10038          "itemtype": "property",
10039          "name": "rotationY",
10040          "type": "Number",
10041          "readonly": "",
10042          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  //rotateZ(radians(rotationZ));\n  //rotateX(radians(rotationX));\n  rotateY(radians(rotationY));\n  box(200, 200, 200);\n}\n</code>\n</div>"],
10043          "alt": "red horizontal line right, green vertical line bottom. black background.",
10044          "class": "p5",
10045          "module": "Events",
10046          "submodule": "Acceleration"
10047        }, {
10048          "file": "src/events/acceleration.js",
10049          "line": 197,
10050          "description": "<p>The system variable rotationZ always contains the rotation of the\ndevice along the z axis. Value is represented as 0 to 359 degrees.\n<br><br>\nUnlike rotationX and rotationY, this variable is available for devices\nwith a built-in compass only.\n<br><br>\nNote: The order the rotations are called is important, ie. if used\ntogether, it must be called in the order Z-X-Y or there might be\nunexpected behaviour.</p>\n",
10051          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  rotateZ(radians(rotationZ));\n  //rotateX(radians(rotationX));\n  //rotateY(radians(rotationY));\n  box(200, 200, 200);\n}\n</code>\n</div>"],
10052          "itemtype": "property",
10053          "name": "rotationZ",
10054          "type": "Number",
10055          "readonly": "",
10056          "alt": "red horizontal line right, green vertical line bottom. black background.",
10057          "class": "p5",
10058          "module": "Events",
10059          "submodule": "Acceleration"
10060        }, {
10061          "file": "src/events/acceleration.js",
10062          "line": 233,
10063          "description": "<p>The system variable pRotationX always contains the rotation of the\ndevice along the x axis in the frame previous to the current frame. Value\nis represented as 0 to +/-180 degrees.\n<br><br>\npRotationX can also be used with rotationX to determine the rotate\ndirection of the device along the X-axis.</p>\n",
10064          "example": ["\n<div class='norender'>\n<code>\n// A simple if statement looking at whether\n// rotationX - pRotationX < 0 is true or not will be\n// sufficient for determining the rotate direction\n// in most cases.\n\n// Some extra logic is needed to account for cases where\n// the angles wrap around.\nlet rotateDirection = 'clockwise';\n\n// Simple range conversion to make things simpler.\n// This is not absolutely necessary but the logic\n// will be different in that case.\n\nlet rX = rotationX + 180;\nlet pRX = pRotationX + 180;\n\nif ((rX - pRX > 0 && rX - pRX < 270) || rX - pRX < -270) {\n  rotateDirection = 'clockwise';\n} else if (rX - pRX < 0 || rX - pRX > 270) {\n  rotateDirection = 'counter-clockwise';\n}\n\nprint(rotateDirection);\n</code>\n</div>"],
10065          "alt": "no image to display.",
10066          "itemtype": "property",
10067          "name": "pRotationX",
10068          "type": "Number",
10069          "readonly": "",
10070          "class": "p5",
10071          "module": "Events",
10072          "submodule": "Acceleration"
10073        }, {
10074          "file": "src/events/acceleration.js",
10075          "line": 278,
10076          "description": "<p>The system variable pRotationY always contains the rotation of the\ndevice along the y axis in the frame previous to the current frame. Value\nis represented as 0 to +/-90 degrees.\n<br><br>\npRotationY can also be used with rotationY to determine the rotate\ndirection of the device along the Y-axis.</p>\n",
10077          "example": ["\n<div class='norender'>\n<code>\n// A simple if statement looking at whether\n// rotationY - pRotationY < 0 is true or not will be\n// sufficient for determining the rotate direction\n// in most cases.\n\n// Some extra logic is needed to account for cases where\n// the angles wrap around.\nlet rotateDirection = 'clockwise';\n\n// Simple range conversion to make things simpler.\n// This is not absolutely necessary but the logic\n// will be different in that case.\n\nlet rY = rotationY + 180;\nlet pRY = pRotationY + 180;\n\nif ((rY - pRY > 0 && rY - pRY < 270) || rY - pRY < -270) {\n  rotateDirection = 'clockwise';\n} else if (rY - pRY < 0 || rY - pRY > 270) {\n  rotateDirection = 'counter-clockwise';\n}\nprint(rotateDirection);\n</code>\n</div>"],
10078          "alt": "no image to display.",
10079          "itemtype": "property",
10080          "name": "pRotationY",
10081          "type": "Number",
10082          "readonly": "",
10083          "class": "p5",
10084          "module": "Events",
10085          "submodule": "Acceleration"
10086        }, {
10087          "file": "src/events/acceleration.js",
10088          "line": 322,
10089          "description": "<p>The system variable pRotationZ always contains the rotation of the\ndevice along the z axis in the frame previous to the current frame. Value\nis represented as 0 to 359 degrees.\n<br><br>\npRotationZ can also be used with rotationZ to determine the rotate\ndirection of the device along the Z-axis.</p>\n",
10090          "example": ["\n<div class='norender'>\n<code>\n// A simple if statement looking at whether\n// rotationZ - pRotationZ < 0 is true or not will be\n// sufficient for determining the rotate direction\n// in most cases.\n\n// Some extra logic is needed to account for cases where\n// the angles wrap around.\nlet rotateDirection = 'clockwise';\n\nif (\n  (rotationZ - pRotationZ > 0 && rotationZ - pRotationZ < 270) ||\n  rotationZ - pRotationZ < -270\n) {\n  rotateDirection = 'clockwise';\n} else if (rotationZ - pRotationZ < 0 || rotationZ - pRotationZ > 270) {\n  rotateDirection = 'counter-clockwise';\n}\nprint(rotateDirection);\n</code>\n</div>"],
10091          "alt": "no image to display.",
10092          "itemtype": "property",
10093          "name": "pRotationZ",
10094          "type": "Number",
10095          "readonly": "",
10096          "class": "p5",
10097          "module": "Events",
10098          "submodule": "Acceleration"
10099        }, {
10100          "file": "src/events/acceleration.js",
10101          "line": 380,
10102          "description": "<p>When a device is rotated, the axis that triggers the <a href=\"#/p5/deviceTurned\">deviceTurned()</a>\nmethod is stored in the turnAxis variable. The turnAxis variable is only defined within\nthe scope of deviceTurned().</p>\n",
10103          "itemtype": "property",
10104          "name": "turnAxis",
10105          "type": "String",
10106          "readonly": "",
10107          "example": ["\n<div>\n<code>\n// Run this example on a mobile device\n// Rotate the device by 90 degrees in the\n// X-axis to change the value.\n\nvar value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction deviceTurned() {\n  if (turnAxis === 'X') {\n    if (value === 0) {\n      value = 255;\n    }
10107 else if (value === 255) {\n      value = 0;\n    }\n  }\n}\n</code>\n</div>"],
10108          "alt": "50x50 black rect in center of canvas. turns white on mobile when device turns\n50x50 black rect in center of canvas. turns white on mobile when x-axis turns",
10109          "class": "p5",
10110          "module": "Events",
10111          "submodule": "Acceleration"
10112        }, {
10113          "file": "src/events/acceleration.js",
10114          "line": 419,
10115          "description": "<p>The <a href=\"#/p5/setMoveThreshold\">setMoveThreshold()</a> function is used to set the movement threshold for\nthe <a href=\"#/p5/deviceMoved\">deviceMoved()</a> function. The default threshold is set to 0.5.</p>\n",
10116          "itemtype": "method",
10117          "name": "setMoveThreshold",
10118          "params": [{
10119            "name": "value",
10120            "description": "<p>The threshold value</p>\n",
10121            "type": "Number"
10122          }],
10123          "example": ["\n<div class=\"norender\">\n<code>\n// Run this example on a mobile device\n// You will need to move the device incrementally further\n// the closer the square's color gets to white in order to change the value.\n\nlet value = 0;\nlet threshold = 0.5;\nfunction setup() {\n  setMoveThreshold(threshold);\n}\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction deviceMoved() {\n  value = value + 5;\n  threshold = threshold + 0.1;\n  if (value > 255) {\n    value = 0;\n    threshold = 30;\n  }\n  setMoveThreshold(threshold);\n}\n</code>\n</div>"],
10124          "alt": "50x50 black rect in center of canvas. turns white on mobile when device moves",
10125          "class": "p5",
10126          "module": "Events",
10127          "submodule": "Acceleration"
10128        }, {
10129          "file": "src/events/acceleration.js",
10130          "line": 462,
10131          "description": "<p>The <a href=\"#/p5/setShakeThreshold\">setShakeThreshold()</a> function is used to set the movement threshold for\nthe <a href=\"#/p5/deviceShaken\">deviceShaken()</a> function. The default threshold is set to 30.</p>\n",
10132          "itemtype": "method",
10133          "name": "setShakeThreshold",
10134          "params": [{
10135            "name": "value",
10136            "description": "<p>The threshold value</p>\n",
10137            "type": "Number"
10138          }],
10139          "example": ["\n<div class=\"norender\">\n<code>\n// Run this example on a mobile device\n// You will need to shake the device more firmly\n// the closer the box's fill gets to white in order to change the value.\n\nlet value = 0;\nlet threshold = 30;\nfunction setup() {\n  setShakeThreshold(threshold);\n}\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction deviceMoved() {\n  value = value + 5;\n  threshold = threshold + 5;\n  if (value > 255) {\n    value = 0;\n    threshold = 30;\n  }\n  setShakeThreshold(threshold);\n}\n</code>\n</div>"],
10140          "alt": "50x50 black rect in center of canvas. turns white on mobile when device\nis being shaked",
10141          "class": "p5",
10142          "module": "Events",
10143          "submodule": "Acceleration"
10144        }, {
10145          "file": "src/events/acceleration.js",
10146          "line": 506,
10147          "description": "<p>The <a href=\"#/p5/deviceMoved\">deviceMoved()</a> function is called when the device is moved by more than\nthe threshold value along X, Y or Z axis. The default threshold is set to 0.5.\nThe threshold value can be changed using <a href=\"https://p5js.org/reference/#/p5/setMoveThreshold\">setMoveThreshold()</a>.</p>\n",
10148          "itemtype": "method",
10149          "name": "deviceMoved",
10150          "example": ["\n<div class=\"norender\">\n<code>\n// Run this example on a mobile device\n// Move the device around\n// to change the value.\n\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction deviceMoved() {\n  value = value + 5;\n  if (value > 255) {\n    value = 0;\n  }\n}\n</code>\n</div>"],
10151          "alt": "50x50 black rect in center of canvas. turns white on mobile when device moves",
10152          "class": "p5",
10153          "module": "Events",
10154          "submodule": "Acceleration"
10155        }, {
10156          "file": "src/events/acceleration.js",
10157          "line": 538,
10158          "description": "<p>The <a href=\"#/p5/deviceTurned\">deviceTurned()</a> function is called when the device rotates by\nmore than 90 degrees continuously.\n<br><br>\nThe axis that triggers the <a href=\"#/p5/deviceTurned\">deviceTurned()</a> method is stored in the turnAxis\nvariable. The <a href=\"#/p5/deviceTurned\">deviceTurned()</a> method can be locked to trigger on any axis:\nX, Y or Z by comparing the turnAxis variable to &#39;X&#39;, &#39;Y&#39; or &#39;Z&#39;.</p>\n",
10159          "itemtype": "method",
10160          "name": "deviceTurned",
10161          "example": ["\n<div class=\"norender\">\n<code>\n// Run this example on a mobile device\n// Rotate the device by 90 degrees\n// to change the value.\n\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction deviceTurned() {\n  if (value === 0) {\n    value = 255;\n  }
10161 else if (value === 255) {\n    value = 0;\n  }\n}\n</code>\n</div>\n<div>\n<code>\n// Run this example on a mobile device\n// Rotate the device by 90 degrees in the\n// X-axis to change the value.\n\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction deviceTurned() {\n  if (turnAxis === 'X') {\n    if (value === 0) {\n      value = 255;\n    } else if (value === 255) {\n      value = 0;\n    }\n  }\n}\n</code>\n</div>"],
10162          "alt": "50x50 black rect in center of canvas. turns white on mobile when device turns\n50x50 black rect in center of canvas. turns white on mobile when x-axis turns",
10163          "class": "p5",
10164          "module": "Events",
10165          "submodule": "Acceleration"
10166        }, {
10167          "file": "src/events/acceleration.js",
10168          "line": 597,
10169          "description": "<p>The <a href=\"#/p5/deviceShaken\">deviceShaken()</a> function is called when the device total acceleration\nchanges of accelerationX and accelerationY values is more than\nthe threshold value. The default threshold is set to 30.\nThe threshold value can be changed using <a href=\"https://p5js.org/reference/#/p5/setShakeThreshold\">setShakeThreshold()</a>.</p>\n",
10170          "itemtype": "method",
10171          "name": "deviceShaken",
10172          "example": ["\n<div class=\"norender\">\n<code>\n// Run this example on a mobile device\n// Shake the device to change the value.\n\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction deviceShaken() {\n  value = value + 5;\n  if (value > 255) {\n    value = 0;\n  }\n}\n</code>\n</div>"],
10173          "alt": "50x50 black rect in center of canvas. turns white on mobile when device shakes",
10174          "class": "p5",
10175          "module": "Events",
10176          "submodule": "Acceleration"
10177        }, {
10178          "file": "src/events/keyboard.js",
10179          "line": 18,
10180          "description": "<p>The boolean system variable <a href=\"#/p5/keyIsPressed\">keyIsPressed</a> is true if any key is pressed\nand false if no keys are pressed.</p>\n",
10181          "itemtype": "property",
10182          "name": "keyIsPressed",
10183          "type": "Boolean",
10184          "readonly": "",
10185          "example": ["\n<div>\n<code>\nfunction draw() {\n  if (keyIsPressed === true) {\n    fill(0);\n  } else {\n    fill(255);\n  }\n  rect(25, 25, 50, 50);\n}\n</code>\n</div>"],
10186          "alt": "50x50 white rect that turns black on keypress.",
10187          "class": "p5",
10188          "module": "Events",
10189          "submodule": "Keyboard"
10190        }, {
10191          "file": "src/events/keyboard.js",
10192          "line": 45,
10193          "description": "<p>The system variable key always contains the value of the most recent\nkey on the keyboard that was typed. To get the proper capitalization, it\nis best to use it within <a href=\"#/p5/keyTyped\">keyTyped()</a>. For non-ASCII keys, use the <a href=\"#/p5/keyCode\">keyCode</a>\nvariable.</p>\n",
10194          "itemtype": "property",
10195          "name": "key",
10196          "type": "String",
10197          "readonly": "",
10198          "example": ["\n<div><code>\n// Click any key to display it!\n// (Not Guaranteed to be Case Sensitive)\nfunction setup() {\n  fill(245, 123, 158);\n  textSize(50);\n}\n\nfunction draw() {\n  background(200);\n  text(key, 33, 65); // Display last key pressed.\n}\n</code></div>"],
10199          "alt": "canvas displays any key value that is pressed in pink font.",
10200          "class": "p5",
10201          "module": "Events",
10202          "submodule": "Keyboard"
10203        }, {
10204          "file": "src/events/keyboard.js",
10205          "line": 74,
10206          "description": "<p>The variable keyCode is used to detect special keys such as BACKSPACE,\nDELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW,\nDOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.\nYou can also check for custom keys by looking up the keyCode of any key\non a site like this: <a href=\"http://keycode.info/\">keycode.info</a>.</p>\n",
10207          "itemtype": "property",
10208          "name": "keyCode",
10209          "type": "Integer",
10210          "readonly": "",
10211          "example": ["\n<div><code>\nlet fillVal = 126;\nfunction draw() {\n  fill(fillVal);\n  rect(25, 25, 50, 50);\n}\n\nfunction keyPressed() {\n  if (keyCode === UP_ARROW) {\n    fillVal = 255;\n  } else if (keyCode === DOWN_ARROW) {\n    fillVal = 0;\n  }\n  return false; // prevent default\n}\n</code></div>"],
10212          "alt": "Grey rect center. turns white when up arrow pressed and black when down",
10213          "class": "p5",
10214          "module": "Events",
10215          "submodule": "Keyboard"
10216        }, {
10217          "file": "src/events/keyboard.js",
10218          "line": 107,
10219          "description": "<p>The <a href=\"#/p5/keyPressed\">keyPressed()</a> function is called once every time a key is pressed. The\nkeyCode for the key that was pressed is stored in the <a href=\"#/p5/keyCode\">keyCode</a> variable.\n<br><br>\nFor non-ASCII keys, use the keyCode variable. You can check if the keyCode\nequals BACKSPACE, DELETE, ENTE
10219R, RETURN, TAB, ESCAPE, SHIFT, CONTROL,\nOPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.\n<br><br>\nFor ASCII keys, the key that was pressed is stored in the key variable. However, it\ndoes not distinguish between uppercase and lowercase. For this reason, it\nis recommended to use <a href=\"#/p5/keyTyped\">keyTyped()</a> to read the key variable, in which the\ncase of the variable will be distinguished.\n<br><br>\nBecause of how operating systems handle key repeats, holding down a key\nmay cause multiple calls to <a href=\"#/p5/keyTyped\">keyTyped()</a> (and <a href=\"#/p5/keyReleased\">keyReleased()</a> as well). The\nrate of repeat is set by the operating system and how each computer is\nconfigured.<br><br>\nBrowsers may have different default\nbehaviors attached to various key events. To prevent any default\nbehavior for this event, add &quot;return false&quot; to the end of the method.</p>\n",
10220          "itemtype": "method",
10221          "name": "keyPressed",
10222          "example": ["\n<div>\n<code>\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction keyPressed() {\n  if (value === 0) {\n    value = 255;\n  } else {\n    value = 0;\n  }\n}\n</code>\n</div>\n<div>\n<code>\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction keyPressed() {\n  if (keyCode === LEFT_ARROW) {\n    value = 255;\n  } else if (keyCode === RIGHT_ARROW) {\n    value = 0;\n  }\n}\n</code>\n</div>\n<div class=\"norender\">\n<code>\nfunction keyPressed() {\n  // Do something\n  return false; // prevent any default behaviour\n}\n</code>\n</div>"],
10223          "alt": "black rect center. turns white when key pressed and black when released\nblack rect center. turns white when left arrow pressed and black when right.",
10224          "class": "p5",
10225          "module": "Events",
10226          "submodule": "Keyboard"
10227        }, {
10228          "file": "src/events/keyboard.js",
10229          "line": 194,
10230          "description": "<p>The <a href=\"#/p5/keyReleased\">keyReleased()</a> function is called once every time a key is released.\nSee <a href=\"#/p5/key\">key</a> and <a href=\"#/p5/keyCode\">keyCode</a> for more information.<br><br>\nBrowsers may have different default\nbehaviors attached to various key events. To prevent any default\nbehavior for this event, add &quot;return false&quot; to the end of the method.</p>\n",
10231          "itemtype": "method",
10232          "name": "keyReleased",
10233          "example": ["\n<div>\n<code>\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction keyReleased() {\n  if (value === 0) {\n    value = 255;\n  } else {\n    value = 0;\n  }\n  return false; // prevent any default behavior\n}\n</code>\n</div>"],
10234          "alt": "black rect center. turns white when key pressed and black when pressed again",
10235          "class": "p5",
10236          "module": "Events",
10237          "submodule": "Keyboard"
10238        }, {
10239          "file": "src/events/keyboard.js",
10240          "line": 246,
10241          "description": "<p>The <a href=\"#/p5/keyTyped\">keyTyped()</a> function is called once every time a key is pressed, but\naction keys such as Ctrl, Shift, and Alt are ignored. The most recent\nkey pressed will be stored in the key variable.\n<br><br>\nBecause of how operating systems handle key repeats, holding down a key\nwill cause multiple calls to <a href=\"#/p5/keyTyped\">keyTyped()</a> (and <a href=\"#/p5/keyReleased\">keyReleased()</a> as well). The\nrate of repeat is set by the operating system and how each computer is\nconfigured.<br><br>\nBrowsers may have different default behaviors attached to various key\nevents. To prevent any default behavior for this event, add &quot;return false&quot;\nto the end of the method.</p>\n",
10242          "itemtype": "method",
10243          "name": "keyTyped",
10244          "example": ["\n<div>\n<code>\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction keyTyped() {\n  if (key === 'a') {\n    value = 255;\n  } else if (key === 'b') {\n    value = 0;\n  }\n  // uncomment to prevent any default behavior\n  // return false;\n}\n</code>\n</div>"],
10245          "alt": "black rect center. turns white when 'a' key typed and black when 'b' pressed",
10246          "class": "p5",
10247          "module": "Events",
10248          "submodule": "Keyboard"
10249        }, {
10250          "file": "src/events/keyboard.js",
10251          "line": 300,
10252          "description": "<p>The onblur function is called when the user is no longer focused\non the p5 element. Because the keyup events will not fire if the user is\nnot focused on the element we must assume all keys currently down have\nbeen released.</p>\n",
10253          "class": "p5",
10254          "module": "Events",
10255          "submodule": "Keyboard"
10256        }, {
10257          "file": "src/events/keyboard.js",
10258          "line": 310,
10259          "description": "<p>The <a href=\"#/p5/keyIsDown\">keyIsDown()</a> function checks if the key is currently down, i.e. pressed.\nIt can be used if you have an object that moves, and you want several keys\nto be able to affect its behaviour simultaneously, such as moving a\nsprite diagonally. You can put in any number representing the keyCode of\nthe key, or use any of the variable <a href=\"#/p5/keyCode\">keyCode</a> names listed\n<a href=\"http://p5js.org/reference/#p5/keyCode\">here</a>.</p>\n",
10260          "itemtype": "method",
10261          "name": "keyIsDown",
10262          "params": [{
10263            "name": "code",
10264            "description": "<p>The key to check for.</p>\n",
10265            "type": "Number"
10266          }],
10267          "return": {
10268            "description": "whether key is down or not",
10269            "type": "Boolean"
10270          },
10271          "example": ["\n<div><code>\nlet x = 100;\nlet y = 100;\n\nfunction setup() {\n  createCanvas(512, 512);\n}\n\nfunction draw() {\n  if (keyIsDown(LEFT_ARROW)) {\n    x -= 5;\n  }\n\n  if (keyIsDown(RIGHT_ARROW)) {\n    x += 5;\n  }\n\n  if (keyIsDown(UP_ARROW)) {\n    y -= 5;\n  }\n\n  if (keyIsDown(DOWN_ARROW)) {\n    y += 5;\n  }\n\n  clear();\n  fill(255, 0, 0);\n  ellipse(x, y, 50, 50);\n}\n</code></div>\n\n<div><code>\nlet diameter = 50;\n\nfunction setup() {\n  createCanvas(512, 512);\n}\n\nfunction draw() {\n  // 107 and 187 are keyCodes for \"+\"\n  if (keyIsDown(107) || keyIsDown(187)) {\n    diameter += 1;\n  }
10271\n\n  // 109 and 189 are keyCodes for \"-\"\n  if (keyIsDown(109) || keyIsDown(189)) {\n    diameter -= 1;\n  }\n\n  clear();\n  fill(255, 0, 0);\n  ellipse(50, 50, diameter, diameter);\n}\n</code></div>"],
10272          "alt": "50x50 red ellipse moves left, right, up and down with arrow presses.\n50x50 red ellipse gets bigger or smaller when + or - are pressed.",
10273          "class": "p5",
10274          "module": "Events",
10275          "submodule": "Keyboard"
10276        }, {
10277          "file": "src/events/mouse.js",
10278          "line": 22,
10279          "description": "<p>The system variable mouseX always contains the current horizontal\nposition of the mouse, relative to (0, 0) of the canvas. If touch is\nused instead of mouse input, mouseX will hold the x value of the most\nrecent touch point.</p>\n",
10280          "itemtype": "property",
10281          "name": "mouseX",
10282          "type": "Number",
10283          "readonly": "",
10284          "example": ["\n<div>\n<code>\n// Move the mouse across the canvas\nfunction draw() {\n  background(244, 248, 252);\n  line(mouseX, 0, mouseX, 100);\n}\n</code>\n</div>"],
10285          "alt": "horizontal black line moves left and right with mouse x-position",
10286          "class": "p5",
10287          "module": "Events",
10288          "submodule": "Mouse"
10289        }, {
10290          "file": "src/events/mouse.js",
10291          "line": 48,
10292          "description": "<p>The system variable mouseY always contains the current vertical position\nof the mouse, relative to (0, 0) of the canvas. If touch is\nused instead of mouse input, mouseY will hold the y value of the most\nrecent touch point.</p>\n",
10293          "itemtype": "property",
10294          "name": "mouseY",
10295          "type": "Number",
10296          "readonly": "",
10297          "example": ["\n<div>\n<code>\n// Move the mouse across the canvas\nfunction draw() {\n  background(244, 248, 252);\n  line(0, mouseY, 100, mouseY);\n}\n</code>\n</div>"],
10298          "alt": "vertical black line moves up and down with mouse y-position",
10299          "class": "p5",
10300          "module": "Events",
10301          "submodule": "Mouse"
10302        }, {
10303          "file": "src/events/mouse.js",
10304          "line": 74,
10305          "description": "<p>The system variable pmouseX always contains the horizontal position of\nthe mouse or finger in the frame previous to the current frame, relative to\n(0, 0) of the canvas. Note: pmouseX will be reset to the current mouseX\nvalue at the start of each touch event.</p>\n",
10306          "itemtype": "property",
10307          "name": "pmouseX",
10308          "type": "Number",
10309          "readonly": "",
10310          "example": ["\n<div>\n<code>\n// Move the mouse across the canvas to leave a trail\nfunction setup() {\n  //slow down the frameRate to make it more visible\n  frameRate(10);\n}\n\nfunction draw() {\n  background(244, 248, 252);\n  line(mouseX, mouseY, pmouseX, pmouseY);\n  print(pmouseX + ' -> ' + mouseX);\n}\n</code>\n</div>"],
10311          "alt": "line trail is created from cursor movements. faster movement make longer line.",
10312          "class": "p5",
10313          "module": "Events",
10314          "submodule": "Mouse"
10315        }, {
10316          "file": "src/events/mouse.js",
10317          "line": 106,
10318          "description": "<p>The system variable pmouseY always contains the vertical position of the\nmouse or finger in the frame previous to the current frame, relative to\n(0, 0) of the canvas. Note: pmouseY will be reset to the current mouseY\nvalue at the start of each touch event.</p>\n",
10319          "itemtype": "property",
10320          "name": "pmouseY",
10321          "type": "Number",
10322          "readonly": "",
10323          "example": ["\n<div>\n<code>\nfunction draw() {\n  background(237, 34, 93);\n  fill(0);\n  //draw a square only if the mouse is not moving\n  if (mouseY === pmouseY && mouseX === pmouseX) {\n    rect(20, 20, 60, 60);\n  }\n\n  print(pmouseY + ' -> ' + mouseY);\n}\n</code>\n</div>"],
10324          "alt": "60x60 black rect center, fuschia background. rect flickers on mouse movement",
10325          "class": "p5",
10326          "module": "Events",
10327          "submodule": "Mouse"
10328        }, {
10329          "file": "src/events/mouse.js",
10330          "line": 137,
10331          "description": "<p>The system variable winMouseX always contains the current horizontal\nposition of the mouse, relative to (0, 0) of the window.</p>\n",
10332          "itemtype": "property",
10333          "name": "winMouseX",
10334          "type": "Number",
10335          "readonly": "",
10336          "example": ["\n<div>\n<code>\nlet myCanvas;\n\nfunction setup() {\n  //use a variable to store a pointer to the canvas\n  myCanvas = createCanvas(100, 100);\n}\n\nfunction draw() {\n  background(237, 34, 93);\n  fill(0);\n\n  //move the canvas to the horizontal mouse position\n  //rela                    tive to the window\n  myCanvas.position(winMouseX + 1, windowHeight / 2);\n\n  //the y of the square is relative to the canvas\n  rect(20, mouseY, 60, 60);\n}\n</code>\n</div>"],
10337          "alt": "60x60 black rect y moves with mouse y and fuschia canvas moves with mouse x",
10338          "class": "p5",
10339          "module": "Events",
10340          "submodule": "Mouse"
10341        }, {
10342          "file": "src/events/mouse.js",
10343          "line": 174,
10344          "description": "<p>The system variable winMouseY always contains the current vertical\nposition of the mouse, relative to (0, 0) of the window.</p>\n",
10345          "itemtype": "property",
10346          "name": "winMouseY",
10347          "type": "Number",
10348          "readonly": "",
10349          "example": ["\n<div>\n<code>\nlet myCanvas;\n\nfunction setup() {\n  //use a variable to store a pointer to the canvas\n  myCanvas = createCanvas(100, 100);\n}\n\nfunction draw() {\n  background(237, 34, 93);\n  fill(0);\n\n  //move the canvas to the vertical mouse position\n  //rel                    ative to the window\n  myCanvas.position(windowWidth / 2, winMouseY 
10349+ 1);\n\n  //the x of the square is relative to the canvas\n  rect(mouseX, 20, 60, 60);\n}\n</code>\n</div>"],
10350          "alt": "60x60 black rect x moves with mouse x and fuschia canvas y moves with mouse y",
10351          "class": "p5",
10352          "module": "Events",
10353          "submodule": "Mouse"
10354        }, {
10355          "file": "src/events/mouse.js",
10356          "line": 211,
10357          "description": "<p>The system variable pwinMouseX always contains the horizontal position\nof the mouse in the frame previous to the current frame, relative to\n(0, 0) of the window. Note: pwinMouseX will be reset to the current winMouseX\nvalue at the start of each touch event.</p>\n",
10358          "itemtype": "property",
10359          "name": "pwinMouseX",
10360          "type": "Number",
10361          "readonly": "",
10362          "example": ["\n<div>\n<code>\nlet myCanvas;\n\nfunction setup() {\n  //use a variable to store a pointer to the canvas\n  myCanvas = createCanvas(100, 100);\n  noStroke();\n  fill(237, 34, 93);\n}\n\nfunction draw() {\n  clear();\n  //the difference between previous and\n  //current x position is the horizontal mouse speed\n  let speed = abs(winMouseX - pwinMouseX);\n  //change the size of the circle\n  //according to the horizontal speed\n  ellipse(50, 50, 10 + speed * 5, 10 + speed * 5);\n  //move the canvas to the mouse position\n  myCanvas.position(winMouseX + 1, winMouseY + 1);\n}\n</code>\n</div>"],
10363          "alt": "fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed",
10364          "class": "p5",
10365          "module": "Events",
10366          "submodule": "Mouse"
10367        }, {
10368          "file": "src/events/mouse.js",
10369          "line": 252,
10370          "description": "<p>The system variable pwinMouseY always contains the vertical position of\nthe mouse in the frame previous to the current frame, relative to (0, 0)\nof the window. Note: pwinMouseY will be reset to the current winMouseY\nvalue at the start of each touch event.</p>\n",
10371          "itemtype": "property",
10372          "name": "pwinMouseY",
10373          "type": "Number",
10374          "readonly": "",
10375          "example": ["\n<div>\n<code>\nlet myCanvas;\n\nfunction setup() {\n  //use a variable to store a pointer to the canvas\n  myCanvas = createCanvas(100, 100);\n  noStroke();\n  fill(237, 34, 93);\n}\n\nfunction draw() {\n  clear();\n  //the difference between previous and\n  //current y position is the vertical mouse speed\n  let speed = abs(winMouseY - pwinMouseY);\n  //change the size of the circle\n  //according to the vertical speed\n  ellipse(50, 50, 10 + speed * 5, 10 + speed * 5);\n  //move the canvas to the mouse position\n  myCanvas.position(winMouseX + 1, winMouseY + 1);\n}\n</code>\n</div>"],
10376          "alt": "fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed",
10377          "class": "p5",
10378          "module": "Events",
10379          "submodule": "Mouse"
10380        }, {
10381          "file": "src/events/mouse.js",
10382          "line": 294,
10383          "description": "<p>Processing automatically tracks if the mouse button is pressed and which\nbutton is pressed. The value of the system variable mouseButton is either\nLEFT, RIGHT, or CENTER depending on which button was pressed last.\nWarning: different browsers may track mouseButton differently.</p>\n",
10384          "itemtype": "property",
10385          "name": "mouseButton",
10386          "type": "Constant",
10387          "readonly": "",
10388          "example": ["\n<div>\n<code>\nfunction draw() {\n  background(237, 34, 93);\n  fill(0);\n\n  if (mouseIsPressed) {\n    if (mouseButton === LEFT) {\n      ellipse(50, 50, 50, 50);\n    }\n    if (mouseButton === RIGHT) {\n      rect(25, 25, 50, 50);\n    }\n    if (mouseButton === CENTER) {\n      triangle(23, 75, 50, 20, 78, 75);\n    }\n  }\n\n  print(mouseButton);\n}\n</code>\n</div>"],
10389          "alt": "50x50 black ellipse appears on center of fuschia canvas on mouse click/press.",
10390          "class": "p5",
10391          "module": "Events",
10392          "submodule": "Mouse"
10393        }, {
10394          "file": "src/events/mouse.js",
10395          "line": 333,
10396          "description": "<p>The boolean system variable mouseIsPressed is true if the mouse is pressed\nand false if not.</p>\n",
10397          "itemtype": "property",
10398          "name": "mouseIsPressed",
10399          "type": "Boolean",
10400          "readonly": "",
10401          "example": ["\n<div>\n<code>\nfunction draw() {\n  background(237, 34, 93);\n  fill(0);\n\n  if (mouseIsPressed) {\n    ellipse(50, 50, 50, 50);\n  } else {\n    rect(25, 25, 50, 50);\n  }\n\n  print(mouseIsPressed);\n}\n</code>\n</div>"],
10402          "alt": "black 50x50 rect becomes ellipse with mouse click/press. fuschia background.",
10403          "class": "p5",
10404          "module": "Events",
10405          "submodule": "Mouse"
10406        }, {
10407          "file": "src/events/mouse.js",
10408          "line": 424,
10409          "description": "<p>The <a href=\"#/p5/mouseMoved\">mouseMoved()</a> function is called every time the mouse moves and a mouse\nbutton is not pressed.<br><br>\nBrowsers may have different default\nbehaviors attached to various mouse events. To prevent any default\nbehavior for this event, add &quot;return false&quot; to the end of the method.</p>\n",
10410          "itemtype": "method",
10411          "name": "mouseMoved",
10412          "params": [{
10413            "name": "event",
10414            "description": "<p>optional MouseEvent callback argument.</p>\n",
10415            "type": "Object",
10416            "optional": true
10417          }],
10418          "example": ["\n<div>\n<code>\n// Move the mouse across the page\n// to change its value\n\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction mouseMoved() {\n  value = value + 5;\n  if (value > 255) {\n    value = 0;\n  }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction mouseMoved() {\n  ellipse(mouseX, mouseY, 5, 5);\n  // prevent default\n  return false;\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// returns a MouseEvent object\n// as a callback argument\nfunction mouseMoved(event) {\n  console.log(event);\n}\n</code>\n</div>"],
10419          "alt": "black 50x50 rect becomes lighter with mouse movements until white then resets\nno image displayed",
10420          "class": "p5",
10421          "module": "Events",
10422          "submodule": "Mouse"
10423        }, {
10424          "file": "src/events/mouse.js",
10425          "line": 479,
10426          "description": "<p>The <a href=\"#/p5/mouseDragged\">mouseDragged()</a> function is called once every time the mouse moves and\na mouse button is pressed. If no <a href=\"#/p5/mouseDragged\">mouseDragged()</a> function is defined, the\n<a href=\"#/p5/touchMoved\">touchMoved()</a> function will be called instead if it is defined.<br><br>\nBrowsers may have different default\nbehaviors attached to various mouse events. To prevent any default\nbehavior for this event, add &quot;return false&quot; to the end of the method.</p>\n",
10427          "itemtype": "method",
10428          "name": "mouseDragged",
10429          "params": [{
10430            "name": "event",
10431            "description": "<p>optional MouseEvent callback argument.</p>\n",
10432            "type": "Object",
10433            "optional": true
10434          }],
10435          "example": ["\n<div>\n<code>\n// Drag the mouse across the page\n// to change its value\n\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction mouseDragged() {\n  value = value + 5;\n  if (value > 255) {\n    value = 0;\n  }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction mouseDragged() {\n  ellipse(mouseX, mouseY, 5, 5);\n  // prevent default\n  return false;\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// returns a MouseEvent object\n// as a callback argument\nfunction mouseDragged(event) {\n  console.log(event);\n}\n</code>\n</div>"],
10436          "alt": "black 50x50 rect turns lighter with mouse click and drag until white, resets\nno image displayed",
10437          "class": "p5",
10438          "module": "Events",
10439          "submodule": "Mouse"
10440        }, {
10441          "file": "src/events/mouse.js",
10442          "line": 560,
10443          "description": "<p>The <a href=\"#/p5/mousePressed\">mousePressed()</a> function is called once after every time a mouse button\nis pressed. The mouseButton variable (see the related reference entry)\ncan be used to determine which button has been pressed. If no\n<a href=\"#/p5/mousePressed\">mousePressed()</a> function is defined, the <a href=\"#/p5/touchStarted\">touchStarted()</a> function will be\ncalled instead if it is defined.<br><br>\nBrowsers may have different default\nbehaviors attached to various mouse events. To prevent any default\nbehavior for this event, add &quot;return false&quot; to the end of the method.</p>\n",
10444          "itemtype": "method",
10445          "name": "mousePressed",
10446          "params": [{
10447            "name": "event",
10448            "description": "<p>optional MouseEvent callback argument.</p>\n",
10449            "type": "Object",
10450            "optional": true
10451          }],
10452          "example": ["\n<div>\n<code>\n// Click within the image to change\n// the value of the rectangle\n\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction mousePressed() {\n  if (value === 0) {\n    value = 255;\n  } else {\n    value = 0;\n  }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction mousePressed() {\n  ellipse(mouseX, mouseY, 5, 5);\n  // prevent default\n  return false;\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// returns a MouseEvent object\n// as a callback argument\nfunction mousePressed(event) {\n  console.log(event);\n}\n</code>\n</div>"],
10453          "alt": "black 50x50 rect turns white with mouse click/press.\nno image displayed",
10454          "class": "p5",
10455          "module": "Events",
10456          "submodule": "Mouse"
10457        }, {
10458          "file": "src/events/mouse.js",
10459          "line": 637,
10460          "description": "<p>The <a href=\"#/p5/mouseReleased\">mouseReleased()</a> function is called every time a mouse button is\nreleased. If no <a href=\"#/p5/mouseReleased\">mouseReleased()</a> function is defined, the <a href=\"#/p5/touchEnded\">touchEnded()</a>\nfunction will be called instead if it is defined.<br><br>\nBrowsers may have different default\nbehaviors attached to various mouse events. To prevent any default\nbehavior for this event, add &quot;return false&quot; to the end of the method.</p>\n",
10461          "itemtype": "method",
10462          "name": "mouseReleased",
10463          "params": [{
10464            "name": "event",
10465            "description": "<p>optional MouseEvent callback argument.</p>\n",
10466            "type": "Object",
10467            "optional": true
10468          }],
10469          "example": ["\n<div>\n<code>\n// Click within the image to change\n// the value of the rectangle\n// after the mouse has been clicked\n\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction mouseReleased() {\n  if (value === 0) {\n    value = 255;\n  } else {\n    value = 0;\n  }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction mouseReleased() {\n  ellipse(mouseX, mouseY, 5, 5);\n  // prevent default\n  return false;\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// returns a MouseEvent object\n// as a callback argument\nfunction mouseReleased(event) {\n  console.log(event);\n}\n</code>\n</div>"],
10470          "alt": "black 50x50 rect turns white with mouse click/press.\nno image displayed",
10471          "class": "p5",
10472          "module": "Events",
10473          "submodule": "Mouse"
10474        }, {
10475          "file": "src/events/mouse.js",
10476          "line": 715,
10477          "description": "<p>The <a href=\"#/p5/mouseClicked\">mouseClicked()</a> function is called once after a mouse button has been\npressed and then released.<br><br>\nBrowsers handle clicks differently, so this function is only guaranteed to be\nrun when the left mouse button is clicked. To handle other mouse buttons\nbeing pressed or released, see <a href=\"#/p5/mousePressed\">mousePressed()</a> or <a href=\"#/p5/mouseReleased\">mouseReleased()</a>.<br><br>\nBrowsers may have different default\nbehaviors attached to various mouse events. To prevent any default\nbehavior for this event, add &quot;return false&quot; to the end of the method.</p>\n",
10478          "itemtype": "method",
10479          "name": "mouseClicked",
10480          "params": [{
10481            "name": "event",
10482            "description": "<p>optional MouseEvent callback argument.</p>\n",
10483            "type": "Object",
10484            "optional": true
10485          }],
10486          "example": ["\n<div>\n<code>\n// Click within the image to change\n// the value of the rectangle\n// after the mouse has been clicked\n\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\n\nfunction mouseClicked() {\n  if (value === 0) {\n    value = 255;\n  } else {\n    value = 0;\n  }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction mouseClicked() {\n  ellipse(mouseX, mouseY, 5, 5);\n  // prevent default\n  return false;\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// returns a MouseEvent object\n// as a callback argument\nfunction mouseClicked(event) {\n  console.log(event);\n}\n</code>\n</div>"],
10487          "alt": "black 50x50 rect turns white with mouse click/press.\nno image displayed",
10488          "class": "p5",
10489          "module": "Events",
10490          "submodule": "Mouse"
10491        }, {
10492          "file": "src/events/mouse.js",
10493          "line": 785,
10494          "description": "<p>The <a href=\"#/p5/doubleClicked\">doubleClicked()</a> function is executed every time a event\nlistener has detected a dblclick event which is a part of the\nDOM L3 specification. The doubleClicked event is fired when a\npointing device button (usually a mouse&#39;s primary button)\nis clicked twice on a single element. For more info on the\ndblclick event refer to mozilla&#39;s documentation here:\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/Events/dblclick\">https://developer.mozilla.org/en-US/docs/Web/Events/dblclick</a></p>\n",
10495          "itemtype": "method",
10496          "name": "doubleClicked",
10497          "params": [{
10498            "name": "event",
10499            "description": "<p>optional MouseEvent callback argument.</p>\n",
10500            "type": "Object",
10501            "optional": true
10502          }],
10503          "example": ["\n<div>\n<code>\n// Click within the image to change\n// the value of the rectangle\n/
10503/ after the mouse has been double clicked\n\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\n\nfunction doubleClicked() {\n  if (value === 0) {\n    value = 255;\n  } else {\n    value = 0;\n  }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction doubleClicked() {\n  ellipse(mouseX, mouseY, 5, 5);\n  // prevent default\n  return false;\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// returns a MouseEvent object\n// as a callback argument\nfunction doubleClicked(event) {\n  console.log(event);\n}\n</code>\n</div>"],
10504          "alt": "black 50x50 rect turns white with mouse doubleClick/press.\nno image displayed",
10505          "class": "p5",
10506          "module": "Events",
10507          "submodule": "Mouse"
10508        }, {
10509          "file": "src/events/mouse.js",
10510          "line": 870,
10511          "description": "<p>The function <a href=\"#/p5/mouseWheel\">mouseWheel()</a> is executed every time a vertical mouse wheel\nevent is detected either triggered by an actual mouse wheel or by a\ntouchpad.<br><br>\nThe event.delta property returns the amount the mouse wheel\nhave scrolled. The values can be positive or negative depending on the\nscroll direction (on OS X with &quot;natural&quot; scrolling enabled, the signs\nare inverted).<br><br>\nBrowsers may have different default behaviors attached to various\nmouse events. To prevent any default behavior for this event, add\n&quot;return false&quot; to the end of the method.<br><br>\nDue to the current support of the &quot;wheel&quot; event on Safari, the function\nmay only work as expected if &quot;return false&quot; is included while using Safari.</p>\n",
10512          "itemtype": "method",
10513          "name": "mouseWheel",
10514          "params": [{
10515            "name": "event",
10516            "description": "<p>optional WheelEvent callback argument.</p>\n",
10517            "type": "Object",
10518            "optional": true
10519          }],
10520          "example": ["\n<div>\n<code>\nlet pos = 25;\n\nfunction draw() {\n  background(237, 34, 93);\n  fill(0);\n  rect(25, pos, 50, 50);\n}\n\nfunction mouseWheel(event) {\n  print(event.delta);\n  //move the square according to the vertical scroll amount\n  pos += event.delta;\n  //uncomment to block page scrolling\n  //return false;\n}\n</code>\n</div>"],
10521          "alt": "black 50x50 rect moves up and down with vertical scroll. fuschia background",
10522          "class": "p5",
10523          "module": "Events",
10524          "submodule": "Mouse"
10525        }, {
10526          "file": "src/events/touch.js",
10527          "line": 12,
10528          "description": "<p>The system variable touches[] contains an array of the positions of all\ncurrent touch points, relative to (0, 0) of the canvas, and IDs identifying a\nunique touch as it moves. Each element in the array is an object with x, y,\nand id properties.</p>\n<p>The touches[] array is not supported on Safari and IE on touch-based\ndesktops (laptops).</p>\n",
10529          "itemtype": "property",
10530          "name": "touches",
10531          "type": "Object[]",
10532          "readonly": "",
10533          "example": ["\n<div>\n<code>\n// On a touchscreen device, touch\n// the canvas using one or more fingers\n// at the same time\nfunction draw() {\n  clear();\n  let display = touches.length + ' touches';\n  text(display, 5, 10);\n}\n</code>\n</div>"],
10534          "alt": "Number of touches currently registered are displayed on the canvas",
10535          "class": "p5",
10536          "module": "Events",
10537          "submodule": "Touch"
10538        }, {
10539          "file": "src/events/touch.js",
10540          "line": 74,
10541          "description": "<p>The touchStarted() function is called once after every time a touch is\nregistered. If no <a href=\"#/p5/touchStarted\">touchStarted()</a> function is defined, the <a href=\"#/p5/mousePressed\">mousePressed()</a>\nfunction will be called instead if it is defined.<br><br>\nBrowsers may have different default behaviors attached to various touch\nevents. To prevent any default behavior for this event, add &quot;return false&quot;\nto the end of the method.</p>\n",
10542          "itemtype": "method",
10543          "name": "touchStarted",
10544          "params": [{
10545            "name": "event",
10546            "description": "<p>optional TouchEvent callback argument.</p>\n",
10547            "type": "Object",
10548            "optional": true
10549          }],
10550          "example": ["\n<div>\n<code>\n// Touch within the image to change\n// the value of the rectangle\n\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}
10550\nfunction touchStarted() {\n  if (value === 0) {\n    value = 255;\n  } else {\n    value = 0;\n  }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction touchStarted() {\n  ellipse(mouseX, mouseY, 5, 5);\n  // prevent default\n  return false;\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// returns a TouchEvent object\n// as a callback argument\nfunction touchStarted(event) {\n  console.log(event);\n}\n</code>\n</div>"],
10551          "alt": "50x50 black rect turns white with touch event.\nno image displayed",
10552          "class": "p5",
10553          "module": "Events",
10554          "submodule": "Touch"
10555        }, {
10556          "file": "src/events/touch.js",
10557          "line": 149,
10558          "description": "<p>The <a href=\"#/p5/touchMoved\">touchMoved()</a> function is called every time a touch move is registered.\nIf no <a href=\"#/p5/touchMoved\">touchMoved()</a> function is defined, the <a href=\"#/p5/mouseDragged\">mouseDragged()</a> function will\nbe called instead if it is defined.<br><br>\nBrowsers may have different default behaviors attached to various touch\nevents. To prevent any default behavior for this event, add &quot;return false&quot;\nto the end of the method.</p>\n",
10559          "itemtype": "method",
10560          "name": "touchMoved",
10561          "params": [{
10562            "name": "event",
10563            "description": "<p>optional TouchEvent callback argument.</p>\n",
10564            "type": "Object",
10565            "optional": true
10566          }],
10567          "example": ["\n<div>\n<code>\n// Move your finger across the page\n// to change its value\n\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction touchMoved() {\n  value = value + 5;\n  if (value > 255) {\n    value = 0;\n  }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction touchMoved() {\n  ellipse(mouseX, mouseY, 5, 5);\n  // prevent default\n  return false;\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// returns a TouchEvent object\n// as a callback argument\nfunction touchMoved(event) {\n  console.log(event);\n}\n</code>\n</div>"],
10568          "alt": "50x50 black rect turns lighter with touch until white. resets\nno image displayed",
10569          "class": "p5",
10570          "module": "Events",
10571          "submodule": "Touch"
10572        }, {
10573          "file": "src/events/touch.js",
10574          "line": 222,
10575          "description": "<p>The <a href=\"#/p5/touchEnded\">touchEnded()</a> function is called every time a touch ends. If no\n<a href=\"#/p5/touchEnded\">touchEnded()</a> function is defined, the <a href=\"#/p5/mouseReleased\">mouseReleased()</a> function will be\ncalled instead if it is defined.<br><br>\nBrowsers may have different default behaviors attached to various touch\nevents. To prevent any default behavior for this event, add &quot;return false&quot;\nto the end of the method.</p>\n",
10576          "itemtype": "method",
10577          "name": "touchEnded",
10578          "params": [{
10579            "name": "event",
10580            "description": "<p>optional TouchEvent callback argument.</p>\n",
10581            "type": "Object",
10582            "optional": true
10583          }],
10584          "example": ["\n<div>\n<code>\n// Release touch within the image to\n// change the value of the rectangle\n\nlet value = 0;\nfunction draw() {\n  fill(value);\n  rect(25, 25, 50, 50);\n}\nfunction touchEnded() {\n  if (value === 0) {\n    value = 255;\n  } else {\n    value = 0;\n  }\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nfunction touchEnded() {\n  ellipse(mouseX, mouseY, 5, 5);\n  // prevent default\n  return false;\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// returns a TouchEvent object\n// as a callback argument\nfunction touchEnded(event) {\n  console.log(event);\n}\n</code>\n</div>"],
10585          "alt": "50x50 black rect turns white with touch.\nno image displayed",
10586          "class": "p5",
10587          "module": "Events",
10588          "submodule": "Touch"
10589        }, {
10590          "file": "src/image/filters.js",
10591          "line": 3,
10592          "description": "<p>This module defines the filters for use with image buffers.</p>\n<p>This module is basically a collection of functions stored in an object\nas opposed to modules. The functions are destructive, modifying\nthe passed in canvas rather than creating a copy.</p>\n<p>Generally speaking users of this module will use the Filters.apply method\non a canvas to create an effect.</p>\n<p>A number of functions are borrowed/adapted from\n<a href=\"http://www.html5rocks.com/en/tutorials/canvas/imagefilters/\">http://www.html5rocks.com/en/tutorials/canvas/imagefilters/</a>\nor the java processing implementation.</p>\n",
10593          "class": "p5",
10594          "module": "Events"
10595        }, {
10596          "file": "src/image/image.js",
10597          "line": 8,
10598          "description": "<p>This module defines the p5 methods for the <a href=\"#/p5.Image\">p5.Image</a> class\nfor drawing images to the main display canvas.</p>\n",
10599          "class": "p5",
10600          "module": "Image",
10601          "submodule": "Image"
10602        }, {
10603          "file": "src/image/image.js",
10604          "line": 22,
10605          "description": "<p>Creates a new <a href=\"#/p5.Image\">p5.Image</a> (the datatype for storing images). This provides a\nfresh buffer of pixels to play with. Set the size of the buffer with the\nwidth and height parameters.\n<br><br>\n.<a href=\"#/p5.Image/pixels\">pixels</a> gives access to an array containing the values for all the pixels\nin the display window.\nThese values are numbers. This array is the size (including an appropriate\nfactor for the <a href=\"#/p5/pixelDensity\">pixelDensity</a>) of the display window x4,\nrepresenting the R, G, B, A values in order for each pixel, mov
10605ing from\nleft to right across each row, then down each column. See .<a href=\"#/p5.Image/pixels\">pixels</a> for\nmore info. It may also be simpler to use <a href=\"#/p5.Image/set\">set()</a> or <a href=\"#/p5.Image/get\">get()</a>.\n<br><br>\nBefore accessing the pixels of an image, the data must loaded with the\n<a href=\"#/p5.Image/loadPixels\">loadPixels()</a> function. After the array data has been modified, the\n<a href=\"#/p5.Image/updatePixels\">updatePixels()</a> function must be run to update the changes.</p>\n",
10606          "itemtype": "method",
10607          "name": "createImage",
10608          "params": [{
10609            "name": "width",
10610            "description": "<p>width in pixels</p>\n",
10611            "type": "Integer"
10612          }, {
10613            "name": "height",
10614            "description": "<p>height in pixels</p>\n",
10615            "type": "Integer"
10616          }],
10617          "return": {
10618            "description": "the <a href=\"#/p5.Image\">p5.Image</a> object",
10619            "type": "p5.Image"
10620          },
10621          "example": ["\n<div>\n<code>\nlet img = createImage(66, 66);\nimg.loadPixels();\nfor (let i = 0; i < img.width; i++) {\n  for (let j = 0; j < img.height; j++) {\n    img.set(i, j, color(0, 90, 102));\n  }\n}\nimg.updatePixels();\nimage(img, 17, 17);\n</code>\n</div>\n\n<div>\n<code>\nlet img = createImage(66, 66);\nimg.loadPixels();\nfor (let i = 0; i < img.width; i++) {\n  for (let j = 0; j < img.height; j++) {\n    img.set(i, j, color(0, 90, 102, (i % img.width) * 2));\n  }\n}\nimg.updatePixels();\nimage(img, 17, 17);\nimage(img, 34, 34);\n</code>\n</div>\n\n<div>\n<code>\nlet pink = color(255, 102, 204);\nlet img = createImage(66, 66);\nimg.loadPixels();\nlet d = pixelDensity();\nlet halfImage = 4 * (img.width * d) * (img.height / 2 * d);\nfor (let i = 0; i < halfImage; i += 4) {\n  img.pixels[i] = red(pink);\n  img.pixels[i + 1] = green(pink);\n  img.pixels[i + 2] = blue(pink);\n  img.pixels[i + 3] = alpha(pink);\n}\nimg.updatePixels();\nimage(img, 17, 17);\n</code>\n</div>"],
10622          "alt": "66x66 dark turquoise rect in center of canvas.\n2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas\nno image displayed",
10623          "class": "p5",
10624          "module": "Image",
10625          "submodule": "Image"
10626        }, {
10627          "file": "src/image/image.js",
10628          "line": 102,
10629          "description": "<p>Save the current canvas as an image. The browser will either save the\nfile immediately, or prompt the user with a dialogue window.</p>\n",
10630          "itemtype": "method",
10631          "name": "saveCanvas",
10632          "example": ["\n <div class='norender notest'><code>\n function setup() {\n let c = createCanvas(100, 100);\n background(255, 0, 0);\n saveCanvas(c, 'myCanvas', 'jpg');\n }\n </code></div>\n <div class='norender notest'><code>\n // note that this example has the same result as above\n // if no canvas is specified, defaults to main canvas\n function setup() {\n let c = createCanvas(100, 100);\n background(255, 0, 0);\n saveCanvas('myCanvas', 'jpg');\n\n // all of the following are valid\n saveCanvas(c, 'myCanvas', 'jpg');\n saveCanvas(c, 'myCanvas.jpg');\n saveCanvas(c, 'myCanvas');\n saveCanvas(c);\n saveCanvas('myCanvas', 'png');\n saveCanvas('myCanvas');\n saveCanvas();\n }\n </code></div>"],
10633          "alt": "no image displayed\n no image displayed\n no image displayed",
10634          "class": "p5",
10635          "module": "Image",
10636          "submodule": "Image",
10637          "overloads": [{
10638            "line": 102,
10639            "params": [{
10640              "name": "selectedCanvas",
10641              "description": "<p>a variable\n                                representing a specific html5 canvas (optional)</p>\n",
10642              "type": "p5.Element|HTMLCanvasElement"
10643            }, {
10644              "name": "filename",
10645              "description": "",
10646              "type": "String",
10647              "optional": true
10648            }, {
10649              "name": "extension",
10650              "description": "<p>&#39;jpg&#39; or &#39;png&#39;</p>\n",
10651              "type": "String",
10652              "optional": true
10653            }]
10654          }, {
10655            "line": 144,
10656            "params": [{
10657              "name": "filename",
10658              "description": "",
10659              "type": "String",
10660              "optional": true
10661            }, {
10662              "name": "extension",
10663              "description": "",
10664              "type": "String",
10665              "optional": true
10666            }]
10667          }]
10668        }, {
10669          "file": "src/image/image.js",
10670          "line": 195,
10671          "description": "<p>Capture a sequence of frames that can be used to create a movie.\nAccepts a callback. For example, you may wish to 
10671send the frames\nto a server where they can be stored or converted into a movie.\nIf no callback is provided, the browser will pop up save dialogues in an\nattempt to download all of the images that have just been created. With the\ncallback provided the image data isn&#39;t saved by default but instead passed\nas an argument to the callback function as an array of objects, with the\nsize of array equal to the total number of frames.</p>\n<p>Note that <a href=\"#/p5.Image/saveFrames\">saveFrames()</a> will only save the first 15 frames of an animation.\nTo export longer animations, you might look into a library like\n<a href=\"https://github.com/spite/ccapture.js/\">ccapture.js</a>.</p>\n",
10672          "itemtype": "method",
10673          "name": "saveFrames",
10674          "params": [{
10675            "name": "filename",
10676            "description": "",
10677            "type": "String"
10678          }, {
10679            "name": "extension",
10680            "description": "<p>&#39;jpg&#39; or &#39;png&#39;</p>\n",
10681            "type": "String"
10682          }, {
10683            "name": "duration",
10684            "description": "<p>Duration in seconds to save the frames for.</p>\n",
10685            "type": "Number"
10686          }, {
10687            "name": "framerate",
10688            "description": "<p>Framerate to save the frames in.</p>\n",
10689            "type": "Number"
10690          }, {
10691            "name": "callback",
10692            "description": "<p>A callback function that will be executed\n                                to handle the image data. This function\n                                should accept an array as argument. The\n                                array will contain the specified number of\n                                frames of objects. Each object has three\n                                properties: imageData - an\n                                image/octet-stream, filename and extension.</p>\n",
10693            "type": "Function(Array)",
10694            "optional": true
10695          }],
10696          "example": ["\n<div><code>\n function draw() {\n background(mouseX);\n }\n\n function mousePressed() {\n saveFrames('out', 'png', 1, 25, data => {\n   print(data);\n });\n }\n</code></div>"],
10697          "alt": "canvas background goes from light to dark with mouse x.",
10698          "class": "p5",
10699          "module": "Image",
10700          "submodule": "Image"
10701        }, {
10702          "file": "src/image/loading_displaying.js",
10703          "line": 17,
10704          "description": "<p>Loads an image from a path and creates a <a href=\"#/p5.Image\">p5.Image</a> from it.\n<br><br>\nThe image may not be immediately available for rendering\nIf you want to ensure that the image is ready before doing\nanything with it, place the <a href=\"#/p5/loadImage\">loadImage()</a> call in <a href=\"#/p5/preload\">preload()</a>.\nYou may also supply a callback function to handle the image when it&#39;s ready.\n<br><br>\nThe path to the image should be relative to the HTML file\nthat links in your sketch. Loading an image from a URL or other\nremote location may be blocked due to your browser&#39;s built-in\nsecurity.</p>\n",
10705          "itemtype": "method",
10706          "name": "loadImage",
10707          "params": [{
10708            "name": "path",
10709            "description": "<p>Path of the image to be loaded</p>\n",
10710            "type": "String"
10711          }, {
10712            "name": "successCallback",
10713            "description": "<p>Function to be called once\n                               the image is loaded. Will be passed the\n                               <a href=\"#/p5.Image\">p5.Image</a>.</p>\n",
10714            "type": "function(p5.Image)",
10715            "optional": true
10716          }, {
10717            "name": "failureCallback",
10718            "description": "<p>called with event error if\n                               the image fails to load.</p>\n",
10719            "type": "Function(Event)",
10720            "optional": true
10721          }],
10722          "return": {
10723            "description": "the <a href=\"#/p5.Image\">p5.Image</a> object",
10724            "type": "p5.Image"
10725          },
10726          "example": ["\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/laDefense.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n}\n</code>\n</div>\n<div>\n<code>\nfunction setup() {\n  // here we use a callback to display the image after loading\n  loadImage('assets/laDefense.jpg', img => {\n    image(img, 0, 0);\n  });\n}\n</code>\n</div>"],
10727          "alt": "image of the underside of a white umbrella and grided ceililng above\nimage of the underside of a white umbrella and grided ceililng above",
10728          "class": "p5",
10729          "module": "Image",
10730          "submodule": "Loading & Displaying"
10731        }, {
10732          "file": "src/image/loading_displaying.js",
10733          "line": 127,
10734          "description": "<p>Draw an image to the p5.js canvas.</p>\n<p>This function can be used with different numbers of parameters. The\nsimplest use requires only three parameters: img, x, and 
10734y—where (x, y) is\nthe position of the image. Two more parameters can optionally be added to\nspecify the width and height of the image.</p>\n<p>This function can also be used with all eight Number parameters. To\ndifferentiate between all these parameters, p5.js uses the language of\n&quot;destination rectangle&quot; (which corresponds to &quot;dx&quot;, &quot;dy&quot;, etc.) and &quot;source\nimage&quot; (which corresponds to &quot;sx&quot;, &quot;sy&quot;, etc.) below. Specifying the\n&quot;source image&quot; dimensions can be useful when you want to display a\nsubsection of the source image instead of the whole thing. Here&#39;s a diagram\nto explain further:\n<img src=\"assets/drawImage.png\"></img></p>\n",
10735          "itemtype": "method",
10736          "name": "image",
10737          "example": ["\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/laDefense.jpg');\n}\nfunction setup() {\n  // Top-left corner of the img is at (0, 0)\n  // Width and height are the img's original width and height\n  image(img, 0, 0);\n}\n</code>\n</div>\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/laDefense.jpg');\n}\nfunction setup() {\n  background(50);\n  // Top-left corner of the img is at (10, 10)\n  // Width and height are 50 x 50\n  image(img, 10, 10, 50, 50);\n}\n</code>\n</div>\n<div>\n<code>\nfunction setup() {\n  // Here, we use a callback to display the image after loading\n  loadImage('assets/laDefense.jpg', img => {\n    image(img, 0, 0);\n  });\n}\n</code>\n</div>\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/gradient.png');\n}\nfunction setup() {\n  // 1. Background image\n  // Top-left corner of the img is at (0, 0)\n  // Width and height are the img's original width and height, 100 x 100\n  image(img, 0, 0);\n  // 2. Top right image\n  // Top-left corner of destination rectangle is at (50, 0)\n  // Destination rectangle width and height are 40 x 20\n  // The next parameters are relative to the source image:\n  // - Starting at position (50, 50) on the source image, capture a 50 x 50\n  // subsection\n  // - Draw this subsection to fill the dimensions of the destination rectangle\n  image(img, 50, 0, 40, 20, 50, 50, 50, 50);\n}\n</code>\n</div>"],
10738          "alt": "image of the underside of a white umbrella and gridded ceiling above\nimage of the underside of a white umbrella and gridded ceiling above",
10739          "class": "p5",
10740          "module": "Image",
10741          "submodule": "Loading & Displaying",
10742          "overloads": [{
10743            "line": 127,
10744            "params": [{
10745              "name": "img",
10746              "description": "<p>the image to display</p>\n",
10747              "type": "p5.Image|p5.Element"
10748            }, {
10749              "name": "x",
10750              "description": "<p>the x-coordinate of the top-left corner of the image</p>\n",
10751              "type": "Number"
10752            }, {
10753              "name": "y",
10754              "description": "<p>the y-coordinate of the top-left corner of the image</p>\n",
10755              "type": "Number"
10756            }, {
10757              "name": "width",
10758              "description": "<p>the width to draw the image</p>\n",
10759              "type": "Number",
10760              "optional": true
10761            }, {
10762              "name": "height",
10763              "description": "<p>the height to draw the image</p>\n",
10764              "type": "Number",
10765              "optional": true
10766            }]
10767          }, {
10768            "line": 215,
10769            "params": [{
10770              "name": "img",
10771              "description": "",
10772              "type": "p5.Image|p5.Element"
10773            }, {
10774              "name": "dx",
10775              "description": "<p>the x-coordinate of the destination\n                          rectangle in which to draw the source image</p>\n",
10776              "type": "Number"
10777            }, {
10778              "name": "dy",
10779              "description": "<p>the y-coordinate of the destination\n                          rectangle in which to draw the source image</p>\n",
10780              "type": "Number"
10781            }, {
10782              "name": "dWidth",
10783              "description": "<p>the width of the destination rectangle</p>\n",
10784              "type": "Number"
10785            }, {
10786              "name": "dHeight",
10787              "description": "<p>the height of the destination rectangle</p>\n",
10788              "type": "Number"
10789            }, {
10790              "name": "sx",
10791              "description": "<p>the x-coordinate of the subsection of the source\nimage to draw into the destination rectangle</p>\n",
10792              "type": "Number"
10793            }, {
10794              "name": "sy",
10795              "description": "<p>the y-coordinate of the subsection of the source\nimage to draw into the destination rectangle</p>\n",
10796              "type": "Number"
10797            }, {
10798              "name": "sWidth",
10799              "description": "<p>the width of the subsection of the\n                          source image to draw into the destination\n                          rectangle</p>\n",
10800              "type": "Number",
10801              "optional": true
10802            }, {
10803              "name": "sHeight",
10804              "description": "<p>the height of the subsection of the\n                           source image to draw into the destination rectangle</p>\n",
10805              "type": "Number",
10806              "optional": true
10807            }]
10808          }]
10809        }, {
10810          "file": "src/image/loading_displaying.js",
10811          "line": 298,
10812          "description": "<p>Sets the fill value for displaying images. Images can be tinted to\nspecified colors or made transparent by including an alpha value.\n<br><br>\nTo apply transparency to an image without affecting its color, use\nwhite as the tint color and specify an alpha value. For instance,\ntint(255, 128) will make an image 50% transparent (assuming the default\nalpha range of 0-255, which can be changed with <a href=\"#/p5/colorMode\">colorMode()</a>).\n<br><br>\nThe value for the gray parameter must be less than or equal to the current\nmaximum value as specified by <a href=\"#/p5/colorMode\">colorMode()</a>. The default maximum value is\n255.</p>\n",
10813          "itemtype": "method",
10814          "name": "tint",
10815          "example": ["\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/laDefense.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  tint(0, 153, 204); // Tint blue\n  image(img, 50, 0);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/laDefense.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  tint(0, 153, 204, 126); // Tint blue and set transparency\n  image(img, 50, 0);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/laDefense.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  tint(255, 126); // Apply transparency without changing color\n  image(img, 50, 0);\n}\n</code>\n</div>"],
10816          "alt": "2 side by side images of umbrella and ceiling, one image with blue tint\nImages of umbrella and ceiling, one half of image with blue tint\n2 side by side images of umbrella and ceiling, one image translucent",
10817          "class": "p5",
10818          "module": "Image",
10819          "submodule": "Loading & Displaying",
10820          "overloads": [{
10821            "line": 298,
10822            "params": [{
10823              "name": "v1",
10824              "description": "<p>red or hue value relative to\n                                the current color range</p>\n",
10825              "type": "Number"
10826            }, {
10827              "name": "v2",
10828              "description": "<p>
10828green or saturation value\n                                relative to the current color range</p>\n",
10829              "type": "Number"
10830            }, {
10831              "name": "v3",
10832              "description": "<p>blue or brightness value\n                                relative to the current color range</p>\n",
10833              "type": "Number"
10834            }, {
10835              "name": "alpha",
10836              "description": "",
10837              "type": "Number",
10838              "optional": true
10839            }]
10840          }, {
10841            "line": 371,
10842            "params": [{
10843              "name": "value",
10844              "description": "<p>a color string</p>\n",
10845              "type": "String"
10846            }]
10847          }, {
10848            "line": 376,
10849            "params": [{
10850              "name": "gray",
10851              "description": "<p>a gray value</p>\n",
10852              "type": "Number"
10853            }, {
10854              "name": "alpha",
10855              "description": "",
10856              "type": "Number",
10857              "optional": true
10858            }]
10859          }, {
10860            "line": 382,
10861            "params": [{
10862              "name": "values",
10863              "description": "<p>an array containing the red,green,blue &amp;\n                                and alpha components of the color</p>\n",
10864              "type": "Number[]"
10865            }]
10866          }, {
10867            "line": 388,
10868            "params": [{
10869              "name": "color",
10870              "description": "<p>the tint color</p>\n",
10871              "type": "p5.Color"
10872            }]
10873          }]
10874        }, {
10875          "file": "src/image/loading_displaying.js",
10876          "line": 398,
10877          "description": "<p>Removes the current fill value for displaying images and reverts to\ndisplaying images with their original hues.</p>\n",
10878          "itemtype": "method",
10879          "name": "noTint",
10880          "example": ["\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  tint(0, 153, 204); // Tint blue\n  image(img, 0, 0);\n  noTint(); // Disable tint\n  image(img, 50, 0);\n}\n</code>\n</div>"],
10881          "alt": "2 side by side images of bricks, left image with blue tint",
10882          "class": "p5",
10883          "module": "Image",
10884          "submodule": "Loading & Displaying"
10885        }, {
10886          "file": "src/image/loading_displaying.js",
10887          "line": 464,
10888          "description": "<p>Set image mode. Modifies the location from which images are drawn by\nchanging the way in which parameters given to <a href=\"#/p5/image\">image()</a> are interpreted.\nThe default mode is imageMode(CORNER), which interprets the second and\nthird parameters of <a href=\"#/p5/image\">image()</a> as the upper-left corner of the image. If\ntwo additional parameters are specified, they are used to set the image&#39;s\nwidth and height.\n<br><br>\nimageMode(CORNERS) interprets the second and third parameters of <a href=\"#/p5/image\">image()</a>\nas the location of one corner, and the fourth and fifth parameters as the\nopposite corner.\n<br><br>\nimageMode(CENTER) interprets the second and third parameters of <a href=\"#/p5/image\">image()</a>\nas the image&#39;s center point. If two additional parameters are specified,\nthey are used to set the image&#39;s width and height.</p>\n",
10889          "itemtype": "method",
10890          "name": "imageMode",
10891          "params": [{
10892            "name": "mode",
10893            "description": "<p>either CORNER, CORNERS, or CENTER</p>\n",
10894            "type": "Constant"
10895          }],
10896          "example": ["\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  imageMode(CORNER);\n  image(img, 10, 10, 50, 50);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  imageMode(CORNERS);\n  image(img, 10, 10, 90, 40);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  imageMode(CENTER);\n  image(img, 50, 50, 80, 80);\n}\n</code>\n</div>"],
10897          "alt": "small square image of bricks\nhorizontal rectangle image of bricks\nlarge square image of bricks",
10898          "class": "p5",
10899          "module": "Image",
10900          "submodule": "Loading & Displaying"
10901        }, {
10902          "file": "src/image/p5.Image.js",
10903          "line": 9,
10904          "description": "<p>This module defines the <a href=\"#/p5.Image\">p5.Image</a> class and P5 methods for\ndrawing images to the main display canvas.</p>\n",
10905          "class": "p5.Image",
10906          "module": "Image",
10907          "submodule": "Image"
10908        }, {
10909          "file": "src/image/p5.Image.js",
10910          "line": 90,
10911          "description": "<p>Image width.</p>\n",
10912          "itemtype": "property",
10913          "name": "width",
10914          "type": "Number",
10915          "readonly": "",
10916          "example": ["\n<div><code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  createCanvas(100, 100);\n  image(img, 0, 0);\n  for (let i = 0; i < img.width;
10916 i++) {\n    let c = img.get(i, img.height / 2);\n    stroke(c);\n    line(i, height / 2, i, height);\n  }\n}\n</code></div>"],
10917          "alt": "rocky mountains in top and horizontal lines in corresponding colors in bottom.",
10918          "class": "p5.Image",
10919          "module": "Image",
10920          "submodule": "Image"
10921        }, {
10922          "file": "src/image/p5.Image.js",
10923          "line": 117,
10924          "description": "<p>Image height.</p>\n",
10925          "itemtype": "property",
10926          "name": "height",
10927          "type": "Number",
10928          "readonly": "",
10929          "example": ["\n<div><code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  createCanvas(100, 100);\n  image(img, 0, 0);\n  for (let i = 0; i < img.height; i++) {\n    let c = img.get(img.width / 2, i);\n    stroke(c);\n    line(0, i, width / 2, i);\n  }\n}\n</code></div>"],
10930          "alt": "rocky mountains on right and vertical lines in corresponding colors on left.",
10931          "class": "p5.Image",
10932          "module": "Image",
10933          "submodule": "Image"
10934        }, {
10935          "file": "src/image/p5.Image.js",
10936          "line": 152,
10937          "description": "<p>Array containing the values for all the pixels in the display window.\nThese values are numbers. This array is the size (include an appropriate\nfactor for pixelDensity) of the display window x4,\nrepresenting the R, G, B, A values in order for each pixel, moving from\nleft to right across each row, then down each column. Retina and other\nhigh denisty displays may have more pixels (by a factor of\npixelDensity^2).\nFor example, if the image is 100x100 pixels, there will be 40,000. With\npixelDensity = 2, there will be 160,000. The first four values\n(indices 0-3) in the array will be the R, G, B, A values of the pixel at\n(0, 0). The second four values (indices 4-7) will contain the R, G, B, A\nvalues of the pixel at (1, 0). More generally, to set values for a pixel\nat (x, y):</p>\n<pre><code class=\"lang-javascript\">let d = pixelDensity();\nfor (let i = 0; i &lt; d; i++) {\n  for (let j = 0; j &lt; d; j++) {\n    // loop over\n    index = 4 * ((y * d + j) * width * d + (x * d + i
10937));\n    pixels[index] = r;\n    pixels[index+1] = g;\n    pixels[index+2] = b;\n    pixels[index+3] = a;\n  }\n}\n</code></pre>\n<p><br><br>\nBefore accessing this array, the data must loaded with the <a href=\"#/p5.Image/loadPixels\">loadPixels()</a>\nfunction. After the array data has been modified, the <a href=\"#/p5.Image/updatePixels\">updatePixels()</a>\nfunction must be run to update the changes.</p>\n",
10938          "itemtype": "property",
10939          "name": "pixels",
10940          "type": "Number[]",
10941          "example": ["\n<div>\n<code>\nlet img = createImage(66, 66);\nimg.loadPixels();\nfor (let i = 0; i < img.width; i++) {\n  for (let j = 0; j < img.height; j++) {\n    img.set(i, j, color(0, 90, 102));\n  }\n}\nimg.updatePixels();\nimage(img, 17, 17);\n</code>\n</div>\n<div>\n<code>\nlet pink = color(255, 102, 204);\nlet img = createImage(66, 66);\nimg.loadPixels();\nfor (let i = 0; i < 4 * (width * height / 2); i += 4) {\n  img.pixels[i] = red(pink);\n  img.pixels[i + 1] = green(pink);\n  img.pixels[i + 2] = blue(pink);\n  img.pixels[i + 3] = alpha(pink);\n}\nimg.updatePixels();\nimage(img, 17, 17);\n</code>\n</div>"],
10942          "alt": "66x66 turquoise rect in center of canvas\n66x66 pink rect in center of canvas",
10943          "class": "p5.Image",
10944          "module": "Image",
10945          "submodule": "Image"
10946        }, {
10947          "file": "src/image/p5.Image.js",
10948          "line": 222,
10949          "description": "<p>Helper fxn for sharing pixel methods</p>\n",
10950          "class": "p5.Image",
10951          "module": "Image",
10952          "submodule": "Image"
10953        }, {
10954          "file": "src/image/p5.Image.js",
10955          "line": 231,
10956          "description": "<p>Loads the pixels data for this image into the [pixels] attribute.</p>\n",
10957          "itemtype": "method",
10958          "name": "loadPixels",
10959          "example": ["\n<div><code>\nlet myImage;\nlet halfImage;\n\nfunction preload() {\n  myImage = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  myImage.loadPixels();\n  halfImage = 4 * width * height / 2;\n  for (let i = 0; i < halfImage; i++) {\n    myImage.pixels[i + halfImage] = myImage.pixels[i];\n  }\n  myImage.updatePixels();\n}\n\nfunction draw() {\n  image(myImage, 0, 0);\n}\n</code></div>"],
10960          "alt": "2 images of rocky mountains vertically stacked",
10961          "class": "p5.Image",
10962          "module": "Image",
10963          "submodule": "Image"
10964        }, {
10965          "file": "src/image/p5.Image.js",
10966          "line": 267,
10967          "description": "<p>Updates the backing canvas for this image with the contents of\nthe [pixels] array.</p>\n",
10968          "itemtype": "method",
10969          "name": "updatePixels",
10970          "example": ["\n<div><code>\nlet myImage;\nlet halfImage;\n\nfunction preload() {\n  myImage = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  myImage.loadPixels();\n  halfImage = 4 * width * height / 2;\n  for (let i = 0; i < halfImage; i++) {\n    myImage.pixels[i + halfImage] = myImage.pixels[i];\n  }\n  myImage.updatePixels();\n}\n\nfunction draw() {\n  image(myImage, 0, 0);\n}\n</code></div>"],
10971          "alt": "2 images of rocky mountains vertically stacked",
10972          "class": "p5.Image",
10973          "module": "Image",
10974          "submodule": "Image",
10975          "overloads": [{
10976            "line": 267,
10977            "params": [{
10978              "name": "x",
10979              "description": "<p>x-offset of the target update area for the\n                             underlying canvas</p>\n",
10980              "type": "Integer"
10981            }, {
10982              "name": "y",
10983              "description": "<p>y-offset of the target update area for the\n                             underlying canvas</p>\n",
10984              "type": "Integer"
10985            }, {
10986              "name": "w",
10987              "description": "<p>height of the target update area for the\n                             underlying canvas</p>\n",
10988              "type": "Integer"
10989            }, {
10990              "name": "h",
10991              "description": "<p>height of the target update area for the\n                             underlying canvas</p>\n",
10992              "type": "Integer"
10993            }]
10994          }, {
10995            "line": 307,
10996            "params": []
10997          }]
10998        }, {
10999          "file": "src/image/p5.Image.js",
11000          "line": 315,
11001          "description": "<p>Get a region of pixels from an image.</p>\n<p>If no params are passed, those whole image is returned,\nif x and y are the only params passed a single pixel is extracted\nif all params are passed a rectangle region is extracted and a <a href=\"#/p5.Image\">p5.Image</a>\nis returned.</p>\n<p>Returns undefined if the region is outside the bounds of the image</p>\n",
11002          "itemtype": "method",
11003          "name": "get",
11004          "params": [{
11005            "name": "x",
11006            "description": "<p>x-coordinate of the pixel</p>\n",
11007            "type": "Number",
11008            "optional": true
11009          }, {
11010            "name": "y",
11011            "description": "<p>y-coordinate of the pixel</p>\n",
11012            "type": "Number",
11013            "optional": true
11014          }, {
11015            "name": "w",
11016            "description": "<p>width</p>\n",
11017            "type": "Number",
11018            "optional": true
11019          }, {
11020            "name": "h",
11021            "description": "<p>height</p>\n",
11022            "type": "Number",
11023            "optional": true
11024          }],
11025          "return": {
11026            "description": "color of pixel at x,y in array format\n                                   [R, G, B, A] or <a href=\"#/p5.Image\">p5.Image</a>",
11027            "type": "Number[]|Color|p5.Image"
11028          },
11029          "example": ["\n<div><code>\nlet myImage;\nlet c;\n\nfunction preload() {\n  myImage = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  background(myImage);\n  noStroke();\n  c = myImage.get(60, 90);\n  fill(c);\n  rect(25, 25, 50, 50);\n}\n\n//get() returns color here\n</code></div>"],
11030          "alt": "image of rocky mountains with 50x50 green rect in front",
11031          "class": "p5.Image",
11032          "module": "Image",
11033          "submodule": "Image"
11034        }, {
11035          "file": "src/image/p5.Image.js",
11036          "line": 360,
11037          "description": "<p>Set the color of a single pixel or write an image into\nthis <a href=\"#/p5.Image\">p5.Image</a>.</p>\n<p>Note that for a large number of pixels this will\nbe slower than directly manipulating the pixels array\nand then calling <a href=\"#/p5.Image/updatePixels\">updatePixels()</a>.</p>\n",
11038          "itemtype": "method",
11039          "name": "set",
11040          "params": [{
11041            "name": "x",
11042            "description": "<p>x-coordinate of the pixel</p>\n",
11043            "type": "Number"
11044          }, {
11045            "name": "y",
11046            "description": "<p>y-coordinate of the pixel</p>\n",
11047            "type": "Number"
11048          }, {
11049            "name": "a",
11050            "description": "<p>grayscale value | pixel array |\n                               a <a href=\"#/p5.Color\">p5.Color</a> | image to copy</p>\n",
11051            "type": "Number|Number[]|Object"
11052          }],
11053          "example": ["\n<div>\n<code>\nlet img = createImage(66, 66);\nimg.loadPixels();\nfor (let i = 0; i < img.width;
11053 i++) {\n  for (let j = 0; j < img.height; j++) {\n    img.set(i, j, color(0, 90, 102, (i % img.width) * 2));\n  }\n}\nimg.updatePixels();\nimage(img, 17, 17);\nimage(img, 34, 34);\n</code>\n</div>"],
11054          "alt": "2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas",
11055          "class": "p5.Image",
11056          "module": "Image",
11057          "submodule": "Image"
11058        }, {
11059          "file": "src/image/p5.Image.js",
11060          "line": 398,
11061          "description": "<p>Resize the image to a new width and height. To make the image scale\nproportionally, use 0 as the value for the wide or high parameter.\nFor instance, to make the width of an image 150 pixels, and change\nthe height using the same proportion, use resize(150, 0).</p>\n",
11062          "itemtype": "method",
11063          "name": "resize",
11064          "params": [{
11065            "name": "width",
11066            "description": "<p>the resized image width</p>\n",
11067            "type": "Number"
11068          }, {
11069            "name": "height",
11070            "description": "<p>the resized image height</p>\n",
11071            "type": "Number"
11072          }],
11073          "example": ["\n<div><code>\nlet img;\n\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\n\nfunction draw() {\n  image(img, 0, 0);\n}\n\nfunction mousePressed() {\n  img.resize(50, 100);\n}\n</code></div>"],
11074          "alt": "image of rocky mountains. zoomed in",
11075          "class": "p5.Image",
11076          "module": "Image",
11077          "submodule": "Image"
11078        }, {
11079          "file": "src/image/p5.Image.js",
11080          "line": 483,
11081          "description": "<p>Copies a region of pixels from one image to another. If no\nsrcImage is specified this is used as the source. If the source\nand destination regions aren&#39;t the same size, it will\nautomatically resize source pixels to fit the specified\ntarget region.</p>\n",
11082          "itemtype": "method",
11083          "name": "copy",
11084          "example": ["\n<div><code>\nlet photo;\nlet bricks;\nlet x;\nlet y;\n\nfunction preload() {\n  photo = loadImage('assets/rockies.jpg');\n  bricks = loadImage('assets/bricks.jpg');\n}\n\nfunction setup() {\n  x = bricks.width / 2;\n  y = bricks.height / 2;\n  photo.copy(bricks, 0, 0, x, y, 0, 0, x, y);\n  image(photo, 0, 0);\n}\n</code></div>"],
11085          "alt": "image of rocky mountains and smaller image on top of bricks at top left",
11086          "class": "p5.Image",
11087          "module": "Image",
11088          "submodule": "Image",
11089          "overloads": [{
11090            "line": 483,
11091            "params": [{
11092              "name": "srcImage",
11093              "description": "<p>source image</p>\n",
11094              "type": "p5.Image|p5.Element"
11095            }, {
11096              "name": "sx",
11097              "description": "<p>X coordinate of the source&#39;s upper left corner</p>\n",
11098              "type": "Integer"
11099            }, {
11100              "name": "sy",
11101              "description": "<p>Y coordinate of the source&#39;s upper left corner</p>\n",
11102              "type": "Integer"
11103            }, {
11104              "name": "sw",
11105              "description": "<p>source image width</p>\n",
11106              "type": "Integer"
11107            }, {
11108              "name": "sh",
11109              "description": "<p>source image height</p>\n",
11110              "type": "Integer"
11111            }, {
11112              "name": "dx",
11113              "description": "<p>X coordinate of the destination&#39;s upper left corner</p>\n",
11114              "type": "Integer"
11115            }, {
11116              "name": "dy",
11117              "description": "<p>Y coordinate of the destination&#39;s upper left corner</p>\n",
11118              "type": "Integer"
11119            }, {
11120              "name": "dw",
11121              "description": "<p>destination image width</p>\n",
11122              "type": "Integer"
11123            }, {
11124              "name": "dh",
11125              "description": "<p>destination image height</p>\n",
11126              "type": "Integer"
11127            }]
11128          }, {
11129            "line": 524,
11130            "params": [{
11131              "name": "sx",
11132              "description": "",
11133              "type": "Integer"
11134            }, {
11135              "name": "sy",
11136              "description": "",
11137              "type": "Integer"
11138            }, {
11139              "name": "sw",
11140              "description": "",
11141              "type": "Integer"
11142            }, {
11143              "name": "sh",
11144              "description": "",
11145              "type": "Integer"
11146            }, {
11147              "name": "dx",
11148              "description": "",
11149              "type": "Integer"
11150            }, {
11151              "name": "dy",
11152              "description": "",
11153              "type": "Integer"
11154            }, {
11155              "name": "dw",
11156              "description": "",
11157              "type": "Integer"
11158            }, {
11159              "name": "dh",
11160              "description": "",
11161              "type": "Integer"
11162            }]
11163          }]
11164        }, {
11165          "file": "src/image/p5.Image.js",
11166          "line": 564,
11167          "description": "<p>Masks part of an image from displaying by loading another\nimage and using it&#39;s alpha channel as an alpha channel for\nthis image.</p>\n",
11168          "itemtype": "method",
11169          "name": "mask",
11170          "params": [{
11171            "name": "srcImage",
11172            "description": "<p>source image</p>\n",
11173            "type": "p5.Image"
11174          }],
11175          "example": ["\n<div><code>\nlet photo, maskImage;\nfunction preload() {\n  photo = loadImage('assets/rockies.jpg');\n  maskImage = loadImage('assets/mask2.png');\n}\n\nfunction setup() {\n  createCanvas(100, 100);\n  photo.mask(maskImage);\n  image(photo, 0, 0);\n}\n</code></div>"],
11176          "alt": "image of rocky mountains with white at right\n\n\nhttp://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/",
11177          "class": "p5.Image",
11178          "module": "Image",
11179          "submodule": "Image"
11180        }, {
11181          "file": "src/image/p5.Image.js",
11182          "line": 627,
11183          "description": "<p>Applies an image filter to a <a href=\"#/p5.Image\">p5.Image</a></p>\n",
11184          "itemtype": "method",
11185          "name": "filter",
11186          "params": [{
11187            "name": "filterType",
11188            "description": "<p>either THRESHOLD, GRAY, OPAQUE, INVERT,\n                               POSTERIZE, BLUR, ERODE, DILATE or BLUR.\
11188n                               See Filters.js for docs on\n                               each available filter</p>\n",
11189            "type": "Constant"
11190          }, {
11191            "name": "filterParam",
11192            "description": "<p>an optional parameter unique\n                               to each filter, see above</p>\n",
11193            "type": "Number",
11194            "optional": true
11195          }],
11196          "example": ["\n<div><code>\nlet photo1;\nlet photo2;\n\nfunction preload() {\n  photo1 = loadImage('assets/rockies.jpg');\n  photo2 = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  photo2.filter('gray');\n  image(photo1, 0, 0);\n  image(photo2, width / 2, 0);\n}\n</code></div>"],
11197          "alt": "2 images of rocky mountains left one in color, right in black and white",
11198          "class": "p5.Image",
11199          "module": "Image",
11200          "submodule": "Image"
11201        }, {
11202          "file": "src/image/p5.Image.js",
11203          "line": 663,
11204          "description": "<p>Copies a region of pixels from one image to another, using a specified\nblend mode to do the operation.</p>\n",
11205          "itemtype": "method",
11206          "name": "blend",
11207          "example": ["\n<div><code>\nlet mountains;\nlet bricks;\n\nfunction preload() {\n  mountains = loadImage('assets/rockies.jpg');\n  bricks = loadImage('assets/bricks_third.jpg');\n}\n\nfunction setup() {\n  mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, ADD);\n  image(mountains, 0, 0);\n  image(bricks, 0, 0);\n}\n</code></div>\n<div><code>\nlet mountains;\nlet bricks;\n\nfunction preload() {\n  mountains = loadImage('assets/rockies.jpg');\n  bricks = loadImage('assets/bricks_third.jpg');\n}\n\nfunction setup() {\n  mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST);\n  image(mountains, 0, 0);\n  image(bricks, 0, 0);\n}\n</code></div>\n<div><code>\nlet mountains;\nlet bricks;\n\nfunction preload() {\n  mountains = loadImage('assets/rockies.jpg');\n  bricks = loadImage('assets/bricks_third.jpg');\n}\n\nfunction setup() {\n  mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST);\n  image(mountains, 0, 0);\n  image(bricks, 0, 0);\n}\n</code></div>"],
11208          "alt": "image of rocky mountains. Brick images on left and right. Right overexposed\nimage of rockies. Brickwall images on left and right. Right mortar transparent\nimage of rockies. Brickwall images on left and right. Right translucent",
11209          "class": "p5.Image",
11210          "module": "Image",
11211          "submodule": "Image",
11212          "overloads": [{
11213            "line": 663,
11214            "params": [{
11215              "name": "srcImage",
11216              "description": "<p>source image</p>\n",
11217              "type": "p5.Image"
11218            }, {
11219              "name": "sx",
11220              "description": "<p>X coordinate of the source&#39;s upper left corner</p>\n",
11221              "type": "Integer"
11222            }, {
11223              "name": "sy",
11224              "description": "<p>Y coordinate of the source&#39;s upper left corner</p>\n",
11225              "type": "Integer"
11226            }, {
11227              "name": "sw",
11228              "description": "<p>source image width</p>\n",
11229              "type": "Integer"
11230            }, {
11231              "name": "sh",
11232              "description": "<p>source image height</p>\n",
11233              "type": "Integer"
11234            }, {
11235              "name": "dx",
11236              "description": "<p>X coordinate of the destination&#39;s upper left corner</p>\n",
11237              "type": "Integer"
11238            }, {
11239              "name": "dy",
11240              "description": "<p>Y coordinate of the destination&#39;s upper left corner</p>\n",
11241              "type": "Integer"
11242            }, {
11243              "name": "dw",
11244              "description": "<p>destination image width</p>\n",
11245              "type": "Integer"
11246            }, {
11247              "name": "dh",
11248              "description": "<p>destination image height</p>\n",
11249              "type": "Integer"
11250            }, {
11251              "name": "blendMode",
11252              "description": "<p>the blend mode. either\n    BLEND, DARKEST, LIGHTEST, DIFFERENCE,\n    MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,\n    SOFT_LIGHT, DODGE, BURN, ADD or NORMAL.</p>\n<p>Available blend modes are: normal | multiply | screen | overlay |\n           darken | lighten | color-dodge | color-burn | hard-light |\n           soft-light | difference | exclusion | hue | saturation |\n           color | luminosity</p>\n<p><a href=\"http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/\">http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/</a></p>\n",
11253              "type": "Constant"
11254            }]
11255          }, {
11256            "line": 742,
11257            "params": [{
11258              "name": "sx",
11259              "description": "",
11260              "type": "Integer"
11261            }, {
11262              "name": "sy",
11263              "description": "",
11264              "type": "Integer"
11265            }, {
11266              "name": "sw",
11267              "description": "",
11268              "type": "Integer"
11269            }, {
11270              "name": "sh",
11271              "description": "",
11272              "type": "Integer"
11273            }, {
11274              "name": "dx",
11275              "description": "",
11276              "type": "Integer"
11277            }, {
11278              "name": "dy",
11279              "description": "",
11280              "type": "Integer"
11281            }, {
11282              "name": "dw",
11283              "description": "",
11284              "type": "Integer"
11285            }, {
11286              "name": "dh",
11287              "description": "",
11288              "type": "Integer"
11289            }, {
11290              "name": "blendMode",
11291              "description": "",
11292              "type": "Constant"
11293            }]
11294          }]
11295        }, {
11296          "file": "src/image/p5.Image.js",
11297          "line": 785,
11298          "description": "<p>Saves the image to a file and force the browser to download it.\nAccepts two strings for filename and file extension\nSupports png (default) and jpg.</p>\n",
11299          "itemtype": "method",
11300          "name": "save",
11301          "params": [{
11302            "name": "filename",
11303            "description": "<p>give your file a name</p>\n",
11304            "type": "String"
11305          }, {
11306            "name": "extension",
11307            "description": "<p>&#39;png&#39; or &#39;jpg&#39;</p>\n",
11308            "type": "String"
11309          }],
11310          "example": ["\n<div><code>\nlet photo;\n\nfunction preload() {\n  photo = loadImage('assets/rockies.jpg');\n}\n\nfunction draw() {\n  image(photo, 0, 0);\n}\n\nfunction keyTyped() {\n  if (key === 's') {\n    photo.save('photo', 'png');\n  }\n}\n</code></div>"],
11311          "alt": "image of rocky mountains.",
11312          "class": "p5.Image",
11313          "module": "Image",
11314          "submodule": "Image"
11315        }, {
11316          "file": "src/image/pixels.js",
11317          "line": 14,
11318          "description": "<p><a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference\n/Global_Objects/Uint8ClampedArray' target='_blank'>Uint8ClampedArray</a>\ncontaining the values for all the pixels in the display window.\nThese values are numbers. This array is the size (include an appropriate\nfactor for <a href=\"#/p5/pixelDensity\">pixelDensity</a>) of the display window x4,\nrepresenting the R, G, B, A values in order for each pixel, mov
11318ing from\nleft to right across each row, then down each column. Retina and other\nhigh density displays will have more pixels[] (by a factor of\npixelDensity^2).\nFor example, if the image is 100x100 pixels, there will be 40,000. On a\nretina display, there will be 160,000.\n<br><br>\nThe first four values (indices 0-3) in the array will be the R, G, B, A\nvalues of the pixel at (0, 0). The second four values (indices 4-7) will\ncontain the R, G, B, A values of the pixel at (1, 0). More generally, to\nset values for a pixel at (x, y):</p>\n<pre><code class=\"lang-javascript\">let d = pixelDensity();\nfor (let i = 0; i &lt; d; i++) {\n  for (let j = 0; j &lt; d; j++) {\n    // loop over\n    index = 4 * ((y * d + j) * width * d + (x * d + i));\n    pixels[index] = r;\n    pixels[index+1] = g;\n    pixels[index+2] = b;\n    pixels[index+3] = a;\n  }\n}\n</code></pre>\n<p>While the above method is complex, it is flexible enough to work with\nany pixelDensity. Note that <a href=\"#/p5/set\">set()</a> will automatically take care of\nsetting all the appropriate values in <a href=\"#/p5/pixels\">pixels[]</a> for a given (x, y) at\nany pixelDensity, but the performance may not be as fast when lots of\nmodifications are made to the pixel array.\n<br><br>\nBefore accessing this array, the data must loaded with the <a href=\"#/p5/loadPixels\">loadPixels()</a>\nfunction. After the array data has been modified, the <a href=\"#/p5/updatePixels\">updatePixels()</a>\nfunction must be run to update the changes.\n<br><br>\nNote that this is not a standard javascript array.  This means that\nstandard javascript functions such as <a href=\"#/p5/slice\">slice()</a> or\n<a href=\"#/p5/arrayCopy\">arrayCopy()</a> do not\nwork.</p>",
11319          "itemtype": "property",
11320          "name": "pixels",
11321          "type": "Number[]",
11322          "example": ["\n<div>\n<code>\nlet pink = color(255, 102, 204);\nloadPixels();\nlet d = pixelDensity();\nlet halfImage = 4 * (width * d) * (height / 2 * d);\nfor (let i = 0; i < halfImage; i += 4) {\n  pixels[i] = red(pink);\n  pixels[i + 1] = green(pink);\n  pixels[i + 2] = blue(pink);\n  pixels[i + 3] = alpha(pink);\n}\nupdatePixels();\n</code>\n</div>"],
11323          "alt": "top half of canvas pink, bottom grey",
11324          "class": "p5",
11325          "module": "Image",
11326          "submodule": "Pixels"
11327        }, {
11328          "file": "src/image/pixels.js",
11329          "line": 83,
11330          "description": "<p>Copies a region of pixels from one image to another, using a specified\nblend mode to do the operation.</p>\n",
11331          "itemtype": "method",
11332          "name": "blend",
11333          "example": ["\n<div><code>\nlet img0;\nlet img1;\n\nfunction preload() {\n  img0 = loadImage('assets/rockies.jpg');\n  img1 = loadImage('assets/bricks_third.jpg');\n}\n\nfunction setup() {\n  background(img0);\n  image(img1, 0, 0);\n  blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST);\n}\n</code></div>\n<div><code>\nlet img0;\nlet img1;\n\nfunction preload() {\n  img0 = loadImage('assets/rockies.jpg');\n  img1 = loadImage('assets/bricks_third.jpg');\n}\n\nfunction setup() {\n  background(img0);\n  image(img1, 0, 0);\n  blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST);\n}\n</code></div>\n<div><code>\nlet img0;\nlet img1;\n\nfunction preload() {\n  img0 = loadImage('assets/rockies.jpg');\n  img1 = loadImage('assets/bricks_third.jpg');\n}\n\nfunction setup() {\n  background(img0);\n  image(img1, 0, 0);\n  blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, ADD);\n}\n</code></div>"],
11334          "alt": "image of rocky mountains. Brick images on left and right. Right overexposed\nimage of rockies. Brickwall images on left and right. Right mortar transparent\nimage of rockies. Brickwall images on left and right. Right translucent",
11335          "class": "p5",
11336          "module": "Image",
11337          "submodule": "Pixels",
11338          "overloads": [{
11339            "line": 83,
11340            "params": [{
11341              "name": "srcImage",
11342              "description": "<p>source image</p>\n",
11343              "type": "p5.Image"
11344            }, {
11345              "name": "sx",
11346              "description": "<p>X coordinate of the source&#39;s upper left corner</p>\n",
11347              "type": "Integer"
11348            }, {
11349              "name": "sy",
11350              "description": "<p>Y coordinate of the source&#39;s upper left corner</p>\n",
11351              "type": "Integer"
11352            }, {
11353              "name": "sw",
11354              "description": "<p>source image width</p>\n",
11355              "type": "Integer"
11356            }, {
11357              "name": "sh",
11358              "description": "<p>source image height</p>\n",
11359              "type": "Integer"
11360            }, {
11361              "name": "dx",
11362              "description": "<p>X coordinate of the destination&#39;s upper left corner</p>\n",
11363              "type": "Integer"
11364            }, {
11365              "name": "dy",
11366              "description": "<p>Y coordinate of the destination&#39;s upper left corner</p>\n",
11367              "type": "Integer"
11368            }, {
11369              "name": "dw",
11370              "description": "<p>destination image width</p>\n",
11371              "type": "Integer"
11372            }, {
11373              "name": "dh",
11374              "description": "<p>destination image height</p>\n",
11375              "type": "Integer"
11376            }, {
11377              "name": "blendMode",
11378              "description": "<p>the blend mode. either\n    BLEND, DARKEST, LIGHTEST, DIFFERENCE,\n    MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,\n    SOFT_LIGHT, DODGE, BURN, ADD or NORMAL.</p>\n",
11379              "type": "Constant"
11380            }]
11381          }, {
11382            "line": 156,
11383            "params": [{
11384              "name": "sx",
11385              "description": "",
11386              "type": "Integer"
11387            }, {
11388              "name": "sy",
11389              "description": "",
11390              "type": "Integer"
11391            }, {
11392              "name": "sw",
11393              "description": "",
11394              "type": "Integer"
11395            }, {
11396              "name": "sh",
11397              "description": "",
11398              "type": "Integer"
11399            }, {
11400              "name": "dx",
11401              "description": "",
11402              "type": "Integer"
11403            }, {
11404              "name": "dy",
11405              "description": "",
11406              "type": "Integer"
11407            }, {
11408              "name": "dw",
11409              "description": "",
11410              "type": "Integer"
11411            }, {
11412              "name": "dh",
11413              "description": "",
11414              "type": "Integer"
11415            }, {
11416              "name": "blendMode",
11417              "description": "",
11418              "type": "Constant"
11419            }]
11420          }]
11421        }, {
11422          "file": "src/image/pixels.js",
11423          "line": 177,
11424          "description": "<p>Copies a region of the canvas to another region of the canvas\nand copies a region of pixels from an image used as the srcImg parameter\ninto the canvas srcImage is specified this is used as the source. If\nthe source and destination regions aren&#39;t the same size, it will\nautomatically resize source pixels to fit the specified\ntarget region.</p>\n",
11425          "itemtype": "method",
11426          "name": "copy",
11427          "example": ["\n<div><code>\nlet img;\n\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  background(img);\n  copy(img, 7, 22, 10, 10, 35, 25, 50, 50);
11427\n  stroke(255);\n  noFill();\n  // Rectangle shows area being copied\n  rect(7, 22, 10, 10);\n}\n</code></div>"],
11428          "alt": "image of rocky mountains. Brick images on left and right. Right overexposed\nimage of rockies. Brickwall images on left and right. Right mortar transparent\nimage of rockies. Brickwall images on left and right. Right translucent",
11429          "class": "p5",
11430          "module": "Image",
11431          "submodule": "Pixels",
11432          "overloads": [{
11433            "line": 177,
11434            "params": [{
11435              "name": "srcImage",
11436              "description": "<p>source image</p>\n",
11437              "type": "p5.Image|p5.Element"
11438            }, {
11439              "name": "sx",
11440              "description": "<p>X coordinate of the source&#39;s upper left corner</p>\n",
11441              "type": "Integer"
11442            }, {
11443              "name": "sy",
11444              "description": "<p>Y coordinate of the source&#39;s upper left corner</p>\n",
11445              "type": "Integer"
11446            }, {
11447              "name": "sw",
11448              "description": "<p>source image width</p>\n",
11449              "type": "Integer"
11450            }, {
11451              "name": "sh",
11452              "description": "<p>source image height</p>\n",
11453              "type": "Integer"
11454            }, {
11455              "name": "dx",
11456              "description": "<p>X coordinate of the destination&#39;s upper left corner</p>\n",
11457              "type": "Integer"
11458            }, {
11459              "name": "dy",
11460              "description": "<p>Y coordinate of the destination&#39;s upper left corner</p>\n",
11461              "type": "Integer"
11462            }, {
11463              "name": "dw",
11464              "description": "<p>destination image width</p>\n",
11465              "type": "Integer"
11466            }, {
11467              "name": "dh",
11468              "description": "<p>destination image height</p>\n",
11469              "type": "Integer"
11470            }]
11471          }, {
11472            "line": 220,
11473            "params": [{
11474              "name": "sx",
11475              "description": "",
11476              "type": "Integer"
11477            }, {
11478              "name": "sy",
11479              "description": "",
11480              "type": "Integer"
11481            }, {
11482              "name": "sw",
11483              "description": "",
11484              "type": "Integer"
11485            }, {
11486              "name": "sh",
11487              "description": "",
11488              "type": "Integer"
11489            }, {
11490              "name": "dx",
11491              "description": "",
11492              "type": "Integer"
11493            }, {
11494              "name": "dy",
11495              "description": "",
11496              "type": "Integer"
11497            }, {
11498              "name": "dw",
11499              "description": "",
11500              "type": "Integer"
11501            }, {
11502              "name": "dh",
11503              "description": "",
11504              "type": "Integer"
11505            }]
11506          }]
11507        }, {
11508          "file": "src/image/pixels.js",
11509          "line": 236,
11510          "description": "<p>Applies a filter to the canvas.\n<br><br></p>\n<p>The presets options are:\n<br><br></p>\n<p>THRESHOLD\nConverts the image to black and white pixels depending if they are above or\nbelow the threshold defined by the level parameter. The parameter must be\nbetween 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used.\n<br><br></p>\n<p>GRAY\nConverts any colors in the image to grayscale equivalents. No parameter\nis used.\n<br><br></p>\n<p>OPAQUE\nSets the alpha channel to entirely opaque. No parameter is used.\n<br><br></p>\n<p>INVERT\nSets each pixel to its inverse value. No parameter is used.\n<br><br></p>\n<p>POSTERIZE\nLimits each channel of the image to the number of colors specified as the\nparameter. The parameter can be set to values between 2 and 255, but\nresults are most noticeable in the lower ranges.\n<br><br></p>\n<p>BLUR\nExecutes a Gaussian blur with the level parameter specifying the extent\nof the blurring. If no parameter is used, the blur is equivalent to\nGaussian blur of radius 1. Larger values increase the blur.\n<br><br></p>\n<p>ERODE\nReduces the light areas. No parameter is used.\n<br><br></p>\n<p>DILATE\nIncreases the light areas. No parameter is used.</p>\n",
11511          "itemtype": "method",
11512          "name": "filter",
11513          "params": [{
11514            "name": "filterType",
11515            "description": "<p>either THRESHOLD, GRAY, OPAQUE, INVERT,\n                               POSTERIZE, BLUR, ERODE, DILATE or BLUR.\
11515n                               See Filters.js for docs on\n                               each available filter</p>\n",
11516            "type": "Constant"
11517          }, {
11518            "name": "filterParam",
11519            "description": "<p>an optional parameter unique\n                               to each filter, see above</p>\n",
11520            "type": "Number",
11521            "optional": true
11522          }],
11523          "example": ["\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  filter(THRESHOLD);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  filter(GRAY);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  filter(OPAQUE);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  filter(INVERT);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  filter(POSTERIZE, 3);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  filter(DILATE);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);
11523\n  filter(BLUR, 3);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/bricks.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  filter(ERODE);\n}\n</code>\n</div>"],
11524          "alt": "black and white image of a brick wall.\ngreyscale image of a brickwall\nimage of a brickwall\njade colored image of a brickwall\nred and pink image of a brickwall\nimage of a brickwall\nblurry image of a brickwall\nimage of a brickwall\nimage of a brickwall with less detail",
11525          "class": "p5",
11526          "module": "Image",
11527          "submodule": "Pixels"
11528        }, {
11529          "file": "src/image/pixels.js",
11530          "line": 415,
11531          "description": "<p>Returns an array of [R,G,B,A] values for any pixel or grabs a section of\nan image. If no parameters are specified, the entire image is returned.\nUse the x and y parameters to get the value of one pixel. Get a section of\nthe display window by specifying additional w and h parameters. When\ngetting an image, the x and y parameters define the coordinates for the\nupper-left corner of the image, regardless of the current <a href=\"#/p5/imageMode\">imageMode()</a>.\n<br><br>\nIf the pixel requested is outside of the image window, [0,0,0,255] is\nreturned. To get the numbers scaled according to the current color ranges\nand taking into account <a href=\"#/p5/colorMode\">colorMode</a>, use <a href=\"#/p5/getColor\">getColor</a> instead of get.\n<br><br>\nGetting the color of a single pixel with get(x, y) is easy, but not as fast\nas grabbing the data directly from <a href=\"#/p5/pixels\">pixels[]</a>. The equivalent statement to\nget(x, y) using <a href=\"#/p5/pixels\">pixels[]</a> with pixel density d is</p>\n<pre><code class=\"lang-javascript\">let x, y, d; // set these to the coordinates\nlet off = (y * width + x) * d * 4;\nlet components = [\n  pixels[off],\n  pixels[off + 1],\n  pixels[off + 2],\n  pixels[off + 3]\n];\nprint(components);\n</code></pre>\n<p><br><br>\nSee the reference for <a href=\"#/p5/pixels\">pixels[]</a> for more information.</p>\n<p>If you want to extract an array of colors or a subimage from an p5.Image object,\ntake a look at <a href=\"#/p5.Image/get\">p5.Image.get()</a></p>\n",
11532          "itemtype": "method",
11533          "name": "get",
11534          "params": [{
11535            "name": "x",
11536            "description": "<p>x-coordinate of the pixel</p>\n",
11537            "type": "Number",
11538            "optional": true
11539          }, {
11540            "name": "y",
11541            "description": "<p>y-coordinate of the pixel</p>\n",
11542            "type": "Number",
11543            "optional": true
11544          }, {
11545            "name": "w",
11546            "description": "<p>width</p>\n",
11547            "type": "Number",
11548            "optional": true
11549          }, {
11550            "name": "h",
11551            "description": "<p>height</p>\n",
11552            "type": "Number",
11553            "optional": true
11554          }],
11555          "return": {
11556            "description": "values of pixel at x,y in array format\n                             [R, G, B, A] or <a href=\"#/p5.Image\">p5.Image</a>",
11557            "type": "Number[]|p5.Image"
11558          },
11559          "example": ["\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  let c = get();\n  image(c, width / 2, 0);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\nfunction setup() {\n  image(img, 0, 0);\n  let c = get(50, 90);\n  fill(c);\n  noStroke();\n  rect(25, 25, 50, 50);\n}\n</code>\n</div>"],
11560          "alt": "2 images of the rocky mountains, side-by-side\nImage of the rocky mountains with 50x50 green rect in center of canvas",
11561          "class": "p5",
11562          "module": "Image",
11563          "submodule": "Pixels"
11564        }, {
11565          "file": "src/image/pixels.js",
11566          "line": 520,
11567          "description": "<p>Loads the pixel data for the display window into the <a href=\"#/p5/pixels\">pixels[]</a> array. This\nfunction must always be called before reading from or writing to <a href=\"#/p5/pixels\">pixels[]</a>.\nNote that only changes made with <a href=\"#/p5/set\">set()</a> or direct manipulation of <a href=\"#/p5/pixels\">pixels[]</a>\nwill occur.</p>\n",
11568          "itemtype": "method",
11569          "name": "loadPixels",
11570          "example": ["\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  image(img, 0, 0);\n  let d = pixelDensity();\n  let halfImage = 4 * (img.width * d) * (img.height * d / 2);\n  loadPixels();\n  for (let i = 0; i < halfImage;
11570 i++) {\n    pixels[i + halfImage] = pixels[i];\n  }\n  updatePixels();\n}\n</code>\n</div>"],
11571          "alt": "two images of the rocky mountains. one on top, one on bottom of canvas.",
11572          "class": "p5",
11573          "module": "Image",
11574          "submodule": "Pixels"
11575        }, {
11576          "file": "src/image/pixels.js",
11577          "line": 557,
11578          "description": "<p>Changes the color of any pixel, or writes an image directly to the\ndisplay window.</p>\n<p>The x and y parameters specify the pixel to change and the c parameter\nspecifies the color value. This can be a <a href=\"#/p5.Color\">p5.Color</a> object, or [R, G, B, A]\npixel array. It can also be a single grayscale value.\nWhen setting an image, the x and y parameters define the coordinates for\nthe upper-left corner of the image, regardless of the current <a href=\"#/p5/imageMode\">imageMode()</a>.\n</p>\n<p>\nAfter using <a href=\"#/p5/set\">set()</a>, you must call <a href=\"#/p5/updatePixels\">updatePixels()</a> for your changes to appear.\nThis should be called once all pixels have been set, and must be called before\ncalling .<a href=\"#/p5/get\">get()</a> or drawing the image.\n</p>\n<p>Setting the color of a single pixel with set(x, y) is easy, but not as\nfast as putting the data directly into <a href=\"#/p5/pixels\">pixels[]</a>. Setting the <a href=\"#/p5/pixels\">pixels[]</a>\nvalues directly may be complicated when working with a retina display,\nbut will perform better when lots of pixels need to be set directly on\nevery loop.</p>\n<p>See the reference for <a href=\"#/p5/pixels\">pixels[]</a> for more information.</p>",
11579          "itemtype": "method",
11580          "name": "set",
11581          "params": [{
11582            "name": "x",
11583            "description": "<p>x-coordinate of the pixel</p>\n",
11584            "type": "Number"
11585          }, {
11586            "name": "y",
11587            "description": "<p>y-coordinate of the pixel</p>\n",
11588            "type": "Number"
11589          }, {
11590            "name": "c",
11591            "description": "<p>insert a grayscale value | a pixel array |\n                               a <a href=\"#/p5.Color\">p5.Color</a> object | a <a href=\"#/p5.Image\">p5.Image</a> to copy</p>\n",
11592            "type": "Number|Number[]|Object"
11593          }],
11594          "example": ["\n<div>\n<code>\nlet black = color(0);\nset(30, 20, black);\nset(85, 20, black);\nset(85, 75, black);\nset(30, 75, black);\nupdatePixels();\n</code>\n</div>\n\n<div>\n<code>\nfor (let i = 30; i < width - 15; i++) {\n  for (let j = 20; j < height - 25; j++) {\n    let c = color(204 - j, 153 - i, 0);\n    set(i, j, c);\n  }\n}\nupdatePixels();\n</code>\n</div>\n\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  set(0, 0, img);\n  updatePixels();\n  line(0, 0, width, height);\n  line(0, height, width, 0);\n}\n</code>\n</div>"],
11595          "alt": "4 black points in the shape of a square middle-right of canvas.\nsquare with orangey-brown gradient lightening at bottom right.\nimage of the rocky mountains. with lines like an 'x' through the center.",
11596          "class": "p5",
11597          "module": "Image",
11598          "submodule": "Pixels"
11599        }, {
11600          "file": "src/image/pixels.js",
11601          "line": 631,
11602          "description": "<p>Updates the display window with the data in the <a href=\"#/p5/pixels\">pixels[]</a> array.\nUse in conjunction with <a href=\"#/p5/loadPixels\">loadPixels()</a>. If you&#39;re only reading pixels from\nthe array, there&#39;s no need to call <a href=\"#/p5/updatePixels\">updatePixels()</a> — updating is only\nnecessary to apply changes. <a href=\"#/p5/updatePixels\">updatePixels()</a> should be called anytime the\npixels array is manipulated or <a href=\"#/p5/set\">set()</a> is called, and only changes made with\n<a href=\"#/p5/set\">set()</a> or direct changes to <a href=\"#/p5/pixels\">pixels[]</a> will occur.</p>\n",
11603          "itemtype": "method",
11604          "name": "updatePixels",
11605          "params": [{
11606            "name": "x",
11607            "description": "<p>x-coordinate of the upper-left corner of region\n                        to update</p>\n",
11608            "type": "Number",
11609            "optional": true
11610          }, {
11611            "name": "y",
11612            "description": "<p>y-coordinate of the upper-left corner of region\n                        to update</p>\n",
11613            "type": "Number",
11614            "optional": true
11615          }, {
11616            "name": "w",
11617            "description": "<p>width of region to update</p>\n",
11618            "type": "Number",
11619            "optional": true
11620          }, {
11621            "name": "h",
11622            "description": "<p>height of region to update</p>\n",
11623            "type": "Number",
11624            "optional": true
11625          }],
11626          "example": ["\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/rockies.jpg');\n}\n\nfunction setup() {\n  image(img, 0, 0);\n  let d = pixelDensity();\n  let halfImage = 4 * (img.width * d) * (img.height * d / 2);\n  loadPixels();\n  for (let i = 0; i < halfImage;
11626 i++) {\n    pixels[i + halfImage] = pixels[i];\n  }\n  updatePixels();\n}\n</code>\n</div>"],
11627          "alt": "two images of the rocky mountains. one on top, one on bottom of canvas.",
11628          "class": "p5",
11629          "module": "Image",
11630          "submodule": "Pixels"
11631        }, {
11632          "file": "src/io/files.js",
11633          "line": 19,
11634          "description": "<p>Loads a JSON file from a file or a URL, and returns an Object.\nNote that even if the JSON file contains an Array, an Object will be\nreturned with index numbers as keys.</p>\n<p>This method is asynchronous, meaning it may not finish before the next\nline in your sketch is executed. JSONP is supported via a polyfill and you\ncan pass in as the second argument an object with definitions of the json\ncallback following the syntax specified <a href=\"https://github.com/camsong/\nfetch-jsonp\">here</a>.</p>\n<p>This method is suitable for fetching files up to size of 64MB.</p>\n",
11635          "itemtype": "method",
11636          "name": "loadJSON",
11637          "return": {
11638            "description": "JSON data",
11639            "type": "Object|Array"
11640          },
11641          "example": ["\n\n<p>Calling <a href=\"#/p5/loadJSON\">loadJSON()</a> inside <a href=\"#/p5/preload\">preload()</a> guarantees to complete the\noperation before <a href=\"#/p5/setup\">setup()</a> and <a href=\"#/p5/draw\">draw()</a> are called.</p>\n\n<div><code>\n// Examples use USGS Earthquake API:\n//   https://earthquake.usgs.gov/fdsnws/event/1/#methods\nlet earthquakes;\nfunction preload() {\n  // Get the most recent earthquake in the database\n  let url =\n   'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' +\n    'summary/all_day.geojson';\n  earthquakes = loadJSON(url);\n}\n\nfunction setup() {\n  noLoop();\n}\n\nfunction draw() {\n  background(200);\n  // Get the magnitude and name of the earthquake out of the loaded JSON\n  let earthquakeMag = earthquakes.features[0].properties.mag;\n  let earthquakeName = earthquakes.features[0].properties.place;\n  ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);\n  textAlign(CENTER);\n  text(earthquakeName, 0, height - 30, width, 30);\n}\n</code></div>\n\n\n<p>Outside of preload(), you may supply a callback function to handle the\nobject:</p>\n<div><code>\nfunction setup() {\n  noLoop();\n  let url =\n   'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' +\n    'summary/all_day.geojson';\n  loadJSON(url, drawEarthquake);\n}\n\nfunction draw() {\n  background(200);\n}\n\nfunction drawEarthquake(earthquakes) {\n  // Get the magnitude and name of the earthquake out of the loaded JSON\n  let earthquakeMag = earthquakes.features[0].properties.mag;\n  let earthquakeName = earthquakes.features[0].properties.place;\n  ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);\n  textAlign(CENTER);\n  text(earthquakeName, 0, height - 30, width, 30);\n}\n</code></div>"],
11642          "alt": "50x50 ellipse that changes from black to white depending on the current humidity\n50x50 ellipse that changes from black to white depending on the current humidity",
11643          "class": "p5",
11644          "module": "IO",
11645          "submodule": "Input",
11646          "overloads": [{
11647            "line": 19,
11648            "params": [{
11649              "name": "path",
11650              "description": "<p>name of the file or url to load</p>\n",
11651              "type": "String"
11652            }, {
11653              "name": "jsonpOptions",
11654              "description": "<p>options object for jsonp related settings</p>\n",
11655              "type": "Object",
11656              "optional": true
11657            }, {
11658              "name": "datatype",
11659              "description": "<p>&quot;json&quot; or &quot;jsonp&quot;</p>\n",
11660              "type": "String",
11661              "optional": true
11662            }, {
11663              "name": "callback",
11664              "description": "<p>function to be executed after\n                                   <a href=\"#/p5/loadJSON\">loadJSON()</a> completes, data is passed\n                                   in as first argument</p>\n",
11665              "type": "Function",
11666              "optional": true
11667            }, {
11668              "name": "errorCallback",
11669              "description": "<p>function to be executed if\n                                   there is an error, response is passed\n                                   in as first argument</p>\n",
11670              "type": "Function",
11671              "optional": true
11672            }],
11673            "return": {
11674              "description": "JSON data",
11675              "type": "Object|Array"
11676            }
11677          }, {
11678            "line": 105,
11679            "params": [{
11680              "name": "path",
11681              "description": "",
11682              "type": "String"
11683            }, {
11684              "name": "datatype",
11685              "description": "",
11686              "type": "String"
11687            }, {
11688              "name": "callback",
11689              "description": "",
11690              "type": "Function",
11691              "optional": true
11692            }, {
11693              "name": "errorCallback",
11694              "description": "",
11695              "type": "Function",
11696              "optional": true
11697            }],
11698            "return": {
11699              "description": "",
11700              "type": "Object|Array"
11701            }
11702          }, {
11703            "line": 113,
11704            "params": [{
11705              "name": "path",
11706              "description": "",
11707              "type": "String"
11708            }, {
11709              "name": "callback",
11710              "description": "",
11711              "type": "Function"
11712            }, {
11713              "name": "errorCallback",
11714              "description": "",
11715              "type": "Function",
11716              "optional": true
11717            }],
11718            "return": {
11719              "description": "",
11720              "type": "Object|Array"
11721            }
11722          }]
11723        }, {
11724          "file": "src/io/files.js",
11725          "line": 180,
11726          "description": "<p>Reads the contents of a file and creates a String array of its individual\nlines. If the name of the file is used as the parameter, as in the above\nexample, the file must be located in the sketch directory/folder.\n<br><br>\nAlternatively, the file maybe be loaded from anywhere on the local\ncomputer using an absolute path (something that starts with / on Unix and\nLinux, or a drive letter on Windows), or the filename parameter can be a\nURL for a file found on a network.\n<br><br>\nThis method is asynchronous, meaning it may not finish before the next\nline in your sketch is executed.</p>\n<p>This method is suitable for fetching files up to size of 64MB.</p>\n",
11727          "itemtype": "method",
11728          "name": "loadStrings",
11729          "params": [{
11730            "name": "filename",
11731            "description": "<p>name of the file or url to load</p>\n",
11732            "type": "String"
11733          }, {
11734            "name": "callback",
11735            "description": "<p>function to be executed after <a href=\"#/p5/loadStrings\">loadStrings()</a>\n                              completes, Array is passed in as first\n                              argument</p>\n",
11736            "type": "Function",
11737            "optional": true
11738          }, {
11739            "name": "errorCallback",
11740            "description": "<p>function to be executed if\n                              there is an error, response is passed\n                              in as first argument</p>\n",
11741            "type": "Function",
11742            "optional": true
11743          }],
11744          "return": {
11745            "description": "Array of Strings",
11746            "type": "String[]"
11747          },
11748          "example": ["\n\n<p>Calling loadStrings() inside <a href=\"#/p5/preload\">preload()</a> guarantees to complete the\noperation before <a href=\"#/p5/setup\">setup()</a> and <a href=\"#/p5/draw\">draw()</a> are called.</p>\n\n<div><code>\nlet result;\nfunction preload() {\n  result = loadStrings('assets/test.txt');\n}\n\nfunction setup() {\n  background(200);\n  let ind = floor(random(result.length));\n  text(result[ind], 10, 10, 80, 80);\n}\n</code></div>\n\n<p>Outside of preload(), you may supply a callback function to handle the\nobject:</p>\n\n<div><code>\nfunction setup() {\n  loadStrings('assets/test.txt', pickString);\n}\n\nfunction pickString(result) {\n  background(200);\n  let ind = floor(random(result.length));\n  text(result[ind], 10, 10, 80, 80);\n}\n</code></div>"],
11749          "alt": "randomly generated text from a file, for example \"i smell like butter\"\nrandomly generated text from a file, for example \"i have three feet\"",
11750          "class": "p5",
11751          "module": "IO",
11752          "submodule": "Input"
11753        }, {
11754          "file": "src/io/files.js",
11755          "line": 293,
11756          "description": "<p>Reads the contents of a file or URL and creates a <a href=\"#/p5.Table\">p5.Table</a> object with\nits values. If a file is specified, it must be located in the sketch&#39;s\n&quot;data&quot; folder. The filename parameter can also be a URL to a file found\nonline. By default, the file is assumed to be comma-separated (in CSV\nformat). Table only looks for a header row if the &#39;header&#39; option is\nincluded.</p>\n\n<p>Possible options include:\n<ul>\n<li>csv - parse the table as comma-separated values</li>\n<li>tsv - parse the table as tab-separated values</li>\n<li>header - this table has a header (title) row</li>\n</ul>\n</p>\n\n<p>When passing in multiple options, pass them in as separate parameters,\nseperated by commas. For example:\n<br><br>\n<code>\nloadTable(&#39;my_csv_file.csv&#39;, &#39;csv&#39;, &#39;header&#39;);\n</code>\n</p>\n\n<p> All files loaded and saved use UTF-8 encoding.</p>\n\n<p>This method is asynchronous, meaning it may not finish before the next\nline in your sketch is executed. Calling <a href=\"#/p5/loadTable\">loadTable()</a> inside <a href=\"#/p5/preload\">preload()</a>\nguarantees to complete the operation before <a href=\"#/p5/setup\">setup()</a> and <a href=\"#/p5/draw\">draw()</a> are called.\n<p>Outside of <a href=\"#/p5/preload\">preload()</a>, you may supply a callback function to handle the\nobject:</p>\n</p>\n\n<p>This method is suitable for fetching files up to size of 64MB.</p>\n",
11757          "itemtype": "method",
11758          "name": "loadTable",
11759          "return": {
11760            "description": "<a href=\"#/p5.Table\">Table</a>
11760 object containing data",
11761            "type": "Object"
11762          },
11763          "example": ["\n<div class='norender'>\n<code>\n// Given the following CSV file called \"mammals.csv\"\n// located in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nlet table;\n\nfunction preload() {\n  //my table is comma separated value \"csv\"\n  //and has a header specifying the columns labels\n  table = loadTable('assets/mammals.csv', 'csv', 'header');\n  //the file can be remote\n  //table = loadTable(\"http://p5js.org/reference/assets/mammals.csv\",\n  //                  \"csv\", \"header\");\n}\n\nfunction setup() {\n  //count the columns\n  print(table.getRowCount() + ' total rows in table');\n  print(table.getColumnCount() + ' total columns in table');\n\n  print(table.getColumn('name'));\n  //[\"Goat\", \"Leopard\", \"Zebra\"]\n\n  //cycle through the table\n  for (let r = 0; r < table.getRowCount(); r++)\n    for (let c = 0; c < table.getColumnCount(); c++) {\n      print(table.getString(r, c));\n    }\n}\n</code>\n</div>"],
11764          "alt": "randomly generated text from a file, for example \"i smell like butter\"\nrandomly generated text from a file, for example \"i have three feet\"",
11765          "class": "p5",
11766          "module": "IO",
11767          "submodule": "Input",
11768          "overloads": [{
11769            "line": 293,
11770            "params": [{
11771              "name": "filename",
11772              "description": "<p>name of the file or URL to load</p>\n",
11773              "type": "String"
11774            }, {
11775              "name": "options",
11776              "description": "<p>&quot;header&quot; &quot;csv&quot; &quot;tsv&quot;</p>\n",
11777              "type": "String"
11778            }, {
11779              "name": "callback",
11780              "description": "<p>function to be executed after\n                                    <a href=\"#/p5/loadTable\">loadTable()</a> completes. On success, the\n                                    <a href=\"#/p5.Table\">Table</a> object is passed in as the\n                                    first argument.</p>\n",
11781              "type": "Function",
11782              "optional": true
11783            }, {
11784              "name": "errorCallback",
11785              "description": "<p>function to be executed if\n                                    there is an error, response is passed\n                                    in as first argument</p>\n",
11786              "type": "Function",
11787              "optional": true
11788            }],
11789            "return": {
11790              "description": "<a href=\"#/p5.Table\">Table</a> object containing data",
11791              "type": "Object"
11792            }
11793          }, {
11794            "line": 383,
11795            "params": [{
11796              "name": "filename",
11797              "description": "",
11798              "type": "String"
11799            }, {
11800              "name": "callback",
11801              "description": "",
11802              "type": "Function",
11803              "optional": true
11804            }, {
11805              "name": "errorCallback",
11806              "description": "",
11807              "type": "Function",
11808              "optional": true
11809            }],
11810            "return": {
11811              "description": "",
11812              "type": "Object"
11813            }
11814          }]
11815        }, {
11816          "file": "src/io/files.js",
11817          "line": 603,
11818          "description": "<p>Reads the contents of a file and creates an XML object with its values.\nIf the name of the file is used as the parameter, as in the above example,\nthe file must be located in the sketch directory/folder.</p>\n<p>Alternatively, the file maybe be loaded from anywhere on the local\ncomputer using an absolute path (something that starts with / on Unix and\nLinux, or a drive letter on Windows), or the filename parameter can be a\nURL for a file found on a network.</p>\n<p>This method is asynchronous, meaning it may not finish before the next\nline in your sketch is executed. Calling <a href=\"#/p5/loadXML\">loadXML()</a> inside <a href=\"#/p5/preload\">preload()</a>\nguarantees to complete the operation before <a href=\"#/p5/setup\">setup()</a> and <a href=\"#/p5/draw\">draw()</a> are called.</p>\n<p>Outside of <a href=\"#/p5/preload\">preload()</a>, you may supply a callback function to handle the\nobject.</p>\n<p>This method is suitable for fetching files up to size of 64MB.</p>\n",
11819          "itemtype": "method",
11820          "name": "loadXML",
11821          "params": [{
11822            "name": "filename",
11823            "description": "<p>name of the file or URL to load</p>\n",
11824            "type": "String"
11825          }, {
11826            "name": "callback",
11827            "description": "<p>function to be executed after <a href=\"#/p5/loadXML\">loadXML()</a>\n                              completes, XML object is passed in as\n                              first argument</p>\n",
11828            "type": "Function",
11829            "optional": true
11830          }, {
11831            "name": "errorCallback",
11832            "description": "<p>function to be executed if\n                              there is an error, response is passed\n                              in as first argument</p>\n",
11833            "type": "Function",
11834            "optional": true
11835          }],
11836          "return": {
11837            "description": "XML object containing data",
11838            "type": "Object"
11839          },
11840          "example": ["\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let children = xml.getChildren('animal');\n\n  for (let i = 0; i < children.length; i++) {\n    let id = children[i].getNum('id');\n    let coloring = children[i].getString('species');\n    let name = children[i].getContent();\n    print(id + ', ' + coloring + ', ' + name);\n  }\n}\n\n// Sketch prints:\n// 0, Capra hircus, Goat\n// 1, Panthera pardus, Leopard\n// 2, Equus zebra, Zebra\n</code></div>"],
11841          "alt": "no image displayed",
11842          "class": "p5",
11843          "module": "IO",
11844          "submodule": "Input"
11845        }, {
11846          "file": "src/io/files.js",
11847          "line": 714,
11848          "description": "<p>This method is suitable for fetching files up to size of 64MB.</p>\n",
11849          "itemtype": "method",
11850          "name": "loadBytes",
11851          "params": [{
11852            "name": "file",
11853            "description": "<p>name of the file or URL to load</p>\n",
11854            "type": "String"
11855          }, {
11856            "name": "callback",
11857            "description": "<p>function to be executed after <a href=\"#/p5/loadBytes\">loadBytes()</a>\n                                   completes</p>\n",
11858            "type": "Function",
11859            "optional": true
11860          }, {
11861            "name": "errorCallback",
11862            "description": "<p>function to be executed if there\n                                   is an error</p>\n",
11863            "type": "Function",
11864            "optional": true
11865          }],
11866          "return": {
11867            "description": "an object whose 'bytes' property will be the loaded buffer",
11868            "type": "Object"
11869          },
11870          "example": ["\n<div class='norender'><code>\nlet data;\n\nfunction preload() {\n  data = loadBytes('assets/mammals.xml');\n}\n\nfunction setup() {\n  for (let i = 0; i < 5; i++) {\n    console.log(data.bytes[i].toString(16));\n  }\n}\n</code></div>"],
11871          "alt": "no image displayed",
11872          "class": "p5",
11873          "module": "IO",
11874          "submodule": "Input"
11875        }, {
11876          "file": "src/io/files.js",
11877          "line": 774,
11878          "description": "<p>Method for executing an HTTP GET request. If data type is not specified,\np5 will try to guess based on the URL, defaulting to text. This is equivalent to\ncalling <code>httpDo(path, &#39;GET&#39;)</code>. The &#39;binary&#39; datatype will return\na Blob object, and the &#39;arrayBuffer&#39; datatype will return an ArrayBuffer\nwhich can be used to initialize typed arrays (such as Uint8Array).</p>\n",
11879          "itemtype": "method",
11880          "name": "httpGet",
11881          "return": {
11882            "description": "A promise that resolves with the data when the operation\n                  completes successfully or rejects with the error after\n                  one occurs.",
11883            "type": "Promise"
11884          },
11885          "example": ["\n<div class='norender'><code>\n// Examples use USGS Earthquake API:\n//   https://earthquake.usgs.gov/fdsnws/event/1/#methods\nlet earthquakes;\nfunction preload() {\n  // Get the most recent earthquake in the database\n  let url =\n   'https://earthquake.usgs.gov/fdsnws/event/1/query?' +\n    'format=geojson&limit=1&orderby=time';\n  httpGet(url, 'jsonp', false, function(response) {\n    // when the HTTP request completes, populate the variable that holds the\n    // earthquake data used in the visualization.\n    earthquakes = response;\n  });\n}\n\nfunction draw() {\n  if (!earthquakes) {\n    // Wait until the earthquake data has loaded before drawing.\n    return;\n  }\n  background(200);\n  // Get the magnitude and name of the earthquake out of the loaded JSON\n  let earthquakeMag = earthquakes.features[0].properties.mag;\n  let earthquakeName = earthquakes.features[0].properties.place;\n  ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);\n  textAlign(CENTER);
11885\n  text(earthquakeName, 0, height - 30, width, 30);\n  noLoop();\n}\n</code></div>"],
11886          "class": "p5",
11887          "module": "IO",
11888          "submodule": "Input",
11889          "overloads": [{
11890            "line": 774,
11891            "params": [{
11892              "name": "path",
11893              "description": "<p>name of the file or url to load</p>\n",
11894              "type": "String"
11895            }, {
11896              "name": "datatype",
11897              "description": "<p>&quot;json&quot;, &quot;jsonp&quot;, &quot;binary&quot;, &quot;arrayBuffer&quot;,\n                                   &quot;xml&quot;, or &quot;text&quot;</p>\n",
11898              "type": "String",
11899              "optional": true
11900            }, {
11901              "name": "data",
11902              "description": "<p>param data passed sent with request</p>\n",
11903              "type": "Object|Boolean",
11904              "optional": true
11905            }, {
11906              "name": "callback",
11907              "description": "<p>function to be executed after\n                                   <a href=\"#/p5/httpGet\">httpGet()</a> completes, data is passed in\n                                   as first argument</p>\n",
11908              "type": "Function",
11909              "optional": true
11910            }, {
11911              "name": "errorCallback",
11912              "description": "<p>function to be executed if\n                                   there is an error, response is passed\n                                   in as first argument</p>\n",
11913              "type": "Function",
11914              "optional": true
11915            }],
11916            "return": {
11917              "description": "A promise that resolves with the data when the operation\n                  completes successfully or rejects with the error after\n                  one occurs.",
11918              "type": "Promise"
11919            }
11920          }, {
11921            "line": 828,
11922            "params": [{
11923              "name": "path",
11924              "description": "",
11925              "type": "String"
11926            }, {
11927              "name": "data",
11928              "description": "",
11929              "type": "Object|Boolean"
11930            }, {
11931              "name": "callback",
11932              "description": "",
11933              "type": "Function",
11934              "optional": true
11935            }, {
11936              "name": "errorCallback",
11937              "description": "",
11938              "type": "Function",
11939              "optional": true
11940            }],
11941            "return": {
11942              "description": "",
11943              "type": "Promise"
11944            }
11945          }, {
11946            "line": 836,
11947            "params": [{
11948              "name": "path",
11949              "description": "",
11950              "type": "String"
11951            }, {
11952              "name": "callback",
11953              "description": "",
11954              "type": "Function"
11955            }, {
11956              "name": "errorCallback",
11957              "description": "",
11958              "type": "Function",
11959              "optional": true
11960            }],
11961            "return": {
11962              "description": "",
11963              "type": "Promise"
11964            }
11965          }]
11966        }, {
11967          "file": "src/io/files.js",
11968          "line": 851,
11969          "description": "<p>Method for executing an HTTP POST request. If data type is not specified,\np5 will try to guess based on the URL, defaulting to text. This is equivalent to\ncalling <code>httpDo(path, &#39;POST&#39;)</code>.</p>\n",
11970          "itemtype": "method",
11971          "name": "httpPost",
11972          "return": {
11973            "description": "A promise that resolves with the data when the operation\n                  completes successfully or rejects with the error after\n                  one occurs.",
11974            "type": "Promise"
11975          },
11976          "example": ["\n<div>\n<code>\n// Examples use jsonplaceholder.typicode.com for a Mock Data API\n\nlet url = 'https://jsonplaceholder.typicode.com/posts';\nlet postData = { userId: 1, title: 'p5 Clicked!', body: 'p5.js is way cool.' };\n\nfunction setup() {\n  createCanvas(800, 800);\n}\n\nfunction mousePressed() {\n  // Pick new random color values\n  let r = random(255);\n  let g = random(255);\n  let b = random(255);\n\n  httpPost(url, 'json', postData, function(result) {\n    strokeWeight(2);\n    stroke(r, g, b);\n    fill(r, g, b, 127);\n    ellipse(mouseX, mouseY, 200, 200);\n    text(result.body, mouseX, mouseY);\n  });\n}\n</code>\n</div>\n\n\n<div><code>\nlet url = 'https://invalidURL'; // A bad URL that will cause errors\nlet postData = { title: 'p5 Clicked!', body: 'p5.js is way cool.' };\n\nfunction setup() {\n  createCanvas(800, 800);\n}\n\nfunction mousePressed() {\n  // Pick new random color values\n  let r = random(255);\n  let g = random(255);\n  let b = random(255);\n\n  httpPost(\n    url,\n    'json',\n    postData,\n    function(result) {\n      // ... won't be called\n    },\n    function(error) {\n      strokeWeight(2);\n      stroke(r, g, b);\n      fill(r, g, b, 127);\n      text(error.toString(), mouseX, mouseY);\n    }\n  );\n}\n</code></div>\n"],
11977          "class": "p5",
11978          "module": "IO",
11979          "submodule": "Input",
11980          "overloads": [{
11981            "line": 851,
11982            "params": [{
11983              "name": "path",
11984              "description": "<p>name of the file or url to load</p>\n",
11985              "type": "String"
11986            }, {
11987              "name": "datatype",
11988              "description": "<p>&quot;json&quot;, &quot;jsonp&quot;, &quot;xml&quot;, or &quot;text&quot;.\n                                   If omitted, <a href=\"#/p5/httpPost\">httpPost()</a> will guess.</p>\n",
11989              "type": "String",
11990              "optional": true
11991            }, {
11992              "name": "data",
11993              "description": "<p>param data passed sent with request</p>\n",
11994              "type": "Object|Boolean",
11995              "optional": true
11996            }, {
11997              "name": "callback",
11998              "description": "<p>function to be executed after\n                                   <a href=\"#/p5/httpPost\">httpPost()</a> completes, data is passed in\n                                   as first argument</p>\n",
11999              "type": "Function",
12000              "optional": true
12001            }, {
12002              "name": "errorCallback",
12003              "description": "<p>function to be executed if\n                                   there is an error, response is passed\n                                   in as first argument</p>\n",
12004              "type": "Function",
12005              "optional": true
12006            }],
12007            "return": {
12008              "description": "A promise that resolves with the data when the operation\n                  completes successfully or rejects with the error after\n                  one occurs.",
12009              "type": "Promise"
12010            }
12011          }, {
12012            "line": 933,
12013            "params": [{
12014              "name": "path",
12015              "description": "",
12016              "type": "String"
12017            }, {
12018              "name": "data",
12019              "description": "",
12020              "type": "Object|Boolean"
12021            }, {
12022              "name": "callback",
12023              "description": "",
12024              "type": "Function",
12025              "optional": true
12026            }, {
12027              "name": "errorCallback",
12028              "description": "",
12029              "type": "Function",
12030              "optional": true
12031            }],
12032            "return": {
12033              "description": "",
12034              "type": "Promise"
12035            }
12036          }, {
12037            "line": 941,
12038            "params": [{
12039              "name": "path",
12040              "description": "",
12041              "type": "String"
12042            }, {
12043              "name": "callback",
12044              "description": "",
12045              "type": "Function"
12046            }, {
12047              "name": "errorCallback",
12048              "description": "",
12049              "type": "Function",
12050              "optional": true
12051            }],
12052            "return": {
12053              "description": "",
12054              "type": "Promise"
12055            }
12056          }]
12057        }, {
12058          "file": "src/io/files.js",
12059          "line": 956,
12060          "description": "<p>Method for executing an HTTP request. If data type is not specified,\np5 will try to guess based on the URL, defaulting to text.<br><br>\nFor more advanced use, you may also pass in the path as the first argument\nand a object as the second argument, the signature follows the one specified\nin the Fetch API specification.\nThis method is suitable for fetching files up to size of 64MB when &quot;GET&quot; is used.</p>\n",
12061          "itemtype": "method",
12062          "name": "httpDo",
12063          "return": {
12064            "description": "A promise that resolves with the data when the operation\n                  completes successfully or rejects with the error after\n                  one occurs.",
12065            "type": "Promise"
12066          },
12067          "example": ["\n<div>\n<code>\n// Examples use USGS Earthquake API:\n// https://earthquake.usgs.gov/fdsnws/event/1/#methods\n\n// dis
12067plays an animation of all USGS earthquakes\nlet earthquakes;\nlet eqFeatureIndex = 0;\n\nfunction preload() {\n  let url = 'https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson';\n  httpDo(\n    url,\n    {\n      method: 'GET',\n      // Other Request options, like special headers for apis\n      headers: { authorization: 'Bearer secretKey' }\n    },\n    function(res) {\n      earthquakes = res;\n    }\n  );\n}\n\nfunction draw() {\n  // wait until the data is loaded\n  if (!earthquakes || !earthquakes.features[eqFeatureIndex]) {\n    return;\n  }\n  clear();\n\n  let feature = earthquakes.features[eqFeatureIndex];\n  let mag = feature.properties.mag;\n  let rad = mag / 11 * ((width + height) / 2);\n  fill(255, 0, 0, 100);\n  ellipse(width / 2 + random(-2, 2), height / 2 + random(-2, 2), rad, rad);\n\n  if (eqFeatureIndex >= earthquakes.features.length) {\n    eqFeatureIndex = 0;\n  } else {\n    eqFeatureIndex += 1;\n  }\n}\n</code>\n</div>"],
12068          "class": "p5",
12069          "module": "IO",
12070          "submodule": "Input",
12071          "overloads": [{
12072            "line": 956,
12073            "params": [{
12074              "name": "path",
12075              "description": "<p>name of the file or url to load</p>\n",
12076              "type": "String"
12077            }, {
12078              "name": "method",
12079              "description": "<p>either &quot;GET&quot;, &quot;POST&quot;, or &quot;PUT&quot;,\n                                   defaults to &quot;GET&quot;</p>\n",
12080              "type": "String",
12081              "optional": true
12082            }, {
12083              "name": "datatype",
12084              "description": "<p>&quot;json&quot;, &quot;jsonp&quot;, &quot;xml&quot;, or &quot;text&quot;</p>\n",
12085              "type": "String",
12086              "optional": true
12087            }, {
12088              "name": "data",
12089              "description": "<p>param data passed sent with request</p>\n",
12090              "type": "Object",
12091              "optional": true
12092            }, {
12093              "name": "callback",
12094              "description": "<p>function to be executed after\n                                   <a href=\"#/p5/httpGet\">httpGet()</a> completes, data is passed in\n                                   as first argument</p>\n",
12095              "type": "Function",
12096              "optional": true
12097            }, {
12098              "name": "errorCallback",
12099              "description": "<p>function to be executed if\n                                   there is an error, response is passed\n                                   in as first argument</p>\n",
12100              "type": "Function",
12101              "optional": true
12102            }],
12103            "return": {
12104              "description": "A promise that resolves with the data when the operation\n                  completes successfully or rejects with the error after\n                  one occurs.",
12105              "type": "Promise"
12106            }
12107          }, {
12108            "line": 1027,
12109            "params": [{
12110              "name": "path",
12111              "description": "",
12112              "type": "String"
12113            }, {
12114              "name": "options",
12115              "description": "<p>Request object options as documented in the\n                                   &quot;fetch&quot; API\n<a href=\"https://developer.mozilla.org/en/docs/Web/API/Fetch_API\">reference</a></p>\n",
12116              "type": "Object"
12117            }, {
12118              "name": "callback",
12119              "description": "",
12120              "type": "Function",
12121              "optional": true
12122            }, {
12123              "name": "errorCallback",
12124              "description": "",
12125              "type": "Function",
12126              "optional": true
12127            }],
12128            "return": {
12129              "description": "",
12130              "type": "Promise"
12131            }
12132          }]
12133        }, {
12134          "file": "src/io/files.js",
12135          "line": 1183,
12136          "itemtype": "method",
12137          "name": "createWriter",
12138          "params": [{
12139            "name": "name",
12140            "description": "<p>name of the file to be created</p>\n",
12141            "type": "String"
12142          }, {
12143            "name": "extension",
12144            "description": "",
12145            "type": "String",
12146            "optional": true
12147          }],
12148          "return": {
12149            "description": "",
12150            "type": "p5.PrintWriter"
12151          },
12152          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100);\n  background(200);\n  text('click here to save', 10, 10, 70, 80);\n}\n\nfunction mousePressed() {\n  if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n    var writer = createWriter('squares.txt');\n    for (let i = 0; i < 10;
12152 i++) {\n      writer.print(i * i);\n    }\n    writer.close();\n    writer.clear();\n  }\n}\n</code>\n</div>"],
12153          "class": "p5",
12154          "module": "IO",
12155          "submodule": "Output"
12156        }, {
12157          "file": "src/io/files.js",
12158          "line": 1238,
12159          "description": "<p>Writes data to the PrintWriter stream</p>\n",
12160          "itemtype": "method",
12161          "name": "write",
12162          "params": [{
12163            "name": "data",
12164            "description": "<p>all data to be written by the PrintWriter</p>\n",
12165            "type": "Array"
12166          }],
12167          "example": ["\n<div class=\"norender notest\">\n<code>\n// creates a file called 'newFile.txt'\nlet writer = createWriter('newFile.txt');\n// write 'Hello world!'' to the file\nwriter.write(['Hello world!']);\n// close the PrintWriter and save the file\nwriter.close();\n</code>\n</div>\n<div class='norender notest'>\n<code>\n// creates a file called 'newFile2.txt'\nlet writer = createWriter('newFile2.txt');\n// write 'apples,bananas,123' to the file\nwriter.write(['apples', 'bananas', 123]);\n// close the PrintWriter and save the file\nwriter.close();\n</code>\n</div>\n<div class='norender notest'>\n<code>\n// creates a file called 'newFile3.txt'\nlet writer = createWriter('newFile3.txt');\n// write 'My name is: Teddy' to the file\nwriter.write('My name is:');\nwriter.write(' Teddy');\n// close the PrintWriter and save the file\nwriter.close();\n</code>\n</div>"],
12168          "class": "p5.PrintWriter",
12169          "module": "IO",
12170          "submodule": "Output"
12171        }, {
12172          "file": "src/io/files.js",
12173          "line": 1278,
12174          "description": "<p>Writes data to the PrintWriter stream, and adds a new line at the end</p>\n",
12175          "itemtype": "method",
12176          "name": "print",
12177          "params": [{
12178            "name": "data",
12179            "description": "<p>all data to be printed by the PrintWriter</p>\n",
12180            "type": "Array"
12181          }],
12182          "example": ["\n<div class='norender notest'>\n<code>\n// creates a file called 'newFile.txt'\nlet writer = createWriter('newFile.txt');\n// creates a file containing\n//  My name is:\n//  Teddy\nwriter.print('My name is:');\nwriter.print('Teddy');\n// close the PrintWriter and save the file\nwriter.close();\n</code>\n</div>\n<div class='norender notest'>\n<code>\nlet writer;\n\nfunction setup() {\n  createCanvas(400, 400);\n  // create a PrintWriter\n  writer = createWriter('newFile.txt');\n}\n\nfunction draw() {\n  // print all mouseX and mouseY coordinates to the stream\n  writer.print([mouseX, mouseY]);\n}\n\nfunction mouseClicked() {\n  // close the PrintWriter and save the file\n  writer.close();\n}\n</code>\n</div>"],
12183          "class": "p5.PrintWriter",
12184          "module": "IO",
12185          "submodule": "Output"
12186        }, {
12187          "file": "src/io/files.js",
12188          "line": 1321,
12189          "description": "<p>Clears the data already written to the PrintWriter object</p>\n",
12190          "itemtype": "method",
12191          "name": "clear",
12192          "example": ["\n<div class =\"norender notest\"><code>\n// create writer object\nlet writer = createWriter('newFile.txt');\nwriter.write(['clear me']);\n// clear writer object here\nwriter.clear();\n// close writer\nwriter.close();\n</code></div>\n"],
12193          "class": "p5.PrintWriter",
12194          "module": "IO",
12195          "submodule": "Output"
12196        }, {
12197          "file": "src/io/files.js",
12198          "line": 1339,
12199          "description": "<p>Closes the PrintWriter</p>\n",
12200          "itemtype": "method",
12201          "name": "close",
12202          "example": ["\n<div class=\"norender notest\">\n<code>\n// create a file called 'newFile.txt'\nlet writer = createWriter('newFile.txt');\n// close the PrintWriter and save the file\nwriter.close();\n</code>\n</div>\n<div class='norender notest'>\n<code>\n// create a file called 'newFile2.txt'\nlet writer = createWriter('newFile2.txt');\n// write some data to the file\nwriter.write([100, 101, 102]);\n// close the PrintWriter and save the file\nwriter.close();\n</code>\n</div>"],
12203          "class": "p5.PrintWriter",
12204          "module": "IO",
12205          "submodule": "Output"
12206        }, {
12207          "file": "src/io/files.js",
12208          "line": 1388,
12209          "description": "<p>Save an image, text, json, csv, wav, or html. Prompts download to\nthe client&#39;s computer. <b>Note that it is not recommended to call <a href=\"#/p5/save\">save()</a>\nwithin draw if it&#39;s looping, as the <a href=\"#/p5/save\">save()</a> function will open a new save\ndialog every frame.</b></p>\n<p>The default behavior is to save the canvas as an image. You can\noptionally specify a filename.\nFor example:</p>\n <pre class='language-javascript'><code>\n save();
12209\n save(&#39;myCanvas.jpg&#39;); // save a specific canvas with a filename\n </code></pre>\n\n<p>Alternately, the first parameter can be a pointer to a canvas\n<a href=\"#/p5.Element\">p5.Element</a>, an Array of Strings,\nan Array of JSON, a JSON object, a <a href=\"#/p5.Table\">p5.Table</a>, a <a href=\"#/p5.Image\">p5.Image</a>, or a\np5.SoundFile (requires p5.sound). The second parameter is a filename\n(including extension). The third parameter is for options specific\nto this type of object. This method will save a file that fits the\ngiven parameters. For example:</p>\n\n <pre class='language-javascript'><code>\n // Saves canvas as an image\n save('myCanvas.jpg');\n\n // Saves pImage as a png image\n let img = createImage(10, 10);\n save(img, 'my.png');\n\n // Saves canvas as an image\n let cnv = createCanvas(100, 100);\n save(cnv, 'myCanvas.jpg');\n\n // Saves p5.Renderer object as an image\n let gb = createGraphics(100, 100);\n save(gb, 'myGraphics.jpg');\n\n let myTable = new p5.Table();\n\n // Saves table as html file\n save(myTable, 'myTable.html');\n\n // Comma Separated Values\n save(myTable, 'myTable.csv');\n\n // Tab Separated Values\n save(myTable, 'myTable.tsv');\n\n let myJSON = { a: 1, b: true };\n\n // Saves pretty JSON\n save(myJSON, 'my.json');\n\n // Optimizes JSON filesize\n save(myJSON, 'my.json', true);\n\n // Saves array of strings to a text file with line breaks after each item\n let arrayOfStrings = ['a', 'b'];\n save(arrayOfStrings, 'my.txt');\n </code></pre>",
12210          "itemtype": "method",
12211          "name": "save",
12212          "params": [{
12213            "name": "objectOrFilename",
12214            "description": "<p>If filename is provided, will\n                                           save canvas as an image with\n                                           either png or jpg extension\n                                           depending on the filename.\n                                           If object is provided, will\n                                           save depending on the object\n                                           and filename (see examples\n                                           above).</p>\n",
12215            "type": "Object|String",
12216            "optional": true
12217          }, {
12218            "name": "filename",
12219            "description": "<p>If an object is provided as the first\n                             parameter, then the second parameter\n                             indicates the filename,\n                             and should include an appropriate\n                             file extension (see examples above).</p>\n",
12220            "type": "String",
12221            "optional": true
12222          }, {
12223            "name": "options",
12224            "description": "<p>Additional options depend on\n                          filetype. For example, when saving JSON,\n                          <code>true</code> indicates that the\n                          output will be optimized for filesize,\n                          rather than readability.</p>\n",
12225            "type": "Boolean|String",
12226            "optional": true
12227          }],
12228          "class": "p5",
12229          "module": "IO",
12230          "submodule": "Output"
12231        }, {
12232          "file": "src/io/files.js",
12233          "line": 1516,
12234          "description": "<p>Writes the contents of an Array or a JSON object to a .json file.\nThe file saving process and location of the saved file will\nvary between web browsers.</p>\n",
12235          "itemtype": "method",
12236          "name": "saveJSON",
12237          "params": [{
12238            "name": "json",
12239            "description": "",
12240            "type": "Array|Object"
12241          }, {
12242            "name": "filename",
12243            "description": "",
12244            "type": "String"
12245          }, {
12246            "name": "optimize",
12247            "description": "<p>If true, removes line breaks\n                               and spaces from the output\n                               file to optimize filesize\n                               (but not readability).</p>\n",
12248            "type": "Boolean",
12249            "optional": true
12250          }],
12251          "example": ["\n <div><code>\n let json = {}; // new  JSON Object\n\n json.id = 0;\n json.species = 'Panthera leo';\n json.name = 'Lion';\n\n function setup() {\n createCanvas(100, 100);\n background(200);\n text('click here to save', 10, 10, 70, 80);\n }\n\n function mousePressed() {\n if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n   saveJSON(json, 'lion.json');\n }\n }\n\n // saves the following to a file called \"lion.json\":\n // {\n //   \"id\": 0,\n //   \"species\": \"Panthera leo\",\n //   \"name\": \"Lion\"\n // }\n </code></div>"],
12252          "alt": "no image displayed",
12253          "class": "p5",
12254          "module": "IO",
12255          "submodule": "Output"
12256        }, {
12257          "file": "src/io/files.js",
12258          "line": 1574,
12259          "description": "<p>Writes an array of Strings to a text file, one line per String.\nThe file saving process and location of the saved file will\nvary between web browsers.</p>\n",
12260          "itemtype": "method",
12261          "name": "saveStrings",
12262          "params": [{
12263            "name": "list",
12264            "description": "<p>string array to be written</p>\n",
12265            "type": "String[]"
12266          }, {
12267            "name": "filename",
12268            "description": "<p>filename for output</p>\n",
12269            "type": "String"
12270          }, {
12271            "name": "extension",
12272            "description": "<p>the filename&#39;s extension</p>\n",
12273            "type": "String",
12274            "optional": true
12275          }],
12276          "example": ["\n <div><code>\n let words = 'apple bear cat dog';\n\n // .split() outputs an Array\n let list = split(words, ' ');\n\n function setup() {\n createCanvas(100, 100);\n background(200);\n text('click here to save', 10, 10, 70, 80);\n }\n\n function mousePressed() {\n if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n   saveStrings(list, 'nouns.txt');\n }\n }\n\n // Saves the following to a file called 'nouns.txt':\n //\n // apple\n // bear\n // cat\n // dog\n </code></div>"],
12277          "alt": "no image displayed",
12278          "class": "p5",
12279          "module": "IO",
12280          "submodule": "Output"
12281        }, {
12282          "file": "src/io/files.js",
12283          "line": 1642,
12284          "description": "<p>Writes the contents of a <a href=\"#/p5.Table\">Table</a> object to a file. Defaults to a\ntext file with comma-separated-values (&#39;csv&#39;) but can also\nuse tab separation (&#39;tsv&#39;), or generate an HTML table (&#39;html&#39;).\nThe file saving process and location of the saved file will\nvary between web browsers.</p>\n",
12285          "itemtype": "method",
12286          "name": "saveTable",
12287          "params": [{
12288            "name": "Table",
12289            "description": "<p>the <a href=\"#/p5.Table\">Table</a> object to save to a file</p>\n",
12290            "type": "p5.Table"
12291          }, {
12292            "name": "filename",
12293            "description": "<p>the filename to which the Table should be saved</p>\n",
12294            "type": "String"
12295          }, {
12296            "name": "options",
12297            "description": "<p>can be one of &quot;tsv&quot;, &quot;csv&quot;, or &quot;html&quot;</p>\n",
12298            "type": "String",
12299            "optional": true
12300          }],
12301          "example": ["\n<div><code>\n let table;\n\n function setup() {\n table = new p5.Table();\n\n table.addColumn('id');\n table.addColumn('species');\n table.addColumn('name');\n\n let newRow = table.addRow();\n newRow.setNum('id', table.getRowCount() - 1);\n newRow.setString('species', 'Panthera leo');\n newRow.setString('name', 'Lion');\n\n // To save, un-comment next line then click 'run'\n // saveTable(table, 'new.csv');\n }\n\n // Saves the following to a file called 'new.csv':\n // id,species,name\n // 0,Panthera leo,Lion\n </code></div>"],
12302          "alt": "no image displayed",
12303          "class": "p5",
12304          "module": "IO",
12305          "submodule": "Output"
12306        }, {
12307          "file": "src/io/p5.Table.js",
12308          "line": 11,
12309          "description": "<p>Table Options</p>\n<p>Generic class for handling tabular data, typically from a\nCSV, TSV, or other sort of spreadsheet file.</p>\n<p>CSV files are\n<a href=\"http://en.wikipedia.org/wiki/Comma-separated_values\">\ncomma separated values</a>, often with the data in quotes. TSV\nfiles use tabs as separators, and usually don&#39;t bother with the\nquotes.</p>\n<p>File names should end with .csv if they&#39;re comma separated.</p>\n<p>A rough &quot;spec&quot; for CSV can be found\n<a href=\"http://tools.ietf.org/html/rfc4180\">here</a>.</p>\n<p>To load files, use the <a href=\"#/p5/loadTable\">loadTable</a> method.</p>\n<p>To save tables to your computer, use the <a href=\"#/p5/save\">save</a> method\n or the <a href=\"#/p5/saveTable\">saveTable</a> method.</p>\n\n<p>Possible options include:</p>\n<ul>\n<li>csv - parse the table as comma-separated values\n<li>tsv - parse the table as tab-separated values\n<li>header - this table has a header (title) row\n</ul>",
12310          "class": "p5.Table",
12311          "module": "IO",
12312          "submodule": "Table"
12313        }, {
12314          "file": "src/io/p5.Table.js",
12315          "line": 45,
12316          "itemtype": "property",
12317          "name": "columns",
12318          "type": "String[]",
12319          "class": "p5.Table",
12320          "module": "IO",
12321          "submodule": "Table"
12322        }, {
12323          "file": "src/io/p5.Table.js",
12324          "line": 50,
12325          "itemtype": "property",
12326          "name": "rows",
12327          "type": "p5.TableRow[]",
12328          "class": "p5.Table",
12329          "module": "IO",
12330          "submodule": "Table"
12331        }, {
12332          "file": "src/io/p5.Table.js",
12333          "line": 56,
12334          "description": "<p>Use <a href=\"#/p5/addRow\">addRow()</a> to add a new row of data to a <a href=\"#/p5.Table\">p5.Table</a> object. By default,\nan empty row is created. Typically, you would store a reference to\nthe new row in a TableRow object (see newRow in the example above),\nand then set individual values using <a href=\"#/p5/set\">set()</a>.</p>\n<p>If a <a href=\"#/p5.TableRow\">p5.TableRow</a> object is included as a parameter, then that row is\nduplicated and added to the table.</p>\n",
12335          "itemtype": "method",
12336          "name": "addRow",
12337          "params": [{
12338            "name": "row",
12339            "description": "<p>row to be added to the table</p>\n",
12340            "type": "p5.TableRow",
12341            "optional": true
12342          }],
12343          "return": {
12344            "description": "the row that was added",
12345            "type": "p5.TableRow"
12346          },
12347          "example": ["\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n //add a row\n let newRow = table.addRow();\n newRow.setString('id', table.getRowCount() - 1);\n newRow.setString('species', 'Canis Lupus');\n newRow.setString('name', 'Wolf');\n\n //print the results\n for (let r = 0; r < table.getRowCount(); r++)\n   for (let c = 0; c < table.getColumnCount(); c++)\n     print(table.getString(r, c));\n }\n </code>\n </div>"],
12348          "alt": "no image displayed",
12349          "class": "p5.Table",
12350          "module": "IO",
12351          "submodule": "Table"
12352        }, {
12353          "file": "src/io/p5.Table.js",
12354          "line": 120,
12355          "description": "<p>Removes a row from the table object.</p>\n",
12356          "itemtype": "method",
12357          "name": "removeRow",
12358          "params": [{
12359            "name": "id",
12360            "description": "<p>ID number of the row to remove</p>\n",
12361            "type": "Integer"
12362          }],
12363          "example": ["\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nlet table;\n\nfunction preload() {\n  //my table is comma separated value \"csv\"\n  //and has a header specifying the columns labels\n  table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n  //remove the first row\n  table.removeRow(0);\n\n  //print the results\n  for (let r = 0; r < table.getRowCount(); r++)\n    for (let c = 0; c < table.getColumnCount(); c++)\n      print(table.getString(r, c));\n}\n</code>\n</div>"],
12364          "alt": "no image displayed",
12365          "class": "p5.Table",
12366          "module": "IO",
12367          "submodule": "Table"
12368        }, {
12369          "file": "src/io/p5.Table.js",
12370          "line": 168,
12371          "description": "<p>Returns a reference to the specified <a href=\"#/p5.TableRow\">p5.TableRow</a>. The reference\ncan then be used to get and set values of the selected row.</p>\n",
12372          "itemtype": "method",
12373          "name": "getRow",
12374          "params": [{
12375            "name": "rowID",
12376            "description": "<p>ID number of the row to get</p>\n",
12377            "type": "Integer"
12378          }],
12379          "return": {
12380            "description": "<a href=\"#/p5.TableRow\">p5.TableRow</a> object",
12381            "type": "p5.TableRow"
12382          },
12383          "example": ["\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nlet table;\n\nfunction preload() {\n  //my table is comma separated value \"csv\"\n  //and has a header specifying the columns labels\n  table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n  let row = table.getRow(1);\n  //print it column by column\n  //note: a row is an object, not an array\n  for (let c = 0; c < table.getColumnCount(); c++) {\n    print(row.getString(c));\n  }\n}\n</code>\n</div>"],
12384          "alt": "no image displayed",
12385          "class": "p5.Table",
12386          "module": "IO",
12387          "submodule": "Table"
12388        }, {
12389          "file": "src/io/p5.Table.js",
12390          "line": 214,
12391          "description": "<p>Gets all rows from the table. Returns an array of <a href=\"#/p5.TableRow\">p5.TableRow</a>s.</p>\n",
12392          "itemtype": "method",
12393          "name": "getRows",
12394          "return": {
12395            "description": "Array of <a href=\"#/p5.TableRow\">p5.TableRow</a>s",
12396            "type": "p5.TableRow[]"
12397          },
12398          "example": ["\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n let rows = table.getRows();\n\n //warning: rows is an array of objects\n for (let r = 0; r < rows.length; r++) {\n   rows[r].set('name', 'Unicorn');\n }\n\n //print the results\n for (let r = 0; r < table.getRowCount(); r++)\n   for (let c = 0; c < table.getColumnCount(); c++)\n     print(table.getString(r, c));\n }\n </code>\n </div>"],
12399          "alt": "no image displayed",
12400          "class": "p5.Table",
12401          "module": "IO",
12402          "submodule": "Table"
12403        }, {
12404          "file": "src/io/p5.Table.js",
12405          "line": 263,
12406          "description": "<p>Finds the first row in the Table that contains the value\nprovided, and returns a reference to that row. Even if\nmultiple rows are possible matches, only the first matching\nrow is returned. The column to search may be specified by\neither its ID or title.</p>\n",
12407          "itemtype": "method",
12408          "name": "findRow",
12409          "params": [{
12410            "name": "value",
12411            "description": "<p>The value to match</p>\n",
12412            "type": "String"
12413          }, {
12414            "name": "column",
12415            "description": "<p>ID number or title of the\n                               column to search</p>\n"
12415,
12416            "type": "Integer|String"
12417          }],
12418          "return": {
12419            "description": "",
12420            "type": "p5.TableRow"
12421          },
12422          "example": ["\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n //find the animal named zebra\n let row = table.findRow('Zebra', 'name');\n //find the corresponding species\n print(row.getString('species'));\n }\n </code>\n </div>"],
12423          "alt": "no image displayed",
12424          "class": "p5.Table",
12425          "module": "IO",
12426          "submodule": "Table"
12427        }, {
12428          "file": "src/io/p5.Table.js",
12429          "line": 328,
12430          "description": "<p>Finds the rows in the Table that contain the value\nprovided, and returns references to those rows. Returns an\nArray, so for must be used to iterate through all the rows,\nas shown in the example above. The column to search may be\nspecified by either its ID or title.</p>\n",
12431          "itemtype": "method",
12432          "name": "findRows",
12433          "params": [{
12434            "name": "value",
12435            "description": "<p>The value to match</p>\n",
12436            "type": "String"
12437          }, {
12438            "name": "column",
12439            "description": "<p>ID number or title of the\n                               column to search</p>\n",
12440            "type": "Integer|String"
12441          }],
12442          "return": {
12443            "description": "An Array of TableRow objects",
12444            "type": "p5.TableRow[]"
12445          },
12446          "example": ["\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n //add another goat\n let newRow = table.addRow();\n newRow.setString('id', table.getRowCount() - 1);\n newRow.setString('species', 'Scape Goat');\n newRow.setString('name', 'Goat');\n\n //find the rows containing animals named Goat\n let rows = table.findRows('Goat', 'name');\n print(rows.length + ' Goats found');\n }\n </code>\n </div>"],
12447          "alt": "no image displayed",
12448          "class": "p5.Table",
12449          "module": "IO",
12450          "submodule": "Table"
12451        }, {
12452          "file": "src/io/p5.Table.js",
12453          "line": 397,
12454          "description": "<p>Finds the first row in the Table that matches the regular\nexpression provided, and returns a reference to that row.\nEven if multiple rows are possible matches, only the first\nmatching row is returned. The column to search may be\nspecified by either its ID or title.</p>\n",
12455          "itemtype": "method",
12456          "name": "matchRow",
12457          "params": [{
12458            "name": "regexp",
12459            "description": "<p>The regular expression to match</p>\n",
12460            "type": "String|RegExp"
12461          }, {
12462            "name": "column",
12463            "description": "<p>The column ID (number) or\n                                 title (string)</p>\n",
12464            "type": "String|Integer"
12465          }],
12466          "return": {
12467            "description": "TableRow object",
12468            "type": "p5.TableRow"
12469          },
12470          "example": ["\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nlet table;\n\nfunction preload() {\n  //my table is comma separated value \"csv\"\n  //and has a header specifying the columns labels\n  table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n  //Search using specified regex on a given column, return TableRow object\n  let mammal = table.matchRow(new RegExp('ant'), 1);\n  print(mammal.getString(1));\n  //Output \"Panthera pardus\"\n}\n</code>\n</div>\n"],
12471          "class": "p5.Table",
12472          "module": "IO",
12473          "submodule": "Table"
12474        }, {
12475          "file": "src/io/p5.Table.js",
12476          "line": 456,
12477          "description": "<p>Finds the rows in the Table that match the regular expression provided,\nand returns references to those rows. Returns an array, so for must be\nused to iterate through all the rows, as shown in the example. The\ncolumn to search may be specified by either its ID or title.</p>\n",
12478          "itemtype": "method",
12479          "name": "matchRows",
12480          "params": [{
12481            "name": "regexp",
12482            "description": "<p>The regular expression to match</p>\n",
12483            "type": "String"
12484          }, {
12485            "name": "column",
12486            "description": "<p>The column ID (number) or\n                                 title (string)</p>\n",
12487            "type": "String|Integer",
12488            "optional": true
12489          }],
12490          "return": {
12491            "description": "An Array of TableRow objects",
12492            "type": "p5.TableRow[]"
12493          },
12494          "example": ["\n<div class=\"norender\">\n<code>\nlet table;\n\nfunction setup() {\n  table = new p5.Table();\n\n  table.addColumn('name');\n  table.addColumn('type');\n\n  let newRow = table.addRow();\n  newRow.setString('name', 'Lion');\n  newRow.setString('type', 'Mammal');\n\n  newRow = table.addRow();\n  newRow.setString('name', 'Snake');\n  newRow.setString('type', 'Reptile');\n\n  newRow = table.addRow();\n  newRow.setString('name', 'Mosquito');\n  newRow.setString('type', 'Insect');\n\n  newRow = table.addRow();\n  newRow.setString('name', 'Lizard');\n  newRow.setString('type', 'Reptile');\n\n  let rows = table.matchRows('R.*', 'type');\n  for (let i = 0; i < rows.length;
12494 i++) {\n    print(rows[i].getString('name') + ': ' + rows[i].getString('type'));\n  }\n}\n// Sketch prints:\n// Snake: Reptile\n// Lizard: Reptile\n</code>\n</div>"],
12495          "class": "p5.Table",
12496          "module": "IO",
12497          "submodule": "Table"
12498        }, {
12499          "file": "src/io/p5.Table.js",
12500          "line": 523,
12501          "description": "<p>Retrieves all values in the specified column, and returns them\nas an array. The column may be specified by either its ID or title.</p>\n",
12502          "itemtype": "method",
12503          "name": "getColumn",
12504          "params": [{
12505            "name": "column",
12506            "description": "<p>String or Number of the column to return</p>\n",
12507            "type": "String|Number"
12508          }],
12509          "return": {
12510            "description": "Array of column values",
12511            "type": "Array"
12512          },
12513          "example": ["\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n //getColumn returns an array that can be printed directly\n print(table.getColumn('species'));\n //outputs [\"Capra hircus\", \"Panthera pardus\", \"Equus zebra\"]\n }\n </code>\n </div>"],
12514          "alt": "no image displayed",
12515          "class": "p5.Table",
12516          "module": "IO",
12517          "submodule": "Table"
12518        }, {
12519          "file": "src/io/p5.Table.js",
12520          "line": 576,
12521          "description": "<p>Removes all rows from a Table. While all rows are removed,\ncolumns and column titles are maintained.</p>\n",
12522          "itemtype": "method",
12523          "name": "clearRows",
12524          "example": ["\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n table.clearRows();\n print(table.getRowCount() + ' total rows in table');\n print(table.getColumnCount() + ' total columns in table');\n }\n </code>\n </div>"],
12525          "alt": "no image displayed",
12526          "class": "p5.Table",
12527          "module": "IO",
12528          "submodule": "Table"
12529        }, {
12530          "file": "src/io/p5.Table.js",
12531          "line": 618,
12532          "description": "<p>Use <a href=\"#/p5/addColumn\">addColumn()</a> to add a new column to a <a href=\"#/p5.Table\">Table</a> object.\nTypically, you will want to specify a title, so the column\nmay be easily referenced later by name. (If no title is\nspecified, the new column&#39;s title will be null.)</p>\n",
12533          "itemtype": "method",
12534          "name": "addColumn",
12535          "params": [{
12536            "name": "title",
12537            "description": "<p>title of the given column</p>\n",
12538            "type": "String",
12539            "optional": true
12540          }],
12541          "example": ["\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n table.addColumn('carnivore');\n table.set(0, 'carnivore', 'no');\n table.set(1, 'carnivore', 'yes');\n table.set(2, 'carnivore', 'no');\n\n //print the results\n for (let r = 0; r < table.getRowCount(); r++)\n   for (let c = 0; c < table.getColumnCount(); c++)\n     print(table.getString(r, c));\n }\n </code>\n </div>"],
12542          "alt": "no image displayed",
12543          "class": "p5.Table",
12544          "module": "IO",
12545          "submodule": "Table"
12546        }, {
12547          "file": "src/io/p5.Table.js",
12548          "line": 669,
12549          "description": "<p>Returns the total number of columns in a Table.</p>\n",
12550          "itemtype": "method",
12551          "name": "getColumnCount",
12552          "return": {
12553            "description": "Number of columns in this table",
12554            "type": "Integer"
12555          },
12556          "example": ["\n <div>\n <code>\n // given the cvs file \"blobs.csv\" in /assets directory\n // ID, Name, Flavor, Shape, Color\n // Blob1, Blobby, Sweet, Blob, Pink\n // Blob2, Saddy, Savory, Blob, Blue\n\n let table;\n\n function preload() {\n table = loadTable('assets/blobs.csv');\n }\n\n function setup() {\n createCanvas(200, 100);\n textAlign(CENTER);\n background(255);\n }\n\n function draw() {\n let numOfColumn = table.getColumnCount();\n text('There are ' + numOfColumn + ' columns in the table.', 100, 50);\n }\n </code>\n </div>"],
12557          "class": "p5.Table",
12558          "module": "IO",
12559          "submodule": "Table"
12560        }, {
12561          "file": "src/io/p5.Table.js",
12562          "line": 705,
12563          "description": "<p>Returns the total number of rows in a Table.</p>\n",
12564          "itemtype": "method",
12565          "name": "getRowCount",
12566          "return": {
12567            "description": "Number of rows in this table",
12568            "type": "Integer"
12569          },
12570          "example": ["\n <div>\n <code>\n // given the cvs file \"blobs.csv\" in /assets directory\n //\n // ID, Name, Flavor, Shape, Color\n // Blob1, Blobby, Sweet, Blob, Pink\n // Blob2, Saddy, Savory, Blob, Blue\n\n let table;\n\n function preload() {\n table = loadTable('assets/blobs.csv');\n }\n\n function setup() {\n createCanvas(200, 100);\n textAlign(CENTER);\n background(255);\n }\n\n function draw() {\n text('There are ' + table.getRowCount() + ' rows in the table.', 100, 50);\n }\n </code>\n </div>"],
12571          "class": "p5.Table",
12572          "module": "IO",
12573          "submodule": "Table"
12574        }, {
12575          "file": "src/io/p5.Table.js",
12576          "line": 741,
12577          "description": "<p>Removes any of the specified characters (or &quot;tokens&quot;).</p>\n\n<p>If no column is specified, then the values in all columns and\nrows are processed. A specific column may be referenced by\neither its ID or title.</p>",
12578          "itemtype": "method",
12579          "name": "removeTokens",
12580          "params": [{
12581            "name": "chars",
12582            "description": "<p>String listing characters to be removed</p>\n",
12583            "type": "String"
12584          }, {
12585            "name": "column",
12586            "description": "<p>Column ID (number)\n                                 or name (string)</p>\n",
12587            "type": "String|Integer",
12588            "optional": true
12589          }],
12590          "example": ["\n <div class=\"norender\"><code>\n function setup() {\n let table = new p5.Table();\n\n table.addColumn('name');\n table.addColumn('type');\n\n let newRow = table.addRow();\n newRow.setString('name', '   $Lion  ,');\n newRow.setString('type', ',,,Mammal');\n\n newRow = table.addRow();\n newRow.setString('name', '$Snake  ');\n newRow.setString('type', ',,,Reptile');\n\n table.removeTokens(',$ ');\n print(table.getArray());\n }\n\n // prints:\n //  0  \"Lion\"   \"Mamal\"\n //  1  \"Snake\"  \"Reptile\"\n </code></div>"],
12591          "class": "p5.Table",
12592          "module": "IO",
12593          "submodule": "Table"
12594        }, {
12595          "file": "src/io/p5.Table.js",
12596          "line": 815,
12597          "description": "<p>Trims leading and trailing whitespace, such as spaces and tabs,\nfrom String table values. If no column is specified, then the\nvalues in all columns and rows are trimmed. A specific column\nmay be referenced by either its ID or title.</p>\n",
12598          "itemtype": "method",
12599          "name": "trim",
12600          "params": [{
12601            "name": "column",
12602            "description": "<p>Column ID (number)\n                                 or name (string)</p>\n",
12603            "type": "String|Integer",
12604            "optional": true
12605          }],
12606          "example": ["\n <div class=\"norender\"><code>\n function setup() {\n let table = new p5.Table();\n\n table.addColumn('name');\n table.addColumn('type');\n\n let newRow = table.addRow();\n newRow.setString('name', '   Lion  ,');\n newRow.setString('type', ' Mammal  ');\n\n newRow = table.addRow();\n newRow.setString('name', '  Snake  ');\n newRow.setString('type', '  Reptile  ');\n\n table.trim();\n print(table.getArray());\n }\n\n // prints:\n //  0  \"Lion\"   \"Mamal\"\n //  1  \"Snake\"  \"Reptile\"\n </code></div>"],
12607          "class": "p5.Table",
12608          "module": "IO",
12609          "submodule": "Table"
12610        }, {
12611          "file": "src/io/p5.Table.js",
12612          "line": 879,
12613          "description": "<p>
12613Use <a href=\"#/p5/removeColumn\">removeColumn()</a> to remove an existing column from a Table\nobject. The column to be removed may be identified by either\nits title (a String) or its index value (an int).\nremoveColumn(0) would remove the first column, removeColumn(1)\nwould remove the second column, and so on.</p>\n",
12614          "itemtype": "method",
12615          "name": "removeColumn",
12616          "params": [{
12617            "name": "column",
12618            "description": "<p>columnName (string) or ID (number)</p>\n",
12619            "type": "String|Integer"
12620          }],
12621          "example": ["\n <div class=\"norender\">\n <code>\n // Given the CSV file \"mammals.csv\"\n // in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n table.removeColumn('id');\n print(table.getColumnCount());\n }\n </code>\n </div>"],
12622          "alt": "no image displayed",
12623          "class": "p5.Table",
12624          "module": "IO",
12625          "submodule": "Table"
12626        }, {
12627          "file": "src/io/p5.Table.js",
12628          "line": 944,
12629          "description": "<p>Stores a value in the Table&#39;s specified row and column.\nThe row is specified by its ID, while the column may be specified\nby either its ID or title.</p>\n",
12630          "itemtype": "method",
12631          "name": "set",
12632          "params": [{
12633            "name": "row",
12634            "description": "<p>row ID</p>\n",
12635            "type": "Integer"
12636          }, {
12637            "name": "column",
12638            "description": "<p>column ID (Number)\n                              or title (String)</p>\n",
12639            "type": "String|Integer"
12640          }, {
12641            "name": "value",
12642            "description": "<p>value to assign</p>\n",
12643            "type": "String|Number"
12644          }],
12645          "example": ["\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nlet table;\n\nfunction preload() {\n  //my table is comma separated value \"csv\"\n  //and has a header specifying the columns labels\n  table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n  table.set(0, 'species', 'Canis Lupus');\n  table.set(0, 'name', 'Wolf');\n\n  //print the results\n  for (let r = 0; r < table.getRowCount(); r++)\n    for (let c = 0; c < table.getColumnCount(); c++)\n      print(table.getString(r, c));\n}\n</code>\n</div>"],
12646          "alt": "no image displayed",
12647          "class": "p5.Table",
12648          "module": "IO",
12649          "submodule": "Table"
12650        }, {
12651          "file": "src/io/p5.Table.js",
12652          "line": 994,
12653          "description": "<p>Stores a Float value in the Table&#39;s specified row and column.\nThe row is specified by its ID, while the column may be specified\nby either its ID or title.</p>\n",
12654          "itemtype": "method",
12655          "name": "setNum",
12656          "params": [{
12657            "name": "row",
12658            "description": "<p>row ID</p>\n",
12659            "type": "Integer"
12660          }, {
12661            "name": "column",
12662            "description": "<p>column ID (Number)\n                              or title (String)</p>\n",
12663            "type": "String|Integer"
12664          }, {
12665            "name": "value",
12666            "description": "<p>value to assign</p>\n",
12667            "type": "Number"
12668          }],
12669          "example": ["\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nlet table;\n\nfunction preload() {\n  //my table is comma separated value \"csv\"\n  //and has a header specifying the columns labels\n  table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n  table.setNum(1, 'id', 1);\n\n  print(table.getColumn(0));\n  //[\"0\", 1, \"2\"]\n}\n</code>\n</div>"],
12670          "alt": "no image displayed",
12671          "class": "p5.Table",
12672          "module": "IO",
12673          "submodule": "Table"
12674        }, {
12675          "file": "src/io/p5.Table.js",
12676          "line": 1040,
12677          "description": "<p>Stores a String value in the Table&#39;s specified row and column.\nThe row is specified by its ID, while the column may be specified\nby either its ID or title.</p>\n",
12678          "itemtype": "method",
12679          "name": "setString",
12680          "params": [{
12681            "name": "row",
12682            "description": "<p>row ID</p>\n",
12683            "type": "Integer"
12684          }, {
12685            "name": "column",
12686            "description": "<p>column ID (Number)\n                              or title (String)</p>\n",
12687            "type": "String|Integer"
12688          }, {
12689            "name": "value",
12690            "description": "<p>value to assign</p>\n",
12691            "type": "String"
12692          }],
12693          "example": ["\n<div class=\"norender\"><code>\n// Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nlet table;\n\nfunction preload() {\n  //my table is comma separated value \"csv\"\n  //and has a header specifying the columns labels\n  table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n  //add a row\n  let newRow = table.addRow();\n  newRow.setString('id', table.getRowCount() - 1);\n  newRow.setString('species', 'Canis Lupus');\n  newRow.setString('name', 'Wolf');\n\n  print(table.getArray());\n}\n</code></div>"],
12694          "alt": "no image displayed",
12695          "class": "p5.Table",
12696          "module": "IO",
12697          "submodule": "Table"
12698        }, {
12699          "file": "src/io/p5.Table.js",
12700          "line": 1085,
12701          "description": "<p>Retrieves a value from the Table&#39;s specified row and column.\nThe row is specified by its ID, while the column may be specified by\neither its ID or title.</p>\n",
12702          "itemtype": "method",
12703          "name": "get",
12704          "params": [{
12705            "name": "row",
12706            "description": "<p>row ID</p>\n",
12707            "type": "Integer"
12708          }, {
12709            "name": "column",
12710            "description": "<p>columnName (string) or\n                                  ID (number)</p>\n",
12711            "type": "String|Integer"
12712          }],
12713          "return": {
12714            "description": "",
12715            "type": "String|Number"
12716          },
12717          "example": ["\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nlet table;\n\nfunction preload() {\n  //my table is comma separated value \"csv\"\n  //and has a header specifying the columns labels\n  table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n  print(table.get(0, 1));\n  //Capra hircus\n  print(table.get(0, 'species'));\n  //Capra hircus\n}\n</code>\n</div>"],
12718          "alt": "no image displayed",
12719          "class": "p5.Table",
12720          "module": "IO",
12721          "submodule": "Table"
12722        }, {
12723          "file": "src/io/p5.Table.js",
12724          "line": 1132,
12725          "description": "<p>Retrieves a Float value from the Table&#39;s specified row and column.\nThe row is specified by its ID, while the column may be specified by\neither its ID or title.</p>\n",
12726          "itemtype": "method",
12727          "name": "getNum",
12728          "params": [{
12729            "name": "row",
12730            "description": "<p>row ID</p>\n",
12731            "type": "Integer"
12732          }, {
12733            "name": "column",
12734            "description": "<p>columnName (string) or\n                                  ID (number)</p>\n",
12735            "type": "String|Integer"
12736          }],
12737          "return": {
12738            "description": "",
12739            "type": "Number"
12740          },
12741          "example": ["\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nlet table;\n\nfunction preload() {\n  //my table is comma separated value \"csv\"\n  //and has a header specifying the columns labels\n  table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n  print(table.getNum(1, 0) + 100);\n  //id 1 + 100 = 101\n}\n</code>\n</div>"],
12742          "alt": "no image displayed",
12743          "class": "p5.Table",
12744          "module": "IO",
12745          "submodule": "Table"
12746        }, {
12747          "file": "src/io/p5.Table.js",
12748          "line": 1177,
12749          "description": "<p>Retrieves a String value from the Table&#39;s specified row and column.\nThe row is specified by its ID, while the column may be specified by\neither its ID or title.</p>\n",
12750          "itemtype": "method",
12751          "name": "getString",
12752          "params": [{
12753            "name": "row",
12754            "description": "<p>row ID</p>\n",
12755            "type": "Integer"
12756          }, {
12757            "name": "column",
12758            "description": "<p>columnName (string) or\n                                  ID (number)</p>\n",
12759            "type": "String|Integer"
12760          }],
12761          "return": {
12762            "description": "",
12763            "type": "String"
12764          },
12765          "example": ["\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nlet table;\n\nfunction preload() {\n  // table is comma separated value \"CSV\"\n  // and has specifiying header for column labels\n  table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n  print(table.getString(0, 0)); // 0\n  print(table.getString(0, 1)); // Capra hircus\n  print(table.getString(0, 2)); // Goat\n  print(table.getString(1, 0)); // 1\n  print(table.getString(1, 1)); // Panthera pardus\n  print(table.getString(1, 2)); // Leopard\n  print(table.getString(2, 0)); // 2\n  print(table.getString(2, 1)); // Equus zebra\n  print(table.getString(2, 2)); // Zebra\n}\n</code>\n</div>"],
12766          "alt": "no image displayed",
12767          "class": "p5.Table",
12768          "module": "IO",
12769          "submodule": "Table"
12770        }, {
12771          "file": "src/io/p5.Table.js",
12772          "line": 1230,
12773          "description": "<p>Retrieves all table data and returns as an object. If a column name is\npassed in, each row object will be stored with that attribute as its\ntitle.</p>\n",
12774          "itemtype": "method",
12775          "name": "getObject",
12776          "params": [{
12777            "name": "headerColumn",
12778            "description": "<p>Name of the column which should be used to\n                             title each row object (optional)</p>\n",
12779            "type": "String",
12780            "optional": true
12781          }],
12782          "return": {
12783            "description": "",
12784            "type": "Object"
12785          },
12786          "example": ["\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder:\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leopard\n// 2,Equus zebra,Zebra\n\nlet table;\n\nfunction preload() {\n  //my table is comma separated value \"csv\"\n  //and has a header specifying the columns labels\n  table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n  let tableObject = table.getObject();\n\n  print(tableObject);\n  //outputs an object\n}\n</code>\n</div>"],
12787          "alt": "no image displayed",
12788          "class": "p5.Table",
12789          "module": "IO",
12790          "submodule": "Table"
12791        }, {
12792          "file": "src/io/p5.Table.js",
12793          "line": 1296,
12794          "description": "<p>Retrieves all table data and returns it as a multidimensional array.</p>\n",
12795          "itemtype": "method",
12796          "name": "getArray",
12797          "return": {
12798            "description": "",
12799            "type": "Array"
12800          },
12801          "example": ["\n<div class=\"norender\">\n<code>\n// Given the CSV file \"mammals.csv\"\n// in the project's \"assets\" folder\n//\n// id,species,name\n// 0,Capra hircus,Goat\n// 1,Panthera pardus,Leoperd\n// 2,Equus zebra,Zebra\n\nlet table;\n\nfunction preload() {\n  // table is comma separated value \"CSV\"\n  // and has specifiying header for column labels\n  table = loadTable('assets/mammals.csv', 'csv', 'header');\n}\n\nfunction setup() {\n  let tableArray = table.getArray();\n  for (let i = 0; i < tableArray.length;
12801 i++) {\n    print(tableArray[i]);\n  }\n}\n</code>\n</div>"],
12802          "alt": "no image displayed",
12803          "class": "p5.Table",
12804          "module": "IO",
12805          "submodule": "Table"
12806        }, {
12807          "file": "src/io/p5.TableRow.js",
12808          "line": 42,
12809          "description": "<p>Stores a value in the TableRow&#39;s specified column.\nThe column may be specified by either its ID or title.</p>\n",
12810          "itemtype": "method",
12811          "name": "set",
12812          "params": [{
12813            "name": "column",
12814            "description": "<p>Column ID (Number)\n                              or Title (String)</p>\n",
12815            "type": "String|Integer"
12816          }, {
12817            "name": "value",
12818            "description": "<p>The value to be stored</p>\n",
12819            "type": "String|Number"
12820          }],
12821          "example": ["\n <div class=\"norender\"><code>\n // Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n let rows = table.getRows();\n for (let r = 0; r < rows.length; r++) {\n   rows[r].set('name', 'Unicorn');\n }\n\n //print the results\n print(table.getArray());\n }\n </code></div>"],
12822          "alt": "no image displayed",
12823          "class": "p5.TableRow",
12824          "module": "IO",
12825          "submodule": "Table"
12826        }, {
12827          "file": "src/io/p5.TableRow.js",
12828          "line": 106,
12829          "description": "<p>Stores a Float value in the TableRow&#39;s specified column.\nThe column may be specified by either its ID or title.</p>\n",
12830          "itemtype": "method",
12831          "name": "setNum",
12832          "params": [{
12833            "name": "column",
12834            "description": "<p>Column ID (Number)\n                              or Title (String)</p>\n",
12835            "type": "String|Integer"
12836          }, {
12837            "name": "value",
12838            "description": "<p>The value to be stored\n                              as a Float</p>\n",
12839            "type": "Number|String"
12840          }],
12841          "example": ["\n <div class=\"norender\"><code>\n // Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n let rows = table.getRows();\n for (let r = 0; r < rows.length; r++) {\n   rows[r].setNum('id', r + 10);\n }\n\n print(table.getArray());\n }\n </code></div>"],
12842          "alt": "no image displayed",
12843          "class": "p5.TableRow",
12844          "module": "IO",
12845          "submodule": "Table"
12846        }, {
12847          "file": "src/io/p5.TableRow.js",
12848          "line": 150,
12849          "description": "<p>Stores a String value in the TableRow&#39;s specified column.\nThe column may be specified by either its ID or title.</p>\n",
12850          "itemtype": "method",
12851          "name": "setString",
12852          "params": [{
12853            "name": "column",
12854            "description": "<p>Column ID (Number)\n                              or Title (String)</p>\n",
12855            "type": "String|Integer"
12856          }, {
12857            "name": "value",
12858            "description": "<p>The value to be stored\n                              as a String</p>\n",
12859            "type": "String|Number|Boolean|Object"
12860          }],
12861          "example": ["\n <div class=\"norender\"><code>\n // Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n let rows = table.getRows();\n for (let r = 0; r < rows.length; r++) {\n   let name = rows[r].getString('name');\n   rows[r].setString('name', 'A ' + name + ' named George');\n }\n\n print(table.getArray());\n }\n </code></div>"],
12862          "alt": "no image displayed",
12863          "class": "p5.TableRow",
12864          "module": "IO",
12865          "submodule": "Table"
12866        }, {
12867          "file": "src/io/p5.TableRow.js",
12868          "line": 195,
12869          "description": "<p>Retrieves a value from the TableRow&#39;s specified column.\nThe column may be specified by either its ID or title.</p>\n",
12870          "itemtype": "method",
12871          "name": "get",
12872          "params": [{
12873            "name": "column",
12874            "description": "<p>columnName (string) or\n                                 ID (number)</p>\n",
12875            "type": "String|Integer"
12876          }],
12877          "return": {
12878            "description": "",
12879            "type": "String|Number"
12880          },
12881          "example": ["\n <div class=\"norender\"><code>\n // Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n let names = [];\n let rows = table.getRows();\n for (let r = 0; r < rows.length; r++) {\n   names.push(rows[r].get('name'));\n }\n\n print(names);\n }\n </code></div>"],
12882          "alt": "no image displayed",
12883          "class": "p5.TableRow",
12884          "module": "IO",
12885          "submodule": "Table"
12886        }, {
12887          "file": "src/io/p5.TableRow.js",
12888          "line": 243,
12889          "description": "<p>Retrieves a Float value from the TableRow&#39;s specified\ncolumn. The column may be specified by either its ID or\ntitle.</p>\n",
12890          "itemtype": "method",
12891          "name": "getNum",
12892          "params": [{
12893            "name": "column",
12894            "description": "<p>columnName (string) or\n                                 ID (number)</p>\n",
12895            "type": "String|Integer"
12896          }],
12897          "return": {
12898            "description": "Float Floating point number",
12899            "type": "Number"
12900          },
12901          "example": ["\n <div class=\"norender\"><code>\n // Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n let rows = table.getRows();\n let minId = Infinity;\n let maxId = -Infinity;\n for (let r = 0; r < rows.length; r++) {\n   let id = rows[r].getNum('id');\n   minId = min(minId, id);\n   maxId = min(maxId, id);\n }\n print('minimum id = ' + minId + ', maximum id = ' + maxId);\n }\n </code></div>"],
12902          "alt": "no image displayed",
12903          "class": "p5.TableRow",
12904          "module": "IO",
12905          "submodule": "Table"
12906        }, {
12907          "file": "src/io/p5.TableRow.js",
12908          "line": 299,
12909          "description": "<p>Retrieves an String value from the TableRow&#39;s specified\ncolumn. The column may be specified by either its ID or\ntitle.</p>\n",
12910          "itemtype": "method",
12911          "name": "getString",
12912          "params": [{
12913            "name": "column",
12914            "description": "<p>columnName (string) or\n                                 ID (number)</p>\n",
12915            "type": "String|Integer"
12916          }],
12917          "return": {
12918            "description": "String",
12919            "type": "String"
12920          },
12921          "example": ["\n <div class=\"norender\"><code>\n // Given the CSV file \"mammals.csv\" in the project's \"assets\" folder:\n //\n // id,species,name\n // 0,Capra hircus,Goat\n // 1,Panthera pardus,Leopard\n // 2,Equus zebra,Zebra\n\n let table;\n\n function preload() {\n //my table is comma separated value \"csv\"\n //and has a header specifying the columns labels\n table = loadTable('assets/mammals.csv', 'csv', 'header');\n }\n\n function setup() {\n let rows = table.getRows();\n let longest = '';\n for (let r = 0; r < rows.length; r++) {\n   let species = rows[r].getString('species');\n   if (longest.length < species.length) {\n     longest = species;\n   }\n }\n\n print('longest: ' + longest);\n }\n </code></div>"],
12922          "alt": "no image displayed",
12923          "class": "p5.TableRow",
12924          "module": "IO",
12925          "submodule": "Table"
12926        }, {
12927          "file": "src/io/p5.XML.js",
12928          "line": 65,
12929          "description": "<p>Gets a copy of the element&#39;s parent. Returns the parent as another\n<a href=\"#/p5.XML\">p5.XML</a> object.</p>\n",
12930          "itemtype": "method",
12931          "name": "getParent",
12932          "return": {
12933            "description": "element parent",
12934            "type": "p5.XML"
12935          },
12936          "example": ["\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let children = xml.getChildren('animal');\n  let parent = children[1].getParent();\n  print(parent.getName());\n}\n\n// Sketch prints:\n// mammals\n</code></div>"],
12937          "class": "p5.XML",
12938          "module": "IO",
12939          "submodule": "XML"
12940        }, {
12941          "file": "src/io/p5.XML.js",
12942          "line": 103,
12943          "description": "<p>Gets the element&#39;s full name, which is returned as a String.</p>\n",
12944          "itemtype": "method",
12945          "name": "getName",
12946          "return": {
12947            "description": "the name of the node",
12948            "type": "String"
12949          },
12950          "example": ["&lt;animal\n <div class='norender'><code>\n // The following short XML file called \"mammals.xml\" is parsed\n // in the code below.\n //\n // <?xml version=\"1.0\"?>\n // &lt;mammals&gt;\n //   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n //   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n //   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n // &lt;/mammals&gt;\n\n let xml;\n\n function preload() {\n xml = loadXML('assets/mammals.xml');\n }\n\n function setup() {\n print(xml.getName());\n }\n\n // Sketch prints:\n // mammals\n </code></div>"],
12951          "class": "p5.XML",
12952          "module": "IO",
12953          "submodule": "XML"
12954        }, {
12955          "file": "src/io/p5.XML.js",
12956          "line": 138,
12957          "description": "<p>Sets the element&#39;s name, which is specified as a String.</p>\n",
12958          "itemtype": "method",
12959          "name": "setName",
12960          "params": [{
12961            "name": "the",
12962            "description": "<p>new name of the node</p>\n",
12963            "type": "String"
12964          }],
12965          "example": ["&lt;animal\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  print(xml.getName());\n  xml.setName('fish');\n  print(xml.getName());\n}\n\n// Sketch prints:\n// mammals\n// fish\n</code></div>"],
12966          "class": "p5.XML",
12967          "module": "IO",
12968          "submodule": "XML"
12969        }, {
12970          "file": "src/io/p5.XML.js",
12971          "line": 184,
12972          "description": "<p>Checks whether or not the element has any children, and returns the result\nas a boolean.</p>\n",
12973          "itemtype": "method",
12974          "name": "hasChildren",
12975          "return": {
12976            "description": "",
12977            "type": "Boolean"
12978          },
12979          "example": ["&lt;animal\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  print(xml.hasChildren());\n}\n\n// Sketch prints:\n// true\n</code></div>"],
12980          "class": "p5.XML",
12981          "module": "IO",
12982          "submodule": "XML"
12983        }, {
12984          "file": "src/io/p5.XML.js",
12985          "line": 220,
12986          "description": "<p>Get the names of all of the element&#39;s children, and returns the names as an\narray of Strings. This is the same as looping through and calling <a href=\"#/p5.XML/getName\">getName()</a>\non each child element individually.</p>\n",
12987          "itemtype": "method",
12988          "name": "listChildren",
12989          "return": {
12990            "description": "names of the children of the element",
12991            "type": "String[]"
12992          },
12993          "example": ["&lt;animal\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  print(xml.listChildren());\n}\n\n// Sketch prints:\n// [\"animal\", \"animal\", \"animal\"]\n</code></div>"],
12994          "class": "p5.XML",
12995          "module": "IO",
12996          "submodule": "XML"
12997        }, {
12998          "file": "src/io/p5.XML.js",
12999          "line": 261,
13000          "description": "<p>Returns all of the element&#39;s children as an array of <a href=\"#/p5.XML\">p5.XML</a> objects. When\nthe name parameter is specified, then it will return all children that match\nthat name.</p>\n",
13001          "itemtype": "method",
13002          "name": "getChildren",
13003          "params": [{
13004            "name": "name",
13005            "description": "<p>element name</p>\n",
13006            "type": "String",
13007            "optional": true
13008          }],
13009          "return": {
13010            "description": "children of the element",
13011            "type": "p5.XML[]"
13012          },
13013          "example": ["&lt;animal\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let animals = xml.getChildren('animal');\n\n  for (let i = 0; i < animals.length;
13013 i++) {\n    print(animals[i].getContent());\n  }\n}\n\n// Sketch prints:\n// \"Goat\"\n// \"Leopard\"\n// \"Zebra\"\n</code></div>"],
13014          "class": "p5.XML",
13015          "module": "IO",
13016          "submodule": "XML"
13017        }, {
13018          "file": "src/io/p5.XML.js",
13019          "line": 317,
13020          "description": "<p>Returns the first of the element&#39;s children that matches the name parameter\nor the child of the given index.It returns undefined if no matching\nchild is found.</p>\n",
13021          "itemtype": "method",
13022          "name": "getChild",
13023          "params": [{
13024            "name": "name",
13025            "description": "<p>element name or index</p>\n",
13026            "type": "String|Integer"
13027          }],
13028          "return": {
13029            "description": "",
13030            "type": "p5.XML"
13031          },
13032          "example": ["&lt;animal\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let firstChild = xml.getChild('animal');\n  print(firstChild.getContent());\n}\n\n// Sketch prints:\n// \"Goat\"\n</code></div>\n<div class='norender'><code>\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let secondChild = xml.getChild(1);\n  print(secondChild.getContent());\n}\n\n// Sketch prints:\n// \"Leopard\"\n</code></div>"],
13033          "class": "p5.XML",
13034          "module": "IO",
13035          "submodule": "XML"
13036        }, {
13037          "file": "src/io/p5.XML.js",
13038          "line": 378,
13039          "description": "<p>Appends a new child to the element. The child can be specified with\neither a String, which will be used as the new tag&#39;s name, or as a\nreference to an existing <a href=\"#/p5.XML\">p5.XML</a> object.\nA reference to the newly created child is returned as an <a href=\"#/p5.XML\">p5.XML</a> object.</p>\n",
13040          "itemtype": "method",
13041          "name": "addChild",
13042          "params": [{
13043            "name": "node",
13044            "description": "<p>a <a href=\"#/p5.XML\">p5.XML</a> Object which will be the child to be added</p>\n",
13045            "type": "p5.XML"
13046          }],
13047          "example": ["\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let child = new p5.XML();\n  child.setName('animal');\n  child.setAttribute('id', '3');\n  child.setAttribute('species', 'Ornithorhynchus anatinus');\n  child.setContent('Platypus');\n  xml.addChild(child);\n\n  let animals = xml.getChildren('animal');\n  print(animals[animals.length - 1].getContent());\n}\n\n// Sketch prints:\n// \"Goat\"\n// \"Leopard\"\n// \"Zebra\"\n</code></div>"],
13048          "class": "p5.XML",
13049          "module": "IO",
13050          "submodule": "XML"
13051        }, {
13052          "file": "src/io/p5.XML.js",
13053          "line": 430,
13054          "description": "<p>Removes the element specified by name or index.</p>\n",
13055          "itemtype": "method",
13056          "name": "removeChild",
13057          "params": [{
13058            "name": "name",
13059            "description": "<p>element name or index</p>\n",
13060            "type": "String|Integer"
13061          }],
13062          "example": ["\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  xml.removeChild('animal');\n  let children = xml.getChildren();\n  for (let i = 0; i < children.length;
13062 i++) {\n    print(children[i].getContent());\n  }\n}\n\n// Sketch prints:\n// \"Leopard\"\n// \"Zebra\"\n</code></div>\n<div class='norender'><code>\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  xml.removeChild(1);\n  let children = xml.getChildren();\n  for (let i = 0; i < children.length; i++) {\n    print(children[i].getContent());\n  }\n}\n\n// Sketch prints:\n// \"Goat\"\n// \"Zebra\"\n</code></div>"],
13063          "class": "p5.XML",
13064          "module": "IO",
13065          "submodule": "XML"
13066        }, {
13067          "file": "src/io/p5.XML.js",
13068          "line": 502,
13069          "description": "<p>Counts the specified element&#39;s number of attributes, returned as an Number.</p>\n",
13070          "itemtype": "method",
13071          "name": "getAttributeCount",
13072          "return": {
13073            "description": "",
13074            "type": "Integer"
13075          },
13076          "example": ["\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let firstChild = xml.getChild('animal');\n  print(firstChild.getAttributeCount());\n}\n\n// Sketch prints:\n// 2\n</code></div>"],
13077          "class": "p5.XML",
13078          "module": "IO",
13079          "submodule": "XML"
13080        }, {
13081          "file": "src/io/p5.XML.js",
13082          "line": 538,
13083          "description": "<p>Gets all of the specified element&#39;s attributes, and returns them as an\narray of Strings.</p>\n",
13084          "itemtype": "method",
13085          "name": "listAttributes",
13086          "return": {
13087            "description": "an array of strings containing the names of attributes",
13088            "type": "String[]"
13089          },
13090          "example": ["\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let firstChild = xml.getChild('animal');\n  print(firstChild.listAttributes());\n}\n\n// Sketch prints:\n// [\"id\", \"species\"]\n</code></div>"],
13091          "class": "p5.XML",
13092          "module": "IO",
13093          "submodule": "XML"
13094        }, {
13095          "file": "src/io/p5.XML.js",
13096          "line": 580,
13097          "description": "<p>Checks whether or not an element has the specified attribute.</p>\n",
13098          "itemtype": "method",
13099          "name": "hasAttribute",
13100          "params": [{
13101            "name": "the",
13102            "description": "<p>attribute to be checked</p>\n",
13103            "type": "String"
13104          }],
13105          "return": {
13106            "description": "true if attribute found else false",
13107            "type": "Boolean"
13108          },
13109          "example": ["\n <div class='norender'><code>\n // The following short XML file called \"mammals.xml\" is parsed\n // in the code below.\n //\n // <?xml version=\"1.0\"?>\n // &lt;mammals&gt;\n //   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n //   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n //   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n // &lt;/mammals&gt;\n\n let xml;\n\n function preload() {\n xml = loadXML('assets/mammals.xml');\n }\n\n function setup() {\n let firstChild = xml.getChild('animal');\n print(firstChild.hasAttribute('species'));\n print(firstChild.hasAttribute('color'));\n }\n\n // Sketch prints:\n // true\n // false\n </code></div>"],
13110          "class": "p5.XML",
13111          "module": "IO",
13112          "submodule": "XML"
13113        }, {
13114          "file": "src/io/p5.XML.js",
13115          "line": 624,
13116          "description": "<p>Returns an attribute value of the element as an Number. If the defaultValue\nparameter is specified and the attribute doesn&#39;t exist, then defaultValue\nis returned. If no defaultValue is specified and the attribute doesn&#39;t\nexist, the value 0 is returned.</p>\n",
13117          "itemtype": "method",
13118          "name": "getNum",
13119          "params": [{
13120            "name": "name",
13121            "description": "<p>the non-null full name of the attribute</p>\n",
13122            "type": "String"
13123          }, {
13124            "name": "defaultValue",
13125            "description": "<p>the default value of the attribute</p>\n",
13126            "type": "Number",
13127            "optional": true
13128          }],
13129          "return": {
13130            "description": "",
13131            "type": "Number"
13132          },
13133          "example": ["\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let firstChild = xml.getChild('animal');\n  print(firstChild.getNum('id'));\n}\n\n// Sketch prints:\n// 0\n</code></div>"],
13134          "class": "p5.XML",
13135          "module": "IO",
13136          "submodule": "XML"
13137        }, {
13138          "file": "src/io/p5.XML.js",
13139          "line": 670,
13140          "description": "<p>Returns an attribute value of the element as an String. If the defaultValue\nparameter is specified and the attribute doesn&#39;t exist, then defaultValue\nis returned. If no defaultValue is specified and the attribute doesn&#39;t\nexist, null is returned.</p>\n",
13141          "itemtype": "method",
13142          "name": "getString",
13143          "params": [{
13144            "name": "name",
13145            "description": "<p>the non-null full name of the attribute</p>\n",
13146            "type": "String"
13147          }, {
13148            "name": "defaultValue",
13149            "description": "<p>the default value of the attribute</p>\n",
13150            "type": "Number",
13151            "optional": true
13152          }],
13153          "return": {
13154            "description": "",
13155            "type": "String"
13156          },
13157          "example": ["\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let firstChild = xml.getChild('animal');
13157\n  print(firstChild.getString('species'));\n}\n\n// Sketch prints:\n// \"Capra hircus\"\n</code></div>"],
13158          "class": "p5.XML",
13159          "module": "IO",
13160          "submodule": "XML"
13161        }, {
13162          "file": "src/io/p5.XML.js",
13163          "line": 716,
13164          "description": "<p>Sets the content of an element&#39;s attribute. The first parameter specifies\nthe attribute name, while the second specifies the new content.</p>\n",
13165          "itemtype": "method",
13166          "name": "setAttribute",
13167          "params": [{
13168            "name": "name",
13169            "description": "<p>the full name of the attribute</p>\n",
13170            "type": "String"
13171          }, {
13172            "name": "value",
13173            "description": "<p>the value of the attribute</p>\n",
13174            "type": "Number|String|Boolean"
13175          }],
13176          "example": ["\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let firstChild = xml.getChild('animal');\n  print(firstChild.getString('species'));\n  firstChild.setAttribute('species', 'Jamides zebra');\n  print(firstChild.getString('species'));\n}\n\n// Sketch prints:\n// \"Capra hircus\"\n// \"Jamides zebra\"\n</code></div>"],
13177          "class": "p5.XML",
13178          "module": "IO",
13179          "submodule": "XML"
13180        }, {
13181          "file": "src/io/p5.XML.js",
13182          "line": 757,
13183          "description": "<p>Returns the content of an element. If there is no such content,\ndefaultValue is returned if specified, otherwise null is returned.</p>\n",
13184          "itemtype": "method",
13185          "name": "getContent",
13186          "params": [{
13187            "name": "defaultValue",
13188            "description": "<p>value returned if no content is found</p>\n",
13189            "type": "String",
13190            "optional": true
13191          }],
13192          "return": {
13193            "description": "",
13194            "type": "String"
13195          },
13196          "example": ["\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let firstChild = xml.getChild('animal');\n  print(firstChild.getContent());\n}\n\n// Sketch prints:\n// \"Goat\"\n</code></div>"],
13197          "class": "p5.XML",
13198          "module": "IO",
13199          "submodule": "XML"
13200        }, {
13201          "file": "src/io/p5.XML.js",
13202          "line": 798,
13203          "description": "<p>Sets the element&#39;s content.</p>\n",
13204          "itemtype": "method",
13205          "name": "setContent",
13206          "params": [{
13207            "name": "text",
13208            "description": "<p>the new content</p>\n",
13209            "type": "String"
13210          }],
13211          "example": ["\n<div class='norender'><code>\n// The following short XML file called \"mammals.xml\" is parsed\n// in the code below.\n//\n// <?xml version=\"1.0\"?>\n// &lt;mammals&gt;\n//   &lt;animal id=\"0\" species=\"Capra hircus\">Goat&lt;/animal&gt;\n//   &lt;animal id=\"1\" species=\"Panthera pardus\">Leopard&lt;/animal&gt;\n//   &lt;animal id=\"2\" species=\"Equus zebra\">Zebra&lt;/animal&gt;\n// &lt;/mammals&gt;\n\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  let firstChild = xml.getChild('animal');\n  print(firstChild.getContent());\n  firstChild.setContent('Mountain Goat');\n  print(firstChild.getContent());\n}\n\n// Sketch prints:\n// \"Goat\"\n// \"Mountain Goat\"\n</code></div>"],
13212          "class": "p5.XML",
13213          "module": "IO",
13214          "submodule": "XML"
13215        }, {
13216          "file": "src/io/p5.XML.js",
13217          "line": 839,
13218          "description": "<p>Serializes the element into a string. This function is useful for preparing\nthe content to be sent over a http request or saved to file.</p>\n",
13219          "itemtype": "method",
13220          "name": "serialize",
13221          "return": {
13222            "description": "Serialized string of the element",
13223            "type": "String"
13224          },
13225          "example": ["\n<div class='norender'><code>\nlet xml;\n\nfunction preload() {\n  xml = loadXML('assets/mammals.xml');\n}\n\nfunction setup() {\n  print(xml.serialize());\n}\n\n// Sketch prints:\n// <mammals>\n//   <animal id=\"0\" species=\"Capra hircus\">Goat</animal>\n//   <animal id=\"1\" species=\"Panthera pardus\">Leopard</animal>\n//   <animal id=\"2\" species=\"Equus zebra\">Zebra</animal>\n// </mammals>\n</code></div>"],
13226          "class": "p5.XML",
13227          "module": "IO",
13228          "submodule": "XML"
13229        }, {
13230          "file": "src/math/calculation.js",
13231          "line": 12,
13232          "description": "<p>Calculates the absolute value (magnitude) of a number. Maps to Math.abs().\nThe absolute value of a number is always positive.</p>\n",
13233          "itemtype": "method",
13234          "name": "abs",
13235          "params": [{
13236            "name": "n",
13237            "description": "<p>number to compute</p>\n",
13238            "type": "Number"
13239          }],
13240          "return": {
13241            "description": "absolute value of given number",
13242            "type": "Number"
13243          },
13244          "example": ["\n<div class = \"norender\"><code>\nfunction setup() {\n  let x = -3;\n  let y = abs(x);\n\n  print(x); // -3\n  print(y); // 3\n}\n</code></div>"],
13245          "alt": "no image displayed",
13246          "class": "p5",
13247          "module": "Math",
13248          "submodule": "Calculation"
13249        }, {
13250          "file": "src/math/calculation.js",
13251          "line": 36,
13252          "description": "<p>Calculates the closest int value that is greater than or equal to the\nvalue of the parameter. Maps to Math.ceil(). For example, ceil(9.03)\nreturns the value 10.</p>\n",
13253          "itemtype": "method",
13254          "name": "ceil",
13255          "params": [{
13256            "name": "n",
13257            "description": "<p>number to round up</p>\n",
13258            "type": "Number"
13259          }],
13260          "return": {
13261            "description": "rounded up number",
13262            "type": "Integer"
13263          },
13264          "example": ["\n<div><code>\nfunction draw() {\n  background(200);\n  // map, mouseX between 0 and 5.\n  let ax = map(mouseX, 0, 100, 0, 5);\n  let ay = 66;\n\n  //Get the ceiling of the mapped number.\n  let bx = ceil(map(mouseX, 0, 100, 0, 5));\n  let by = 33;\n\n  // Multiply the mapped numbers by 20 to more easily\n  // see the changes.\n  stroke(0);\n  fill(0);\n  line(0, ay, ax * 20, ay);\n  line(0, by, bx * 20, by);\n\n  // Reformat the float returned by map and draw it.\n  noStroke();\n  text(nfc(ax, 2), ax, ay - 5);\n  text(nfc(bx, 1), bx, by - 5);\n}\n</code></div>"],
13265          "alt": "2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals",
13266          "class": "p5",
13267          "module": "Math",
13268          "submodule": "Calculation"
13269        }, {
13270          "file": "src/math/calculation.js",
13271          "line": 76,
13272          "description": "<p>Constrains a value between a minimum and maximum value.</p>\n",
13273          "itemtype": "method",
13274          "name": "constrain",
13275          "params": [{
13276            "name": "n",
13277            "description": "<p>number to constrain</p>\n",
13278            "type": "Number"
13279          }, {
13280            "name": "low",
13281            "description": "<p>minimum limit</p>\n",
13282            "type": "Number"
13283          }, {
13284            "name": "high",
13285            "description": "<p>maximum limit</p>\n",
13286            "type": "Number"
13287          }],
13288          "return": {
13289            "description": "constrained number",
13290            "type": "Number"
13291          },
13292          "example": ["\n<div><code>\nfunction draw() {\n  background(200);\n\n  let leftWall = 25;\n  let rightWall = 75;\n\n  // xm is just the mouseX, while\n  // xc is the mouseX, but constrained\n  // between the leftWall and rightWall!\n  let xm = mouseX;\n  let xc = constrain(mouseX, leftWall, rightWall);\n\n  // Draw the walls.\n  stroke(150);\n  line(leftWall, 0, leftWall, height);\n  line(rightWall, 0, rightWall, height);\n\n  // Draw xm and xc as circles.\n  noStroke();\n  fill(150);\n  ellipse(xm, 33, 9, 9); // Not Constrained\n  fill(0);\n  ellipse(xc, 66, 9, 9); // Constrained\n}\n</code></div>"],
13293          "alt": "2 vertical lines. 2 ellipses move with mouse X 1 does not move passed lines",
13294          "class": "p5",
13295          "module": "Math",
13296          "submodule": "Calculation"
13297        }, {
13298          "file": "src/math/calculation.js",
13299          "line": 121,
13300          "description": "<p>Calculates the distance between two points.</p>\n",
13301          "itemtype": "method",
13302          "name": "dist",
13303          "return": {
13304            "description": "distance between the two points",
13305            "type": "Number"
13306          },
13307          "example": ["\n<div><code>\n// Move your mouse inside the canvas to see the\n// change in distance between two points!\nfunction draw() {\n  background(200);\n  fill(0);\n\n  let x1 = 10;\n  let y1 = 90;\n  let x2 = mouseX;\n  let y2 = mouseY;\n\n  line(x1, y1, x2, y2);\n  ellipse(x1, y1, 7, 7);\n  ellipse(x2, y2, 7, 7);\n\n  // d is the length of the line\n  // the distance from point 1 to point 2.\n  let d = int(dist(x1, y1, x2, y2));\n\n  // Let's write d along the line we are drawing!\n  push();\n  translate((x1 + x2) / 2, (y1 + y2) / 2);\n  rotate(atan2(y2 - y1, x2 - x1));
13307\n  text(nfc(d, 1), 0, -5);\n  pop();\n  // Fancy!\n}\n</code></div>"],
13308          "alt": "2 ellipses joined by line. 1 ellipse moves with mouse X&Y. Distance displayed.",
13309          "class": "p5",
13310          "module": "Math",
13311          "submodule": "Calculation",
13312          "overloads": [{
13313            "line": 121,
13314            "params": [{
13315              "name": "x1",
13316              "description": "<p>x-coordinate of the first point</p>\n",
13317              "type": "Number"
13318            }, {
13319              "name": "y1",
13320              "description": "<p>y-coordinate of the first point</p>\n",
13321              "type": "Number"
13322            }, {
13323              "name": "x2",
13324              "description": "<p>x-coordinate of the second point</p>\n",
13325              "type": "Number"
13326            }, {
13327              "name": "y2",
13328              "description": "<p>y-coordinate of the second point</p>\n",
13329              "type": "Number"
13330            }],
13331            "return": {
13332              "description": "distance between the two points",
13333              "type": "Number"
13334            }
13335          }, {
13336            "line": 165,
13337            "params": [{
13338              "name": "x1",
13339              "description": "",
13340              "type": "Number"
13341            }, {
13342              "name": "y1",
13343              "description": "",
13344              "type": "Number"
13345            }, {
13346              "name": "z1",
13347              "description": "<p>z-coordinate of the first point</p>\n",
13348              "type": "Number"
13349            }, {
13350              "name": "x2",
13351              "description": "",
13352              "type": "Number"
13353            }, {
13354              "name": "y2",
13355              "description": "",
13356              "type": "Number"
13357            }, {
13358              "name": "z2",
13359              "description": "<p>z-coordinate of the second point</p>\n",
13360              "type": "Number"
13361            }],
13362            "return": {
13363              "description": "distance between the two points",
13364              "type": "Number"
13365            }
13366          }]
13367        }, {
13368          "file": "src/math/calculation.js",
13369          "line": 190,
13370          "description": "<p>Returns Euler&#39;s number e (2.71828...) raised to the power of the n\nparameter. Maps to Math.exp().</p>\n",
13371          "itemtype": "method",
13372          "name": "exp",
13373          "params": [{
13374            "name": "n",
13375            "description": "<p>exponent to raise</p>\n",
13376            "type": "Number"
13377          }],
13378          "return": {
13379            "description": "e^n",
13380            "type": "Number"
13381          },
13382          "example": ["\n<div><code>\nfunction draw() {\n  background(200);\n\n  // Compute the exp() function with a value between 0 and 2\n  let xValue = map(mouseX, 0, width, 0, 2);\n  let yValue = exp(xValue);\n\n  let y = map(yValue, 0, 8, height, 0);\n\n  let legend = 'exp (' + nfc(xValue, 3) + ')\\n= ' + nf(yValue, 1, 4);\n  stroke(150);\n  line(mouseX, y, mouseX, height);\n  fill(0);\n  text(legend, 5, 15);\n  noStroke();\n  ellipse(mouseX, y, 7, 7);\n\n  // Draw the exp(x) curve,\n  // over the domain of x from 0 to 2\n  noFill();\n  stroke(0);\n  beginShape();\n  for (let x = 0; x < width; x++) {\n    xValue = map(x, 0, width, 0, 2);\n    yValue = exp(xValue);\n    y = map(yValue, 0, 8, height, 0);\n    vertex(x, y);\n  }\n\n  endShape();\n  line(0, 0, 0, height);\n  line(0, height - 1, width, height - 1);\n}\n</code></div>"],
13383          "alt": "ellipse moves along a curve with mouse x. e^n displayed.",
13384          "class": "p5",
13385          "module": "Math",
13386          "submodule": "Calculation"
13387        }, {
13388          "file": "src/math/calculation.js",
13389          "line": 240,
13390          "description": "<p>Calculates the closest int value that is less than or equal to the\nvalue of the parameter. Maps to Math.floor().</p>\n",
13391          "itemtype": "method",
13392          "name": "floor",
13393          "params": [{
13394            "name": "n",
13395            "description": "<p>number to round down</p>\n",
13396            "type": "Number"
13397          }],
13398          "return": {
13399            "description": "rounded down number",
13400            "type": "Integer"
13401          },
13402          "example": ["\n<div><code>\nfunction draw() {\n  background(200);\n  //map, mouseX between 0 and 5.\n  let ax = map(mouseX, 0, 100, 0, 5);\n  let ay = 66;\n\n  //Get the floor of the mapped number.\n  let bx = floor(map(mouseX, 0, 100, 0, 5));\n  let by = 33;\n\n  // Multiply the mapped numbers by 20 to more easily\n  // see the changes.\n  stroke(0);\n  fill(0);\n  line(0, ay, ax * 20, ay);\n  line(0, by, bx * 20, by);\n\n  // Reformat the float returned by map and draw it.\n  noStroke();\n  text(nfc(ax, 2), ax, ay - 5);\n  text(nfc(bx, 1), bx, by - 5);\n}\n</code></div>"],
13403          "alt": "2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals",
13404          "class": "p5",
13405          "module": "Math",
13406          "submodule": "Calculation"
13407        }, {
13408          "file": "src/math/calculation.js",
13409          "line": 279,
13410          "description": "<p>Calculates a number between two numbers at a specific increment. The amt\nparameter is the amount to interpolate between the two values where 0.0\nequal to the first point, 0.1 is very near the first point, 0.5 is\nhalf-way in between, and 1.0 is equal to the second point. If the\nvalue of amt is more than 1.0 or less than 0.0, the number will be\ncalculated accordingly in the ratio of the two given numbers. The lerp\nfunction is convenient for creating motion along a straight\npath and for drawing dotted lines.</p>\n",
13411          "itemtype": "method",
13412          "name": "lerp",
13413          "params": [{
13414            "name": "start",
13415            "description": "<p>first value</p>\n",
13416            "type": "Number"
13417          }, {
13418            "name": "stop",
13419            "description": "<p>second value</p>\n",
13420            "type": "Number"
13421          }, {
13422            "name": "amt",
13423            "description": "<p>number</p>\n",
13424            "type": "Number"
13425          }],
13426          "return": {
13427            "description": "lerped value",
13428            "type": "Number"
13429          },
13430          "example": ["\n<div><code>\nfunction setup() {\n  background(200);\n  let a = 20;\n  let b = 80;\n  let c = lerp(a, b, 0.2);\n  let d = lerp(a, b, 0.5);\n  let e = lerp(a, b, 0.8);\n\n  let y = 50;\n\n  strokeWeight(5);\n  stroke(0); // Draw the original points in black\n  point(a, y);\n  point(b, y);\n\n  stroke(100); // Draw the lerp points in gray\n  point(c, y);\n  point(d, y);\n  point(e, y);\n}\n</code></div>"],
13431          "alt": "5 points horizontally staggered mid-canvas. mid 3 are grey, outer black",
13432          "class": "p5",
13433          "module": "Math",
13434          "submodule": "Calculation"
13435        }, {
13436          "file": "src/math/calculation.js",
13437          "line": 327,
13438          "description": "<p>Calculates the natural logarithm (the base-e logarithm) of a number. This\nfunction expects the n parameter to be a value greater than 0.0. Maps to\nMath.log().</p>\n",
13439          "itemtype": "method",
13440          "name": "log",
13441          "params": [{
13442            "name": "n",
13443            "description": "<p>number greater than 0</p>\n",
13444            "type": "Number"
13445          }],
13446          "return": {
13447            "description": "natural logarithm of n",
13448            "type": "Number"
13449          },
13450          "example": ["\n<div><code>\nfunction draw() {\n  background(200);\n  let maxX = 2.8;\n  let maxY = 1.5;\n\n  // Compute the natural log of a value between 0 and maxX\n  let xValue = map(mouseX, 0, width, 0, maxX);\n  let yValue, y;\n  if (xValue > 0) {\n   // Cannot take the log of a negative number.\n    yValue = log(xValue);\n    y = map(yValue, -maxY, maxY, height, 0);\n\n    // Display the calculation occurring.\n    let legend = 'log(' + nf(xValue, 1, 2) + ')\\n= ' + nf(yValue, 1, 3);\n    stroke(150);\n    line(mouseX, y, mouseX, height);\n    fill(0);\n    text(legend, 5, 15);\n    noStroke();\n    ellipse(mouseX, y, 7, 7);\n  }\n\n  // Draw the log(x) curve,\n  // over the domain of x from 0 to maxX\n  noFill();\n  stroke(0);\n  beginShape();\n  for (let x = 0; x < width; x++) {\n    xValue = map(x, 0, width, 0, maxX);\n    yValue = log(xValue);\n    y = map(yValue, -maxY, maxY, height, 0);\n    vertex(x, y);\n  }\n  endShape();\n  line(0, 0, 0, height);\n  line(0, height / 2, width, height / 2);\n}\n</code></div>"],
13451          "alt": "ellipse moves along a curve with mouse x. natural logarithm of n displayed.",
13452          "class": "p5",
13453          "module": "Math",
13454          "submodule": "Calculation"
13455        }, {
13456          "file": "src/math/calculation.js",
13457          "line": 383,
13458          "description": "<p>Calculates the magnitude (or length) of a vector. A vector is a direction\nin space commonly used in computer graphics and linear algebra. Because it\nhas no &quot;start&quot; position, the magnitude of a vector can be thought of as\nthe distance from the coordinate 0,0 to its x,y value. Therefore, <a href=\"#/p5/mag\">mag()</a> is\na shortcut for writing dist(0, 0, x, y).</p>\n",
13459          "itemtype": "method",
13460          "name": "mag",
13461          "params": [{
13462            "name": "a",
13463            "description": "<p>first value</p>\n",
13464            "type": "Number"
13465          }, {
13466            "name": "b",
13467            "description": "<p>second value</p>\n",
13468            "type": "Number"
13469          }],
13470          "return": {
13471            "description": "magnitude of vector from (0,0) to (a,b)",
13472            "type": "Number"
13473          },
13474          "example": ["\n<div><code>\nfunction setup() {\n  let x1 = 20;\n  let x2 = 80;\n  let y1 = 30;\n  let y2 = 70;\n\n  line(0, 0, x1, y1);\n  print(mag(x1, y1)); // Prints \"36.05551275463989\"\n  line(0, 0, x2, y1);\n  print(mag(x2, y1)); // Prints \"85.44003745317531\"\n  line(0, 0, x1, y2);\n  print(mag(x1, y2)); // Prints \"72.80109889280519\"\n  line(0, 0, x2, y2);\n  print(mag(x2, y2)); // Prints \"106.3014581273465\"\n}\n</code></div>"],
13475          "alt": "4 lines of different length radiate from top left of canvas.",
13476          "class": "p5",
13477          "module": "Math",
13478          "submodule": "Calculation"
13479        }, {
13480          "file": "src/math/calculation.js",
13481          "line": 422,
13482          "description": "<p>Re-maps a number from one range to another.\n<br><br>\nIn the first example above, the number 25 is converted from a value in the\nrange of 0 to 100 into a value that ranges from the left edge of the\nwindow (0) to the right edge (width).</p>\n",
13483          "itemtype": "method",
13484          "name": "map",
13485          "params": [{
13486            "name": "value",
13487            "description": "<p>the incoming value to be converted</p>\n",
13488            "type": "Number"
13489          }, {
13490            "name": "start1",
13491            "description": "<p>lower bound of the value&#39;s current range</p>\n",
13492            "type": "Number"
13493          }, {
13494            "name": "stop1",
13495            "description": "<p>upper bound of the value&#39;s current range</p>\n",
13496            "type": "Number"
13497          }, {
13498            "name": "start2",
13499            "description": "<p>lower bound of the value&#39;s target range</p>\n",
13500            "type": "Number"
13501          }, {
13502            "name": "stop2",
13503            "description": "<p>upper bound of the value&#39;s target range</p>\n",
13504            "type": "Number"
13505          }, {
13506            "name": "withinBounds",
13507            "description": "<p>constrain the value to the newly mapped range</p>\n",
13508            "type": "Boolean",
13509            "optional": true
13510          }],
13511          "return": {
13512            "description": "remapped number",
13513            "type": "Number"
13514          },
13515          "example": ["\n  <div><code>\nlet value = 25;\nlet m = map(value, 0, 100, 0, width);\nellipse(m, 50, 10, 10);\n</code></div>\n\n  <div><code>\nfunction setup() {\n  noStroke();\n}\n\nfunction draw() {\n  background(204);\n  let x1 = map(mouseX, 0, width, 25, 75);\n  ellipse(x1, 25, 25, 25);\n  //This ellipse is constrained to the 0-100 range\n  //after setting withinBounds to true\n  let x2 = map(mouseX, 0, width, 0, 100, true);\n  ellipse(x2, 75, 25, 25);\n}\n</code></div>"],
13516          "alt": "10 by 10 white ellipse with in mid left canvas\n2 25 by 25 white ellipses move with mouse x. Bottom has more range from X",
13517          "class": "p5",
13518          "module": "Math",
13519          "submodule": "Calculation"
13520        }, {
13521          "file": "src/math/calculation.js",
13522          "line": 478,
13523          "description": "<p>Determines the largest value in a sequence of numbers, and then returns\nthat value. <a href=\"#/p5/max\">max()</a> accepts any number of Number parameters, or an Array\nof any length.</p>\n",
13524          "itemtype": "method",
13525          "name": "max",
13526          "return": {
13527            "description": "maximum Number",
13528            "type": "Number"
13529          },
13530          "example": ["\n<div><code>\nfunction setup() {\n  // Change the elements in the array and run the sketch\n  // to show how max() works!\n  let numArray = [2, 1, 5, 4, 8, 9];\n  fill(0);\n  noStroke();\n  text('Array Elements', 0, 10);\n  // Draw all numbers in the array\n  let spacing = 15;\n  let elemsY = 25;\n  for (let i = 0; i < numArray.length;
13530 i++) {\n    text(numArray[i], i * spacing, elemsY);\n  }\n  let maxX = 33;\n  let maxY = 80;\n  // Draw the Maximum value in the array.\n  textSize(32);\n  text(max(numArray), maxX, maxY);\n}\n</code></div>"],
13531          "alt": "Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 9",
13532          "class": "p5",
13533          "module": "Math",
13534          "submodule": "Calculation",
13535          "overloads": [{
13536            "line": 478,
13537            "params": [{
13538              "name": "n0",
13539              "description": "<p>Number to compare</p>\n",
13540              "type": "Number"
13541            }, {
13542              "name": "n1",
13543              "description": "<p>Number to compare</p>\n",
13544              "type": "Number"
13545            }],
13546            "return": {
13547              "description": "maximum Number",
13548              "type": "Number"
13549            }
13550          }, {
13551            "line": 514,
13552            "params": [{
13553              "name": "nums",
13554              "description": "<p>Numbers to compare</p>\n",
13555              "type": "Number[]"
13556            }],
13557            "return": {
13558              "description": "",
13559              "type": "Number"
13560            }
13561          }]
13562        }, {
13563          "file": "src/math/calculation.js",
13564          "line": 528,
13565          "description": "<p>Determines the smallest value in a sequence of numbers, and then returns\nthat value. <a href=\"#/p5/min\">min()</a> accepts any number of Number parameters, or an Array\nof any length.</p>\n",
13566          "itemtype": "method",
13567          "name": "min",
13568          "return": {
13569            "description": "minimum Number",
13570            "type": "Number"
13571          },
13572          "example": ["\n<div><code>\nfunction setup() {\n  // Change the elements in the array and run the sketch\n  // to show how min() works!\n  let numArray = [2, 1, 5, 4, 8, 9];\n  fill(0);\n  noStroke();\n  text('Array Elements', 0, 10);\n  // Draw all numbers in the array\n  let spacing = 15;\n  let elemsY = 25;\n  for (let i = 0; i < numArray.length; i++) {\n    text(numArray[i], i * spacing, elemsY);\n  }\n  let maxX = 33;\n  let maxY = 80;\n  // Draw the Minimum value in the array.\n  textSize(32);\n  text(min(numArray), maxX, maxY);\n}\n</code></div>"],
13573          "alt": "Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 1",
13574          "class": "p5",
13575          "module": "Math",
13576          "submodule": "Calculation",
13577          "overloads": [{
13578            "line": 528,
13579            "params": [{
13580              "name": "n0",
13581              "description": "<p>Number to compare</p>\n",
13582              "type": "Number"
13583            }, {
13584              "name": "n1",
13585              "description": "<p>Number to compare</p>\n",
13586              "type": "Number"
13587            }],
13588            "return": {
13589              "description": "minimum Number",
13590              "type": "Number"
13591            }
13592          }, {
13593            "line": 564,
13594            "params": [{
13595              "name": "nums",
13596              "description": "<p>Numbers to compare</p>\n",
13597              "type": "Number[]"
13598            }],
13599            "return": {
13600              "description": "",
13601              "type": "Number"
13602            }
13603          }]
13604        }, {
13605          "file": "src/math/calculation.js",
13606          "line": 578,
13607          "description": "<p>Normalizes a number from another range into a value between 0 and 1.\nIdentical to map(value, low, high, 0, 1).\nNumbers outside of the range are not clamped to 0 and 1, because\nout-of-range values are often intentional and useful. (See the second\nexample above.)</p>\n",
13608          "itemtype": "method",
13609          "name": "norm",
13610          "params": [{
13611            "name": "value",
13612            "description": "<p>incoming value to be normalized</p>\n",
13613            "type": "Number"
13614          }, {
13615            "name": "start",
13616            "description": "<p>lower bound of the value&#39;s current range</p>\n",
13617            "type": "Number"
13618          }, {
13619            "name": "stop",
13620            "description": "<p>upper bound of the value&#39;s current range</p>\n",
13621            "type": "Number"
13622          }],
13623          "return": {
13624            "description": "normalized number",
13625            "type": "Number"
13626          },
13627          "example": ["\n<div><code>\nfunction draw() {\n  background(200);\n  let currentNum = mouseX;\n  let lowerBound = 0;\n  let upperBound = width; //100;\n  let normalized = norm(currentNum, lowerBound, upperBound);\n  let lineY = 70;\n  line(0, lineY, width, lineY);\n  //Draw an ellipse mapped to the non-normalized value.\n  noStroke();\n  fill(50);\n  let s = 7; // ellipse size\n  ellipse(currentNum, lineY, s, s);\n\n  // Draw the guide\n  let guideY = lineY + 15;\n  text('0', 0, guideY);\n  textAlign(RIGHT);\n  text('100', width, guideY);
13627\n\n  // Draw the normalized value\n  textAlign(LEFT);\n  fill(0);\n  textSize(32);\n  let normalY = 40;\n  let normalX = 20;\n  text(normalized, normalX, normalY);\n}\n</code></div>"],
13628          "alt": "ellipse moves with mouse. 0 shown left & 100 right and updating values center",
13629          "class": "p5",
13630          "module": "Math",
13631          "submodule": "Calculation"
13632        }, {
13633          "file": "src/math/calculation.js",
13634          "line": 631,
13635          "description": "<p>Facilitates exponential expressions. The <a href=\"#/p5/pow\">pow()</a> function is an efficient\nway of multiplying numbers by themselves (or their reciprocals) in large\nquantities. For example, pow(3, 5) is equivalent to the expression\n3<em>3</em>3<em>3</em>3 and pow(3, -5) is equivalent to 1 / 3<em>3</em>3<em>3</em>3. Maps to\nMath.pow().</p>\n",
13636          "itemtype": "method",
13637          "name": "pow",
13638          "params": [{
13639            "name": "n",
13640            "description": "<p>base of the exponential expression</p>\n",
13641            "type": "Number"
13642          }, {
13643            "name": "e",
13644            "description": "<p>power by which to raise the base</p>\n",
13645            "type": "Number"
13646          }],
13647          "return": {
13648            "description": "n^e",
13649            "type": "Number"
13650          },
13651          "example": ["\n<div><code>\nfunction setup() {\n  //Exponentially increase the size of an ellipse.\n  let eSize = 3; // Original Size\n  let eLoc = 10; // Original Location\n\n  ellipse(eLoc, eLoc, eSize, eSize);\n\n  ellipse(eLoc * 2, eLoc * 2, pow(eSize, 2), pow(eSize, 2));\n\n  ellipse(eLoc * 4, eLoc * 4, pow(eSize, 3), pow(eSize, 3));\n\n  ellipse(eLoc * 8, eLoc * 8, pow(eSize, 4), pow(eSize, 4));\n}\n</code></div>"],
13652          "alt": "small to large ellipses radiating from top left of canvas",
13653          "class": "p5",
13654          "module": "Math",
13655          "submodule": "Calculation"
13656        }, {
13657          "file": "src/math/calculation.js",
13658          "line": 665,
13659          "description": "<p>Calculates the integer closest to the n parameter. For example,\nround(133.8) returns the value 134. Maps to Math.round().</p>\n",
13660          "itemtype": "method",
13661          "name": "round",
13662          "params": [{
13663            "name": "n",
13664            "description": "<p>number to round</p>\n",
13665            "type": "Number"
13666          }],
13667          "return": {
13668            "description": "rounded number",
13669            "type": "Integer"
13670          },
13671          "example": ["\n<div><code>\nfunction draw() {\n  background(200);\n  //map, mouseX between 0 and 5.\n  let ax = map(mouseX, 0, 100, 0, 5);\n  let ay = 66;\n\n  // Round the mapped number.\n  let bx = round(map(mouseX, 0, 100, 0, 5));\n  let by = 33;\n\n  // Multiply the mapped numbers by 20 to more easily\n  // see the changes.\n  stroke(0);\n  fill(0);\n  line(0, ay, ax * 20, ay);\n  line(0, by, bx * 20, by);\n\n  // Reformat the float returned by map and draw it.\n  noStroke();\n  text(nfc(ax, 2), ax, ay - 5);\n  text(nfc(bx, 1), bx, by - 5);\n}\n</code></div>"],
13672          "alt": "horizontal center line squared values displayed on top and regular on bottom.",
13673          "class": "p5",
13674          "module": "Math",
13675          "submodule": "Calculation"
13676        }, {
13677          "file": "src/math/calculation.js",
13678          "line": 704,
13679          "description": "<p>Squares a number (multiplies a number by itself). The result is always a\npositive number, as multiplying two negative numbers always yields a\npositive result. For example, -1 * -1 = 1.</p>\n",
13680          "itemtype": "method",
13681          "name": "sq",
13682          "params": [{
13683            "name": "n",
13684            "description": "<p>number to square</p>\n",
13685            "type": "Number"
13686          }],
13687          "return": {
13688            "description": "squared number",
13689            "type": "Number"
13690          },
13691          "example": ["\n<div><code>\nfunction draw() {\n  background(200);\n  let eSize = 7;\n  let x1 = map(mouseX, 0, width, 0, 10);\n  let y1 = 80;\n  let x2 = sq(x1);\n  let y2 = 20;\n\n  // Draw the non-squared.\n  line(0, y1, width, y1);\n  ellipse(x1, y1, eSize, eSize);\n\n  // Draw the squared.\n  line(0, y2, width, y2);\n  ellipse(x2, y2, eSize, eSize);\n\n  // Draw dividing line.\n  stroke(100);\n  line(0, height / 2, width, height / 2);\n\n  // Draw text.\n  let spacing = 15;\n  noStroke();\n  fill(0);\n  text('x = ' + x1, 0, y1 + spacing);\n  text('sq(x) = ' + x2, 0, y2 + spacing);\n}\n</code></div>"],
13692          "alt": "horizontal center line squared values displayed on top and regular on bottom.",
13693          "class": "p5",
13694          "module": "Math",
13695          "submodule": "Calculation"
13696        }, {
13697          "file": "src/math/calculation.js",
13698          "line": 751,
13699          "description": "<p>Calculates the square root of a number. The square root of a number is\nalways positive, even though there may be a valid negative root. The\nsquare root s of number a is such that s*s = a. It is the opposite of\nsquaring. Maps to Math.sqrt().</p>\n",
13700          "itemtype": "method",
13701          "name": "sqrt",
13702          "params": [{
13703            "name": "n",
13704            "description": "<p>non-negative number to square root</p>\n",
13705            "type": "Number"
13706          }],
13707          "return": {
13708            "description": "square root of number",
13709            "type": "Number"
13710          },
13711          "example": ["\n<div><code>\nfunction draw() {\n  background(200);\n  let eSize = 7;\n  let x1 = mouseX;\n  let y1 = 80;\n  let x2 = sqrt(x1);\n  let y2 = 20;\n\n  // Draw the non-squared.\n  line(0, y1, width, y1);\n  ellipse(x1, y1, eSize, eSize);\n\n  // Draw the squared.\n  line(0, y2, width, y2);\n  ellipse(x2, y2, eSize, eSize);\n\n  // Draw dividing line.\n  stroke(100);\n  line(0, height / 2, width, height / 2);\n\n  // Draw text.\n  noStroke();\n  fill(0);\n  let spacing = 15;\n  text('x = ' + x1, 0, y1 + spacing);\n  text('sqrt(x) = ' + x2, 0, y2 + spacing);\n}\n</code></div>"],
13712          "alt": "horizontal center line squareroot values displayed on top and regular on bottom.",
13713          "class": "p5",
13714          "module": "Math",
13715          "submodule": "Calculation"
13716        }, {
13717          "file": "src/math/math.js",
13718          "line": 12,
13719          "description": "<p>Creates a new <a href=\"#/p5.Vector\">p5.Vector</a> (the datatype for storing vectors). This provides a\ntwo or three dimensional vector, specifically a Euclidean (also known as\ngeometric) vector. A vector is an entity that has both magnitude and\ndirection.</p>\n",
13720          "itemtype": "method",
13721          "name": "createVector",
13722          "params": [{
13723            "name": "x",
13724            "description": "<p>x component of the vector</p>\n",
13725            "type": "Number",
13726            "optional": true
13727          }, {
13728            "name": "y",
13729            "description": "<p>y component of the vector</p>\n",
13730            "type": "Number",
13731            "optional": true
13732          }, {
13733            "name": "z",
13734            "description": "<p>z component of the vector</p>\n",
13735            "type": "Number",
13736            "optional": true
13737          }],
13738          "return": {
13739            "description": "",
13740            "type": "p5.Vector"
13741          },
13742          "example": ["\n<div modernizr='webgl'><code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  noStroke();\n  fill(255, 102, 204);\n}\n\nfunction draw() {\n  background(255);\n  pointLight(color(255), createVector(sin(millis() / 1000) * 20, -40, -10));\n  scale(0.75);\n  sphere();\n}\n</code></div>"],
13743          "alt": "a purple sphere lit by a point light oscillating horizontally",
13744          "class": "p5",
13745          "module": "Math",
13746          "submodule": "Math"
13747        }, {
13748          "file": "src/math/noise.js",
13749          "line": 40,
13750          "description": "<p>Returns the Perlin noise value at specified coordinates. Perlin noise is\na random sequence generator producing a more natural ordered, harmonic\nsuccession of numbers compared to the standard <b>random()</b>
13750 function.\nIt was invented by Ken Perlin in the 1980s and been used since in\ngraphical applications to produce procedural textures, natural motion,\nshapes, terrains etc.<br /><br /> The main difference to the\n<b>random()</b> function is that Perlin noise is defined in an infinite\nn-dimensional space where each pair of coordinates corresponds to a\nfixed semi-random value (fixed only for the lifespan of the program; see\nthe <a href=\"#/p5/noiseSeed\">noiseSeed()</a> function). p5.js can compute 1D, 2D and 3D noise,\ndepending on the number of coordinates given. The resulting value will\nalways be between 0.0 and 1.0. The noise value can be animated by moving\nthrough the noise space as demonstrated in the example above. The 2nd\nand 3rd dimension can also be interpreted as time.<br /><br />The actual\nnoise is structured similar to an audio signal, in respect to the\nfunction&#39;s use of frequencies. Similar to the concept of harmonics in\nphysics, perlin noise is computed over several octaves which are added\ntogether for the final result. <br /><br />Another way to adjust the\ncharacter of the resulting sequence is the scale of the input\ncoordinates. As the function works within an infinite space the value of\nthe coordinates doesn&#39;t matter as such, only the distance between\nsuccessive coordinates does (eg. when using <b>noise()</b> within a\nloop). As a general rule the smaller the difference between coordinates,\nthe smoother the resulting noise sequence will be. Steps of 0.005-0.03\nwork best for most applications, but this will differ depending on use.</p>\n",
13751          "itemtype": "method",
13752          "name": "noise",
13753          "params": [{
13754            "name": "x",
13755            "description": "<p>x-coordinate in noise space</p>\n",
13756            "type": "Number"
13757          }, {
13758            "name": "y",
13759            "description": "<p>y-coordinate in noise space</p>\n",
13760            "type": "Number",
13761            "optional": true
13762          }, {
13763            "name": "z",
13764            "description": "<p>z-coordinate in noise space</p>\n",
13765            "type": "Number",
13766            "optional": true
13767          }],
13768          "return": {
13769            "description": "Perlin noise value (between 0 and 1) at specified\n                     coordinates",
13770            "type": "Number"
13771          },
13772          "example": ["\n<div>\n<code>\nlet xoff = 0.0;\n\nfunction draw() {\n  background(204);\n  xoff = xoff + 0.01;\n  let n = noise(xoff) * width;\n  line(n, 0, n, height);\n}\n</code>\n</div>\n<div>\n<code>let noiseScale=0.02;\n\nfunction draw() {\n  background(0);\n  for (let x=0; x < width; x++) {\n    let noiseVal = noise((mouseX+x)*noiseScale, mouseY*noiseScale);\n    stroke(noiseVal*255);\n    line(x, mouseY+noiseVal*80, x, height);\n  }\n}\n</code>\n</div>"],
13773          "alt": "vertical line moves left to right with updating noise values.\nhorizontal wave pattern effected by mouse x-position & updating noise values.",
13774          "class": "p5",
13775          "module": "Math",
13776          "submodule": "Noise"
13777        }, {
13778          "file": "src/math/noise.js",
13779          "line": 187,
13780          "description": "<p>Adjusts the character and level of detail produced by the Perlin noise\n function. Similar to harmonics in physics, noise is computed over\n several octaves. Lower octaves contribute more to the output signal and\n as such define the overall intensity of the noise, whereas higher octaves\n create finer grained details in the noise sequence.\n <br><br>\n By default, noise is computed over 4 octaves with each octave contributing\n exactly half than its predecessor, starting at 50% strength for the 1st\n octave. This falloff amount can be changed by adding an additional function\n parameter. Eg. a falloff factor of 0.75 means each octave will now have\n 75% impact (25% less) of the previous lower octave. Any value between\n 0.0 and 1.0 is valid, however note that values greater than 0.5 might\n result in greater than 1.0 values returned by <b>noise()</b>.\n <br><br>\n By changing these parameters, the signal created by the <b>noise()</b>\n function can be adapted to fit very specific needs and characteristics.</p>\n",
13781          "itemtype": "method",
13782          "name": "noiseDetail",
13783          "params": [{
13784            "name": "lod",
13785            "description": "<p>number of octaves to be used by the noise</p>\n",
13786            "type": "Number"
13787          }, {
13788            "name": "falloff",
13789            "description": "<p>falloff factor for each octave</p>\n",
13790            "type": "Number"
13791          }],
13792          "example": ["\n <div>\n <code>\n let noiseVal;\n let noiseScale = 0.02;\nfunction setup() {\n   createCanvas(100, 100);\n }\nfunction draw() {\n   background(0);\n   for (let y = 0; y < height;
13792 y++) {\n     for (let x = 0; x < width / 2; x++) {\n       noiseDetail(2, 0.2);\n       noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);\n       stroke(noiseVal * 255);\n       point(x, y);\n       noiseDetail(8, 0.65);\n       noiseVal = noise(\n         (mouseX + x + width / 2) * noiseScale,\n         (mouseY + y) * noiseScale\n       );\n       stroke(noiseVal * 255);\n       point(x + width / 2, y);\n     }\n   }\n }\n </code>\n </div>"],
13793          "alt": "2 vertical grey smokey patterns affected my mouse x-position and noise.",
13794          "class": "p5",
13795          "module": "Math",
13796          "submodule": "Noise"
13797        }, {
13798          "file": "src/math/noise.js",
13799          "line": 253,
13800          "description": "<p>Sets the seed value for <b>noise()</b>. By default, <b>noise()</b>\nproduces different results each time the program is run. Set the\n<b>value</b> parameter to a constant to return the same pseudo-random\nnumbers each time the software is run.</p>\n",
13801          "itemtype": "method",
13802          "name": "noiseSeed",
13803          "params": [{
13804            "name": "seed",
13805            "description": "<p>the seed value</p>\n",
13806            "type": "Number"
13807          }],
13808          "example": ["\n<div>\n<code>let xoff = 0.0;\n\nfunction setup() {\n  noiseSeed(99);\n  stroke(0, 10);\n}\n\nfunction draw() {\n  xoff = xoff + .01;\n  let n = noise(xoff) * width;\n  line(n, 0, n, height);\n}\n</code>\n</div>"],
13809          "alt": "vertical grey lines drawing in pattern affected by noise.",
13810          "class": "p5",
13811          "module": "Math",
13812          "submodule": "Noise"
13813        }, {
13814          "file": "src/math/p5.Vector.js",
13815          "line": 67,
13816          "description": "<p>The x component of the vector</p>\n",
13817          "itemtype": "property",
13818          "name": "x",
13819          "type": "Number",
13820          "class": "p5.Vector",
13821          "module": "Math",
13822          "submodule": "Math"
13823        }, {
13824          "file": "src/math/p5.Vector.js",
13825          "line": 72,
13826          "description": "<p>The y component of the vector</p>\n",
13827          "itemtype": "property",
13828          "name": "y",
13829          "type": "Number",
13830          "class": "p5.Vector",
13831          "module": "Math",
13832          "submodule": "Math"
13833        }, {
13834          "file": "src/math/p5.Vector.js",
13835          "line": 77,
13836          "description": "<p>The z component of the vector</p>\n",
13837          "itemtype": "property",
13838          "name": "z",
13839          "type": "Number",
13840          "class": "p5.Vector",
13841          "module": "Math",
13842          "submodule": "Math"
13843        }, {
13844          "file": "src/math/p5.Vector.js",
13845          "line": 84,
13846          "description": "<p>Returns a string representation of a vector v by calling String(v)\nor v.toString(). This method is useful for logging vectors in the\nconsole.</p>\n",
13847          "itemtype": "method",
13848          "name": "toString",
13849          "return": {
13850            "description": "",
13851            "type": "String"
13852          },
13853          "example": ["\n<div class = \"norender\">\n<code>\nfunction setup() {\n  let v = createVector(20, 30);\n  print(String(v)); // prints \"p5.Vector Object : [20, 30, 0]\"\n}\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(0, 0);\n  let v1 = createVector(mouseX, mouseY);\n  drawArrow(v0, v1, 'black');\n\n  noStroke();\n  text(v1.toString(), 10, 25, 90, 75);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
13854          "class": "p5.Vector",
13855          "module": "Math",
13856          "submodule": "Math"
13857        }, {
13858          "file": "src/math/p5.Vector.js",
13859          "line": 134,
13860          "description": "<p>Sets the x, y, and z component of the vector using two or three separate\nvariables, the data from a <a href=\"#/p5.Vector\">p5.Vector</a>, or the values from a float array.</p>\n",
13861          "itemtype": "method",
13862          "name": "set",
13863          "chainable": 1,
13864          "example": ["\n<div class=\"norender\">\n<code>\nfunction setup() {\n  let v = createVector(1, 2, 3);
13864\n  v.set(4, 5, 6); // Sets vector to [4, 5, 6]\n\n  let v1 = createVector(0, 0, 0);\n  let arr = [1, 2, 3];\n  v1.set(arr); // Sets vector to [1, 2, 3]\n}\n</code>\n</div>\n\n<div>\n<code>\nlet v0, v1;\nfunction setup() {\n  createCanvas(100, 100);\n\n  v0 = createVector(0, 0);\n  v1 = createVector(50, 50);\n}\n\nfunction draw() {\n  background(240);\n\n  drawArrow(v0, v1, 'black');\n  v1.set(v1.x + random(-1, 1), v1.y + random(-1, 1));\n\n  noStroke();\n  text('x: ' + round(v1.x) + ' y: ' + round(v1.y), 20, 90);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
13865          "class": "p5.Vector",
13866          "module": "Math",
13867          "submodule": "Math",
13868          "overloads": [{
13869            "line": 134,
13870            "params": [{
13871              "name": "x",
13872              "description": "<p>the x component of the vector</p>\n",
13873              "type": "Number",
13874              "optional": true
13875            }, {
13876              "name": "y",
13877              "description": "<p>the y component of the vector</p>\n",
13878              "type": "Number",
13879              "optional": true
13880            }, {
13881              "name": "z",
13882              "description": "<p>the z component of the vector</p>\n",
13883              "type": "Number",
13884              "optional": true
13885            }],
13886            "chainable": 1
13887          }, {
13888            "line": 193,
13889            "params": [{
13890              "name": "value",
13891              "description": "<p>the vector to set</p>\n",
13892              "type": "p5.Vector|Number[]"
13893            }],
13894            "chainable": 1
13895          }]
13896        }, {
13897          "file": "src/math/p5.Vector.js",
13898          "line": 217,
13899          "description": "<p>Gets a copy of the vector, returns a <a href=\"#/p5.Vector\">p5.Vector</a> object.</p>\n",
13900          "itemtype": "method",
13901          "name": "copy",
13902          "return": {
13903            "description": "the copy of the <a href=\"#/p5.Vector\">p5.Vector</a> object",
13904            "type": "p5.Vector"
13905          },
13906          "example": ["\n<div class=\"norender\">\n<code>\nlet v1 = createVector(1, 2, 3);\nlet v2 = v1.copy();\nprint(v1.x === v2.x && v1.y === v2.y && v1.z === v2.z);\n// Prints \"true\"\n</code>\n</div>"],
13907          "class": "p5.Vector",
13908          "module": "Math",
13909          "submodule": "Math"
13910        }, {
13911          "file": "src/math/p5.Vector.js",
13912          "line": 240,
13913          "description": "<p>Adds x, y, and z components to a vector, adds one vector to another, or\nadds two independent vectors together. The version of the method that adds\ntwo vectors together is a static method and returns a <a href=\"#/p5.Vector\">p5.Vector</a>, the others\nacts directly on the vector. See the examples for more context.</p>\n",
13914          "itemtype": "method",
13915          "name": "add",
13916          "chainable": 1,
13917          "example": ["\n<div class=\"norender\">\n<code>\nlet v = createVector(1, 2, 3);\nv.add(4, 5, 6);\n// v's components are set to [5, 7, 9]\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// Static method\nlet v1 = createVector(1, 2, 3);\nlet v2 = createVector(2, 3, 4);\n\nlet v3 = p5.Vector.add(v1, v2);\n// v3 has components [3, 5, 7]\nprint(v3);\n</code>\n</div>\n\n<div>\n<code>\n// red vector + blue vector = purple vector\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(0, 0);\n  let v1 = createVector(mouseX, mouseY);\n  drawArrow(v0, v1, 'red');\n\n  let v2 = createVector(-30, 20);\n  drawArrow(v1, v2, 'blue');\n\n  let v3 = p5.Vector.add(v1, v2);\n  drawArrow(v0, v3, 'purple');\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
13918          "class": "p5.Vector",
13919          "module": "Math",
13920          "submodule": "Math",
13921          "overloads": [{
13922            "line": 240,
13923            "params": [{
13924              "name": "x",
13925              "description": "<p>the x component of the vector to be added</p>\n",
13926              "type": "Number"
13927            }, {
13928              "name": "y",
13929              "description": "<p>the y component of the vector to be added</p>\n",
13930              "type": "Number",
13931              "optional": true
13932            }, {
13933              "name": "z",
13934              "description": "<p>the z component of the vector to be added</p>\n",
13935              "type": "Number",
13936              "optional": true
13937            }],
13938            "chainable": 1
13939          }, {
13940            "line": 306,
13941            "params": [{
13942              "name": "value",
13943              "description": "<p>the vector to add</p>\n",
13944              "type": "p5.Vector|Number[]"
13945            }],
13946            "chainable": 1
13947          }, {
13948            "line": 1556,
13949            "params": [{
13950              "name": "v1",
13951              "description": "<p>a <a href=\"#/p5.Vector\">p5.Vector</a> to add</p>\n",
13952              "type": "p5.Vector"
13953            }, {
13954              "name": "v2",
13955              "description": "<p>a <a href=\"#/p5.Vector\">p5.Vector</a> to add</p>\n",
13956              "type": "p5.Vector"
13957            }, {
13958              "name": "target",
13959              "description": "<p>the vector to receive the result</p>\n",
13960              "type": "p5.Vector"
13961            }],
13962            "static": 1
13963          }, {
13964            "line": 1563,
13965            "params": [{
13966              "name": "v1",
13967              "description": "",
13968              "type": "p5.Vector"
13969            }, {
13970              "name": "v2",
13971              "description": "",
13972              "type": "p5.Vector"
13973            }],
13974            "static": 1,
13975            "return": {
13976              "description": "the resulting <a href=\"#/p5.Vector\">p5.Vector</a>",
13977              "type": "p5.Vector"
13978            }
13979          }]
13980        }, {
13981          "file": "src/math/p5.Vector.js",
13982          "line": 330,
13983          "description": "<p>Subtracts x, y, and z components from a vector, subtracts one vector from\nanother, or subtracts two independent vectors. The version of the method\nthat subtracts two vectors is a static method and returns a <a href=\"#/p5.Vector\">p5.Vector</a>, the\nother acts directly on the vector. See the examples for more context.</p>\n",
13984          "itemtype": "method",
13985          "name": "sub",
13986          "chainable": 1,
13987          "example": ["\n<div class=\"norender\">\n<code>
13987\nlet v = createVector(4, 5, 6);\nv.sub(1, 1, 1);\n// v's components are set to [3, 4, 5]\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// Static method\nlet v1 = createVector(2, 3, 4);\nlet v2 = createVector(1, 2, 3);\n\nlet v3 = p5.Vector.sub(v1, v2);\n// v3 has components [1, 1, 1]\nprint(v3);\n</code>\n</div>\n\n<div>\n<code>\n// red vector - blue vector = purple vector\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(0, 0);\n  let v1 = createVector(70, 50);\n  drawArrow(v0, v1, 'red');\n\n  let v2 = createVector(mouseX, mouseY);\n  drawArrow(v0, v2, 'blue');\n\n  let v3 = p5.Vector.sub(v1, v2);\n  drawArrow(v2, v3, 'purple');\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
13988          "class": "p5.Vector",
13989          "module": "Math",
13990          "submodule": "Math",
13991          "overloads": [{
13992            "line": 330,
13993            "params": [{
13994              "name": "x",
13995              "description": "<p>the x component of the vector to subtract</p>\n",
13996              "type": "Number"
13997            }, {
13998              "name": "y",
13999              "description": "<p>the y component of the vector to subtract</p>\n",
14000              "type": "Number",
14001              "optional": true
14002            }, {
14003              "name": "z",
14004              "description": "<p>the z component of the vector to subtract</p>\n",
14005              "type": "Number",
14006              "optional": true
14007            }],
14008            "chainable": 1
14009          }, {
14010            "line": 396,
14011            "params": [{
14012              "name": "value",
14013              "description": "<p>the vector to subtract</p>\n",
14014              "type": "p5.Vector|Number[]"
14015            }],
14016            "chainable": 1
14017          }, {
14018            "line": 1586,
14019            "params": [{
14020              "name": "v1",
14021              "description": "<p>a <a href=\"#/p5.Vector\">p5.Vector</a> to subtract from</p>\n",
14022              "type": "p5.Vector"
14023            }, {
14024              "name": "v2",
14025              "description": "<p>a <a href=\"#/p5.Vector\">p5.Vector</a> to subtract</p>\n",
14026              "type": "p5.Vector"
14027            }, {
14028              "name": "target",
14029              "description": "<p>if undefined a new vector will be created</p>\n",
14030              "type": "p5.Vector"
14031            }],
14032            "static": 1
14033          }, {
14034            "line": 1593,
14035            "params": [{
14036              "name": "v1",
14037              "description": "",
14038              "type": "p5.Vector"
14039            }, {
14040              "name": "v2",
14041              "description": "",
14042              "type": "p5.Vector"
14043            }],
14044            "static": 1,
14045            "return": {
14046              "description": "the resulting <a href=\"#/p5.Vector\">p5.Vector</a>",
14047              "type": "p5.Vector"
14048            }
14049          }]
14050        }, {
14051          "file": "src/math/p5.Vector.js",
14052          "line": 420,
14053          "description": "<p>Multiply the vector by a scalar. The static version of this method\ncreates a new <a href=\"#/p5.Vector\">p5.Vector</a> while the non static version acts on the vector\ndirectly. See the examples for more context.</p>\n",
14054          "itemtype": "method",
14055          "name": "mult",
14056          "chainable": 1,
14057          "example": ["\n<div class=\"norender\">\n<code>\nlet v = createVector(1, 2, 3);\nv.mult(2);\n// v's components are set to [2, 4, 6]\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// Static method\nlet v1 = createVector(1, 2, 3);\nlet v2 = p5.Vector.mult(v1, 2);\n// v2 has components [2, 4, 6]\nprint(v2);\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(50, 50);\n  let v1 = createVector(25, -25);\n  drawArrow(v0, v1, 'red');\n\n  let num = map(mouseX, 0, width, -2, 2, true);\n  let v2 = p5.Vector.mult(v1, num);\n  drawArrow(v0, v2, 'blue');\n\n  noStroke();\n  text('multiplied by ' + num.toFixed(2), 5, 90);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
14058          "class": "p5.Vector",
14059          "module": "Math",
14060          "submodule": "Math",
14061          "overloads": [{
14062            "line": 420,
14063            "params": [{
14064              "name": "n",
14065              "description": "<p>the number to multiply with the vector</p>\n",
14066              "type": "Number"
14067            }],
14068            "chainable": 1
14069          }, {
14070            "line": 1614,
14071            "params": [{
14072              "name": "v",
14073              "description": "<p>the vector to multiply</p>\n",
14074              "type": "p5.Vector"
14075            }, {
14076              "name": "n",
14077              "description": "",
14078              "type": "Number"
14079            }, {
14080              "name": "target",
14081              "description": "<p>if undefined a new vector will be created</p>\n",
14082              "type": "p5.Vector"
14083            }],
14084            "static": 1
14085          }, {
14086            "line": 1621,
14087            "params": [{
14088              "name": "v",
14089              "description": "",
14090              "type": "p5.Vector"
14091            }, {
14092              "name": "n",
14093              "description": "",
14094              "type": "Number"
14095            }],
14096            "static": 1,
14097            "return": {
14098              "description": "the resulting new <a href=\"#/p5.Vector\">p5.Vector</a>",
14099              "type": "p5.Vector"
14100            }
14101          }]
14102        }, {
14103          "file": "src/math/p5.Vector.js",
14104          "line": 495,
14105          "description": "<p>Divide the vector by a scalar. The static version of this method creates a\nnew <a href=\"#/p5.Vector\">p5.Vector</a> while the non static version acts on the vector directly.\nSee the examples for more context.</p>\n",
14106          "itemtype": "method",
14107          "name": "div",
14108          "chainable": 1,
14109          "example": ["\n<div class=\"norender\">\n<code>\nlet v = createVector(6, 4, 2);\nv.div(2); //v's components are set to [3, 2, 1]\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// Static method\nlet v1 = createVector(6, 4, 2);\nlet v2 = p5.Vector.div(v1, 2);\n// v2 has components [3, 2, 1]\nprint(v2);\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(0, 100);\n  let v1 = createVector(50, -50);\n  drawArrow(v0, v1, 'red');\n\n  let num = map(mouseX, 0, width, 10, 0.5, true);\n  let v2 = p5.Vector.div(v1, num);\n  drawArrow(v0, v2, 'blue');\n\n  noStroke();\n  text('divided by ' + num.toFixed(2), 10, 90);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
14110          "class": "p5.Vector",
14111          "module": "Math",
14112          "submodule": "Math",
14113          "overloads": [{
14114            "line": 495,
14115            "params": [{
14116              "name": "n",
14117              "description": "<p>the number to divide the vector by</p>\n",
14118              "type": "Number"
14119            }],
14120            "chainable": 1
14121          }, {
14122            "line": 1641,
14123            "params": [{
14124              "name": "v",
14125              "description": "<p>the vector to divide</p>\n",
14126              "type": "p5.Vector"
14127            }, {
14128              "name": "n",
14129              "description": "",
14130              "type": "Number"
14131            }, {
14132              "name": "target",
14133              "description": "<p>if undefined a new vector will be created</p>\n",
14134              "type": "p5.Vector"
14135            }],
14136            "static": 1
14137          }, {
14138            "line": 1648,
14139            "params": [{
14140              "name": "v",
14141              "description": "",
14142              "type": "p5.Vector"
14143            }, {
14144              "name": "n",
14145              "description": "",
14146              "type": "Number"
14147            }],
14148            "static": 1,
14149            "return": {
14150              "description": "the resulting new <a href=\"#/p5.Vector\">p5.Vector</a>",
14151              "type": "p5.Vector"
14152            }
14153          }]
14154        }, {
14155          "file": "src/math/p5.Vector.js",
14156          "line": 573,
14157          "description": "<p>Calculates the magnitude (length) of the vector and returns the result as\na float (this is simply the equation sqrt(x<em>x + y</em>y + z*z).)</p>\n",
14158          "itemtype": "method",
14159          "name": "mag",
14160          "return": {
14161            "description": "magnitude of the vector",
14162            "type": "Number"
14163          },
14164          "example": ["\n<div>\n<code>\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(0, 0);\n  let v1 = createVector(mouseX, mouseY);\n  drawArrow(v0, v1, 'black');\n\n  noStroke();
14164\n  text('vector length: ' + v1.mag().toFixed(2), 10, 70, 90, 30);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>\n<div class=\"norender\">\n<code>\nlet v = createVector(20.0, 30.0, 40.0);\nlet m = v.mag();\nprint(m); // Prints \"53.85164807134504\"\n</code>\n</div>"],
14165          "class": "p5.Vector",
14166          "module": "Math",
14167          "submodule": "Math",
14168          "overloads": [{
14169            "line": 573,
14170            "params": [],
14171            "return": {
14172              "description": "magnitude of the vector",
14173              "type": "Number"
14174            }
14175          }, {
14176            "line": 1738,
14177            "params": [{
14178              "name": "vecT",
14179              "description": "<p>the vector to return the magnitude of</p>\n",
14180              "type": "p5.Vector"
14181            }],
14182            "static": 1,
14183            "return": {
14184              "description": "the magnitude of vecT",
14185              "type": "Number"
14186            }
14187          }]
14188        }, {
14189          "file": "src/math/p5.Vector.js",
14190          "line": 621,
14191          "description": "<p>Calculates the squared magnitude of the vector and returns the result\nas a float (this is simply the equation <em>(x<em>x + y</em>y + z*z)</em>.)\nFaster if the real length is not required in the\ncase of comparing vectors, etc.</p>\n",
14192          "itemtype": "method",
14193          "name": "magSq",
14194          "return": {
14195            "description": "squared magnitude of the vector",
14196            "type": "Number"
14197          },
14198          "example": ["\n<div class=\"norender\">\n<code>\n// Static method\nlet v1 = createVector(6, 4, 2);\nprint(v1.magSq()); // Prints \"56\"\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(0, 0);\n  let v1 = createVector(mouseX, mouseY);\n  drawArrow(v0, v1, 'black');\n\n  noStroke();\n  text('vector length squared: ' + v1.magSq().toFixed(2), 10, 45, 90, 55);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
14199          "class": "p5.Vector",
14200          "module": "Math",
14201          "submodule": "Math"
14202        }, {
14203          "file": "src/math/p5.Vector.js",
14204          "line": 675,
14205          "description": "<p>Calculates the dot product of two vectors. The version of the method\nthat computes the dot product of two independent vectors is a static\nmethod. See the examples for more context.</p>\n",
14206          "itemtype": "method",
14207          "name": "dot",
14208          "return": {
14209            "description": "the dot product",
14210            "type": "Number"
14211          },
14212          "example": ["\n<div class=\"norender\">\n<code>\nlet v1 = createVector(1, 2, 3);\nlet v2 = createVector(2, 3, 4);\n\nprint(v1.dot(v2)); // Prints \"20\"\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n//Static method\nlet v1 = createVector(1, 2, 3);\nlet v2 = createVector(3, 2, 1);\nprint(p5.Vector.dot(v1, v2)); // Prints \"10\"\n</code>\n</div>"],
14213          "class": "p5.Vector",
14214          "module": "Math",
14215          "submodule": "Math",
14216          "overloads": [{
14217            "line": 675,
14218            "params": [{
14219              "name": "x",
14220              "description": "<p>x component of the vector</p>\n",
14221              "type": "Number"
14222            }, {
14223              "name": "y",
14224              "description": "<p>y component of the vector</p>\n",
14225              "type": "Number",
14226              "optional": true
14227            }, {
14228              "name": "z",
14229              "description": "<p>z component of the vector</p>\n",
14230              "type": "Number",
14231              "optional": true
14232            }],
14233            "return": {
14234              "description": "the dot product",
14235              "type": "Number"
14236            }
14237          }, {
14238            "line": 706,
14239            "params": [{
14240              "name": "value",
14241              "description": "<p>value component of the vector or a <a href=\"#/p5.Vector\">p5.Vector</a></p>\n",
14242              "type": "p5.Vector"
14243            }],
14244            "return": {
14245              "description": "",
14246              "type": "Number"
14247            }
14248          }, {
14249            "line": 1668,
14250            "params": [{
14251              "name": "v1",
14252              "description": "<p>the first <a href=\"#/p5.Vector\">p5.Vector</a></p>\n",
14253              "type": "p5.Vector"
14254            }, {
14255              "name": "v2",
14256              "description": "<p>the second <a href=\"#/p5.Vector\">p5.Vector</a></p>\n",
14257              "type": "p5.Vector"
14258            }],
14259            "static": 1,
14260            "return": {
14261              "description": "the dot product",
14262              "type": "Number"
14263            }
14264          }]
14265        }, {
14266          "file": "src/math/p5.Vector.js",
14267          "line": 718,
14268          "description": "<p>Calculates and returns a vector composed of the cross product between\ntwo vectors. Both the static and non static methods return a new <a href=\"#/p5.Vector\">p5.Vector</a>.\nSee the examples for more context.</p>\n",
14269          "itemtype": "method",
14270          "name": "cross",
14271          "return": {
14272            "description": "<a href=\"#/p5.Vector\">p5.Vector</a> composed of cross product",
14273            "type": "p5.Vector"
14274          },
14275          "example": ["\n<div class=\"norender\">\n<code>\nlet v1 = createVector(1, 2, 3);\nlet v2 = createVector(1, 2, 3);\n\nv1.cross(v2); // v's components are [0, 0, 0]\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// Static method\nlet v1 = createVector(1, 0, 0);\nlet v2 = createVector(0, 1, 0);
14275\n\nlet crossProduct = p5.Vector.cross(v1, v2);\n// crossProduct has components [0, 0, 1]\nprint(crossProduct);\n</code>\n</div>"],
14276          "class": "p5.Vector",
14277          "module": "Math",
14278          "submodule": "Math",
14279          "overloads": [{
14280            "line": 718,
14281            "params": [{
14282              "name": "v",
14283              "description": "<p><a href=\"#/p5.Vector\">p5.Vector</a> to be crossed</p>\n",
14284              "type": "p5.Vector"
14285            }],
14286            "return": {
14287              "description": "<a href=\"#/p5.Vector\">p5.Vector</a> composed of cross product",
14288              "type": "p5.Vector"
14289            }
14290          }, {
14291            "line": 1682,
14292            "params": [{
14293              "name": "v1",
14294              "description": "<p>the first <a href=\"#/p5.Vector\">p5.Vector</a></p>\n",
14295              "type": "p5.Vector"
14296            }, {
14297              "name": "v2",
14298              "description": "<p>the second <a href=\"#/p5.Vector\">p5.Vector</a></p>\n",
14299              "type": "p5.Vector"
14300            }],
14301            "static": 1,
14302            "return": {
14303              "description": "the cross product",
14304              "type": "Number"
14305            }
14306          }]
14307        }, {
14308          "file": "src/math/p5.Vector.js",
14309          "line": 759,
14310          "description": "<p>Calculates the Euclidean distance between two points (considering a\npoint as a vector object).</p>\n",
14311          "itemtype": "method",
14312          "name": "dist",
14313          "return": {
14314            "description": "the distance",
14315            "type": "Number"
14316          },
14317          "example": ["\n<div class=\"norender\">\n<code>\nlet v1 = createVector(1, 0, 0);\nlet v2 = createVector(0, 1, 0);\n\nlet distance = v1.dist(v2); // distance is 1.4142...\nprint(distance);\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\n// Static method\nlet v1 = createVector(1, 0, 0);\nlet v2 = createVector(0, 1, 0);\n\nlet distance = p5.Vector.dist(v1, v2);\n// distance is 1.4142...\nprint(distance);\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(0, 0);\n\n  let v1 = createVector(70, 50);\n  drawArrow(v0, v1, 'red');\n\n  let v2 = createVector(mouseX, mouseY);\n  drawArrow(v0, v2, 'blue');\n\n  noStroke();\n  text('distance between vectors: ' + v2.dist(v1).toFixed(2), 5, 50, 95, 50);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
14318          "class": "p5.Vector",
14319          "module": "Math",
14320          "submodule": "Math",
14321          "overloads": [{
14322            "line": 759,
14323            "params": [{
14324              "name": "v",
14325              "description": "<p>the x, y, and z coordinates of a <a href=\"#/p5.Vector\">p5.Vector</a></p>\n",
14326              "type": "p5.Vector"
14327            }],
14328            "return": {
14329              "description": "the distance",
14330              "type": "Number"
14331            }
14332          }, {
14333            "line": 1697,
14334            "params": [{
14335              "name": "v1",
14336              "description": "<p>the first <a href=\"#/p5.Vector\">p5.Vector</a></p>\n",
14337              "type": "p5.Vector"
14338            }, {
14339              "name": "v2",
14340              "description": "<p>the second <a href=\"#/p5.Vector\">p5.Vector</a></p>\n",
14341              "type": "p5.Vector"
14342            }],
14343            "static": 1,
14344            "return": {
14345              "description": "the distance",
14346              "type": "Number"
14347            }
14348          }]
14349        }, {
14350          "file": "src/math/p5.Vector.js",
14351          "line": 830,
14352          "description": "<p>Normalize the vector to length 1 (make it a unit vector).</p>\n",
14353          "itemtype": "method",
14354          "name": "normalize",
14355          "return": {
14356            "description": "normalized <a href=\"#/p5.Vector\">p5.Vector</a>",
14357            "type": "p5.Vector"
14358          },
14359          "example": ["\n<div class=\"norender\">\n<code>\nlet v = createVector(10, 20, 2);\n// v has components [10.0, 20.0, 2.0]\nv.normalize();\n// v's components are set to\n// [0.4454354, 0.8908708, 0.089087084]\n</code>\n</div>\n<div>\n<code>\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(50, 50);\n  let v1 = createVector(mouseX - 50, mouseY - 50);\n\n  drawArrow(v0, v1, 'red');\n  v1.normalize();\n  drawArrow(v0, v1.mult(35), 'blue');\n\n  noFill();\n  ellipse(50, 50, 35 * 2);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
14360          "class": "p5.Vector",
14361          "module": "Math",
14362          "submodule": "Math"
14363        }, {
14364          "file": "src/math/p5.Vector.js",
14365          "line": 886,
14366          "description": "<p>Limit the magnitude of this vector to the value used for the <b>max</b>\nparameter.</p>\n",
14367          "itemtype": "method",
14368          "name": "limit",
14369          "params": [{
14370            "name": "max",
14371            "description": "<p>the maximum magnitude for the vector</p>\n",
14372            "type": "Number"
14373          }],
14374          "chainable": 1,
14375          "example": ["\n<div class=\"norender\">\n<code>\nlet v = createVector(10, 20, 2);\n// v has components [10.0, 20.0, 2.0]\nv.limit(5);\n// v's components are set to\n// [2.2271771, 4.4543543, 0.4454354]\n</code>\n</div>\n<div>\n<code>\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(50, 50);\n  let v1 = createVector(mouseX - 50, mouseY - 50);\n\n  drawArrow(v0, v1, 'red');\n  drawArrow(v0, v1.limit(35), 'blue');\n\n  noFill();\n  ellipse(50, 50, 35 * 2);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
14376          "class": "p5.Vector",
14377          "module": "Math",
14378          "submodule": "Math"
14379        }, {
14380          "file": "src/math/p5.Vector.js",
14381          "line": 944,
14382          "description": "<p>Set the magnitude of this vector to the value used for the <b>len</b>\nparameter.</p>\n",
14383          "itemtype": "method",
14384          "name": "setMag",
14385          "params": [{
14386            "name": "len",
14387            "description": "<p>the new length for this vector</p>\n",
14388            "type": "Number"
14389          }],
14390          "chainable": 1,
14391          "example": ["\n<div class=\"norender\">\n<code>\nlet v = createVector(10, 20, 2);\n// v has components [10.0, 20.0, 2.0]\nv.setMag(10);\n// v's components are set to [6.0, 8.0, 0.0]\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(0, 0);\n  let v1 = createVector(50, 50);\n\n  drawArrow(v0, v1, 'red');\n\n  let length = map(mouseX, 0, width, 0, 141, true);\n  v1.setMag(length);\n  drawArrow(v0, v1, 'blue');\n\n  noStroke();\n  text('magnitude set to: ' + length.toFixed(2), 10, 70, 90, 30);\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
14392          "class": "p5.Vector",
14393          "module": "Math",
14394          "submodule": "Math"
14395        }, {
14396          "file": "src/math/p5.Vector.js",
14397          "line": 1000,
14398          "description": "<p>Calculate the angle of rotation for this vector (only 2D vectors)</p>\n",
14399          "itemtype": "method",
14400          "name": "heading",
14401          "return": {
14402            "description": "the angle of rotation",
14403            "type": "Number"
14404          },
14405          "example": ["\n<div class = \"norender\">\n<code>\nfunction setup() {\n  let v1 = createVector(30, 50);\n  print(v1.heading()); // 1.0303768265243125\n\n  v1 = createVector(40, 50);\n  print(v1.heading());
14405 // 0.8960553845713439\n\n  v1 = createVector(30, 70);\n  print(v1.heading()); // 1.1659045405098132\n}\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(50, 50);\n  let v1 = createVector(mouseX - 50, mouseY - 50);\n\n  drawArrow(v0, v1, 'black');\n\n  let myHeading = v1.heading();\n  noStroke();\n  text(\n    'vector heading: ' +\n      myHeading.toFixed(2) +\n      ' radians or ' +\n      degrees(myHeading).toFixed(2) +\n      ' degrees',\n    10,\n    50,\n    90,\n    50\n  );\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
14406          "class": "p5.Vector",
14407          "module": "Math",
14408          "submodule": "Math"
14409        }, {
14410          "file": "src/math/p5.Vector.js",
14411          "line": 1069,
14412          "description": "<p>Rotate the vector by an angle (only 2D vectors), magnitude remains the\nsame</p>\n",
14413          "itemtype": "method",
14414          "name": "rotate",
14415          "params": [{
14416            "name": "angle",
14417            "description": "<p>the angle of rotation</p>\n",
14418            "type": "Number"
14419          }],
14420          "chainable": 1,
14421          "example": ["\n<div class=\"norender\">\n<code>\nlet v = createVector(10.0, 20.0);\n// v has components [10.0, 20.0, 0.0]\nv.rotate(HALF_PI);\n// v's components are set to [-20.0, 9.999999, 0.0]\n</code>\n</div>\n\n<div>\n<code>\nlet angle = 0;\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(50, 50);\n  let v1 = createVector(50, 0);\n\n  drawArrow(v0, v1.rotate(angle), 'black');\n  angle += 0.01;\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
14422          "class": "p5.Vector",
14423          "module": "Math",
14424          "submodule": "Math"
14425        }, {
14426          "file": "src/math/p5.Vector.js",
14427          "line": 1125,
14428          "description": "<p>Calculates and returns the angle (in radians) between two vectors.</p>\n",
14429          "itemtype": "method",
14430          "name": "angleBetween",
14431          "params": [{
14432            "name": "the",
14433            "description": "<p>x, y, and z components of a <a href=\"#/p5.Vector\">p5.Vector</a></p>\n",
14434            "type": "p5.Vector"
14435          }],
14436          "return": {
14437            "description": "the angle between (in radians)",
14438            "type": "Number"
14439          },
14440          "example": ["\n<div class=\"norender\">\n<code>\nlet v1 = createVector(1, 0, 0);\nlet v2 = createVector(0, 1, 0);\n\nlet angle = v1.angleBetween(v2);\n// angle is PI/2\nprint(angle);\n</code>\n</div>\n\n<div>\n<code>\nfunction draw() {\n  background(240);\n  let v0 = createVector(50, 50);\n\n  let v1 = createVector(50, 0);\n  drawArrow(v0, v1, 'red');\n\n  let v2 = createVector(mouseX - 50, mouseY - 50);\n  drawArrow(v0, v2, 'blue');\n\n  let angleBetween = v1.angleBetween(v2);\n  noStroke();\n  text(\n    'angle between: ' +\n      angleBetween.toFixed(2) +\n      ' radians or ' +\n      degrees(angleBetween).toFixed(2) +\n      ' degrees',\n    10,\n    50,\n    90,\n    50\n  );\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
14441          "class": "p5.Vector",
14442          "module": "Math",
14443          "submodule": "Math"
14444        }, {
14445          "file": "src/math/p5.Vector.js",
14446          "line": 1198,
14447          "description": "<p>Linear interpolate the vector to another vector</p>\n",
14448          "itemtype": "method",
14449          "name": "lerp",
14450          "chainable": 1,
14451          "example": ["\n<div class=\"norender\">\n<code>\nlet v = createVector(1, 1, 0);\n\nv.lerp(3, 3, 0, 0.5); // v now has components [2,2,0]\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nlet v1 = createVector(0, 0, 0);\nlet v2 = createVector(100, 100, 0);\n\nlet v3 = p5.Vector.lerp(v1, v2, 0.5);\n// v3 has components [50,50,0]\nprint(v3);\n</code>\n</div>\n\n<div>\n<code>\nlet step = 0.01;\nlet amount = 0;\n\nfunction draw() {\n  background(240);\n  let v0 = createVector(0, 0);\n\n  let v1 = createVector(mouseX, mouseY);\n  drawArrow(v0, v1, 'red');\n\n  let v2 = createVector(90, 90);\n  drawArrow(v0, v2, 'blue');\n\n  if (amount > 1 || amount < 0) {\n    step *= -1;\n  }\n  amount += step;\n  let v3 = p5.Vector.lerp(v1, v2, amount);\n\n  drawArrow(v0, v3, 'purple');\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
14452          "class": "p5.Vector",
14453          "module": "Math",
14454          "submodule": "Math",
14455          "overloads": [{
14456            "line": 1198,
14457            "params": [{
14458              "name": "x",
14459              "description": "<p>the x component</p>\n",
14460              "type": "Number"
14461            }, {
14462              "name": "y",
14463              "description": "<p>the y component</p>\n",
14464              "type": "Number"
14465            }, {
14466              "name": "z",
14467              "description": "<p>the z component</p>\n",
14468              "type": "Number"
14469            }, {
14470              "name": "amt",
14471              "description": "<p>the amount of interpolation; some value between 0.0\n                        (old vector) and 1.0 (new vector). 0.9 is very near\n                        the new vector. 0.5 is halfway in between.</p>\n",
14472              "type": "Number"
14473            }],
14474            "chainable": 1
14475          }, {
14476            "line": 1271,
14477            "params": [{
14478              "name": "v",
14479              "description": "<p>the <a href=\"#/p5.Vector\">p5.Vector</a> to lerp to</p>\n",
14480              "type": "p5.Vector"
14481            }, {
14482              "name": "amt",
14483              "description": "",
14484              "type": "Number"
14485            }],
14486            "chainable": 1
14487          }, {
14488            "line": 1712,
14489            "params": [{
14490              "name": "v1",
14491              "description": "",
14492              "type": "p5.Vector"
14493            }, {
14494              "name": "v2",
14495              "description": "",
14496              "type": "p5.Vector"
14497            }, {
14498              "name": "amt",
14499              "description": "",
14500              "type": "Number"
14501            }, {
14502              "name": "target",
14503              "description": "<p>if undefined a new vector will be created</p>\n",
14504              "type": "p5.Vector"
14505            }],
14506            "static": 1
14507          }, {
14508            "line": 1720,
14509            "params": [{
14510              "name": "v1",
14511              "description": "",
14512              "type": "p5.Vector"
14513            }, {
14514              "name": "v2",
14515              "description": "",
14516              "type": "p5.Vector"
14517            }, {
14518              "name": "amt",
14519              "description": "",
14520              "type": "Number"
14521            }],
14522            "static": 1,
14523            "return": {
14524              "description": "the lerped value",
14525              "type": "Number"
14526            }
14527          }]
14528        }, {
14529          "file": "src/math/p5.Vector.js",
14530          "line": 1287,
14531          "description": "<p>Return a representation of this vector as a float array. This is only\nfor temporary use. If used in any other fashion, the contents should be\ncopied by using the <b>p5.Vector.<a href=\"#/p5.Vector/copy\">copy()</a></b>
14531 method to copy into your own\narray.</p>\n",
14532          "itemtype": "method",
14533          "name": "array",
14534          "return": {
14535            "description": "an Array with the 3 values",
14536            "type": "Number[]"
14537          },
14538          "example": ["\n<div class = \"norender\">\n<code>\nfunction setup() {\n  let v = createVector(20, 30);\n  print(v.array()); // Prints : Array [20, 30, 0]\n}\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nlet v = createVector(10.0, 20.0, 30.0);\nlet f = v.array();\nprint(f[0]); // Prints \"10.0\"\nprint(f[1]); // Prints \"20.0\"\nprint(f[2]); // Prints \"30.0\"\n</code>\n</div>"],
14539          "class": "p5.Vector",
14540          "module": "Math",
14541          "submodule": "Math"
14542        }, {
14543          "file": "src/math/p5.Vector.js",
14544          "line": 1319,
14545          "description": "<p>Equality check against a <a href=\"#/p5.Vector\">p5.Vector</a></p>\n",
14546          "itemtype": "method",
14547          "name": "equals",
14548          "return": {
14549            "description": "whether the vectors are equals",
14550            "type": "Boolean"
14551          },
14552          "example": ["\n<div class = \"norender\">\n<code>\nlet v1 = createVector(5, 10, 20);\nlet v2 = createVector(5, 10, 20);\nlet v3 = createVector(13, 10, 19);\n\nprint(v1.equals(v2.x, v2.y, v2.z)); // true\nprint(v1.equals(v3.x, v3.y, v3.z)); // false\n</code>\n</div>\n\n<div class=\"norender\">\n<code>\nlet v1 = createVector(10.0, 20.0, 30.0);\nlet v2 = createVector(10.0, 20.0, 30.0);\nlet v3 = createVector(0.0, 0.0, 0.0);\nprint(v1.equals(v2)); // true\nprint(v1.equals(v3)); // false\n</code>\n</div>"],
14553          "class": "p5.Vector",
14554          "module": "Math",
14555          "submodule": "Math",
14556          "overloads": [{
14557            "line": 1319,
14558            "params": [{
14559              "name": "x",
14560              "description": "<p>the x component of the vector</p>\n",
14561              "type": "Number",
14562              "optional": true
14563            }, {
14564              "name": "y",
14565              "description": "<p>the y component of the vector</p>\n",
14566              "type": "Number",
14567              "optional": true
14568            }, {
14569              "name": "z",
14570              "description": "<p>the z component of the vector</p>\n",
14571              "type": "Number",
14572              "optional": true
14573            }],
14574            "return": {
14575              "description": "whether the vectors are equals",
14576              "type": "Boolean"
14577            }
14578          }, {
14579            "line": 1349,
14580            "params": [{
14581              "name": "value",
14582              "description": "<p>the vector to compare</p>\n",
14583              "type": "p5.Vector|Array"
14584            }],
14585            "return": {
14586              "description": "",
14587              "type": "Boolean"
14588            }
14589          }]
14590        }, {
14591          "file": "src/math/p5.Vector.js",
14592          "line": 1374,
14593          "description": "<p>Make a new 2D vector from an angle</p>\n",
14594          "itemtype": "method",
14595          "name": "fromAngle",
14596          "static": 1,
14597          "params": [{
14598            "name": "angle",
14599            "description": "<p>the desired angle, in radians</p>\n",
14600            "type": "Number"
14601          }, {
14602            "name": "length",
14603            "description": "<p>the length of the new vector (defaults to 1)</p>\n",
14604            "type": "Number",
14605            "optional": true
14606          }],
14607          "return": {
14608            "description": "the new <a href=\"#/p5.Vector\">p5.Vector</a> object",
14609            "type": "p5.Vector"
14610          },
14611          "example": ["\n<div>\n<code>\nfunction draw() {\n  background(200);\n\n  // Create a variable, proportional to the mouseX,\n  // varying from 0-360, to represent an angle in degrees.\n  angleMode(DEGREES);\n  let myDegrees = map(mouseX, 0, width, 0, 360);\n\n  // Display that variable in an onscreen text.\n  // (Note the nfc() function to truncate additional decimal places,\n  // and the \"\\xB0\" character for the degree symbol.)\n  let readout = 'angle = ' + nfc(myDegrees, 1) + '\\xB0';\n  noStroke();\n  fill(0);\n  text(readout, 5, 15);\n\n  // Create a p5.Vector using the fromAngle function,\n  // and extract its x and y components.\n  let v = p5.Vector.fromAngle(radians(myDegrees), 30);\n  let vx = v.x;\n  let vy = v.y;\n\n  push();\n  translate(width / 2, height / 2);\n  noFill();\n  stroke(150);\n  line(0, 0, 30, 0);\n  stroke(0);\n  line(0, 0, vx, vy);\n  pop();\n}\n</code>\n</div>"],
14612          "class": "p5.Vector",
14613          "module": "Math",
14614          "submodule": "Math"
14615        }, {
14616          "file": "src/math/p5.Vector.js",
14617          "line": 1426,
14618          "description": "<p>Make a new 3D vector from a pair of ISO spherical angles</p>\n",
14619          "itemtype": "method",
14620          "name": "fromAngles",
14621          "static": 1,
14622          "params": [{
14623            "name": "theta",
14624            "description": "<p>the polar angle, in radians (zero is up)</p>\n",
14625            "type": "Number"
14626          }, {
14627            "name": "phi",
14628            "description": "<p>the azimuthal angle, in radians\n                              (zero is out of the screen)</p>\n",
14629            "type": "Number"
14630          }, {
14631            "name": "length",
14632            "description": "<p>the length of the new vector (defaults to 1)</p>\n",
14633            "type": "Number",
14634            "optional": true
14635          }],
14636          "return": {
14637            "description": "the new <a href=\"#/p5.Vector\">p5.Vector</a> object",
14638            "type": "p5.Vector"
14639          },
14640          "example": ["\n<div modernizr='webgl'>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  fill(255);\n  noStroke();\n}\nfunction draw() {\n  background(255);\n\n  let t = millis() / 1000;\n\n  // add three point lights\n  pointLight(color('#f00'), p5.Vector.fromAngles(t * 1.0, t * 1.3, 100));\n  pointLight(color('#0f0'), p5.Vector.fromAngles(t * 1.1, t * 1.2, 100));\n  pointLight(color('#00f'), p5.Vector.fromAngles(t * 1.2, t * 1.1, 100));\n\n  sphere(35);\n}\n</code>\n</div>"],
14641          "class": "p5.Vector",
14642          "module": "Math",
14643          "submodule": "Math"
14644        }, {
14645          "file": "src/math/p5.Vector.js",
14646          "line": 1475,
14647          "description": "<p>Make a new 2D unit vector from a random angle</p>\n",
14648          "itemtype": "method",
14649          "name": "random2D",
14650          "static": 1,
14651          "return": {
14652            "description": "the new <a href=\"#/p5.Vector\">p5.Vector</a> object",
14653            "type": "p5.Vector"
14654          },
14655          "example": ["\n<div class=\"norender\">\n<code>\nlet v = p5.Vector.random2D();\n// May make v's attributes something like:\n// [0.61554617, -0.51195765, 0.0] or\n// [-0.4695841, -0.
1465514366731, 0.0] or\n// [0.6091097, -0.22805278, 0.0]\nprint(v);\n</code>\n</div>\n\n<div>\n<code>\nfunction setup() {\n  frameRate(1);\n}\n\nfunction draw() {\n  background(240);\n\n  let v0 = createVector(50, 50);\n  let v1 = p5.Vector.random2D();\n  drawArrow(v0, v1.mult(50), 'black');\n}\n\n// draw an arrow for a vector at a given base position\nfunction drawArrow(base, vec, myColor) {\n  push();\n  stroke(myColor);\n  strokeWeight(3);\n  fill(myColor);\n  translate(base.x, base.y);\n  line(0, 0, vec.x, vec.y);\n  rotate(vec.heading());\n  let arrowSize = 7;\n  translate(vec.mag() - arrowSize, 0);\n  triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);\n  pop();\n}\n</code>\n</div>"],
14656          "class": "p5.Vector",
14657          "module": "Math",
14658          "submodule": "Math"
14659        }, {
14660          "file": "src/math/p5.Vector.js",
14661          "line": 1528,
14662          "description": "<p>Make a new random 3D unit vector.</p>\n",
14663          "itemtype": "method",
14664          "name": "random3D",
14665          "static": 1,
14666          "return": {
14667            "description": "the new <a href=\"#/p5.Vector\">p5.Vector</a> object",
14668            "type": "p5.Vector"
14669          },
14670          "example": ["\n<div class=\"norender\">\n<code>\nlet v = p5.Vector.random3D();\n// May make v's attributes something like:\n// [0.61554617, -0.51195765, 0.599168] or\n// [-0.4695841, -0.14366731, -0.8711202] or\n// [0.6091097, -0.22805278, -0.7595902]\nprint(v);\n</code>\n</div>"],
14671          "class": "p5.Vector",
14672          "module": "Math",
14673          "submodule": "Math"
14674        }, {
14675          "file": "src/math/p5.Vector.js",
14676          "line": 1611,
14677          "description": "<p>Multiplies a vector by a scalar and returns a new vector.</p>\n",
14678          "class": "p5.Vector",
14679          "module": "Math",
14680          "submodule": "Math"
14681        }, {
14682          "file": "src/math/p5.Vector.js",
14683          "line": 1638,
14684          "description": "<p>Divides a vector by a scalar and returns a new vector.</p>\n",
14685          "class": "p5.Vector",
14686          "module": "Math",
14687          "submodule": "Math"
14688        }, {
14689          "file": "src/math/p5.Vector.js",
14690          "line": 1665,
14691          "description": "<p>Calculates the dot product of two vectors.</p>\n",
14692          "class": "p5.Vector",
14693          "module": "Math",
14694          "submodule": "Math"
14695        }, {
14696          "file": "src/math/p5.Vector.js",
14697          "line": 1679,
14698          "description": "<p>Calculates the cross product of two vectors.</p>\n",
14699          "class": "p5.Vector",
14700          "module": "Math",
14701          "submodule": "Math"
14702        }, {
14703          "file": "src/math/p5.Vector.js",
14704          "line": 1693,
14705          "description": "<p>Calculates the Euclidean distance between two points (considering a\npoint as a vector object).</p>\n",
14706          "class": "p5.Vector",
14707          "module": "Math",
14708          "submodule": "Math"
14709        }, {
14710          "file": "src/math/p5.Vector.js",
14711          "line": 1708,
14712          "description": "<p>Linear interpolate a vector to another vector and return the result as a\nnew vector.</p>\n",
14713          "class": "p5.Vector",
14714          "module": "Math",
14715          "submodule": "Math"
14716        }, {
14717          "file": "src/math/random.js",
14718          "line": 48,
14719          "description": "<p>Sets the seed value for <a href=\"#/p5/random\">random()</a>.</p>\n<p>By default, <a href=\"#/p5/random\">random()</a> produces different results each time the program\nis run. Set the seed parameter to a constant to return the same\npseudo-random numbers each time the software is run.</p>\n",
14720          "itemtype": "method",
14721          "name": "randomSeed",
14722          "params": [{
14723            "name": "seed",
14724            "description": "<p>the seed value</p>\n",
14725            "type": "Number"
14726          }],
14727          "example": ["\n<div>\n<code>\nrandomSeed(99);\nfor (let i = 0; i < 100; i++) {\n  let r = random(0, 255);\n  stroke(r);\n  line(i, 0, i, 100);\n}\n</code>\n</div>"],
14728          "alt": "many vertical lines drawn in white, black or grey.",
14729          "class": "p5",
14730          "module": "Math",
14731          "submodule": "Random"
14732        }, {
14733          "file": "src/math/random.js",
14734          "line": 79,
14735          "description": "<p>Return a random floating-point number.</p>\n<p>Takes either 0, 1 or 2 arguments.</p>\n<p>If no argument is given, returns a random number from 0\nup to (but not including) 1.</p>\n<p>If one argument is given and it is a number, returns a random number from 0\nup to (but not including) the number.</p>\n<p>If one argument is given and it is an array, returns a random element from\nthat array.</p>\n<p>If two arguments are given, returns a random number from the\nfirst argument up to (but not including) the second argument.</p>\n",
14736          "itemtype": "method",
14737          "name": "random",
14738          "return": {
14739            "description": "the random number",
14740            "type": "Number"
14741          },
14742          "example": ["\n<div>\n<code>\nfor (let i = 0; i < 100;
14742 i++) {\n  let r = random(50);\n  stroke(r * 5);\n  line(50, i, 50 + r, i);\n}\n</code>\n</div>\n<div>\n<code>\nfor (let i = 0; i < 100; i++) {\n  let r = random(-50, 50);\n  line(50, i, 50 + r, i);\n}\n</code>\n</div>\n<div>\n<code>\n// Get a random element from an array using the random(Array) syntax\nlet words = ['apple', 'bear', 'cat', 'dog'];\nlet word = random(words); // select random word\ntext(word, 10, 50); // draw the word\n</code>\n</div>"],
14743          "alt": "100 horizontal lines from center canvas to right. size+fill change each time\n100 horizontal lines from center of canvas. height & side change each render\nword displayed at random. Either apple, bear, cat, or dog",
14744          "class": "p5",
14745          "module": "Math",
14746          "submodule": "Random",
14747          "overloads": [{
14748            "line": 79,
14749            "params": [{
14750              "name": "min",
14751              "description": "<p>the lower bound (inclusive)</p>\n",
14752              "type": "Number",
14753              "optional": true
14754            }, {
14755              "name": "max",
14756              "description": "<p>the upper bound (exclusive)</p>\n",
14757              "type": "Number",
14758              "optional": true
14759            }],
14760            "return": {
14761              "description": "the random number",
14762              "type": "Number"
14763            }
14764          }, {
14765            "line": 133,
14766            "params": [{
14767              "name": "choices",
14768              "description": "<p>the array to choose from</p>\n",
14769              "type": "Array"
14770            }],
14771            "return": {
14772              "description": "the random element from the array",
14773              "type": "*"
14774            }
14775          }]
14776        }, {
14777          "file": "src/math/random.js",
14778          "line": 166,
14779          "description": "<p>Returns a random number fitting a Gaussian, or\n normal, distribution. There is theoretically no minimum or maximum\n value that <a href=\"#/p5/randomGaussian\">randomGaussian()</a> might return. Rather, there is\n just a very low probability that values far from the mean will be\n returned; and a higher probability that numbers near the mean will\n be returned.\n <br><br>\n Takes either 0, 1 or 2 arguments.<br>\n If no args, returns a mean of 0 and standard deviation of 1.<br>\n If one arg, that arg is the mean (standard deviation is 1).<br>\n If two args, first is mean, second is standard deviation.</p>\n",
14780          "itemtype": "method",
14781          "name": "randomGaussian",
14782          "params": [{
14783            "name": "mean",
14784            "description": "<p>the mean</p>\n",
14785            "type": "Number"
14786          }, {
14787            "name": "sd",
14788            "description": "<p>the standard deviation</p>\n",
14789            "type": "Number"
14790          }],
14791          "return": {
14792            "description": "the random number",
14793            "type": "Number"
14794          },
14795          "example": ["\n <div>\n <code>\n for (let y = 0; y < 100; y++) {\n   let x = randomGaussian(50, 15);\n   line(50, y, x, y);\n }\n </code>\n </div>\n <div>\n <code>\n let distribution = new Array(360);\nfunction setup() {\n   createCanvas(100, 100);\n   for (let i = 0; i < distribution.length; i++) {\n     distribution[i] = floor(randomGaussian(0, 15));\n   }\n }\nfunction draw() {\n   background(204);\n  translate(width / 2, width / 2);\n  for (let i = 0; i < distribution.length; i++) {\n     rotate(TWO_PI / distribution.length);\n     stroke(0);\n     let dist = abs(distribution[i]);\n     line(0, 0, dist, 0);\n   }\n }\n </code>\n </div>"],
14796          "alt": "100 horizontal lines from center of canvas. height & side change each render\n black lines radiate from center of canvas. size determined each render",
14797          "class": "p5",
14798          "module": "Math",
14799          "submodule": "Random"
14800        }, {
14801          "file": "src/math/trigonometry.js",
14802          "line": 20,
14803          "description": "<p>The inverse of <a href=\"#/p5/cos\">cos()</a>, returns the arc cosine of a value. This function\nexpects the values in the range of -1 to 1 and values are returned in\nthe range 0 to PI (3.1415927).</p>\n",
14804          "itemtype": "method",
14805          "name": "acos",
14806          "params": [{
14807            "name": "value",
14808            "description": "<p>the value whose arc cosine is to be returned</p>\n",
14809            "type": "Number"
14810          }],
14811          "return": {
14812            "description": "the arc cosine of the given value",
14813            "type": "Number"
14814          },
14815          "example": ["\n<div class= “norender\">\n<code>\nlet a = PI;\nlet c = cos(a);\nlet ac = acos(c);\n// Prints: \"3.1415927 : -1.0 : 3.1415927\"\nprint(a + ' : ' + c + ' : ' + ac);\n</code>\n</div>\n\n<div class= “norender\">\n<code>\nlet a = PI + PI / 4.0;\nlet c = cos(a);\nlet ac = acos(c);\n// Prints: \"3.926991 : -0.70710665 : 2.3561943\"\nprint(a + ' : ' + c + ' : ' + ac);\n</code>\n</div>"],
14816          "class": "p5",
14817          "module": "Math",
14818          "submodule": "Trigonometry"
14819        }, {
14820          "file": "src/math/trigonometry.js",
14821          "line": 54,
14822          "description": "<p>The inverse of <a href=\"#/p5/sin\">sin()</a>, returns the arc sine of a value. This function\nexpects the values in the range of -1 to 1 and values are returned\nin the range -PI/2 to PI/2.</p>\n",
14823          "itemtype": "method",
14824          "name": "asin",
14825          "params": [{
14826            "name": "value",
14827            "description": "<p>the value whose arc sine is to be returned</p>\n",
14828            "type": "Number"
14829          }],
14830          "return": {
14831            "description": "the arc sine of the given value",
14832            "type": "Number"
14833          },
14834          "example": ["\n<div class= “norender\">\n<code>\nlet a = PI + PI / 3;\nlet s = sin(a);\nlet as = asin(s);\n// Prints: \"1.0471976 : 0.86602545 : 1.0471976\"\nprint(a + ' : ' + s + ' : ' + as);\n</code>\n</div>\n\n<div class= “norender\">\n<code>\nlet a = PI + PI / 3.0;\nlet s = sin(a);\nlet as = asin(s);\n// Prints: \"4.1887903 : -0.86602545 : -1.0471976\"\nprint(a + ' : ' + s + ' : ' + as);\n</code>\n</div>\n"],
14835          "class": "p5",
14836          "module": "Math",
14837          "submodule": "Trigonometry"
14838        }, {
14839          "file": "src/math/trigonometry.js",
14840          "line": 89,
14841          "description": "<p>The inverse of <a href=\"#/p5/tan\">tan()</a>, returns the arc tangent of a value. This function\nexpects the values in the range of -Infinity to Infinity (exclusive) and\nvalues are returned in the range -PI/2 to PI/2.</p>\n",
14842          "itemtype": "method",
14843          "name": "atan",
14844          "params": [{
14845            "name": "value",
14846            "description": "<p>the value whose arc tangent is to be returned</p>\n",
14847            "type": "Number"
14848          }],
14849          "return": {
14850            "description": "the arc tangent of the given value",
14851            "type": "Number"
14852          },
14853          "example": ["\n<div class= “norender\">\n<code>\nlet a = PI + PI / 3;\nlet t = tan(a);\nlet at = atan(t);\n// Prints: \"1.0471976 : 1.7320509 : 1.0471976\"\nprint(a + ' : ' + t + ' : ' + at);\n</code>\n</div>\n\n<div class= “norender\">\n<code>\nlet a = PI + PI / 3.0;\nlet t = tan(a);\nlet at = atan(t);\n// Prints: \"4.1887903 : 1.7320513 : 1.0471977\"\nprint(a + ' : ' + t + ' : ' + at);\n</code>\n</div>\n"],
14854          "class": "p5",
14855          "module": "Math",
14856          "submodule": "Trigonometry"
14857        }, {
14858          "file": "src/math/trigonometry.js",
14859          "line": 124,
14860          "description": "<p>Calculates the angle (in radians) from a specified point to the coordinate\norigin as measured from the positive x-axis. Values are returned as a\nfloat in the range from PI to -PI. The atan2<a href=\"#/p5/\">()</a> function is most often used\nfor orienting geometry to the position of the cursor.\n<br><br>\nNote: The y-coordinate of the point is the first parameter, and the\nx-coordinate is the second parameter, due the the structure of calculating\nthe tangent.</p>\n",
14861          "itemtype": "method",
14862          "name": "atan2",
14863          "params": [{
14864            "name": "y",
14865            "description": "<p>y-coordinate of the point</p>\n",
14866            "type": "Number"
14867          }, {
14868            "name": "x",
14869            "description": "<p>x-coordinate of the point</p>\n",
14870            "type": "Number"
14871          }],
14872          "return": {
14873            "description": "the arc tangent of the given point",
14874            "type": "Number"
14875          },
14876          "example": ["\n<div>\n<code>\nfunction draw() {\n  background(204);\n  translate(width / 2, height / 2);
14876\n  let a = atan2(mouseY - height / 2, mouseX - width / 2);\n  rotate(a);\n  rect(-30, -5, 60, 10);\n}\n</code>\n</div>"],
14877          "alt": "60 by 10 rect at center of canvas rotates with mouse movements",
14878          "class": "p5",
14879          "module": "Math",
14880          "submodule": "Trigonometry"
14881        }, {
14882          "file": "src/math/trigonometry.js",
14883          "line": 160,
14884          "description": "<p>Calculates the cosine of an angle. This function takes into account the\ncurrent <a href=\"#/p5/angleMode\">angleMode</a>. Values are returned in the range -1 to 1.</p>\n",
14885          "itemtype": "method",
14886          "name": "cos",
14887          "params": [{
14888            "name": "angle",
14889            "description": "<p>the angle</p>\n",
14890            "type": "Number"
14891          }],
14892          "return": {
14893            "description": "the cosine of the angle",
14894            "type": "Number"
14895          },
14896          "example": ["\n<div>\n<code>\nlet a = 0.0;\nlet inc = TWO_PI / 25.0;\nfor (let i = 0; i < 25; i++) {\n  line(i * 4, 50, i * 4, 50 + cos(a) * 40.0);\n  a = a + inc;\n}\n</code>\n</div>"],
14897          "alt": "vertical black lines form wave patterns, extend-down on left and right side",
14898          "class": "p5",
14899          "module": "Math",
14900          "submodule": "Trigonometry"
14901        }, {
14902          "file": "src/math/trigonometry.js",
14903          "line": 188,
14904          "description": "<p>Calculates the sine of an angle. This function takes into account the\ncurrent <a href=\"#/p5/angleMode\">angleMode</a>. Values are returned in the range -1 to 1.</p>\n",
14905          "itemtype": "method",
14906          "name": "sin",
14907          "params": [{
14908            "name": "angle",
14909            "description": "<p>the angle</p>\n",
14910            "type": "Number"
14911          }],
14912          "return": {
14913            "description": "the sine of the angle",
14914            "type": "Number"
14915          },
14916          "example": ["\n<div>\n<code>\nlet a = 0.0;\nlet inc = TWO_PI / 25.0;\nfor (let i = 0; i < 25; i++) {\n  line(i * 4, 50, i * 4, 50 + sin(a) * 40.0);\n  a = a + inc;\n}\n</code>\n</div>"],
14917          "alt": "vertical black lines extend down and up from center to form wave pattern",
14918          "class": "p5",
14919          "module": "Math",
14920          "submodule": "Trigonometry"
14921        }, {
14922          "file": "src/math/trigonometry.js",
14923          "line": 216,
14924          "description": "<p>Calculates the tangent of an angle. This function takes into account\nthe current <a href=\"#/p5/angleMode\">angleMode</a>. Values are returned in the range -1 to 1.</p>\n",
14925          "itemtype": "method",
14926          "name": "tan",
14927          "params": [{
14928            "name": "angle",
14929            "description": "<p>the angle</p>\n",
14930            "type": "Number"
14931          }],
14932          "return": {
14933            "description": "the tangent of the angle",
14934            "type": "Number"
14935          },
14936          "example": ["\n<div>\n<code>\nlet a = 0.0;\nlet inc = TWO_PI / 50.0;\nfor (let i = 0; i < 100; i = i + 2) {\n  line(i, 50, i, 50 + tan(a) * 2.0);\n  a = a + inc;\n}\n</code>"],
14937          "alt": "vertical black lines end down and up from center to form spike pattern",
14938          "class": "p5",
14939          "module": "Math",
14940          "submodule": "Trigonometry"
14941        }, {
14942          "file": "src/math/trigonometry.js",
14943          "line": 244,
14944          "description": "<p>Converts a radian measurement to its corresponding value in degrees.\nRadians and degrees are two ways of measuring the same thing. There are\n360 degrees in a circle and 2*PI radians in a circle. For example,\n90° = PI/2 = 1.5707964. This function does not take into account the\ncurrent <a href=\"#/p5/angleMode\">angleMode</a>.</p>\n",
14945          "itemtype": "method",
14946          "name": "degrees",
14947          "params": [{
14948            "name": "radians",
14949            "description": "<p>the radians value to convert to degrees</p>\n",
14950            "type": "Number"
14951          }],
14952          "return": {
14953            "description": "the converted angle",
14954            "type": "Number"
14955          },
14956          "example": ["\n<div class= “norender\">\n<code>\nlet rad = PI / 4;\nlet deg = degrees(rad);\nprint(rad + ' radians is ' + deg + ' degrees');\n// Prints: 0.7853981633974483 radians is 45 degrees\n</code>\n</div>\n"],
14957          "class": "p5",
14958          "module": "Math",
14959          "submodule": "Trigonometry"
14960        }, {
14961          "file": "src/math/trigonometry.js",
14962          "line": 271,
14963          "description": "<p>Converts a degree measurement to its corresponding value in radians.\nRadians and degrees are two ways of measuring the same thing. There are\n360 degrees in a circle and 2*PI radians in a circle. For example,\n90° = PI/2 = 1.5707964. This function does not take into account the\ncurrent <a href=\"#/p5/angleMode\">angleMode</a>.</p>\n",
14964          "itemtype": "method",
14965          "name": "radians",
14966          "params": [{
14967            "name": "degrees",
14968            "description": "<p>the degree value to convert to radians</p>\n",
14969            "type": "Number"
14970          }],
14971          "return": {
14972            "description": "the converted angle",
14973            "type": "Number"
14974          },
14975          "example": ["\n<div class= “norender\">\n<code>\nlet deg = 45.0;\nlet rad = radians(deg);\nprint(deg + ' degrees is ' + rad + ' radians');\n// Prints: 45 degrees is 0.7853981633974483 radians\n</code>\n</div>"],
14976          "class": "p5",
14977          "module": "Math",
14978          "submodule": "Trigonometry"
14979        }, {
14980          "file": "src/math/trigonometry.js",
14981          "line": 296,
14982          "description": "<p>Sets the current mode of p5 to given mode. Default mode is RADIANS.</p>\n",
14983          "itemtype": "method",
14984          "name": "angleMode",
14985          "params": [{
14986            "name": "mode",
14987            "description": "<p>either RADIANS or DEGREES</p>\n",
14988            "type": "Constant"
14989          }],
14990          "example": ["\n<div>\n<code>\nfunction draw() {\n  background(204);\n  angleMode(DEGREES);
14990 // Change the mode to DEGREES\n  let a = atan2(mouseY - height / 2, mouseX - width / 2);\n  translate(width / 2, height / 2);\n  push();\n  rotate(a);\n  rect(-20, -5, 40, 10); // Larger rectangle is rotating in degrees\n  pop();\n  angleMode(RADIANS); // Change the mode to RADIANS\n  rotate(a); // variable a stays the same\n  rect(-40, -5, 20, 10); // Smaller rectangle is rotating in radians\n}\n</code>\n</div>"],
14991          "alt": "40 by 10 rect in center rotates with mouse moves. 20 by 10 rect moves faster.",
14992          "class": "p5",
14993          "module": "Math",
14994          "submodule": "Trigonometry"
14995        }, {
14996          "file": "src/typography/attributes.js",
14997          "line": 13,
14998          "description": "<p>Sets the current alignment for drawing text. Accepts two\narguments: horizAlign (LEFT, CENTER, or RIGHT) and\nvertAlign (TOP, BOTTOM, CENTER, or BASELINE).</p>\n<p>The horizAlign parameter is in reference to the x value\nof the <a href=\"#/p5/text\">text()</a> function, while the vertAlign parameter is\nin reference to the y value.</p>\n<p>So if you write textAlign(LEFT), you are aligning the left\nedge of your text to the x value you give in <a href=\"#/p5/text\">text()</a>. If you\nwrite textAlign(RIGHT, TOP), you are aligning the right edge\nof your text to the x value and the top of edge of the text\nto the y value.</p>\n",
14999          "itemtype": "method",
15000          "name": "textAlign",
15001          "chainable": 1,
15002          "example": ["\n<div>\n<code>\ntextSize(16);\ntextAlign(RIGHT);\ntext('ABCD', 50, 30);\ntextAlign(CENTER);\ntext('EFGH', 50, 50);\ntextAlign(LEFT);\ntext('IJKL', 50, 70);\n</code>\n</div>\n\n<div>\n<code>\ntextSize(16);\nstrokeWeight(0.5);\n\nline(0, 12, width, 12);\ntextAlign(CENTER, TOP);\ntext('TOP', 0, 12, width);\n\nline(0, 37, width, 37);\ntextAlign(CENTER, CENTER);\ntext('CENTER', 0, 37, width);\n\nline(0, 62, width, 62);\ntextAlign(CENTER, BASELINE);\ntext('BASELINE', 0, 62, width);\n\nline(0, 87, width, 87);\ntextAlign(CENTER, BOTTOM);\ntext('BOTTOM', 0, 87, width);\n</code>\n</div>"],
15003          "alt": "Letters ABCD displayed at top right, EFGH at center and IJKL at bottom left.\nThe names of the four vertical alignments rendered each showing that alignment's placement relative to a horizontal line.",
15004          "class": "p5",
15005          "module": "Typography",
15006          "submodule": "Attributes",
15007          "overloads": [{
15008            "line": 13,
15009            "params": [{
15010              "name": "horizAlign",
15011              "description": "<p>horizontal alignment, either LEFT,\n                           CENTER, or RIGHT</p>\n",
15012              "type": "Constant"
15013            }, {
15014              "name": "vertAlign",
15015              "description": "<p>vertical alignment, either TOP,\n                           BOTTOM, CENTER, or BASELINE</p>\n",
15016              "type": "Constant",
15017              "optional": true
15018            }],
15019            "chainable": 1
15020          }, {
15021            "line": 75,
15022            "params": [],
15023            "return": {
15024              "description": "",
15025              "type": "Object"
15026            }
15027          }]
15028        }, {
15029          "file": "src/typography/attributes.js",
15030          "line": 84,
15031          "description": "<p>Sets/gets the spacing, in pixels, between lines of text. This\nsetting will be used in all subsequent calls to the <a href=\"#/p5/text\">text()</a> function.</p>\n",
15032          "itemtype": "method",
15033          "name": "textLeading",
15034          "chainable": 1,
15035          "example": ["\n<div>\n<code>\n// Text to display. The \"\\n\" is a \"new line\" character\nlet lines = 'L1\\nL2\\nL3';\ntextSize(12);\n\ntextLeading(10); // Set leading to 10\ntext(lines, 10, 25);\n\ntextLeading(20); // Set leading to 20\ntext(lines, 40, 25);\n\ntextLeading(30); // Set leading to 30\ntext(lines, 70, 25);\n</code>\n</div>"],
15036          "alt": "set L1 L2 & L3 displayed vertically 3 times. spacing increases for each set",
15037          "class": "p5",
15038          "module": "Typography",
15039          "submodule": "Attributes",
15040          "overloads": [{
15041            "line": 84,
15042            "params": [{
15043              "name": "leading",
15044              "description": "<p>the size in pixels for spacing between lines</p>\n",
15045              "type": "Number"
15046            }],
15047            "chainable": 1
15048          }, {
15049            "line": 113,
15050            "params": [],
15051            "return": {
15052              "description": "",
15053              "type": "Number"
15054            }
15055          }]
15056        }, {
15057          "file": "src/typography/attributes.js",
15058          "line": 122,
15059          "description": "<p>Sets/gets the current font size. This size will be used in all subsequent\ncalls to the <a href=\"#/p5/text\">text()</a> function. Font size is measured in pixels.</p>\n",
15060          "itemtype": "method",
15061          "name": "textSize",
15062          "chainable": 1,
15063          "example": ["\n<div>\n<code>\ntextSize(12);\ntext('Font Size 12', 10, 30);\ntextSize(14);\ntext('Font Size 14', 10, 60);\ntextSize(16);\ntext('Font Size 16', 10, 90);\n</code>\n</div>"],
15064          "alt": "Font Size 12 displayed small, Font Size 14 medium & Font Size 16 large",
15065          "class": "p5",
15066          "module": "Typography",
15067          "submodule": "Attributes",
15068          "overloads": [{
15069            "line": 122,
15070            "params": [{
15071              "name": "theSize",
15072              "description": "<p>the size of the letters in units of pixels</p>\n",
15073              "type": "Number"
15074            }],
15075            "chainable": 1
15076          }, {
15077            "line": 145,
15078            "params": [],
15079            "return": {
15080              "description": "",
15081              "type": "Number"
15082            }
15083          }]
15084        }, {
15085          "file": "src/typography/attributes.js",
15086          "line": 154,
15087          "description": "<p>Sets/gets the style of the text for system fonts to NORMAL, ITALIC, BOLD or BOLDITALIC.\nNote: this may be is overridden by CSS styling. For non-system fonts\n(opentype, truetype, etc.) please load styled fonts instead.</p>\n",
15088          "itemtype": "method",
15089          "name": "textStyle",
15090          "chainable": 1,
15091          "example": ["\n<div>\n<code>\nstrokeWeight(0);\ntextSize(12);\ntextStyle(NORMAL);\ntext('Font Style Normal', 10, 15);\ntextStyle(ITALIC);\ntext('Font Style Italic', 10, 40);\ntextStyle(BOLD);\ntext('Font Style Bold', 10, 65);\ntextStyle(BOLDITALIC);\ntext('Font Style Bold Italic', 10, 90);\n</code>\n</div>"],
15092          "alt": "words Font Style Normal displayed normally, Italic in italic, bold in bold and bold italic in bold italics.",
15093          "class": "p5",
15094          "module": "Typography",
15095          "submodule": "Attributes",
15096          "overloads": [{
15097            "line": 154,
15098            "params": [{
15099              "name": "theStyle",
15100              "description": "<p>styling for text, either NORMAL,\n                           ITALIC, BOLD or BOLDITALIC</p>\n",
15101              "type": "Constant"
15102            }],
15103            "chainable": 1
15104          }, {
15105            "line": 182,
15106            "params": [],
15107            "return": {
15108              "description": "",
15109              "type": "String"
15110            }
15111          }]
15112        }, {
15113          "file": "src/typography/attributes.js",
15114          "line": 191,
15115          "description": "<p>
15115Calculates and returns the width of any character or text string.</p>\n",
15116          "itemtype": "method",
15117          "name": "textWidth",
15118          "params": [{
15119            "name": "theText",
15120            "description": "<p>the String of characters to measure</p>\n",
15121            "type": "String"
15122          }],
15123          "return": {
15124            "description": "",
15125            "type": "Number"
15126          },
15127          "example": ["\n<div>\n<code>\ntextSize(28);\n\nlet aChar = 'P';\nlet cWidth = textWidth(aChar);\ntext(aChar, 0, 40);\nline(cWidth, 0, cWidth, 50);\n\nlet aString = 'p5.js';\nlet sWidth = textWidth(aString);\ntext(aString, 0, 85);\nline(sWidth, 50, sWidth, 100);\n</code>\n</div>"],
15128          "alt": "Letter P and p5.js are displayed with vertical lines at end. P is wide",
15129          "class": "p5",
15130          "module": "Typography",
15131          "submodule": "Attributes"
15132        }, {
15133          "file": "src/typography/attributes.js",
15134          "line": 226,
15135          "description": "<p>Returns the ascent of the current font at its current size. The ascent\nrepresents the distance, in pixels, of the tallest character above\nthe baseline.</p>\n",
15136          "itemtype": "method",
15137          "name": "textAscent",
15138          "return": {
15139            "description": "",
15140            "type": "Number"
15141          },
15142          "example": ["\n<div>\n<code>\nlet base = height * 0.75;\nlet scalar = 0.8; // Different for each font\n\ntextSize(32); // Set initial text size\nlet asc = textAscent() * scalar; // Calc ascent\nline(0, base - asc, width, base - asc);\ntext('dp', 0, base); // Draw text on baseline\n\ntextSize(64); // Increase text size\nasc = textAscent() * scalar; // Recalc ascent\nline(40, base - asc, width, base - asc);\ntext('dp', 40, base); // Draw text on baseline\n</code>\n</div>"],
15143          "class": "p5",
15144          "module": "Typography",
15145          "submodule": "Attributes"
15146        }, {
15147          "file": "src/typography/attributes.js",
15148          "line": 255,
15149          "description": "<p>Returns the descent of the current font at its current size. The descent\nrepresents the distance, in pixels, of the character with the longest\ndescender below the baseline.</p>\n",
15150          "itemtype": "method",
15151          "name": "textDescent",
15152          "return": {
15153            "description": "",
15154            "type": "Number"
15155          },
15156          "example": ["\n<div>\n<code>\nlet base = height * 0.75;\nlet scalar = 0.8; // Different for each font\n\ntextSize(32); // Set initial text size\nlet desc = textDescent() * scalar; // Calc ascent\nline(0, base + desc, width, base + desc);\ntext('dp', 0, base); // Draw text on baseline\n\ntextSize(64); // Increase text size\ndesc = textDescent() * scalar; // Recalc ascent\nline(40, base + desc, width, base + desc);\ntext('dp', 40, base); // Draw text on baseline\n</code>\n</div>"],
15157          "class": "p5",
15158          "module": "Typography",
15159          "submodule": "Attributes"
15160        }, {
15161          "file": "src/typography/attributes.js",
15162          "line": 284,
15163          "description": "<p>Helper function to measure ascent and descent.</p>\n",
15164          "class": "p5",
15165          "module": "Typography",
15166          "submodule": "Attributes"
15167        }, {
15168          "file": "src/typography/loading_displaying.js",
15169          "line": 16,
15170          "description": "<p>Loads an opentype font file (.otf, .ttf) from a file or a URL,\nand returns a PFont Object. This method is asynchronous,\nmeaning it may not finish before the next line in your sketch\nis executed.\n<br><br>\nThe path to the font should be relative to the HTML file\nthat links in your sketch. Loading fonts from a URL or other\nremote location may be blocked due to your browser&#39;s built-in\nsecurity.</p>\n",
15171          "itemtype": "method",
15172          "name": "loadFont",
15173          "params": [{
15174            "name": "path",
15175            "description": "<p>name of the file or url to load</p>\n",
15176            "type": "String"
15177          }, {
15178            "name": "callback",
15179            "description": "<p>function to be executed after\n                                   <a href=\"#/p5/loadFont\">loadFont()</a> completes</p>\n",
15180            "type": "Function",
15181            "optional": true
15182          }, {
15183            "name": "onError",
15184            "description": "<p>function to be executed if\n                                   an error occurs</p>\n",
15185            "type": "Function",
15186            "optional": true
15187          }],
15188          "return": {
15189            "description": "<a href=\"#/p5.Font\">p5.Font</a> object",
15190            "type": "p5.Font"
15191          },
15192          "example": ["\n\n<p>Calling loadFont() inside <a href=\"#/p5/preload\">preload()</a> guarantees that the load\noperation will have completed before <a href=\"#/p5/setup\">setup()</a> and <a href=\"#/p5/draw\">draw()</a> are called.</p>\n\n<div><code>\nlet myFont;\nfunction preload() {\n  myFont = loadFont('assets/AvenirNextLTPro-Demi.otf');\n}\n\nfunction setup() {\n  fill('#ED225D');\n  textFont(myFont);\n  textSize(36);\n  text('p5*js', 10, 50);\n}\n</code></div>\n\nOutside of <a href=\"#/p5/preload\">preload()</a>, you may supply a callback function to handle the\nobject:\n\n<div><code>\nfunction setup() {\n  loadFont('assets/AvenirNextLTPro-Demi.otf', drawText);\n}\n\nfunction drawText(font) {\n  fill('#ED225D');\n  textFont(font, 36);\n  text('p5*js', 10, 50);\n}\n</code></div>\n\n<p>You can also use the font filename string (without the file extension) to style other HTML\nelements.</p>\n\n<div><code>\nfunction preload() {\n  loadFont('assets/Avenir.otf');\n}\n\nfunction setup() {\n  let myDiv = createDiv('hello there');\n  myDiv.style('font-family', 'Avenir');\n}\n</code></div>"],
15193          "alt": "p5*js in p5's theme dark pink\np5*js in p5's theme dark pink",
15194          "class": "p5",
15195          "module": "Typography",
15196          "submodule": "Loading & Displaying"
15197        }, {
15198          "file": "src/typography/loading_displaying.js",
15199          "line": 143,
15200          "description": "<p>Draws text to the screen. Displays the information specified in the first\nparameter on the screen in the position specified by the additional\nparameters. A default font will be used unless a font is set with the\n<a href=\"#/p5/textFont\">textFont()</a> function and a default size will be used unless a font is set\nwith <a href=\"#/p5/textSize\">textSize()</a>. Change the color of the text with the <a href=\"#/p5/fill\">fill()</a> function.\nChange the outline of the text with the <a href=\"#/p5/stroke\">stroke()</a> and <a href=\"#/p5/strokeWeight\">
15200strokeWeight()</a>\nfunctions.\n<br><br>\nThe text displays in relation to the <a href=\"#/p5/textAlign\">textAlign()</a> function, which gives the\noption to draw to the left, right, and center of the coordinates.\n<br><br>\nThe x2 and y2 parameters define a rectangular area to display within and\nmay only be used with string data. When these parameters are specified,\nthey are interpreted based on the current <a href=\"#/p5/rectMode\">rectMode()</a> setting. Text that\ndoes not fit completely within the rectangle specified will not be drawn\nto the screen. If x2 and y2 are not specified, the baseline alignment is the\ndefault, which means that the text will be drawn upwards from x and y.\n<br><br>\n<b>WEBGL</b>: Only opentype/truetype fonts are supported. You must load a font using the\n<a href=\"#/p5/loadFont\">loadFont()</a> method (see the example above).\n<a href=\"#/p5/stroke\">stroke()</a> currently has no effect in webgl mode.</p>\n",
15201          "itemtype": "method",
15202          "name": "text",
15203          "params": [{
15204            "name": "str",
15205            "description": "<p>the alphanumeric\n                                            symbols to be displayed</p>\n",
15206            "type": "String|Object|Array|Number|Boolean"
15207          }, {
15208            "name": "x",
15209            "description": "<p>x-coordinate of text</p>\n",
15210            "type": "Number"
15211          }, {
15212            "name": "y",
15213            "description": "<p>y-coordinate of text</p>\n",
15214            "type": "Number"
15215          }, {
15216            "name": "x2",
15217            "description": "<p>by default, the width of the text box,\n                    see <a href=\"#/p5/rectMode\">rectMode()</a> for more info</p>\n",
15218            "type": "Number",
15219            "optional": true
15220          }, {
15221            "name": "y2",
15222            "description": "<p>by default, the height of the text box,\n                    see <a href=\"#/p5/rectMode\">rectMode()</a> for more info</p>\n",
15223            "type": "Number",
15224            "optional": true
15225          }],
15226          "chainable": 1,
15227          "example": ["\n<div>\n<code>\ntextSize(32);\ntext('word', 10, 30);\nfill(0, 102, 153);\ntext('word', 10, 60);\nfill(0, 102, 153, 51);\ntext('word', 10, 90);\n</code>\n</div>\n<div>\n<code>\nlet s = 'The quick brown fox jumped over the lazy dog.';\nfill(50);\ntext(s, 10, 10, 70, 80); // Text wraps within text box\n</code>\n</div>\n\n<div modernizr='webgl'>\n<code>\nlet avenir;\nfunction preload() {\n  avenir = loadFont('assets/Avenir.otf');\n}\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  textFont(avenir);\n  textSize(width / 3);\n  textAlign(CENTER, CENTER);\n}\nfunction draw() {\n  background(0);\n  let time = millis();\n  rotateX(time / 1000);\n  rotateZ(time / 1234);\n  text('p5.js', 0, 0);\n}\n</code>\n</div>"],
15228          "alt": "'word' displayed 3 times going from black, blue to translucent blue\nThe quick brown fox jumped over the lazy dog.\nthe text 'p5.js' spinning in 3d",
15229          "class": "p5",
15230          "module": "Typography",
15231          "submodule": "Loading & Displaying"
15232        }, {
15233          "file": "src/typography/loading_displaying.js",
15234          "line": 230,
15235          "description": "<p>Sets the current font that will be drawn with the <a href=\"#/p5/text\">text()</a> function.\n<br><br>\n<b>WEBGL</b>: Only fonts loaded via <a href=\"#/p5/loadFont\">loadFont()</a> are supported.</p>\n",
15236          "itemtype": "method",
15237          "name": "textFont",
15238          "return": {
15239            "description": "the current font",
15240            "type": "Object"
15241          },
15242          "example": ["\n<div>\n<code>\nfill(0);\ntextSize(12);\ntextFont('Georgia');\ntext('Georgia', 12, 30);\ntextFont('Helvetica');\ntext('Helvetica', 12, 60);\n</code>\n</div>\n<div>\n<code>\nlet fontRegular, fontItalic, fontBold;\nfunction preload() {\n  fontRegular = loadFont('assets/Regular.otf');\n  fontItalic = loadFont('assets/Italic.ttf');\n  fontBold = loadFont('assets/Bold.ttf');\n}\nfunction setup() {\n  background(210);\n  fill(0)\n   .strokeWeight(0)\n   .textSize(10);\n  textFont(fontRegular);\n  text('Font Style Normal', 10, 30);\n  textFont(fontItalic);\n  text('Font Style Italic', 10, 50);\n  textFont(fontBold);\n  text('Font Style Bold', 10, 70);\n}\n</code>\n</div>"],
15243          "alt": "words Font Style Normal displayed normally, Italic in italic and bold in bold",
15244          "class": "p5",
15245          "module": "Typography",
15246          "submodule": "Loading & Displaying",
15247          "overloads": [{
15248            "line": 230,
15249            "params": [],
15250            "return": {
15251              "description": "the current font",
15252              "type": "Object"
15253            }
15254          }, {
15255            "line": 275,
15256            "params": [{
15257              "name": "font",
15258              "description": "<p>a font loaded via <a href=\"#/p5/loadFont\">loadFont()</a>, or a String\nrepresenting a <a href=\"https://mzl.la/2dOw8WD\">web safe font</a> (a font\nthat is generally available across all systems)</p>\n",
15259              "type": "Object|String"
15260            }, {
15261              "name": "size",
15262              "description": "<p>the font size to use</p>\n",
15263              "type": "Number",
15264              "optional": true
15265            }],
15266            "chainable": 1
15267          }]
15268        }, {
15269          "file": "src/typography/p5.Font.js",
15270          "line": 25,
15271          "description": "<p>Underlying opentype font implementation</p>\n",
15272          "itemtype": "property",
15273          "name": "font",
15274          "class": "p5.Font",
15275          "module": "Typography",
15276          "submodule": "Font"
15277        }, {
15278          "file": "src/typography/p5.Font.js",
15279          "line": 32,
15280          "description": "<p>
15280Returns a tight bounding box for the given text string using this\nfont (currently only supports single lines)</p>\n",
15281          "itemtype": "method",
15282          "name": "textBounds",
15283          "params": [{
15284            "name": "line",
15285            "description": "<p>a line of text</p>\n",
15286            "type": "String"
15287          }, {
15288            "name": "x",
15289            "description": "<p>x-position</p>\n",
15290            "type": "Number"
15291          }, {
15292            "name": "y",
15293            "description": "<p>y-position</p>\n",
15294            "type": "Number"
15295          }, {
15296            "name": "fontSize",
15297            "description": "<p>font size to use (optional) Default is 12.</p>\n",
15298            "type": "Number",
15299            "optional": true
15300          }, {
15301            "name": "options",
15302            "description": "<p>opentype options (optional)\n                           opentype fonts contains alignment and baseline options.\n                           Default is &#39;LEFT&#39; and &#39;alphabetic&#39;</p>\n",
15303            "type": "Object",
15304            "optional": true
15305          }],
15306          "return": {
15307            "description": "a rectangle object with properties: x, y, w, h",
15308            "type": "Object"
15309          },
15310          "example": ["\n<div>\n<code>\nlet font;\nlet textString = 'Lorem ipsum dolor sit amet.';\nfunction preload() {\n  font = loadFont('./assets/Regular.otf');\n}\nfunction setup() {\n  background(210);\n\n  let bbox = font.textBounds(textString, 10, 30, 12);\n  fill(255);\n  stroke(0);\n  rect(bbox.x, bbox.y, bbox.w, bbox.h);\n  fill(0);\n  noStroke();\n\n  textFont(font);\n  textSize(12);\n  text(textString, 10, 30);\n}\n</code>\n</div>"],
15311          "alt": "words Lorem ipsum dol go off canvas and contained by white bounding box",
15312          "class": "p5.Font",
15313          "module": "Typography",
15314          "submodule": "Font"
15315        }, {
15316          "file": "src/typography/p5.Font.js",
15317          "line": 156,
15318          "description": "<p>Computes an array of points following the path for specified text</p>\n",
15319          "itemtype": "method",
15320          "name": "textToPoints",
15321          "params": [{
15322            "name": "txt",
15323            "description": "<p>a line of text</p>\n",
15324            "type": "String"
15325          }, {
15326            "name": "x",
15327            "description": "<p>x-position</p>\n",
15328            "type": "Number"
15329          }, {
15330            "name": "y",
15331            "description": "<p>y-position</p>\n",
15332            "type": "Number"
15333          }, {
15334            "name": "fontSize",
15335            "description": "<p>font size to use (optional)</p>\n",
15336            "type": "Number"
15337          }, {
15338            "name": "options",
15339            "description": "<p>an (optional) object that can contain:</p>\n<p><br>sampleFactor - the ratio of path-length to number of samples\n(default=.25); higher values yield more points and are therefore\nmore precise</p>\n<p><br>simplifyThreshold - if set to a non-zero value, collinear points will be\nbe removed from the polygon; the value represents the threshold angle to use\nwhen determining whether two edges are collinear</p>\n",
15340            "type": "Object",
15341            "optional": true
15342          }],
15343          "return": {
15344            "description": "an array of points, each with x, y, alpha (the path angle)",
15345            "type": "Array"
15346          },
15347          "example": ["\n<div>\n<code>\nlet font;\nfunction preload() {\n  font = loadFont('./assets/Avenir.otf');\n}\n\nlet points;\nlet bounds;\nfunction setup() {\n  createCanvas(100, 100);\n  stroke(0);\n  fill(255, 104, 204);\n\n  points = font.textToPoints('p5', 0, 0, 10, {\n    sampleFactor: 5,\n    simplifyThreshold: 0\n  });\n  bounds = font.textBounds(' p5 ', 0, 0, 10);\n}\n\nfunction draw() {\n  background(255);\n  beginShape();\n  translate(-bounds.x * width / bounds.w, -bounds.y * height / bounds.h);\n  for (let i = 0; i < points.length; i++) {\n    let p = points[i];\n    vertex(\n      p.x * width / bounds.w +\n        sin(20 * p.y / bounds.h + millis() / 1000) * width / 30,\n      p.y * height / bounds.h\n    );\n  }\n  endShape(CLOSE);\n}\n</code>\n</div>\n"],
15348          "class": "p5.Font",
15349          "module": "Typography",
15350          "submodule": "Font"
15351        }, {
15352          "file": "src/utilities/array_functions.js",
15353          "line": 12,
15354          "description": "<p>Adds a value to the end of an array. Extends the length of\nthe array by one. Maps to Array.push().</p>\n",
15355          "itemtype": "method",
15356          "name": "append",
15357          "deprecated": true,
15358          "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push\">array.push(value)</a> instead.",
15359          "params": [{
15360            "name": "array",
15361            "description": "<p>Array to append</p>\n",
15362            "type": "Array"
15363          }, {
15364            "name": "value",
15365            "description": "<p>to be added to the Array</p>\n",
15366            "type": "Any"
15367          }],
15368          "return": {
15369            "description": "the array that was appended to",
15370            "type": "Array"
15371          },
15372          "example": ["\n<div class='norender'><code>\nfunction setup() {\n  var myArray = ['Mango', 'Apple', 'Papaya'];\n  print(myArray); // ['Mango', 'Apple', 'Papaya']\n\n  append(myArray, 'Peach');\n  print(myArray); // ['Mango', 'Apple', 'Papaya', 'Peach']\n}\n</code></div>"],
15373          "class": "p5",
15374          "module": "Data",
15375          "submodule": "Array Functions"
15376        }, {
15377          "file": "src/utilities/array_functions.js",
15378          "line": 37,
15379          "description": "<p>Copies an array (or part of an array) to another array. The src array is\ncopied to the dst array, beginning at the position specified by\nsrcPosition and into the position specified by dstPosition. The number of\nelements to copy is determined by length. Note that copying values\noverwrites existing values in the destination array. To append values\ninstead of overwriting them, use <a href=\"#/p5/concat\">concat()</a>.\n<br><br>\nThe simplified version with only two arguments, arrayCopy(src, dst),\ncopies an entire array to another of the same size. It is equivalent to\narrayCopy(src, 0, dst, 0, src.length).\n<br><br>\nUsing this function is far more efficient for copying array data than\niterating through a for() loop and copying each element individually.</p>\n",
15380          "itemtype": "method",
15381          "name": "arrayCopy",
15382          "deprecated": true,
15383          "example": ["\n<div class='norender'><code>\nvar src = ['A', 'B', 'C'];\nvar dst = [1, 2, 3];\nvar srcPosition = 1;\nvar dstPosition = 0;\nvar length = 2;\n\nprint(src); // ['A', 'B', 'C']\nprint(dst); // [ 1 ,  2 ,  3 ]\n\narrayCopy(src, srcPosition, dst, dstPosition, length);\nprint(dst); // ['B', 'C', 3]\n</code></div>"],
15384          "class": "p5",
15385          "module": "Data",
15386          "submodule": "Array Functions",
15387          "overloads": [{
15388            "line": 37,
15389            "params": [{
15390              "name": "src",
15391              "description": "<p>the source Array</p>\n",
15392              "type": "Array"
15393            }, {
15394              "name": "srcPosition",
15395              "description": "<p>starting position in the source Array</p>\n",
15396              "type": "Integer"
15397            }, {
15398              "name": "dst",
15399              "description": "<p>the destination Array</p>\n",
15400              "type": "Array"
15401            }, {
15402              "name": "dstPosition",
15403              "description": "<p>starting position in the destination Array</p>\n",
15404              "type": "Integer"
15405            }, {
15406              "name": "length",
15407              "description": "<p>number of Array elements to be copied</p>\n",
15408              "type": "Integer"
15409            }]
15410          }, {
15411            "line": 75,
15412            "params": [{
15413              "name": "src",
15414              "description": "",
15415              "type": "Array"
15416            }, {
15417              "name": "dst",
15418              "description": "",
15419              "type": "Array"
15420            }, {
15421              "name": "length",
15422              "description": "",
15423              "type": "Integer",
15424              "optional": true
15425            }]
15426          }]
15427        }, {
15428          "file": "src/utilities/array_functions.js",
15429          "line": 114,
15430          "description": "<p>Concatenates two arrays, maps to Array.concat(). Does not modify the\ninput arrays.</p>\n",
15431          "itemtype": "method",
15432          "name": "concat",
15433          "deprecated": true,
15434          "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat\">arr1.concat(arr2)</a> instead.",
15435          "params": [{
15436            "name": "a",
15437            "description": "<p>first Array to concatenate</p>\n",
15438            "type": "Array"
15439          }, {
15440            "name": "b",
15441            "description": "<p>second Array to concatenate</p>\n",
15442            "type": "Array"
15443          }],
15444          "return": {
15445            "description": "concatenated array",
15446            "type": "Array"
15447          },
15448          "example": ["\n<div class = 'norender'><code>\nfunction setup() {\n  var arr1 = ['A', 'B', 'C'];\n  var arr2 = [1, 2, 3];\n\n  print(arr1); // ['A','B','C']\n  print(arr2); // [1,2,3]\n\n  var arr3 = concat(arr1, arr2);\n\n  print(arr1); // ['A','B','C']\n  print(arr2); // [1, 2, 3]\n  print(arr3); // ['A','B','C', 1, 2, 3]\n}\n</code></div>"],
15449          "class": "p5",
15450          "module": "Data",
15451          "submodule": "Array Functions"
15452        }, {
15453          "file": "src/utilities/array_functions.js",
15454          "line": 145,
15455          "description": "<p>Reverses the order of an array, maps to Array.reverse()</p>\n",
15456          "itemtype": "method",
15457          "name": "reverse",
15458          "deprecated": true,
15459          "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse\">array.reverse()</a> instead.",
15460          "params": [{
15461            "name": "list",
15462            "description": "<p>Array to reverse</p>\n",
15463            "type": "Array"
15464          }],
15465          "return": {
15466            "description": "the reversed list",
15467            "type": "Array"
15468          },
15469          "example": ["\n<div class='norender'><code>\nfunction setup() {\n  var myArray = ['A', 'B', 'C'];\n  print(myArray); // ['A','B','C']\n\n  reverse(myArray);\n  print(myArray); // ['C','B','A']\n}\n</code></div>"],
15470          "class": "p5",
15471          "module": "Data",
15472          "submodule": "Array Functions"
15473        }, {
15474          "file": "src/utilities/array_functions.js",
15475          "line": 167,
15476          "description": "<p>Decreases an array by one element and returns the shortened array,\nmaps to Array.pop().</p>\n",
15477          "itemtype": "method",
15478          "name": "shorten",
15479          "deprecated": true,
15480          "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop\">array.pop()</a> instead.",
15481          "params": [{
15482            "name": "list",
15483            "description": "<p>Array to shorten</p>\n",
15484            "type": "Array"
15485          }],
15486          "return": {
15487            "description": "shortened Array",
15488            "type": "Array"
15489          },
15490          "example": ["\n<div class = 'norender'><code>\nfunction setup() {\n  var myArray = ['A', 'B', 'C'];\n  print(myArray); // ['A', 'B', 'C']\n  var newArray = shorten(myArray);\n  print(myArray); // ['A','B','C']\n  print(newArray); // ['A','B']\n}\n</code></div>"],
15491          "class": "p5",
15492          "module": "Data",
15493          "submodule": "Array Functions"
15494        }, {
15495          "file": "src/utilities/array_functions.js",
15496          "line": 191,
15497          "description": "<p>Randomizes the order of the elements of an array. Implements\n<a href='http://Bost.Ocks.org/mike/shuffle/' target=_blank>
15497\nFisher-Yates Shuffle Algorithm</a>.</p>\n",
15498          "itemtype": "method",
15499          "name": "shuffle",
15500          "params": [{
15501            "name": "array",
15502            "description": "<p>Array to shuffle</p>\n",
15503            "type": "Array"
15504          }, {
15505            "name": "bool",
15506            "description": "<p>modify passed array</p>\n",
15507            "type": "Boolean",
15508            "optional": true
15509          }],
15510          "return": {
15511            "description": "shuffled Array",
15512            "type": "Array"
15513          },
15514          "example": ["\n<div><code>\nfunction setup() {\n  var regularArr = ['ABC', 'def', createVector(), TAU, Math.E];\n  print(regularArr);\n  shuffle(regularArr, true); // force modifications to passed array\n  print(regularArr);\n\n  // By default shuffle() returns a shuffled cloned array:\n  var newArr = shuffle(regularArr);\n  print(regularArr);\n  print(newArr);\n}\n</code></div>"],
15515          "class": "p5",
15516          "module": "Data",
15517          "submodule": "Array Functions"
15518        }, {
15519          "file": "src/utilities/array_functions.js",
15520          "line": 233,
15521          "description": "<p>Sorts an array of numbers from smallest to largest, or puts an array of\nwords in alphabetical order. The original array is not modified; a\nre-ordered array is returned. The count parameter states the number of\nelements to sort. For example, if there are 12 elements in an array and\ncount is set to 5, only the first 5 elements in the array will be sorted.</p>\n",
15522          "itemtype": "method",
15523          "name": "sort",
15524          "deprecated": true,
15525          "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort\">array.sort()</a> instead.",
15526          "params": [{
15527            "name": "list",
15528            "description": "<p>Array to sort</p>\n",
15529            "type": "Array"
15530          }, {
15531            "name": "count",
15532            "description": "<p>number of elements to sort, starting from 0</p>\n",
15533            "type": "Integer",
15534            "optional": true
15535          }],
15536          "return": {
15537            "description": "the sorted list",
15538            "type": "Array"
15539          },
15540          "example": ["\n<div class = 'norender'><code>\nfunction setup() {\n  var words = ['banana', 'apple', 'pear', 'lime'];\n  print(words); // ['banana', 'apple', 'pear', 'lime']\n  var count = 4; // length of array\n\n  words = sort(words, count);\n  print(words); // ['apple', 'banana', 'lime', 'pear']\n}\n</code></div>\n<div class = 'norender'><code>\nfunction setup() {\n  var numbers = [2, 6, 1, 5, 14, 9, 8, 12];\n  print(numbers); // [2, 6, 1, 5, 14, 9, 8, 12]\n  var count = 5; // Less than the length of the array\n\n  numbers = sort(numbers, count);\n  print(numbers); // [1,2,5,6,14,9,8,12]\n}\n</code></div>"],
15541          "class": "p5",
15542          "module": "Data",
15543          "submodule": "Array Functions"
15544        }, {
15545          "file": "src/utilities/array_functions.js",
15546          "line": 281,
15547          "description": "<p>Inserts a value or an array of values into an existing array. The first\nparameter specifies the initial array to be modified, and the second\nparameter defines the data to be inserted. The third parameter is an index\nvalue which specifies the array position from which to insert data.\n(Remember that array index numbering starts at zero, so the first position\nis 0, the second position is 1, and so on.)</p>\n",
15548          "itemtype": "method",
15549          "name": "splice",
15550          "deprecated": true,
15551          "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice\">array.splice()</a> instead.",
15552          "params": [{
15553            "name": "list",
15554            "description": "<p>Array to splice into</p>\n",
15555            "type": "Array"
15556          }, {
15557            "name": "value",
15558            "description": "<p>value to be spliced in</p>\n",
15559            "type": "Any"
15560          }, {
15561            "name": "position",
15562            "description": "<p>in the array from which to insert data</p>\n",
15563            "type": "Integer"
15564          }],
15565          "return": {
15566            "description": "the list",
15567            "type": "Array"
15568          },
15569          "example": ["\n<div class = 'norender'><code>\nfunction setup() {\n  var myArray = [0, 1, 2, 3, 4];\n  var insArray = ['A', 'B', 'C'];\n  print(myArray); // [0, 1, 2, 3, 4]\n  print(insArray); // ['A','B','C']\n\n  splice(myArray, insArray, 3);\n  print(myArray); // [0,1,2,'A','B','C',3,4]\n}\n</code></div>"],
15570          "class": "p5",
15571          "module": "Data",
15572          "submodule": "Array Functions"
15573        }, {
15574          "file": "src/utilities/array_functions.js",
15575          "line": 316,
15576          "description": "<p>Extracts an array of elements from an existing array. The list parameter\ndefines the array from which the elements will be copied, and the start\nand count parameters specify which elements to extract. If no count is\ngiven, elements will be extracted from the start to the end of the array.\nWhen specifying the start, remember that the first array element is 0.\nThis function does not change the source array.</p>\n",
15577          "itemtype": "method",
15578          "name": "subset",
15579          "deprecated": true,
15580          "deprecationMessage": "Use <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice\">array.slice()</a> instead.",
15581          "params": [{
15582            "name": "list",
15583            "description": "<p>Array to extract from</p>\n",
15584            "type": "Array"
15585          }, {
15586            "name": "start",
15587            "description": "<p>position to begin</p>\n",
15588            "type": "Integer"
15589          }, {
15590            "name": "count",
15591            "description": "<p>number of values to extract</p>\n",
15592            "type": "Integer",
15593            "optional": true
15594          }],
15595          "return": {
15596            "description": "Array of extracted elements",
15597            "type": "Array"
15598          },
15599          "example": ["\n<div class = 'norender'><code>\nfunction setup() {\n  var myArray = [1, 2, 3, 4, 5];\n  print(myArray); // [1, 2, 3, 4, 5]\n\n  var sub1 = subset(myArray, 0, 3);\n  var sub2 = subset(myArray, 2, 2);\n  print(sub1); // [1,2,3]\n  print(sub2); // [3,4]\n}\n</code></div>"],
15600          "class": "p5",
15601          "module": "Data",
15602          "submodule": "Array Functions"
15603        }, {
15604          "file": "src/utilities/conversion.js",
15605          "line": 12,
15606          "description": "<p>Converts a string to its floating point representation. The contents of a\nstring must resemble a number, or NaN (not a number) will be returned.\nFor example, float(&quot;1234.56&quot;) evaluates to 1234.56, but float(&quot;giraffe&quot;)\nwill return NaN.</p>\n<p>When an array of values is passed in, then an array of floats of the same\nlength is returned.</p>\n",
15607          "itemtype": "method",
15608          "name": "float",
15609          "params": [{
15610            "name": "str",
15611            "description": "<p>float string to parse</p>\n",
15612            "type": "String"
15613          }],
15614          "return": {
15615            "description": "floating point representation of str
15615ing",
15616            "type": "Number"
15617          },
15618          "example": ["\n<div><code>\nvar str = '20';\nvar diameter = float(str);\nellipse(width / 2, height / 2, diameter, diameter);\n</code></div>"],
15619          "alt": "20 by 20 white ellipse in the center of the canvas",
15620          "class": "p5",
15621          "module": "Data",
15622          "submodule": "Conversion"
15623        }, {
15624          "file": "src/utilities/conversion.js",
15625          "line": 42,
15626          "description": "<p>Converts a boolean, string, or float to its integer representation.\nWhen an array of values is passed in, then an int array of the same length\nis returned.</p>\n",
15627          "itemtype": "method",
15628          "name": "int",
15629          "return": {
15630            "description": "integer representation of value",
15631            "type": "Number"
15632          },
15633          "example": ["\n<div class='norender'><code>\nprint(int('10')); // 10\nprint(int(10.31)); // 10\nprint(int(-10)); // -10\nprint(int(true)); // 1\nprint(int(false)); // 0\nprint(int([false, true, '10.3', 9.8])); // [0, 1, 10, 9]\n</code></div>"],
15634          "class": "p5",
15635          "module": "Data",
15636          "submodule": "Conversion",
15637          "overloads": [{
15638            "line": 42,
15639            "params": [{
15640              "name": "n",
15641              "description": "<p>value to parse</p>\n",
15642              "type": "String|Boolean|Number"
15643            }, {
15644              "name": "radix",
15645              "description": "<p>the radix to convert to (default: 10)</p>\n",
15646              "type": "Integer",
15647              "optional": true
15648            }],
15649            "return": {
15650              "description": "integer representation of value",
15651              "type": "Number"
15652            }
15653          }, {
15654            "line": 62,
15655            "params": [{
15656              "name": "ns",
15657              "description": "<p>values to parse</p>\n",
15658              "type": "Array"
15659            }],
15660            "return": {
15661              "description": "integer representation of values",
15662              "type": "Number[]"
15663            }
15664          }]
15665        }, {
15666          "file": "src/utilities/conversion.js",
15667          "line": 82,
15668          "description": "<p>Converts a boolean, string or number to its string representation.\nWhen an array of values is passed in, then an array of strings of the same\nlength is returned.</p>\n",
15669          "itemtype": "method",
15670          "name": "str",
15671          "params": [{
15672            "name": "n",
15673            "description": "<p>value to parse</p>\n",
15674            "type": "String|Boolean|Number|Array"
15675          }],
15676          "return": {
15677            "description": "string representation of value",
15678            "type": "String"
15679          },
15680          "example": ["\n<div class='norender'><code>\nprint(str('10')); // \"10\"\nprint(str(10.31)); // \"10.31\"\nprint(str(-10)); // \"-10\"\nprint(str(true)); // \"true\"\nprint(str(false)); // \"false\"\nprint(str([true, '10.3', 9.8])); // [ \"true\", \"10.3\", \"9.8\" ]\n</code></div>"],
15681          "class": "p5",
15682          "module": "Data",
15683          "submodule": "Conversion"
15684        }, {
15685          "file": "src/utilities/conversion.js",
15686          "line": 108,
15687          "description": "<p>Converts a number or string to its boolean representation.\nFor a number, any non-zero value (positive or negative) evaluates to true,\nwhile zero evaluates to false. For a string, the value &quot;true&quot; evaluates to\ntrue, while any other value evaluates to false. When an array of number or\nstring values is passed in, then a array of booleans of the same length is\nreturned.</p>\n",
15688          "itemtype": "method",
15689          "name": "boolean",
15690          "params": [{
15691            "name": "n",
15692            "description": "<p>value to parse</p>\n",
15693            "type": "String|Boolean|Number|Array"
15694          }],
15695          "return": {
15696            "description": "boolean representation of value",
15697            "type": "Boolean"
15698          },
15699          "example": ["\n<div class='norender'><code>\nprint(boolean(0)); // false\nprint(boolean(1)); // true\nprint(boolean('true')); // true\nprint(boolean('abcd')); // false\nprint(boolean([0, 12, 'true'])); // [false, true, false]\n</code></div>"],
15700          "class": "p5",
15701          "module": "Data",
15702          "submodule": "Conversion"
15703        }, {
15704          "file": "src/utilities/conversion.js",
15705          "line": 140,
15706          "description": "<p>Converts a number, string representation of a number, or boolean to its byte\nrepresentation. A b
15706yte can be only a whole number between -128 and 127, so\nwhen a value outside of this range is converted, it wraps around to the\ncorresponding byte representation. When an array of number, string or boolean\nvalues is passed in, then an array of bytes the same length is returned.</p>\n",
15707          "itemtype": "method",
15708          "name": "byte",
15709          "return": {
15710            "description": "byte representation of value",
15711            "type": "Number"
15712          },
15713          "example": ["\n<div class='norender'><code>\nprint(byte(127)); // 127\nprint(byte(128)); // -128\nprint(byte(23.4)); // 23\nprint(byte('23.4')); // 23\nprint(byte('hello')); // NaN\nprint(byte(true)); // 1\nprint(byte([0, 255, '100'])); // [0, -1, 100]\n</code></div>"],
15714          "class": "p5",
15715          "module": "Data",
15716          "submodule": "Conversion",
15717          "overloads": [{
15718            "line": 140,
15719            "params": [{
15720              "name": "n",
15721              "description": "<p>value to parse</p>\n",
15722              "type": "String|Boolean|Number"
15723            }],
15724            "return": {
15725              "description": "byte representation of value",
15726              "type": "Number"
15727            }
15728          }, {
15729            "line": 162,
15730            "params": [{
15731              "name": "ns",
15732              "description": "<p>values to parse</p>\n",
15733              "type": "Array"
15734            }],
15735            "return": {
15736              "description": "array of byte representation of values",
15737              "type": "Number[]"
15738            }
15739          }]
15740        }, {
15741          "file": "src/utilities/conversion.js",
15742          "line": 176,
15743          "description": "<p>Converts a number or string to its corresponding single-character\nstring representation. If a string parameter is provided, it is first\nparsed as an integer and then translated into a single-character string.\nWhen an array of number or string values is passed in, then an array of\nsingle-character strings of the same length is returned.</p>\n",
15744          "itemtype": "method",
15745          "name": "char",
15746          "return": {
15747            "description": "string representation of value",
15748            "type": "String"
15749          },
15750          "example": ["\n<div class='norender'><code>\nprint(char(65)); // \"A\"\nprint(char('65')); // \"A\"\nprint(char([65, 66, 67])); // [ \"A\", \"B\", \"C\" ]\nprint(join(char([65, 66, 67]), '')); // \"ABC\"\n</code></div>"],
15751          "class": "p5",
15752          "module": "Data",
15753          "submodule": "Conversion",
15754          "overloads": [{
15755            "line": 176,
15756            "params": [{
15757              "name": "n",
15758              "description": "<p>value to parse</p>\n",
15759              "type": "String|Number"
15760            }],
15761            "return": {
15762              "description": "string representation of value",
15763              "type": "String"
15764            }
15765          }, {
15766            "line": 195,
15767            "params": [{
15768              "name": "ns",
15769              "description": "<p>values to parse</p>\n",
15770              "type": "Array"
15771            }],
15772            "return": {
15773              "description": "array of string representation of values",
15774              "type": "String[]"
15775            }
15776          }]
15777        }, {
15778          "file": "src/utilities/conversion.js",
15779          "line": 210,
15780          "description": "<p>Converts a single-character string to its corresponding integer\nrepresentation. When an array of single-character string values is passed\nin, then an array of integers of the same length is returned.</p>\n",
15781          "itemtype": "method",
15782          "name": "unchar",
15783          "return": {
15784            "description": "integer representation of value",
15785            "type": "Number"
15786          },
15787          "example": ["\n<div class='norender'><code>\nprint(unchar('A')); // 65\nprint(unchar(['A', 'B', 'C'])); // [ 65, 66, 67 ]\nprint(unchar(split('ABC', ''))); // [ 65, 66, 67 ]\n</code></div>"],
15788          "class": "p5",
15789          "module": "Data",
15790          "submodule": "Conversion",
15791          "overloads": [{
15792            "line": 210,
15793            "params": [{
15794              "name": "n",
15795              "description": "<p>value to parse</p>\n",
15796              "type": "String"
15797            }],
15798            "return": {
15799              "description": "integer representation of value",
15800              "type": "Number"
15801            }
15802          }, {
15803            "line": 226,
15804            "params": [{
15805              "name": "ns",
15806              "description": "<p>values to parse</p>\n",
15807              "type": "Array"
15808            }],
15809            "return": {
15810              "description": "integer representation of values",
15811              "type": "Number[]"
15812            }
15813          }]
15814        }, {
15815          "file": "src/utilities/conversion.js",
15816          "line": 239,
15817          "description": "<p>Converts a number to a string in its equivalent hexadecimal notation. If a\nsecond parameter is passed, it is used to set the number of characters to\ngenerate in the hexadecimal notation. When an array is passed in, an\narray of str
15817ings in hexadecimal notation of the same length is returned.</p>\n",
15818          "itemtype": "method",
15819          "name": "hex",
15820          "return": {
15821            "description": "hexadecimal string representation of value",
15822            "type": "String"
15823          },
15824          "example": ["\n<div class='norender'><code>\nprint(hex(255)); // \"000000FF\"\nprint(hex(255, 6)); // \"0000FF\"\nprint(hex([0, 127, 255], 6)); // [ \"000000\", \"00007F\", \"0000FF\" ]\n</code></div>"],
15825          "class": "p5",
15826          "module": "Data",
15827          "submodule": "Conversion",
15828          "overloads": [{
15829            "line": 239,
15830            "params": [{
15831              "name": "n",
15832              "description": "<p>value to parse</p>\n",
15833              "type": "Number"
15834            }, {
15835              "name": "digits",
15836              "description": "",
15837              "type": "Number",
15838              "optional": true
15839            }],
15840            "return": {
15841              "description": "hexadecimal string representation of value",
15842              "type": "String"
15843            }
15844          }, {
15845            "line": 257,
15846            "params": [{
15847              "name": "ns",
15848              "description": "<p>array of values to parse</p>\n",
15849              "type": "Number[]"
15850            }, {
15851              "name": "digits",
15852              "description": "",
15853              "type": "Number",
15854              "optional": true
15855            }],
15856            "return": {
15857              "description": "hexadecimal string representation of values",
15858              "type": "String[]"
15859            }
15860          }]
15861        }, {
15862          "file": "src/utilities/conversion.js",
15863          "line": 286,
15864          "description": "<p>Converts a string representation of a hexadecimal number to its equivalent\ninteger value. When an array of strings in hexadecimal notation is passed\nin, an array of integers of the same length is returned.</p>\n",
15865          "itemtype": "method",
15866          "name": "unhex",
15867          "return": {
15868            "description": "integer representation of hexadecimal value",
15869            "type": "Number"
15870          },
15871          "example": ["\n<div class='norender'><code>\nprint(unhex('A')); // 10\nprint(unhex('FF')); // 255\nprint(unhex(['FF', 'AA', '00'])); // [ 255, 170, 0 ]\n</code></div>"],
15872          "class": "p5",
15873          "module": "Data",
15874          "submodule": "Conversion",
15875          "overloads": [{
15876            "line": 286,
15877            "params": [{
15878              "name": "n",
15879              "description": "<p>value to parse</p>\n",
15880              "type": "String"
15881            }],
15882            "return": {
15883              "description": "integer representation of hexadecimal value",
15884              "type": "Number"
15885            }
15886          }, {
15887            "line": 302,
15888            "params": [{
15889              "name": "ns",
15890              "description": "<p>values to parse</p>\n",
15891              "type": "Array"
15892            }],
15893            "return": {
15894              "description": "integer representations of hexadecimal value",
15895              "type": "Number[]"
15896            }
15897          }]
15898        }, {
15899          "file": "src/utilities/string_functions.js",
15900          "line": 15,
15901          "description": "<p>Combines an array of Strings into one String, each separated by the\ncharacter(s) used for the separator parameter. To join arrays of ints or\nfloats, it&#39;s necessary to first convert them to Strings using <a href=\"#/p5/nf\">nf()</a> or\nnfs().</p>\n",
15902          "itemtype": "method",
15903          "name": "join",
15904          "params": [{
15905            "name": "list",
15906            "description": "<p>array of Strings to be joined</p>\n",
15907            "type": "Array"
15908          }, {
15909            "name": "separator",
15910            "description": "<p>String to be placed between each item</p>\n",
15911            "type": "String"
15912          }],
15913          "return": {
15914            "description": "joined String",
15915            "type": "String"
15916          },
15917          "example": ["\n<div>\n<code>\nvar array = ['Hello', 'world!'];\nvar separator = ' ';\nvar message = join(array, separator);\ntext(message, 5, 50);\n</code>\n</div>"],
15918          "alt": "\"hello world!\" displayed middle left of canvas.",
15919          "class": "p5",
15920          "module": "Data",
15921          "submodule": "String Functions"
15922        }, {
15923          "file": "src/utilities/string_functions.js",
15924          "line": 44,
15925          "description": "<p>This function is used to apply a regular expression to a piece of text,\nand return matching groups (elements found inside parentheses) as a\nString array. If there are no matches, a null value will be returned.\nIf no groups are specified in the regular expression, but the sequence\nmatches, an array of length 1 (with the matched text as the first element\nof the array) will be returned.\n<br><br>\nTo use the function, first check to see if the result is null. If the\nresult is null, then the sequence did not match at all. If the sequence\ndid match, an array is returned.\n<br><br>\nIf there are groups (specified by sets of parentheses) in the regular\nexpression, then the contents of each will be returned in the array.\nElement [0] of a regular expression match returns the entire matching\nstring, and the match groups start at element [1] (the first group is [1],\nthe second [2], and so on).</p>\n",
15926          "itemtype": "method",
15927          "name": "match",
15928          "params": [{
15929            "name": "str",
15930            "description": "<p>the String to be searched</p>\n",
15931            "type": "String"
15932          }, {
15933            "name": "regexp",
15934            "description": "<p>the regexp to be used for matching</p>\n",
15935            "type": "String"
15936          }],
15937          "return": {
15938            "description": "Array of Strings found",
15939            "type": "String[]"
15940          },
15941          "example": ["\n<div>\n<code>\nvar string = 'Hello p5js*!';\nvar regexp = 'p5js\\\\*';\nvar m = match(string, regexp);\ntext(m, 5, 50);\n</code>\n</div>"],
15942          "alt": "\"p5js*\" displayed middle left of canvas.",
15943          "class": "p5",
15944          "module": "Data",
15945          "submodule": "String Functions"
15946        }, {
15947          "file": "src/utilities/string_functions.js",
15948          "line": 85,
15949          "description": "<p>This function is used to apply a regular expression to a piece of text,\nand return a list of matching groups (elements found inside parentheses)\nas a two-dimensional Str
15949ing array. If there are no matches, a null value\nwill be returned. If no groups are specified in the regular expression,\nbut the sequence matches, a two dimensional array is still returned, but\nthe second dimension is only of length one.\n<br><br>\nTo use the function, first check to see if the result is null. If the\nresult is null, then the sequence did not match at all. If the sequence\ndid match, a 2D array is returned.\n<br><br>\nIf there are groups (specified by sets of parentheses) in the regular\nexpression, then the contents of each will be returned in the array.\nAssuming a loop with counter variable i, element [i][0] of a regular\nexpression match returns the entire matching string, and the match groups\nstart at element [i][1] (the first group is [i][1], the second [i][2],\nand so on).</p>\n",
15950          "itemtype": "method",
15951          "name": "matchAll",
15952          "params": [{
15953            "name": "str",
15954            "description": "<p>the String to be searched</p>\n",
15955            "type": "String"
15956          }, {
15957            "name": "regexp",
15958            "description": "<p>the regexp to be used for matching</p>\n",
15959            "type": "String"
15960          }],
15961          "return": {
15962            "description": "2d Array of Strings found",
15963            "type": "String[]"
15964          },
15965          "example": ["\n<div class=\"norender\">\n<code>\nvar string = 'Hello p5js*! Hello world!';\nvar regexp = 'Hello';\nmatchAll(string, regexp);\n</code>\n</div>"],
15966          "class": "p5",
15967          "module": "Data",
15968          "submodule": "String Functions"
15969        }, {
15970          "file": "src/utilities/string_functions.js",
15971          "line": 132,
15972          "description": "<p>Utility function for formatting numbers into strings. There are two\nversions: one for formatting floats, and one for formatting ints.\nThe values for the digits, left, and right parameters should always\nbe positive integers.\n(NOTE): Be cautious when using left and right parameters as it prepends numbers of 0&#39;s if the parameter\nif greater than the current length of the number.\nFor example if number is 123.2 and left parameter passed is 4 which is greater than length of 123\n(integer part) i.e 3 than result will be 0123.2. Same case for right parameter i.e. if right is 3 than\nthe result will be 123.200.</p>\n",
15973          "itemtype": "method",
15974          "name": "nf",
15975          "return": {
15976            "description": "formatted String",
15977            "type": "String"
15978          },
15979          "example": ["\n<div>\n<code>\nvar myFont;\nfunction preload() {\n  myFont = loadFont('assets/fonts/inconsolata.ttf');\n}\nfunction setup() {\n  background(200);\n  var num1 = 321;\n  var num2 = -1321;\n\n  noStroke();\n  fill(0);\n  textFont(myFont);\n  textSize(22);\n\n  text(nf(num1, 4, 2), 10, 30);\n  text(nf(num2, 4, 2), 10, 80);\n  // Draw dividing line\n  stroke(120);\n  line(0, 50, width, 50);\n}\n</code>\n</div>"],
15980          "alt": "\"0321.00\" middle top, -1321.00\" middle bottom canvas",
15981          "class": "p5",
15982          "module": "Data",
15983          "submodule": "String Functions",
15984          "overloads": [{
15985            "line": 132,
15986            "params": [{
15987              "name": "num",
15988              "description": "<p>the Number to format</p>\n",
15989              "type": "Number|String"
15990            }, {
15991              "name": "left",
15992              "description": "<p>number of digits to the left of the\n                               decimal point</p>\n",
15993              "type": "Integer|String",
15994              "optional": true
15995            }, {
15996              "name": "right",
15997              "description": "<p>number of digits to the right of the\n                               decimal point</p>\n",
15998              "type": "Integer|String",
15999              "optional": true
16000            }],
16001            "return": {
16002              "description": "formatted String",
16003              "type": "String"
16004            }
16005          }, {
16006            "line": 180,
16007            "params": [{
16008              "name": "nums",
16009              "description": "<p>the Numbers to format</p>\n",
16010              "type": "Array"
16011            }, {
16012              "name": "left",
16013              "description": "",
16014              "type": "Integer|String",
16015              "optional": true
16016            }, {
16017              "name": "right",
16018              "description": "",
16019              "type": "Integer|String",
16020              "optional": true
16021            }],
16022            "return": {
16023              "description": "formatted Strings",
16024              "type": "String[]"
16025            }
16026          }]
16027        }, {
16028          "file": "src/utilities/string_functions.js",
16029          "line": 243,
16030          "description": "<p>Utility function for formatting numbers into strings and placing\nappropriate commas to mark units of 1000. There are two versions: one\nfor formatting ints, and one for formatting an array of ints. The value\nfor the right parameter should always be a positive integer.</p>\n",
16031          "itemtype": "method",
16032          "name": "nfc",
16033          "return": {
16034            "description": "formatted String",
16035            "type": "String"
16036          },
16037          "example": ["\n<div>\n<code>\nfunction setup() {\n  background(200);\n  var num = 11253106.115;\n  var numArr = [1, 1, 2];\n\n  noStroke();\n  fill(0);\n  textSize(12);\n\n  // Draw formatted numbers\n  text(nfc(num, 4), 10, 30);\n  text(nfc(numArr, 2), 10, 80);\n\n  // Draw dividing line\n  stroke(120);\n  line(0, 50, width, 50);\n}\n</code>\n</div>"],
16038          "alt": "\"11,253,106.115\" top middle and \"1.00,1.00,2.00\" displayed bottom mid",
16039          "class": "p5",
16040          "module": "Data",
16041          "submodule": "String Functions",
16042          "overloads": [{
16043            "line": 243,
16044            "params": [{
16045              "name": "num",
16046              "description": "<p>the Number to format</p>\n",
16047              "type": "Number|String"
16048            }, {
16049              "name": "right",
16050              "description": "<p>number of digits to the right of the\n                                 decimal point</p>\n",
16051              "type": "Integer|String",
16052              "optional": true
16053            }],
16054            "return": {
16055              "description": "formatted String",
16056              "type": "String"
16057            }
16058          }, {
16059            "line": 281,
16060            "params": [{
16061              "name": "nums",
16062              "description": "<p>the Numbers to format</p>\n",
16063              "type": "Array"
16064            }, {
16065              "name": "right",
16066              "description": "",
16067              "type": "Integer|String",
16068              "optional": true
16069            }],
16070            "return": {
16071              "description": "formatted Strings",
16072              "type": "String[]"
16073            }
16074          }]
16075        }, {
16076          "file": "src/utilities/string_functions.js",
16077          "line": 319,
16078          "description": "<p>Utility function for formatting numbers into strings. Similar to <a href=\"#/p5/nf\">nf()</a> but\nputs a &quot;+&quot; in front of positive numbers and a &quot;-&quot; in front of negative\nnumbers. There are two versions: one for formatting floats, and one for\nformatting ints. The values for left, and right parameters\nshould always be positive integers.</p>\n",
16079          "itemtype": "method",
16080          "name": "nfp",
16081          "return": {
16082            "description": "formatted String",
16083            "type": "String"
16084          },
16085          "example": ["\n<div>\n<code>\nfunction setup() {\n  background(200);\n  var num1 = 11253106.115;\n  var num2 = -11253106.115;\n\n  noStroke();\n  fill(0);\n  textSize(12);\n\n  // Draw formatted numbers\n  text(nfp(num1, 4, 2), 10, 30);\n  text(nfp(num2, 4, 2), 10, 80);\n\n  // Draw dividing line\n  stroke(120);\n  line(0, 50, width, 50);\n}\n</code>\n</div>"],
16086          "alt": "\"+11253106.11\" top middle and \"-11253106.11\" displayed bottom middle",
16087          "class": "p5",
16088          "module": "Data",
16089          "submodule": "String Functions",
16090          "overloads": [{
16091            "line": 319,
16092            "params": [{
16093              "name": "num",
16094              "description": "<p>the Number to format</p>\n",
16095              "type": "Number"
16096            }, {
16097              "name": "left",
16098              "description": "<p>number of digits to the left of the decimal\n                               point</p>\n",
16099              "type": "Integer",
16100              "optional": true
16101            }, {
16102              "name": "right",
16103              "description": "<p>number of digits to the right of the\n                               decimal point</p>\n",
16104              "type": "Integer",
16105              "optional": true
16106            }],
16107            "return": {
16108              "description": "formatted String",
16109              "type": "String"
16110            }
16111          }, {
16112            "line": 360,
16113            "params": [{
16114              "name": "nums",
16115              "description": "<p>the Numbers to format</p>\n",
16116              "type": "Number[]"
16117            }, {
16118              "name": "left",
16119              "description": "",
16120              "type": "Integer",
16121              "optional": true
16122            }, {
16123              "name": "right",
16124              "description": "",
16125              "type": "Integer",
16126              "optional": true
16127            }],
16128            "return": {
16129              "description": "formatted Strings",
16130              "type": "String[]"
16131            }
16132          }]
16133        }, {
16134          "file": "src/utilities/string_functions.js",
16135          "line": 381,
16136          "description": "<p>Utility function for formatting numbers into strings. Similar to <a href=\"#/p5/nf\">nf()</a> but\nputs an additional &quot;_&quot; (space) in front of positive numbers just in case to align it with negative\nnumbers which includes &quot;-&quot; (minus) sign.\nThe main usecase of nfs() can be seen when one wants to align the digits (place values) of a positive\nnumber with some negative number (See the example to get a clear picture).\nThere are two versions: one for formatting float, and one for formatting int.\nThe values for the digits, left, and right parameters should always be positive integers.\n(IMP): The result on the canvas basically the expected alignment can vary based on the typeface you are using.\n(NOTE): Be cautious when using left and right parameters as it prepends numbers of 0&#39;s if the parameter\nif greater than the current length of the number.\nFor example if number is 123.2 and left parameter passed is 4 which is greater than length of 123\n(integer part) i.e 3 than result will be 0123.2. Same case for right parameter i.e. if right is 3 than\nthe result will be 123.200.</p>\n",
16137          "itemtype": "method",
16138          "name": "nfs",
16139          "return": {
16140            "description": "formatted String",
16141            "type": "String"
16142          },
16143          "example": ["\n<div>\n<code>\nvar myFont;\nfunction preload() {\n  myFont = loadFont('assets/fonts/inconsolata.ttf');\n}\nfunction setup() {\n  background(200);\n  var num1 = 321;\n  var num2 = -1321;\n\n  noStroke();\n  fill(0);\n  textFont(myFont);\n  textSize(22);
16143\n\n  // nfs() aligns num1 (positive number) with num2 (negative number) by\n  // adding a blank space in front of the num1 (positive number)\n  // [left = 4] in num1 add one 0 in front, to align the digits with num2\n  // [right = 2] in num1 and num2 adds two 0's after both numbers\n  // To see the differences check the example of nf() too.\n  text(nfs(num1, 4, 2), 10, 30);\n  text(nfs(num2, 4, 2), 10, 80);\n  // Draw dividing line\n  stroke(120);\n  line(0, 50, width, 50);\n}\n</code>\n</div>"],
16144          "alt": "\"0321.00\" top middle and \"-1321.00\" displayed bottom middle",
16145          "class": "p5",
16146          "module": "Data",
16147          "submodule": "String Functions",
16148          "overloads": [{
16149            "line": 381,
16150            "params": [{
16151              "name": "num",
16152              "description": "<p>the Number to format</p>\n",
16153              "type": "Number"
16154            }, {
16155              "name": "left",
16156              "description": "<p>number of digits to the left of the decimal\n                               point</p>\n",
16157              "type": "Integer",
16158              "optional": true
16159            }, {
16160              "name": "right",
16161              "description": "<p>number of digits to the right of the\n                               decimal point</p>\n",
16162              "type": "Integer",
16163              "optional": true
16164            }],
16165            "return": {
16166              "description": "formatted String",
16167              "type": "String"
16168            }
16169          }, {
16170            "line": 438,
16171            "params": [{
16172              "name": "nums",
16173              "description": "<p>the Numbers to format</p>\n",
16174              "type": "Array"
16175            }, {
16176              "name": "left",
16177              "description": "",
16178              "type": "Integer",
16179              "optional": true
16180            }, {
16181              "name": "right",
16182              "description": "",
16183              "type": "Integer",
16184              "optional": true
16185            }],
16186            "return": {
16187              "description": "formatted Strings",
16188              "type": "String[]"
16189            }
16190          }]
16191        }, {
16192          "file": "src/utilities/string_functions.js",
16193          "line": 459,
16194          "description": "<p>The <a href=\"#/p5/split\">split()</a> function maps to String.split(), it breaks a String into\npieces using a character or string as the delimiter. The delim parameter\nspecifies the character or characters that mark the boundaries between\neach piece. A String[] array is returned that contains each of the pieces.</p>\n<p>The <a href=\"#/p5/splitTokens\">splitTokens()</a> function works in a similar fashion, except that it\nsplits using a range of characters instead of a specific character or\nsequence.</p>\n",
16195          "itemtype": "method",
16196          "name": "split",
16197          "params": [{
16198            "name": "value",
16199            "description": "<p>the String to be split</p>\n",
16200            "type": "String"
16201          }, {
16202            "name": "delim",
16203            "description": "<p>the String used to separate the data</p>\n",
16204            "type": "String"
16205          }],
16206          "return": {
16207            "description": "Array of Strings",
16208            "type": "String[]"
16209          },
16210          "example": ["\n<div>\n<code>\nvar names = 'Pat,Xio,Alex';\nvar splitString = split(names, ',');\ntext(splitString[0], 5, 30);\ntext(splitString[1], 5, 50);\ntext(splitString[2], 5, 70);\n</code>\n</div>"],
16211          "alt": "\"pat\" top left, \"Xio\" mid left and \"Alex\" displayed bottom left",
16212          "class": "p5",
16213          "module": "Data",
16214          "submodule": "String Functions"
16215        }, {
16216          "file": "src/utilities/string_functions.js",
16217          "line": 493,
16218          "description": "<p>The <a href=\"#/p5/splitTokens\">splitTokens()</a> function splits a String at one or many character\ndelimiters or &quot;tokens.&quot; The delim parameter specifies the character or\ncharacters to be used as a boundary.\n<br><br>\nIf no delim characters are specified, any whitespace character is used to\nsplit. Whitespace characters include tab (\\t), line feed (\\n), carriage\nreturn (\\r), form feed (\\f), and space.</p>\n",
16219          "itemtype": "method",
16220          "name": "splitTokens",
16221          "params": [{
16222            "name": "value",
16223            "description": "<p>the String to be split</p>\n",
16224            "type": "String"
16225          }, {
16226            "name": "delim",
16227            "description": "<p>list of individual Strings that will be used as\n                         separators</p>\n",
16228            "type": "String",
16229            "optional": true
16230          }],
16231          "return": {
16232            "description": "Array of Strings",
16233            "type": "String[]"
16234          },
16235          "example": ["\n<div class = \"norender\">\n<code>\nfunction setup() {\n  var myStr = 'Mango, Banana, Lime';\n  var myStrArr = splitTokens(myStr, ',');\n\n  print(myStrArr); // prints : [\"Mango\",\" Banana\",\" Lime\"]\n}\n</code>\n</div>"],
16236          "class": "p5",
16237          "module": "Data",
16238          "submodule": "String Functions"
16239        }, {
16240          "file": "src/utilities/string_functions.js",
16241          "line": 548,
16242          "description": "<p>Removes whitespace characters from the beginning and end of a String. In\naddition to standard whitespace characters such as space, carriage return,\nand tab, this function also removes the Unicode &quot;nbsp&quot; character.</p>\n",
16243          "itemtype": "method",
16244          "name": "trim",
16245          "return": {
16246            "description": "a trimmed String",
16247            "type": "String"
16248          },
16249          "example": ["\n<div>\n<code>\nvar string = trim('  No new lines\\n   ');\ntext(string + ' here', 2, 50);\n</code>\n</div>"],
16250          "alt": "\"No new lines here\" displayed center canvas",
16251          "class": "p5",
16252          "module": "Data",
16253          "submodule": "String Functions",
16254          "overloads": [{
16255            "line": 548,
16256            "params": [{
16257              "name": "str",
16258              "description": "<p>a String to be trimmed</p>\n",
16259              "type": "String"
16260            }],
16261            "return": {
16262              "description": "a trimmed String",
16263              "type": "String"
16264            }
16265          }, {
16266            "line": 568,
16267            "params": [{
16268              "name": "strs",
16269              "description": "<p>an Array of Strings to be trimmed</p>\n",
16270              "type": "Array"
16271            }],
16272            "return": {
16273              "description": "an Array of trimmed Strings",
16274              "type": "String[]"
16275            }
16276          }]
16277        }, {
16278          "file": "src/utilities/time_date.js",
16279          "line": 12,
16280          "description": "<p>p5.js communicates with the clock on your computer. The <a href=\"#/p5/day\">day()</a> function\nreturns the current day as a value from 1 - 31.</p>\n",
16281          "itemtype": "method",
16282          "name": "day",
16283          "return": {
16284            "description": "the current day",
16285            "type": "Integer"
16286          },
16287          "example": ["\n<div>\n<code>\nvar d = day();\ntext('Current day: \\n' + d, 5, 50);\n</code>\n</div>"],
16288          "alt": "Current day is displayed",
16289          "class": "p5",
16290          "module": "IO",
16291          "submodule": "Time & Date"
16292        }, {
16293          "file": "src/utilities/time_date.js",
16294          "line": 34,
16295          "description": "<p>p5.js communicates with the clock on your computer. The <a href=\"#/p5/hour\">hour()</a> function\nreturns the current hour as a value from 0 - 23.</p>\n",
16296          "itemtype": "method",
16297          "name": "hour",
16298          "return": {
16299            "description": "the current hour",
16300            "type": "Integer"
16301          },
16302          "example": ["\n<div>\n<code>\nvar h = hour();\ntext('Current hour:\\n' + h, 5, 50);\n</code>\n</div>"],
16303          "alt": "Current hour is displayed",
16304          "class": "p5",
16305          "module": "IO",
16306          "submodule": "Time & Date"
16307        }, {
16308          "file": "src/utilities/time_date.js",
16309          "line": 56,
16310          "description": "<p>p5.js communicates with the clock on your computer. The <a href=\"#/p5/minute\">minute()</a> function\nreturns the current minute as a value from 0 - 59.</p>\n",
16311          "itemtype": "method",
16312          "name": "minute",
16313          "return": {
16314            "description": "the current minute",
16315            "type": "Integer"
16316          },
16317          "example": ["\n<div>\n<code>\nvar m = minute();\ntext('Current minute: \\n' + m, 5, 50);\n</code>\n</div>"],
16318          "alt": "Current minute is displayed",
16319          "class": "p5",
16320          "module": "IO",
16321          "submodule": "Time & Date"
16322        }, {
16323          "file": "src/utilities/time_date.js",
16324          "line": 78,
16325          "description": "<p>Returns the number of milliseconds (thousandths of a second) since\nstarting the program. This information is often used for timing events and\nanimation sequences.</p>\n",
16326          "itemtype": "method",
16327          "name": "millis",
16328          "return": {
16329            "description": "the number of milliseconds since starting the program",
16330            "type": "Number"
16331          },
16332          "example": ["\n<div>\n<code>\nvar millisecond = millis();\ntext('Milliseconds \\nrunning: \\n' + millisecond, 5, 40);\n</code>\n</div>"],
16333          "alt": "number of milliseconds since program has started displayed",
16334          "class": "p5",
16335          "module": "IO",
16336          "submodule": "Time & Date"
16337        }, {
16338          "file": "src/utilities/time_date.js",
16339          "line": 101,
16340          "description": "<p>p5.js communicates with the clock on your computer. The <a href=\"#/p5/month\">month()</a> function\nreturns the current month as a value from 1 - 12.</p>\n",
16341          "itemtype": "method",
16342          "name": "month",
16343          "return": {
16344            "description": "the current month",
16345            "type": "Integer"
16346          },
16347          "example": ["\n<div>\n<code>\nvar m = month();\ntext('Current month: \\n' + m, 5, 50);\n</code>\n</div>"],
16348          "alt": "Current month is displayed",
16349          "class": "p5",
16350          "module": "IO",
16351          "submodule": "Time & Date"
16352        }, {
16353          "file": "src/utilities/time_date.js",
16354          "line": 123,
16355          "description": "<p>p5.js communicates with the clock on your computer. The <a href=\"#/p5/second\">second()</a> function\nreturns the current second as a value from 0 - 59.</p>\n",
16356          "itemtype": "method",
16357          "name": "second",
16358          "return": {
16359            "description": "the current second",
16360            "type": "Integer"
16361          },
16362          "example": ["\n<div>\n<code>\nvar s = second();\ntext('Current second: \\n' + s, 5, 50);\n</code>\n</div>"],
16363          "alt": "Current second is displayed",
16364          "class": "p5",
16365          "module": "IO",
16366          "submodule": "Time & Date"
16367        }, {
16368          "file": "src/utilities/time_date.js",
16369          "line": 145,
16370          "description": "<p>p5.js communicates with the clock on your computer. The <a href=\"#/p5/year\">year()</a> function\nreturns the current year as an integer (2014, 2015, 2016, etc).</p>\n",
16371          "itemtype": "method",
16372          "name": "year",
16373          "return": {
16374            "description": "the current year",
16375            "type": "Integer"
16376          },
16377          "example": ["\n<div>\n<code>\nvar y = year();\ntext('Current year: \\n' + y, 5, 50);\n</code>\n</div>"],
16378          "alt": "Current year is displayed",
16379          "class": "p5",
16380          "module": "IO",
16381          "submodule": "Time & Date"
16382        }, {
16383          "file": "src/webgl/3d_primitives.js",
16384          "line": 15,
16385          "description": "<p>Draw a plane with given a width and height</p>\n",
16386          "itemtype": "method",
16387          "name": "plane",
16388          "params": [{
16389            "name": "width",
16390            "description": "<p>width of the plane</p>\n",
16391            "type": "Number",
16392            "optional": true
16393          }, {
16394            "name": "height",
16395            "description": "<p>height of the plane</p>\n",
16396            "type": "Number",
16397            "optional": true
16398          }, {
16399            "name": "detailX",
16400            "description": "<p>Optional number of triangle\n                            subdivisions in x-dimension</p>\n",
16401            "type": "Integer",
16402            "optional": true
16403          }, {
16404            "name": "detailY",
16405            "description": "<p>Optional number of triangle\n                            subdivisions in y-dimension</p>\n",
16406            "type": "Integer",
16407            "optional": true
16408          }],
16409          "chainable": 1,
16410          "example": ["\n<div>\n<code>
16410\n//draw a plane with width 50 and height 50\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  plane(50, 50);\n}\n</code>\n</div>"],
16411          "alt": "Nothing displayed on canvas\nRotating interior view of a box with sides that change color.\n3d red and green gradient.\nRotating interior view of a cylinder with sides that change color.\nRotating view of a cylinder with sides that change color.\n3d red and green gradient.\nrotating view of a multi-colored cylinder with concave sides.",
16412          "class": "p5",
16413          "module": "Shape",
16414          "submodule": "3D Primitives"
16415        }, {
16416          "file": "src/webgl/3d_primitives.js",
16417          "line": 98,
16418          "description": "<p>Draw a box with given width, height and depth</p>\n",
16419          "itemtype": "method",
16420          "name": "box",
16421          "params": [{
16422            "name": "width",
16423            "description": "<p>width of the box</p>\n",
16424            "type": "Number",
16425            "optional": true
16426          }, {
16427            "name": "Height",
16428            "description": "<p>height of the box</p>\n",
16429            "type": "Number",
16430            "optional": true
16431          }, {
16432            "name": "depth",
16433            "description": "<p>depth of the box</p>\n",
16434            "type": "Number",
16435            "optional": true
16436          }, {
16437            "name": "detailX",
16438            "description": "<p>Optional number of triangle\n                           subdivisions in x-dimension</p>\n",
16439            "type": "Integer",
16440            "optional": true
16441          }, {
16442            "name": "detailY",
16443            "description": "<p>Optional number of triangle\n                           subdivisions in y-dimension</p>\n",
16444            "type": "Integer",
16445            "optional": true
16446          }],
16447          "chainable": 1,
16448          "example": ["\n<div>\n<code>\n//draw a spinning box with width, height and depth 200\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  rotateX(frameCount * 0.01);\n  rotateY(frameCount * 0.01);\n  box(50);\n}\n</code>\n</div>"],
16449          "class": "p5",
16450          "module": "Shape",
16451          "submodule": "3D Primitives"
16452        }, {
16453          "file": "src/webgl/3d_primitives.js",
16454          "line": 215,
16455          "description": "<p>Draw a sphere with given radius</p>\n",
16456          "itemtype": "method",
16457          "name": "sphere",
16458          "params": [{
16459            "name": "radius",
16460            "description": "<p>radius of circle</p>\n",
16461            "type": "Number",
16462            "optional": true
16463          }, {
16464            "name": "detailX",
16465            "description": "<p>number of segments,\n                                   the more segments the smoother geometry\n                                   default is 24</p>\n",
16466            "type": "Integer",
16467            "optional": true
16468          }, {
16469            "name": "detailY",
16470            "description": "<p>number of segments,\n                                   the more segments the smoother geometry\n                                   default is 16</p>\n",
16471            "type": "Integer",
16472            "optional": true
16473          }],
16474          "chainable": 1,
16475          "example": ["\n<div>\n<code>\n// draw a sphere with radius 200\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  sphere(40);\n}\n</code>\n</div>"],
16476          "class": "p5",
16477          "module": "Shape",
16478          "submodule": "3D Primitives"
16479        }, {
16480          "file": "src/webgl/3d_primitives.js",
16481          "line": 393,
16482          "description": "<p>Draw a cylinder with given radius and height</p>\n",
16483          "itemtype": "method",
16484          "name": "cylinder",
16485          "params": [{
16486            "name": "radius",
16487            "description": "<p>radius of the surface</p>\n",
16488            "type": "Number",
16489            "optional": true
16490          }, {
16491            "name": "height",
16492            "description": "<p>height of the cylinder</p>\n",
16493            "type": "Number",
16494            "optional": true
16495          }, {
16496            "name": "detailX",
16497            "description": "<p>number of segments,\n                              the more segments the smoother geometry\n                              default is 24</p>\n",
16498            "type": "Integer",
16499            "optional": true
16500          }, {
16501            "name": "detailY",
16502            "description": "<p>number of segments in y-dimension,\n                              the more segments the smoother geometry\n                              default is 1</p>\n",
16503            "type": "Integer",
16504            "optional": true
16505          }, {
16506            "name": "bottomCap",
16507            "description": "<p>whether to draw the bottom of the cylinder</p>\n",
16508            "type": "Boolean",
16509            "optional": true
16510          }, {
16511            "name": "topCap",
16512            "description": "<p>whether to draw the top of the cylinder</p>\n",
16513            "type": "Boolean",
16514            "optional": true
16515          }],
16516          "chainable": 1,
16517          "example": ["\n<div>\n<code>
16517\n//draw a spinning cylinder with radius 20 and height 50\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  rotateX(frameCount * 0.01);\n  rotateZ(frameCount * 0.01);\n  cylinder(20, 50);\n}\n</code>\n</div>"],
16518          "class": "p5",
16519          "module": "Shape",
16520          "submodule": "3D Primitives"
16521        }, {
16522          "file": "src/webgl/3d_primitives.js",
16523          "line": 484,
16524          "description": "<p>Draw a cone with given radius and height</p>\n",
16525          "itemtype": "method",
16526          "name": "cone",
16527          "params": [{
16528            "name": "radius",
16529            "description": "<p>radius of the bottom surface</p>\n",
16530            "type": "Number",
16531            "optional": true
16532          }, {
16533            "name": "height",
16534            "description": "<p>height of the cone</p>\n",
16535            "type": "Number",
16536            "optional": true
16537          }, {
16538            "name": "detailX",
16539            "description": "<p>number of segments,\n                            the more segments the smoother geometry\n                            default is 24</p>\n",
16540            "type": "Integer",
16541            "optional": true
16542          }, {
16543            "name": "detailY",
16544            "description": "<p>number of segments,\n                            the more segments the smoother geometry\n                            default is 1</p>\n",
16545            "type": "Integer",
16546            "optional": true
16547          }, {
16548            "name": "cap",
16549            "description": "<p>whether to draw the base of the cone</p>\n",
16550            "type": "Boolean",
16551            "optional": true
16552          }],
16553          "chainable": 1,
16554          "example": ["\n<div>\n<code>\n//draw a spinning cone with radius 40 and height 70\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  rotateX(frameCount * 0.01);\n  rotateZ(frameCount * 0.01);\n  cone(40, 70);\n}\n</code>\n</div>"],
16555          "class": "p5",
16556          "module": "Shape",
16557          "submodule": "3D Primitives"
16558        }, {
16559          "file": "src/webgl/3d_primitives.js",
16560          "line": 555,
16561          "description": "<p>Draw an ellipsoid with given radius</p>\n",
16562          "itemtype": "method",
16563          "name": "ellipsoid",
16564          "params": [{
16565            "name": "radiusx",
16566            "description": "<p>xradius of circle</p>\n",
16567            "type": "Number",
16568            "optional": true
16569          }, {
16570            "name": "radiusy",
16571            "description": "<p>yradius of circle</p>\n",
16572            "type": "Number",
16573            "optional": true
16574          }, {
16575            "name": "radiusz",
16576            "description": "<p>zradius of circle</p>\n",
16577            "type": "Number",
16578            "optional": true
16579          }, {
16580            "name": "detailX",
16581            "description": "<p>number of segments,\n                                   the more segments the smoother geometry\n                                   default is 24. Avoid detail number above\n                                   150, it may crash the browser.</p>\n",
16582            "type": "Integer",
16583            "optional": true
16584          }, {
16585            "name": "detailY",
16586            "description": "<p>number of segments,\n                                   the more segments the smoother geometry\n                                   default is 16. Avoid detail number above\n                                   150, it may crash the browser.</p>\n",
16587            "type": "Integer",
16588            "optional": true
16589          }],
16590          "chainable": 1,
16591          "example": ["\n<div>\n<code>\n// draw an ellipsoid with radius 20, 30 and 40.\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  ellipsoid(20, 30, 40);\n}\n</code>\n</div>"],
16592          "class": "p5",
16593          "module": "Shape",
16594          "submodule": "3D Primitives"
16595        }, {
16596          "file": "src/webgl/3d_primitives.js",
16597          "line": 645,
16598          "description": "<p>Draw a torus with given radius and tube radius</p>\n",
16599          "itemtype": "method",
16600          "name": "torus",
16601          "params": [{
16602            "name": "radius",
16603            "description": "<p>radius of the whole ring</p>\n",
16604            "type": "Number",
16605            "optional": true
16606          }, {
16607            "name": "tubeRadius",
16608            "description": "<p>radius of the tube</p>\n",
16609            "type": "Number",
16610            "optional": true
16611          }, {
16612            "name": "detailX",
16613            "description": "<p>number of segments in x-dimension,\n                               the more segments the smoother geometry\n                               default is 24</p>\n",
16614            "type": "Integer",
16615            "optional": true
16616          }, {
16617            "name": "detailY",
16618            "description": "<p>number of segments in y-dimension,\n                               the more segments the smoother geometry\n                               default is 16</p>\n",
16619            "type": "Integer",
16620            "optional": true
16621          }],
16622          "chainable": 1,
16623          "example": ["\n<div>\n<code>
16623\n//draw a spinning torus with radius 200 and tube radius 60\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  rotateX(frameCount * 0.01);\n  rotateY(frameCount * 0.01);\n  torus(50, 15);\n}\n</code>\n</div>"],
16624          "class": "p5",
16625          "module": "Shape",
16626          "submodule": "3D Primitives"
16627        }, {
16628          "file": "src/webgl/interaction.js",
16629          "line": 13,
16630          "description": "<p>Allows movement around a 3D sketch using a mouse or trackpad.  Left-clicking\nand dragging will rotate the camera position about the center of the sketch,\nright-clicking and dragging will pan the camera position without rotation,\nand using the mouse wheel (scrolling) will move the camera closer or further\nfrom the center of the sketch. This function can be called with parameters\ndictating sensitivity to mouse movement along the X and Y axes.  Calling\nthis function without parameters is equivalent to calling orbitControl(1,1).\nTo reverse direction of movement in either axis, enter a negative number\nfor sensitivity.</p>\n",
16631          "itemtype": "method",
16632          "name": "orbitControl",
16633          "params": [{
16634            "name": "sensitivityX",
16635            "description": "<p>sensitivity to mouse movement along X axis</p>\n",
16636            "type": "Number",
16637            "optional": true
16638          }, {
16639            "name": "sensitivityY",
16640            "description": "<p>sensitivity to mouse movement along Y axis</p>\n",
16641            "type": "Number",
16642            "optional": true
16643          }],
16644          "chainable": 1,
16645          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  normalMaterial();\n}\nfunction draw() {\n  background(200);\n  orbitControl();\n  rotateY(0.5);\n  box(30, 50);\n}\n</code>\n</div>"],
16646          "alt": "Camera orbits around a box when mouse is hold-clicked & then moved.",
16647          "class": "p5",
16648          "module": "Lights, Camera",
16649          "submodule": "Interaction"
16650        }, {
16651          "file": "src/webgl/interaction.js",
16652          "line": 146,
16653          "description": "<p>debugMode() helps visualize 3D space by adding a grid to indicate where the\n‘ground’ is in a sketch and an axes icon which indicates the +X, +Y, and +Z\ndirections. This function can be called without parameters to create a\ndefault grid and axes icon, or it can be called according to the examples\nabove to customize the size and position of the grid and/or axes icon.  The\ngrid is drawn using the most recently set stroke color and weight.  To\nspecify these parameters, add a call to stroke() and strokeWeight(
16653)\njust before the end of the draw() loop.</p>\n<p>By default, the grid will run through the origin (0,0,0) of the sketch\nalong the XZ plane\nand the axes icon will be offset from the origin.  Both the grid and axes\nicon will be sized according to the current canvas size.  Note that because the\ngrid runs parallel to the default camera view, it is often helpful to use\ndebugMode along with orbitControl to allow full view of the grid.</p>\n",
16654          "itemtype": "method",
16655          "name": "debugMode",
16656          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  camera(0, -30, 100, 0, 0, 0, 0, 1, 0);\n  normalMaterial();\n  debugMode();\n}\n\nfunction draw() {\n  background(200);\n  orbitControl();\n  box(15, 30);\n  // Press the spacebar to turn debugMode off!\n  if (keyIsDown(32)) {\n    noDebugMode();\n  }\n}\n</code>\n</div>", "\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  camera(0, -30, 100, 0, 0, 0, 0, 1, 0);\n  normalMaterial();\n  debugMode(GRID);\n}\n\nfunction draw() {\n  background(200);\n  orbitControl();\n  box(15, 30);\n}\n</code>\n</div>", "\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  camera(0, -30, 100, 0, 0, 0, 0, 1, 0);\n  normalMaterial();\n  debugMode(AXES);\n}\n\nfunction draw() {\n  background(200);\n  orbitControl();\n  box(15, 30);\n}\n</code>\n</div>", "\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  camera(0, -30, 100, 0, 0, 0, 0, 1, 0);\n  normalMaterial();\n  debugMode(GRID, 100, 10, 0, 0, 0);\n}\n\nfunction draw() {\n  background(200);\n  orbitControl();\n  box(15, 30);\n}\n</code>\n</div>", "\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  camera(0, -30, 100, 0, 0, 0, 0, 1, 0);\n  normalMaterial();\n  debugMode(100, 10, 0, 0, 0, 20, 0, -40, 0);\n}\n\nfunction draw() {\n  noStroke();\n  background(200);\n  orbitControl();\n  box(15, 30);\n  // set the stroke color and weight for the grid!\n  stroke(255, 0, 150);\n  strokeWeight(0.8);\n}\n</code>\n</div>"],
16657          "alt": "a 3D box is centered on a grid in a 3D sketch. an icon\nindicates the direction of each axis: a red line points +X,\na green line +Y, and a blue line +Z.",
16658          "class": "p5",
16659          "module": "Lights, Camera",
16660          "submodule": "Interaction",
16661          "overloads": [{
16662            "line": 146,
16663            "params": []
16664          }, {
16665            "line": 279,
16666            "params": [{
16667              "name": "mode",
16668              "description": "<p>either GRID or AXES</p>\n",
16669              "type": "Constant"
16670            }]
16671          }, {
16672            "line": 284,
16673            "params": [{
16674              "name": "mode",
16675              "description": "",
16676              "type": "Constant"
16677            }, {
16678              "name": "gridSize",
16679              "description": "<p>size of one side of the grid</p>\n",
16680              "type": "Number",
16681              "optional": true
16682            }, {
16683              "name": "gridDivisions",
16684              "description": "<p>number of divisions in the grid</p>\n",
16685              "type": "Number",
16686              "optional": true
16687            }, {
16688              "name": "xOff",
16689              "description": "<p>X axis offset from origin (0,0,0)</p>\n",
16690              "type": "Number",
16691              "optional": true
16692            }, {
16693              "name": "yOff",
16694              "description": "<p>Y axis offset from origin (0,0,0)</p>\n",
16695              "type": "Number",
16696              "optional": true
16697            }, {
16698              "name": "zOff",
16699              "description": "<p>Z axis offset from origin (0,0,0)</p>\n",
16700              "type": "Number",
16701              "optional": true
16702            }]
16703          }, {
16704            "line": 294,
16705            "params": [{
16706              "name": "mode",
16707              "description": "",
16708              "type": "Constant"
16709            }, {
16710              "name": "axesSize",
16711              "description": "<p>size of axes icon</p>\n",
16712              "type": "Number",
16713              "optional": true
16714            }, {
16715              "name": "xOff",
16716              "description": "",
16717              "type": "Number",
16718              "optional": true
16719            }, {
16720              "name": "yOff",
16721              "description": "",
16722              "type": "Number",
16723              "optional": true
16724            }, {
16725              "name": "zOff",
16726              "description": "",
16727              "type": "Number",
16728              "optional": true
16729            }]
16730          }, {
16731            "line": 303,
16732            "params": [{
16733              "name": "gridSize",
16734              "description": "",
16735              "type": "Number",
16736              "optional": true
16737            }, {
16738              "name": "gridDivisions",
16739              "description": "",
16740              "type": "Number",
16741              "optional": true
16742            }, {
16743              "name": "gridXOff",
16744              "description": "",
16745              "type": "Number",
16746              "optional": true
16747            }, {
16748              "name": "gridYOff",
16749              "description": "",
16750              "type": "Number",
16751              "optional": true
16752            }, {
16753              "name": "gridZOff",
16754              "description": "",
16755              "type": "Number",
16756              "optional": true
16757            }, {
16758              "name": "axesSize",
16759              "description": "",
16760              "type": "Number",
16761              "optional": true
16762            }, {
16763              "name": "axesXOff",
16764              "description": "",
16765              "type": "Number",
16766              "optional": true
16767            }, {
16768              "name": "axesYOff",
16769              "description": "",
16770              "type": "Number",
16771              "optional": true
16772            }, {
16773              "name": "axesZOff",
16774              "description": "",
16775              "type": "Number",
16776              "optional": true
16777            }]
16778          }]
16779        }, {
16780          "file": "src/webgl/interaction.js",
16781          "line": 380,
16782          "description": "<p>Turns off debugMode() in a 3D sketch.</p>\n",
16783          "itemtype": "method",
16784          "name": "noDebugMode",
16785          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  camera(0, -30, 100, 0, 0, 0, 0, 1, 0);\n  normalMaterial();\n  debugMode();\n}\n\nfunction draw() {\n  background(200);\n  orbitControl();\n  box(15, 30);\n  // Press the spacebar to turn debugMode off!\n  if (keyIsDown(32)) {\n    noDebugMode();\n  }\n}\n</code>\n</div>"],
16786          "alt": "a 3D box is centered on a grid in a 3D sketch. an icon\nindicates the direction of each axis: a red line points +X,\na green line +Y, and a blue line +Z. the grid and icon disappear when the\nspacebar is pressed.",
16787          "class": "p5",
16788          "module": "Lights, Camera",
16789          "submodule": "Interaction"
16790        }, {
16791          "file": "src/webgl/light.js",
16792          "line": 12,
16793          "description": "<p>Creates an ambient light with a color</p>\n",
16794          "itemtype": "method",
16795          "name": "ambientLight",
16796          "chainable": 1,
16797          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n  background(0);\n  ambientLight(150);\n  ambientMaterial(250);\n  noStroke();\n  sphere(25);\n}\n</code>\n</div>"],
16798          "alt": "evenly distributed light across a sphere",
16799          "class": "p5",
16800          "module": "Lights, Camera",
16801          "submodule": "Lights",
16802          "overloads": [{
16803            "line": 12,
16804            "params": [{
16805              "name": "v1",
16806              "description": "<p>red or hue value relative to\n                                the current color range</p>\n",
16807              "type": "Number"
16808            }, {
16809              "name": "v2",
16810              "description": "<p>
16810green or saturation value\n                                relative to the current color range</p>\n",
16811              "type": "Number"
16812            }, {
16813              "name": "v3",
16814              "description": "<p>blue or brightness value\n                                relative to the current color range</p>\n",
16815              "type": "Number"
16816            }, {
16817              "name": "alpha",
16818              "description": "<p>the alpha value</p>\n",
16819              "type": "Number",
16820              "optional": true
16821            }],
16822            "chainable": 1
16823          }, {
16824            "line": 46,
16825            "params": [{
16826              "name": "value",
16827              "description": "<p>a color string</p>\n",
16828              "type": "String"
16829            }],
16830            "chainable": 1
16831          }, {
16832            "line": 52,
16833            "params": [{
16834              "name": "gray",
16835              "description": "<p>a gray value</p>\n",
16836              "type": "Number"
16837            }, {
16838              "name": "alpha",
16839              "description": "",
16840              "type": "Number",
16841              "optional": true
16842            }],
16843            "chainable": 1
16844          }, {
16845            "line": 59,
16846            "params": [{
16847              "name": "values",
16848              "description": "<p>an array containing the red,green,blue &amp;\n                                and alpha components of the color</p>\n",
16849              "type": "Number[]"
16850            }],
16851            "chainable": 1
16852          }, {
16853            "line": 66,
16854            "params": [{
16855              "name": "color",
16856              "description": "<p>the ambient light color</p>\n",
16857              "type": "p5.Color"
16858            }],
16859            "chainable": 1
16860          }]
16861        }, {
16862          "file": "src/webgl/light.js",
16863          "line": 101,
16864          "description": "<p>Creates a directional light with a color and a direction</p>\n",
16865          "itemtype": "method",
16866          "name": "directionalLight",
16867          "chainable": 1,
16868          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n  background(0);\n  //move your mouse to change light direction\n  let dirX = (mouseX / width - 0.5) * 2;\n  let dirY = (mouseY / height - 0.5) * 2;\n  directionalLight(250, 250, 250, -dirX, -dirY, 0.25);\n  ambientMaterial(250);\n  noStroke();\n  sphere(25);\n}\n</code>\n</div>"],
16869          "alt": "light source on canvas changeable with mouse position",
16870          "class": "p5",
16871          "module": "Lights, Camera",
16872          "submodule": "Lights",
16873          "overloads": [{
16874            "line": 101,
16875            "params": [{
16876              "name": "v1",
16877              "description": "<p>red or hue value (depending on the current\ncolor mode),</p>\n",
16878              "type": "Number"
16879            }, {
16880              "name": "v2",
16881              "description": "<p>green or saturation value</p>\n",
16882              "type": "Number"
16883            }, {
16884              "name": "v3",
16885              "description": "<p>blue or brightness value</p>\n",
16886              "type": "Number"
16887            }, {
16888              "name": "position",
16889              "description": "<p>the direction of the light</p>\n",
16890              "type": "p5.Vector"
16891            }],
16892            "chainable": 1
16893          }, {
16894            "line": 134,
16895            "params": [{
16896              "name": "color",
16897              "description": "<p>color Array, CSS color string,\n                                            or <a href=\"#/p5.Color\">p5.Color</a> value</p>\n",
16898              "type": "Number[]|String|p5.Color"
16899            }, {
16900              "name": "x",
16901              "description": "<p>x axis direction</p>\n",
16902              "type": "Number"
16903            }, {
16904              "name": "y",
16905              "description": "<p>y axis direction</p>\n",
16906              "type": "Number"
16907            }, {
16908              "name": "z",
16909              "description": "<p>z axis direction</p>\n",
16910              "type": "Number"
16911            }],
16912            "chainable": 1
16913          }, {
16914            "line": 144,
16915            "params": [{
16916              "name": "color",
16917              "description": "",
16918              "type": "Number[]|String|p5.Color"
16919            }, {
16920              "name": "position",
16921              "description": "",
16922              "type": "p5.Vector"
16923            }],
16924            "chainable": 1
16925          }, {
16926            "line": 151,
16927            "params": [{
16928              "name": "v1",
16929              "description": "",
16930              "type": "Number"
16931            }, {
16932              "name": "v2",
16933              "description": "",
16934              "type": "Number"
16935            }, {
16936              "name": "v3",
16937              "description": "",
16938              "type": "Number"
16939            }, {
16940              "name": "x",
16941              "description": "",
16942              "type": "Number"
16943            }, {
16944              "name": "y",
16945              "description": "",
16946              "type": "Number"
16947            }, {
16948              "name": "z",
16949              "description": "",
16950              "type": "Number"
16951            }],
16952            "chainable": 1
16953          }]
16954        }, {
16955          "file": "src/webgl/light.js",
16956          "line": 212,
16957          "description": "<p>Creates a point light with a color and a light position</p>\n",
16958          "itemtype": "method",
16959          "name": "pointLight",
16960          "chainable": 1,
16961          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n  background(0);\n  //move your mouse to change light position\n  let locX = mouseX - width / 2;
16961\n  let locY = mouseY - height / 2;\n  // to set the light position,\n  // think of the world's coordinate as:\n  // -width/2,-height/2 -------- width/2,-height/2\n  //                |            |\n  //                |     0,0    |\n  //                |            |\n  // -width/2,height/2--------width/2,height/2\n  pointLight(250, 250, 250, locX, locY, 50);\n  ambientMaterial(250);\n  noStroke();\n  sphere(25);\n}\n</code>\n</div>"],
16962          "alt": "spot light on canvas changes position with mouse",
16963          "class": "p5",
16964          "module": "Lights, Camera",
16965          "submodule": "Lights",
16966          "overloads": [{
16967            "line": 212,
16968            "params": [{
16969              "name": "v1",
16970              "description": "<p>red or hue value (depending on the current\ncolor mode),</p>\n",
16971              "type": "Number"
16972            }, {
16973              "name": "v2",
16974              "description": "<p>green or saturation value</p>\n",
16975              "type": "Number"
16976            }, {
16977              "name": "v3",
16978              "description": "<p>blue or brightness value</p>\n",
16979              "type": "Number"
16980            }, {
16981              "name": "x",
16982              "description": "<p>x axis position</p>\n",
16983              "type": "Number"
16984            }, {
16985              "name": "y",
16986              "description": "<p>y axis position</p>\n",
16987              "type": "Number"
16988            }, {
16989              "name": "z",
16990              "description": "<p>z axis position</p>\n",
16991              "type": "Number"
16992            }],
16993            "chainable": 1
16994          }, {
16995            "line": 254,
16996            "params": [{
16997              "name": "v1",
16998              "description": "",
16999              "type": "Number"
17000            }, {
17001              "name": "v2",
17002              "description": "",
17003              "type": "Number"
17004            }, {
17005              "name": "v3",
17006              "description": "",
17007              "type": "Number"
17008            }, {
17009              "name": "position",
17010              "description": "<p>the position of the light</p>\n",
17011              "type": "p5.Vector"
17012            }],
17013            "chainable": 1
17014          }, {
17015            "line": 263,
17016            "params": [{
17017              "name": "color",
17018              "description": "<p>color Array, CSS color string,\nor <a href=\"#/p5.Color\">p5.Color</a> value</p>\n",
17019              "type": "Number[]|String|p5.Color"
17020            }, {
17021              "name": "x",
17022              "description": "",
17023              "type": "Number"
17024            }, {
17025              "name": "y",
17026              "description": "",
17027              "type": "Number"
17028            }, {
17029              "name": "z",
17030              "description": "",
17031              "type": "Number"
17032            }],
17033            "chainable": 1
17034          }, {
17035            "line": 273,
17036            "params": [{
17037              "name": "color",
17038              "description": "",
17039              "type": "Number[]|String|p5.Color"
17040            }, {
17041              "name": "position",
17042              "description": "",
17043              "type": "p5.Vector"
17044            }],
17045            "chainable": 1
17046          }]
17047        }, {
17048          "file": "src/webgl/loading.js",
17049          "line": 14,
17050          "description": "<p>Load a 3d model from an OBJ file.\n<br><br>\nOne of the limitations of the OBJ format is that it doesn&#39;t have a built-in\nsense of scale. This means that models exported from different programs might\nbe very different sizes. If your model isn&#39;t displaying, try calling\n<a href=\"#/p5/loadModel\">loadModel()</a> with the normalized parameter set to true. This will resize the\nmodel to a scale appropriate for p5. You can also make additional changes to\nthe final size of your model with the <a href=\"#/p5/scale\">scale()</a> function.</p>\n",
17051          "itemtype": "method",
17052          "name": "loadModel",
17053          "return": {
17054            "description": "the <a href=\"#/p5.Geometry\">p5.Geometry</a> object",
17055            "type": "p5.Geometry"
17056          },
17057          "example": ["\n<div>\n<code>\n//draw a spinning octahedron\nlet octahedron;\n\nfunction preload() {\n  octahedron = loadModel('assets/octahedron.obj');\n}\n\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  rotateX(frameCount * 0.01);\n  rotateY(frameCount * 0.01);\n  model(octahedron);\n}\n</code>\n</div>", "\n<div>\n<code>
17057\n//draw a spinning teapot\nlet teapot;\n\nfunction preload() {\n  // Load model with normalise parameter set to true\n  teapot = loadModel('assets/teapot.obj', true);\n}\n\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  scale(0.4); // Scaled to make model fit into canvas\n  rotateX(frameCount * 0.01);\n  rotateY(frameCount * 0.01);\n  normalMaterial(); // For effect\n  model(teapot);\n}\n</code>\n</div>"],
17058          "alt": "Vertically rotating 3-d teapot with red, green and blue gradient.",
17059          "class": "p5",
17060          "module": "Shape",
17061          "submodule": "3D Models",
17062          "overloads": [{
17063            "line": 14,
17064            "params": [{
17065              "name": "path",
17066              "description": "<p>Path of the model to be loaded</p>\n",
17067              "type": "String"
17068            }, {
17069              "name": "normalize",
17070              "description": "<p>If true, scale the model to a\n                                     standardized size when loading</p>\n",
17071              "type": "Boolean"
17072            }, {
17073              "name": "successCallback",
17074              "description": "<p>Function to be called\n                                    once the model is loaded. Will be passed\n                                    the 3D model object.</p>\n",
17075              "type": "function(p5.Geometry)",
17076              "optional": true
17077            }, {
17078              "name": "failureCallback",
17079              "description": "<p>called with event error if\n                                        the image fails to load.</p>\n",
17080              "type": "Function(Event)",
17081              "optional": true
17082            }],
17083            "return": {
17084              "description": "the <a href=\"#/p5.Geometry\">p5.Geometry</a> object",
17085              "type": "p5.Geometry"
17086            }
17087          }, {
17088            "line": 90,
17089            "params": [{
17090              "name": "path",
17091              "description": "",
17092              "type": "String"
17093            }, {
17094              "name": "successCallback",
17095              "description": "",
17096              "type": "function(p5.Geometry)",
17097              "optional": true
17098            }, {
17099              "name": "failureCallback",
17100              "description": "",
17101              "type": "Function(Event)",
17102              "optional": true
17103            }],
17104            "return": {
17105              "description": "the <a href=\"#/p5.Geometry\">p5.Geometry</a> object",
17106              "type": "p5.Geometry"
17107            }
17108          }]
17109        }, {
17110          "file": "src/webgl/loading.js",
17111          "line": 135,
17112          "description": "<p>Parse OBJ lines into model. For reference, this is what a simple model of a\nsquare might look like:</p>\n<p>v -0.5 -0.5 0.5\nv -0.5 -0.5 -0.5\nv -0.5 0.5 -0.5\nv -0.5 0.5 0.5</p>\n<p>f 4 3 2 1</p>\n",
17113          "class": "p5",
17114          "module": "Shape",
17115          "submodule": "3D Models"
17116        }, {
17117          "file": "src/webgl/loading.js",
17118          "line": 244,
17119          "description": "<p>Render a 3d model to the screen.</p>\n",
17120          "itemtype": "method",
17121          "name": "model",
17122          "params": [{
17123            "name": "model",
17124            "description": "<p>Loaded 3d model to be rendered</p>\n",
17125            "type": "p5.Geometry"
17126          }],
17127          "example": ["\n<div>\n<code>\n//draw a spinning octahedron\nlet octahedron;\n\nfunction preload() {\n  octahedron = loadModel('assets/octahedron.obj');\n}\n\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  rotateX(frameCount * 0.01);\n  rotateY(frameCount * 0.01);\n  model(octahedron);\n}\n</code>\n</div>"],
17128          "alt": "Vertically rotating 3-d octahedron.",
17129          "class": "p5",
17130          "module": "Shape",
17131          "submodule": "3D Models"
17132        }, {
17133          "file": "src/webgl/material.js",
17134          "line": 14,
17135          "description": "<p>Loads a custom shader from the provided vertex and fragment\nshader paths. The shader files are loaded asynchronously in the\nbackground, so this method should be used in <a href=\"#/p5/preload\">preload()</a>.</p>\n<p>For now, there are three main types of shaders. p5 will automatically\nsupply appropriate vertices, normals, colors, and lighting attributes\nif the parameters defined in the shader match the names.</p>\n",
17136          "itemtype": "method",
17137          "name": "loadShader",
17138          "params": [{
17139            "name": "vertFilename",
17140            "description": "<p>path to file containing vertex shader\nsource code</p>\n",
17141            "type": "String",
17142            "optional": true
17143          }, {
17144            "name": "fragFilename",
17145            "description": "<p>path to file containing fragment shader\nsource code</p>\n",
17146            "type": "String",
17147            "optional": true
17148          }],
17149          "return": {
17150            "description": "a shader object created from the provided\nvertex and fragment shader files.",
17151            "type": "p5.Shader"
17152          },
17153          "example": ["\n<div modernizr='webgl'>\n<code>\nlet mandel;\nfunction preload() {\n  // load the shader definitions from files\n  mandel = loadShader('assets/shader.vert', 'assets/shader.frag');\n}\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  // use the shader\n  shader(mandel);\n  noStroke();\n  mandel.setUniform('p', [-0.74364388703, 0.13182590421]);\n}\n\nfunction draw() {\n  mandel.setUniform('r', 1.5 * exp(-6.5 * (1 + sin(millis() / 2000))));\n  quad(-1, -1, 1, -1, 1, 1, -1, 1);\n}\n</code>\n</div>"],
17154          "alt": "zooming Mandelbrot set. a colorful, infinitely detailed fractal.",
17155          "class": "p5",
17156          "module": "Lights, Camera",
17157          "submodule": "Material"
17158        }, {
17159          "file": "src/webgl/material.js",
17160          "line": 83,
17161          "itemtype": "method",
17162          "name": "createShader",
17163          "params": [{
17164            "name": "vertSrc",
17165            "description": "<p>source code for the vertex shader</p>\n",
17166            "type": "String"
17167          }, {
17168            "name": "fragSrc",
17169            "description": "<p>source code for the fragment shader</p>\n",
17170            "type": "String"
17171          }],
17172          "return": {
17173            "description": "a shader object created from the provided\nvertex and fragment shaders.",
17174            "type": "p5.Shader"
17175          },
17176          "example": ["\n<div modernizr='webgl'>\n<code>\n// the 'varying's are shared between both vertex & fragment shaders\nlet varying = 'precision highp float; varying vec2 vPos;';\n\n// the vertex shader is called for each vertex\nlet vs =\n  varying +\n  'attribute vec3 aPosition;' +\n  'void main() { vPos = (gl_Position = vec4(aPosition,1.0)).xy; }';\n\n// the fragment shader is called for each pixel\nlet fs =\n  varying +\n  'uniform vec2 p;' +\n  'uniform float r;' +\n  'const int I = 500;' +\n  'void main() {' +\n  '  vec2 c = p + vPos * r, z = c;' +\n  '  float n = 0.0;' +\n  '  for (int i = I; i > 0; i --) {' +\n  '    if(z.x*z.x+z.y*z.y > 4.0) {' +\n  '      n = float(i)/float(I);' +\n  '      break;' +\n  '    }' +\n  '    z = vec2(z.x*z.x-z.y*z.y, 2.0*z.x*z.y) + c;' +\n  '  }
17176' +\n  '  gl_FragColor = vec4(0.5-cos(n*17.0)/2.0,0.5-cos(n*13.0)/2.0,0.5-cos(n*23.0)/2.0,1.0);' +\n  '}';\n\nlet mandel;\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n\n  // create and initialize the shader\n  mandel = createShader(vs, fs);\n  shader(mandel);\n  noStroke();\n\n  // 'p' is the center point of the Mandelbrot image\n  mandel.setUniform('p', [-0.74364388703, 0.13182590421]);\n}\n\nfunction draw() {\n  // 'r' is the size of the image in Mandelbrot-space\n  mandel.setUniform('r', 1.5 * exp(-6.5 * (1 + sin(millis() / 2000))));\n  quad(-1, -1, 1, -1, 1, 1, -1, 1);\n}\n</code>\n</div>"],
17177          "alt": "zooming Mandelbrot set. a colorful, infinitely detailed fractal.",
17178          "class": "p5",
17179          "module": "Lights, Camera",
17180          "submodule": "Material"
17181        }, {
17182          "file": "src/webgl/material.js",
17183          "line": 151,
17184          "description": "<p>The <a href=\"#/p5/shader\">shader()</a> function lets the user provide a custom shader\nto fill in shapes in WEBGL mode. Users can create their\nown shaders by loading vertex and fragment shaders with\n<a href=\"#/p5/loadShader\">loadShader()</a>.</p>\n",
17185          "itemtype": "method",
17186          "name": "shader",
17187          "chainable": 1,
17188          "params": [{
17189            "name": "s",
17190            "description": "<p>the desired <a href=\"#/p5.Shader\">p5.Shader</a> to use for rendering\nshapes.</p>\n",
17191            "type": "p5.Shader",
17192            "optional": true
17193          }],
17194          "class": "p5",
17195          "module": "Lights, Camera",
17196          "submodule": "Material"
17197        }, {
17198          "file": "src/webgl/material.js",
17199          "line": 176,
17200          "description": "<p>Normal material for geometry. You can view all\npossible materials in this\n<a href=\"https://p5js.org/examples/3d-materials.html\">example</a>.</p>\n",
17201          "itemtype": "method",
17202          "name": "normalMaterial",
17203          "chainable": 1,
17204          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(200);\n  normalMaterial();\n  sphere(50);\n}\n</code>\n</div>"],
17205          "alt": "Red, green and blue gradient.",
17206          "class": "p5",
17207          "module": "Lights, Camera",
17208          "submodule": "Material"
17209        }, {
17210          "file": "src/webgl/material.js",
17211          "line": 211,
17212          "description": "<p>Texture for geometry.  You can view other possible materials in this\n<a href=\"https://p5js.org/examples/3d-materials.html\">example</a>.</p>\n",
17213          "itemtype": "method",
17214          "name": "texture",
17215          "params": [{
17216            "name": "tex",
17217            "description": "<p>2-dimensional graphics\n                   to render as texture</p>\n",
17218            "type": "p5.Image|p5.MediaElement|p5.Graphics"
17219          }],
17220          "chainable": 1,
17221          "example": ["\n<div>\n<code>\nlet img;\nfunction preload() {\n  img = loadImage('assets/laDefense.jpg');\n}\n\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(0);\n  rotateZ(frameCount * 0.01);\n  rotateX(frameCount * 0.01);\n  rotateY(frameCount * 0.01);\n  //pass image as texture\n  texture(img);\n  box(200, 200, 200);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet pg;\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  pg = createGraphics(200, 200);\n  pg.textSize(100);\n}\n\nfunction draw() {\n  background(0);\n  pg.background(255);\n  pg.text('hello!', 0, 100);\n  //pass image as texture\n  texture(pg);\n  plane(200);\n}\n</code>\n</div>\n\n<div>\n<code>\nlet vid;\nfunction preload() {\n  vid = createVideo('assets/fingers.mov');\n  vid.hide();\n  vid.loop();\n}\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(0);\n  //pass video frame as texture\n  texture(vid);\n  plane(200);\n}\n</code>\n</div>"],
17222          "alt": "Rotating view of many images umbrella and grid roof on a 3d plane\nblack canvas\nblack canvas",
17223          "class": "p5",
17224          "module": "Lights, Camera",
17225          "submodule": "Material"
17226        }, {
17227          "file": "src/webgl/material.js",
17228          "line": 302,
17229          "description": "<p>Sets the coordinate space for texture mapping. The default mode is IMAGE\nwhich refers to the actual coordinates of the image.\nNORMAL refers to a normalized space of values ranging from 0 to 1.\
17229nThis function only works in WEBGL mode.</p>\n<p>With IMAGE, if an image is 100 x 200 pixels, mapping the image onto the entire\nsize of a quad would require the points (0,0) (100, 0) (100,200) (0,200).\nThe same mapping in NORMAL is (0,0) (1,0) (1,1) (0,1).</p>\n",
17230          "itemtype": "method",
17231          "name": "textureMode",
17232          "params": [{
17233            "name": "mode",
17234            "description": "<p>either IMAGE or NORMAL</p>\n",
17235            "type": "Constant"
17236          }],
17237          "example": ["\n<div>\n<code>\nlet img;\n\nfunction preload() {\n  img = loadImage('assets/laDefense.jpg');\n}\n\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  texture(img);\n  textureMode(NORMAL);\n  beginShape();\n  vertex(-50, -50, 0, 0);\n  vertex(50, -50, 1, 0);\n  vertex(50, 50, 1, 1);\n  vertex(-50, 50, 0, 1);\n  endShape();\n}\n</code>\n</div>"],
17238          "alt": "the underside of a white umbrella and gridded ceiling above",
17239          "class": "p5",
17240          "module": "Lights, Camera",
17241          "submodule": "Material"
17242        }, {
17243          "file": "src/webgl/material.js",
17244          "line": 381,
17245          "description": "<p>Ambient material for geometry with a given color. You can view all\npossible materials in this\n<a href=\"https://p5js.org/examples/3d-materials.html\">example</a>.</p>\n",
17246          "itemtype": "method",
17247          "name": "ambientMaterial",
17248          "chainable": 1,
17249          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n  background(0);\n  ambientLight(100);\n  pointLight(250, 250, 250, 100, 100, 0);\n  ambientMaterial(250);\n  sphere(50);\n}\n</code>\n</div>"],
17250          "alt": "radiating light source from top right of canvas",
17251          "class": "p5",
17252          "module": "Lights, Camera",
17253          "submodule": "Material",
17254          "overloads": [{
17255            "line": 381,
17256            "params": [{
17257              "name": "v1",
17258              "description": "<p>gray value, red or hue value\n                        (depending on the current color mode),</p>\n",
17259              "type": "Number"
17260            }, {
17261              "name": "v2",
17262              "description": "<p>green or saturation value</p>\n",
17263              "type": "Number",
17264              "optional": true
17265            }, {
17266              "name": "v3",
17267              "description": "<p>blue or brightness value</p>\n",
17268              "type": "Number",
17269              "optional": true
17270            }, {
17271              "name": "a",
17272              "description": "<p>opacity</p>\n",
17273              "type": "Number",
17274              "optional": true
17275            }],
17276            "chainable": 1
17277          }, {
17278            "line": 412,
17279            "params": [{
17280              "name": "color",
17281              "description": "<p>color, color Array, or CSS color string</p>\n",
17282              "type": "Number[]|String|p5.Color"
17283            }],
17284            "chainable": 1
17285          }]
17286        }, {
17287          "file": "src/webgl/material.js",
17288          "line": 430,
17289          "description": "<p>Specular material for geometry with a given color. You can view all\npossible materials in this\n<a href=\"https://p5js.org/examples/3d-materials.html\">example</a>.</p>\n",
17290          "itemtype": "method",
17291          "name": "specularMaterial",
17292          "chainable": 1,
17293          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n  background(0);\n  ambientLight(100);\n  pointLight(250, 250, 250, 100, 100, 0);\n  specularMaterial(250);\n  sphere(50);\n}\n</code>\n</div>"],
17294          "alt": "diffused radiating light source from top right of canvas",
17295          "class": "p5",
17296          "module": "Lights, Camera",
17297          "submodule": "Material",
17298          "overloads": [{
17299            "line": 430,
17300            "params": [{
17301              "name": "v1",
17302              "description": "<p>gray value, red or hue value\n                      (depending on the current color mode),</p>\n",
17303              "type": "Number"
17304            }, {
17305              "name": "v2",
17306              "description": "<p>green or saturation value</p>\n",
17307              "type": "Number",
17308              "optional": true
17309            }, {
17310              "name": "v3",
17311              "description": "<p>blue or brightness value</p>\n",
17312              "type": "Number",
17313              "optional": true
17314            }, {
17315              "name": "a",
17316              "description": "<p>opacity</p>\n",
17317              "type": "Number",
17318              "optional": true
17319            }],
17320            "chainable": 1
17321          }, {
17322            "line": 461,
17323            "params": [{
17324              "name": "color",
17325              "description": "<p>color Array, or CSS color string</p>\n",
17326              "type": "Number[]|String|p5.Color"
17327            }],
17328            "chainable": 1
17329          }]
17330        }, {
17331          "file": "src/webgl/p5.Camera.js",
17332          "line": 15,
17333          "description": "<p>Sets the camera position for a 3D sketch. Parameters for this function define\nthe position for the camera, the center of the sketch (where the camera is\npointing), and an up direction (the orientation of the camera).</p>\n<p>When called with no arguments, this function creates a default camera\nequivalent to\ncamera(0, 0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0);</p>\n",
17334          "itemtype": "method",
17335          "name": "camera",
17336          "params": [{
17337            "name": "x",
17338            "description": "<p>camera position value on x axis</p>\n",
17339            "type": "Number",
17340            "optional": true
17341          }, {
17342            "name": "y",
17343            "description": "<p>camera position value on y axis</p>\n",
17344            "type": "Number",
17345            "optional": true
17346          }, {
17347            "name": "z",
17348            "description": "<p>camera position value on z axis</p>\n",
17349            "type": "Number",
17350            "optional": true
17351          }, {
17352            "name": "centerX",
17353            "description": "<p>x coordinate representing center of the sketch</p>\n",
17354            "type": "Number",
17355            "optional": true
17356          }, {
17357            "name": "centerY",
17358            "description": "<p>y coordinate representing center of the sketch</p>\n",
17359            "type": "Number",
17360            "optional": true
17361          }, {
17362            "name": "centerZ",
17363            "description": "<p>z coordinate representing center of the sketch</p>\n",
17364            "type": "Number",
17365            "optional": true
17366          }, {
17367            "name": "upX",
17368            "description": "<p>x component of direction &#39;up&#39; from camera</p>\n",
17369            "type": "Number",
17370            "optional": true
17371          }, {
17372            "name": "upY",
17373            "description": "<p>y component of direction &#39;up&#39; from camera</p>\n",
17374            "type": "Number",
17375            "optional": true
17376          }, {
17377            "name": "upZ",
17378            "description": "<p>z component of direction &#39;up&#39; from camera</p>\n",
17379            "type": "Number",
17380            "optional": true
17381          }],
17382          "chainable": 1,
17383          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\nfunction draw() {\n  background(204);\n  //move the camera away from the plane by a sin wave\n  camera(0, 0, 20 + sin(frameCount * 0.01) * 10, 0, 0, 0, 0, 1, 0);\n  plane(10, 10);\n}\n</code>\n</div>"],
17384          "alt": "White square repeatedly grows to fill canvas and then shrinks.",
17385          "class": "p5",
17386          "module": "Lights, Camera",
17387          "submodule": "Camera"
17388        }, {
17389          "file": "src/webgl/p5.Camera.js",
17390          "line": 61,
17391          "description": "<p>Sets a perspective projection for the camera in a 3D sketch. This projection\nrepresents depth through foreshortening: objects that are close to the camera\nappear their actual size while those that are further away from the camera\nappear smaller. The parameters to this function define the viewing frustum\n(the truncated pyramid within which objects are seen by the camera) through\nvertical field of view, aspect ratio (usually width/height), and near and far\nclipping planes.</p>\n<p>When called with no arguments, the defaults\nprovided are equivalent to\nperspective(PI/3.0, width/height, eyeZ/10.0, eyeZ<em>10.0), where eyeZ\nis equal to ((height/2.0) / tan(PI</em>60.0/360.0));</p>\n",
17392          "itemtype": "method",
17393          "name": "perspective",
17394          "params": [{
17395            "name": "fovy",
17396            "description": "<p>camera frustum vertical field of view,\n                          from bottom to top of view, in <a href=\"#/p5/angleMode\">angleMode</a> units</p>\n",
17397            "type": "Number",
17398            "optional": true
17399          }, {
17400            "name": "aspect",
17401            "description": "<p>camera frustum aspect ratio</p>\n",
17402            "type": "Number",
17403            "optional": true
17404          }, {
17405            "name": "near",
17406            "description": "<p>frustum near plane length</p>\n",
17407            "type": "Number",
17408            "optional": true
17409          }, {
17410            "name": "far",
17411            "description": "<p>frustum far plane length</p>\n",
17412            "type": "Number",
17413            "optional": true
17414          }],
17415          "chainable": 1,
17416          "example": ["\n<div>\n<code>
17416\n//drag the mouse to look around!\n//you will see there's a vanishing point\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  perspective(PI / 3.0, width / height, 0.1, 500);\n}\nfunction draw() {\n  background(200);\n  orbitControl();\n  normalMaterial();\n\n  rotateX(-0.3);\n  rotateY(-0.2);\n  translate(0, 0, -50);\n\n  push();\n  translate(-15, 0, sin(frameCount / 30) * 95);\n  box(30);\n  pop();\n  push();\n  translate(15, 0, sin(frameCount / 30 + PI) * 95);\n  box(30);\n  pop();\n}\n</code>\n</div>"],
17417          "alt": "two colored 3D boxes move back and forth, rotating as mouse is dragged.",
17418          "class": "p5",
17419          "module": "Lights, Camera",
17420          "submodule": "Camera"
17421        }, {
17422          "file": "src/webgl/p5.Camera.js",
17423          "line": 126,
17424          "description": "<p>Sets an orthographic projection for the camera in a 3D sketch and defines a\nbox-shaped viewing frustum within which objects are seen. In this projection,\nall objects with the same dimension appear the same size, regardless of\nwhether they are near or far from the camera. The parameters to this\nfunction specify the viewing frustum where left and right are the minimum and\nmaximum x values, top and bottom are the minimum and maximum y values, and near\nand far are the minimum and maximum z values. If no parameters are given, the\ndefault is used: ortho(-width/2, width/2, -height/2, height/2).</p>\n",
17425          "itemtype": "method",
17426          "name": "ortho",
17427          "params": [{
17428            "name": "left",
17429            "description": "<p>camera frustum left plane</p>\n",
17430            "type": "Number",
17431            "optional": true
17432          }, {
17433            "name": "right",
17434            "description": "<p>camera frustum right plane</p>\n",
17435            "type": "Number",
17436            "optional": true
17437          }, {
17438            "name": "bottom",
17439            "description": "<p>camera frustum bottom plane</p>\n",
17440            "type": "Number",
17441            "optional": true
17442          }, {
17443            "name": "top",
17444            "description": "<p>camera frustum top plane</p>\n",
17445            "type": "Number",
17446            "optional": true
17447          }, {
17448            "name": "near",
17449            "description": "<p>camera frustum near plane</p>\n",
17450            "type": "Number",
17451            "optional": true
17452          }, {
17453            "name": "far",
17454            "description": "<p>camera frustum far plane</p>\n",
17455            "type": "Number",
17456            "optional": true
17457          }],
17458          "chainable": 1,
17459          "example": ["\n<div>\n<code>\n//drag the mouse to look around!\n//there's no vanishing point\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  ortho(-width / 2, width / 2, height / 2, -height / 2, 0, 500);\n}\nfunction draw() {\n  background(200);\n  orbitControl();\n  normalMaterial();\n\n  rotateX(0.2);\n  rotateY(-0.2);\n  push();\n  translate(-15, 0, sin(frameCount / 30) * 65);\n  box(30);\n  pop();\n  push();\n  translate(15, 0, sin(frameCount / 30 + PI) * 65);\n  box(30);\n  pop();\n}\n</code>\n</div>"],
17460          "alt": "two 3D boxes move back and forth along same plane, rotating as mouse is dragged.",
17461          "class": "p5",
17462          "module": "Lights, Camera",
17463          "submodule": "Camera"
17464        }, {
17465          "file": "src/webgl/p5.Camera.js",
17466          "line": 187,
17467          "description": "<p>Creates a new <a href=\"#/p5.Camera\">p5.Camera</a> object and tells the\nrenderer to use that camera.\nReturns the p5.Camera object.</p>\n",
17468          "itemtype": "method",
17469          "name": "createCamera",
17470          "return": {
17471            "description": "The newly created camera object.",
17472            "type": "p5.Camera"
17473          },
17474          "class": "p5",
17475          "module": "Lights, Camera",
17476          "submodule": "Camera"
17477        }, {
17478          "file": "src/webgl/p5.Camera.js",
17479          "line": 298,
17480          "description": "<p>Sets a perspective projection for a p5.Camera object and sets parameters\nfor that projection according to <a href=\"#/p5/perspective\">perspective()</a>\nsyntax.</p>\n",
17481          "itemtype": "method",
17482          "name": "perspective",
17483          "class": "p5.Camera",
17484          "module": "Lights, Camera",
17485          "submodule": "Camera"
17486        }, {
17487          "file": "src/webgl/p5.Camera.js",
17488          "line": 379,
17489          "description": "<p>Sets an orthographic projection for a p5.Camera object and sets parameters\nfor that projection according to <a href=\"#/p5/ortho\">ortho()</a> syntax.</p>\n",
17490          "itemtype": "method",
17491          "name": "ortho",
17492          "class": "p5.Camera",
17493          "module": "Lights, Camera",
17494          "submodule": "Camera"
17495        }, {
17496          "file": "src/webgl/p5.Camera.js",
17497          "line": 486,
17498          "description": "<p>Panning rotates the camera view to the left and right.</p>\n",
17499          "itemtype": "method",
17500          "name": "pan",
17501          "params": [{
17502            "name": "angle",
17503            "description": "<p>amount to rotate camera in current\n<a href=\"#/p5/angleMode\">angleMode</a> units.\nGreater than 0 values rotate counterclockwise (to the left).</p>\n",
17504            "type": "Number"
17505          }],
17506          "example": ["\n<div>\n<code>\nlet cam;\nlet delta = 0.01;\n\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  normalMaterial();\n  cam = createCamera();\n  // set initial pan angle\n  cam.pan(-0.8);\n}\n\nfunction draw() {\n  background(200);\n\n  // pan camera according to angle 'delta'\n  cam.pan(delta);\n\n  // every 160 frames, switch direction\n  if (frameCount % 160 === 0) {\n    delta *= -1;\n  }\n\n  rotateX(frameCount * 0.01);\n  translate(-100, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n}\n</code>\n</div>"],
17507          "alt": "camera view pans left and right across a series of rotating 3D boxes.",
17508          "class": "p5.Camera",
17509          "module": "Lights, Camera",
17510          "submodule": "Camera"
17511        }, {
17512          "file": "src/webgl/p5.Camera.js",
17513          "line": 545,
17514          "description": "<p>Tilting rotates the camera view up and down.</p>\n",
17515          "itemtype": "method",
17516          "name": "tilt",
17517          "params": [{
17518            "name": "angle",
17519            "description": "<p>amount to rotate camera in current\n<a href=\"#/p5/angleMode\">angleMode</a> units.\nGreater than 0 values rotate counterclockwise (to the left).</p>\n",
17520            "type": "Number"
17521          }],
17522          "example": ["\n<div>\n<code>\nlet cam;\nlet delta = 0.01;\n\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  normalMaterial();\n  cam = createCamera();\n  // set initial tilt\n  cam.tilt(-0.8);\n}\n\nfunction draw() {\n  background(200);\n\n  // pan camera according to angle 'delta'\n  cam.tilt(delta);\n\n  // every 160 frames, switch direction\n  if (frameCount % 160 === 0) {\n    delta *= -1;\n  }\n\n  rotateY(frameCount * 0.01);\n  translate(0, -100, 0);\n  box(20);\n  translate(0, 35, 0);\n  box(20);\n  translate(0, 35, 0);\n  box(20);\n  translate(0, 35, 0);\n  box(20);\n  translate(0, 35, 0);\n  box(20);\n  translate(0, 35, 0);\n  box(20);\n  translate(0, 35, 0);\n  box(20);\n}\n</code>\n</div>"],
17523          "alt": "camera view tilts up and down across a series of rotating 3D boxes.",
17524          "class": "p5.Camera",
17525          "module": "Lights, Camera",
17526          "submodule": "Camera"
17527        }, {
17528          "file": "src/webgl/p5.Camera.js",
17529          "line": 603,
17530          "description": "<p>Reorients the camera to look at a position in world space.</p>\n",
17531          "itemtype": "method",
17532          "name": "lookAt",
17533          "params": [{
17534            "name": "x",
17535            "description": "<p>x position of a point in world space</p>\n",
17536            "type": "Number"
17537          }, {
17538            "name": "y",
17539            "description": "<p>y position of a point in world space</p>\n",
17540            "type": "Number"
17541          }, {
17542            "name": "z",
17543            "description": "<p>z position of a point in world space</p>\n",
17544            "type": "Number"
17545          }],
17546          "example": ["\n<div>\n<code>\nlet cam;\n\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  normalMaterial();\n  cam = createCamera();\n}\n\nfunction draw() {\n  background(200);\n\n  // look at a new random point every 60 frames\n  if (frameCount % 60 === 0) {\n    cam.lookAt(random(-100, 100), random(-50, 50), 0);\n  }\n\n  rotateX(frameCount * 0.01);\n  translate(-100, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n}\n</code>\n</div>"],
17547          "alt": "camera view of rotating 3D cubes changes to look at a new random\npoint every second .",
17548          "class": "p5.Camera",
17549          "module": "Lights, Camera",
17550          "submodule": "Camera"
17551        }, {
17552          "file": "src/webgl/p5.Camera.js",
17553          "line": 670,
17554          "description": "<p>Sets a camera&#39;s position and orientation.  This is equivalent to calling\n<a href=\"#/p5/camera\">camera()</a> on a p5.Camera object.</p>\n",
17555          "itemtype": "method",
17556          "name": "camera",
17557          "class": "p5.Camera",
17558          "module": "Lights, Camera",
17559          "submodule": "Camera"
17560        }, {
17561          "file": "src/webgl/p5.Camera.js",
17562          "line": 751,
17563          "description": "<p>Move camera along its local axes while maintaining current camera orientation.</p>\n",
17564          "itemtype": "method",
17565          "name": "move",
17566          "params": [{
17567            "name": "x",
17568            "description": "<p>amount to move along camera&#39;s left-right axis</p>\n",
17569            "type": "Number"
17570          }, {
17571            "name": "y",
17572            "description": "<p>amount to move along camera&#39;s up-down axis</p>\n",
17573            "type": "Number"
17574          }, {
17575            "name": "z",
17576            "description": "<p>amount to move along camera&#39;s forward-backward axis</p>\n",
17577            "type": "Number"
17578          }],
17579          "example": ["\n<div>\n<code>\n// see the camera move along its own axes while maintaining its orientation\nlet cam;\nlet delta = 0.5;\n\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  normalMaterial();\n  cam = createCamera();\n}\n\nfunction draw() {\n  background(200);\n\n  // move the camera along its local axes\n  cam.move(delta, delta, 0);\n\n  // every 100 frames, switch direction\n  if (frameCount % 150 === 0) {\n    delta *= -1;\n  }\n\n  translate(-10, -10, 0);\n  box(50, 8, 50);\n  translate(15, 15, 0);\n  box(50, 8, 50);\n  translate(15, 15, 0);\n  box(50, 8, 50);\n  translate(15, 15, 0);\n  box(50, 8, 50);\n  translate(15, 15, 0);\n  box(50, 8, 50);\n  translate(15, 15, 0);\n  box(50, 8, 50);\n}\n</code>\n</div>"],
17580          "alt": "camera view moves along a series of 3D boxes, maintaining the same\norientation throughout the move",
17581          "class": "p5.Camera",
17582          "module": "Lights, Camera",
17583          "submodule": "Camera"
17584        }, {
17585          "file": "src/webgl/p5.Camera.js",
17586          "line": 823,
17587          "description": "<p>Set camera position in world-space while maintaining current camera\norientation.</p>\n",
17588          "itemtype": "method",
17589          "name": "setPosition",
17590          "params": [{
17591            "name": "x",
17592            "description": "<p>x position of a point in world space</p>\n",
17593            "type": "Number"
17594          }, {
17595            "name": "y",
17596            "description": "<p>y position of a point in world space</p>\n",
17597            "type": "Number"
17598          }, {
17599            "name": "z",
17600            "description": "<p>z position of a point in world space</p>\n",
17601            "type": "Number"
17602          }],
17603          "example": ["\n<div>\n<code>\n// press '1' '2' or '3' keys to set camera position\n\nlet cam;\n\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  normalMaterial();\n  cam = createCamera();\n}\n\nfunction draw() {\n  background(200);
17603\n\n  // '1' key\n  if (keyIsDown(49)) {\n    cam.setPosition(30, 0, 80);\n  }\n  // '2' key\n  if (keyIsDown(50)) {\n    cam.setPosition(0, 0, 80);\n  }\n  // '3' key\n  if (keyIsDown(51)) {\n    cam.setPosition(-30, 0, 80);\n  }\n\n  box(20);\n}\n</code>\n</div>"],
17604          "alt": "camera position changes as the user presses keys, altering view of a 3D box",
17605          "class": "p5.Camera",
17606          "module": "Lights, Camera",
17607          "submodule": "Camera"
17608        }, {
17609          "file": "src/webgl/p5.Camera.js",
17610          "line": 1088,
17611          "description": "<p>Sets rendererGL&#39;s current camera to a p5.Camera object.  Allows switching\nbetween multiple cameras.</p>\n",
17612          "itemtype": "method",
17613          "name": "setCamera",
17614          "params": [{
17615            "name": "cam",
17616            "description": "<p>p5.Camera object</p>\n",
17617            "type": "p5.Camera"
17618          }],
17619          "example": ["\n<div>\n<code>\nlet cam1, cam2;\nlet currentCamera;\n\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  normalMaterial();\n\n  cam1 = createCamera();\n  cam2 = createCamera();\n  cam2.setPosition(30, 0, 50);\n  cam2.lookAt(0, 0, 0);\n  cam2.ortho();\n\n  // set variable for previously active camera:\n  currentCamera = 1;\n}\n\nfunction draw() {\n  background(200);\n\n  // camera 1:\n  cam1.lookAt(0, 0, 0);\n  cam1.setPosition(sin(frameCount / 60) * 200, 0, 100);\n\n  // every 100 frames, switch between the two cameras\n  if (frameCount % 100 === 0) {\n    if (currentCamera === 1) {\n      setCamera(cam1);\n      currentCamera = 0;\n    } else {\n      setCamera(cam2);\n      currentCamera = 1;\n    }\n  }\n\n  drawBoxes();\n}\n\nfunction drawBoxes() {\n  rotateX(frameCount * 0.01);\n  translate(-100, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n  translate(35, 0, 0);\n  box(20);\n}\n</code>\n</div>"],
17620          "alt": "Canvas switches between two camera views, each showing a series of spinning\n3D boxes.",
17621          "class": "p5",
17622          "module": "Lights, Camera",
17623          "submodule": "Camera"
17624        }, {
17625          "file": "src/webgl/p5.Geometry.js",
17626          "line": 50,
17627          "itemtype": "method",
17628          "name": "computeFaces",
17629          "chainable": 1,
17630          "class": "p5.Geometry",
17631          "module": "Lights, Camera"
17632        }, {
17633          "file": "src/webgl/p5.Geometry.js",
17634          "line": 92,
17635          "description": "<p>computes smooth normals per vertex as an average of each\nface.</p>\n",
17636          "itemtype": "method",
17637          "name": "computeNormals",
17638          "chainable": 1,
17639          "class": "p5.Geometry",
17640          "module": "Lights, Camera"
17641        }, {
17642          "file": "src/webgl/p5.Geometry.js",
17643          "line": 131,
17644          "description": "<p>Averages the vertex normals. Used in curved\nsurfaces</p>\n",
17645          "itemtype": "method",
17646          "name": "averageNormals",
17647          "chainable": 1,
17648          "class": "p5.Geometry",
17649          "module": "Lights, Camera"
17650        }, {
17651          "file": "src/webgl/p5.Geometry.js",
17652          "line": 152,
17653          "description": "<p>Averages pole normals.  Used in spherical primitives</p>\n",
17654          "itemtype": "method",
17655          "name": "averagePoleNormals",
17656          "chainable": 1,
17657          "class": "p5.Geometry",
17658          "module": "Lights, Camera"
17659        }, {
17660          "file": "src/webgl/p5.Geometry.js",
17661          "line": 245,
17662          "description": "<p>Modifies all vertices to be centered within the range -100 to 100.</p>\n",
17663          "itemtype": "method",
17664          "name": "normalize",
17665          "chainable": 1,
17666          "class": "p5.Geometry",
17667          "module": "Lights, Camera"
17668        }, {
17669          "file": "src/webgl/p5.RendererGL.js",
17670          "line": 216,
17671          "description": "<p>Set attributes for the WebGL Drawing context.\nThis is a way of adjusting ways that the WebGL\nrenderer works to fine-tune the display and performance.\nThis should be put in setup().\nThe available attributes are:\n<br>\nalpha - indicates if the canvas contains an alpha buffer\ndefault is true\n<br><br>\ndepth - indicates whether the drawing buffer has a depth buffer\nof at least 16 bits - default is true\n<br><br>\nstencil - indicates whether the drawing buffer has a stencil buffer\nof at least 8 bits\n<br><br>
17671\nantialias - indicates whether or not to perform anti-aliasing\ndefault is false\n<br><br>\npremultipliedAlpha - indicates that the page compositor will assume\nthe drawing buffer contains colors with pre-multiplied alpha\ndefault is false\n<br><br>\npreserveDrawingBuffer - if true the buffers will not be cleared and\nand will preserve their values until cleared or overwritten by author\n(note that p5 clears automatically on draw loop)\ndefault is true\n<br><br>\nperPixelLighting - if true, per-pixel lighting will be used in the\nlighting shader.\ndefault is false\n<br><br></p>\n",
17672          "itemtype": "method",
17673          "name": "setAttributes",
17674          "example": ["\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n}\n\nfunction draw() {\n  background(255);\n  push();\n  rotateZ(frameCount * 0.02);\n  rotateX(frameCount * 0.02);\n  rotateY(frameCount * 0.02);\n  fill(0, 0, 0);\n  box(50);\n  pop();\n}\n</code>\n</div>\n<br>\nNow with the antialias attribute set to true.\n<br>\n<div>\n<code>\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  setAttributes('antialias', true);\n}\n\nfunction draw() {\n  background(255);\n  push();\n  rotateZ(frameCount * 0.02);\n  rotateX(frameCount * 0.02);\n  rotateY(frameCount * 0.02);\n  fill(0, 0, 0);\n  box(50);\n  pop();\n}\n</code>\n</div>\n\n<div>\n<code>\n// press the mouse button to enable perPixelLighting\nfunction setup() {\n  createCanvas(100, 100, WEBGL);\n  noStroke();\n  fill(255);\n}\n\nvar lights = [\n  { c: '#f00', t: 1.12, p: 1.91, r: 0.2 },\n  { c: '#0f0', t: 1.21, p: 1.31, r: 0.2 },\n  { c: '#00f', t: 1.37, p: 1.57, r: 0.2 },\n  { c: '#ff0', t: 1.12, p: 1.91, r: 0.7 },\n  { c: '#0ff', t: 1.21, p: 1.31, r: 0.7 },\n  { c: '#f0f', t: 1.37, p: 1.57, r: 0.7 }\n];\n\nfunction draw() {\n  var t = millis() / 1000 + 1000;\n  background(0);\n  directionalLight(color('#222'), 1, 1, 1);\n\n  for (var i = 0; i < lights.length; i++) {\n    var light = lights[i];\n    pointLight(\n      color(light.c),\n      p5.Vector.fromAngles(t * light.t, t * light.p, width * light.r)\n    );\n  }\n\n  specularMaterial(255);\n  sphere(width * 0.1);\n\n  rotateX(t * 0.77);\n  rotateY(t * 0.83);\n  rotateZ(t * 0.91);\n  torus(width * 0.3, width * 0.07, 24, 10);\n}\n\nfunction mousePressed() {\n  setAttributes('perPixelLighting', true);\n  noStroke();\n  fill(255);\n}\nfunction mouseReleased() {\n  setAttributes('perPixelLighting', false);\n  noStroke();\n  fill(255);\n}\n</code>\n</div>"],
17675          "alt": "a rotating cube with smoother edges",
17676          "class": "p5",
17677          "module": "Rendering",
17678          "submodule": "Rendering",
17679          "overloads": [{
17680            "line": 216,
17681            "params": [{
17682              "name": "key",
17683              "description": "<p>Name of attribute</p>\n",
17684              "type": "String"
17685            }, {
17686              "name": "value",
17687              "description": "<p>New value of named attribute</p>\n",
17688              "type": "Boolean"
17689            }]
17690          }, {
17691            "line": 349,
17692            "params": [{
17693              "name": "obj",
17694              "description": "<p>object with key-value pairs</p>\n",
17695              "type": "Object"
17696            }]
17697          }]
17698        }, {
17699          "file": "src/webgl/p5.Shader.js",
17700          "line": 274,
17701          "description": "<p>Wrapper around gl.uniform functions.\nAs we store uniform info in the shader we can use that\nto do type checking on the supplied data and call\nthe appropriate function.</p>\n",
17702          "itemtype": "method",
17703          "name": "setUniform",
17704          "chainable": 1,
17705          "params": [{
17706            "name": "uniformName",
17707            "description": "<p>the name of the uniform in the\nshader program</p>\n",
17708            "type": "String"
17709          }, {
17710            "name": "data",
17711            "description": "<p>the data to be associated\nwith that uniform; type varies (could be a single numerical value, array,\nmatrix, or texture / sampler reference)</p>\n",
17712            "type": "Object|Number|Boolean|Number[]"
17713          }],
17714          "class": "p5.Shader",
17715          "module": "Lights, Camera",
17716          "submodule": "Shaders"
17717        }, {
17718          "file": "lib/addons/p5.dom.js",
17719          "line": 40,
17720          "description": "<p>Searches the page for an element with the given ID, class, or tag name (using the &#39;#&#39; or &#39;.&#39;\nprefixes to specify an ID or class respectively, and none for a tag) and returns it as\na <a href=\"#/p5.Element\">p5.Element</a>. If a class or tag name is given with more than 1 element,\nonly the first element will be returned.\nThe DOM node itself can be accessed with .elt.\nReturns null if none found. You can also specify a container to search within.</p>\n",
17721          "itemtype": "method",
17722          "name": "select",
17723          "params": [{
17724            "name": "name",
17725            "description": "<p>id, class, or tag name of element to search for</p>\n",
17726            "type": "String"
17727          }, {
17728            "name": "container",
17729            "description": "<p>id, <a href=\"#/p5.Element\">p5.Element</a>, or\n                                            HTML element to search within</p>\n",
17730            "type": "String|p5.Element|HTMLElement",
17731            "optional": true
17732          }],
17733          "return": {
17734            "description": "<a href=\"#/p5.Element\">p5.Element</a> containing node found",
17735            "type": "p5.Element|null"
17736          },
17737          "example": ["\n<div ><code class='norender'>\nfunction setup() {\n  createCanvas(100, 100);\n  //translates canvas 50px down\n  select('canvas').position(100, 100);\n}\n</code></div>\n<div><code class='norender'>\n// these are all valid calls to select()\nvar a = select('#moo');\nvar b = select('#blah', '#myContainer');\nvar c, e;\nif (b) {\n  c = select('#foo', b);\n}\nvar d = document.getElementById('beep');\nif (d) {\n  e = select('p', d);\n}\n[a, b, c, d, e]; // unused\n</code></div>\n"],
17738          "class": "p5",
17739          "module": "p5.dom",
17740          "submodule": "p5.dom"
17741        }, {
17742          "file": "lib/addons/p5.dom.js",
17743          "line": 107,
17744          "description": "<p>Searches the page for elements with the given class or tag name (using the &#39;.&#39; prefix\nto specify a class and no prefix for a tag) and returns them as <a href=\"#/p5.Element\">p5.Element</a>s\nin an array.\nThe DOM node itself can be accessed with .elt.\nReturns an empty array if none found.\nYou can also specify a container to search within.</p>\n",
17745          "itemtype": "method",
17746          "name": "selectAll",
17747          "params": [{
17748            "name": "name",
17749            "description": "<p>class or tag name of elements to search for</p>\n",
17750            "type": "String"
17751          }, {
17752            "name": "container",
17753            "description": "<p>id, <a href=\"#/p5.Element\">p5.Element</a>, or HTML element to search within</p>\n",
17754            "type": "String",
17755            "optional": true
17756          }],
17757          "return": {
17758            "description": "Array of <a href=\"#/p5.Element\">p5.Element</a>s containing nodes found",
17759            "type": "p5.Element[]"
17760          },
17761          "example": ["\n<div class='norender'><code>\nfunction setup() {\n  createButton('btn');\n  createButton('2nd btn');\n  createButton('3rd btn');\n  var buttons = selectAll('button');\n\n  for (var i = 0; i < buttons.length;
17761 i++) {\n    buttons[i].size(100, 100);\n  }\n}\n</code></div>\n<div class='norender'><code>\n// these are all valid calls to selectAll()\nvar a = selectAll('.moo');\na = selectAll('div');\na = selectAll('button', '#myContainer');\n\nvar d = select('#container');\na = selectAll('p', d);\n\nvar f = document.getElementById('beep');\na = select('.blah', f);\n\na; // unused\n</code></div>\n"],
17762          "class": "p5",
17763          "module": "p5.dom",
17764          "submodule": "p5.dom"
17765        }, {
17766          "file": "lib/addons/p5.dom.js",
17767          "line": 168,
17768          "description": "<p>Helper function for select and selectAll</p>\n",
17769          "class": "p5",
17770          "module": "p5.dom",
17771          "submodule": "p5.dom"
17772        }, {
17773          "file": "lib/addons/p5.dom.js",
17774          "line": 184,
17775          "description": "<p>Helper function for getElement and getElements.</p>\n",
17776          "class": "p5",
17777          "module": "p5.dom",
17778          "submodule": "p5.dom"
17779        }, {
17780          "file": "lib/addons/p5.dom.js",
17781          "line": 218,
17782          "description": "<p>Removes all elements created by p5, except any canvas / graphics\nelements created by <a href=\"#/p5/createCanvas\">createCanvas</a> or <a href=\"#/p5/createGraphics\">createGraphics</a>.\nEvent handlers are removed, and element is removed from the DOM.</p>\n",
17783          "itemtype": "method",
17784          "name": "removeElements",
17785          "example": ["\n<div class='norender'><code>\nfunction setup() {\n  createCanvas(100, 100);\n  createDiv('this is some text');\n  createP('this is a paragraph');\n}\nfunction mousePressed() {\n  removeElements(); // this will remove the div and p, not canvas\n}\n</code></div>\n"],
17786          "class": "p5",
17787          "module": "p5.dom",
17788          "submodule": "p5.dom"
17789        }, {
17790          "file": "lib/addons/p5.dom.js",
17791          "line": 245,
17792          "description": "<p>The .<a href=\"#/p5.Element/changed\">changed()</a> function is called when the value of an\nelement changes.\nThis can be used to attach an element specific event listener.</p>\n",
17793          "itemtype": "method",
17794          "name": "changed",
17795          "params": [{
17796            "name": "fxn",
17797            "description": "<p>function to be fired when the value of\n                               an element changes.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
17798            "type": "Function|Boolean"
17799          }],
17800          "chainable": 1,
17801          "example": ["\n<div><code>\nvar sel;\n\nfunction setup() {\n  textAlign(CENTER);\n  background(200);\n  sel = createSelect();\n  sel.position(10, 10);\n  sel.option('pear');\n  sel.option('kiwi');\n  sel.option('grape');\n  sel.changed(mySelectEvent);\n}\n\nfunction mySelectEvent() {\n  var item = sel.value();\n  background(200);\n  text(\"it's a \" + item + '!', 50, 50);\n}\n</code></div>\n\n<div><code>\nvar checkbox;\nvar cnv;\n\nfunction setup() {\n  checkbox = createCheckbox(' fill');\n  checkbox.changed(changeFill);\n  cnv = createCanvas(100, 100);\n  cnv.position(0, 30);\n  noFill();\n}\n\nfunction draw() {\n  background(200);\n  ellipse(50, 50, 50, 50);\n}\n\nfunction changeFill() {\n  if (checkbox.checked()) {\n    fill(0);\n  } else {\n    noFill();\n  }\n}\n</code></div>"],
17802          "alt": "dropdown: pear, kiwi, grape. When selected text \"its a\" + selection shown.",
17803          "class": "p5",
17804          "module": "p5.dom",
17805          "submodule": "p5.dom"
17806        }, {
17807          "file": "lib/addons/p5.dom.js",
17808          "line": 313,
17809          "description": "<p>The .<a href=\"#/p5.Element/input\">input()</a> function is called when any user input is\ndetected with an element. The input event is often used\nto detect keystrokes in a input element, or changes on a\nslider element. This can be used to attach an element specific\nevent listener.</p>\n",
17810          "itemtype": "method",
17811          "name": "input",
17812          "params": [{
17813            "name": "fxn",
17814            "description": "<p>function to be fired when any user input is\n                               detected within the element.\n                               if <code>false</code> is passed instead, the previously\n                               firing function will no longer fire.</p>\n",
17815            "type": "Function|Boolean"
17816          }],
17817          "chainable": 1,
17818          "example": ["\n<div class='norender'><code>\n// Open your console to see the output\nfunction setup() {\n  var inp = createInput('');\n  inp.input(myInputEvent);\n}\n\nfunction myInputEvent() {\n  console.log('you are typing: ', this.value());\n}\n</code></div>"],
17819          "alt": "no display.",
17820          "class": "p5",
17821          "module": "p5.dom",
17822          "submodule": "p5.dom"
17823        }, {
17824          "file": "lib/addons/p5.dom.js",
17825          "line": 348,
17826          "description": "<p>Helpers for create methods.</p>\n",
17827          "class": "p5",
17828          "module": "p5.dom",
17829          "submodule": "p5.dom"
17830        }, {
17831          "file": "lib/addons/p5.dom.js",
17832          "line": 361,
17833          "description": "<p>Creates a &lt;div&gt;&lt;/div&gt; element in the DOM with given inner HTML.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n",
17834          "itemtype": "method",
17835          "name": "createDiv",
17836          "params": [{
17837            "name": "html",
17838            "description": "<p>inner HTML for element created</p>\n",
17839            "type": "String",
17840            "optional": true
17841          }],
17842          "return": {
17843            "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created node",
17844            "type": "p5.Element"
17845          },
17846          "example": ["\n<div class='norender'><code>\ncreateDiv('this is some text');\n</code></div>"],
17847          "class": "p5",
17848          "module": "p5.dom",
17849          "submodule": "p5.dom"
17850        }, {
17851          "file": "lib/addons/p5.dom.js",
17852          "line": 375,
17853          "description": "<p>Creates a &lt;p&gt;&lt;/p&gt; element in the DOM with given inner HTML. Used\nfor paragraph length text.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n",
17854          "itemtype": "method",
17855          "name": "createP",
17856          "params": [{
17857            "name": "html",
17858            "description": "<p>inner HTML for element created</p>\n",
17859            "type": "String",
17860            "optional": true
17861          }],
17862          "return": {
17863            "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created node",
17864            "type": "p5.Element"
17865          },
17866          "example": ["\n<div class='norender'><code>\ncreateP('this is some text');\n</code></div>"],
17867          "class": "p5",
17868          "module": "p5.dom",
17869          "submodule": "p5.dom"
17870        }, {
17871          "file": "lib/addons/p5.dom.js",
17872          "line": 390,
17873          "description": "<p>Creates a &lt;span&gt;&lt;/span&gt; element in the DOM with given inner HTML.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n",
17874          "itemtype": "method",
17875          "name": "createSpan",
17876          "params": [{
17877            "name": "html",
17878            "description": "<p>inner HTML for element created</p>\n",
17879            "type": "String",
17880            "optional": true
17881          }],
17882          "return": {
17883            "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created node",
17884            "type": "p5.Element"
17885          },
17886          "example": ["\n<div class='norender'><code>\ncreateSpan('this is some text');\n</code></div>"],
17887          "class": "p5",
17888          "module": "p5.dom",
17889          "submodule": "p5.dom"
17890        }, {
17891          "file": "lib/addons/p5.dom.js",
17892          "line": 413,
17893          "description": "<p>Creates an &lt;img&gt; element in the DOM with given src and\nalternate text.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n",
17894          "itemtype": "method",
17895          "name": "createImg",
17896          "return": {
17897            "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created node",
17898            "type": "p5.Element"
17899          },
17900          "example": ["\n<div class='norender'><code>\ncreateImg('http://p5js.org/img/asterisk-01.png');\n</code></div>"],
17901          "class": "p5",
17902          "module": "p5.dom",
17903          "submodule": "p5.dom",
17904          "overloads": [{
17905            "line": 413,
17906            "params": [{
17907              "name": "src",
17908              "description": "<p>src path or url for image</p>\n",
17909              "type": "String"
17910            }, {
17911              "name": "alt",
17912              "description": "<p>alternate text to be used if image does not load</p>\n",
17913              "type": "String",
17914              "optional": true
17915            }, {
17916              "name": "successCallback",
17917              "description": "<p>callback to be called once image data is loaded</p>\n",
17918              "type": "Function",
17919              "optional": true
17920            }],
17921            "return": {
17922              "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created node",
17923              "type": "p5.Element"
17924            }
17925          }, {
17926            "line": 429,
17927            "params": [{
17928              "name": "src",
17929              "description": "",
17930              "type": "String"
17931            }, {
17932              "name": "successCallback",
17933              "description": "",
17934              "type": "Function"
17935            }],
17936            "return": {
17937              "description": "",
17938              "type": "Object|p5.Element"
17939            }
17940          }]
17941        }, {
17942          "file": "lib/addons/p5.dom.js",
17943          "line": 462,
17944          "description": "<p>Creates an &lt;a&gt;&lt;/a&gt; element in the DOM for including a hyperlink.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n",
17945          "itemtype": "method",
17946          "name": "createA",
17947          "params": [{
17948            "name": "href",
17949            "description": "<p>url of page to link to</p>\n",
17950            "type": "String"
17951          }, {
17952            "name": "html",
17953            "description": "<p>inner html of link element to display</p>\n",
17954            "type": "String"
17955          }, {
17956            "name": "target",
17957            "description": "<p>target where new link should open,\n                            could be _blank, _self, _parent, _top.</p>\n",
17958            "type": "String",
17959            "optional": true
17960          }],
17961          "return": {
17962            "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created node",
17963            "type": "p5.Element"
17964          },
17965          "example": ["\n<div class='norender'><code>\ncreateA('http://p5js.org/', 'this is a link');\n</code></div>"],
17966          "class": "p5",
17967          "module": "p5.dom",
17968          "submodule": "p5.dom"
17969        }, {
17970          "file": "lib/addons/p5.dom.js",
17971          "line": 487,
17972          "class": "p5",
17973          "module": "p5.dom",
17974          "submodule": "p5.dom"
17975        }, {
17976          "file": "lib/addons/p5.dom.js",
17977          "line": 489,
17978          "description": "<p>Creates a slider &lt;input&gt;&lt;/input&gt; element in the DOM.\nUse .size() to set the display length of the slider.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n",
17979          "itemtype": "method",
17980          "name": "createSlider",
17981          "params": [{
17982            "name": "min",
17983            "description": "<p>minimum value of the slider</p>\n",
17984            "type": "Number"
17985          }, {
17986            "name": "max",
17987            "description": "<p>maximum value of the slider</p>\n",
17988            "type": "Number"
17989          }, {
17990            "name": "value",
17991            "description": "<p>default value of the slider</p>\n",
17992            "type": "Number",
17993            "optional": true
17994          }, {
17995            "name": "step",
17996            "description": "<p>step size for each tick of the slider (if step is set to 0, the slider will move continuously from the minimum to the maximum value)</p>\n",
17997            "type": "Number",
17998            "optional": true
17999          }],
18000          "return": {
18001            "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created node",
18002            "type": "p5.Element"
18003          },
18004          "example": ["\n<div><code>\nvar slider;\nfunction setup() {\n  slider = createSlider(0, 255, 100);\n  slider.position(10, 10);\n  slider.style('width', '80px');\n}\n\nfunction draw() {\n  var val = slider.value();\n  background(val);\n}\n</code></div>\n\n<div><code>\nvar slider;\nfunction setup() {\n  colorMode(HSB);\n  slider = createSlider(0, 360, 60, 40);\n  slider.position(10, 10);\n  slider.style('width', '80px');\n}\n\nfunction draw() {\n  var val = slider.value();
18004\n  background(val, 100, 100, 1);\n}\n</code></div>"],
18005          "class": "p5",
18006          "module": "p5.dom",
18007          "submodule": "p5.dom"
18008        }, {
18009          "file": "lib/addons/p5.dom.js",
18010          "line": 546,
18011          "description": "<p>Creates a &lt;button&gt;&lt;/button&gt; element in the DOM.\nUse .size() to set the display size of the button.\nUse .mousePressed() to specify behavior on press.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n",
18012          "itemtype": "method",
18013          "name": "createButton",
18014          "params": [{
18015            "name": "label",
18016            "description": "<p>label displayed on the button</p>\n",
18017            "type": "String"
18018          }, {
18019            "name": "value",
18020            "description": "<p>value of the button</p>\n",
18021            "type": "String",
18022            "optional": true
18023          }],
18024          "return": {
18025            "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created node",
18026            "type": "p5.Element"
18027          },
18028          "example": ["\n<div class='norender'><code>\nvar button;\nfunction setup() {\n  createCanvas(100, 100);\n  background(0);\n  button = createButton('click me');\n  button.position(19, 19);\n  button.mousePressed(changeBG);\n}\n\nfunction changeBG() {\n  var val = random(255);\n  background(val);\n}\n</code></div>"],
18029          "class": "p5",
18030          "module": "p5.dom",
18031          "submodule": "p5.dom"
18032        }, {
18033          "file": "lib/addons/p5.dom.js",
18034          "line": 582,
18035          "description": "<p>Creates a checkbox &lt;input&gt;&lt;/input&gt; element in the DOM.\nCalling .checked() on a checkbox returns if it is checked or not</p>\n",
18036          "itemtype": "method",
18037          "name": "createCheckbox",
18038          "params": [{
18039            "name": "label",
18040            "description": "<p>label displayed after checkbox</p>\n",
18041            "type": "String",
18042            "optional": true
18043          }, {
18044            "name": "value",
18045            "description": "<p>value of the checkbox; checked is true, unchecked is false</p>\n",
18046            "type": "Boolean",
18047            "optional": true
18048          }],
18049          "return": {
18050            "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created node",
18051            "type": "p5.Element"
18052          },
18053          "example": ["\n<div class='norender'><code>\nvar checkbox;\n\nfunction setup() {\n  checkbox = createCheckbox('label', false);\n  checkbox.changed(myCheckedEvent);\n}\n\nfunction myCheckedEvent() {\n  if (this.checked()) {\n    console.log('Checking!');\n  } else {\n    console.log('Unchecking!');\n  }\n}\n</code></div>"],
18054          "class": "p5",
18055          "module": "p5.dom",
18056          "submodule": "p5.dom"
18057        }, {
18058          "file": "lib/addons/p5.dom.js",
18059          "line": 650,
18060          "description": "<p>Creates a dropdown menu &lt;select&gt;&lt;/select&gt; element in the DOM.\nIt also helps to assign select-box methods to <a href=\"#/p5.Element\">p5.Element</a> when selecting existing select box</p>\n",
18061          "itemtype": "method",
18062          "name": "createSelect",
18063          "return": {
18064            "description": "",
18065            "type": "p5.Element"
18066          },
18067          "example": ["\n<div><code>\nvar sel;\n\nfunction setup() {\n  textAlign(CENTER);\n  background(200);\n  sel = createSelect();\n  sel.position(10, 10);\n  sel.option('pear');\n  sel.option('kiwi');\n  sel.option('grape');\n  sel.changed(mySelectEvent);\n}\n\nfunction mySelectEvent() {\n  var item = sel.value();\n  background(200);\n  text('it is a' + item + '!', 50, 50);\n}\n</code></div>"],
18068          "class": "p5",
18069          "module": "p5.dom",
18070          "submodule": "p5.dom",
18071          "overloads": [{
18072            "line": 650,
18073            "params": [{
18074              "name": "multiple",
18075              "description": "<p>true if dropdown should support multiple selections</p>\n",
18076              "type": "Boolean",
18077              "optional": true
18078            }],
18079            "return": {
18080              "description": "",
18081              "type": "p5.Element"
18082            }
18083          }, {
18084            "line": 678,
18085            "params": [{
18086              "name": "existing",
18087              "description": "<p>DOM select element</p>\n",
18088              "type": "Object"
18089            }],
18090            "return": {
18091              "description": "",
18092              "type": "p5.Element"
18093            }
18094          }]
18095        }, {
18096          "file": "lib/addons/p5.dom.js",
18097          "line": 754,
18098          "description": "<p>Creates a radio button &lt;input&gt;&lt;/input&gt; element in the DOM.\nThe .option() method can be used to set options for the radio after it is\ncreated. The .value() method will return the currently selected option.</p>\n",
18099          "itemtype": "method",
18100          "name": "createRadio",
18101          "params": [{
18102            "name": "divId",
18103            "description": "<p>the id and name of the created div and input field respectively</p>\n",
18104            "type": "String",
18105            "optional": true
18106          }],
18107          "return": {
18108            "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created node",
18109            "type": "p5.Element"
18110          },
18111          "example": ["\n<div><code>\nvar radio;\n\nfunction setup() {\n  radio = createRadio();\n  radio.option('black');\n  radio.option('white');\n  radio.option('gray');\n  radio.style('width', '60px');\n  textAlign(CENTER);\n  fill(255, 0, 0);\n}
18111\n\nfunction draw() {\n  var val = radio.value();\n  background(val);\n  text(val, width / 2, height / 2);\n}\n</code></div>\n<div><code>\nvar radio;\n\nfunction setup() {\n  radio = createRadio();\n  radio.option('apple', 1);\n  radio.option('bread', 2);\n  radio.option('juice', 3);\n  radio.style('width', '60px');\n  textAlign(CENTER);\n}\n\nfunction draw() {\n  background(200);\n  var val = radio.value();\n  if (val) {\n    text('item cost is $' + val, width / 2, height / 2);\n  }\n}\n</code></div>"],
18112          "class": "p5",
18113          "module": "p5.dom",
18114          "submodule": "p5.dom"
18115        }, {
18116          "file": "lib/addons/p5.dom.js",
18117          "line": 892,
18118          "description": "<p>Creates a colorPicker element in the DOM for color input.\nThe .value() method will return a hex string (#rrggbb) of the color.\nThe .color() method will return a p5.Color object with the current chosen color.</p>\n",
18119          "itemtype": "method",
18120          "name": "createColorPicker",
18121          "params": [{
18122            "name": "value",
18123            "description": "<p>default color of element</p>\n",
18124            "type": "String|p5.Color",
18125            "optional": true
18126          }],
18127          "return": {
18128            "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created node",
18129            "type": "p5.Element"
18130          },
18131          "example": ["\n<div>\n<code>\nvar inp1, inp2;\nfunction setup() {\n  createCanvas(100, 100);\n  background('grey');\n  inp1 = createColorPicker('#ff0000');\n  inp2 = createColorPicker(color('yellow'));\n  inp1.input(setShade1);\n  inp2.input(setShade2);\n  setMidShade();\n}\n\nfunction setMidShade() {\n  // Finding a shade between the two\n  var commonShade = lerpColor(inp1.color(), inp2.color(), 0.5);\n  fill(commonShade);\n  rect(20, 20, 60, 60);\n}\n\nfunction setShade1() {\n  setMidShade();
18131\n  console.log('You are choosing shade 1 to be : ', this.value());\n}\nfunction setShade2() {\n  setMidShade();\n  console.log('You are choosing shade 2 to be : ', this.value());\n}\n</code>\n</div>"],
18132          "class": "p5",
18133          "module": "p5.dom",
18134          "submodule": "p5.dom"
18135        }, {
18136          "file": "lib/addons/p5.dom.js",
18137          "line": 966,
18138          "description": "<p>Creates an &lt;input&gt;&lt;/input&gt; element in the DOM for text input.\nUse .<a href=\"#/p5.Element/size\">size()</a> to set the display length of the box.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n",
18139          "itemtype": "method",
18140          "name": "createInput",
18141          "params": [{
18142            "name": "value",
18143            "description": "<p>default value of the input box</p>\n",
18144            "type": "String",
18145            "optional": true
18146          }, {
18147            "name": "type",
18148            "description": "<p>type of text, ie text, password etc. Defaults to text</p>\n",
18149            "type": "String",
18150            "optional": true
18151          }],
18152          "return": {
18153            "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created node",
18154            "type": "p5.Element"
18155          },
18156          "example": ["\n<div class='norender'><code>\nfunction setup() {\n  var inp = createInput('');\n  inp.input(myInputEvent);\n}\n\nfunction myInputEvent() {\n  console.log('you are typing: ', this.value());\n}\n</code></div>"],
18157          "class": "p5",
18158          "module": "p5.dom",
18159          "submodule": "p5.dom"
18160        }, {
18161          "file": "lib/addons/p5.dom.js",
18162          "line": 996,
18163          "description": "<p>Creates an &lt;input&gt;&lt;/input&gt; element in the DOM of type &#39;file&#39;.\nThis allows users to select local files for use in a sketch.</p>\n",
18164          "itemtype": "method",
18165          "name": "createFileInput",
18166          "params": [{
18167            "name": "callback",
18168            "description": "<p>callback function for when a file loaded</p>\n",
18169            "type": "Function",
18170            "optional": true
18171          }, {
18172            "name": "multiple",
18173            "description": "<p>optional to allow multiple files selected</p>\n",
18174            "type": "String",
18175            "optional": true
18176          }],
18177          "return": {
18178            "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created DOM element",
18179            "type": "p5.Element"
18180          },
18181          "example": ["\n<div class='norender'><code>\nvar input;\nvar img;\n\nfunction setup() {\n  input = createFileInput(handleFile);\n  input.position(0, 0);\n}\n\nfunction draw() {\n  if (img) {\n    image(img, 0, 0, width, height);\n  }\n}\n\nfunction handleFile(file) {\n  print(file);\n  if (file.type === 'image') {\n    img = createImg(file.data);\n    img.hide();\n  }\n}\n</code></div>"],
18182          "class": "p5",
18183          "module": "p5.dom",
18184          "submodule": "p5.dom"
18185        }, {
18186          "file": "lib/addons/p5.dom.js",
18187          "line": 1066,
18188          "class": "p5",
18189          "module": "p5.dom",
18190          "submodule": "p5.dom"
18191        }, {
18192          "file": "lib/addons/p5.dom.js",
18193          "line": 1108,
18194          "description": "<p>Creates an HTML5 &lt;video&gt; element in the DOM for simple playback\nof audio/video. Shown by default, can be hidden with .<a href=\"#/p5.Element/hide\">hide()</a>\nand drawn into canvas using video(). Appends to the container\nnode if one is specified, otherwise appends to body. The first parameter\ncan be either a single string path to a video file, or an array of string\npaths to different formats of the same video. This is useful for ensuring\nthat your video can play across different browsers, as each supports\ndifferent formats. See <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats'>this\npage</a> for further information about supported formats.</p>\n",
18195          "itemtype": "method",
18196          "name": "createVideo",
18197          "params": [{
18198            "name": "src",
18199            "description": "<p>path to a video file, or array of paths for\n                            supporting different browsers</p>\n",
18200            "type": "String|String[]"
18201          }, {
18202            "name": "callback",
18203            "description": "<p>callback function to be called upon\n                            &#39;canplaythrough&#39; event fire, that is, when the\n                            browser can play the media, and estimates that\n                            enough data has been loaded to play the media\n                            up to its end without having to stop for\n                            further buffering of content</p>\n",
18204            "type": "Function",
18205            "optional": true
18206          }],
18207          "return": {
18208            "description": "pointer to video <a href=\"#/p5.Element\">p5.Element</a>",
18209            "type": "p5.MediaElement"
18210          },
18211          "example": ["\n<div><code>\nvar vid;\nfunction setup() {\n  vid = createVideo(['small.mp4', 'small.ogv', 'small.webm'], vidLoad);\n}\n\n// This function is called when the video loads\nfunction vidLoad() {\n  vid.play();\n}\n</code></div>"],
18212          "class": "p5",
18213          "module": "p5.dom",
18214          "submodule": "p5.dom"
18215        }, {
18216          "file": "lib/addons/p5.dom.js",
18217          "line": 1147,
18218          "class": "p5",
18219          "module": "p5.dom",
18220          "submodule": "p5.dom"
18221        }, {
18222          "file": "lib/addons/p5.dom.js",
18223          "line": 1149,
18224          "description": "<p>Creates a hidden HTML5 &lt;audio&gt; element in the DOM for simple audio\nplayback. Appends to the container node if one is specified,\notherwise appends to body. The first parameter\ncan be either a single str
18224ing path to a audio file, or an array of string\npaths to different formats of the same audio. This is useful for ensuring\nthat your audio can play across different browsers, as each supports\ndifferent formats. See <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats'>this\npage for further information about supported formats</a>.</p>\n",
18225          "itemtype": "method",
18226          "name": "createAudio",
18227          "params": [{
18228            "name": "src",
18229            "description": "<p>path to an audio file, or array of paths\n                            for supporting different browsers</p>\n",
18230            "type": "String|String[]",
18231            "optional": true
18232          }, {
18233            "name": "callback",
18234            "description": "<p>callback function to be called upon\n                            &#39;canplaythrough&#39; event fire, that is, when the\n                            browser can play the media, and estimates that\n                            enough data has been loaded to play the media\n                            up to its end without having to stop for\n                            further buffering of content</p>\n",
18235            "type": "Function",
18236            "optional": true
18237          }],
18238          "return": {
18239            "description": "pointer to audio <a href=\"#/p5.Element\">p5.Element</a>",
18240            "type": "p5.MediaElement"
18241          },
18242          "example": ["\n<div><code>\nvar ele;\nfunction setup() {\n  ele = createAudio('assets/beat.mp3');\n\n  // here we set the element to autoplay\n  // The element will play as soon\n  // as it is able to do so.\n  ele.autoplay(true);\n}\n</code></div>"],
18243          "class": "p5",
18244          "module": "p5.dom",
18245          "submodule": "p5.dom"
18246        }, {
18247          "file": "lib/addons/p5.dom.js",
18248          "line": 1187,
18249          "class": "p5",
18250          "module": "p5.dom",
18251          "submodule": "p5.dom"
18252        }, {
18253          "file": "lib/addons/p5.dom.js",
18254          "line": 1189,
18255          "itemtype": "property",
18256          "name": "VIDEO",
18257          "type": "String",
18258          "final": 1,
18259          "category": ["Constants"],
18260          "class": "p5",
18261          "module": "p5.dom",
18262          "submodule": "p5.dom"
18263        }, {
18264          "file": "lib/addons/p5.dom.js",
18265          "line": 1195,
18266          "itemtype": "property",
18267          "name": "AUDIO",
18268          "type": "String",
18269          "final": 1,
18270          "category": ["Constants"],
18271          "class": "p5",
18272          "module": "p5.dom",
18273          "submodule": "p5.dom"
18274        }, {
18275          "file": "lib/addons/p5.dom.js",
18276          "line": 1232,
18277          "description": "<p>Creates a new HTML5 &lt;video&gt; element that contains the audio/video\nfeed from a webcam. The element is separate from the canvas and is\ndisplayed by default. The element can be hidden using .<a href=\"#/p5.Element/hide\">hide()</a>. The feed\ncan be drawn onto the canvas using <a href=\"#/p5/image\">image()</a>. The loadedmetadata property can\nbe used to detect when the element has fully loaded (see second example).</p>\n<p>More specific properties of the feed can be passing in a Constraints object.\nSee the\n<a href='http://w3c.github.io/mediacapture-main/getusermedia.html#media-track-constraints'> W3C\nspec</a> for possible properties. Note that not all of these are supported\nby all browsers.</p>\n<p>Security note: A new browser security specification requires that getUserMedia,\nwhich is behind <a href=\"#/p5/createCapture\">createCapture()</a>, only works when you&#39;re running the code locally,\nor on HTTPS. Learn more <a href='http://stackoverflow.com/questions/34197653/getusermedia-in-chrome-47-without-using-https'>here</a>\nand <a href='https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia'>here</a>.</p>",
18278          "itemtype": "method",
18279          "name": "createCapture",
18280          "params": [{
18281            "name": "type",
18282            "description": "<p>type of capture, either VIDEO or\n                                  AUDIO if none specified, default both,\n                                  or a Constraints object</p>\n",
18283            "type": "String|Constant|Object"
18284          }, {
18285            "name": "callback",
18286            "description": "<p>function to be called once\n                                  stream has loaded</p>\n",
18287            "type": "Function",
18288            "optional": true
18289          }],
18290          "return": {
18291            "description": "capture video <a href=\"#/p5.Element\">p5.Element</a>",
18292            "type": "p5.Element"
18293          },
18294          "example": ["\n<div class='norender notest'><code>\nvar capture;\n\nfunction setup() {\n  createCanvas(480, 480);\n  capture = createCapture(VIDEO);\n  capture.hide();\n}\n\nfunction draw() {\n  image(capture, 0, 0, width, width * capture.height / capture.width);\n  filter(INVERT);\n}\n</code></div>\n<div class='norender notest'><code>\nfunction setup() {\n  createCanvas(480, 120);\n  var constraints = {\n    video: {\n      mandatory: {\n        minWidth: 1280,\n        minHeight: 720\n      },\n      optional: [{ maxFrameRate: 10 }]\n    },\n    audio: true\n  };\n  createCapture(constraints, function(stream) {\n    console.log(stream);\n  });\n}\n</code></div>\n<code><div class='norender notest'>\nvar capture;\n\nfunction setup() {\n  createCanvas(640, 480);\n  capture = createCapture(VIDEO);\n}\nfunction draw() {\n  background(0);
18294\n  if (capture.loadedmetadata) {\n    var c = capture.get(0, 0, 100, 100);\n    image(c, 0, 0);\n  }\n}"],
18295          "class": "p5",
18296          "module": "p5.dom",
18297          "submodule": "p5.dom"
18298        }, {
18299          "file": "lib/addons/p5.dom.js",
18300          "line": 1368,
18301          "description": "<p>Creates element with given tag in the DOM with given content.\nAppends to the container node if one is specified, otherwise\nappends to body.</p>\n",
18302          "itemtype": "method",
18303          "name": "createElement",
18304          "params": [{
18305            "name": "tag",
18306            "description": "<p>tag for the new element</p>\n",
18307            "type": "String"
18308          }, {
18309            "name": "content",
18310            "description": "<p>html content to be inserted into the element</p>\n",
18311            "type": "String",
18312            "optional": true
18313          }],
18314          "return": {
18315            "description": "pointer to <a href=\"#/p5.Element\">p5.Element</a> holding created node",
18316            "type": "p5.Element"
18317          },
18318          "example": ["\n<div class='norender'><code>\ncreateElement('h2', 'im an h2 p5.element!');\n</code></div>"],
18319          "class": "p5",
18320          "module": "p5.dom",
18321          "submodule": "p5.dom"
18322        }, {
18323          "file": "lib/addons/p5.dom.js",
18324          "line": 1394,
18325          "description": "<p>Adds specified class to the element.</p>\n",
18326          "itemtype": "method",
18327          "name": "addClass",
18328          "params": [{
18329            "name": "class",
18330            "description": "<p>name of class to add</p>\n",
18331            "type": "String"
18332          }],
18333          "chainable": 1,
18334          "example": ["\n <div class='norender'><code>\n var div = createDiv('div');\n div.addClass('myClass');\n </code></div>"],
18335          "class": "p5.Element",
18336          "module": "p5.dom",
18337          "submodule": "p5.dom"
18338        }, {
18339          "file": "lib/addons/p5.dom.js",
18340          "line": 1421,
18341          "description": "<p>Removes specified class from the element.</p>\n",
18342          "itemtype": "method",
18343          "name": "removeClass",
18344          "params": [{
18345            "name": "class",
18346            "description": "<p>name of class to remove</p>\n",
18347            "type": "String"
18348          }],
18349          "chainable": 1,
18350          "example": ["\n <div class='norender'><code>\n // In this example, a class is set when the div is created\n // and removed when mouse is pressed. This could link up\n // with a CSS style rule to toggle style properties.\nvar div;\nfunction setup() {\n   div = createDiv('div');\n   div.addClass('myClass');\n }\nfunction mousePressed() {\n   div.removeClass('myClass');\n }\n </code></div>"],
18351          "class": "p5.Element",
18352          "module": "p5.dom",
18353          "submodule": "p5.dom"
18354        }, {
18355          "file": "lib/addons/p5.dom.js",
18356          "line": 1453,
18357          "description": "<p>Attaches the element  as a child to the parent specified.\n Accepts either a string ID, DOM node, or <a href=\"#/p5.Element\">p5.Element</a>.\n If no argument is specified, an array of children DOM nodes is returned.</p>\n",
18358          "itemtype": "method",
18359          "name": "child",
18360          "return": {
18361            "description": "an array of child nodes",
18362            "type": "Node[]"
18363          },
18364          "example": ["\n <div class='norender'><code>\n var div0 = createDiv('this is the parent');\n var div1 = createDiv('this is the child');\n div0.child(div1); // use p5.Element\n </code></div>\n <div class='norender'><code>\n var div0 = createDiv('this is the parent');\n var div1 = createDiv('this is the child');\n div1.id('apples');\n div0.child('apples'); // use id\n </code></div>\n <div class='norender notest'><code>\n // this example assumes there is a div already on the page\n // with id \"myChildDiv\"\n var div0 = createDiv('this is the parent');\n var elt = document.getElementById('myChildDiv');\n div0.child(elt);
18364 // use element from page\n </code></div>"],
18365          "class": "p5.Element",
18366          "module": "p5.dom",
18367          "submodule": "p5.dom",
18368          "overloads": [{
18369            "line": 1453,
18370            "params": [],
18371            "return": {
18372              "description": "an array of child nodes",
18373              "type": "Node[]"
18374            }
18375          }, {
18376            "line": 1481,
18377            "params": [{
18378              "name": "child",
18379              "description": "<p>the ID, DOM node, or <a href=\"#/p5.Element\">p5.Element</a>\n                        to add to the current element</p>\n",
18380              "type": "String|p5.Element",
18381              "optional": true
18382            }],
18383            "chainable": 1
18384          }]
18385        }, {
18386          "file": "lib/addons/p5.dom.js",
18387          "line": 1503,
18388          "description": "<p>Centers a p5 Element either vertically, horizontally,\nor both, relative to its parent or according to\nthe body if the Element has no parent. If no argument is passed\nthe Element is aligned both vertically and horizontally.</p>\n",
18389          "itemtype": "method",
18390          "name": "center",
18391          "params": [{
18392            "name": "align",
18393            "description": "<p>passing &#39;vertical&#39;, &#39;horizontal&#39; aligns element accordingly</p>\n",
18394            "type": "String",
18395            "optional": true
18396          }],
18397          "chainable": 1,
18398          "example": ["\n<div><code>\nfunction setup() {\n  var div = createDiv('').size(10, 10);\n  div.style('background-color', 'orange');\n  div.center();\n}\n</code></div>"],
18399          "class": "p5.Element",
18400          "module": "p5.dom",
18401          "submodule": "p5.dom"
18402        }, {
18403          "file": "lib/addons/p5.dom.js",
18404          "line": 1557,
18405          "description": "<p>If an argument is given, sets the inner HTML of the element,\n replacing any existing html. If true is included as a second\n argument, html is appended instead of replacing existing html.\n If no arguments are given, returns\n the inner HTML of the element.</p>\n",
18406          "itemtype": "method",
18407          "name": "html",
18408          "return": {
18409            "description": "the inner HTML of the element",
18410            "type": "String"
18411          },
18412          "example": ["\n <div class='norender'><code>\n var div = createDiv('').size(100, 100);\n div.html('hi');\n </code></div>\n <div class='norender'><code>\n var div = createDiv('Hello ').size(100, 100);\n div.html('World', true);\n </code></div>"],
18413          "class": "p5.Element",
18414          "module": "p5.dom",
18415          "submodule": "p5.dom",
18416          "overloads": [{
18417            "line": 1557,
18418            "params": [],
18419            "return": {
18420              "description": "the inner HTML of the element",
18421              "type": "String"
18422            }
18423          }, {
18424            "line": 1578,
18425            "params": [{
18426              "name": "html",
18427              "description": "<p>the HTML to be placed inside the element</p>\n",
18428              "type": "String",
18429              "optional": true
18430            }, {
18431              "name": "append",
18432              "description": "<p>whether to append HTML to existing</p>\n",
18433              "type": "Boolean",
18434              "optional": true
18435            }],
18436            "chainable": 1
18437          }]
18438        }, {
18439          "file": "lib/addons/p5.dom.js",
18440          "line": 1596,
18441          "description": "<p>Sets the position of the element relative to (0, 0) of the\n window. Essentially, set
18441s position:absolute and left and top\n properties of style. If no arguments given returns the x and y position\n of the element in an object.</p>\n",
18442          "itemtype": "method",
18443          "name": "position",
18444          "return": {
18445            "description": "the x and y position of the element in an object",
18446            "type": "Object"
18447          },
18448          "example": ["\n <div><code class='norender'>\n function setup() {\n   var cnv = createCanvas(100, 100);\n   // positions canvas 50px to the right and 100px\n   // below upper left corner of the window\n   cnv.position(50, 100);\n }\n </code></div>"],
18449          "class": "p5.Element",
18450          "module": "p5.dom",
18451          "submodule": "p5.dom",
18452          "overloads": [{
18453            "line": 1596,
18454            "params": [],
18455            "return": {
18456              "description": "the x and y position of the element in an object",
18457              "type": "Object"
18458            }
18459          }, {
18460            "line": 1615,
18461            "params": [{
18462              "name": "x",
18463              "description": "<p>x-position relative to upper left of window</p>\n",
18464              "type": "Number",
18465              "optional": true
18466            }, {
18467              "name": "y",
18468              "description": "<p>y-position relative to upper left of window</p>\n",
18469              "type": "Number",
18470              "optional": true
18471            }],
18472            "chainable": 1
18473          }]
18474        }, {
18475          "file": "lib/addons/p5.dom.js",
18476          "line": 1690,
18477          "description": "<p>Sets the given style (css) property (1st arg) of the element with the\ngiven value (2nd arg). If a single argument is given, .style()\nreturns the value of the given property; however, if the single argument\nis given in css syntax (&#39;text-align:center&#39;), .style() sets the css\nappropriatly. .style() also handles 2d and 3d css transforms. If\nthe 1st arg is &#39;rotate&#39;, &#39;translate&#39;, or &#39;position&#39;, the following arguments\naccept Numbers as values. (&#39;translate&#39;, 10, 100, 50);</p>\n",
18478          "itemtype": "method",
18479          "name": "style",
18480          "return": {
18481            "description": "value of property",
18482            "type": "String"
18483          },
18484          "example": ["\n<div><code class='norender'>\nvar myDiv = createDiv('I like pandas.');\nmyDiv.style('font-size', '18px');\nmyDiv.style('color', '#ff0000');\n</code></div>\n<div><code class='norender'>\nvar col = color(25, 23, 200, 50);\nvar button = createButton('button');\nbutton.style('background-color', col);\nbutton.position(10, 10);\n</code></div>\n<div><code class='norender'>\nvar myDiv = createDiv('I like lizards.');\nmyDiv.style('position', 20, 20);\nmyDiv.style('rotate', 45);\n</code></div>\n<div><code class='norender'>\nvar myDiv;\nfunction setup() {\n  background(200);\n  myDiv = createDiv('I like gray.');\n  myDiv.position(20, 20);\n}\n\nfunction draw() {\n  myDiv.style('font-size', mouseX + 'px');\n}\n</code></div>"],
18485          "class": "p5.Element",
18486          "module": "p5.dom",
18487          "submodule": "p5.dom",
18488          "overloads": [{
18489            "line": 1690,
18490            "params": [{
18491              "name": "property",
18492              "description": "<p>property to be set</p>\n",
18493              "type": "String"
18494            }],
18495            "return": {
18496              "description": "value of property",
18497              "type": "String"
18498            }
18499          }, {
18500            "line": 1732,
18501            "params": [{
18502              "name": "property",
18503              "description": "",
18504              "type": "String"
18505            }, {
18506              "name": "value",
18507              "description": "<p>value to assign to property (only String|Number for rotate/translate)</p>\n",
18508              "type": "String|Number|p5.Color"
18509            }, {
18510              "name": "value2",
18511              "description": "<p>position can take a 2nd value</p>\n",
18512              "type": "String|Number|p5.Color",
18513              "optional": true
18514            }, {
18515              "name": "value3",
18516              "description": "<p>translate can take a 2nd &amp; 3rd value</p>\n",
18517              "type": "String|Number|p5.Color",
18518              "optional": true
18519            }],
18520            "chainable": 1
18521          }]
18522        }, {
18523          "file": "lib/addons/p5.dom.js",
18524          "line": 1791,
18525          "description": "<p>Adds a new attribute or changes the value of an existing attribute\n on the specified element. If no value is specified, returns the\n value of the given attribute, or null if attribute is not set.</p>\n",
18526          "itemtype": "method",
18527          "name": "attribute",
18528          "return": {
18529            "description": "value of attribute",
18530            "type": "String"
18531          },
18532          "example": ["\n <div class='norender'><code>\n var myDiv = createDiv('I like pandas.');\n myDiv.attribute('align', 'center');\n </code></div>"],
18533          "class": "p5.Element",
18534          "module": "p5.dom",
18535          "submodule": "p5.dom",
18536          "overloads": [{
18537            "line": 1791,
18538            "params": [],
18539            "return": {
18540              "description": "value of attribute",
18541              "type": "String"
18542            }
18543          }, {
18544            "line": 1806,
18545            "params": [{
18546              "name": "attr",
18547              "description": "<p>attribute to set</p>\n",
18548              "type": "String"
18549            }, {
18550              "name": "value",
18551              "description": "<p>value to assign to attribute</p>\n",
18552              "type": "String"
18553            }],
18554            "chainable": 1
18555          }]
18556        }, {
18557          "file": "lib/addons/p5.dom.js",
18558          "line": 1835,
18559          "description": "<p>Removes an attribute on the specified element.</p>\n",
18560          "itemtype": "method",
18561          "name": "removeAttribute",
18562          "params": [{
18563            "name": "attr",
18564            "description": "<p>attribute to remove</p>\n",
18565            "type": "String"
18566          }],
18567          "chainable": 1,
18568          "example": ["\n <div><code>\n var button;\n var checkbox;\nfunction setup() {\n   checkbox = createCheckbox('enable', true);\n   checkbox.changed(enableButton);\n   button = createButton('button');\n   button.position(10, 10);\n }\nfunction enableButton() {\n   if (this.checked()) {\n     // Re-enable the button\n     button.removeAttribute('disabled');\n   } else {\n     // Disable the button\n     button.attribute('disabled', '');\n   }\n }\n </code></div>"],
18569          "class": "p5.Element",
18570          "module": "p5.dom",
18571          "submodule": "p5.dom"
18572        }, {
18573          "file": "lib/addons/p5.dom.js",
18574          "line": 1880,
18575          "description": "<p>Either returns the value of the element if no arguments\ngiven, or sets the value of the element.</p>\n",
18576          "itemtype": "method",
18577          "name": "value",
18578          "return": {
18579            "description": "value of the element",
18580            "type": "String|Number"
18581          },
18582          "example": ["\n<div class='norender'><code>\n// gets the value\nvar inp;\nfunction setup() {\n  inp = createInput('');\n}
18582\n\nfunction mousePressed() {\n  print(inp.value());\n}\n</code></div>\n<div class='norender'><code>\n// sets the value\nvar inp;\nfunction setup() {\n  inp = createInput('myValue');\n}\n\nfunction mousePressed() {\n  inp.value('myValue');\n}\n</code></div>"],
18583          "class": "p5.Element",
18584          "module": "p5.dom",
18585          "submodule": "p5.dom",
18586          "overloads": [{
18587            "line": 1880,
18588            "params": [],
18589            "return": {
18590              "description": "value of the element",
18591              "type": "String|Number"
18592            }
18593          }, {
18594            "line": 1910,
18595            "params": [{
18596              "name": "value",
18597              "description": "",
18598              "type": "String|Number"
18599            }],
18600            "chainable": 1
18601          }]
18602        }, {
18603          "file": "lib/addons/p5.dom.js",
18604          "line": 1926,
18605          "description": "<p>Shows the current element. Essentially, setting display:block for the style.</p>\n",
18606          "itemtype": "method",
18607          "name": "show",
18608          "chainable": 1,
18609          "example": ["\n <div class='norender'><code>\n var div = createDiv('div');\n div.style('display', 'none');\n div.show(); // turns display to block\n </code></div>"],
18610          "class": "p5.Element",
18611          "module": "p5.dom",
18612          "submodule": "p5.dom"
18613        }, {
18614          "file": "lib/addons/p5.dom.js",
18615          "line": 1944,
18616          "description": "<p>Hides the current element. Essentially, setting display:none for the style.</p>\n",
18617          "itemtype": "method",
18618          "name": "hide",
18619          "chainable": 1,
18620          "example": ["\n<div class='norender'><code>\nvar div = createDiv('this is a div');\ndiv.hide();\n</code></div>"],
18621          "class": "p5.Element",
18622          "module": "p5.dom",
18623          "submodule": "p5.dom"
18624        }, {
18625          "file": "lib/addons/p5.dom.js",
18626          "line": 1960,
18627          "description": "<p>Sets the width and height of the element. AUTO can be used to\n only adjust one dimension. If no arguments given returns the width and height\n of the element in an object.</p>\n",
18628          "itemtype": "method",
18629          "name": "size",
18630          "return": {
18631            "description": "the width and height of the element in an object",
18632            "type": "Object"
18633          },
18634          "example": ["\n <div class='norender'><code>\n var div = createDiv('this is a div');\n div.size(100, 100);\n </code></div>"],
18635          "class": "p5.Element",
18636          "module": "p5.dom",
18637          "submodule": "p5.dom",
18638          "overloads": [{
18639            "line": 1960,
18640            "params": [],
18641            "return": {
18642              "description": "the width and height of the element in an object",
18643              "type": "Object"
18644            }
18645          }, {
18646            "line": 1974,
18647            "params": [{
18648              "name": "w",
18649              "description": "<p>width of the element, either AUTO, or a number</p>\n",
18650              "type": "Number|Constant"
18651            }, {
18652              "name": "h",
18653              "description": "<p>height of the element, either AUTO, or a number</p>\n",
18654              "type": "Number|Constant",
18655              "optional": true
18656            }],
18657            "chainable": 1
18658          }]
18659        }, {
18660          "file": "lib/addons/p5.dom.js",
18661          "line": 2038,
18662          "description": "<p>Removes the element and deregisters all listeners.</p>\n",
18663          "itemtype": "method",
18664          "name": "remove",
18665          "example": ["\n<div class='norender'><code>\nvar myDiv = createDiv('this is some text');\nmyDiv.remove();\n</code></div>"],
18666          "class": "p5.Element",
18667          "module": "p5.dom",
18668          "submodule": "p5.dom"
18669        }, {
18670          "file": "lib/addons/p5.dom.js",
18671          "line": 2086,
18672          "description": "<p>Path to the media element source.</p>\n",
18673          "itemtype": "property",
18674          "name": "src",
18675          "return": {
18676            "description": "src",
18677            "type": "String"
18678          },
18679          "example": ["\n<div><code>\nvar ele;\n\nfunction setup() {\n  background(250);\n\n  //p5.MediaElement objects are usually created\n  //by calling the createAudio(), createVideo(),\n  //and createCapture() functions.\n\n  //In this example we create\n  //a new p5.MediaElement via createAudio().\n  ele = createAudio('assets/beat.mp3');\n\n  //We'll set up our example so that\n  //when you click on the text,\n  //an alert box displays the MediaElement's\n  //src field.\n  textAlign(CENTER);\n  text('Click Me!', width / 2, height / 2);\n}\n\nfunction mouseClicked() {\n  //here we test if the mouse is over the\n  //canvas element when it's clicked\n  if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {\n    //Show our p5.MediaElement's src field\n    alert(ele.src);\n  }\n}\n</code></div>"],
18680          "class": "p5.MediaElement",
18681          "module": "p5.dom",
18682          "submodule": "p5.dom"
18683        }, {
18684          "file": "lib/addons/p5.dom.js",
18685          "line": 2152,
18686          "description": "<p>Play an HTML5 media element.</p>\n",
18687          "itemtype": "method",
18688          "name": "play",
18689          "chainable": 1,
18690          "example": ["\n<div><code>\nvar ele;\n\nfunction setup() {\n  //p5.MediaElement objects are usually created\n  //by calling the createAudio(), createVideo(),\n  //and createCapture() functions.\n\n  //In this example we create\n  //a new p5.MediaElement via createAudio().\n  ele = createAudio('assets/beat.mp3');\n\n  background(250);\n  textAlign(CENTER);\n  text('Click to Play!', width / 2, height / 2);\n}\n\nfunction mouseClicked() {\n  //here we test if the mouse is over the\n  //canvas element when it's clicked\n  if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {\n    //Here we call the play() function on\n    //the p5.MediaElement we created above.\n    //This will start the audio sample.\n    ele.play();\n\n    background(200);\n    text('You clicked Play!', width / 2, height / 2);\n  }\n}\n</code></div>"],
18691          "class": "p5.MediaElement",
18692          "module": "p5.dom",
18693          "submodule": "p5.dom"
18694        }, {
18695          "file": "lib/addons/p5.dom.js",
18696          "line": 2213,
18697          "description": "<p>Stops an HTML5 media element (sets current time to zero).</p>\n",
18698          "itemtype": "method",
18699          "name": "stop",
18700          "chainable": 1,
18701          "example": ["\n<div><code>\n//This example both starts\n//and stops a sound sample\n//when the user clicks the canvas\n\n//We will store the p5.MediaElement\n//object in here\nvar ele;\n\n//while our audio is playing,\n//this will be set to true\nvar sampleIsPlaying = false;\n\nfunction setup() {\n  //Here we create a p5.MediaElement object\n  //using the createAudio() function.\n  ele = createAudio('assets/beat.mp3');\n  background(200);\n  textAlign(CENTER);\n  text('Click to play!', width / 2, height / 2);\n}\n\nfunction mouseClicked() {\n  //here we test if the mouse is over the\n  //canvas element when it's clicked\n  if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {\n    background(200);\n\n    if (sampleIsPlaying) {\n      //if the sample is currently playing\n      //calling the stop() function on\n      //our p5.MediaElement will stop\n      //it and reset its current\n      //time to 0 (i.e. it will start\n      //at the beginning the next time\n      //you play it)\n      ele.stop();\n\n      sampleIsPlaying = false;\n      text('Click to play!', width / 2, height / 2);\n    } else {\n      //loop our sound element until we\n      //call ele.stop() on it.\n      ele.loop();\n\n      sampleIsPlaying = true;\n      text('Click to stop!', width / 2, height / 2);\n    }\n  }\n}\n</code></div>"],
18702          "class": "p5.MediaElement",
18703          "module": "p5.dom",
18704          "submodule": "p5.dom"
18705        }, {
18706          "file": "lib/addons/p5.dom.js",
18707          "line": 2277,
18708          "description": "<p>Pauses an HTML5 media element.</p>\n",
18709          "itemtype": "method",
18710          "name": "pause",
18711          "chainable": 1,
18712          "example": ["\n<div><code>\n//This example both starts\n//and pauses a sound sample\n//when the user clicks the canvas\n\n//We will store the p5.MediaElement\n//object in here\nvar ele;\n\n//while our audio is playing,\n//this will be set to true\nvar sampleIsPlaying = false;\n\nfunction setup() {\n  //Here we create a p5.MediaElement object\n  //using the createAudio() function.\n  ele = createAudio('assets/lucky_dragons.mp3');\n  background(200);\n  textAlign(CENTER);\n  text('Click to play!', width / 2, height / 2);\n}\n\nfunction mouseClicked() {\n  //here we test if the mouse is over the\n  //canvas element when it's clicked\n  if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {\n    background(200);\n\n    if (sampleIsPlaying) {\n      //Calling pause() on our\n      //p5.MediaElement will stop it\n      //playing, but when we call the\n      //loop() or play() functions\n      //the sample will start from\n      //where we paused it.\n      ele.pause();\n\n      sampleIsPlaying = false;\n      text('Click to resume!', width / 2, height / 2);\n    } else {\n      //loop our sound element until we\n      //call ele.pause() on it.\n      ele.loop();\n\n      sampleIsPlaying = true;\n      text('Click to pause!', width / 2, height / 2);\n    }\n  }\n}\n</code></div>"],
18713          "class": "p5.MediaElement",
18714          "module": "p5.dom",
18715          "submodule": "p5.dom"
18716        }, {
18717          "file": "lib/addons/p5.dom.js",
18718          "line": 2339,
18719          "description": "<p>Set &#39;loop&#39; to true for an HTML5 media element, and starts playing.</p>\n",
18720          "itemtype": "method",
18721          "name": "loop",
18722          "chainable": 1,
18723          "example": ["\n<div><code>\n//Clicking the canvas will loop\n//the audio sample until the user\n//clicks again to stop it\n\n//We will store the p5.MediaElement\n//object in here\nvar ele;\n\n//while our audio is playing,\n//this will be set to true\nvar sampleIsLooping = false;\n\nfunction setup() {\n  //Here we create a p5.MediaElement object\n  //using the createAudio() function.\n  ele = createAudio('assets/lucky_dragons.mp3');\n  background(200);\n  textAlign(CENTER);\n  text('Click to loop!', width / 2, height / 2);\n}\n\nfunction mouseClicked() {\n  //here we test if the mouse is over the\n  //canvas element when it's clicked\n  if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {\n    background(200);\n\n    if (!sampleIsLooping) {\n      //loop our sound element until we\n      //call ele.stop() on it.\n      ele.loop();\n\n      sampleIsLooping = true;\n      text('Click to stop!', width / 2, height / 2);\n    } else {\n      ele.stop();\n\n      sampleIsLooping = false;\n      text('Click to loop!', width / 2, height / 2);\n    }\n  }\n}\n</code></div>"],
18724          "class": "p5.MediaElement",
18725          "module": "p5.dom",
18726          "submodule": "p5.dom"
18727        }, {
18728          "file": "lib/addons/p5.dom.js",
18729          "line": 2395,
18730          "description": "<p>Set &#39;loop&#39; to false for an HTML5 media element. Element will stop\nwhen it reaches the end.</p>\n",
18731          "itemtype": "method",
18732          "name": "noLoop",
18733          "chainable": 1,
18734          "example": ["\n<div><code>\n//This example both starts\n//and stops loop of sound sample\n//when the user clicks the canvas\n\n//We will store the p5.MediaElement\n//object in here\nvar ele;\n//while our audio is playing,\n//this will be set to true\nvar sampleIsPlaying = false;\n\nfunction setup() {\n  //Here we create a p5.MediaElement object\n  //using the createAudio() function.\n  ele = createAudio('assets/beat.mp3');\n  background(200);\n  textAlign(CENTER);\n  text('Click to play!', width / 2, height / 2);\n}\n\nfunction mouseClicked() {\n  //here we test if the mouse is over the\n  //canvas element when it's clicked\n  if (mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height) {\n    background(200);\n\n    if (sampleIsPlaying) {\n      ele.noLoop();\n      text('No more Loops!', width / 2, height / 2);\n    } else {\n      ele.loop();\n      sampleIsPlaying = true;\n      text('Click to stop looping!', width / 2, height / 2);\n    }\n  }\n}\n</code></div>\n"],
18735          "class": "p5.MediaElement",
18736          "module": "p5.dom",
18737          "submodule": "p5.dom"
18738        }, {
18739          "file": "lib/addons/p5.dom.js",
18740          "line": 2447,
18741          "description": "<p>
18741Set HTML5 media element to autoplay or not.</p>\n",
18742          "itemtype": "method",
18743          "name": "autoplay",
18744          "params": [{
18745            "name": "autoplay",
18746            "description": "<p>whether the element should autoplay</p>\n",
18747            "type": "Boolean"
18748          }],
18749          "chainable": 1,
18750          "class": "p5.MediaElement",
18751          "module": "p5.dom",
18752          "submodule": "p5.dom"
18753        }, {
18754          "file": "lib/addons/p5.dom.js",
18755          "line": 2459,
18756          "description": "<p>Sets volume for this HTML5 media element. If no argument is given,\nreturns the current volume.</p>\n",
18757          "itemtype": "method",
18758          "name": "volume",
18759          "return": {
18760            "description": "current volume",
18761            "type": "Number"
18762          },
18763          "example": ["\n<div><code>\nvar ele;\nfunction setup() {\n  // p5.MediaElement objects are usually created\n  // by calling the createAudio(), createVideo(),\n  // and createCapture() functions.\n  // In this example we create\n  // a new p5.MediaElement via createAudio().\n  ele = createAudio('assets/lucky_dragons.mp3');\n  background(250);\n  textAlign(CENTER);\n  text('Click to Play!', width / 2, height / 2);\n}\nfunction mouseClicked() {\n  // Here we call the volume() function\n  // on the sound element to set its volume\n  // Volume must be between 0.0 and 1.0\n  ele.volume(0.2);\n  ele.play();\n  background(200);\n  text('You clicked Play!', width / 2, height / 2);\n}\n</code></div>\n<div><code>\nvar audio;\nvar counter = 0;\n\nfunction loaded() {\n  audio.play();\n}\n\nfunction setup() {\n  audio = createAudio('assets/lucky_dragons.mp3', loaded);\n  textAlign(CENTER);\n}\n\nfunction draw() {\n  if (counter === 0) {\n    background(0, 255, 0);\n    text('volume(0.9)', width / 2, height / 2);\n  } else if (counter === 1) {\n    background(255, 255, 0);\n    text('volume(0.5)', width / 2, height / 2);\n  } else if (counter === 2) {\n    background(255, 0, 0);\n    text('volume(0.1)', width / 2, height / 2);\n  }\n}\n\nfunction mousePressed() {\n  counter++;\n  if (counter === 0) {\n    audio.volume(0.9);\n  } else if (counter === 1) {\n    audio.volume(0.5);\n  } else if (counter === 2) {\n    audio.volume(0.1);\n  } else {\n    counter = 0;\n    audio.volume(0.9);\n  }\n}\n</code>\n</div>"],
18764          "class": "p5.MediaElement",
18765          "module": "p5.dom",
18766          "submodule": "p5.dom",
18767          "overloads": [{
18768            "line": 2459,
18769            "params": [],
18770            "return": {
18771              "description": "current volume",
18772              "type": "Number"
18773            }
18774          }, {
18775            "line": 2532,
18776            "params": [{
18777              "name": "val",
18778              "description": "<p>volume between 0.0 and 1.0</p>\n",
18779              "type": "Number"
18780            }],
18781            "chainable": 1
18782          }]
18783        }, {
18784          "file": "lib/addons/p5.dom.js",
18785          "line": 2545,
18786          "description": "<p>If no arguments are given, returns the current playback speed of the\nelement. The speed parameter sets the speed where 2.0 will play the\nelement twice as fast, 0.5 will play at half the speed, and -1 will play\nthe element in normal speed in reverse.(Note that not all browsers support\nbackward playback and even if they do, playback might not be smooth.)</p>\n",
18787          "itemtype": "method",
18788          "name": "speed",
18789          "return": {
18790            "description": "current playback speed of the element",
18791            "type": "Number"
18792          },
18793          "example": ["\n<div class='norender notest'><code>\n//Clicking the canvas will loop\n//the audio sample until the user\n//clicks again to stop it\n\n//We will store the p5.MediaElement\n//object in here\nvar ele;\nvar button;\n\nfunction setup() {\n  createCanvas(710, 400);\n  //Here we create a p5.MediaElement object\n  //using the createAudio() function.\n  ele = createAudio('assets/beat.mp3');\n  ele.loop();\n  background(200);\n\n  button = createButton('2x speed');\n  button.position(100, 68);\n  button.mousePressed(twice_speed);\n\n  button = createButton('half speed');\n  button.position(200, 68);\n  button.mousePressed(half_speed);\n\n  button = createButton('reverse play');\n  button.position(300, 68);\n  button.mousePressed(reverse_speed);\n\n  button = createButton('STOP');\n  button.position(400, 68);\n  button.mousePressed(stop_song);\n\n  button = createButton('PLAY!');\n  button.position(500, 68);\n  button.mousePressed(play_speed);\n}
18793\n\nfunction twice_speed() {\n  ele.speed(2);\n}\n\nfunction half_speed() {\n  ele.speed(0.5);\n}\n\nfunction reverse_speed() {\n  ele.speed(-1);\n}\n\nfunction stop_song() {\n  ele.stop();\n}\n\nfunction play_speed() {\n  ele.play();\n}\n</code></div>"],
18794          "class": "p5.MediaElement",
18795          "module": "p5.dom",
18796          "submodule": "p5.dom",
18797          "overloads": [{
18798            "line": 2545,
18799            "params": [],
18800            "return": {
18801              "description": "current playback speed of the element",
18802              "type": "Number"
18803            }
18804          }, {
18805            "line": 2616,
18806            "params": [{
18807              "name": "speed",
18808              "description": "<p>speed multiplier for element playback</p>\n",
18809              "type": "Number"
18810            }],
18811            "chainable": 1
18812          }]
18813        }, {
18814          "file": "lib/addons/p5.dom.js",
18815          "line": 2633,
18816          "description": "<p>If no arguments are given, returns the current time of the element.\nIf an argument is given the current time of the element is set to it.</p>\n",
18817          "itemtype": "method",
18818          "name": "time",
18819          "return": {
18820            "description": "current time (in seconds)",
18821            "type": "Number"
18822          },
18823          "example": ["\n<div><code>\nvar ele;\nvar beginning = true;\nfunction setup() {\n  //p5.MediaElement objects are usually created\n  //by calling the createAudio(), createVideo(),\n  //and createCapture() functions.\n\n  //In this example we create\n  //a new p5.MediaElement via createAudio().\n  ele = createAudio('assets/lucky_dragons.mp3');\n  background(250);\n  textAlign(CENTER);\n  text('start at beginning', width / 2, height / 2);\n}\n\n// this function fires with click anywhere\nfunction mousePressed() {\n  if (beginning === true) {\n    // here we start the sound at the beginning\n    // time(0) is not necessary here\n    // as this produces the same result as\n    // play()\n    ele.play().time(0);\n    background(200);\n    text('jump 2 sec in', width / 2, height / 2);\n    beginning = false;\n  } else {\n    // here we jump 2 seconds into the sound\n    ele.play().time(2);\n    background(250);\n    text('start at beginning', width / 2, height / 2);\n    beginning = true;\n  }\n}\n</code></div>"],
18824          "class": "p5.MediaElement",
18825          "module": "p5.dom",
18826          "submodule": "p5.dom",
18827          "overloads": [{
18828            "line": 2633,
18829            "params": [],
18830            "return": {
18831              "description": "current time (in seconds)",
18832              "type": "Number"
18833            }
18834          }, {
18835            "line": 2678,
18836            "params": [{
18837              "name": "time",
18838              "description": "<p>time to jump to (in seconds)</p>\n",
18839              "type": "Number"
18840            }],
18841            "chainable": 1
18842          }]
18843        }, {
18844          "file": "lib/addons/p5.dom.js",
18845          "line": 2692,
18846          "description": "<p>Returns the duration of the HTML5 media element.</p>\n",
18847          "itemtype": "method",
18848          "name": "duration",
18849          "return": {
18850            "description": "duration",
18851            "type": "Number"
18852          },
18853          "example": ["\n<div><code>\nvar ele;\nfunction setup() {\n  //p5.MediaElement objects are usually created\n  //by calling the createAudio(), createVideo(),\n  //and createCapture() functions.\n  //In this example we create\n  //a new p5.MediaElement via createAudio().\n  ele = createAudio('assets/doorbell.mp3');\n  background(250);\n  textAlign(CENTER);\n  text('Click to know the duration!', 10, 25, 70, 80);\n}\nfunction mouseClicked() {\n  ele.play();\n  background(200);\n  //ele.duration dislpays the duration\n  text(ele.duration() + ' seconds', width / 2, height / 2);\n}\n</code></div>"],
18854          "class": "p5.MediaElement",
18855          "module": "p5.dom",
18856          "submodule": "p5.dom"
18857        }, {
18858          "file": "lib/addons/p5.dom.js",
18859          "line": 2833,
18860          "description": "<p>Schedule an event to be called when the audio or video\nelement reaches the end. If the element is looping,\nthis will not be called. The element is passed in\nas the argument to the onended callback.</p>\n",
18861          "itemtype": "method",
18862          "name": "onended",
18863          "params": [{
18864            "name": "callback",
18865            "description": "<p>function to call when the\n                            soundfile has ended. The\n                            media element will be passed\n                            in as the argument to the\n                            callback.</p>\n",
18866            "type": "Function"
18867          }],
18868          "chainable": 1,
18869          "example": ["\n<div><code>\nfunction setup() {\n  var audioEl = createAudio('assets/beat.mp3');\n  audioEl.showControls();\n  audioEl.onended(sayDone);\n}\n\nfunction sayDone(elt) {\n  alert('done playing ' + elt.src);\n}\n</code></div>"],
18870          "class": "p5.MediaElement",
18871          "module": "p5.dom",
18872          "submodule": "p5.dom"
18873        }, {
18874          "file": "lib/addons/p5.dom.js",
18875          "line": 2864,
18876          "class": "p5.MediaElement",
18877          "module": "p5.dom",
18878          "submodule": "p5.dom"
18879        }, {
18880          "file": "lib/addons/p5.dom.js",
18881          "line": 2866,
18882          "description": "<p>Send the audio output of this element to a specified audioNode or\np5.sound object. If no element is provided, connects to p5&#39;s master\noutput. That connection is established when this method is first called.\nAll connections are removed by the .disconnect() method.</p>\n<p>This method is meant to be used with the p5.sound.js addon library.</p>\n",
18883          "itemtype": "method",
18884          "name": "connect",
18885          "params": [{
18886            "name": "audioNode",
18887            "description": "<p>AudioNode from the Web Audio API,\nor an object from the p5.sound library</p>\n",
18888            "type": "AudioNode|Object"
18889          }],
18890          "class": "p5.MediaElement",
18891          "module": "p5.dom",
18892          "submodule": "p5.dom"
18893        }, {
18894          "file": "lib/addons/p5.dom.js",
18895          "line": 2915,
18896          "description": "<p>Disconnect all Web Audio routing, including to master output.\nThis is useful if you want to re-route the output through\naudio effects, for example.</p>\n",
18897          "itemtype": "method",
18898          "name": "disconnect",
18899          "class": "p5.MediaElement",
18900          "module": "p5.dom",
18901          "submodule": "p5.dom"
18902        }, {
18903          "file": "lib/addons/p5.dom.js",
18904          "line": 2930,
18905          "class": "p5.MediaElement",
18906          "module": "p5.dom",
18907          "submodule": "p5.dom"
18908        }, {
18909          "file": "lib/addons/p5.dom.js",
18910          "line": 2932,
18911          "description": "<p>Show the default MediaElement controls, as determined by the web browser.</p>\n",
18912          "itemtype": "method",
18913          "name": "showControls",
18914          "example": ["\n<div><code>\nvar ele;\nfunction setup() {\n  //p5.MediaElement objects are usually created\n  //by calling the createAudio(), createVideo(),\n  //and createCapture() functions.\n  //In this example we create\n  //a new p5.MediaElement via createAudio()\n  ele = createAudio('assets/lucky_dragons.mp3');\n  background(200);\n  textAlign(CENTER);\n  text('Click to Show Controls!', 10, 25, 70, 80);\n}\nfunction mousePressed() {\n  ele.showControls();\n  background(200);\n  text('Controls Shown', width / 2, height / 2);\n}\n</code></div>"],
18915          "class": "p5.MediaElement",
18916          "module": "p5.dom",
18917          "submodule": "p5.dom"
18918        }, {
18919          "file": "lib/addons/p5.dom.js",
18920          "line": 2963,
18921          "description": "<p>Hide the default mediaElement controls.</p>\n",
18922          "itemtype": "method",
18923          "name": "hideControls",
18924          "example": ["\n<div><code>\nvar ele;\nfunction setup() {\n  //p5.MediaElement objects are usually created\n  //by calling the createAudio(), createVideo(),\n  //and createCapture() functions.\n  //In this example we create\n  //a new p5.MediaElement via createAudio()\n  ele = createAudio('assets/lucky_dragons.mp3');\n  ele.showControls();\n  background(200);\n  textAlign(CENTER);\n  text('Click to hide Controls!', 10, 25, 70, 80);\n}\nfunction mousePressed() {\n  ele.hideControls();\n  background(200);\n  text('Controls hidden', width / 2, height / 2);\n}\n</code></div>"],
18925          "class": "p5.MediaElement",
18926          "module": "p5.dom",
18927          "submodule": "p5.dom"
18928        }, {
18929          "file": "lib/addons/p5.dom.js",
18930          "line": 2992,
18931          "class": "p5.MediaElement",
18932          "module": "p5.dom",
18933          "submodule": "p5.dom"
18934        }, {
18935          "file": "lib/addons/p5.dom.js",
18936          "line": 3003,
18937          "description": "<p>Schedule events to trigger every time a MediaElement\n(audio/video) reaches a playback cue point.</p>\n<p>Accepts a callback function, a time (in seconds) at which to trigger\nthe callback, and an optional parameter for the callback.</p>\n<p>Time will be passed as the first parameter to the callback function,\nand param will be the second parameter.</p>\n",
18938          "itemtype": "method",
18939          "name": "addCue",
18940          "params": [{
18941            "name": "time",
18942            "description": "<p>Time in seconds, relative to this media\n                            element&#39;s playback. For example, to trigger\n                            an event every time playback reaches two\n                            seconds, pass in the number 2. This will be\n                            passed as the first parameter to\n                            the callback function.</p>\n",
18943            "type": "Number"
18944          }, {
18945            "name": "callback",
18946            "description": "<p>Name of a function that will be\n                            called at the given time. The callback will\n                            receive time and (optionally) param as its\n                            two parameters.</p>\n",
18947            "type": "Function"
18948          }, {
18949            "name": "value",
18950            "description": "<p>An object to be passed as the\n                            second parameter to the\n                            callback function.</p>\n",
18951            "type": "Object",
18952            "optional": true
18953          }],
18954          "return": {
18955            "description": "id ID of this cue,\n                    useful for removeCue(id)",
18956            "type": "Number"
18957          },
18958          "example": ["\n<div><code>\n//\n//\nfunction setup() {\n  noCanvas();\n\n  var audioEl = createAudio('assets/beat.mp3');\n  audioEl.showControls();
18958\n\n  // schedule three calls to changeBackground\n  audioEl.addCue(0.5, changeBackground, color(255, 0, 0));\n  audioEl.addCue(1.0, changeBackground, color(0, 255, 0));\n  audioEl.addCue(2.5, changeBackground, color(0, 0, 255));\n  audioEl.addCue(3.0, changeBackground, color(0, 255, 255));\n  audioEl.addCue(4.2, changeBackground, color(255, 255, 0));\n  audioEl.addCue(5.0, changeBackground, color(255, 255, 0));\n}\n\nfunction changeBackground(val) {\n  background(val);\n}\n</code></div>"],
18959          "class": "p5.MediaElement",
18960          "module": "p5.dom",
18961          "submodule": "p5.dom"
18962        }, {
18963          "file": "lib/addons/p5.dom.js",
18964          "line": 3067,
18965          "description": "<p>Remove a callback based on its ID. The ID is returned by the\naddCue method.</p>\n",
18966          "itemtype": "method",
18967          "name": "removeCue",
18968          "params": [{
18969            "name": "id",
18970            "description": "<p>ID of the cue, as returned by addCue</p>\n",
18971            "type": "Number"
18972          }],
18973          "example": ["\n<div><code>\nvar audioEl, id1, id2;\nfunction setup() {\n  background(255, 255, 255);\n  audioEl = createAudio('assets/beat.mp3');\n  audioEl.showControls();\n  // schedule five calls to changeBackground\n  id1 = audioEl.addCue(0.5, changeBackground, color(255, 0, 0));\n  audioEl.addCue(1.0, changeBackground, color(0, 255, 0));\n  audioEl.addCue(2.5, changeBackground, color(0, 0, 255));\n  audioEl.addCue(3.0, changeBackground, color(0, 255, 255));\n  id2 = audioEl.addCue(4.2, changeBackground, color(255, 255, 0));\n  text('Click to remove first and last Cue!', 10, 25, 70, 80);\n}\nfunction mousePressed() {\n  audioEl.removeCue(id1);\n  audioEl.removeCue(id2);\n}\nfunction changeBackground(val) {\n  background(val);\n}\n</code></div>"],
18974          "class": "p5.MediaElement",
18975          "module": "p5.dom",
18976          "submodule": "p5.dom"
18977        }, {
18978          "file": "lib/addons/p5.dom.js",
18979          "line": 3109,
18980          "description": "<p>Remove all of the callbacks that had originally been scheduled\nvia the addCue method.</p>\n",
18981          "itemtype": "method",
18982          "name": "clearCues",
18983          "params": [{
18984            "name": "id",
18985            "description": "<p>ID of the cue, as returned by addCue</p>\n",
18986            "type": "Number"
18987          }],
18988          "example": ["\n<div><code>\nvar audioEl;\nfunction setup() {\n  background(255, 255, 255);\n  audioEl = createAudio('assets/beat.mp3');\n  //Show the default MediaElement controls, as determined by the web browser\n  audioEl.showControls();\n  // schedule calls to changeBackground\n  background(200);\n  text('Click to change Cue!', 10, 25, 70, 80);\n  audioEl.addCue(0.5, changeBackground, color(255, 0, 0));\n  audioEl.addCue(1.0, changeBackground, color(0, 255, 0));\n  audioEl.addCue(2.5, changeBackground, color(0, 0, 255));\n  audioEl.addCue(3.0, changeBackground, color(0, 255, 255));\n  audioEl.addCue(4.2, changeBackground, color(255, 255, 0));\n}\nfunction mousePressed() {\n  // here we clear the scheduled callbacks\n  audioEl.clearCues();\n  // then we add some more callbacks\n  audioEl.addCue(1, changeBackground, color(2, 2, 2));\n  audioEl.addCue(3, changeBackground, color(255, 255, 0));\n}\nfunction changeBackground(val) {\n  background(val);\n}\n</code></div>"],
18989          "class": "p5.MediaElement",
18990          "module": "p5.dom",
18991          "submodule": "p5.dom"
18992        }, {
18993          "file": "lib/addons/p5.dom.js",
18994          "line": 3179,
18995          "description": "<p>Underlying File object. All normal File methods can be called on this.</p>\n",
18996          "itemtype": "property",
18997          "name": "file",
18998          "class": "p5.File",
18999          "module": "p5.dom",
19000          "submodule": "p5.dom"
19001        }, {
19002          "file": "lib/addons/p5.dom.js",
19003          "line": 3191,
19004          "description": "<p>File type (image, text, etc.)</p>\n",
19005          "itemtype": "property",
19006          "name": "type",
19007          "class": "p5.File",
19008          "module": "p5.dom",
19009          "submodule": "p5.dom"
19010        }, {
19011          "file": "lib/addons/p5.dom.js",
19012          "line": 3197,
19013          "description": "<p>File subtype (usually the file extension jpg, png, xml, etc.)</p>\n",
19014          "itemtype": "property",
19015          "name": "subtype",
19016          "class": "p5.File",
19017          "module": "p5.dom",
19018          "submodule": "p5.dom"
19019        }, {
19020          "file": "lib/addons/p5.dom.js",
19021          "line": 3203,
19022          "description": "<p>File name</p>\n",
19023          "itemtype": "property",
19024          "name": "name",
19025          "class": "p5.File",
19026          "module": "p5.dom",
19027          "submodule": "p5.dom"
19028        }, {
19029          "file": "lib/addons/p5.dom.js",
19030          "line": 3209,
19031          "description": "<p>File size</p>\n",
19032          "itemtype": "property",
19033          "name": "size",
19034          "class": "p5.File",
19035          "module": "p5.dom",
19036          "submodule": "p5.dom"
19037        }, {
19038          "file": "lib/addons/p5.dom.js",
19039          "line": 3216,
19040          "description": "<p>URL string containing image data.</p>\n",
19041          "itemtype": "property",
19042          "name": "data",
19043          "class": "p5.File",
19044          "module": "p5.dom",
19045          "submodule": "p5.dom"
19046        }, {
19047          "file": "lib/addons/p5.sound.js",
19048          "line": 46,
19049          "description": "<p>p5.sound \n<a href=\"https://p5js.org/reference/#/libraries/p5.sound\">https://p5js.org/reference/#/libraries/p5.sound</a></p>\n<p>From the Processing Foundation and contributors\n<a href=\"https://github.com/processing/p5.js-sound/graphs/contributors\">https://github.com/processing/p5.js-sound/graphs/contributors</a></p>\n<p>MIT License (MIT)\n<a href=\"https://github.com/processing/p5.js-sound/blob/master/LICENSE\">https://github.com/processing/p5.js-sound/blob/master/LICENSE</a></p>\n<p>Some of the many audio libraries &amp; resources that inspire p5.sound:</p>\n<ul>\n<li>TONE.js (c) Yotam Mann. Licensed under The MIT License (MIT). <a href=\"https://github.com/TONEnoTONE/Tone.js\">https://github.com/TONEnoTONE/Tone.js</a></li>\n<li>buzz.js (c) Jay Salvat. Licensed under The MIT License (MIT). <a href=\"http://buzz.jaysalvat.com/\">http://buzz.jaysalvat.com/</a></li>\n<li>Boris Smus Web Audio API book, 2013. Licensed under the Apache License <a href=\"http://www.apache.org/licenses/LICENSE-2.0\">http://www.apache.org/licenses/LICENSE-2.0</a></li>\n<li>wavesurfer.js <a href=\"https://github.com/katspaugh/wavesurfer.js\">https://github.com/katspaugh/wavesurfer.js</a></li>\n<li>Web Audio Components by Jordan Santell <a href=\"https://github.com/web-audio-components\">https://github.com/web-audio-components</a></li>\n<li><p>Wilm Thoben&#39;s Sound library for Processing <a href=\"https://github.com/processing/processing/tree/master/java/libraries/sound\">https://github.com/processing/processing/tree/master/java/libraries/sound</a></p>\n<p>Web Audio API: <a href=\"http://w3.org/TR/webaudio/\">http://w3.org/TR/webaudio/</a></p>\n</li>\n</ul>\n",
19050          "class": "p5.sound",
19051          "module": "p5.sound",
19052          "submodule": "p5.sound"
19053        }, {
19054          "file": "lib/addons/p5.sound.js",
19055          "line": 214,
19056          "description": "<p>Determine which filetypes are supported (inspired by buzz.js)\nThe audio element (el) will only be used to test browser support for various audio formats</p>\n",
19057          "class": "p5.sound",
19058          "module": "p5.sound",
19059          "submodule": "p5.sound"
19060        }, {
19061          "file": "lib/addons/p5.sound.js",
19062          "line": 364,
19063          "description": "<p>Returns the Audio Context for this sketch. Useful for users\nwho would like to dig deeper into the <a target='_blank' href=\n'http://webaudio.github.io/web-audio-api/'>Web Audio API\n</a>.</p>\n\n<p>Some browsers require users to startAudioContext\nwith a user gesture, such as touchStarted in the example below.</p>",
19064          "itemtype": "method",
19065          "name": "getAudioContext",
19066          "return": {
19067            "description": "AudioContext for this sketch",
19068            "type": "Object"
19069          },
19070          "example": ["\n<div><code>\n function draw() {\n   background(255);\n   textAlign(CENTER);\n\n   if (getAudioContext().state !== 'running') {\n     text('click to start audio', width/2, height/2);\n   } else {\n     text('audio is enabled', width/2, height/2);\n   }\n }
19070\n\n function touchStarted() {\n   if (getAudioContext().state !== 'running') {\n     getAudioContext().resume();\n   }\n   var synth = new p5.MonoSynth();\n   synth.play('A4', 0.5, 0, 0.2);\n }\n\n</div></code>"],
19071          "class": "p5.sound",
19072          "module": "p5.sound",
19073          "submodule": "p5.sound"
19074        }, {
19075          "file": "lib/addons/p5.sound.js",
19076          "line": 401,
19077          "description": "<p>It is a good practice to give users control over starting audio playback.\nThis practice is enforced by Google Chrome&#39;s autoplay policy as of r70\n(<a href=\"https://goo.gl/7K7WLu\">info</a>), iOS Safari, and other browsers.\n</p>\n\n<p>\nuserStartAudio() starts the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/AudioContext\"\ntarget=\"_blank\" title=\"Audio Context @ MDN\">Audio Context</a> on a user gesture. It utilizes\nthe <a href=\"https://github.com/tambien/StartAudioContext\">StartAudioContext</a> library by\nYotam Mann (MIT Licence, 2016). Read more at <a href=\"https://github.com/tambien/StartAudioContext\">https://github.com/tambien/StartAudioContext</a>.\n</p>\n\n<p>Starting the audio context on a user gesture can be as simple as <code>userStartAudio()</code>.\nOptional parameters let you decide on a specific element that will start the audio context,\nand/or call a function once the audio context is started.</p>",
19078          "params": [{
19079            "name": "element(s)",
19080            "description": "<p>This argument can be an Element,\n                              Selector String, NodeList, p5.Element,\n                              jQuery Element, or an Array of any of those.</p>\n",
19081            "type": "Element|Array",
19082            "optional": true
19083          }, {
19084            "name": "callback",
19085            "description": "<p>Callback to invoke when the AudioContext has started</p>\n",
19086            "type": "Function",
19087            "optional": true
19088          }],
19089          "return": {
19090            "description": "Returns a Promise which is resolved when\n                                     the AudioContext state is 'running'",
19091            "type": "Promise"
19092          },
19093          "itemtype": "method",
19094          "name": "userStartAudio",
19095          "example": ["\n<div><code>\nfunction setup() {\n  var myDiv = createDiv('click to start audio');\n  myDiv.position(0, 0);\n\n  var mySynth = new p5.MonoSynth();\n \n  // This won't play until the context has started\n  mySynth.play('A6');\n\n  // Start the audio context on a click/touch event\n  userStartAudio().then(function() {\n     myDiv.remove();\n   });\n}\n</code></div>"],
19096          "class": "p5.sound",
19097          "module": "p5.sound",
19098          "submodule": "p5.sound"
19099        }, {
19100          "file": "lib/addons/p5.sound.js",
19101          "line": 458,
19102          "description": "<p>Master contains AudioContext and the master sound output.</p>\n",
19103          "class": "p5.sound",
19104          "module": "p5.sound",
19105          "submodule": "p5.sound"
19106        }, {
19107          "file": "lib/addons/p5.sound.js",
19108          "line": 492,
19109          "description": "<p>Returns a number representing the master amplitude (volume) for sound\nin this sketch.</p>\n",
19110          "itemtype": "method",
19111          "name": "getMasterVolume",
19112          "return": {
19113            "description": "Master amplitude (volume) for sound in this sketch.\n                 Should be between 0.0 (silence) and 1.0.",
19114            "type": "Number"
19115          },
19116          "class": "p5.sound",
19117          "module": "p5.sound",
19118          "submodule": "p5.sound"
19119        }, {
19120          "file": "lib/addons/p5.sound.js",
19121          "line": 503,
19122          "description": "<p>Scale the output of all sound in this sketch</p>\nScaled between 0.0 (silence) and 1.0 (full volume).\n1.0 is the maximum amplitude of a digital sound, so multiplying\nby greater than 1.0 may cause digital distortion. To\nfade, provide a <code>rampTime</code> parameter. For more\ncomplex fades, see the Envelope class.\n\nAlternately, you can pass in a signal source such as an\noscillator to modulate the amplitude with an audio signal.\n\n<p><b>How This Works</b>: When you load the p5.sound module, it\ncreates a single instance of p5sound. All sound objects in this\nmodule output to p5sound before reaching your computer&#39;s output.\nSo if you change the amplitude of p5sound, it impacts all of the\nsound in this module.</p>\n\n<p>If no value is provided, returns a Web Audio API Gain Node</p>",
19123          "itemtype": "method",
19124          "name": "masterVolume",
19125          "params": [{
19126            "name": "volume",
19127            "description": "<p>Volume (amplitude) between 0.0\n                                   and 1.0 or modulating signal/oscillator</p>\n",
19128            "type": "Number|Object"
19129          }, {
19130            "name": "rampTime",
19131            "description": "<p>Fade for t seconds</p>\n",
19132            "type": "Number",
19133            "optional": true
19134          }, {
19135            "name": "timeFromNow",
19136            "description": "<p>Schedule this event to happen at\n                               t seconds 
19136in the future</p>\n",
19137            "type": "Number",
19138            "optional": true
19139          }],
19140          "class": "p5.sound",
19141          "module": "p5.sound",
19142          "submodule": "p5.sound"
19143        }, {
19144          "file": "lib/addons/p5.sound.js",
19145          "line": 545,
19146          "description": "<p><code>p5.soundOut</code> is the p5.sound master output. It sends output to\nthe destination of this window&#39;s web audio context. It contains\nWeb Audio API nodes including a dyanmicsCompressor (<code>.limiter</code>),\nand Gain Nodes for <code>.input</code> and <code>.output</code>.</p>\n",
19147          "itemtype": "property",
19148          "name": "soundOut",
19149          "type": "Object",
19150          "class": "p5.sound",
19151          "module": "p5.sound",
19152          "submodule": "p5.sound"
19153        }, {
19154          "file": "lib/addons/p5.sound.js",
19155          "line": 570,
19156          "class": "p5",
19157          "module": "p5.sound",
19158          "submodule": "p5.sound"
19159        }, {
19160          "file": "lib/addons/p5.sound.js",
19161          "line": 573,
19162          "description": "<p>Returns a number representing the sample rate, in samples per second,\nof all sound objects in this audio context. It is determined by the\nsampling rate of your operating system&#39;s sound card, and it is not\ncurrently possile to change.\nIt is often 44100, or twice the range of human hearing.</p>\n",
19163          "itemtype": "method",
19164          "name": "sampleRate",
19165          "return": {
19166            "description": "samplerate samples per second",
19167            "type": "Number"
19168          },
19169          "class": "p5",
19170          "module": "p5.sound",
19171          "submodule": "p5.sound"
19172        }, {
19173          "file": "lib/addons/p5.sound.js",
19174          "line": 586,
19175          "description": "<p>Returns the closest MIDI note value for\na given frequency.</p>\n",
19176          "itemtype": "method",
19177          "name": "freqToMidi",
19178          "params": [{
19179            "name": "frequency",
19180            "description": "<p>A freqeuncy, for example, the &quot;A&quot;\n                           above Middle C is 440Hz</p>\n",
19181            "type": "Number"
19182          }],
19183          "return": {
19184            "description": "MIDI note value",
19185            "type": "Number"
19186          },
19187          "class": "p5",
19188          "module": "p5.sound",
19189          "submodule": "p5.sound"
19190        }, {
19191          "file": "lib/addons/p5.sound.js",
19192          "line": 600,
19193          "description": "<p>Returns the frequency value of a MIDI note value.\nGeneral MIDI treats notes as integers where middle C\nis 60, C# is 61, D is 62 etc. Useful for generating\nmusical frequencies with oscillators.</p>\n",
19194          "itemtype": "method",
19195          "name": "midiToFreq",
19196          "params": [{
19197            "name": "midiNote",
19198            "description": "<p>The number of a MIDI note</p>\n",
19199            "type": "Number"
19200          }],
19201          "return": {
19202            "description": "Frequency value of the given MIDI note",
19203            "type": "Number"
19204          },
19205          "example": ["\n<div><code>\nvar notes = [60, 64, 67, 72];\nvar i = 0;\n\nfunction setup() {\n  osc = new p5.Oscillator('Triangle');\n  osc.start();\n  frameRate(1);\n}\n\nfunction draw() {\n  var freq = midiToFreq(notes[i]);\n  osc.freq(freq);\n  i++;\n  if (i >= notes.length){\n    i = 0;\n  }\n}\n</code></div>"],
19206          "class": "p5",
19207          "module": "p5.sound",
19208          "submodule": "p5.sound"
19209        }, {
19210          "file": "lib/addons/p5.sound.js",
19211          "line": 662,
19212          "description": "<p>List the SoundFile formats that you will include. LoadSound\nwill search your directory for these extensions, and will pick\na format that is compatable with the client&#39;s web browser.\n<a href=\"http://media.io/\">Here</a> is a free online file\nconverter.</p>\n",
19213          "itemtype": "method",
19214          "name": "soundFormats",
19215          "params": [{
19216            "name": "formats",
19217            "description": "<p>i.e. &#39;mp3&#39;, &#39;wav&#39;, &#39;ogg&#39;</p>\n",
19218            "type": "String",
19219            "optional": true,
19220            "multiple": true
19221          }],
19222          "example": ["\n<div><code>\nfunction preload() {\n  // set the global sound formats\n  soundFormats('mp3', 'ogg');\n\n  // load either beatbox.mp3, or .ogg, depending on browser\n  mySound = loadSound('assets/beatbox.mp3');\n}\n\nfunction setup() {\n  mySound.play();\n}\n</code></div>"],
19223          "class": "p5",
19224          "module": "p5.sound",
19225          "submodule": "p5.sound"
19226        }, {
19227          "file": "lib/addons/p5.sound.js",
19228          "line": 775,
19229          "description": "<p>Used by Osc and Envelope to chain signal math</p>\n",
19230          "class": "p5",
19231          "module": "p5.sound",
19232          "submodule": "p5.sound"
19233        }, {
19234          "file": "lib/addons/p5.sound.js",
19235          "line": 1121,
19236          "description": "<p>loadSound() returns a new p5.SoundFile from a specified\npath. If called during preload(), the p5.SoundFile will be ready\nto play in time for setup() and draw(). If called outside of\npreload, the p5.SoundFile will not be ready immediately, so\nloadSound accepts a callback as the second parameter. Using a\n<a href=\"https://github.com/processing/p5.js/wiki/Local-server\">\nlocal server</a> is recommended when loading external files.</p>\n",
19237          "itemtype": "method",
19238          "name": "loadSound",
19239          "params": [{
19240            "name": "path",
19241            "description": "<p>Path to the sound file, or an array with\n                                  paths to soundfiles in multiple formats\n                                  i.e. [&#39;sound.ogg&#39;, &#39;sound.mp3&#39;].\n                                  Alternately, accepts an object: either\n                                  from the HTML5 File API, or a p5.File.</p>\n",
19242            "type": "String|Array"
19243          }, {
19244            "name": "successCallback",
19245            "description": "<p>Name of a function to call once file loads</p>\n",
19246            "type": "Function",
19247            "optional": true
19248          }, {
19249            "name": "errorCallback",
19250            "description": "<p>Name of a function to call if there is\n                                    an error loading the file.</p>\n",
19251            "type": "Function",
19252            "optional": true
19253          }, {
19254            "name": "whileLoading",
19255            "description": "<p>Name of a function to call while file is loading.\n                               This function will receive the percentage loaded\n                               so far, from 0.0 to 1.0.</p>\n",
19256            "type": "Function",
19257            "optional": true
19258          }],
19259          "return": {
19260            "description": "Returns a p5.SoundFile",
19261            "type": "SoundFile"
19262          },
19263          "example": ["\n<div><code>\nfunction preload() {\n mySound = loadSound('assets/doorbell.mp3');\n}\n\nfunction setup() {\n  mySound.setVolume(0.1);\n  mySound.play();\n}\n</code></div>"],
19264          "class": "p5.SoundFile",
19265          "module": "p5.sound",
19266          "submodule": "p5.sound"
19267        }, {
19268          "file": "lib/addons/p5.sound.js",
19269          "line": 1277,
19270          "description": "<p>Returns true if the sound file finished loading successfully.</p>\n",
19271          "itemtype": "method",
19272          "name": "isLoaded",
19273          "return": {
19274            "description": "",
19275            "type": "Boolean"
19276          },
19277          "class": "p5.SoundFile",
19278          "module": "p5.sound",
19279          "submodule": "p5.sound"
19280        }, {
19281          "file": "lib/addons/p5.sound.js",
19282          "line": 1290,
19283          "description": "<p>Play the p5.SoundFile</p>\n",
19284          "itemtype": "method",
19285          "name": "play",
19286          "params": [{
19287            "name": "startTime",
19288            "description": "<p>(optional) schedule playback to start (in seconds from now).</p>\n",
19289            "type": "Number",
19290            "optional": true
19291          }, {
19292            "name": "rate",
19293            "description": "<p>(optional) playback rate</p>\n",
19294            "type": "Number",
19295            "optional": true
19296          }, {
19297            "name": "amp",
19298            "description": "<p>(optional) amplitude (volume)\n                                    of playback</p>\n",
19299            "type": "Number",
19300            "optional": true
19301          }, {
19302            "name": "cueStart",
19303            "description": "<p>(optional) cue start time in seconds</p>\n",
19304            "type": "Number",
19305            "optional": true
19306          }, {
19307            "name": "duration",
19308            "description": "<p>(optional) duration of playback in seconds</p>\n",
19309            "type": "Number",
19310            "optional": true
19311          }],
19312          "class": "p5.SoundFile",
19313          "module": "p5.sound",
19314          "submodule": "p5.sound"
19315        }, {
19316          "file": "lib/addons/p5.sound.js",
19317          "line": 1395,
19318          "description": "<p>p5.SoundFile has two play modes: <code>restart</code> and\n<code>sustain</code>. Play Mode determines what happens to a\np5.SoundFile if it is triggered while in the middle of playback.\nIn sustain mode, playback will continue simultaneous to the\nnew playback. In restart mode, play() will stop playback\nand start over. With untilDone, a sound will play only if it&#39;s\nnot already playing. Sustain is the default mode.</p>\n",
19319          "itemtype": "method",
19320          "name": "playMode",
19321          "params": [{
19322            "name": "str",
19323            "description": "<p>&#39;restart&#39; or &#39;sustain&#39; or &#39;untilDone&#39;</p>\n",
19324            "type": "String"
19325          }],
19326          "example": ["\n<div><code>\nvar mySound;\nfunction preload(){\n  mySound = loadSound('assets/Damscray_DancingTiger.mp3');\n}\nfunction mouseClicked() {\n  mySound.playMode('sustain');\n  mySound.play();\n}\nfunction keyPressed() {\n  mySound.playMode('restart');\n  mySound.play();\n}\n\n </code></div>"],
19327          "class": "p5.SoundFile",
19328          "module": "p5.sound",
19329          "submodule": "p5.sound"
19330        }, {
19331          "file": "lib/addons/p5.sound.js",
19332          "line": 1439,
19333          "description": "<p>Pauses a file that is currently playing. If the file is not\nplaying, then nothing will happen.</p>\n<p>After pausing, .play() will resume from the paused\nposition.\nIf p5.SoundFile had been set to loop before it was paused,\nit will continue to loop after it is unpaused with .play().</p>\n",
19334          "itemtype": "method",
19335          "name": "pause",
19336          "params": [{
19337            "name": "startTime",
19338            "description": "<p>(optional) schedule event to occur\n                             seconds from now</p>\n",
19339            "type": "Number",
19340            "optional": true
19341          }],
19342          "example": ["\n<div><code>\nvar soundFile;\n\nfunction preload() {\n  soundFormats('ogg', 'mp3');\n  soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3');\n}\nfunction setup() {\n  background(0, 255, 0);\n  soundFile.setVolume(0.1);\n  soundFile.loop();\n}\nfunction keyTyped() {\n  if (key == 'p') {\n    soundFile.pause();\n    background(255, 0, 0);\n  }\n}\n\nfunction keyReleased() {\n  if (key == 'p') {\n    soundFile.play();\n    background(0, 255, 0);\n  }\n}\n</code>\n</div>"],
19343          "class": "p5.SoundFile",
19344          "module": "p5.sound",
19345          "submodule": "p5.sound"
19346        }, {
19347          "file": "lib/addons/p5.sound.js",
19348          "line": 1495,
19349          "description": "<p>
19349Loop the p5.SoundFile. Accepts optional parameters to set the\nplayback rate, playback volume, loopStart, loopEnd.</p>\n",
19350          "itemtype": "method",
19351          "name": "loop",
19352          "params": [{
19353            "name": "startTime",
19354            "description": "<p>(optional) schedule event to occur\n                            seconds from now</p>\n",
19355            "type": "Number",
19356            "optional": true
19357          }, {
19358            "name": "rate",
19359            "description": "<p>(optional) playback rate</p>\n",
19360            "type": "Number",
19361            "optional": true
19362          }, {
19363            "name": "amp",
19364            "description": "<p>(optional) playback volume</p>\n",
19365            "type": "Number",
19366            "optional": true
19367          }, {
19368            "name": "cueLoopStart",
19369            "description": "<p>(optional) startTime in seconds</p>\n",
19370            "type": "Number",
19371            "optional": true
19372          }, {
19373            "name": "duration",
19374            "description": "<p>(optional) loop duration in seconds</p>\n",
19375            "type": "Number",
19376            "optional": true
19377          }],
19378          "class": "p5.SoundFile",
19379          "module": "p5.sound",
19380          "submodule": "p5.sound"
19381        }, {
19382          "file": "lib/addons/p5.sound.js",
19383          "line": 1511,
19384          "description": "<p>Set a p5.SoundFile&#39;s looping flag to true or false. If the sound\nis currently playing, this change will take effect when it\nreaches the end of the current playback.</p>\n",
19385          "itemtype": "method",
19386          "name": "setLoop",
19387          "params": [{
19388            "name": "Boolean",
19389            "description": "<p>set looping to true or false</p>\n",
19390            "type": "Boolean"
19391          }],
19392          "class": "p5.SoundFile",
19393          "module": "p5.sound",
19394          "submodule": "p5.sound"
19395        }, {
19396          "file": "lib/addons/p5.sound.js",
19397          "line": 1532,
19398          "description": "<p>Returns &#39;true&#39; if a p5.SoundFile is currently looping and playing, &#39;false&#39; if not.</p>\n",
19399          "itemtype": "method",
19400          "name": "isLooping",
19401          "return": {
19402            "description": "",
19403            "type": "Boolean"
19404          },
19405          "class": "p5.SoundFile",
19406          "module": "p5.sound",
19407          "submodule": "p5.sound"
19408        }, {
19409          "file": "lib/addons/p5.sound.js",
19410          "line": 1547,
19411          "description": "<p>Returns true if a p5.SoundFile is playing, false if not (i.e.\npaused or stopped).</p>\n",
19412          "itemtype": "method",
19413          "name": "isPlaying",
19414          "return": {
19415            "description": "",
19416            "type": "Boolean"
19417          },
19418          "class": "p5.SoundFile",
19419          "module": "p5.sound",
19420          "submodule": "p5.sound"
19421        }, {
19422          "file": "lib/addons/p5.sound.js",
19423          "line": 1557,
19424          "description": "<p>Returns true if a p5.SoundFile is paused, false if not (i.e.\nplaying or stopped).</p>\n",
19425          "itemtype": "method",
19426          "name": "isPaused",
19427          "return": {
19428            "description": "",
19429            "type": "Boolean"
19430          },
19431          "class": "p5.SoundFile",
19432          "module": "p5.sound",
19433          "submodule": "p5.sound"
19434        }, {
19435          "file": "lib/addons/p5.sound.js",
19436          "line": 1567,
19437          "description": "<p>Stop soundfile playback.</p>\n",
19438          "itemtype": "method",
19439          "name": "stop",
19440          "params": [{
19441            "name": "startTime",
19442            "description": "<p>(optional) schedule event to occur\n                            in seconds from now</p>\n",
19443            "type": "Number",
19444            "optional": true
19445          }],
19446          "class": "p5.SoundFile",
19447          "module": "p5.sound",
19448          "submodule": "p5.sound"
19449        }, {
19450          "file": "lib/addons/p5.sound.js",
19451          "line": 1613,
19452          "description": "<p>Multiply the output volume (amplitude) of a sound file\nbetween 0.0 (silence) and 1.0 (full volume).\n1.0 is the maximum amplitude of a digital sound, so multiplying\nby greater than 1.0 may cause digital distortion. To\nfade, provide a <code>rampTime</code> parameter. For more\ncomplex fades, see the Envelope class.</p>\n<p>Alternately, you can pass in a signal source such as an\noscillator to modulate the amplitude with an audio signal.</p>\n",
19453          "itemtype": "method",
19454          "name": "setVolume",
19455          "params": [{
19456            "name": "volume",
19457            "description": "<p>Volume (amplitude) between 0.0\n                                   and 1.0 or modulating signal/oscillator</p>\n",
19458            "type": "Number|Object"
19459          }, {
19460            "name": "rampTime",
19461            "description": "<p>Fade for t seconds</p>\n",
19462            "type": "Number",
19463            "optional": true
19464          }, {
19465            "name": "timeFromNow",
19466            "description": "<p>Schedule this event to happen at\n                               t seconds 
19466in the future</p>\n",
19467            "type": "Number",
19468            "optional": true
19469          }],
19470          "class": "p5.SoundFile",
19471          "module": "p5.sound",
19472          "submodule": "p5.sound"
19473        }, {
19474          "file": "lib/addons/p5.sound.js",
19475          "line": 1654,
19476          "description": "<p>Set the stereo panning of a p5.sound object to\na floating point number between -1.0 (left) and 1.0 (right).\nDefault is 0.0 (center).</p>\n",
19477          "itemtype": "method",
19478          "name": "pan",
19479          "params": [{
19480            "name": "panValue",
19481            "description": "<p>Set the stereo panner</p>\n",
19482            "type": "Number",
19483            "optional": true
19484          }, {
19485            "name": "timeFromNow",
19486            "description": "<p>schedule this event to happen\n                                seconds from now</p>\n",
19487            "type": "Number",
19488            "optional": true
19489          }],
19490          "example": ["\n<div><code>\n\n var ball = {};\n var soundFile;\n\n function preload() {\n   soundFormats('ogg', 'mp3');\n   soundFile = loadSound('assets/beatbox.mp3');\n }\n\n function draw() {\n   background(0);\n   ball.x = constrain(mouseX, 0, width);\n   ellipse(ball.x, height/2, 20, 20)\n }\n\n function mousePressed(){\n   // map the ball's x location to a panning degree\n   // between -1.0 (left) and 1.0 (right)\n   var panning = map(ball.x, 0., width,-1.0, 1.0);\n   soundFile.pan(panning);\n   soundFile.play();\n }\n </div></code>"],
19491          "class": "p5.SoundFile",
19492          "module": "p5.sound",
19493          "submodule": "p5.sound"
19494        }, {
19495          "file": "lib/addons/p5.sound.js",
19496          "line": 1693,
19497          "description": "<p>Returns the current stereo pan position (-1.0 to 1.0)</p>\n",
19498          "itemtype": "method",
19499          "name": "getPan",
19500          "return": {
19501            "description": "Returns the stereo pan setting of the Oscillator\n                         as a number between -1.0 (left) and 1.0 (right).\n                         0.0 is center and default.",
19502            "type": "Number"
19503          },
19504          "class": "p5.SoundFile",
19505          "module": "p5.sound",
19506          "submodule": "p5.sound"
19507        }, {
19508          "file": "lib/addons/p5.sound.js",
19509          "line": 1704,
19510          "description": "<p>Set the playback rate of a sound file. Will change the speed and the pitch.\nValues less than zero will reverse the audio buffer.</p>\n",
19511          "itemtype": "method",
19512          "name": "rate",
19513          "params": [{
19514            "name": "playbackRate",
19515            "description": "<p>Set the playback rate. 1.0 is normal,\n                                   .5 is half-speed, 2.0 is twice as fast.\n                                   Values less than zero play backwards.</p>\n",
19516            "type": "Number",
19517            "optional": true
19518          }],
19519          "example": ["\n<div><code>\nvar song;\n\nfunction preload() {\n  song = loadSound('assets/Damscray_DancingTiger.mp3');\n}\n\nfunction setup() {\n  song.loop();\n}\n\nfunction draw() {\n  background(200);\n\n  // Set the rate to a range between 0.1 and 4\n  // Changing the rate also alters the pitch\n  var speed = map(mouseY, 0.1, height, 0, 2);\n  speed = constrain(speed, 0.01, 4);\n  song.rate(speed);\n\n  // Draw a circle to show what is going on\n  stroke(0);\n  fill(51, 100);\n  ellipse(mouseX, 100, 48, 48);\n}\n\n </code>\n </div>\n"],
19520          "class": "p5.SoundFile",
19521          "module": "p5.sound",
19522          "submodule": "p5.sound"
19523        }, {
19524          "file": "lib/addons/p5.sound.js",
19525          "line": 1777,
19526          "description": "<p>Returns the duration of a sound file in seconds.</p>\n",
19527          "itemtype": "method",
19528          "name": "duration",
19529          "return": {
19530            "description": "The duration of the soundFile in seconds.",
19531            "type": "Number"
19532          },
19533          "class": "p5.SoundFile",
19534          "module": "p5.sound",
19535          "submodule": "p5.sound"
19536        }, {
19537          "file": "lib/addons/p5.sound.js",
19538          "line": 1791,
19539          "description": "<p>Return the current position of the p5.SoundFile playhead, in seconds.\nTime is relative to the normal buffer direction, so if <code>reverseBuffer</code>\nhas been called, currentTime will count backwards.</p>\n",
19540          "itemtype": "method",
19541          "name": "currentTime",
19542          "return": {
19543            "description": "currentTime of the soundFile in seconds.",
19544            "type": "Number"
19545          },
19546          "class": "p5.SoundFile",
19547          "module": "p5.sound",
19548          "submodule": "p5.sound"
19549        }, {
19550          "file": "lib/addons/p5.sound.js",
19551          "line": 1802,
19552          "description": "<p>Move the playhead of the song to a position, in seconds. Start timing\nand playback duration. If none are given, will reset the file to play\nentire duration from start to finish.</p>\n",
19553          "itemtype": "method",
19554          "name": "jump",
19555          "params": [{
19556            "name": "cueTime",
19557            "description": "<p>cueTime of the soundFile in seconds.</p>\n",
19558            "type": "Number"
19559          }, {
19560            "name": "duration",
19561            "description": "<p>duration in seconds.</p>\n",
19562            "type": "Number"
19563          }],
19564          "class": "p5.SoundFile",
19565          "module": "p5.sound",
19566          "submodule": "p5.sound"
19567        }, {
19568          "file": "lib/addons/p5.sound.js",
19569          "line": 1825,
19570          "description": "<p>Return the number of channels in a sound file.\nFor example, Mono = 1, Stereo = 2.</p>\n",
19571          "itemtype": "method",
19572          "name": "channels",
19573          "return": {
19574            "description": "[channels]",
19575            "type": "Number"
19576          },
19577          "class": "p5.SoundFile",
19578          "module": "p5.sound",
19579          "submodule": "p5.sound"
19580        }, {
19581          "file": "lib/addons/p5.sound.js",
19582          "line": 1835,
19583          "description": "<p>Return the sample rate of the sound file.</p>\n",
19584          "itemtype": "method",
19585          "name": "sampleRate",
19586          "return": {
19587            "description": "[sampleRate]",
19588            "type": "Number"
19589          },
19590          "class": "p5.SoundFile",
19591          "module": "p5.sound",
19592          "submodule": "p5.sound"
19593        }, {
19594          "file": "lib/addons/p5.sound.js",
19595          "line": 1844,
19596          "description": "<p>Return the number of samples in a sound file.\nEqual to sampleRate * duration.</p>\n",
19597          "itemtype": "method",
19598          "name": "frames",
19599          "return": {
19600            "description": "[sampleCount]",
19601            "type": "Number"
19602          },
19603          "class": "p5.SoundFile",
19604          "module": "p5.sound",
19605          "submodule": "p5.sound"
19606        }, {
19607          "file": "lib/addons/p5.sound.js",
19608          "line": 1854,
19609          "description": "<p>Returns an array of amplitude peaks in a p5.SoundFile that can be\nused to draw a static waveform. Scans through the p5.SoundFile&#39;s\naudio buffer to find the greatest amplitudes. Accepts one\nparameter, &#39;length&#39;, which determines size of the array.\nLarger arrays result in more precise waveform visualizations.</p>\n<p>Inspired by Wavesurfer.js.</p>\n",
19610          "itemtype": "method",
19611          "name": "getPeaks",
19612          "params": [{
19613            "name": "length",
19614            "description": "<p>length is the size of the returned array.\n                         Larger length results in more precision.\n                         Defaults to 5*width of the browser window.</p>\n",
19615            "type": "Number",
19616            "optional": true
19617          }],
19618          "return": {
19619            "description": "Array of peaks.",
19620            "type": "Float32Array"
19621          },
19622          "class": "p5.SoundFile",
19623          "module": "p5.sound",
19624          "submodule": "p5.sound"
19625        }, {
19626          "file": "lib/addons/p5.sound.js",
19627          "line": 1906,
19628          "description": "<p>Reverses the p5.SoundFile&#39;s buffer source.\nPlayback must be handled separately (see example).</p>\n",
19629          "itemtype": "method",
19630          "name": "reverseBuffer",
19631          "example": ["\n<div><code>\nvar drum;\n\nfunction preload() {\n  drum = loadSound('assets/drum.mp3');\n}\n\nfunction setup() {\n  drum.reverseBuffer();\n  drum.play();\n}\n\n </code>\n </div>"],
19632          "class": "p5.SoundFile",
19633          "module": "p5.sound",
19634          "submodule": "p5.sound"
19635        }, {
19636          "file": "lib/addons/p5.sound.js",
19637          "line": 1946,
19638          "description": "<p>Schedule an event to be called when the soundfile\nreaches the end of a buffer. If the soundfile is\nplaying through once, this will be called when it\nends. If it is looping, it will be called when\nstop is called.</p>\n",
19639          "itemtype": "method",
19640          "name": "onended",
19641          "params": [{
19642            "name": "callback",
19643            "description": "<p>function to call when the\n                            soundfile has ended.</p>\n",
19644            "type": "Function"
19645          }],
19646          "class": "p5.SoundFile",
19647          "module": "p5.sound",
19648          "submodule": "p5.sound"
19649        }, {
19650          "file": "lib/addons/p5.sound.js",
19651          "line": 1999,
19652          "description": "<p>Connects the output of a p5sound object to input of another\np5.sound object. For example, you may connect a p5.SoundFile to an\nFFT or an Effect. If no parameter is given, it will connect to\nthe master output. Most p5sound objects connect to the master\noutput when they are created.</p>\n",
19653          "itemtype": "method",
19654          "name": "connect",
19655          "params": [{
19656            "name": "object",
19657            "description": "<p>Audio object that accepts an input</p>\n",
19658            "type": "Object",
19659            "optional": true
19660          }],
19661          "class": "p5.SoundFile",
19662          "module": "p5.sound",
19663          "submodule": "p5.sound"
19664        }, {
19665          "file": "lib/addons/p5.sound.js",
19666          "line": 2020,
19667          "description": "<p>Disconnects the output of this p5sound object.</p>\n",
19668          "itemtype": "method",
19669          "name": "disconnect",
19670          "class": "p5.SoundFile",
19671          "module": "p5.sound",
19672          "submodule": "p5.sound"
19673        }, {
19674          "file": "lib/addons/p5.sound.js",
19675          "line": 2030,
19676          "class": "p5.SoundFile",
19677          "module": "p5.sound",
19678          "submodule": "p5.sound"
19679        }, {
19680          "file": "lib/addons/p5.sound.js",
19681          "line": 2035,
19682          "description": "<p>Reset the source for this SoundFile to a\nnew path (URL).</p>\n",
19683          "itemtype": "method",
19684          "name": "setPath",
19685          "params": [{
19686            "name": "path",
19687            "description": "<p>path to audio file</p>\n",
19688            "type": "String"
19689          }, {
19690            "name": "callback",
19691            "description": "<p>Callback</p>\n",
19692            "type": "Function"
19693          }],
19694          "class": "p5.SoundFile",
19695          "module": "p5.sound",
19696          "submodule": "p5.sound"
19697        }, {
19698          "file": "lib/addons/p5.sound.js",
19699          "line": 2048,
19700          "description": "<p>Replace the current Audio Buffer with a new Buffer.</p>\n",
19701          "itemtype": "method",
19702          "name": "setBuffer",
19703          "params": [{
19704            "name": "buf",
19705            "description": "<p>Array of Float32 Array(s). 2 Float32 Arrays\n                   will create a stereo source. 1 will create\n                   a mono source.</p>\n",
19706            "type": "Array"
19707          }],
19708          "class": "p5.SoundFile",
19709          "module": "p5.sound",
19710          "submodule": "p5.sound"
19711        }, {
19712          "file": "lib/addons/p5.sound.js",
19713          "line": 2120,
19714          "description": "<p>processPeaks returns an array of timestamps where it thinks there is a beat.</p>\n<p>This is an asynchronous function that processes the soundfile in an offline audio context,\nand sends the results to your callback function.</p>\n<p>The process involves running the soundfile through a lowpass filter, and finding all of the\npeaks above the initial threshold. If the total number of peaks are below the minimum number of peaks,\nit decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached.</p>\n",
19715          "itemtype": "method",
19716          "name": "processPeaks",
19717          "params": [{
19718            "name": "callback",
19719            "description": "<p>a function to call once this data is returned</p>\n",
19720            "type": "Function"
19721          }, {
19722            "name": "initThreshold",
19723            "description": "<p>initial threshold defaults to 0.9</p>\n",
19724            "type": "Number",
19725            "optional": true
19726          }, {
19727            "name": "minThreshold",
19728            "description": "<p>minimum threshold defaults to 0.22</p>\n",
19729            "type": "Number",
19730            "optional": true
19731          }, {
19732            "name": "minPeaks",
19733            "description": "<p>minimum number of peaks defaults to 200</p>\n",
19734            "type": "Number",
19735            "optional": true
19736          }],
19737          "return": {
19738            "description": "Array of timestamped peaks",
19739            "type": "Array"
19740          },
19741          "class": "p5.SoundFile",
19742          "module": "p5.sound",
19743          "submodule": "p5.sound"
19744        }, {
19745          "file": "lib/addons/p5.sound.js",
19746          "line": 2313,
19747          "class": "p5.SoundFile",
19748          "module": "p5.sound",
19749          "submodule": "p5.sound"
19750        }, {
19751          "file": "lib/addons/p5.sound.js",
19752          "line": 2322,
19753          "description": "<p>Schedule events to trigger every time a MediaElement\n(audio/video) reaches a playback cue point.</p>\n<p>Accepts a callback function, a time (in seconds) at which to trigger\nthe callback, and an optional parameter for the callback.</p>\n<p>Time will be passed as the first parameter to the callback function,\nand param will be the second parameter.</p>\n",
19754          "itemtype": "method",
19755          "name": "addCue",
19756          "params": [{
19757            "name": "time",
19758            "description": "<p>Time in seconds, relative to this media\n                           element&#39;s playback. For example, to trigger\n                           an event every time playback reaches two\n                           seconds, pass in the number 2. This will be\n                           passed as the first parameter to\n                           the callback function.</p>\n",
19759            "type": "Number"
19760          }, {
19761            "name": "callback",
19762            "description": "<p>Name of a function that will be\n                           called at the given time. The callback will\n                           receive time and (optionally) param as its\n                           two parameters.</p>\n",
19763            "type": "Function"
19764          }, {
19765            "name": "value",
19766            "description": "<p>An object to be passed as the\n                           second parameter to the\n                           callback function.</p>\n",
19767            "type": "Object",
19768            "optional": true
19769          }],
19770          "return": {
19771            "description": "id ID of this cue,\n                    useful for removeCue(id)",
19772            "type": "Number"
19773          },
19774          "example": ["\n<div><code>\nvar mySound;\nfunction preload() {\n  mySound = loadSound('assets/beat.mp3');\n}\n\nfunction setup() {\n  background(0);\n  noStroke();\n  fill(255);\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n\n  // schedule calls to changeText\n  mySound.addCue(0.50, changeText, \"hello\" );\n  mySound.addCue(1.00, changeText, \"p5\" );\n  mySound.addCue(1.50, changeText, \"what\" );\n  mySound.addCue(2.00, changeText, \"do\" );\n  mySound.addCue(2.50, changeText, \"you\" );\n  mySound.addCue(3.00, changeText, \"want\" );\n  mySound.addCue(4.00, changeText, \"to\" );\n  mySound.addCue(5.00, changeText, \"make\" );
19774\n  mySound.addCue(6.00, changeText, \"?\" );\n}\n\nfunction changeText(val) {\n  background(0);\n  text(val, width/2, height/2);\n}\n\nfunction mouseClicked() {\n  if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n    if (mySound.isPlaying() ) {\n      mySound.stop();\n    } else {\n      mySound.play();\n    }\n  }\n}\n</code></div>"],
19775          "class": "p5.SoundFile",
19776          "module": "p5.sound",
19777          "submodule": "p5.sound"
19778        }, {
19779          "file": "lib/addons/p5.sound.js",
19780          "line": 2400,
19781          "description": "<p>Remove a callback based on its ID. The ID is returned by the\naddCue method.</p>\n",
19782          "itemtype": "method",
19783          "name": "removeCue",
19784          "params": [{
19785            "name": "id",
19786            "description": "<p>ID of the cue, as returned by addCue</p>\n",
19787            "type": "Number"
19788          }],
19789          "class": "p5.SoundFile",
19790          "module": "p5.sound",
19791          "submodule": "p5.sound"
19792        }, {
19793          "file": "lib/addons/p5.sound.js",
19794          "line": 2419,
19795          "description": "<p>Remove all of the callbacks that had originally been scheduled\nvia the addCue method.</p>\n",
19796          "itemtype": "method",
19797          "name": "clearCues",
19798          "class": "p5.SoundFile",
19799          "module": "p5.sound",
19800          "submodule": "p5.sound"
19801        }, {
19802          "file": "lib/addons/p5.sound.js",
19803          "line": 2444,
19804          "description": "<p>Save a p5.SoundFile as a .wav file. The browser will prompt the user\nto download the file to their device. To upload a file to a server, see\n<a href=\"/docs/reference/#/p5.SoundFile/getBlob\">getBlob</a></p>\n",
19805          "itemtype": "method",
19806          "name": "save",
19807          "params": [{
19808            "name": "fileName",
19809            "description": "<p>name of the resulting .wav file.</p>\n",
19810            "type": "String",
19811            "optional": true
19812          }],
19813          "example": ["\n <div><code>\n var inp, button, mySound;\n var fileName = 'cool';\n function preload() {\n   mySound = loadSound('assets/doorbell.mp3');\n }\n function setup() {\n   btn = createButton('click to save file');\n   btn.position(0, 0);\n   btn.mouseClicked(handleMouseClick);\n }\n\n function handleMouseClick() {\n   mySound.save(fileName);\n }\n</code></div>"],
19814          "class": "p5.SoundFile",
19815          "module": "p5.sound",
19816          "submodule": "p5.sound"
19817        }, {
19818          "file": "lib/addons/p5.sound.js",
19819          "line": 2473,
19820          "description": "<p>This method is useful for sending a SoundFile to a server. It returns the\n.wav-encoded audio data as a &quot;<a target=\"_blank\" title=\"Blob reference at\nMDN\" href=\"https://developer.mozilla.org/en-US/docs/Web/API/Blob\">Blob</a>&quot;.\nA Blob is a file-like data object that can be uploaded to a server\nwith an <a href=\"/docs/reference/#/p5/httpDo\">http</a> request. We&#39;ll\nuse the <code>httpDo</code> options object to send a POST request with some\nspecific options: we encode the request as <code>multipart/form-data</code>,\nand attach the blob as one of the form values using <code>FormData</code>.</p>\n",
19821          "itemtype": "method",
19822          "name": "getBlob",
19823          "return": {
19824            "description": "A file-like data object",
19825            "type": "Blob"
19826          },
19827          "example": ["\n <div><code>\n\n function preload() {\n   mySound = loadSound('assets/doorbell.mp3');\n }\n\n function setup() {\n   noCanvas();\n   var soundBlob = mySound.getBlob();\n\n   // Now we can send the blob to a server...\n   var serverUrl = 'https://jsonplaceholder.typicode.com/posts';\n   var httpRequestOptions = {\n     method: 'POST',\n     body: new FormData().append('soundBlob', soundBlob),\n     headers: new Headers({\n       'Content-Type': 'multipart/form-data'\n     })\n   };\n   httpDo(serverUrl, httpRequestOptions);\n\n   // We can also create an `ObjectURL` pointing to the Blob\n   var blobUrl = URL.createObjectURL(soundBlob);\n\n   // The `<Audio>` Element accepts Object URL's\n   var htmlAudioElt = createAudio(blobUrl).showControls();\n\n   createDiv();\n\n   // The ObjectURL exists as long as this tab is open\n   var input = createInput(blobUrl);\n   input.attribute('readonly', true);\n   input.mouseClicked(function() { input.elt.select() });\n }\n\n</code></div>"],
19828          "class": "p5.SoundFile",
19829          "module": "p5.sound",
19830          "submodule": "p5.sound"
19831        }, {
19832          "file": "lib/addons/p5.sound.js",
19833          "line": 2611,
19834          "description": "<p>Connects to the p5sound instance (master output) by default.\nOptionally, you can pass in a specific source (i.e. a soundfile).</p>\n",
19835          "itemtype": "method",
19836          "name": "setInput",
19837          "params": [{
19838            "name": "snd",
19839            "description": "<p>set the sound source\n                                     (optional, defaults to\n                                     master output)</p>\n",
19840            "type": "SoundObject|undefined",
19841            "optional": true
19842          }, {
19843            "name": "smoothing",
19844            "description": "<p>a range between 0.0 and 1.0\n                                      to smooth amplitude readings</p>\n",
19845            "type": "Number|undefined",
19846            "optional": true
19847          }],
19848          "example": ["\n<div><code>\nfunction preload(){\n  sound1 = loadSound('assets/beat.mp3');\n  sound2 = loadSound('assets/drum.mp3');\n}\nfunction setup(){\n  amplitude = new p5.Amplitude();\n  sound1.play();\n  sound2.play();\n  amplitude.setInput(sound2);\n}\nfunction draw() {\n  background(0);\n  fill(255);\n  var level = amplitude.getLevel();\n  var size = map(level, 0, 1, 0, 200);\n  ellipse(width/2, height/2, size, size);\n}\nfunction mouseClicked(){\n  sound1.stop();\n  sound2.stop();\n}\n</code></div>"],
19849          "class": "p5.Amplitude",
19850          "module": "p5.sound",
19851          "submodule": "p5.sound"
19852        }, {
19853          "file": "lib/addons/p5.sound.js",
19854          "line": 2718,
19855          "description": "<p>Returns a single Amplitude reading at the moment it is called.\nFor continuous readings, run in the draw loop.</p>\n",
19856          "itemtype": "method",
19857          "name": "getLevel",
19858          "params": [{
19859            "name": "channel",
19860            "description": "<p>Optionally return only channel 0 (left) or 1 (right)</p>\n",
19861            "type": "Number",
19862            "optional": true
19863          }],
19864          "return": {
19865            "description": "Amplitude as a number between 0.0 and 1.0",
19866            "type": "Number"
19867          },
19868          "example": ["\n<div><code>\nfunction preload(){\n  sound = loadSound('assets/beat.mp3');\n}\nfunction setup() {\n  amplitude = new p5.Amplitude();\n  sound.play();\n}\nfunction draw() {\n  background(0);\n  fill(255);\n  var level = amplitude.getLevel();\n  var size = map(level, 0, 1, 0, 200);\n  ellipse(width/2, height/2, size, size);\n}\nfunction mouseClicked(){\n  sound.stop();\n}\n</code></div>"],
19869          "class": "p5.Amplitude",
19870          "module": "p5.sound",
19871          "submodule": "p5.sound"
19872        }, {
19873          "file": "lib/addons/p5.sound.js",
19874          "line": 2759,
19875          "description": "<p>Determines whether the results of Amplitude.process() will be\nNormalized. To normalize, Amplitude finds the difference the\nloudest reading it has processed and the maximum amplitude of\n1.0. Amplitude adds this difference to all values to produce\nresults that will reliably map between 0.0 and 1.0. However,\nif a louder moment occurs, the amount that Normalize adds to\nall the values will change. Accepts an optional boolean parameter\n(true or false). Normalizing is off by default.</p>\n",
19876          "itemtype": "method",
19877          "name": "toggleNormalize",
19878          "params": [{
19879            "name": "boolean",
19880            "description": "<p>set normalize to true (1) or false (0)</p>\n",
19881            "type": "Boolean",
19882            "optional": true
19883          }],
19884          "class": "p5.Amplitude",
19885          "module": "p5.sound",
19886          "submodule": "p5.sound"
19887        }, {
19888          "file": "lib/addons/p5.sound.js",
19889          "line": 2779,
19890          "description": "<p>Smooth Amplitude analysis by averaging with the last analysis\nframe. Off by default.</p>\n",
19891          "itemtype": "method",
19892          "name": "smooth",
19893          "params": [{
19894            "name": "set",
19895            "description": "<p>smoothing from 0.0 &lt;= 1</p>\n",
19896            "type": "Number"
19897          }],
19898          "class": "p5.Amplitude",
19899          "module": "p5.sound",
19900          "submodule": "p5.sound"
19901        }, {
19902          "file": "lib/addons/p5.sound.js",
19903          "line": 2953,
19904          "description": "<p>Set the input source for the FFT analysis. If no source is\nprovided, FFT will analyze all sound in the sketch.</p>\n",
19905          "itemtype": "method",
19906          "name": "setInput",
19907          "params": [{
19908            "name": "source",
19909            "description": "<p>p5.sound object (or web audio API source node)</p>\n",
19910            "type": "Object",
19911            "optional": true
19912          }],
19913          "class": "p5.FFT",
19914          "module": "p5.sound",
19915          "submodule": "p5.sound"
19916        }, {
19917          "file": "lib/addons/p5.sound.js",
19918          "line": 2972,
19919          "description": "<p>Returns an array of amplitude values (between -1.0 and +1.0) that represent\na snapshot of amplitude readings in a single buffer. Length will be\nequal to bins (defaults to 1024). Can be used to draw the waveform\nof a sound.</p>\n",
19920          "itemtype": "method",
19921          "name": "waveform",
19922          "params": [{
19923            "name": "bins",
19924            "description": "<p>Must be a power of two between\n                          16 and 1024. Defaults to 1024.</p>\n",
19925            "type": "Number",
19926            "optional": true
19927          }, {
19928            "name": "precision",
19929            "description": "<p>If any value is provided, will return results\n                            in a Float32 Array which is more precise\n                            than a regular array.</p>\n",
19930            "type": "String",
19931            "optional": true
19932          }],
19933          "return": {
19934            "description": "Array    Array of amplitude values (-1 to 1)\n                          over time. Array length = bins.",
19935            "type": "Array"
19936          },
19937          "class": "p5.FFT",
19938          "module": "p5.sound",
19939          "submodule": "p5.sound"
19940        }, {
19941          "file": "lib/addons/p5.sound.js",
19942          "line": 3015,
19943          "description": "<p>Returns an array of amplitude values (between 0 and 255)\nacross the frequency spectrum. Length is equal to FFT bins\n(1024 by default). The array indices correspond to frequencies\n(i.e. pitches), from the lowest to the highest that humans can\nhear. Each value represents amplitude at that slice of the\nfrequency spectrum. Must be called prior to using\n<code>getEnergy()</code>.</p>\n",
19944          "itemtype": "method",
19945          "name": "analyze",
19946          "params": [{
19947            "name": "bins",
19948            "description": "<p>Must be a power of two between\n                           16 and 1024. Defaults to 1024.</p>\n",
19949            "type": "Number",
19950            "optional": true
19951          }, {
19952            "name": "scale",
19953            "description": "<p>If &quot;dB,&quot; returns decibel\n                           float measurements between\n                           -14
199530 and 0 (max).\n                           Otherwise returns integers from 0-255.</p>\n",
19954            "type": "Number",
19955            "optional": true
19956          }],
19957          "return": {
19958            "description": "spectrum    Array of energy (amplitude/volume)\n                            values across the frequency spectrum.\n                            Lowest energy (silence) = 0, highest\n                            possible is 255.",
19959            "type": "Array"
19960          },
19961          "example": ["\n<div><code>\nvar osc;\nvar fft;\n\nfunction setup(){\n  createCanvas(100,100);\n  osc = new p5.Oscillator();\n  osc.amp(0);\n  osc.start();\n  fft = new p5.FFT();\n}\n\nfunction draw(){\n  background(0);\n\n  var freq = map(mouseX, 0, 800, 20, 15000);\n  freq = constrain(freq, 1, 20000);\n  osc.freq(freq);\n\n  var spectrum = fft.analyze();\n  noStroke();\n  fill(0,255,0); // spectrum is green\n  for (var i = 0; i< spectrum.length; i++){\n    var x = map(i, 0, spectrum.length, 0, width);\n    var h = -height + map(spectrum[i], 0, 255, height, 0);\n    rect(x, height, width / spectrum.length, h );\n  }\n\n  stroke(255);\n  text('Freq: ' + round(freq)+'Hz', 10, 10);\n\n  isMouseOverCanvas();\n}\n\n// only play sound when mouse is over canvas\nfunction isMouseOverCanvas() {\n  var mX = mouseX, mY = mouseY;\n  if (mX > 0 && mX < width && mY < height && mY > 0) {\n    osc.amp(0.5, 0.2);\n  } else {\n    osc.amp(0, 0.2);\n  }\n}\n</code></div>\n\n"],
19962          "class": "p5.FFT",
19963          "module": "p5.sound",
19964          "submodule": "p5.sound"
19965        }, {
19966          "file": "lib/addons/p5.sound.js",
19967          "line": 3107,
19968          "description": "<p>Returns the amount of energy (volume) at a specific\n<a href=\"https://en.wikipedia.org/wiki/Audio_frequency\" target=\"_blank\">\nfrequency</a>, or the average amount of energy between two\nfrequencies. Accepts Number(s) corresponding\nto frequency (in Hz), or a String corresponding to predefined\nfrequency ranges (&quot;bass&quot;, &quot;lowMid&quot;, &quot;mid&quot;, &quot;highMid&quot;, &quot;treble&quot;).\nReturns a range between 0 (no energy/volume at that frequency) and\n255 (maximum energy).\n<em>NOTE: analyze() must be called prior to getEnergy(). Analyze()\ntells the FFT to analyze frequency data, and getEnergy() uses\nthe results determine the value at a specific frequency or\nrange of frequencies.</em></p></p>\n",
19969          "itemtype": "method",
19970          "name": "getEnergy",
19971          "params": [{
19972            "name": "frequency1",
19973            "description": "<p>Will return a value representing\n                              energy at this frequency. Alternately,\n                              the strings &quot;bass&quot;, &quot;lowMid&quot; &quot;mid&quot;,\n                              &quot;highMid&quot;, and &quot;treble&quot; will return\n                              predefined frequency ranges.</p>\n",
19974            "type": "Number|String"
19975          }, {
19976            "name": "frequency2",
19977            "description": "<p>If a second frequency is given,\n                              will return average amount of\n                              energy that exists between the\n                              two frequencies.</p>\n",
19978            "type": "Number",
19979            "optional": true
19980          }],
19981          "return": {
19982            "description": "Energy   Energy (volume/amplitude) from\n                            0 and 255.",
19983            "type": "Number"
19984          },
19985          "class": "p5.FFT",
19986          "module": "p5.sound",
19987          "submodule": "p5.sound"
19988        }, {
19989          "file": "lib/addons/p5.sound.js",
19990          "line": 3189,
19991          "description": "<p>Returns the\n<a href=\"http://en.wikipedia.org/wiki/Spectral_centroid\" target=\"_blank\">\nspectral centroid</a> of the input signal.\n<em>NOTE: analyze() must be called prior to getCentroid(). Analyze()\ntells the FFT to analyze frequency data, and getCentroid() uses\nthe results determine the spectral centroid.</em></p></p>\n",
19992          "itemtype": "method",
19993          "name": "getCentroid",
19994          "return": {
19995            "description": "Spectral Centroid Frequency   Frequency of the spectral centroid in Hz.",
19996            "type": "Number"
19997          },
19998          "example": ["\n<div><code>\n\n\nfunction setup(){\ncnv = createCanvas(100,100);\nsound = new p5.AudioIn();\nsound.start();\nfft = new p5.FFT();\nsound.connect(fft);\n}\n\n\nfunction draw(){\n\nvar centroidplot = 0.0;\nvar spectralCentroid = 0;\n\n\nbackground(0);\nstroke(0,255,0);\nvar spectrum = fft.analyze();\nfill(0,255,0); // spectrum is green\n\n//draw the spectrum\nfor (var i = 0; i< spectrum.length; i++){\n  var x = map(log(i), 0, log(spectrum.length), 0, width);
19998\n  var h = map(spectrum[i], 0, 255, 0, height);\n  var rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length));\n  rect(x, height, rectangle_width, -h )\n}\n\nvar nyquist = 22050;\n\n// get the centroid\nspectralCentroid = fft.getCentroid();\n\n// the mean_freq_index calculation is for the display.\nvar mean_freq_index = spectralCentroid/(nyquist/spectrum.length);\n\ncentroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width);\n\n\nstroke(255,0,0); // the line showing where the centroid is will be red\n\nrect(centroidplot, 0, width / spectrum.length, height)\nnoStroke();\nfill(255,255,255);  // text is white\ntext(\"centroid: \", 10, 20);\ntext(round(spectralCentroid)+\" Hz\", 10, 40);\n}\n </code></div>"],
19999          "class": "p5.FFT",
20000          "module": "p5.sound",
20001          "submodule": "p5.sound"
20002        }, {
20003          "file": "lib/addons/p5.sound.js",
20004          "line": 3269,
20005          "description": "<p>Smooth FFT analysis by averaging with the last analysis frame.</p>\n",
20006          "itemtype": "method",
20007          "name": "smooth",
20008          "params": [{
20009            "name": "smoothing",
20010            "description": "<p>0.0 &lt; smoothing &lt; 1.0.\n                             Defaults to 0.8.</p>\n",
20011            "type": "Number"
20012          }],
20013          "class": "p5.FFT",
20014          "module": "p5.sound",
20015          "submodule": "p5.sound"
20016        }, {
20017          "file": "lib/addons/p5.sound.js",
20018          "line": 3291,
20019          "description": "<p>Returns an array of average amplitude values for a given number\nof frequency bands split equally. N defaults to 16.\n<em>NOTE: analyze() must be called prior to linAverages(). Analyze()\ntells the FFT to analyze frequency data, and linAverages() uses\nthe results to group them into a smaller set of averages.</em></p></p>\n",
20020          "itemtype": "method",
20021          "name": "linAverages",
20022          "params": [{
20023            "name": "N",
20024            "description": "<p>Number of returned frequency groups</p>\n",
20025            "type": "Number"
20026          }],
20027          "return": {
20028            "description": "linearAverages   Array of average amplitude values for each group",
20029            "type": "Array"
20030          },
20031          "class": "p5.FFT",
20032          "module": "p5.sound",
20033          "submodule": "p5.sound"
20034        }, {
20035          "file": "lib/addons/p5.sound.js",
20036          "line": 3321,
20037          "description": "<p>Returns an array of average amplitude values of the spectrum, for a given\nset of <a href=\"https://en.wikipedia.org/wiki/Octave_band\" target=\"_blank\">\nOctave Bands</a>\n<em>NOTE: analyze() must be called prior to logAverages(). Analyze()\ntells the FFT to analyze frequency data, and logAverages() uses\nthe results to group them into a smaller set of averages.</em></p></p>\n",
20038          "itemtype": "method",
20039          "name": "logAverages",
20040          "params": [{
20041            "name": "octaveBands",
20042            "description": "<p>Array of Octave Bands objects for grouping</p>\n",
20043            "type": "Array"
20044          }],
20045          "return": {
20046            "description": "logAverages    Array of average amplitude values for each group",
20047            "type": "Array"
20048          },
20049          "class": "p5.FFT",
20050          "module": "p5.sound",
20051          "submodule": "p5.sound"
20052        }, {
20053          "file": "lib/addons/p5.sound.js",
20054          "line": 3351,
20055          "description": "<p>Calculates and Returns the 1/N\n<a href=\"https://en.wikipedia.org/wiki/Octave_band\" target=\"_blank\">Octave Bands</a>\nN defaults to 3 and minimum central frequency to 15.625Hz.\n(1/3 Octave Bands ~= 31 Frequency Bands)\nSetting fCtr0 to a central value of a higher octave will ignore the lower bands\nand produce less frequency groups.</p>\n",
20056          "itemtype": "method",
20057          "name": "getOctaveBands",
20058          "params": [{
20059            "name": "N",
20060            "description": "<p>Specifies the 1/N type of generated octave bands</p>\n",
20061            "type": "Number"
20062          }, {
20063            "name": "fCtr0",
20064            "description": "<p>Minimum central frequency for the lowest band</p>\n",
20065            "type": "Number"
20066          }],
20067          "return": {
20068            "description": "octaveBands   Array of octave band objects with their bounds",
20069            "type": "Array"
20070          },
20071          "class": "p5.FFT",
20072          "module": "p5.sound",
20073          "submodule": "p5.sound"
20074        }, {
20075          "file": "lib/addons/p5.sound.js",
20076          "line": 3409,
20077          "class": "p5.FFT",
20078          "module": "p5.sound",
20079          "submodule": "p5.sound"
20080        }, {
20081          "file": "lib/addons/p5.sound.js",
20082          "line": 3786,
20083          "class": "p5.FFT",
20084          "module": "p5.sound",
20085          "submodule": "p5.sound"
20086        }, {
20087          "file": "lib/addons/p5.sound.js",
20088          "line": 3807,
20089          "class": "p5.FFT",
20090          "module": "p5.sound",
20091          "submodule": "p5.sound"
20092        }, {
20093          "file": "lib/addons/p5.sound.js",
20094          "line": 3866,
20095          "class": "p5.FFT",
20096          "module": "p5.sound",
20097          "submodule": "p5.sound"
20098        }, {
20099          "file": "lib/addons/p5.sound.js",
20100          "line": 4184,
20101          "class": "p5.FFT",
20102          "module": "p5.sound",
20103          "submodule": "p5.sound"
20104        }, {
20105          "file": "lib/addons/p5.sound.js",
20106          "line": 4356,
20107          "class": "p5.FFT",
20108          "module": "p5.sound",
20109          "submodule": "p5.sound"
20110        }, {
20111          "file": "lib/addons/p5.sound.js",
20112          "line": 4514,
20113          "class": "p5.FFT",
20114          "module": "p5.sound",
20115          "submodule": "p5.sound"
20116        }, {
20117          "file": "lib/addons/p5.sound.js",
20118          "line": 4555,
20119          "class": "p5.FFT",
20120          "module": "p5.sound",
20121          "submodule": "p5.sound"
20122        }, {
20123          "file": "lib/addons/p5.sound.js",
20124          "line": 4625,
20125          "class": "p5.FFT",
20126          "module": "p5.sound",
20127          "submodule": "p5.sound"
20128        }, {
20129          "file": "lib/addons/p5.sound.js",
20130          "line": 4813,
20131          "class": "p5.FFT",
20132          "module": "p5.sound",
20133          "submodule": "p5.sound"
20134        }, {
20135          "file": "lib/addons/p5.sound.js",
20136          "line": 4870,
20137          "class": "p5.FFT",
20138          "module": "p5.sound",
20139          "submodule": "p5.sound"
20140        }, {
20141          "file": "lib/addons/p5.sound.js",
20142          "line": 5038,
20143          "class": "p5.FFT",
20144          "module": "p5.sound",
20145          "submodule": "p5.sound"
20146        }, {
20147          "file": "lib/addons/p5.sound.js",
20148          "line": 5086,
20149          "class": "p5.FFT",
20150          "module": "p5.sound",
20151          "submodule": "p5.sound"
20152        }, {
20153          "file": "lib/addons/p5.sound.js",
20154          "line": 5117,
20155          "class": "p5.FFT",
20156          "module": "p5.sound",
20157          "submodule": "p5.sound"
20158        }, {
20159          "file": "lib/addons/p5.sound.js",
20160          "line": 5138,
20161          "class": "p5.FFT",
20162          "module": "p5.sound",
20163          "submodule": "p5.sound"
20164        }, {
20165          "file": "lib/addons/p5.sound.js",
20166          "line": 5158,
20167          "class": "p5.FFT",
20168          "module": "p5.sound",
20169          "submodule": "p5.sound"
20170        }, {
20171          "file": "lib/addons/p5.sound.js",
20172          "line": 5260,
20173          "description": "<p>Fade to value, for smooth transitions</p>\n",
20174          "itemtype": "method",
20175          "name": "fade",
20176          "params": [{
20177            "name": "value",
20178            "description": "<p>Value to set this signal</p>\n",
20179            "type": "Number"
20180          }, {
20181            "name": "secondsFromNow",
20182            "description": "<p>Length of fade, in seconds from now</p>\n",
20183            "type": "Number",
20184            "optional": true
20185          }],
20186          "class": "p5.Signal",
20187          "module": "p5.sound",
20188          "submodule": "p5.sound"
20189        }, {
20190          "file": "lib/addons/p5.sound.js",
20191          "line": 5271,
20192          "description": "<p>Connect a p5.sound object or Web Audio node to this\np5.Signal so that its amplitude values can be scaled.</p>\n",
20193          "itemtype": "method",
20194          "name": "setInput",
20195          "params": [{
20196            "name": "input",
20197            "description": "",
20198            "type": "Object"
20199          }],
20200          "class": "p5.Signal",
20201          "module": "p5.sound",
20202          "submodule": "p5.sound"
20203        }, {
20204          "file": "lib/addons/p5.sound.js",
20205          "line": 5285,
20206          "description": "<p>Add a constant value to this audio signal,\nand return the resulting audio signal. Does\nnot change the value of the original signal,\ninstead it returns a new p5.SignalAdd.</p>\n",
20207          "itemtype": "method",
20208          "name": "add",
20209          "params": [{
20210            "name": "number",
20211            "description": "",
20212            "type": "Number"
20213          }],
20214          "return": {
20215            "description": "object",
20216            "type": "p5.Signal"
20217          },
20218          "class": "p5.Signal",
20219          "module": "p5.sound",
20220          "submodule": "p5.sound"
20221        }, {
20222          "file": "lib/addons/p5.sound.js",
20223          "line": 5304,
20224          "description": "<p>Multiply this signal by a constant value,\nand return the resulting audio signal. Does\nnot change the value of the original signal,\ninstead it returns a new p5.SignalMult.</p>\n",
20225          "itemtype": "method",
20226          "name": "mult",
20227          "params": [{
20228            "name": "number",
20229            "description": "<p>to multiply</p>\n",
20230            "type": "Number"
20231          }],
20232          "return": {
20233            "description": "object",
20234            "type": "p5.Signal"
20235          },
20236          "class": "p5.Signal",
20237          "module": "p5.sound",
20238          "submodule": "p5.sound"
20239        }, {
20240          "file": "lib/addons/p5.sound.js",
20241          "line": 5323,
20242          "description": "<p>Scale this signal value to a given range,\nand return the result as an audio signal. Does\nnot change the value of the original signal,\ninstead it returns a new p5.SignalScale.</p>\n",
20243          "itemtype": "method",
20244          "name": "scale",
20245          "params": [{
20246            "name": "number",
20247            "description": "<p>to multiply</p>\n",
20248            "type": "Number"
20249          }, {
20250            "name": "inMin",
20251            "description": "<p>input range minumum</p>\n",
20252            "type": "Number"
20253          }, {
20254            "name": "inMax",
20255            "description": "<p>input range maximum</p>\n",
20256            "type": "Number"
20257          }, {
20258            "name": "outMin",
20259            "description": "<p>input range minumum</p>\n",
20260            "type": "Number"
20261          }, {
20262            "name": "outMax",
20263            "description": "<p>input range maximum</p>\n",
20264            "type": "Number"
20265          }],
20266          "return": {
20267            "description": "object",
20268            "type": "p5.Signal"
20269          },
20270          "class": "p5.Signal",
20271          "module": "p5.sound",
20272          "submodule": "p5.sound"
20273        }, {
20274          "file": "lib/addons/p5.sound.js",
20275          "line": 5457,
20276          "description": "<p>Start an oscillator. Accepts an optional parameter to\ndetermine how long (in seconds from now) until the\noscillator starts.</p>\n",
20277          "itemtype": "method",
20278          "name": "start",
20279          "params": [{
20280            "name": "time",
20281            "description": "<p>startTime in seconds from now.</p>\n",
20282            "type": "Number",
20283            "optional": true
20284          }, {
20285            "name": "frequency",
20286            "description": "<p>frequency in Hz.</p>\n",
20287            "type": "Number",
20288            "optional": true
20289          }],
20290          "class": "p5.Oscillator",
20291          "module": "p5.sound",
20292          "submodule": "p5.sound"
20293        }, {
20294          "file": "lib/addons/p5.sound.js",
20295          "line": 5497,
20296          "description": "<p>Stop an oscillator. Accepts an optional parameter\nto determine how long (in seconds from now) until the\noscillator stops.</p>\n",
20297          "itemtype": "method",
20298          "name": "stop",
20299          "params": [{
20300            "name": "secondsFromNow",
20301            "description": "<p>Time, in seconds from now.</p>\n",
20302            "type": "Number"
20303          }],
20304          "class": "p5.Oscillator",
20305          "module": "p5.sound",
20306          "submodule": "p5.sound"
20307        }, {
20308          "file": "lib/addons/p5.sound.js",
20309          "line": 5513,
20310          "description": "<p>Set the amplitude between 0 and 1.0. Or, pass in an object\nsuch as an oscillator to modulate amplitude with an audio signal.</p>\n",
20311          "itemtype": "method",
20312          "name": "amp",
20313          "params": [{
20314            "name": "vol",
20315            "description": "<p>between 0 and 1.0\n                            or a modulating signal/oscillator</p>\n",
20316            "type": "Number|Object"
20317          }, {
20318            "name": "rampTime",
20319            "description": "<p>create a fade that lasts rampTime</p>\n",
20320            "type": "Number",
20321            "optional": true
20322          }, {
20323            "name": "timeFromNow",
20324            "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
20325            "type": "Number",
20326            "optional": true
20327          }],
20328          "return": {
20329            "description": "gain  If no value is provided,\n                            returns the Web Audio API\n                            AudioParam that c
20329ontrols\n                            this oscillator's\n                            gain/amplitude/volume)",
20330            "type": "AudioParam"
20331          },
20332          "class": "p5.Oscillator",
20333          "module": "p5.sound",
20334          "submodule": "p5.sound"
20335        }, {
20336          "file": "lib/addons/p5.sound.js",
20337          "line": 5548,
20338          "description": "<p>Set frequency of an oscillator to a value. Or, pass in an object\nsuch as an oscillator to modulate the frequency with an audio signal.</p>\n",
20339          "itemtype": "method",
20340          "name": "freq",
20341          "params": [{
20342            "name": "Frequency",
20343            "description": "<p>Frequency in Hz\n                                      or modulating signal/oscillator</p>\n",
20344            "type": "Number|Object"
20345          }, {
20346            "name": "rampTime",
20347            "description": "<p>Ramp time (in seconds)</p>\n",
20348            "type": "Number",
20349            "optional": true
20350          }, {
20351            "name": "timeFromNow",
20352            "description": "<p>Schedule this event to happen\n                                 at x seconds from now</p>\n",
20353            "type": "Number",
20354            "optional": true
20355          }],
20356          "return": {
20357            "description": "Frequency If no value is provided,\n                                returns the Web Audio API\n                                AudioParam that controls\n                                this oscillator's frequency",
20358            "type": "AudioParam"
20359          },
20360          "example": ["\n<div><code>\nvar osc = new p5.Oscillator(300);\nosc.start();\nosc.freq(40, 10);\n</code></div>"],
20361          "class": "p5.Oscillator",
20362          "module": "p5.sound",
20363          "submodule": "p5.sound"
20364        }, {
20365          "file": "lib/addons/p5.sound.js",
20366          "line": 5607,
20367          "description": "<p>Set type to &#39;sine&#39;, &#39;triangle&#39;, &#39;sawtooth&#39; or &#39;square&#39;.</p>\n",
20368          "itemtype": "method",
20369          "name": "setType",
20370          "params": [{
20371            "name": "type",
20372            "description": "<p>&#39;sine&#39;, &#39;triangle&#39;, &#39;sawtooth&#39; or &#39;square&#39;.</p>\n",
20373            "type": "String"
20374          }],
20375          "class": "p5.Oscillator",
20376          "module": "p5.sound",
20377          "submodule": "p5.sound"
20378        }, {
20379          "file": "lib/addons/p5.sound.js",
20380          "line": 5619,
20381          "description": "<p>Connect to a p5.sound / Web Audio object.</p>\n",
20382          "itemtype": "method",
20383          "name": "connect",
20384          "params": [{
20385            "name": "unit",
20386            "description": "<p>A p5.sound or Web Audio object</p>\n",
20387            "type": "Object"
20388          }],
20389          "class": "p5.Oscillator",
20390          "module": "p5.sound",
20391          "submodule": "p5.sound"
20392        }, {
20393          "file": "lib/addons/p5.sound.js",
20394          "line": 5636,
20395          "description": "<p>Disconnect all outputs</p>\n",
20396          "itemtype": "method",
20397          "name": "disconnect",
20398          "class": "p5.Oscillator",
20399          "module": "p5.sound",
20400          "submodule": "p5.sound"
20401        }, {
20402          "file": "lib/addons/p5.sound.js",
20403          "line": 5653,
20404          "description": "<p>Pan between Left (-1) and Right (1)</p>\n",
20405          "itemtype": "method",
20406          "name": "pan",
20407          "params": [{
20408            "name": "panning",
20409            "description": "<p>Number between -1 and 1</p>\n",
20410            "type": "Number"
20411          }, {
20412            "name": "timeFromNow",
20413            "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
20414            "type": "Number"
20415          }],
20416          "class": "p5.Oscillator",
20417          "module": "p5.sound",
20418          "submodule": "p5.sound"
20419        }, {
20420          "file": "lib/addons/p5.sound.js",
20421          "line": 5685,
20422          "description": "<p>Set the phase of an oscillator between 0.0 and 1.0.\nIn this implementation, phase is a delay time\nbased on the oscillator&#39;s current frequency.</p>\n",
20423          "itemtype": "method",
20424          "name": "phase",
20425          "params": [{
20426            "name": "phase",
20427            "description": "<p>float between 0.0 and 1.0</p>\n",
20428            "type": "Number"
20429          }],
20430          "class": "p5.Oscillator",
20431          "module": "p5.sound",
20432          "submodule": "p5.sound"
20433        }, {
20434          "file": "lib/addons/p5.sound.js",
20435          "line": 5739,
20436          "description": "<p>Add a value to the p5.Oscillator&#39;s output amplitude,\nand return the oscillator. Calling this method again\nwill override the initial add() with a new value.</p>\n",
20437          "itemtype": "method",
20438          "name": "add",
20439          "params": [{
20440            "name": "number",
20441            "description": "<p>Constant number to add</p>\n",
20442            "type": "Number"
20443          }],
20444          "return": {
20445            "description": "Oscillator Returns this oscillator\n                                   with scaled output",
20446            "type": "p5.Oscillator"
20447          },
20448          "class": "p5.Oscillator",
20449          "module": "p5.sound",
20450          "submodule": "p5.sound"
20451        }, {
20452          "file": "lib/addons/p5.sound.js",
20453          "line": 5756,
20454          "description": "<p>Multiply the p5.Oscillator&#39;s output amplitude\nby a fixed value (i.e. turn it up!). Calling this method\nagain will override the initial mult() with a new value.</p>\n",
20455          "itemtype": "method",
20456          "name": "mult",
20457          "params": [{
20458            "name": "number",
20459            "description": "<p>Constant number to multiply</p>\n",
20460            "type": "Number"
20461          }],
20462          "return": {
20463            "description": "Oscillator Returns this oscillator\n                                   with multiplied output",
20464            "type": "p5.Oscillator"
20465          },
20466          "class": "p5.Oscillator",
20467          "module": "p5.sound",
20468          "submodule": "p5.sound"
20469        }, {
20470          "file": "lib/addons/p5.sound.js",
20471          "line": 5772,
20472          "description": "<p>Scale this oscillator&#39;s amplitude values to a given\nrange, and return the oscillator. Calling this method\nagain will override the initial scale() with new values.</p>\n",
20473          "itemtype": "method",
20474          "name": "scale",
20475          "params": [{
20476            "name": "inMin",
20477            "description": "<p>input range minumum</p>\n",
20478            "type": "Number"
20479          }, {
20480            "name": "inMax",
20481            "description": "<p>input range maximum</p>\n",
20482            "type": "Number"
20483          }, {
20484            "name": "outMin",
20485            "description": "<p>input range minumum</p>\n",
20486            "type": "Number"
20487          }, {
20488            "name": "outMax",
20489            "description": "<p>input range maximum</p>\n",
20490            "type": "Number"
20491          }],
20492          "return": {
20493            "description": "Oscillator Returns this oscillator\n                                   with scaled output",
20494            "type": "p5.Oscillator"
20495          },
20496          "class": "p5.Oscillator",
20497          "module": "p5.sound",
20498          "submodule": "p5.sound"
20499        }, {
20500          "file": "lib/addons/p5.sound.js",
20501          "line": 5871,
20502          "class": "p5.SqrOsc",
20503          "module": "p5.sound",
20504          "submodule": "p5.sound"
20505        }, {
20506          "file": "lib/addons/p5.sound.js",
20507          "line": 6074,
20508          "class": "p5.SqrOsc",
20509          "module": "p5.sound",
20510          "submodule": "p5.sound"
20511        }, {
20512          "file": "lib/addons/p5.sound.js",
20513          "line": 6363,
20514          "description": "<p>Time until envelope reaches attackLevel</p>\n",
20515          "itemtype": "property",
20516          "name": "attackTime",
20517          "class": "p5.Envelope",
20518          "module": "p5.sound",
20519          "submodule": "p5.sound"
20520        }, {
20521          "file": "lib/addons/p5.sound.js",
20522          "line": 6368,
20523          "description": "<p>Level once attack is complete.</p>\n",
20524          "itemtype": "property",
20525          "name": "attackLevel",
20526          "class": "p5.Envelope",
20527          "module": "p5.sound",
20528          "submodule": "p5.sound"
20529        }, {
20530          "file": "lib/addons/p5.sound.js",
20531          "line": 6373,
20532          "description": "<p>Time until envelope reaches decayLevel.</p>\n",
20533          "itemtype": "property",
20534          "name": "decayTime",
20535          "class": "p5.Envelope",
20536          "module": "p5.sound",
20537          "submodule": "p5.sound"
20538        }, {
20539          "file": "lib/addons/p5.sound.js",
20540          "line": 6378,
20541          "description": "<p>Level after decay. The envelope will sustain here until it is released.</p>\n",
20542          "itemtype": "property",
20543          "name": "decayLevel",
20544          "class": "p5.Envelope",
20545          "module": "p5.sound",
20546          "submodule": "p5.sound"
20547        }, {
20548          "file": "lib/addons/p5.sound.js",
20549          "line": 6383,
20550          "description": "<p>Duration of the release portion of the envelope.</p>\n",
20551          "itemtype": "property",
20552          "name": "releaseTime",
20553          "class": "p5.Envelope",
20554          "module": "p5.sound",
20555          "submodule": "p5.sound"
20556        }, {
20557          "file": "lib/addons/p5.sound.js",
20558          "line": 6388,
20559          "description": "<p>Level at the end of the release.</p>\n",
20560          "itemtype": "property",
20561          "name": "releaseLevel",
20562          "class": "p5.Envelope",
20563          "module": "p5.sound",
20564          "submodule": "p5.sound"
20565        }, {
20566          "file": "lib/addons/p5.sound.js",
20567          "line": 6424,
20568          "description": "<p>Reset the envelope with a series of time/value pairs.</p>\n",
20569          "itemtype": "method",
20570          "name": "set",
20571          "params": [{
20572            "name": "attackTime",
20573            "description": "<p>Time (in seconds) before level\n                               reaches attackLevel</p>\n",
20574            "type": "Number"
20575          }, {
20576            "name": "attackLevel",
20577            "description": "<p>Typically an amplitude between\n                               0.0 and 1.0</p>\n",
20578            "type": "Number"
20579          }, {
20580            "name": "decayTime",
20581            "description": "<p>Time</p>\n",
20582            "type": "Number"
20583          }, {
20584            "name": "decayLevel",
20585            "description": "<p>Amplitude (In a standard ADSR envelope,\n                               decayLevel = sustainLevel)</p>\n",
20586            "type": "Number"
20587          }, {
20588            "name": "releaseTime",
20589            "description": "<p>Release Time (in seconds)</p>\n",
20590            "type": "Number"
20591          }, {
20592            "name": "releaseLevel",
20593            "description": "<p>Amplitude</p>\n",
20594            "type": "Number"
20595          }],
20596          "example": ["\n<div><code>\nvar t1 = 0.1;
20596 // attack time in seconds\nvar l1 = 0.7; // attack level 0.0 to 1.0\nvar t2 = 0.3; // decay time in seconds\nvar l2 = 0.1; // decay level  0.0 to 1.0\nvar t3 = 0.2; // sustain time in seconds\nvar l3 = 0.5; // sustain level  0.0 to 1.0\n// release level defaults to zero\n\nvar env;\nvar triOsc;\n\nfunction setup() {\n  background(0);\n  noStroke();\n  fill(255);\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n\n  env = new p5.Envelope(t1, l1, t2, l2, t3, l3);\n  triOsc = new p5.Oscillator('triangle');\n  triOsc.amp(env); // give the env control of the triOsc's amp\n  triOsc.start();\n}\n\n// mouseClick triggers envelope if over canvas\nfunction mouseClicked() {\n  // is mouse over canvas?\n  if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {\n    env.play(triOsc);\n  }\n}\n</code></div>\n"],
20597          "class": "p5.Envelope",
20598          "module": "p5.sound",
20599          "submodule": "p5.sound"
20600        }, {
20601          "file": "lib/addons/p5.sound.js",
20602          "line": 6483,
20603          "description": "<p>Set values like a traditional\n<a href=\"https://en.wikipedia.org/wiki/Synthesizer#/media/File:ADSR_parameter.svg\">\nADSR envelope\n</a>.</p>\n",
20604          "itemtype": "method",
20605          "name": "setADSR",
20606          "params": [{
20607            "name": "attackTime",
20608            "description": "<p>Time (in seconds before envelope\n                              reaches Attack Level</p>\n",
20609            "type": "Number"
20610          }, {
20611            "name": "decayTime",
20612            "description": "<p>Time (in seconds) before envelope\n                              reaches Decay/Sustain Level</p>\n",
20613            "type": "Number",
20614            "optional": true
20615          }, {
20616            "name": "susRatio",
20617            "description": "<p>Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n                              where 1.0 = attackLevel, 0.0 = releaseLevel.\n                              The susRatio determines the decayLevel and the level at which the\n                              sustain portion of the envelope will sustain.\n                              For example, if attackLevel is 0.4, releaseLevel is 0,\n                              and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n                              increased to 1.0 (using <code>setRange</code>),\n                              then decayLevel would increase proportionally, to become 0.5.</p>\n",
20618            "type": "Number",
20619            "optional": true
20620          }, {
20621            "name": "releaseTime",
20622            "description": "<p>Time in seconds from now (defaults to 0)</p>\n",
20623            "type": "Number",
20624            "optional": true
20625          }],
20626          "example": ["\n<div><code>\nvar attackLevel = 1.0;\nvar releaseLevel = 0;\n\nvar attackTime = 0.001;\nvar decayTime = 0.2;\nvar susPercent = 0.2;\nvar releaseTime = 0.5;\n\nvar env, triOsc;\n\nfunction setup() {\n  var cnv = createCanvas(100, 100);\n\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n\n  env = new p5.Envelope();\n  env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n  env.setRange(attackLevel, releaseLevel);\n\n  triOsc = new p5.Oscillator('triangle');\n  triOsc.amp(env);\n  triOsc.start();\n  triOsc.freq(220);\n\n  cnv.mousePressed(playEnv);\n}\n\nfunction playEnv()  {\n  env.play();\n}\n</code></div>"],
20627          "class": "p5.Envelope",
20628          "module": "p5.sound",
20629          "submodule": "p5.sound"
20630        }, {
20631          "file": "lib/addons/p5.sound.js",
20632          "line": 6548,
20633          "description": "<p>Set max (attackLevel) and min (releaseLevel) of envelope.</p>\n",
20634          "itemtype": "method",
20635          "name": "setRange",
20636          "params": [{
20637            "name": "aLevel",
20638            "description": "<p>attack level (defaults to 1)</p>\n",
20639            "type": "Number"
20640          }, {
20641            "name": "rLevel",
20642            "description": "<p>release level (defaults to 0)</p>\n",
20643            "type": "Number"
20644          }],
20645          "example": ["\n<div><code>\nvar attackLevel = 1.0;\nvar releaseLevel = 0;\n\nvar attackTime = 0.001;\nvar decayTime = 0.2;\nvar susPercent = 0.2;\nvar releaseTime = 0.5;\n\nvar env, triOsc;\n\nfunction setup() {\n  var cnv = createCanvas(100, 100);\n\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n\n  env = new p5.Envelope();\n  env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n  env.setRange(attackLevel, releaseLevel);\n\n  triOsc = new p5.Oscillator('triangle');\n  triOsc.amp(env);\n  triOsc.start();\n  triOsc.freq(220);\n\n  cnv.mousePressed(playEnv);\n}\n\nfunction playEnv()  {\n  env.play();\n}\n</code></div>"],
20646          "class": "p5.Envelope",
20647          "module": "p5.sound",
20648          "submodule": "p5.sound"
20649        }, {
20650          "file": "lib/addons/p5.sound.js",
20651          "line": 6627,
20652          "description": "<p>Assign a parameter to be controlled by this envelope.\nIf a p5.Sound object is given, then the p5.Envelope will c
20652ontrol its\noutput gain. If multiple inputs are provided, the env will\ncontrol all of them.</p>\n",
20653          "itemtype": "method",
20654          "name": "setInput",
20655          "params": [{
20656            "name": "inputs",
20657            "description": "<p>A p5.sound object or\n                              Web Audio Param.</p>\n",
20658            "type": "Object",
20659            "optional": true,
20660            "multiple": true
20661          }],
20662          "class": "p5.Envelope",
20663          "module": "p5.sound",
20664          "submodule": "p5.sound"
20665        }, {
20666          "file": "lib/addons/p5.sound.js",
20667          "line": 6642,
20668          "description": "<p>Set whether the envelope ramp is linear (default) or exponential.\nExponential ramps can be useful because we perceive amplitude\nand frequency logarithmically.</p>\n",
20669          "itemtype": "method",
20670          "name": "setExp",
20671          "params": [{
20672            "name": "isExp",
20673            "description": "<p>true is exponential, false is linear</p>\n",
20674            "type": "Boolean"
20675          }],
20676          "class": "p5.Envelope",
20677          "module": "p5.sound",
20678          "submodule": "p5.sound"
20679        }, {
20680          "file": "lib/addons/p5.sound.js",
20681          "line": 6660,
20682          "description": "<p>Play tells the envelope to start acting on a given input.\nIf the input is a p5.sound object (i.e. AudioIn, Oscillator,\nSoundFile), then Envelope will control its output volume.\nEnvelopes can also be used to control any <a href=\"\nhttp://docs.webplatform.org/wiki/apis/webaudio/AudioParam\">\nWeb Audio Audio Param.</a></p>\n",
20683          "itemtype": "method",
20684          "name": "play",
20685          "params": [{
20686            "name": "unit",
20687            "description": "<p>A p5.sound object or\n                              Web Audio Param.</p>\n",
20688            "type": "Object"
20689          }, {
20690            "name": "startTime",
20691            "description": "<p>time from now (in seconds) at which to play</p>\n",
20692            "type": "Number",
20693            "optional": true
20694          }, {
20695            "name": "sustainTime",
20696            "description": "<p>time to sustain before releasing the envelope</p>\n",
20697            "type": "Number",
20698            "optional": true
20699          }],
20700          "example": ["\n<div><code>\nvar attackLevel = 1.0;\nvar releaseLevel = 0;\n\nvar attackTime = 0.001;\nvar decayTime = 0.2;\nvar susPercent = 0.2;\nvar releaseTime = 0.5;\n\nvar env, triOsc;\n\nfunction setup() {\n  var cnv = createCanvas(100, 100);\n\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n\n  env = new p5.Envelope();\n  env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n  env.setRange(attackLevel, releaseLevel);\n\n  triOsc = new p5.Oscillator('triangle');\n  triOsc.amp(env);\n  triOsc.start();\n  triOsc.freq(220);\n\n  cnv.mousePressed(playEnv);\n}\n\nfunction playEnv()  {\n  // trigger env on triOsc, 0 seconds from now\n  // After decay, sustain for 0.2 seconds before release\n  env.play(triOsc, 0, 0.2);\n}\n</code></div>"],
20701          "class": "p5.Envelope",
20702          "module": "p5.sound",
20703          "submodule": "p5.sound"
20704        }, {
20705          "file": "lib/addons/p5.sound.js",
20706          "line": 6721,
20707          "description": "<p>Trigger the Attack, and Decay portion of the Envelope.\nSimilar to holding down a key on a piano, but it will\nhold the sustain level until you let go. Input can be\nany p5.sound object, or a <a href=\"\nhttp://docs.webplatform.org/wiki/apis/webaudio/AudioParam\">\nWeb Audio Param</a>.</p>\n",
20708          "itemtype": "method",
20709          "name": "triggerAttack",
20710          "params": [{
20711            "name": "unit",
20712            "description": "<p>p5.sound Object or Web Audio Param</p>\n",
20713            "type": "Object"
20714          }, {
20715            "name": "secondsFromNow",
20716            "description": "<p>time from now (in seconds)</p>\n",
20717            "type": "Number"
20718          }],
20719          "example": ["\n<div><code>\n\nvar attackLevel = 1.0;\nvar releaseLevel = 0;\n\nvar attackTime = 0.001;\nvar decayTime = 0.3;\nvar susPercent = 0.4;\nvar releaseTime = 0.5;\n\nvar env, triOsc;\n\nfunction setup() {\n  var cnv = createCanvas(100, 100);\n  background(200);\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n\n  env = new p5.Envelope();\n  env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n  env.setRange(attackLevel, releaseLevel);\n\n  triOsc = new p5.Oscillator('triangle');\n  triOsc.amp(env);\n  triOsc.start();\n  triOsc.freq(220);\n\n  cnv.mousePressed(envAttack);\n}\n\nfunction envAttack()  {\n  console.log('trigger attack');\n  env.triggerAttack();\n\n  background(0,255,0);\n  text('attack!', width/2, height/2);\n}\n\nfunction mouseReleased() {\n  env.triggerRelease();\n\n  background(200);\n  text('click to play', width/2, height/2);\n}\n</code></div>"],
20720          "class": "p5.Envelope",
20721          "module": "p5.sound",
20722          "submodule": "p5.sound"
20723        }, {
20724          "file": "lib/addons/p5.sound.js",
20725          "line": 6828,
20726          "description": "<p>Trigger the Release of the Envelope. This is similar to releasing\nthe key on a piano and letting the sound fade according to the\nrelease level and release time.</p>\n",
20727          "itemtype": "method",
20728          "name": "triggerRelease",
20729          "params": [{
20730            "name": "unit",
20731            "description": "<p>p5.sound Object or Web Audio Param</p>\n",
20732            "type": "Object"
20733          }, {
20734            "name": "secondsFromNow",
20735            "description": "<p>time to trigger the release</p>\n",
20736            "type": "Number"
20737          }],
20738          "example": ["\n<div><code>\n\nvar attackLevel = 1.0;\nvar releaseLevel = 0;\n\nvar attackTime = 0.001;\nvar decayTime = 0.3;\nvar susPercent = 0.4;\nvar releaseTime = 0.5;\n\nvar env, triOsc;\n\nfunction setup() {\n  var cnv = createCanvas(100, 100);\n  background(200);\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n\n  env = new p5.Envelope();\n  env.setADSR(attackTime, decayTime, susPercent, releaseTime);\n  env.setRange(attackLevel, releaseLevel);\n\n  triOsc = new p5.Oscillator('triangle');\n  triOsc.amp(env);\n  triOsc.start();\n  triOsc.freq(220);\n\n  cnv.mousePressed(envAttack);\n}\n\nfunction envAttack()  {\n  console.log('trigger attack');\n  env.triggerAttack();\n\n  background(0,255,0);\n  text('attack!', width/2, height/2);\n}\n\nfunction mouseReleased() {\n  env.triggerRelease();\n\n  background(200);\n  text('click to play', width/2, height/2);\n}\n</code></div>"],
20739          "class": "p5.Envelope",
20740          "module": "p5.sound",
20741          "submodule": "p5.sound"
20742        }, {
20743          "file": "lib/addons/p5.sound.js",
20744          "line": 6925,
20745          "description": "<p>Exponentially ramp to a value using the first two\nvalues from <code><a href=\"#/p5.Envelope/setADSR\">setADSR(attackTime, decayTime)</a></code>\nas <a href=\"https://en.wikipedia.org/wiki/RC_time_constant\">\ntime constants</a> for simple exponential ramps.\nIf the value is higher than current value, it uses attackTime,\nwhile a decrease uses decayTime.</p>\n",
20746          "itemtype": "method",
20747          "name": "ramp",
20748          "params": [{
20749            "name": "unit",
20750            "description": "<p>p5.sound Object or Web Audio Param</p>\n",
20751            "type": "Object"
20752          }, {
20753            "name": "secondsFromNow",
20754            "description": "<p>When to trigger the ramp</p>\n",
20755            "type": "Number"
20756          }, {
20757            "name": "v",
20758            "description": "<p>Target value</p>\n",
20759            "type": "Number"
20760          }, {
20761            "name": "v2",
20762            "description": "<p>Second target value (optional)</p>\n",
20763            "type": "Number",
20764            "optional": true
20765          }],
20766          "example": ["\n<div><code>\nvar env, osc, amp, cnv;\n\nvar attackTime = 0.001;\nvar decayTime = 0.2;\nvar attackLevel = 1;\nvar decayLevel = 0;\n\nfunction setup() {\n  cnv = createCanvas(100, 100);\n  fill(0,255,0);\n  noStroke();\n\n  env = new p5.Envelope();\n  env.setADSR(attackTime, decayTime);\n\n  osc = new p5.Oscillator();\n  osc.amp(env);\n  osc.start();\n\n  amp = new p5.Amplitude();\n\n  cnv.mousePressed(triggerRamp);\n}\n\nfunction triggerRamp() {\n  env.ramp(osc, 0, attackLevel, decayLevel);\n}\n\nfunction draw() {\n  background(20,20,20);\n  text('click me', 10, 20);
20766\n  var h = map(amp.getLevel(), 0, 0.4, 0, height);;\n\n  rect(0, height, width, -h);\n}\n</code></div>"],
20767          "class": "p5.Envelope",
20768          "module": "p5.sound",
20769          "submodule": "p5.sound"
20770        }, {
20771          "file": "lib/addons/p5.sound.js",
20772          "line": 7032,
20773          "description": "<p>Add a value to the p5.Oscillator&#39;s output amplitude,\nand return the oscillator. Calling this method\nagain will override the initial add() with new values.</p>\n",
20774          "itemtype": "method",
20775          "name": "add",
20776          "params": [{
20777            "name": "number",
20778            "description": "<p>Constant number to add</p>\n",
20779            "type": "Number"
20780          }],
20781          "return": {
20782            "description": "Envelope Returns this envelope\n                                   with scaled output",
20783            "type": "p5.Envelope"
20784          },
20785          "class": "p5.Envelope",
20786          "module": "p5.sound",
20787          "submodule": "p5.sound"
20788        }, {
20789          "file": "lib/addons/p5.sound.js",
20790          "line": 7048,
20791          "description": "<p>Multiply the p5.Envelope&#39;s output amplitude\nby a fixed value. Calling this method\nagain will override the initial mult() with new values.</p>\n",
20792          "itemtype": "method",
20793          "name": "mult",
20794          "params": [{
20795            "name": "number",
20796            "description": "<p>Constant number to multiply</p>\n",
20797            "type": "Number"
20798          }],
20799          "return": {
20800            "description": "Envelope Returns this envelope\n                                   with scaled output",
20801            "type": "p5.Envelope"
20802          },
20803          "class": "p5.Envelope",
20804          "module": "p5.sound",
20805          "submodule": "p5.sound"
20806        }, {
20807          "file": "lib/addons/p5.sound.js",
20808          "line": 7064,
20809          "description": "<p>Scale this envelope&#39;s amplitude values to a given\nrange, and return the envelope. Calling this method\nagain will override the initial scale() with new values.</p>\n",
20810          "itemtype": "method",
20811          "name": "scale",
20812          "params": [{
20813            "name": "inMin",
20814            "description": "<p>input range minumum</p>\n",
20815            "type": "Number"
20816          }, {
20817            "name": "inMax",
20818            "description": "<p>input range maximum</p>\n",
20819            "type": "Number"
20820          }, {
20821            "name": "outMin",
20822            "description": "<p>input range minumum</p>\n",
20823            "type": "Number"
20824          }, {
20825            "name": "outMax",
20826            "description": "<p>input range maximum</p>\n",
20827            "type": "Number"
20828          }],
20829          "return": {
20830            "description": "Envelope Returns this envelope\n                                   with scaled output",
20831            "type": "p5.Envelope"
20832          },
20833          "class": "p5.Envelope",
20834          "module": "p5.sound",
20835          "submodule": "p5.sound"
20836        }, {
20837          "file": "lib/addons/p5.sound.js",
20838          "line": 7172,
20839          "description": "<p>Set the width of a Pulse object (an oscillator that implements\nPulse Width Modulation).</p>\n",
20840          "itemtype": "method",
20841          "name": "width",
20842          "params": [{
20843            "name": "width",
20844            "description": "<p>Width between the pulses (0 to 1.0,\n                       defaults to 0)</p>\n",
20845            "type": "Number",
20846            "optional": true
20847          }],
20848          "class": "p5.Pulse",
20849          "module": "p5.sound",
20850          "submodule": "p5.sound"
20851        }, {
20852          "file": "lib/addons/p5.sound.js",
20853          "line": 7359,
20854          "description": "<p>Set type of noise to &#39;white&#39;, &#39;pink&#39; or &#39;brown&#39;.\nWhite is the default.</p>\n",
20855          "itemtype": "method",
20856          "name": "setType",
20857          "params": [{
20858            "name": "type",
20859            "description": "<p>&#39;white&#39;, &#39;pink&#39; or &#39;brown&#39;</p>\n",
20860            "type": "String",
20861            "optional": true
20862          }],
20863          "class": "p5.Noise",
20864          "module": "p5.sound",
20865          "submodule": "p5.sound"
20866        }, {
20867          "file": "lib/addons/p5.sound.js",
20868          "line": 7472,
20869          "itemtype": "property",
20870          "name": "input",
20871          "type": "GainNode",
20872          "class": "p5.AudioIn",
20873          "module": "p5.sound",
20874          "submodule": "p5.sound"
20875        }, {
20876          "file": "lib/addons/p5.sound.js",
20877          "line": 7476,
20878          "itemtype": "property",
20879          "name": "output",
20880          "type": "GainNode",
20881          "class": "p5.AudioIn",
20882          "module": "p5.sound",
20883          "submodule": "p5.sound"
20884        }, {
20885          "file": "lib/addons/p5.sound.js",
20886          "line": 7480,
20887          "itemtype": "property",
20888          "name": "stream",
20889          "type": "MediaStream|null",
20890          "class": "p5.AudioIn",
20891          "module": "p5.sound",
20892          "submodule": "p5.sound"
20893        }, {
20894          "file": "lib/addons/p5.sound.js",
20895          "line": 7484,
20896          "itemtype": "property",
20897          "name": "mediaStream",
20898          "type": "MediaStreamAudioSourceNode|null",
20899          "class": "p5.AudioIn",
20900          "module": "p5.sound",
20901          "submodule": "p5.sound"
20902        }, {
20903          "file": "lib/addons/p5.sound.js",
20904          "line": 7488,
20905          "itemtype": "property",
20906          "name": "currentSource",
20907          "type": "Number|null",
20908          "class": "p5.AudioIn",
20909          "module": "p5.sound",
20910          "submodule": "p5.sound"
20911        }, {
20912          "file": "lib/addons/p5.sound.js",
20913          "line": 7492,
20914          "description": "<p>Client must allow browser to access their microphone / audioin source.\nDefault: false. Will become true when the client enables acces.</p>\n",
20915          "itemtype": "property",
20916          "name": "enabled",
20917          "type": "Boolean",
20918          "class": "p5.AudioIn",
20919          "module": "p5.sound",
20920          "submodule": "p5.sound"
20921        }, {
20922          "file": "lib/addons/p5.sound.js",
20923          "line": 7499,
20924          "description": "<p>Input amplitude, connect to it by default but not to master out</p>\n",
20925          "itemtype": "property",
20926          "name": "amplitude",
20927          "type": "p5.Amplitude",
20928          "class": "p5.AudioIn",
20929          "module": "p5.sound",
20930          "submodule": "p5.sound"
20931        }, {
20932          "file": "lib/addons/p5.sound.js",
20933          "line": 7512,
20934          "description": "<p>Start processing audio input. This enables the use of other\nAudioIn methods like getLevel(). Note that by default, AudioIn\nis not connected to p5.sound&#39;s output. So you won&#39;t hear\nanything unless you use the connect() method.<br/></p>\n<p>Certain browsers limit access to the user&#39;s microphone. For example,\nChrome only allows access from localhost and over https. For this reason,\nyou may want to include an errorCallback—a function that is called 
20934in case\nthe browser won&#39;t provide mic access.</p>\n",
20935          "itemtype": "method",
20936          "name": "start",
20937          "params": [{
20938            "name": "successCallback",
20939            "description": "<p>Name of a function to call on\n                                  success.</p>\n",
20940            "type": "Function",
20941            "optional": true
20942          }, {
20943            "name": "errorCallback",
20944            "description": "<p>Name of a function to call if\n                                  there was an error. For example,\n                                  some browsers do not support\n                                  getUserMedia.</p>\n",
20945            "type": "Function",
20946            "optional": true
20947          }],
20948          "class": "p5.AudioIn",
20949          "module": "p5.sound",
20950          "submodule": "p5.sound"
20951        }, {
20952          "file": "lib/addons/p5.sound.js",
20953          "line": 7565,
20954          "description": "<p>Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel().\nIf re-starting, the user may be prompted for permission access.</p>\n",
20955          "itemtype": "method",
20956          "name": "stop",
20957          "class": "p5.AudioIn",
20958          "module": "p5.sound",
20959          "submodule": "p5.sound"
20960        }, {
20961          "file": "lib/addons/p5.sound.js",
20962          "line": 7581,
20963          "description": "<p>Connect to an audio unit. If no parameter is provided, will\nconnect to the master output (i.e. your speakers).<br/></p>\n",
20964          "itemtype": "method",
20965          "name": "connect",
20966          "params": [{
20967            "name": "unit",
20968            "description": "<p>An object that accepts audio input,\n                        such as an FFT</p>\n",
20969            "type": "Object",
20970            "optional": true
20971          }],
20972          "class": "p5.AudioIn",
20973          "module": "p5.sound",
20974          "submodule": "p5.sound"
20975        }, {
20976          "file": "lib/addons/p5.sound.js",
20977          "line": 7602,
20978          "description": "<p>Disconnect the AudioIn from all audio units. For example, if\nconnect() had been called, disconnect() will stop sending\nsignal to your speakers.<br/></p>\n",
20979          "itemtype": "method",
20980          "name": "disconnect",
20981          "class": "p5.AudioIn",
20982          "module": "p5.sound",
20983          "submodule": "p5.sound"
20984        }, {
20985          "file": "lib/addons/p5.sound.js",
20986          "line": 7616,
20987          "description": "<p>Read the Amplitude (volume level) of an AudioIn. The AudioIn\nclass contains its own instance of the Amplitude class to help\nmake it easy to get a microphone&#39;s volume level. Accepts an\noptional smoothing value (0.0 &lt; 1.0). <em>NOTE: AudioIn must\n.start() before using .getLevel().</em><br/></p>\n",
20988          "itemtype": "method",
20989          "name": "getLevel",
20990          "params": [{
20991            "name": "smoothing",
20992            "description": "<p>Smoothing is 0.0 by default.\n                             Smooths values based on previous values.</p>\n",
20993            "type": "Number",
20994            "optional": true
20995          }],
20996          "return": {
20997            "description": "Volume level (between 0.0 and 1.0)",
20998            "type": "Number"
20999          },
21000          "class": "p5.AudioIn",
21001          "module": "p5.sound",
21002          "submodule": "p5.sound"
21003        }, {
21004          "file": "lib/addons/p5.sound.js",
21005          "line": 7634,
21006          "description": "<p>Set amplitude (volume) of a mic input between 0 and 1.0. <br/></p>\n",
21007          "itemtype": "method",
21008          "name": "amp",
21009          "params": [{
21010            "name": "vol",
21011            "description": "<p>between 0 and 1.0</p>\n",
21012            "type": "Number"
21013          }, {
21014            "name": "time",
21015            "description": "<p>ramp time (optional)</p>\n",
21016            "type": "Number",
21017            "optional": true
21018          }],
21019          "class": "p5.AudioIn",
21020          "module": "p5.sound",
21021          "submodule": "p5.sound"
21022        }, {
21023          "file": "lib/addons/p5.sound.js",
21024          "line": 7653,
21025          "description": "<p>Returns a list of available input sources. This is a wrapper\nfor &lt;a title=&quot;MediaDevices.enumerateDevices() - Web APIs | MDN&quot; target=&quot;_blank&quot; href=\n &quot;<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices\">https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices</a>&quot;</p>\n<blockquote>\n<p>and it returns a Promise.</p>\n</blockquote>\n",
21026          "itemtype": "method",
21027          "name": "getSources",
21028          "params": [{
21029            "name": "successCallback",
21030            "description": "<p>This callback function handles the sources when they\n                                     have been enumerated. The callback function\n                                     receives the deviceList array as its only argument</p>\n",
21031            "type": "Function",
21032            "optional": true
21033          }, {
21034            "name": "errorCallback",
21035            "description": "<p>This optional callback receives the error\n                                   message as its argument.</p>\n",
21036            "type": "Function",
21037            "optional": true
21038          }],
21039          "return": {
21040            "description": "Returns a Promise that can be used in place of the callbacks, similar\n                           to the enumerateDevices() method",
21041            "type": "Promise"
21042          },
21043          "example": ["\n <div><code>\n var audiograb;
21043\n\n function setup(){\n   //new audioIn\n   audioGrab = new p5.AudioIn();\n\n   audioGrab.getSources(function(deviceList) {\n     //print out the array of available sources\n     console.log(deviceList);\n     //set the source to the first item in the deviceList array\n     audioGrab.setSource(0);\n   });\n }\n </code></div>"],
21044          "class": "p5.AudioIn",
21045          "module": "p5.sound",
21046          "submodule": "p5.sound"
21047        }, {
21048          "file": "lib/addons/p5.sound.js",
21049          "line": 7704,
21050          "description": "<p>Set the input source. Accepts a number representing a\nposition in the array returned by getSources().\nThis is only available in browsers that support\n&lt;a title=&quot;MediaDevices.enumerateDevices() - Web APIs | MDN&quot; target=&quot;_blank&quot; href=\n&quot;<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices\">https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices</a>&quot;</p>\n<blockquote>\n<p>navigator.mediaDevices.enumerateDevices()</a>.<br/></p>\n</blockquote>\n",
21051          "itemtype": "method",
21052          "name": "setSource",
21053          "params": [{
21054            "name": "num",
21055            "description": "<p>position of input source in the array</p>\n",
21056            "type": "Number"
21057          }],
21058          "class": "p5.AudioIn",
21059          "module": "p5.sound",
21060          "submodule": "p5.sound"
21061        }, {
21062          "file": "lib/addons/p5.sound.js",
21063          "line": 7744,
21064          "class": "p5.AudioIn",
21065          "module": "p5.sound",
21066          "submodule": "p5.sound"
21067        }, {
21068          "file": "lib/addons/p5.sound.js",
21069          "line": 7760,
21070          "class": "p5.AudioIn",
21071          "module": "p5.sound",
21072          "submodule": "p5.sound"
21073        }, {
21074          "file": "lib/addons/p5.sound.js",
21075          "line": 7784,
21076          "class": "p5.AudioIn",
21077          "module": "p5.sound",
21078          "submodule": "p5.sound"
21079        }, {
21080          "file": "lib/addons/p5.sound.js",
21081          "line": 7810,
21082          "class": "p5.AudioIn",
21083          "module": "p5.sound",
21084          "submodule": "p5.sound"
21085        }, {
21086          "file": "lib/addons/p5.sound.js",
21087          "line": 7832,
21088          "class": "p5.AudioIn",
21089          "module": "p5.sound",
21090          "submodule": "p5.sound"
21091        }, {
21092          "file": "lib/addons/p5.sound.js",
21093          "line": 7854,
21094          "class": "p5.AudioIn",
21095          "module": "p5.sound",
21096          "submodule": "p5.sound"
21097        }, {
21098          "file": "lib/addons/p5.sound.js",
21099          "line": 7900,
21100          "class": "p5.AudioIn",
21101          "module": "p5.sound",
21102          "submodule": "p5.sound"
21103        }, {
21104          "file": "lib/addons/p5.sound.js",
21105          "line": 7931,
21106          "class": "p5.AudioIn",
21107          "module": "p5.sound",
21108          "submodule": "p5.sound"
21109        }, {
21110          "file": "lib/addons/p5.sound.js",
21111          "line": 7949,
21112          "class": "p5.AudioIn",
21113          "module": "p5.sound",
21114          "submodule": "p5.sound"
21115        }, {
21116          "file": "lib/addons/p5.sound.js",
21117          "line": 8286,
21118          "class": "p5.AudioIn",
21119          "module": "p5.sound",
21120          "submodule": "p5.sound"
21121        }, {
21122          "file": "lib/addons/p5.sound.js",
21123          "line": 8308,
21124          "class": "p5.AudioIn",
21125          "module": "p5.sound",
21126          "submodule": "p5.sound"
21127        }, {
21128          "file": "lib/addons/p5.sound.js",
21129          "line": 8384,
21130          "description": "<p>In classes that extend\np5.Effect, connect effect nodes\nto the wet parameter</p>\n",
21131          "class": "p5.Effect",
21132          "module": "p5.sound",
21133          "submodule": "p5.sound"
21134        }, {
21135          "file": "lib/addons/p5.sound.js",
21136          "line": 8397,
21137          "description": "<p>Set the output volume of the filter.</p>\n",
21138          "itemtype": "method",
21139          "name": "amp",
21140          "params": [{
21141            "name": "vol",
21142            "description": "<p>amplitude between 0 and 1.0</p>\n",
21143            "type": "Number",
21144            "optional": true
21145          }, {
21146            "name": "rampTime",
21147            "description": "<p>create a fade that lasts until rampTime</p>\n",
21148            "type": "Number",
21149            "optional": true
21150          }, {
21151            "name": "tFromNow",
21152            "description": "<p>schedule this event to happen in tFromNow seconds</p>\n",
21153            "type": "Number",
21154            "optional": true
21155          }],
21156          "class": "p5.Effect",
21157          "module": "p5.sound",
21158          "submodule": "p5.sound"
21159        }, {
21160          "file": "lib/addons/p5.sound.js",
21161          "line": 8414,
21162          "description": "<p>Link effects together in a chain<br>Example usage: filter.chain(reverb, delay, panner);\nMay be used with an open-ended number of arguments</p>\n",
21163          "itemtype": "method",
21164          "name": "chain",
21165          "params": [{
21166            "name": "arguments",
21167            "description": "<p>Chain together multiple sound objects</p>\n",
21168            "type": "Object",
21169            "optional": true
21170          }],
21171          "class": "p5.Effect",
21172          "module": "p5.sound",
21173          "submodule": "p5.sound"
21174        }, {
21175          "file": "lib/addons/p5.sound.js",
21176          "line": 8431,
21177          "description": "<p>Adjust the dry/wet value.</p>\n",
21178          "itemtype": "method",
21179          "name": "drywet",
21180          "params": [{
21181            "name": "fade",
21182            "description": "<p>The desired drywet value (0 - 1.0)</p>\n",
21183            "type": "Number",
21184            "optional": true
21185          }],
21186          "class": "p5.Effect",
21187          "module": "p5.sound",
21188          "submodule": "p5.sound"
21189        }, {
21190          "file": "lib/addons/p5.sound.js",
21191          "line": 8443,
21192          "description": "<p>Send output to a p5.js-sound, Web Audio Node, or use signal to\ncontrol an AudioParam</p>\n",
21193          "itemtype": "method",
21194          "name": "connect",
21195          "params": [{
21196            "name": "unit",
21197            "description": "",
21198            "type": "Object"
21199          }],
21200          "class": "p5.Effect",
21201          "module": "p5.sound",
21202          "submodule": "p5.sound"
21203        }, {
21204          "file": "lib/addons/p5.sound.js",
21205          "line": 8454,
21206          "description": "<p>Disconnect all output.</p>\n",
21207          "itemtype": "method",
21208          "name": "disconnect",
21209          "class": "p5.Effect",
21210          "module": "p5.sound",
21211          "submodule": "p5.sound"
21212        }, {
21213          "file": "lib/addons/p5.sound.js",
21214          "line": 8572,
21215          "description": "<p>The p5.Filter is built with a\n<a href=\"http://www.w3.org/TR/webaudio/#BiquadFilterNode\">\nWeb Audio BiquadFilter Node</a>.</p>\n",
21216          "itemtype": "property",
21217          "name": "biquadFilter",
21218          "type": "DelayNode",
21219          "class": "p5.Filter",
21220          "module": "p5.sound",
21221          "submodule": "p5.sound"
21222        }, {
21223          "file": "lib/addons/p5.sound.js",
21224          "line": 8590,
21225          "description": "<p>Filter an audio signal according to a set\nof filter parameters.</p>\n",
21226          "itemtype": "method",
21227          "name": "process",
21228          "params": [{
21229            "name": "Signal",
21230            "description": "<p>An object that outputs audio</p>\n",
21231            "type": "Object"
21232          }, {
21233            "name": "freq",
21234            "description": "<p>Frequency in Hz, from 10 to 22050</p>\n",
21235            "type": "Number",
21236            "optional": true
21237          }, {
21238            "name": "res",
21239            "description": "<p>Resonance/Width of the filter frequency\n                      from 0.001 to 1000</p>\n",
21240            "type": "Number",
21241            "optional": true
21242          }],
21243          "class": "p5.Filter",
21244          "module": "p5.sound",
21245          "submodule": "p5.sound"
21246        }, {
21247          "file": "lib/addons/p5.sound.js",
21248          "line": 8604,
21249          "description": "<p>Set the frequency and the resonance of the filter.</p>\n",
21250          "itemtype": "method",
21251          "name": "set",
21252          "params": [{
21253            "name": "freq",
21254            "description": "<p>Frequency in Hz, from 10 to 22050</p>\n",
21255            "type": "Number",
21256            "optional": true
21257          }, {
21258            "name": "res",
21259            "description": "<p>Resonance (Q) from 0.001 to 1000</p>\n",
21260            "type": "Number",
21261            "optional": true
21262          }, {
21263            "name": "timeFromNow",
21264            "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
21265            "type": "Number",
21266            "optional": true
21267          }],
21268          "class": "p5.Filter",
21269          "module": "p5.sound",
21270          "submodule": "p5.sound"
21271        }, {
21272          "file": "lib/addons/p5.sound.js",
21273          "line": 8621,
21274          "description": "<p>Set the filter frequency, in Hz, from 10 to 22050 (the range of\
21274nhuman hearing, although in reality most people hear in a narrower\nrange).</p>\n",
21275          "itemtype": "method",
21276          "name": "freq",
21277          "params": [{
21278            "name": "freq",
21279            "description": "<p>Filter Frequency</p>\n",
21280            "type": "Number"
21281          }, {
21282            "name": "timeFromNow",
21283            "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
21284            "type": "Number",
21285            "optional": true
21286          }],
21287          "return": {
21288            "description": "value  Returns the current frequency value",
21289            "type": "Number"
21290          },
21291          "class": "p5.Filter",
21292          "module": "p5.sound",
21293          "submodule": "p5.sound"
21294        }, {
21295          "file": "lib/addons/p5.sound.js",
21296          "line": 8645,
21297          "description": "<p>Controls either width of a bandpass frequency,\nor the resonance of a low/highpass cutoff frequency.</p>\n",
21298          "itemtype": "method",
21299          "name": "res",
21300          "params": [{
21301            "name": "res",
21302            "description": "<p>Resonance/Width of filter freq\n                     from 0.001 to 1000</p>\n",
21303            "type": "Number"
21304          }, {
21305            "name": "timeFromNow",
21306            "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
21307            "type": "Number",
21308            "optional": true
21309          }],
21310          "return": {
21311            "description": "value Returns the current res value",
21312            "type": "Number"
21313          },
21314          "class": "p5.Filter",
21315          "module": "p5.sound",
21316          "submodule": "p5.sound"
21317        }, {
21318          "file": "lib/addons/p5.sound.js",
21319          "line": 8667,
21320          "description": "<p>Controls the gain attribute of a Biquad Filter.\nThis is distinctly different from .amp() which is inherited from p5.Effect\n.amp() controls the volume via the output gain node\np5.Filter.gain() controls the gain parameter of a Biquad Filter node.</p>\n",
21321          "itemtype": "method",
21322          "name": "gain",
21323          "params": [{
21324            "name": "gain",
21325            "description": "",
21326            "type": "Number"
21327          }],
21328          "return": {
21329            "description": "Returns the current or updated gain value",
21330            "type": "Number"
21331          },
21332          "class": "p5.Filter",
21333          "module": "p5.sound",
21334          "submodule": "p5.sound"
21335        }, {
21336          "file": "lib/addons/p5.sound.js",
21337          "line": 8688,
21338          "description": "<p>Toggle function. Switches between the specified type and allpass</p>\n",
21339          "itemtype": "method",
21340          "name": "toggle",
21341          "return": {
21342            "description": "[Toggle value]",
21343            "type": "Boolean"
21344          },
21345          "class": "p5.Filter",
21346          "module": "p5.sound",
21347          "submodule": "p5.sound"
21348        }, {
21349          "file": "lib/addons/p5.sound.js",
21350          "line": 8703,
21351          "description": "<p>Set the type of a p5.Filter. Possible types include:\n&quot;lowpass&quot; (default), &quot;highpass&quot;, &quot;bandpass&quot;,\n&quot;lowshelf&quot;, &quot;highshelf&quot;, &quot;peaking&quot;, &quot;notch&quot;,\n&quot;allpass&quot;.</p>\n",
21352          "itemtype": "method",
21353          "name": "setType",
21354          "params": [{
21355            "name": "t",
21356            "description": "",
21357            "type": "String"
21358          }],
21359          "class": "p5.Filter",
21360          "module": "p5.sound",
21361          "submodule": "p5.sound"
21362        }, {
21363          "file": "lib/addons/p5.sound.js",
21364          "line": 8910,
21365          "description": "<p>The p5.EQ is built with abstracted p5.Filter objects.\nTo modify any bands, use methods of the <a \nhref=\"/reference/#/p5.Filter\" title=\"p5.Filter reference\">\np5.Filter</a> API, especially <code>gain</code> and <code>freq</code>.\nBands are stored in an array, with indices 0 - 3, or 0 - 7</p>\n",
21366          "itemtype": "property",
21367          "name": "bands",
21368          "type": "Array",
21369          "class": "p5.EQ",
21370          "module": "p5.sound",
21371          "submodule": "p5.sound"
21372        }, {
21373          "file": "lib/addons/p5.sound.js",
21374          "line": 8945,
21375          "description": "<p>Process an input by connecting it to the EQ</p>\n",
21376          "itemtype": "method",
21377          "name": "process",
21378          "params": [{
21379            "name": "src",
21380            "description": "<p>Audio source</p>\n",
21381            "type": "Object"
21382          }],
21383          "class": "p5.EQ",
21384          "module": "p5.sound",
21385          "submodule": "p5.sound"
21386        }, {
21387          "file": "lib/addons/p5.sound.js",
21388          "line": 9033,
21389          "description": "<p><a title=\"Web Audio Panner docs\"  href=\n\"https://developer.mozilla.org/en-US/docs/Web/API/PannerNode\">\nWeb Audio Spatial Panner Node</a></p>\n<p>Properties include</p>\n<ul>\n<li>&lt;a title=&quot;w3 spec for Panning Model&quot;\nhref=&quot;<a href=\"https://www.w3.org/TR/webaudio/#idl-def-PanningModelType\">https://www.w3.org/TR/webaudio/#idl-def-PanningModelType</a>&quot;<blockquote>\n<p>panningModel</a>: &quot;equal power&quot; or &quot;HRTF&quot;</p>\n</blockquote>\n</li>\n<li>&lt;a title=&quot;w3 spec for Distance Model&quot;\nhref=&quot;<a href=\"https://www.w3.org/TR/webaudio/#idl-def-DistanceModelType\">https://www.w3.org/TR/webaudio/#idl-def-DistanceModelType</a>&quot;<blockquote>\n<p>distanceModel</a>: &quot;linear&quot;, &quot;inverse&quot;, or &quot;exponential&quot;</p>\n</blockquote>\n</li>\n</ul>\n",
21390          "itemtype": "property",
21391          "name": "panner",
21392          "type": "AudioNode",
21393          "class": "p5.Panner3D",
21394          "module": "p5.sound",
21395          "submodule": "p5.sound"
21396        }, {
21397          "file": "lib/addons/p5.sound.js",
21398          "line": 9056,
21399          "description": "<p>Connect an audio sorce</p>\n",
21400          "itemtype": "method",
21401          "name": "process",
21402          "params": [{
21403            "name": "src",
21404            "description": "<p>Input source</p>\n",
21405            "type": "Object"
21406          }],
21407          "class": "p5.Panner3D",
21408          "module": "p5.sound",
21409          "submodule": "p5.sound"
21410        }, {
21411          "file": "lib/addons/p5.sound.js",
21412          "line": 9065,
21413          "description": "<p>Set the X,Y,Z position of the Panner</p>\n",
21414          "itemtype": "method",
21415          "name": "set",
21416          "params": [{
21417            "name": "xVal",
21418            "description": "",
21419            "type": "Number"
21420          }, {
21421            "name": "yVal",
21422            "description": "",
21423            "type": "Number"
21424          }, {
21425            "name": "zVal",
21426            "description": "",
21427            "type": "Number"
21428          }, {
21429            "name": "time",
21430            "description": "",
21431            "type": "Number"
21432          }],
21433          "return": {
21434            "description": "Updated x, y, z values as an array",
21435            "type": "Array"
21436          },
21437          "class": "p5.Panner3D",
21438          "module": "p5.sound",
21439          "submodule": "p5.sound"
21440        }, {
21441          "file": "lib/addons/p5.sound.js",
21442          "line": 9084,
21443          "description": "<p>Getter and setter methods for position coordinates</p>\n",
21444          "itemtype": "method",
21445          "name": "positionX",
21446          "return": {
21447            "description": "updated coordinate value",
21448            "type": "Number"
21449          },
21450          "class": "p5.Panner3D",
21451          "module": "p5.sound",
21452          "submodule": "p5.sound"
21453        }, {
21454          "file": "lib/addons/p5.sound.js",
21455          "line": 9089,
21456          "description": "<p>Getter and setter methods for position coordinates</p>\n",
21457          "itemtype": "method",
21458          "name": "positionY",
21459          "return": {
21460            "description": "updated coordinate value",
21461            "type": "Number"
21462          },
21463          "class": "p5.Panner3D",
21464          "module": "p5.sound",
21465          "submodule": "p5.sound"
21466        }, {
21467          "file": "lib/addons/p5.sound.js",
21468          "line": 9094,
21469          "description": "<p>Getter and setter methods for position coordinates</p>\n",
21470          "itemtype": "method",
21471          "name": "positionZ",
21472          "return": {
21473            "description": "updated coordinate value",
21474            "type": "Number"
21475          },
21476          "class": "p5.Panner3D",
21477          "module": "p5.sound",
21478          "submodule": "p5.sound"
21479        }, {
21480          "file": "lib/addons/p5.sound.js",
21481          "line": 9132,
21482          "description": "<p>Set the X,Y,Z position of the Panner</p>\n",
21483          "itemtype": "method",
21484          "name": "orient",
21485          "params": [{
21486            "name": "xVal",
21487            "description": "",
21488            "type": "Number"
21489          }, {
21490            "name": "yVal",
21491            "description": "",
21492            "type": "Number"
21493          }, {
21494            "name": "zVal",
21495            "description": "",
21496            "type": "Number"
21497          }, {
21498            "name": "time",
21499            "description": "",
21500            "type": "Number"
21501          }],
21502          "return": {
21503            "description": "Updated x, y, z values as an array",
21504            "type": "Array"
21505          },
21506          "class": "p5.Panner3D",
21507          "module": "p5.sound",
21508          "submodule": "p5.sound"
21509        }, {
21510          "file": "lib/addons/p5.sound.js",
21511          "line": 9151,
21512          "description": "<p>Getter and setter methods for orient coordinates</p>\n",
21513          "itemtype": "method",
21514          "name": "orientX",
21515          "return": {
21516            "description": "updated coordinate value",
21517            "type": "Number"
21518          },
21519          "class": "p5.Panner3D",
21520          "module": "p5.sound",
21521          "submodule": "p5.sound"
21522        }, {
21523          "file": "lib/addons/p5.sound.js",
21524          "line": 9156,
21525          "description": "<p>Getter and setter methods for orient coordinates</p>\n",
21526          "itemtype": "method",
21527          "name": "orientY",
21528          "return": {
21529            "description": "updated coordinate value",
21530            "type": "Number"
21531          },
21532          "class": "p5.Panner3D",
21533          "module": "p5.sound",
21534          "submodule": "p5.sound"
21535        }, {
21536          "file": "lib/addons/p5.sound.js",
21537          "line": 9161,
21538          "description": "<p>Getter and setter methods for orient coordinates</p>\n",
21539          "itemtype": "method",
21540          "name": "orientZ",
21541          "return": {
21542            "description": "updated coordinate value",
21543            "type": "Number"
21544          },
21545          "class": "p5.Panner3D",
21546          "module": "p5.sound",
21547          "submodule": "p5.sound"
21548        }, {
21549          "file": "lib/addons/p5.sound.js",
21550          "line": 9199,
21551          "description": "<p>Set the rolloff factor and max distance</p>\n",
21552          "itemtype": "method",
21553          "name": "setFalloff",
21554          "params": [{
21555            "name": "maxDistance",
21556            "description": "",
21557            "type": "Number",
21558            "optional": true
21559          }, {
21560            "name": "rolloffFactor",
21561            "description": "",
21562            "type": "Number",
21563            "optional": true
21564          }],
21565          "class": "p5.Panner3D",
21566          "module": "p5.sound",
21567          "submodule": "p5.sound"
21568        }, {
21569          "file": "lib/addons/p5.sound.js",
21570          "line": 9209,
21571          "description": "<p>Maxium distance between the source and the listener</p>\n",
21572          "itemtype": "method",
21573          "name": "maxDist",
21574          "params": [{
21575            "name": "maxDistance",
21576            "description": "",
21577            "type": "Number"
21578          }],
21579          "return": {
21580            "description": "updated value",
21581            "type": "Number"
21582          },
21583          "class": "p5.Panner3D",
21584          "module": "p5.sound",
21585          "submodule": "p5.sound"
21586        }, {
21587          "file": "lib/addons/p5.sound.js",
21588          "line": 9221,
21589          "description": "<p>How quickly the volume is reduced as the source moves away from the listener</p>\n",
21590          "itemtype": "method",
21591          "name": "rollof",
21592          "params": [{
21593            "name": "rolloffFactor",
21594            "description": "",
21595            "type": "Number"
21596          }],
21597          "return": {
21598            "description": "updated value",
21599            "type": "Number"
21600          },
21601          "class": "p5.Panner3D",
21602          "module": "p5.sound",
21603          "submodule": "p5.sound"
21604        }, {
21605          "file": "lib/addons/p5.sound.js",
21606          "line": 9526,
21607          "description": "<p>The p5.Delay is built with two\n<a href=\"http://www.w3.org/TR/webaudio/#DelayNode\">\nWeb Audio Delay Nodes</a>, one for each stereo channel.</p>\n",
21608          "itemtype": "property",
21609          "name": "leftDelay",
21610          "type": "DelayNode",
21611          "class": "p5.Delay",
21612          "module": "p5.sound",
21613          "submodule": "p5.sound"
21614        }, {
21615          "file": "lib/addons/p5.sound.js",
21616          "line": 9534,
21617          "description": "<p>The p5.Delay is built with two\n<a href=\"http://www.w3.org/TR/webaudio/#DelayNode\">\nWeb Audio Delay Nodes</a>, one for each stereo channel.</p>\n",
21618          "itemtype": "property",
21619          "name": "rightDelay",
21620          "type": "DelayNode",
21621          "class": "p5.Delay",
21622          "module": "p5.sound",
21623          "submodule": "p5.sound"
21624        }, {
21625          "file": "lib/addons/p5.sound.js",
21626          "line": 9566,
21627          "description": "<p>Add delay to an audio signal according to a set\nof delay parameters.</p>\n",
21628          "itemtype": "method",
21629          "name": "process",
21630          "params": [{
21631            "name": "Signal",
21632            "description": "<p>An object that outputs audio</p>\n",
21633            "type": "Object"
21634          }, {
21635            "name": "delayTime",
21636            "description": "<p>Time (in seconds) of the delay/echo.\n                             Some browsers limit delayTime to\n                             1 second.</p>\n",
21637            "type": "Number",
21638            "optional": true
21639          }, {
21640            "name": "feedback",
21641            "description": "<p>sends the delay back through itself\n                             in a loop that decreases in volume\n                             each time.</p>\n",
21642            "type": "Number",
21643            "optional": true
21644          }, {
21645            "name": "lowPass",
21646            "description": "<p>Cutoff frequency. Only frequencies\n                             below the lowPass will be part of the\n                             delay.</p>\n",
21647            "type": "Number",
21648            "optional": true
21649          }],
21650          "class": "p5.Delay",
21651          "module": "p5.sound",
21652          "submodule": "p5.sound"
21653        }, {
21654          "file": "lib/addons/p5.sound.js",
21655          "line": 9601,
21656          "description": "<p>Set the delay (echo) time, in seconds. Usually this value will be\na floating point number between 0.0 and 1.0.</p>\n",
21657          "itemtype": "method",
21658          "name": "delayTime",
21659          "params": [{
21660            "name": "delayTime",
21661            "description": "<p>Time (in seconds) of the delay</p>\n",
21662            "type": "Number"
21663          }],
21664          "class": "p5.Delay",
21665          "module": "p5.sound",
21666          "submodule": "p5.sound"
21667        }, {
21668          "file": "lib/addons/p5.sound.js",
21669          "line": 9620,
21670          "description": "<p>Feedback occurs when Delay sends its signal back through its input\nin a loop. The feedback amount determines how much signal to send each\ntime through the loop. A feedback greater than 1.0 is not desirable because\nit will increase the overall output each time through the loop,\ncreating an infinite feedback loop. The default value is 0.5</p>\n",
21671          "itemtype": "method",
21672          "name": "feedback",
21673          "params": [{
21674            "name": "feedback",
21675            "description": "<p>0.0 to 1.0, or an object such as an\n                                Oscillator that can be used to\n                                modulate this param</p>\n",
21676            "type": "Number|Object"
21677          }],
21678          "return": {
21679            "description": "Feedback value",
21680            "type": "Number"
21681          },
21682          "class": "p5.Delay",
21683          "module": "p5.sound",
21684          "submodule": "p5.sound"
21685        }, {
21686          "file": "lib/addons/p5.sound.js",
21687          "line": 9648,
21688      
21688    "description": "<p>Set a lowpass filter frequency for the delay. A lowpass filter\nwill cut off any frequencies higher than the filter frequency.</p>\n",
21689          "itemtype": "method",
21690          "name": "filter",
21691          "params": [{
21692            "name": "cutoffFreq",
21693            "description": "<p>A lowpass filter will cut off any\n                            frequencies higher than the filter frequency.</p>\n",
21694            "type": "Number|Object"
21695          }, {
21696            "name": "res",
21697            "description": "<p>Resonance of the filter frequency\n                            cutoff, or an object (i.e. a p5.Oscillator)\n                            that can be used to modulate this parameter.\n                            High numbers (i.e. 15) will produce a resonance,\n                            low numbers (i.e. .2) will produce a slope.</p>\n",
21698            "type": "Number|Object"
21699          }],
21700          "class": "p5.Delay",
21701          "module": "p5.sound",
21702          "submodule": "p5.sound"
21703        }, {
21704          "file": "lib/addons/p5.sound.js",
21705          "line": 9665,
21706          "description": "<p>Choose a preset type of delay. &#39;pingPong&#39; bounces the signal\nfrom the left to the right channel to produce a stereo effect.\nAny other parameter will revert to the default delay setting.</p>\n",
21707          "itemtype": "method",
21708          "name": "setType",
21709          "params": [{
21710            "name": "type",
21711            "description": "<p>&#39;pingPong&#39; (1) or &#39;default&#39; (0)</p>\n",
21712            "type": "String|Number"
21713          }],
21714          "class": "p5.Delay",
21715          "module": "p5.sound",
21716          "submodule": "p5.sound"
21717        }, {
21718          "file": "lib/addons/p5.sound.js",
21719          "line": 9698,
21720          "description": "<p>Set the output level of the delay effect.</p>\n",
21721          "itemtype": "method",
21722          "name": "amp",
21723          "params": [{
21724            "name": "volume",
21725            "description": "<p>amplitude between 0 and 1.0</p>\n",
21726            "type": "Number"
21727          }, {
21728            "name": "rampTime",
21729            "description": "<p>create a fade that lasts rampTime</p>\n",
21730            "type": "Number",
21731            "optional": true
21732          }, {
21733            "name": "timeFromNow",
21734            "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
21735            "type": "Number",
21736            "optional": true
21737          }],
21738          "class": "p5.Delay",
21739          "module": "p5.sound",
21740          "submodule": "p5.sound"
21741        }, {
21742          "file": "lib/addons/p5.sound.js",
21743          "line": 9707,
21744          "description": "<p>Send output to a p5.sound or web audio object</p>\n",
21745          "itemtype": "method",
21746          "name": "connect",
21747          "params": [{
21748            "name": "unit",
21749            "description": "",
21750            "type": "Object"
21751          }],
21752          "class": "p5.Delay",
21753          "module": "p5.sound",
21754          "submodule": "p5.sound"
21755        }, {
21756          "file": "lib/addons/p5.sound.js",
21757          "line": 9713,
21758          "description": "<p>Disconnect all output.</p>\n",
21759          "itemtype": "method",
21760          "name": "disconnect",
21761          "class": "p5.Delay",
21762          "module": "p5.sound",
21763          "submodule": "p5.sound"
21764        }, {
21765          "file": "lib/addons/p5.sound.js",
21766          "line": 9806,
21767          "description": "<p>Connect a source to the reverb, and assign reverb parameters.</p>\n",
21768          "itemtype": "method",
21769          "name": "process",
21770          "params": [{
21771            "name": "src",
21772            "description": "<p>p5.sound / Web Audio object with a sound\n                         output.</p>\n",
21773            "type": "Object"
21774          }, {
21775            "name": "seconds",
21776            "description": "<p>Duration of the reverb, in seconds.\n                         Min: 0, Max: 10. Defaults to 3.</p>\n",
21777            "type": "Number",
21778            "optional": true
21779          }, {
21780            "name": "decayRate",
21781            "description": "<p>Percentage of decay with each echo.\n                          Min: 0, Max: 100. Defaults to 2.</p>\n",
21782            "type": "Number",
21783            "optional": true
21784          }, {
21785            "name": "reverse",
21786            "description": "<p>Play the reverb backwards or forwards.</p>\n",
21787            "type": "Boolean",
21788            "optional": true
21789          }],
21790          "class": "p5.Reverb",
21791          "module": "p5.sound",
21792          "submodule": "p5.sound"
21793        }, {
21794          "file": "lib/addons/p5.sound.js",
21795          "line": 9835,
21796          "description": "<p>Set the reverb settings. Similar to .process(), but without\nassigning a new input.</p>\n",
21797          "itemtype": "method",
21798          "name": "set",
21799          "params": [{
21800            "name": "seconds",
21801            "description": "<p>Duration of the reverb, in seconds.\n                         Min: 0, Max: 10. Defaults to 3.</p>\n",
21802            "type": "Number",
21803            "optional": true
21804          }, {
21805            "name": "decayRate",
21806            "description": "<p>Percentage of decay with each echo.\n                          Min: 0, Max: 100. Defaults to 2.</p>\n",
21807            "type": "Number",
21808            "optional": true
21809          }, {
21810            "name": "reverse",
21811            "description": "<p>Play the reverb backwards or forwards.</p>\n",
21812            "type": "Boolean",
21813            "optional": true
21814          }],
21815          "class": "p5.Reverb",
21816          "module": "p5.sound",
21817          "submodule": "p5.sound"
21818        }, {
21819          "file": "lib/addons/p5.sound.js",
21820          "line": 9863,
21821          "description": "<p>Set the output level of the reverb effect.</p>\n",
21822          "itemtype": "method",
21823          "name": "amp",
21824          "params": [{
21825            "name": "volume",
21826            "description": "<p>amplitude between 0 and 1.0</p>\n",
21827            "type": "Number"
21828          }, {
21829            "name": "rampTime",
21830            "description": "<p>create a fade that lasts rampTime</p>\n",
21831            "type": "Number",
21832            "optional": true
21833          }, {
21834            "name": "timeFromNow",
21835            "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
21836            "type": "Number",
21837            "optional": true
21838          }],
21839          "class": "p5.Reverb",
21840          "module": "p5.sound",
21841          "submodule": "p5.sound"
21842        }, {
21843          "file": "lib/addons/p5.sound.js",
21844          "line": 9872,
21845          "description": "<p>Send output to a p5.sound or web audio object</p>\n",
21846          "itemtype": "method",
21847          "name": "connect",
21848          "params": [{
21849            "name": "unit",
21850            "description": "",
21851            "type": "Object"
21852          }],
21853          "class": "p5.Reverb",
21854          "module": "p5.sound",
21855          "submodule": "p5.sound"
21856        }, {
21857          "file": "lib/addons/p5.sound.js",
21858          "line": 9878,
21859          "description": "<p>Disconnect all output.</p>\n",
21860          "itemtype": "method",
21861          "name": "disconnect",
21862          "class": "p5.Reverb",
21863          "module": "p5.sound",
21864          "submodule": "p5.sound"
21865        }, {
21866          "file": "lib/addons/p5.sound.js",
21867          "line": 9969,
21868          "description": "<p>Internally, the p5.Convolver uses the a\n<a href=\"http://www.w3.org/TR/webaudio/#ConvolverNode\">\nWeb Audio Convolver Node</a>.</p>\n",
21869          "itemtype": "property",
21870          "name": "convolverNode",
21871          "type": "ConvolverNode",
21872          "class": "p5.Convolver",
21873          "module": "p5.sound",
21874          "submodule": "p5.sound"
21875        }, {
21876          "file": "lib/addons/p5.sound.js",
21877          "line": 9992,
21878          "description": "<p>Create a p5.Convolver. Accepts a path to a soundfile\nthat will be used to generate an impulse response.</p>\n",
21879          "itemtype": "method",
21880          "name": "createConvolver",
21881          "params": [{
21882            "name": "path",
21883            "description": "<p>
21883path to a sound file</p>\n",
21884            "type": "String"
21885          }, {
21886            "name": "callback",
21887            "description": "<p>function to call if loading is successful.\n                              The object will be passed in as the argument\n                              to the callback function.</p>\n",
21888            "type": "Function",
21889            "optional": true
21890          }, {
21891            "name": "errorCallback",
21892            "description": "<p>function to call if loading is not successful.\n                              A custom error will be passed in as the argument\n                              to the callback function.</p>\n",
21893            "type": "Function",
21894            "optional": true
21895          }],
21896          "return": {
21897            "description": "",
21898            "type": "p5.Convolver"
21899          },
21900          "example": ["\n<div><code>\nvar cVerb, sound;\nfunction preload() {\n  // We have both MP3 and OGG versions of all sound assets\n  soundFormats('ogg', 'mp3');\n\n  // Try replacing 'bx-spring' with other soundfiles like\n  // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'\n  cVerb = createConvolver('assets/bx-spring.mp3');\n\n  // Try replacing 'Damscray_DancingTiger' with\n  // 'beat', 'doorbell', lucky_dragons_-_power_melody'\n  sound = loadSound('assets/Damscray_DancingTiger.mp3');\n}\n\nfunction setup() {\n  // disconnect from master output...\n  sound.disconnect();\n\n  // ...and process with cVerb\n  // so that we only hear the convolution\n  cVerb.process(sound);\n\n  sound.play();\n}\n</code></div>"],
21901          "class": "p5.Convolver",
21902          "module": "p5.sound",
21903          "submodule": "p5.sound"
21904        }, {
21905          "file": "lib/addons/p5.sound.js",
21906          "line": 10116,
21907          "description": "<p>Connect a source to the reverb, and assign reverb parameters.</p>\n",
21908          "itemtype": "method",
21909          "name": "process",
21910          "params": [{
21911            "name": "src",
21912            "description": "<p>p5.sound / Web Audio object with a sound\n                         output.</p>\n",
21913            "type": "Object"
21914          }],
21915          "example": ["\n<div><code>\nvar cVerb, sound;\nfunction preload() {\n  soundFormats('ogg', 'mp3');\n\n  cVerb = createConvolver('assets/concrete-tunnel.mp3');\n\n  sound = loadSound('assets/beat.mp3');\n}\n\nfunction setup() {\n  // disconnect from master output...\n  sound.disconnect();\n\n  // ...and process with (i.e. connect to) cVerb\n  // so that we only hear the convolution\n  cVerb.process(sound);\n\n  sound.play();\n}\n</code></div>"],
21916          "class": "p5.Convolver",
21917          "module": "p5.sound",
21918          "submodule": "p5.sound"
21919        }, {
21920          "file": "lib/addons/p5.sound.js",
21921          "line": 10148,
21922          "description": "<p>If you load multiple impulse files using the .addImpulse method,\nthey will be stored as Objects in this Array. Toggle between them\nwith the <code>toggleImpulse(id)</code> method.</p>\n",
21923          "itemtype": "property",
21924          "name": "impulses",
21925          "type": "Array",
21926          "class": "p5.Convolver",
21927          "module": "p5.sound",
21928          "submodule": "p5.sound"
21929        }, {
21930          "file": "lib/addons/p5.sound.js",
21931          "line": 10156,
21932          "description": "<p>Load and assign a new Impulse Response to the p5.Convolver.\nThe impulse is added to the <code>.impulses</code> array. Previous\nimpulses can be accessed with the <code>.toggleImpulse(id)</code>\nmethod.</p>\n",
21933          "itemtype": "method",
21934          "name": "addImpulse",
21935          "params": [{
21936            "name": "path",
21937            "description": "<p>path to a sound file</p>\n",
21938            "type": "String"
21939          }, {
21940            "name": "callback",
21941            "description": "<p>function (optional)</p>\n",
21942            "type": "Function"
21943          }, {
21944            "name": "errorCallback",
21945            "description": "<p>function (optional)</p>\n",
21946            "type": "Function"
21947          }],
21948          "class": "p5.Convolver",
21949          "module": "p5.sound",
21950          "submodule": "p5.sound"
21951        }, {
21952          "file": "lib/addons/p5.sound.js",
21953          "line": 10174,
21954          "description": "<p>Similar to .addImpulse, except that the <code>.impulses</code>\nArray is reset to save memory. A new <code>.impulses</code>\narray is created with this impulse as the only item.</p>\n",
21955          "itemtype": "method",
21956          "name": "resetImpulse",
21957          "params": [{
21958            "name": "path",
21959            "description": "<p>
21959path to a sound file</p>\n",
21960            "type": "String"
21961          }, {
21962            "name": "callback",
21963            "description": "<p>function (optional)</p>\n",
21964            "type": "Function"
21965          }, {
21966            "name": "errorCallback",
21967            "description": "<p>function (optional)</p>\n",
21968            "type": "Function"
21969          }],
21970          "class": "p5.Convolver",
21971          "module": "p5.sound",
21972          "submodule": "p5.sound"
21973        }, {
21974          "file": "lib/addons/p5.sound.js",
21975          "line": 10192,
21976          "description": "<p>If you have used <code>.addImpulse()</code> to add multiple impulses\nto a p5.Convolver, then you can use this method to toggle between\nthe items in the <code>.impulses</code> Array. Accepts a parameter\nto identify which impulse you wish to use, identified either by its\noriginal filename (String) or by its position in the <code>.impulses\n</code> Array (Number).<br/>\nYou can access the objects in the .impulses Array directly. Each\nObject has two attributes: an <code>.audioBuffer</code> (type:\nWeb Audio <a href=\"\nhttp://webaudio.github.io/web-audio-api/#the-audiobuffer-interface\">\nAudioBuffer)</a> and a <code>.name</code>, a String that corresponds\nwith the original filename.</p>\n",
21977          "itemtype": "method",
21978          "name": "toggleImpulse",
21979          "params": [{
21980            "name": "id",
21981            "description": "<p>Identify the impulse by its original filename\n                          (String), or by its position in the\n                          <code>.impulses</code> Array (Number).</p>\n",
21982            "type": "String|Number"
21983          }],
21984          "class": "p5.Convolver",
21985          "module": "p5.sound",
21986          "submodule": "p5.sound"
21987        }, {
21988          "file": "lib/addons/p5.sound.js",
21989          "line": 10234,
21990          "class": "p5.Convolver",
21991          "module": "p5.sound",
21992          "submodule": "p5.sound"
21993        }, {
21994          "file": "lib/addons/p5.sound.js",
21995          "line": 10259,
21996          "class": "p5.Convolver",
21997          "module": "p5.sound",
21998          "submodule": "p5.sound"
21999        }, {
22000          "file": "lib/addons/p5.sound.js",
22001          "line": 10454,
22002          "description": "<p>Set the global tempo, in beats per minute, for all\np5.Parts. This method will impact all active p5.Parts.</p>\n",
22003          "itemtype": "method",
22004          "name": "setBPM",
22005          "params": [{
22006            "name": "BPM",
22007            "description": "<p>Beats Per Minute</p>\n",
22008            "type": "Number"
22009          }, {
22010            "name": "rampTime",
22011            "description": "<p>Seconds from now</p>\n",
22012            "type": "Number"
22013          }],
22014          "class": "p5.Convolver",
22015          "module": "p5.sound",
22016          "submodule": "p5.sound"
22017        }, {
22018          "file": "lib/addons/p5.sound.js",
22019          "line": 10544,
22020          "description": "<p>Array of values to pass into the callback\nat each step of the phrase. Depending on the callback\nfunction&#39;s requirements, these values may be numbers,\nstrings, or an object with multiple parameters.\nZero (0) indicates a rest.</p>\n",
22021          "itemtype": "property",
22022          "name": "sequence",
22023          "type": "Array",
22024          "class": "p5.Phrase",
22025          "module": "p5.sound",
22026          "submodule": "p5.sound"
22027        }, {
22028          "file": "lib/addons/p5.sound.js",
22029          "line": 10632,
22030          "description": "<p>Set the tempo of this part, in Beats Per Minute.</p>\n",
22031          "itemtype": "method",
22032          "name": "setBPM",
22033          "params": [{
22034            "name": "BPM",
22035            "description": "<p>Beats Per Minute</p>\n",
22036            "type": "Number"
22037          }, {
22038            "name": "rampTime",
22039            "description": "<p>Seconds from now</p>\n",
22040            "type": "Number",
22041            "optional": true
22042          }],
22043          "class": "p5.Part",
22044          "module": "p5.sound",
22045          "submodule": "p5.sound"
22046        }, {
22047          "file": "lib/addons/p5.sound.js",
22048          "line": 10642,
22049          "description": "<p>Returns the tempo, in Beats Per Minute, of this part.</p>\n",
22050          "itemtype": "method",
22051          "name": "getBPM",
22052          "return": {
22053            "description": "",
22054            "type": "Number"
22055          },
22056          "class": "p5.Part",
22057          "module": "p5.sound",
22058          "submodule": "p5.sound"
22059        }, {
22060          "file": "lib/addons/p5.sound.js",
22061          "line": 10651,
22062          "description": "<p>Start playback of this part. It will play\nthrough all of its phrases at a speed\ndetermined by setBPM.</p>\n",
22063          "itemtype": "method",
22064          "name": "start",
22065          "params": [{
22066            "name": "time",
22067            "description": "<p>seconds from now</p>\n",
22068            "type": "Number",
22069            "optional": true
22070          }],
22071          "class": "p5.Part",
22072          "module": "p5.sound",
22073          "submodule": "p5.sound"
22074        }, {
22075          "file": "lib/addons/p5.sound.js",
22076          "line": 10667,
22077          "description": "<p>Loop playback of this part. It will begin\nlooping through all of its phrases at a speed\ndetermined by setBPM.</p>\n",
22078          "itemtype": "method",
22079          "name": "loop",
22080          "params": [{
22081            "name": "time",
22082            "description": "<p>seconds from now</p>\n",
22083            "type": "Number",
22084            "optional": true
22085          }],
22086          "class": "p5.Part",
22087          "module": "p5.sound",
22088          "submodule": "p5.sound"
22089        }, {
22090          "file": "lib/addons/p5.sound.js",
22091          "line": 10684,
22092          "description": "<p>Tell the part to stop looping.</p>\n",
22093          "itemtype": "method",
22094          "name": "noLoop",
22095          "class": "p5.Part",
22096          "module": "p5.sound",
22097          "submodule": "p5.sound"
22098        }, {
22099          "file": "lib/addons/p5.sound.js",
22100          "line": 10696,
22101          "description": "<p>Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again.</p>\n",
22102          "itemtype": "method",
22103          "name": "stop",
22104          "params": [{
22105            "name": "time",
22106            "description": "<p>seconds from now</p>\n",
22107            "type": "Number",
22108            "optional": true
22109          }],
22110          "class": "p5.Part",
22111          "module": "p5.sound",
22112          "submodule": "p5.sound"
22113        }, {
22114          "file": "lib/addons/p5.sound.js",
22115          "line": 10706,
22116          "description": "<p>Pause the part. Playback will resume\nfrom the current step.</p>\n",
22117          "itemtype": "method",
22118          "name": "pause",
22119          "params": [{
22120            "name": "time",
22121            "description": "<p>seconds from now</p>\n",
22122            "type": "Number"
22123          }],
22124          "class": "p5.Part",
22125          "module": "p5.sound",
22126          "submodule": "p5.sound"
22127        }, {
22128          "file": "lib/addons/p5.sound.js",
22129          "line": 10718,
22130          "description": "<p>Add a p5.Phrase to this Part.</p>\n",
22131          "itemtype": "method",
22132          "name": "addPhrase",
22133          "params": [{
22134            "name": "phrase",
22135            "description": "<p>reference to a p5.Phrase</p>\n",
22136            "type": "p5.Phrase"
22137          }],
22138          "class": "p5.Part",
22139          "module": "p5.sound",
22140          "submodule": "p5.sound"
22141        }, {
22142          "file": "lib/addons/p5.sound.js",
22143          "line": 10739,
22144          "description": "<p>Remove a phrase from this part, based on the name it was\ngiven when it was created.</p>\n",
22145          "itemtype": "method",
22146          "name": "removePhrase",
22147          "params": [{
22148            "name": "phraseName",
22149            "description": "",
22150            "type": "String"
22151          }],
22152          "class": "p5.Part",
22153          "module": "p5.sound",
22154          "submodule": "p5.sound"
22155        }, {
22156          "file": "lib/addons/p5.sound.js",
22157          "line": 10753,
22158          "description": "<p>Get a phrase from this part, based on the name it was\ngiven when it was created. Now you can modify its array.</p>\n",
22159          "itemtype": "method",
22160          "name": "getPhrase",
22161          "params": [{
22162            "name": "phraseName",
22163            "description": "",
22164            "type": "String"
22165          }],
22166          "class": "p5.Part",
22167          "module": "p5.sound",
22168          "submodule": "p5.sound"
22169        }, {
22170          "file": "lib/addons/p5.sound.js",
22171          "line": 10767,
22172          "description": "<p>Find all sequences with the specified name, and replace their patterns with the specified array.</p>\n",
22173          "itemtype": "method",
22174          "name": "replaceSequence",
22175          "params": [{
22176            "name": "phraseName",
22177            "description": "",
22178            "type": "String"
22179          }, {
22180            "name": "sequence",
22181            "description": "<p>Array of values to pass into the callback\n                          at each step of the phrase.</p>\n",
22182            "type": "Array"
22183          }],
22184          "class": "p5.Part",
22185          "module": "p5.sound",
22186          "submodule": "p5.sound"
22187        }, {
22188          "file": "lib/addons/p5.sound.js",
22189          "line": 10794,
22190          "description": "<p>Set the function that will be called at every step. This will clear the previous function.</p>\n",
22191          "itemtype": "method",
22192          "name": "onStep",
22193          "params": [{
22194            "name": "callback",
22195            "description": "<p>The name of the callback\n                            you want to fire\n                            on every beat/tatum.</p>\n",
22196            "type": "Function"
22197          }],
22198          "class": "p5.Part",
22199          "module": "p5.sound",
22200          "submodule": "p5.sound"
22201        }, {
22202          "file": "lib/addons/p5.sound.js",
22203          "line": 10847,
22204          "description": "<p>Start playback of the score.</p>\n",
22205          "itemtype": "method",
22206          "name": "start",
22207          "class": "p5.Score",
22208          "module": "p5.sound",
22209          "submodule": "p5.sound"
22210        }, {
22211          "file": "lib/addons/p5.sound.js",
22212          "line": 10856,
22213          "description": "<p>Stop playback of the score.</p>\n",
22214          "itemtype": "method",
22215          "name": "stop",
22216          "class": "p5.Score",
22217          "module": "p5.sound",
22218          "submodule": "p5.sound"
22219        }, {
22220          "file": "lib/addons/p5.sound.js",
22221          "line": 10866,
22222          "description": "<p>Pause playback of the score.</p>\n",
22223          "itemtype": "method",
22224          "name": "pause",
22225          "class": "p5.Score",
22226          "module": "p5.sound",
22227          "submodule": "p5.sound"
22228        }, {
22229          "file": "lib/addons/p5.sound.js",
22230          "line": 10874,
22231          "description": "<p>Loop playback of the score.</p>\n",
22232          "itemtype": "method",
22233          "name": "loop",
22234          "class": "p5.Score",
22235          "module": "p5.sound",
22236          "submodule": "p5.sound"
22237        }, {
22238          "file": "lib/addons/p5.sound.js",
22239          "line": 10883,
22240          "description": "<p>Stop looping playback of the score. If it\nis currently playing, this will go into effect\nafter the current roun
22240d of playback completes.</p>\n",
22241          "itemtype": "method",
22242          "name": "noLoop",
22243          "class": "p5.Score",
22244          "module": "p5.sound",
22245          "submodule": "p5.sound"
22246        }, {
22247          "file": "lib/addons/p5.sound.js",
22248          "line": 10908,
22249          "description": "<p>Set the tempo for all parts in the score</p>\n",
22250          "itemtype": "method",
22251          "name": "setBPM",
22252          "params": [{
22253            "name": "BPM",
22254            "description": "<p>Beats Per Minute</p>\n",
22255            "type": "Number"
22256          }, {
22257            "name": "rampTime",
22258            "description": "<p>Seconds from now</p>\n",
22259            "type": "Number"
22260          }],
22261          "class": "p5.Score",
22262          "module": "p5.sound",
22263          "submodule": "p5.sound"
22264        }, {
22265          "file": "lib/addons/p5.sound.js",
22266          "line": 10976,
22267          "description": "<p>musicalTimeMode uses <a href = \"https://github.com/Tonejs/Tone.js/wiki/Time\">Tone.Time</a> convention\ntrue if string, false if number</p>\n",
22268          "itemtype": "property",
22269          "name": "musicalTimeMode",
22270          "type": "Boolean",
22271          "class": "p5.SoundLoop",
22272          "module": "p5.sound",
22273          "submodule": "p5.sound"
22274        }, {
22275          "file": "lib/addons/p5.sound.js",
22276          "line": 10983,
22277          "description": "<p>musicalTimeMode variables\nmodify these only when the interval is specified in musicalTime format as a string</p>\n",
22278          "class": "p5.SoundLoop",
22279          "module": "p5.sound",
22280          "submodule": "p5.sound"
22281        }, {
22282          "file": "lib/addons/p5.sound.js",
22283          "line": 10990,
22284          "description": "<p>Set a limit to the number of loops to play. defaults to Infinity</p>\n",
22285          "itemtype": "property",
22286          "name": "maxIterations",
22287          "type": "Number",
22288          "class": "p5.SoundLoop",
22289          "module": "p5.sound",
22290          "submodule": "p5.sound"
22291        }, {
22292          "file": "lib/addons/p5.sound.js",
22293          "line": 10999,
22294          "description": "<p>Do not initiate the callback if timeFromNow is &lt; 0\nThis ususually occurs for a few milliseconds when the page\nis not fully loaded</p>\n<p>The callback should only be called until maxIterations is reached</p>\n",
22295          "class": "p5.SoundLoop",
22296          "module": "p5.sound",
22297          "submodule": "p5.sound"
22298        }, {
22299          "file": "lib/addons/p5.sound.js",
22300          "line": 11013,
22301          "description": "<p>Start the loop</p>\n",
22302          "itemtype": "method",
22303          "name": "start",
22304          "params": [{
22305            "name": "timeFromNow",
22306            "description": "<p>schedule a starting time</p>\n",
22307            "type": "Number",
22308            "optional": true
22309          }],
22310          "class": "p5.SoundLoop",
22311          "module": "p5.sound",
22312          "submodule": "p5.sound"
22313        }, {
22314          "file": "lib/addons/p5.sound.js",
22315          "line": 11026,
22316          "description": "<p>Stop the loop</p>\n",
22317          "itemtype": "method",
22318          "name": "stop",
22319          "params": [{
22320            "name": "timeFromNow",
22321            "description": "<p>schedule a stopping time</p>\n",
22322            "type": "Number",
22323            "optional": true
22324          }],
22325          "class": "p5.SoundLoop",
22326          "module": "p5.sound",
22327          "submodule": "p5.sound"
22328        }, {
22329          "file": "lib/addons/p5.sound.js",
22330          "line": 11039,
22331          "description": "<p>Pause the loop</p>\n",
22332          "itemtype": "method",
22333          "name": "pause",
22334          "params": [{
22335            "name": "timeFromNow",
22336            "description": "<p>schedule a pausing time</p>\n",
22337            "type": "Number",
22338            "optional": true
22339          }],
22340          "class": "p5.SoundLoop",
22341          "module": "p5.sound",
22342          "submodule": "p5.sound"
22343        }, {
22344          "file": "lib/addons/p5.sound.js",
22345          "line": 11052,
22346          "description": "<p>Synchronize loops. Use this method to start two more more loops in synchronization\nor to start a loop in synchronization with a loop that is already playing\nThis method will schedule the implicit loop in sync with the explicit master loop\ni.e. loopToStart.syncedStart(loopToSyncWith)</p>\n",
22347          "itemtype": "method",
22348          "name": "syncedStart",
22349          "params": [{
22350            "name": "otherLoop",
22351            "description": "<p>a p5.SoundLoop to sync with</p>\n",
22352            "type": "Object"
22353          }, {
22354            "name": "timeFromNow",
22355            "description": "<p>Start the loops in sync after timeFromNow seconds</p>\n",
22356            "type": "Number",
22357            "optional": true
22358          }],
22359          "class": "p5.SoundLoop",
22360          "module": "p5.sound",
22361          "submodule": "p5.sound"
22362        }, {
22363          "file": "lib/addons/p5.sound.js",
22364          "line": 11133,
22365          "description": "<p>Getters and Setters, setting any paramter will result in a change in the clock&#39;s\nfrequency, that will be reflected after the next callback\nbeats per minute (defaults to 60)</p>\n",
22366          "itemtype": "property",
22367          "name": "bpm",
22368          "type": "Number",
22369          "class": "p5.SoundLoop",
22370          "module": "p5.sound",
22371          "submodule": "p5.sound"
22372        }, {
22373          "file": "lib/addons/p5.sound.js",
22374          "line": 11151,
22375          "description": "<p>number of quarter notes in a measure (defaults to 4)</p>\n",
22376          "itemtype": "property",
22377          "name": "timeSignature",
22378          "type": "Number",
22379          "class": "p5.SoundLoop",
22380          "module": "p5.sound",
22381          "submodule": "p5.sound"
22382        }, {
22383          "file": "lib/addons/p5.sound.js",
22384          "line": 11167,
22385          "description": "<p>length of the loops interval</p>\n",
22386          "itemtype": "property",
22387          "name": "interval",
22388          "type": "Number|String",
22389          "class": "p5.SoundLoop",
22390          "module": "p5.sound",
22391          "submodule": "p5.sound"
22392        }, {
22393          "file": "lib/addons/p5.sound.js",
22394          "line": 11181,
22395          "description": "<p>how many times the callback has been called so far</p>\n",
22396          "itemtype": "property",
22397          "name": "iterations",
22398          "type": "Number",
22399          "readonly": "",
22400          "class": "p5.SoundLoop",
22401          "module": "p5.sound",
22402          "submodule": "p5.sound"
22403        }, {
22404          "file": "lib/addons/p5.sound.js",
22405          "line": 11222,
22406          "description": "<p>The p5.Compressor is built with a <a href=\"https://www.w3.org/TR/webaudio/#the-dynamicscompressornode-interface\" \n  target=\"_blank\" title=\"W3 spec for Dynamics Compressor Node\">
22406Web Audio Dynamics Compressor Node\n  </a></p>\n",
22407          "itemtype": "property",
22408          "name": "compressor",
22409          "type": "AudioNode",
22410          "class": "p5.Compressor",
22411          "module": "p5.sound",
22412          "submodule": "p5.sound"
22413        }, {
22414          "file": "lib/addons/p5.sound.js",
22415          "line": 11233,
22416          "description": "<p>Performs the same function as .connect, but also accepts\noptional parameters to set compressor&#39;s audioParams</p>\n",
22417          "itemtype": "method",
22418          "name": "process",
22419          "params": [{
22420            "name": "src",
22421            "description": "<p>Sound source to be connected</p>\n",
22422            "type": "Object"
22423          }, {
22424            "name": "attack",
22425            "description": "<p>The amount of time (in seconds) to reduce the gain by 10dB,\n                           default = .003, range 0 - 1</p>\n",
22426            "type": "Number",
22427            "optional": true
22428          }, {
22429            "name": "knee",
22430            "description": "<p>A decibel value representing the range above the \n                           threshold where the curve smoothly transitions to the &quot;ratio&quot; portion.\n                           default = 30, range 0 - 40</p>\n",
22431            "type": "Number",
22432            "optional": true
22433          }, {
22434            "name": "ratio",
22435            "description": "<p>The amount of dB change in input for a 1 dB change in output\n                           default = 12, range 1 - 20</p>\n",
22436            "type": "Number",
22437            "optional": true
22438          }, {
22439            "name": "threshold",
22440            "description": "<p>The decibel value above which the compression will start taking effect\n                           default = -24, range -100 - 0</p>\n",
22441            "type": "Number",
22442            "optional": true
22443          }, {
22444            "name": "release",
22445            "description": "<p>The amount of time (in seconds) to increase the gain by 10dB\n                           default = .25, range 0 - 1</p>\n",
22446            "type": "Number",
22447            "optional": true
22448          }],
22449          "class": "p5.Compressor",
22450          "module": "p5.sound",
22451          "submodule": "p5.sound"
22452        }, {
22453          "file": "lib/addons/p5.sound.js",
22454          "line": 11256,
22455          "description": "<p>Set the paramters of a compressor.</p>\n",
22456          "itemtype": "method",
22457          "name": "set",
22458          "params": [{
22459            "name": "attack",
22460            "description": "<p>The amount of time (in seconds) to reduce the gain by 10dB,\n                           default = .003, range 0 - 1</p>\n",
22461            "type": "Number"
22462          }, {
22463            "name": "knee",
22464            "description": "<p>A decibel value representing the range above the \n                           threshold where the curve smoothly transitions to the &quot;ratio&quot; portion.\n                           default = 30, range 0 - 40</p>\n",
22465            "type": "Number"
22466          }, {
22467            "name": "ratio",
22468            "description": "<p>The amount of dB change in input for a 1 dB change in output\n                           default = 12, range 1 - 20</p>\n",
22469            "type": "Number"
22470          }, {
22471            "name": "threshold",
22472            "description": "<p>The decibel value above which the compression will start taking effect\n                           default = -24, range -100 - 0</p>\n",
22473            "type": "Number"
22474          }, {
22475            "name": "release",
22476            "description": "<p>The amount of time (in seconds) to increase the gain by 10dB\n                           default = .25, range 0 - 1</p>\n",
22477            "type": "Number"
22478          }],
22479          "class": "p5.Compressor",
22480          "module": "p5.sound",
22481          "submodule": "p5.sound"
22482        }, {
22483          "file": "lib/addons/p5.sound.js",
22484          "line": 11288,
22485          "description": "<p>Get current attack or set value w/ time ramp</p>\n",
22486          "itemtype": "method",
22487          "name": "attack",
22488          "params": [{
22489            "name": "attack",
22490            "description": "<p>Attack is the amount of time (in seconds) to reduce the gain by 10dB,\n                         default = .003, range 0 - 1</p>\n",
22491            "type": "Number",
22492            "optional": true
22493          }, {
22494            "name": "time",
22495            "description": "<p>Assign time value to schedule the change in value</p>\n",
22496            "type": "Number",
22497            "optional": true
22498          }],
22499          "class": "p5.Compressor",
22500          "module": "p5.sound",
22501          "submodule": "p5.sound"
22502        }, {
22503          "file": "lib/addons/p5.sound.js",
22504          "line": 11308,
22505          "description": "<p>Get current knee or set value w/ time ramp</p>\n",
22506          "itemtype": "method",
22507          "name": "knee",
22508          "params": [{
22509            "name": "knee",
22510            "description": "<p>A decibel value representing the range above the \n                       threshold where the curve smoothly transitions to the &quot;ratio&quot; portion.\n                       default = 30, range 0 - 40</p>\n",
22511            "type": "Number",
22512            "optional": true
22513          }, {
22514            "name": "time",
22515            "description": "<p>Assign time value to schedule the change in value</p>\n",
22516            "type": "Number",
22517            "optional": true
22518          }],
22519          "class": "p5.Compressor",
22520          "module": "p5.sound",
22521          "submodule": "p5.sound"
22522        }, {
22523          "file": "lib/addons/p5.sound.js",
22524          "line": 11328,
22525          "description": "<p>Get current ratio or set value w/ time ramp</p>\n",
22526          "itemtype": "method",
22527          "name": "ratio",
22528          "params": [{
22529            "name": "ratio",
22530            "description": "<p>The amount of dB change in input for a 1 dB change in output\n                           default = 12, range 1 - 20</p>\n",
22531            "type": "Number",
22532            "optional": true
22533          }, {
22534            "name": "time",
22535            "description": "<p>Assign time value to schedule the change in value</p>\n",
22536            "type": "Number",
22537            "optional": true
22538          }],
22539          "class": "p5.Compressor",
22540          "module": "p5.sound",
22541          "submodule": "p5.sound"
22542        }, {
22543          "file": "lib/addons/p5.sound.js",
22544          "line": 11347,
22545          "description": "<p>Get current threshold or set value w/ time ramp</p>\n",
22546          "itemtype": "method",
22547          "name": "threshold",
22548          "params": [{
22549            "name": "threshold",
22550            "description": "<p>The decibel value above which the compression will start taking effect\n                           default = -24, range -100 - 0</p>\n",
22551            "type": "Number"
22552          }, {
22553            "name": "time",
22554            "description": "<p>Assign time value to schedule the change in value</p>\n",
22555            "type": "Number",
22556            "optional": true
22557          }],
22558          "class": "p5.Compressor",
22559          "module": "p5.sound",
22560          "submodule": "p5.sound"
22561        }, {
22562          "file": "lib/addons/p5.sound.js",
22563          "line": 11366,
22564          "description": "<p>Get current release or set value w/ time ramp</p>\n",
22565          "itemtype": "method",
22566          "name": "release",
22567          "params": [{
22568            "name": "release",
22569            "description": "<p>The amount of time (in seconds) to increase the gain by 10dB\n                           default = .25, range 0 - 1</p>\n",
22570            "type": "Number"
22571          }, {
22572            "name": "time",
22573            "description": "<p>Assign time value to schedule the change in value</p>\n",
22574            "type": "Number",
22575            "optional": true
22576          }],
22577          "class": "p5.Compressor",
22578          "module": "p5.sound",
22579          "submodule": "p5.sound"
22580        }, {
22581          "file": "lib/addons/p5.sound.js",
22582          "line": 11386,
22583          "description": "<p>Return the current reduction value</p>\n",
22584          "itemtype": "method",
22585          "name": "reduction",
22586          "return": {
22587            "description": "Value of the amount of gain reduction that is applied to the signal",
22588            "type": "Number"
22589          },
22590          "class": "p5.Compressor",
22591          "module": "p5.sound",
22592          "submodule": "p5.sound"
22593        }, {
22594          "file": "lib/addons/p5.sound.js",
22595          "line": 11502,
22596          "description": "<p>Connect a specific device to the p5.SoundRecorder.\nIf no parameter is given, p5.SoundRecorer will record\nall audible p5.sound from your sketch.</p>\n",
22597          "itemtype": "method",
22598          "name": "setInput",
22599          "params": [{
22600            "name": "unit",
22601            "description": "<p>p5.sound object or a web audio unit\n                       that outputs sound</p>\n",
22602            "type": "Object",
22603            "optional": true
22604          }],
22605          "class": "p5.SoundRecorder",
22606          "module": "p5.sound",
22607          "submodule": "p5.sound"
22608        }, {
22609          "file": "lib/addons/p5.sound.js",
22610          "line": 11523,
22611          "description": "<p>Start recording. To access the recording, provide\na p5.SoundFile as the first parameter. The p5.SoundRecorder\nwill send its recording to that p5.SoundFile for playback once\nrecording is complete. Optional parameters include duration\n(in seconds) of the recording, and a callback function that\nwill be called once the complete recording has been\ntransfered to the p5.SoundFile.</p>\n",
22612          "itemtype": "method",
22613          "name": "record",
22614          "params": [{
22615            "name": "soundFile",
22616            "description": "<p>p5.SoundFile</p>\n",
22617            "type": "p5.SoundFile"
22618          }, {
22619            "name": "duration",
22620            "description": "<p>Time (in seconds)</p>\n",
22621            "type": "Number",
22622            "optional": true
22623          }, {
22624            "name": "callback",
22625            "description": "<p>The name of a function that will be\n                              called once the recording completes</p>\n",
22626            "type": "Function",
22627            "optional": true
22628          }],
22629          "class": "p5.SoundRecorder",
22630          "module": "p5.sound",
22631          "submodule": "p5.sound"
22632        }, {
22633          "file": "lib/addons/p5.sound.js",
22634          "line": 11556,
22635          "description": "<p>Stop the recording. Once the recording is stopped,\nthe results will be sent to the p5.SoundFile that\nwas given on .record(), and if a callback function\nwas provided on record, that function will be called.</p>\n",
22636          "itemtype": "method",
22637          "name": "stop",
22638          "class": "p5.SoundRecorder",
22639          "module": "p5.sound",
22640          "submodule": "p5.sound"
22641        }, {
22642          "file": "lib/addons/p5.sound.js",
22643          "line": 11629,
22644          "description": "<p>Save a p5.SoundFile as a .wav file. The browser will prompt the user\nto download the file to their device.\nFor uploading audio to a server, use\n<a href=\"/docs/reference/#/p5.SoundFile/saveBlob\"><code>p5.SoundFile.saveBlob</code></a>.</p>\n",
22645          "itemtype": "method",
22646          "name": "saveSound",
22647          "params": [{
22648            "name": "soundFile",
22649            "description": "<p>
22649p5.SoundFile that you wish to save</p>\n",
22650            "type": "p5.SoundFile"
22651          }, {
22652            "name": "fileName",
22653            "description": "<p>name of the resulting .wav file.</p>\n",
22654            "type": "String"
22655          }],
22656          "class": "p5",
22657          "module": "p5.sound",
22658          "submodule": "p5.sound"
22659        }, {
22660          "file": "lib/addons/p5.sound.js",
22661          "line": 11755,
22662          "description": "<p>isDetected is set to true when a peak is detected.</p>\n",
22663          "itemtype": "attribute",
22664          "name": "isDetected",
22665          "type": "Boolean",
22666          "default": "false",
22667          "class": "p5.PeakDetect",
22668          "module": "p5.sound",
22669          "submodule": "p5.sound"
22670        }, {
22671          "file": "lib/addons/p5.sound.js",
22672          "line": 11768,
22673          "description": "<p>The update method is run in the draw loop.</p>\n<p>Accepts an FFT object. You must call .analyze()\non the FFT object prior to updating the peakDetect\nbecause it relies on a completed FFT analysis.</p>\n",
22674          "itemtype": "method",
22675          "name": "update",
22676          "params": [{
22677            "name": "fftObject",
22678            "description": "<p>A p5.FFT object</p>\n",
22679            "type": "p5.FFT"
22680          }],
22681          "class": "p5.PeakDetect",
22682          "module": "p5.sound",
22683          "submodule": "p5.sound"
22684        }, {
22685          "file": "lib/addons/p5.sound.js",
22686          "line": 11799,
22687          "description": "<p>onPeak accepts two arguments: a function to call when\na peak is detected. The value of the peak,\nbetween 0.0 and 1.0, is passed to the callback.</p>\n",
22688          "itemtype": "method",
22689          "name": "onPeak",
22690          "params": [{
22691            "name": "callback",
22692            "description": "<p>Name of a function that will\n                            be called when a peak is\n                            detected.</p>\n",
22693            "type": "Function"
22694          }, {
22695            "name": "val",
22696            "description": "<p>Optional value to pass\n                            into the function when\n                            a peak is detected.</p>\n",
22697            "type": "Object",
22698            "optional": true
22699          }],
22700          "example": ["\n<div><code>\nvar cnv, soundFile, fft, peakDetect;\nvar ellipseWidth = 0;\n\nfunction preload() {\n  soundFile = loadSound('assets/beat.mp3');\n}\n\nfunction setup() {\n  cnv = createCanvas(100,100);\n  textAlign(CENTER);\n\n  fft = new p5.FFT();\n  peakDetect = new p5.PeakDetect();\n\n  setupSound();\n\n  // when a beat is detected, call triggerBeat()\n  peakDetect.onPeak(triggerBeat);\n}\n\nfunction draw() {\n  background(0);\n  fill(255);\n  text('click to play', width/2, height/2);\n\n  fft.analyze();\n  peakDetect.update(fft);\n\n  ellipseWidth *= 0.95;\n  ellipse(width/2, height/2, ellipseWidth, ellipseWidth);\n}\n\n// this function is called by peakDetect.onPeak\nfunction triggerBeat() {\n  ellipseWidth = 50;\n}\n\n// mouseclick starts/stops sound\nfunction setupSound() {\n  cnv.mouseClicked( function() {\n    if (soundFile.isPlaying() ) {\n      soundFile.stop();\n    } else {\n      soundFile.play();\n    }\n  });\n}\n</code></div>"],
22701          "class": "p5.PeakDetect",
22702          "module": "p5.sound",
22703          "submodule": "p5.sound"
22704        }, {
22705          "file": "lib/addons/p5.sound.js",
22706          "line": 11948,
22707          "description": "<p>Connect a source to the gain node.</p>\n",
22708          "itemtype": "method",
22709          "name": "setInput",
22710          "params": [{
22711            "name": "src",
22712            "description": "<p>p5.sound / Web Audio object with a sound\n                         output.</p>\n",
22713            "type": "Object"
22714          }],
22715          "class": "p5.Gain",
22716          "module": "p5.sound",
22717          "submodule": "p5.sound"
22718        }, {
22719          "file": "lib/addons/p5.sound.js",
22720          "line": 11958,
22721          "description": "<p>Send output to a p5.sound or web audio object</p>\n",
22722          "itemtype": "method",
22723          "name": "connect",
22724          "params": [{
22725            "name": "unit",
22726            "description": "",
22727            "type": "Object"
22728          }],
22729          "class": "p5.Gain",
22730          "module": "p5.sound",
22731          "submodule": "p5.sound"
22732        }, {
22733          "file": "lib/addons/p5.sound.js",
22734          "line": 11968,
22735          "description": "<p>Disconnect all output.</p>\n",
22736          "itemtype": "method",
22737          "name": "disconnect",
22738          "class": "p5.Gain",
22739          "module": "p5.sound",
22740          "submodule": "p5.sound"
22741        }, {
22742          "file": "lib/addons/p5.sound.js",
22743          "line": 11978,
22744          "description": "<p>Set the output level of the gain node.</p>\n",
22745          "itemtype": "method",
22746          "name": "amp",
22747          "params": [{
22748            "name": "volume",
22749            "description": "<p>amplitude between 0 and 1.0</p>\n",
22750            "type": "Number"
22751          }, {
22752            "name": "rampTime",
22753            "description": "<p>create a fade that lasts rampTime</p>\n",
22754            "type": "Number",
22755            "optional": true
22756          }, {
22757            "name": "timeFromNow",
22758            "description": "<p>schedule this event to happen\n                              seconds from now</p>\n",
22759            "type": "Number",
22760            "optional": true
22761          }],
22762          "class": "p5.Gain",
22763          "module": "p5.sound",
22764          "submodule": "p5.sound"
22765        }, {
22766          "file": "lib/addons/p5.sound.js",
22767          "line": 12036,
22768          "description": "<p>Connect to p5 objects or Web Audio Nodes</p>\n",
22769          "itemtype": "method",
22770          "name": "connect",
22771          "params": [{
22772            "name": "unit",
22773            "description": "",
22774            "type": "Object"
22775          }],
22776          "class": "p5.AudioVoice",
22777          "module": "p5.sound",
22778          "submodule": "p5.sound"
22779        }, {
22780          "file": "lib/addons/p5.sound.js",
22781          "line": 12045,
22782          "description": "<p>Disconnect from soundOut</p>\n",
22783          "itemtype": "method",
22784          "name": "disconnect",
22785          "class": "p5.AudioVoice",
22786          "module": "p5.sound",
22787          "submodule": "p5.sound"
22788        }, {
22789          "file": "lib/addons/p5.sound.js",
22790          "line": 12125,
22791          "description": "<p>Play tells the MonoSynth to start playing a note. This method schedules\nthe calling of .triggerAttack and .triggerRelease.</p>\n",
22792          "itemtype": "method",
22793          "name": "play",
22794          "params": [{
22795            "name": "note",
22796            "description": "<p>the note you want to play, specified as a\n                               frequency in Hertz (Number) or as a midi\n                               value in Note/Octave format (&quot;C4&quot;, &quot;Eb3&quot;...etc&quot;)\n                               See <a href = \"https://github.com/Tonejs/Tone.js/wiki/Instruments\">\n                               Tone</a>. Defaults to 440 hz.</p>\n",
22797            "type": "String | Number"
22798          }, {
22799            "name": "velocity",
22800            "description": "<p>velocity of the note to play (ranging from 0 to 1)</p>\n",
22801            "type": "Number",
22802            "optional": true
22803          }, {
22804            "name": "secondsFromNow",
22805            "description": "<p>time from now (in seconds) at which to play</p>\n",
22806            "type": "Number",
22807            "optional": true
22808          }, {
22809            "name": "sustainTime",
22810            "description": "<p>time to sustain before releasing the envelope</p>\n",
22811            "type": "Number",
22812            "optional": true
22813          }],
22814          "example": ["\n<div><code>\nvar monoSynth;\n\nfunction setup() {\n  var cnv = createCanvas(100, 100);\n  cnv.mousePressed(playSynth);\n\n  monoSynth = new p5.MonoSynth();\n\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n}\n\nfunction playSynth() {\n  // time from now (in seconds)\n  var time = 0;\n  // note duration (in seconds)\n  var dur = 1/6;\n  // note velocity (volume, from 0 to 1)\n  var v = random();\n\n  monoSynth.play(\"Fb3\", v, 0, dur);\n  monoSynth.play(\"Gb3\", v, time += dur, dur);\n\n  background(random(255), random(255), 255);\n  text('click to play', width/2, height/2);\n}\n</code></div>\n"],
22815          "class": "p5.MonoSynth",
22816          "module": "p5.sound",
22817          "submodule": "p5.sound"
22818        }, {
22819          "file": "lib/addons/p5.sound.js",
22820          "line": 12173,
22821          "description": "<p>Trigger the Attack, and Decay portion of the Envelope.\nSimilar to holding down a key on a piano, but it will\nhold the sustain level until you let go.</p>\n",
22822          "params": [{
22823            "name": "note",
22824            "description": "<p>the note you want to play, specified as a\n                               frequency in Hertz (Number) or as a midi\n                               value in Note/Octave format (&quot;C4&quot;, &quot;Eb3&quot;...etc&quot;)\n                               See <a href = \"https://github.com/Tonejs/Tone.js/wiki/Instruments\">\n                               Tone</a>. Defaults to 440 hz</p>\n",
22825            "type": "String | Number"
22826          }, {
22827            "name": "velocity",
22828            "description": "<p>velocity of the note to play (ranging from 0 to 1)</p>\n",
22829            "type": "Number",
22830            "optional": true
22831          }, {
22832            "name": "secondsFromNow",
22833            "description": "<p>time from now (in seconds) at which to play</p>\n",
22834            "type": "Number",
22835            "optional": true
22836          }],
22837          "itemtype": "method",
22838          "name": "triggerAttack",
22839          "example": ["\n<div><code>\nvar monoSynth = new p5.MonoSynth();\n\nfunction mousePressed() {\n  monoSynth.triggerAttack(\"E3\");\n}\n\nfunction mouseReleased() {\n  monoSynth.triggerRelease();\n}\n</code></div>"],
22840          "class": "p5.MonoSynth",
22841          "module": "p5.sound",
22842          "submodule": "p5.sound"
22843        }, {
22844          "file": "lib/addons/p5.sound.js",
22845          "line": 12206,
22846          "description": "<p>Trigger the release of the Envelope. This is similar to releasing\nthe key on a piano and letting the sound fade according to the\nrelease level and release time.</p>\n",
22847          "params": [{
22848            "name": "secondsFromNow",
22849            "description": "<p>time to trigger the release</p>\n",
22850            "type": "Number"
22851          }],
22852          "itemtype": "method",
22853          "name": "triggerRelease",
22854          "example": ["\n<div><code>\nvar monoSynth = new p5.MonoSynth();\n\nfunction mousePressed() {\n  monoSynth.triggerAttack(\"E3\");\n}\n\nfunction mouseReleased() {\n  monoSynth.triggerRelease();\n}\n</code></div>"],
22855          "class": "p5.MonoSynth",
22856          "module": "p5.sound",
22857          "submodule": "p5.sound"
22858        }, {
22859          "file": "lib/addons/p5.sound.js",
22860          "line": 12230,
22861          "description": "<p>Set values like a traditional\n<a href=\"https://en.wikipedia.org/wiki/Synthesizer#/media/File:ADSR_parameter.svg\">\nADSR envelope\n</a>.</p>\n",
22862          "itemtype": "method",
22863          "name": "setADSR",
22864          "params": [{
22865            "name": "attackTime",
22866            "description": "<p>Time (in seconds before envelope\n                              reaches Attack Level</p>\n",
22867            "type": "Number"
22868          }, {
22869            "name": "decayTime",
22870            "description": "<p>Time (in seconds) before envelope\n                              reaches Decay/Sustain Level</p>\n",
22871            "type": "Number",
22872            "optional": true
22873          }, {
22874            "name": "susRatio",
22875            "description": "<p>Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n                              where 1.0 = attackLevel, 0.0 = releaseLevel.\n                              The susRatio determines the decayLevel and the level at which the\n                              sustain portion of the envelope will sustain.\n                              For example, if attackLevel is 0.4, releaseLevel is 0,\n                              and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n                              increased to 1.0 (using <code>setRange</code>),\n                              then decayLevel would increase proportionally, to become 0.5.</p>\n",
22876            "type": "Number",
22877            "optional": true
22878          }, {
22879            "name": "releaseTime",
22880            "description": "<p>Time in seconds from now (defaults to 0)</p>\n",
22881            "type": "Number",
22882            "optional": true
22883          }],
22884          "class": "p5.MonoSynth",
22885          "module": "p5.sound",
22886          "submodule": "p5.sound"
22887        }, {
22888          "file": "lib/addons/p5.sound.js",
22889          "line": 12254,
22890          "description": "<p>Getters and Setters</p>\n",
22891          "itemtype": "property",
22892          "name": "attack",
22893          "type": "Number",
22894          "class": "p5.MonoSynth",
22895          "module": "p5.sound",
22896          "submodule": "p5.sound"
22897        }, {
22898          "file": "lib/addons/p5.sound.js",
22899          "line": 12258,
22900          "itemtype": "property",
22901          "name": "decay",
22902          "type": "Number",
22903          "class": "p5.MonoSynth",
22904          "module": "p5.sound",
22905          "submodule": "p5.sound"
22906        }, {
22907          "file": "lib/addons/p5.sound.js",
22908          "line": 12261,
22909          "itemtype": "property",
22910          "name": "sustain",
22911          "type": "Number",
22912          "class": "p5.MonoSynth",
22913          "module": "p5.sound",
22914          "submodule": "p5.sound"
22915        }, {
22916          "file": "lib/addons/p5.sound.js",
22917          "line": 12264,
22918          "itemtype": "property",
22919          "name": "release",
22920          "type": "Number",
22921          "class": "p5.MonoSynth",
22922          "module": "p5.sound",
22923          "submodule": "p5.sound"
22924        }, {
22925          "file": "lib/addons/p5.sound.js",
22926          "line": 12301,
22927          "description": "<p>MonoSynth amp</p>\n",
22928          "itemtype": "method",
22929          "name": "amp",
22930          "params": [{
22931            "name": "vol",
22932            "description": "<p>desired volume</p>\n",
22933            "type": "Number"
22934          }, {
22935            "name": "rampTime",
22936            "description": "<p>Time to reach new volume</p>\n",
22937            "type": "Number",
22938            "optional": true
22939          }],
22940          "return": {
22941            "description": "new volume value",
22942            "type": "Number"
22943          },
22944          "class": "p5.MonoSynth",
22945          "module": "p5.sound",
22946          "submodule": "p5.sound"
22947        }, {
22948          "file": "lib/addons/p5.sound.js",
22949          "line": 12315,
22950          "description": "<p>Connect to a p5.sound / Web Audio object.</p>\n",
22951          "itemtype": "method",
22952          "name": "connect",
22953          "params": [{
22954            "name": "unit",
22955            "description": "<p>A p5.sound or Web Audio object</p>\n",
22956            "type": "Object"
22957          }],
22958          "class": "p5.MonoSynth",
22959          "module": "p5.sound",
22960          "submodule": "p5.sound"
22961        }, {
22962          "file": "lib/addons/p5.sound.js",
22963          "line": 12325,
22964          "description": "<p>Disconnect all outputs</p>\n",
22965          "itemtype": "method",
22966          "name": "disconnect",
22967          "class": "p5.MonoSynth",
22968          "module": "p5.sound",
22969          "submodule": "p5.sound"
22970        }, {
22971          "file": "lib/addons/p5.sound.js",
22972          "line": 12335,
22973          "description": "<p>Get rid of the MonoSynth and free up its resources / memory.</p>\n",
22974          "itemtype": "method",
22975          "name": "dispose",
22976          "class": "p5.MonoSynth",
22977          "module": "p5.sound",
22978          "submodule": "p5.sound"
22979        }, {
22980          "file": "lib/addons/p5.sound.js",
22981          "line": 12405,
22982          "description": "<p>An object that holds information about which notes have been played and\nwhich notes are currently being played. New notes are added as keys\non the fly. While a note has been attacked, but not released, the value of the\nkey is the audiovoice which is generating that note. When notes are released,\nthe value of the key becomes undefined.</p>\n",
22983          "itemtype": "property",
22984          "name": "notes",
22985          "class": "p5.PolySynth",
22986          "module": "p5.sound",
22987          "submodule": "p5.sound"
22988        }, {
22989          "file": "lib/addons/p5.sound.js",
22990          "line": 
2299012417,
22991          "description": "<p>A PolySynth must have at least 1 voice, defaults to 8</p>\n",
22992          "itemtype": "property",
22993          "name": "polyvalue",
22994          "class": "p5.PolySynth",
22995          "module": "p5.sound",
22996          "submodule": "p5.sound"
22997        }, {
22998          "file": "lib/addons/p5.sound.js",
22999          "line": 12422,
23000          "description": "<p>Monosynth that generates the sound for each note that is triggered. The\np5.PolySynth defaults to using the p5.MonoSynth as its voice.</p>\n",
23001          "itemtype": "property",
23002          "name": "AudioVoice",
23003          "class": "p5.PolySynth",
23004          "module": "p5.sound",
23005          "submodule": "p5.sound"
23006        }, {
23007          "file": "lib/addons/p5.sound.js",
23008          "line": 12453,
23009          "description": "<p>Play a note by triggering noteAttack and noteRelease with sustain time</p>\n",
23010          "itemtype": "method",
23011          "name": "play",
23012          "params": [{
23013            "name": "note",
23014            "description": "<p>midi note to play (ranging from 0 to 127 - 60 being a middle C)</p>\n",
23015            "type": "Number",
23016            "optional": true
23017          }, {
23018            "name": "velocity",
23019            "description": "<p>velocity of the note to play (ranging from 0 to 1)</p>\n",
23020            "type": "Number",
23021            "optional": true
23022          }, {
23023            "name": "secondsFromNow",
23024            "description": "<p>time from now (in seconds) at which to play</p>\n",
23025            "type": "Number",
23026            "optional": true
23027          }, {
23028            "name": "sustainTime",
23029            "description": "<p>time to sustain before releasing the envelope</p>\n",
23030            "type": "Number",
23031            "optional": true
23032          }],
23033          "example": ["\n<div><code>\nvar polySynth;\n\nfunction setup() {\n  var cnv = createCanvas(100, 100);\n  cnv.mousePressed(playSynth);\n\n  polySynth = new p5.PolySynth();\n\n  textAlign(CENTER);\n  text('click to play', width/2, height/2);\n}\n\nfunction playSynth() {\n  // note duration (in seconds)\n  var dur = 0.1;\n\n  // time from now (in seconds)\n  var time = 0;\n\n  // velocity (volume, from 0 to 1)\n  var vel = 0.1;\n\n  polySynth.play(\"G2\", vel, 0, dur);\n  polySynth.play(\"C3\", vel, 0, dur);\n  polySynth.play(\"G3\", vel, 0, dur);\n\n  background(random(255), random(255), 255);\n  text('click to play', width/2, height/2);\n}\n</code></div>"],
23034          "class": "p5.PolySynth",
23035          "module": "p5.sound",
23036          "submodule": "p5.sound"
23037        }, {
23038          "file": "lib/addons/p5.sound.js",
23039          "line": 12499,
23040          "description": "<p>noteADSR sets the envelope for a specific note that has just been triggered.\nUsing this method modifies the envelope of whichever audiovoice is being used\nto play the desired note. The envelope should be reset before noteRelease is called\nin order to prevent the modified envelope from being used on other notes.</p>\n",
23041          "itemtype": "method",
23042          "name": "noteADSR",
23043          "params": [{
23044            "name": "note",
23045            "description": "<p>Midi note on which ADSR should be set.</p>\n",
23046            "type": "Number",
23047            "optional": true
23048          }, {
23049            "name": "attackTime",
23050            "description": "<p>Time (in seconds before envelope\n                              reaches Attack Level</p>\n",
23051            "type": "Number",
23052            "optional": true
23053          }, {
23054            "name": "decayTime",
23055            "description": "<p>Time (in seconds) before envelope\n                              reaches Decay/Sustain Level</p>\n",
23056            "type": "Number",
23057            "optional": true
23058          }, {
23059            "name": "susRatio",
23060            "description": "<p>Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n                              where 1.0 = attackLevel, 0.0 = releaseLevel.\n                              The susRatio determines the decayLevel and the level at which the\n                              sustain portion of the envelope will sustain.\n                              For example, if attackLevel is 0.4, releaseLevel is 0,\n                              and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n                              increased to 1.0 (using <code>setRange</code>),\n                              then decayLevel would increase proportionally, to become 0.5.</p>\n",
23061            "type": "Number",
23062            "optional": true
23063          }, {
23064            "name": "releaseTime",
23065            "description": "<p>Time in seconds from now (defaults to 0)</p>\n",
23066            "type": "Number",
23067            "optional": true
23068          }],
23069          "class": "p5.PolySynth",
23070          "module": "p5.sound",
23071          "submodule": "p5.sound"
23072        }, {
23073          "file": "lib/addons/p5.sound.js",
23074          "line": 12527,
23075          "description": "<p>Set the PolySynths global envelope. This method modifies the envelopes of each\nmonosynth so that all notes are played with this envelope.</p>\n",
23076          "itemtype": "method",
23077          "name": "setADSR",
23078          "params": [{
23079            "name": "attackTime",
23080            "description": "<p>Time (in seconds before envelope\n                               reaches Attack Level</p>\n",
23081            "type": "Number",
23082            "optional": true
23083          }, {
23084            "name": "decayTime",
23085            "description": "<p>Time (in seconds) before envelope\n                               reaches Decay/Sustain Level</p>\n",
23086            "type": "Number",
23087            "optional": true
23088          }, {
23089            "name": "susRatio",
23090            "description": "<p>Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,\n                               where 1.0 = attackLevel, 0.0 = releaseLevel.\n                               The susRatio determines the decayLevel and the level at which the\n                               sustain portion of the envelope will sustain.\n                               For example, if attackLevel is 0.4, releaseLevel is 0,\n                               and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is\n                               increased to 1.0 (using <code>setRange</code>),\n                               then decayLevel would increase proportionally, to become 0.5.</p>\n",
23091            "type": "Number",
23092            "optional": true
23093          }, {
23094            "name": "releaseTime",
23095            "description": "<p>Time in seconds from now (defaults to 0)</p>\n",
23096            "type": "Number",
23097            "optional": true
23098          }],
23099          "class": "p5.PolySynth",
23100          "module": "p5.sound",
23101          "submodule": "p5.sound"
23102        }, {
23103          "file": "lib/addons/p5.sound.js",
23104          "line": 12551,
23105          "description": "<p>Trigger the Attack, and Decay portion of a MonoSynth.\nSimilar to holding down a key on a piano, but it will\nhold the sustain level until you let go.</p>\n",
23106          "itemtype": "method",
23107          "name": "noteAttack",
23108          "params": [{
23109            "name": "note",
23110            "description": "<p>midi note on which attack should be triggered.</p>\n",
23111            "type": "Number",
23112            "optional": true
23113          }, {
23114            "name": "velocity",
23115            "description": "<p>velocity of the note to play (ranging from 0 to 1)/</p>\n",
23116            "type": "Number",
23117            "optional": true
23118          }, {
23119            "name": "secondsFromNow",
23120            "description": "<p>time from now (in seconds)</p>\n",
23121            "type": "Number",
23122            "optional": true
23123          }],
23124          "example": ["\n<div><code>\nvar polySynth = new p5.PolySynth();\nvar pitches = [\"G\", \"D\", \"G\", \"C\"];\nvar octaves = [2, 3, 4];\n\nfunction mousePressed() {\n  // play a chord: multiple notes at the same time\n  for (var i = 0; i < 4;
23124 i++) {\n    var note = random(pitches) + random(octaves);\n    polySynth.noteAttack(note, 0.1);\n  }\n}\n\nfunction mouseReleased() {\n  // release all voices\n  polySynth.noteRelease();\n}\n</code></div>"],
23125          "class": "p5.PolySynth",
23126          "module": "p5.sound",
23127          "submodule": "p5.sound"
23128        }, {
23129          "file": "lib/addons/p5.sound.js",
23130          "line": 12641,
23131          "description": "<p>Trigger the Release of an AudioVoice note. This is similar to releasing\nthe key on a piano and letting the sound fade according to the\nrelease level and release time.</p>\n",
23132          "itemtype": "method",
23133          "name": "noteRelease",
23134          "params": [{
23135            "name": "note",
23136            "description": "<p>midi note on which attack should be triggered.\n                                  If no value is provided, all notes will be released.</p>\n",
23137            "type": "Number",
23138            "optional": true
23139          }, {
23140            "name": "secondsFromNow",
23141            "description": "<p>time to trigger the release</p>\n",
23142            "type": "Number",
23143            "optional": true
23144          }],
23145          "example": ["\n<div><code>\nvar pitches = [\"G\", \"D\", \"G\", \"C\"];\nvar octaves = [2, 3, 4];\nvar polySynth = new p5.PolySynth();\n\nfunction mousePressed() {\n  // play a chord: multiple notes at the same time\n  for (var i = 0; i < 4; i++) {\n    var note = random(pitches) + random(octaves);\n    polySynth.noteAttack(note, 0.1);\n  }\n}\n\nfunction mouseReleased() {\n  // release all voices\n  polySynth.noteRelease();\n}\n</code></div>\n"],
23146          "class": "p5.PolySynth",
23147          "module": "p5.sound",
23148          "submodule": "p5.sound"
23149        }, {
23150          "file": "lib/addons/p5.sound.js",
23151          "line": 12706,
23152          "description": "<p>Connect to a p5.sound / Web Audio object.</p>\n",
23153          "itemtype": "method",
23154          "name": "connect",
23155          "params": [{
23156            "name": "unit",
23157            "description": "<p>A p5.sound or Web Audio object</p>\n",
23158            "type": "Object"
23159          }],
23160          "class": "p5.PolySynth",
23161          "module": "p5.sound",
23162          "submodule": "p5.sound"
23163        }, {
23164          "file": "lib/addons/p5.sound.js",
23165          "line": 12716,
23166          "description": "<p>Disconnect all outputs</p>\n",
23167          "itemtype": "method",
23168          "name": "disconnect",
23169          "class": "p5.PolySynth",
23170          "module": "p5.sound",
23171          "submodule": "p5.sound"
23172        }, {
23173          "file": "lib/addons/p5.sound.js",
23174          "line": 12726,
23175          "description": "<p>Get rid of the MonoSynth and free up its resources / memory.</p>\n",
23176          "itemtype": "method",
23177          "name": "dispose",
23178          "class": "p5.PolySynth",
23179          "module": "p5.sound",
23180          "submodule": "p5.sound"
23181        }, {
23182          "file": "lib/addons/p5.sound.js",
23183          "line": 12794,
23184          "description": "<p>The p5.Distortion is built with a\n<a href=\"http://www.w3.org/TR/webaudio/#WaveShaperNode\">\nWeb Audio WaveShaper Node</a>.</p>\n",
23185          "itemtype": "property",
23186          "name": "WaveShaperNode",
23187          "type": "AudioNode",
23188          "class": "p5.Distortion",
23189          "module": "p5.sound",
23190          "submodule": "p5.sound"
23191        }, {
23192          "file": "lib/addons/p5.sound.js",
23193          "line": 12809,
23194          "description": "<p>Process a sound source, optionally specify amount and oversample values.</p>\n",
23195          "itemtype": "method",
23196          "name": "process",
23197          "params": [{
23198            "name": "amount",
23199            "description": "<p>Unbounded distortion amount.\n                               Normal values range from 0-1.</p>\n",
23200            "type": "Number",
23201            "optional": true,
23202            "optdefault": "0.25"
23203          }, {
23204            "name": "oversample",
23205            "description": "<p>&#39;none&#39;, &#39;2x&#39;, or &#39;4x&#39;.</p>\n",
23206            "type": "String",
23207            "optional": true,
23208            "optdefault": "'none'"
23209          }],
23210          "class": "p5.Distortion",
23211          "module": "p5.sound",
23212          "submodule": "p5.sound"
23213        }, {
23214          "file": "lib/addons/p5.sound.js",
23215          "line": 12821,
23216          "description": "<p>Set the amount and oversample of the waveshaper distortion.</p>\n",
23217          "itemtype": "method",
23218          "name": "set",
23219          "params": [{
23220            "name": "amount",
23221            "description": "<p>Unbounded distortion amount.\n                               Normal values range from 0-1.</p>\n",
23222            "type": "Number",
23223            "optional": true,
23224            "optdefault": "0.25"
23225          }, {
23226            "name": "oversample",
23227            "description": "<p>&#39;none&#39;, &#39;2x&#39;, or &#39;4x&#39;.</p>\n",
23228            "type": "String",
23229            "optional": true,
23230            "optdefault": "'none'"
23231          }],
23232          "class": "p5.Distortion",
23233          "module": "p5.sound",
23234          "submodule": "p5.sound"
23235        }, {
23236          "file": "lib/addons/p5.sound.js",
23237          "line": 12839,
23238          "description": "<p>Return the distortion amount, typically between 0-1.</p>\n",
23239          "itemtype": "method",
23240          "name": "getAmount",
23241          "return": {
23242            "description": "Unbounded distortion amount.\n                 Normal values range from 0-1.",
23243            "type": "Number"
23244          },
23245          "class": "p5.Distortion",
23246          "module": "p5.sound",
23247          "submodule": "p5.sound"
23248        }, {
23249          "file": "lib/addons/p5.sound.js",
23250          "line": 12849,
23251          "description": "<p>Return the oversampling.</p>\n",
23252          "itemtype": "method",
23253          "name": "getOversample",
23254          "return": {
23255            "description": "Oversample can either be 'none', '2x', or '4x'.",
23256            "type": "String"
23257          },
23258          "class": "p5.Distortion",
23259          "module": "p5.sound",
23260          "submodule": "p5.sound"
23261        }],
23262        "warnings": [{
23263          "message": "unknown tag: alt",
23264          "line": " src/color/creating_reading.js:16"
23265        }, {
23266          "message": "unknown tag: alt",
23267          "line": " src/color/creating_reading.js:61"
23268        }, {
23269          "message": "unknown tag: alt",
23270          "line": " src/color/creating_reading.js:91"
23271        }, {
23272          "message": "unknown tag: alt",
23273          "line": " src/color/creating_reading.js:121"
23274        }, {
23275          "message": "unknown tag: alt",
23276          "line": " src/color/creating_reading.js:319"
23277        }, {
23278          "message": "unknown tag: alt",
23279          "line": " src/color/creating_reading.js:350"
23280        }, {
23281          "message": "unknown tag: alt",
23282          "line": " src/color/creating_reading.js:387"
23283        }, {
23284          "message": "unknown tag: alt",
23285          "line": " src/color/creating_reading.js:484"
23286        }, {
23287          "message": "unknown tag: alt",
23288          "line": " src/color/creating_reading.js:514"
23289        }, {
23290          "message": "unknown tag: alt",
23291          "line": " src/color/creating_reading.js:554"
23292        }, {
23293          "message": "unknown tag: alt",
23294          "line": " src/color/p5.Color.js:52"
23295        }, {
23296          "message": "unknown tag: alt",
23297          "line": " src/color/p5.Color.js:248"
23298        }, {
23299          "message": "unknown tag: alt",
23300          "line": " src/color/p5.Color.js:275"
23301        }, {
23302          "message": "unknown tag: alt",
23303          "line": " src/color/p5.Color.js:302"
23304        }, {
23305          "message": "unknown tag: alt",
23306          "line": " src/color/p5.Color.js:329"
23307        }, {
23308          "message": "unknown tag: alt",
23309          "line": " src/color/p5.Color.js:763"
23310        }, {
23311          "message": "unknown tag: alt",
23312          "line": " src/color/setting.js:15"
23313        }, {
23314          "message": "unknown tag: alt",
23315          "line": " src/color/setting.js:185"
23316        }, {
23317          "message": "unknown tag: alt",
23318          "line": " src/color/setting.js:223"
23319        }, {
23320          "message": "unknown tag: alt",
23321          "line": " src/color/setting.js:344"
23322        }, {
23323          "message": "unknown tag: alt",
23324          "line": " src/color/setting.js:501"
23325        }, {
23326          "message": "unknown tag: alt",
23327          "line": " src/color/setting.js:542"
23328        }, {
23329          "message": "unknown tag: alt",
23330          "line": " src/color/setting.js:582"
23331        }, {
23332          "message": "unknown tag: alt",
23333          "line": " src/core/shape/2d_primitives.js:16"
23334        }, {
23335          "message": "unknown tag: alt",
23336          "line": " src/core/shape/2d_primitives.js:149"
23337        }, {
23338          "message": "unknown tag: alt",
23339          "line": " src/core/shape/2d_primitives.js:209"
23340        }, {
23341          "message": "unknown tag: alt",
23342          "line": " src/core/shape/2d_primitives.js:239"
23343        }, {
23344          "message": "unknown tag: alt",
23345          "line": " src/core/shape/2d_primitives.js:295"
23346        }, {
23347          "message": "unknown tag: alt",
23348          "line": " src/core/shape/2d_primitives.js:330"
23349        }, {
23350          "message": "unknown tag: alt",
23351          "line": " src/core/shape/2d_primitives.js:384"
23352        }, {
23353          "message": "unknown tag: alt",
23354          "line": " src/core/shape/2d_primitives.js:467"
23355        }, {
23356          "message": "unknown tag: alt",
23357          "line": " src/core/shape/2d_primitives.js:524"
23358        }, {
23359          "message": "unknown tag: alt",
23360          "line": " src/core/shape/attributes.js:14"
23361        }, {
23362          "message": "unknown tag: alt",
23363          "line": " src/core/shape/attributes.js:83"
23364        }, {
23365          "message": "unknown tag: alt",
23366          "line": " src/core/shape/attributes.js:113"
23367        }, {
23368          "message": "unknown tag: alt",
23369          "line": " src/core/shape/attributes.js:182"
23370        }, {
23371          "message": "unknown tag: alt",
23372          "line": " src/core/shape/attributes.js:213"
23373        }, {
23374          "message": "unknown tag: alt",
23375          "line": " src/core/shape/attributes.js:250"
23376        }, {
23377          "message": "unknown tag: alt",
23378          "line": " src/core/shape/attributes.js:317"
23379        }, {
23380          "message": "unknown tag: alt",
23381          "line": " src/core/shape/curves.js:13"
23382        }, {
23383          "message": "unknown tag: alt",
23384          "line": " src/core/shape/curves.js:96"
23385        }, {
23386          "message": "unknown tag: alt",
23387          "line": " src/core/shape/curves.js:139"
23388        }, {
23389          "message": "unknown tag: alt",
23390          "line": " src/core/shape/curves.js:194"
23391        }, {
23392          "message": "unknown tag: alt",
23393          "line": " src/core/shape/curves.js:273"
23394        }, {
23395          "message": "unknown tag: alt",
23396          "line": " src/core/shape/curves.js:364"
23397        }, {
23398          "message": "unknown tag: alt",
23399          "line": " src/core/shape/curves.js:406"
23400        }, {
23401          "message": "unknown tag: alt",
23402          "line": " src/core/shape/curves.js:502"
23403        }, {
23404          "message": "unknown tag: alt",
23405          "line": " src/core/shape/vertex.js:22"
23406        }, {
23407          "message": "unknown tag: alt",
23408          "line": " src/core/shape/vertex.js:70"
23409        }, {
23410          "message": "unknown tag: alt",
23411          "line": " src/core/shape/vertex.js:270"
23412        }, {
23413          "message": "unknown tag: alt",
23414          "line": " src/core/shape/vertex.js:270"
23415        }, {
23416          "message": "unknown tag: alt",
23417          "line": " src/core/shape/vertex.js:270"
23418        }, {
23419          "message": "unknown tag: alt",
23420          "line": " src/core/shape/vertex.js:398"
23421        }, {
23422          "message": "unknown tag: alt",
23423          "line": " src/core/shape/vertex.js:443"
23424        }, {
23425          "message": "unknown tag: alt",
23426          "line": " src/core/shape/vertex.js:508"
23427        }, {
23428          "message": "unknown tag: alt",
23429          "line": " src/core/shape/vertex.js:568"
23430        }, {
23431          "message": "unknown tag: alt",
23432          "line": " src/core/shape/vertex.js:654"
23433        }, {
23434          "message": "unknown tag: alt",
23435          "line": " src/core/shape/vertex.js:720"
23436        }, {
23437          "message": "unknown tag: alt",
23438          "line": " src/core/shape/vertex.js:813"
23439        }, {
23440          "message": "unknown tag: alt",
23441          "line": " src/core/shape/vertex.js:813"
23442        }, {
23443          "message": "unknown tag: alt",
23444          "line": " src/core/shape/vertex.js:813"
23445        }, {
23446          "message": "unknown tag: alt",
23447          "line": " src/core/shape/vertex.js:813"
23448        }, {
23449          "message": "unknown tag: alt",
23450          "line": " src/core/constants.js:58"
23451        }, {
23452          "message": "unknown tag: alt",
23453          "line": " src/core/constants.js:77"
23454        }, {
23455          "message": "unknown tag: alt",
23456          "line": " src/core/constants.js:96"
23457        }, {
23458          "message": "unknown tag: alt",
23459          "line": " src/core/constants.js:115"
23460        }, {
23461          "message": "unknown tag: alt",
23462          "line": " src/core/constants.js:134"
23463        }, {
23464          "message": "unknown tag: alt",
23465          "line": " src/core/environment.js:22"
23466        }, {
23467          "message": "unknown tag: alt",
23468          "line": " src/core/environment.js:53"
23469        }, {
23470          "message": "unknown tag: alt",
23471          "line": " src/core/environment.js:80"
23472        }, {
23473          "message": "unknown tag: alt",
23474          "line": " src/core/environment.js:112"
23475        }, {
23476          "message": "unknown tag: alt",
23477          "line": " src/core/environment.js:181"
23478        }, {
23479          "message": "unknown tag: alt",
23480          "line": " src/core/environment.js:281"
23481        }, {
23482          "message": "unknown tag: alt",
23483          "line": " src/core/environment.js:306"
23484        }, {
23485          "message": "unknown tag: alt",
23486          "line": " src/core/environment.js:325"
23487        }, {
23488          "message": "unknown tag: alt",
23489          "line": " src/core/environment.js:344"
23490        }, {
23491          "message": "unknown tag: alt",
23492          "line": " src/core/environment.js:360"
23493        }, {
23494          "message": "unknown tag: alt",
23495          "line": " src/core/environment.js:376"
23496        }, {
23497          "message": "unknown tag: alt",
23498          "line": " src/core/environment.js:454"
23499        }, {
23500          "message": "unknown tag: alt",
23501          "line": " src/core/environment.js:505"
23502        }, {
23503          "message": "replacing incorrect tag: returns with return",
23504          "line": " src/core/environment.js:540"
23505        }, {
23506          "message": "replacing incorrect tag: returns with return",
23507          "line": " src/core/environment.js:560"
23508        }, {
23509          "message": "unknown tag: alt",
23510          "line": " src/core/environment.js:560"
23511        }, {
23512          "message": "unknown tag: alt",
23513          "line": " src/core/environment.js:617"
23514        }, {
23515          "message": "unknown tag: alt",
23516          "line": " src/core/environment.js:648"
23517        }, {
23518          "message": "unknown tag: alt",
23519          "line": " src/core/environment.js:671"
23520        }, {
23521          "message": "unknown tag: alt",
23522          "line": " src/core/main.js:49"
23523        }, {
23524          "message": "unknown tag: alt",
23525          "line": " src/core/main.js:90"
23526        }, {
23527          "message": "unknown tag: alt",
23528          "line": " src/core/main.js:121"
23529        }, {
23530          "message": "unknown tag: alt",
23531          "line": " src/core/main.js:400"
23532        }, {
23533          "message": "unknown tag: alt",
23534          "line": " src/core/p5.Element.js:52"
23535        }, {
23536          "message": "unknown tag: alt",
23537          "line": " src/core/p5.Element.js:122"
23538        }, {
23539          "message": "unknown tag: alt",
23540          "line": " src/core/p5.Element.js:159"
23541        }, {
23542          "message": "unknown tag: alt",
23543          "line": " src/core/p5.Element.js:194"
23544        }, {
23545          "message": "unknown tag: alt",
23546          "line": " src/core/p5.Element.js:255"
23547        }, {
23548          "message": "unknown tag: alt",
23549          "line": " src/core/p5.Element.js:304"
23550        }, {
23551          "message": "unknown tag: alt",
23552          "line": " src/core/p5.Element.js:370"
23553        }, {
23554          "message": "unknown tag: alt",
23555          "line": " src/core/p5.Element.js:424"
23556        }, {
23557          "message": "unknown tag: alt",
23558          "line": " src/core/p5.Element.js:480"
23559        }, {
23560          "message": "unknown tag: alt",
23561          "line": " src/core/p5.Element.js:538"
23562        }, {
23563          "message": "unknown tag: alt",
23564          "line": " src/core/p5.Element.js:581"
23565        }, {
23566          "message": "unknown tag: alt",
23567          "line": " src/core/p5.Element.js:623"
23568        }, {
23569          "message": "unknown tag: alt",
23570          "line": " src/core/p5.Element.js:671"
23571        }, {
23572          "message": "unknown tag: alt",
23573          "line": " src/core/p5.Element.js:711"
23574        }, {
23575          "message": "unknown tag: alt",
23576          "line": " src/core/p5.Element.js:760"
23577        }, {
23578          "message": "unknown tag: alt",
23579          "line": " src/core/p5.Element.js:798"
23580        }, {
23581          "message": "unknown tag: alt",
23582          "line": " src/core/p5.Element.js:836"
23583        }, {
23584          "message": "unknown tag: alt",
23585          "line": " src/core/p5.Graphics.js:65"
23586        }, {
23587          "message": "unknown tag: alt",
23588          "line": " src/core/rendering.js:17"
23589        }, {
23590          "message": "unknown tag: alt",
23591          "line": " src/core/rendering.js:119"
23592        }, {
23593          "message": "unknown tag: alt",
23594          "line": " src/core/rendering.js:174"
23595        }, {
23596          "message": "unknown tag: alt",
23597          "line": " src/core/rendering.js:197"
23598        }, {
23599          "message": "unknown tag: alt",
23600          "line": " src/core/rendering.js:236"
23601        }, {
23602          "message": "unknown tag: alt",
23603          "line": " src/core/structure.js:12"
23604        }, {
23605          "message": "unknown tag: alt",
23606          "line": " src/core/structure.js:74"
23607        }, {
23608          "message": "unknown tag: alt",
23609          "line": " src/core/structure.js:116"
23610        }, {
23611          "message": "unknown tag: alt",
23612          "line": " src/core/structure.js:181"
23613        }, {
23614          "message": "unknown tag: alt",
23615          "line": " src/core/structure.js:247"
23616        }, {
23617          "message": "unknown tag: alt",
23618          "line": " src/core/transform.js:13"
23619        }, {
23620          "message": "unknown tag: alt",
23621          "line": " src/core/transform.js:135"
23622        }, {
23623          "message": "unknown tag: alt",
23624          "line": " src/core/transform.js:161"
23625        }, {
23626          "message": "unknown tag: alt",
23627          "line": " src/core/transform.js:201"
23628        }, {
23629          "message": "unknown tag: alt",
23630          "line": " src/core/transform.js:231"
23631        }, {
23632          "message": "unknown tag: alt",
23633          "line": " src/core/transform.js:261"
23634        }, {
23635          "message": "unknown tag: alt",
23636          "line": " src/core/transform.js:291"
23637        }, {
23638          "message": "unknown tag: alt",
23639          "line": " src/core/transform.js:366"
23640        }, {
23641          "message": "unknown tag: alt",
23642          "line": " src/core/transform.js:405"
23643        }, {
23644          "message": "unknown tag: alt",
23645          "line": " src/core/transform.js:444"
23646        }, {
23647          "message": "unknown tag: alt",
23648          "line": " src/events/acceleration.js:23"
23649        }, {
23650          "message": "unknown tag: alt",
23651          "line": " src/events/acceleration.js:46"
23652        }, {
23653          "message": "unknown tag: alt",
23654          "line": " src/events/acceleration.js:69"
23655        }, {
23656          "message": "unknown tag: alt",
23657          "line": " src/events/acceleration.js:135"
23658        }, {
23659          "message": "unknown tag: alt",
23660          "line": " src/events/acceleration.js:166"
23661        }, {
23662          "message": "unknown tag: alt",
23663          "line": " src/events/acceleration.js:197"
23664        }, {
23665          "message": "unknown tag: alt",
23666          "line": " src/events/acceleration.js:233"
23667        }, {
23668          "message": "unknown tag: alt",
23669          "line": " src/events/acceleration.js:278"
23670        }, {
23671          "message": "unknown tag: alt",
23672          "line": " src/events/acceleration.js:322"
23673        }, {
23674          "message": "unknown tag: alt",
23675          "line": " src/events/acceleration.js:380"
23676        }, {
23677          "message": "unknown tag: alt",
23678          "line": " src/events/acceleration.js:419"
23679        }, {
23680          "message": "unknown tag: alt",
23681          "line": " src/events/acceleration.js:462"
23682        }, {
23683          "message": "unknown tag: alt",
23684          "line": " src/events/acceleration.js:506"
23685        }, {
23686          "message": "unknown tag: alt",
23687          "line": " src/events/acceleration.js:538"
23688        }, {
23689          "message": "unknown tag: alt",
23690          "line": " src/events/acceleration.js:597"
23691        }, {
23692          "message": "unknown tag: alt",
23693          "line": " src/events/keyboard.js:18"
23694        }, {
23695          "message": "unknown tag: alt",
23696          "line": " src/events/keyboard.js:45"
23697        }, {
23698          "message": "unknown tag: alt",
23699          "line": " src/events/keyboard.js:74"
23700        }, {
23701          "message": "unknown tag: alt",
23702          "line": " src/events/keyboard.js:107"
23703        }, {
23704          "message": "unknown tag: alt",
23705          "line": " src/events/keyboard.js:194"
23706        }, {
23707          "message": "unknown tag: alt",
23708          "line": " src/events/keyboard.js:246"
23709        }, {
23710          "message": "unknown tag: alt",
23711          "line": " src/events/keyboard.js:310"
23712        }, {
23713          "message": "unknown tag: alt",
23714          "line": " src/events/mouse.js:22"
23715        }, {
23716          "message": "unknown tag: alt",
23717          "line": " src/events/mouse.js:48"
23718        }, {
23719          "message": "unknown tag: alt",
23720          "line": " src/events/mouse.js:74"
23721        }, {
23722          "message": "unknown tag: alt",
23723          "line": " src/events/mouse.js:106"
23724        }, {
23725          "message": "unknown tag: alt",
23726          "line": " src/events/mouse.js:137"
23727        }, {
23728          "message": "unknown tag: alt",
23729          "line": " src/events/mouse.js:174"
23730        }, {
23731          "message": "unknown tag: alt",
23732          "line": " src/events/mouse.js:211"
23733        }, {
23734          "message": "unknown tag: alt",
23735          "line": " src/events/mouse.js:252"
23736        }, {
23737          "message": "unknown tag: alt",
23738          "line": " src/events/mouse.js:294"
23739        }, {
23740          "message": "unknown tag: alt",
23741          "line": " src/events/mouse.js:333"
23742        }, {
23743          "message": "unknown tag: alt",
23744          "line": " src/events/mouse.js:424"
23745        }, {
23746          "message": "unknown tag: alt",
23747          "line": " src/events/mouse.js:479"
23748        }, {
23749          "message": "unknown tag: alt",
23750          "line": " src/events/mouse.js:560"
23751        }, {
23752          "message": "unknown tag: alt",
23753          "line": " src/events/mouse.js:637"
23754        }, {
23755          "message": "unknown tag: alt",
23756          "line": " src/events/mouse.js:715"
23757        }, {
23758          "message": "unknown tag: alt",
23759          "line": " src/events/mouse.js:785"
23760        }, {
23761          "message": "unknown tag: alt",
23762          "line": " src/events/mouse.js:870"
23763        }, {
23764          "message": "unknown tag: alt",
23765          "line": " src/events/touch.js:12"
23766        }, {
23767          "message": "unknown tag: alt",
23768          "line": " src/events/touch.js:74"
23769        }, {
23770          "message": "unknown tag: alt",
23771          "line": " src/events/touch.js:149"
23772        }, {
23773          "message": "unknown tag: alt",
23774          "line": " src/events/touch.js:222"
23775        }, {
23776          "message": "unknown tag: alt",
23777          "line": " src/image/image.js:22"
23778        }, {
23779          "message": "unknown tag: alt",
23780          "line": " src/image/image.js:102"
23781        }, {
23782          "message": "unknown tag: alt",
23783          "line": " src/image/image.js:195"
23784        }, {
23785          "message": "unknown tag: alt",
23786          "line": " src/image/loading_displaying.js:17"
23787        }, {
23788          "message": "replacing incorrect tag: returns with return",
23789          "line": " src/image/loading_displaying.js:110"
23790        }, {
23791          "message": "unknown tag: alt",
23792          "line": " src/image/loading_displaying.js:127"
23793        }, {
23794          "message": "unknown tag: alt",
23795          "line": " src/image/loading_displaying.js:298"
23796        }, {
23797          "message": "unknown tag: alt",
23798          "line": " src/image/loading_displaying.js:398"
23799        }, {
23800          "message": "unknown tag: alt",
23801          "line": " src/image/loading_displaying.js:464"
23802        }, {
23803          "message": "unknown tag: alt",
23804          "line": " src/image/p5.Image.js:90"
23805        }, {
23806          "message": "unknown tag: alt",
23807          "line": " src/image/p5.Image.js:117"
23808        }, {
23809          "message": "unknown tag: alt",
23810          "line": " src/image/p5.Image.js:152"
23811        }, {
23812          "message": "unknown tag: alt",
23813          "line": " src/image/p5.Image.js:231"
23814        }, {
23815          "message": "unknown tag: alt",
23816          "line": " src/image/p5.Image.js:267"
23817        }, {
23818          "message": "unknown tag: alt",
23819          "line": " src/image/p5.Image.js:315"
23820        }, {
23821          "message": "unknown tag: alt",
23822          "line": " src/image/p5.Image.js:360"
23823        }, {
23824          "message": "unknown tag: alt",
23825          "line": " src/image/p5.Image.js:398"
23826        }, {
23827          "message": "unknown tag: alt",
23828          "line": " src/image/p5.Image.js:483"
23829        }, {
23830          "message": "unknown tag: alt",
23831          "line": " src/image/p5.Image.js:564"
23832        }, {
23833          "message": "unknown tag: alt",
23834          "line": " src/image/p5.Image.js:627"
23835        }, {
23836          "message": "unknown tag: alt",
23837          "line": " src/image/p5.Image.js:663"
23838        }, {
23839          "message": "unknown tag: alt",
23840          "line": " src/image/p5.Image.js:785"
23841        }, {
23842          "message": "unknown tag: alt",
23843          "line": " src/image/pixels.js:14"
23844        }, {
23845          "message": "unknown tag: alt",
23846          "line": " src/image/pixels.js:83"
23847        }, {
23848          "message": "unknown tag: alt",
23849          "line": " src/image/pixels.js:177"
23850        }, {
23851          "message": "unknown tag: alt",
23852          "line": " src/image/pixels.js:236"
23853        }, {
23854          "message": "unknown tag: alt",
23855          "line": " src/image/pixels.js:415"
23856        }, {
23857          "message": "unknown tag: alt",
23858          "line": " src/image/pixels.js:520"
23859        }, {
23860          "message": "unknown tag: alt",
23861          "line": " src/image/pixels.js:557"
23862        }, {
23863          "message": "unknown tag: alt",
23864          "line": " src/image/pixels.js:631"
23865        }, {
23866          "message": "unknown tag: alt",
23867          "line": " src/io/files.js:19"
23868        }, {
23869          "message": "unknown tag: alt",
23870          "line": " src/io/files.js:180"
23871        }, {
23872          "message": "unknown tag: alt",
23873          "line": " src/io/files.js:293"
23874        }, {
23875          "message": "unknown tag: alt",
23876          "line": " src/io/files.js:603"
23877        }, {
23878          "message": "replacing incorrect tag: returns with return",
23879          "line": " src/io/files.js:714"
23880        }, {
23881          "message": "unknown tag: alt",
23882          "line": " src/io/files.js:714"
23883        }, {
23884          "message": "unknown tag: alt",
23885          "line": " src/io/files.js:1516"
23886        }, {
23887          "message": "unknown tag: alt",
23888          "line": " src/io/files.js:1574"
23889        }, {
23890          "message": "unknown tag: alt",
23891          "line": " src/io/files.js:1642"
23892        }, {
23893          "message": "unknown tag: alt",
23894          "line": " src/io/p5.Table.js:56"
23895        }, {
23896          "message": "unknown tag: alt",
23897          "line": " src/io/p5.Table.js:120"
23898        }, {
23899          "message": "unknown tag: alt",
23900          "line": " src/io/p5.Table.js:168"
23901        }, {
23902          "message": "unknown tag: alt",
23903          "line": " src/io/p5.Table.js:214"
23904        }, {
23905          "message": "unknown tag: alt",
23906          "line": " src/io/p5.Table.js:263"
23907        }, {
23908          "message": "unknown tag: alt",
23909          "line": " src/io/p5.Table.js:328"
23910        }, {
23911          "message": "unknown tag: alt",
23912          "line": " src/io/p5.Table.js:523"
23913        }, {
23914          "message": "unknown tag: alt",
23915          "line": " src/io/p5.Table.js:576"
23916        }, {
23917          "message": "unknown tag: alt",
23918          "line": " src/io/p5.Table.js:618"
23919        }, {
23920          "message": "unknown tag: alt",
23921          "line": " src/io/p5.Table.js:879"
23922        }, {
23923          "message": "unknown tag: alt",
23924          "line": " src/io/p5.Table.js:944"
23925        }, {
23926          "message": "unknown tag: alt",
23927          "line": " src/io/p5.Table.js:994"
23928        }, {
23929          "message": "unknown tag: alt",
23930          "line": " src/io/p5.Table.js:1040"
23931        }, {
23932          "message": "unknown tag: alt",
23933          "line": " src/io/p5.Table.js:1085"
23934        }, {
23935          "message": "unknown tag: alt",
23936          "line": " src/io/p5.Table.js:1132"
23937        }, {
23938          "message": "unknown tag: alt",
23939          "line": " src/io/p5.Table.js:1177"
23940        }, {
23941          "message": "unknown tag: alt",
23942          "line": " src/io/p5.Table.js:1230"
23943        }, {
23944          "message": "unknown tag: alt",
23945          "line": " src/io/p5.Table.js:1296"
23946        }, {
23947          "message": "unknown tag: alt",
23948          "line": " src/io/p5.TableRow.js:42"
23949        }, {
23950          "message": "unknown tag: alt",
23951          "line": " src/io/p5.TableRow.js:106"
23952        }, {
23953          "message": "unknown tag: alt",
23954          "line": " src/io/p5.TableRow.js:150"
23955        }, {
23956          "message": "unknown tag: alt",
23957          "line": " src/io/p5.TableRow.js:195"
23958        }, {
23959          "message": "unknown tag: alt",
23960          "line": " src/io/p5.TableRow.js:243"
23961        }, {
23962          "message": "unknown tag: alt",
23963          "line": " src/io/p5.TableRow.js:299"
23964        }, {
23965          "message": "unknown tag: alt",
23966          "line": " src/io/p5.XML.js:11"
23967        }, {
23968          "message": "unknown tag: alt",
23969          "line": " src/math/calculation.js:12"
23970        }, {
23971          "message": "unknown tag: alt",
23972          "line": " src/math/calculation.js:36"
23973        }, {
23974          "message": "unknown tag: alt",
23975          "line": " src/math/calculation.js:76"
23976        }, {
23977          "message": "unknown tag: alt",
23978          "line": " src/math/calculation.js:121"
23979        }, {
23980          "message": "unknown tag: alt",
23981          "line": " src/math/calculation.js:190"
23982        }, {
23983          "message": "unknown tag: alt",
23984          "line": " src/math/calculation.js:240"
23985        }, {
23986          "message": "unknown tag: alt",
23987          "line": " src/math/calculation.js:279"
23988        }, {
23989          "message": "unknown tag: alt",
23990          "line": " src/math/calculation.js:327"
23991        }, {
23992          "message": "unknown tag: alt",
23993          "line": " src/math/calculation.js:383"
23994        }, {
23995          "message": "unknown tag: alt",
23996          "line": " src/math/calculation.js:422"
23997        }, {
23998          "message": "unknown tag: alt",
23999          "line": " src/math/calculation.js:478"
24000        }, {
24001          "message": "unknown tag: alt",
24002          "line": " src/math/calculation.js:528"
24003        }, {
24004          "message": "unknown tag: alt",
24005          "line": " src/math/calculation.js:578"
24006        }, {
24007          "message": "unknown tag: alt",
24008          "line": " src/math/calculation.js:631"
24009        }, {
24010          "message": "unknown tag: alt",
24011          "line": " src/math/calculation.js:665"
24012        }, {
24013          "message": "unknown tag: alt",
24014          "line": " src/math/calculation.js:704"
24015        }, {
24016          "message": "unknown tag: alt",
24017          "line": " src/math/calculation.js:751"
24018        }, {
24019          "message": "unknown tag: alt",
24020          "line": " src/math/math.js:12"
24021        }, {
24022          "message": "unknown tag: alt",
24023          "line": " src/math/noise.js:40"
24024        }, {
24025          "message": "un
24025known tag: alt",
24026          "line": " src/math/noise.js:187"
24027        }, {
24028          "message": "unknown tag: alt",
24029          "line": " src/math/noise.js:253"
24030        }, {
24031          "message": "unknown tag: alt",
24032          "line": " src/math/p5.Vector.js:12"
24033        }, {
24034          "message": "unknown tag: alt",
24035          "line": " src/math/random.js:48"
24036        }, {
24037          "message": "unknown tag: alt",
24038          "line": " src/math/random.js:79"
24039        }, {
24040          "message": "unknown tag: alt",
24041          "line": " src/math/random.js:166"
24042        }, {
24043          "message": "unknown tag: alt",
24044          "line": " src/math/trigonometry.js:124"
24045        }, {
24046          "message": "unknown tag: alt",
24047          "line": " src/math/trigonometry.js:160"
24048        }, {
24049          "message": "unknown tag: alt",
24050          "line": " src/math/trigonometry.js:188"
24051        }, {
24052          "message": "unknown tag: alt",
24053          "line": " src/math/trigonometry.js:216"
24054        }, {
24055          "message": "unknown tag: alt",
24056          "line": " src/math/trigonometry.js:296"
24057        }, {
24058          "message": "replacing incorrect tag: returns with return",
24059          "line": " src/math/trigonometry.js:332"
24060        }, {
24061          "message": "replacing incorrect tag: returns with return",
24062          "line": " src/math/trigonometry.js:347"
24063        }, {
24064          "message": "replacing incorrect tag: returns with return",
24065          "line": " src/math/trigonometry.js:362"
24066        }, {
24067          "message": "unknown tag: alt",
24068          "line": " src/typography/attributes.js:13"
24069        }, {
24070          "message": "unknown tag: alt",
24071          "line": " src/typography/attributes.js:84"
24072        }, {
24073          "message": "unknown tag: alt",
24074          "line": " src/typography/attributes.js:122"
24075        }, {
24076          "message": "unknown tag: alt",
24077          "line": " src/typography/attributes.js:154"
24078        }, {
24079          "message": "unknown tag: alt",
24080          "line": " src/typography/attributes.js:191"
24081        }, {
24082          "message": "unknown tag: alt",
24083          "line": " src/typography/loading_displaying.js:16"
24084        }, {
24085          "message": "unknown tag: alt",
24086          "line": " src/typography/loading_displaying.js:143"
24087        }, {
24088          "message": "unknown tag: alt",
24089          "line": " src/typography/loading_displaying.js:230"
24090        }, {
24091          "message": "unknown tag: alt",
24092          "line": " src/typography/p5.Font.js:32"
24093        }, {
24094          "message": "unknown tag: alt",
24095          "line": " src/utilities/conversion.js:12"
24096        }, {
24097          "message": "unknown tag: alt",
24098          "line": " src/utilities/string_functions.js:15"
24099        }, {
24100          "message": "unknown tag: alt",
24101          "line": " src/utilities/string_functions.js:44"
24102        }, {
24103          "message": "unknown tag: alt",
24104          "line": " src/utilities/string_functions.js:132"
24105        }, {
24106          "message": "unknown tag: alt",
24107          "line": " src/utilities/string_functions.js:243"
24108        }, {
24109          "message": "unknown tag: alt",
24110          "line": " src/utilities/string_functions.js:319"
24111        }, {
24112          "message": "unknown tag: alt",
24113          "line": " src/utilities/string_functions.js:381"
24114        }, {
24115          "message": "unknown tag: alt",
24116          "line": " src/utilities/string_functions.js:459"
24117        }, {
24118          "message": "unknown tag: alt",
24119          "line": " src/utilities/string_functions.js:548"
24120        }, {
24121          "message": "unknown tag: alt",
24122          "line": " src/utilities/time_date.js:12"
24123        }, {
24124          "message": "unknown tag: alt",
24125          "line": " src/utilities/time_date.js:34"
24126        }, {
24127          "message": "unknown tag: alt",
24128          "line": " src/utilities/time_date.js:56"
24129        }, {
24130          "message": "unknown tag: alt",
24131          "line": " src/utilities/time_date.js:78"
24132        }, {
24133          "message": "unknown tag: alt",
24134          "line": " src/utilities/time_date.js:101"
24135        }, {
24136          "message": "unknown tag: alt",
24137          "line": " src/utilities/time_date.js:123"
24138        }, {
24139          "message": "unknown tag: alt",
24140          "line": " src/utilities/time_date.js:145"
24141        }, {
24142          "message": "unknown tag: alt",
24143          "line": " src/webgl/3d_primitives.js:15"
24144        }, {
24145          "message": "unknown tag: alt",
24146          "line": " src/webgl/interaction.js:13"
24147        }, {
24148          "message": "unknown tag: alt",
24149          "line": " src/webgl/interaction.js:146"
24150        }, {
24151          "message": "unknown tag: alt",
24152          "line": " src/webgl/interaction.js:146"
24153        }, {
24154          "message": "unknown tag: alt",
24155          "line": " src/webgl/interaction.js:146"
24156        }, {
24157          "message": "unknown tag: alt",
24158          "line": " src/webgl/interaction.js:146"
24159        }, {
24160          "message": "unknown tag: alt",
24161          "line": " src/webgl/interaction.js:146"
24162        }, {
24163          "message": "unknown tag: alt",
24164          "line": " src/webgl/interaction.js:380"
24165        }, {
24166          "message": "unknown tag: alt",
24167          "line": " src/webgl/light.js:12"
24168        }, {
24169          "message": "unknown tag: alt",
24170          "line": " src/webgl/light.js:101"
24171        }, {
24172          "message": "unknown tag: alt",
24173          "line": " src/webgl/light.js:212"
24174        }, {
24175          "message": "unknown tag: alt",
24176          "line": " src/webgl/loading.js:14"
24177        }, {
24178          "message": "unknown tag: alt",
24179          "line": " src/webgl/loading.js:14"
24180        }, {
24181          "message": "unknown tag: alt",
24182          "line": " src/webgl/loading.js:244"
24183        }, {
24184          "message": "unknown tag: alt",
24185          "line": " src/webgl/material.js:14"
24186        }, {
24187          "message": "replacing incorrect tag: returns with return",
24188          "line": " src/webgl/material.js:83"
24189        }, {
24190          "message": "unknown tag: alt",
24191          "line": " src/webgl/material.js:83"
24192        }, {
24193          "message": "unknown tag: alt",
24194          "line": " src/webgl/material.js:176"
24195        }, {
24196          "message": "unknown tag: alt",
24197          "line": " src/webgl/material.js:211"
24198        }, {
24199          "message": "unknown tag: alt",
24200          "line": " src/webgl/material.js:302"
24201        }, {
24202          "message": "unknown tag: alt",
24203          "line": " src/webgl/material.js:302"
24204        }, {
24205          "message": "unknown tag: alt",
24206          "line": " src/webgl/material.js:381"
24207        }, {
24208          "message": "unknown tag: alt",
24209          "line": " src/webgl/material.js:430"
24210        }, {
24211          "message": "unknown tag: alt",
24212          "line": " src/webgl/p5.Camera.js:15"
24213        }, {
24214          "message": "unknown tag: alt",
24215          "line": " src/webgl/p5.Camera.js:61"
24216        }, {
24217          "message": "unknown tag: alt",
24218          "line": " src/webgl/p5.Camera.js:126"
24219        }, {
24220          "message": "unknown tag: alt",
24221          "line": " src/webgl/p5.Camera.js:209"
24222        }, {
24223          "message": "unknown tag: alt",
24224          "line": " src/webgl/p5.Camera.js:486"
24225        }, {
24226          "message": "unknown tag: alt",
24227          "line": " src/webgl/p5.Camera.js:545"
24228        }, {
24229          "message": "unknown tag: alt",
24230          "line": " src/webgl/p5.Camera.js:603"
24231        }, {
24232          "message": "unknown tag: alt",
24233          "line": " src/webgl/p5.Camera.js:751"
24234        }, {
24235          "message": "unknown tag: alt",
24236          "line": " src/webgl/p5.Camera.js:823"
24237        }, {
24238          "message": "unknown tag: alt",
24239          "line": " src/webgl/p5.Camera.js:1088"
24240        }, {
24241          "message": "unknown tag: alt",
24242          "line": " src/webgl/p5.RendererGL.js:216"
24243        }, {
24244          "message": "unknown tag: alt",
24245          "line": " src/webgl/p5.RendererGL.js:428"
24246        }, {
24247          "message": "unknown tag: alt",
24248          "line": " src/webgl/p5.RendererGL.js:475"
24249        }, {
24250          "message": "unknown tag: alt",
24251          "line": " src/webgl/p5.RendererGL.js:516"
24252        }, {
24253          "message": "replacing incorrect tag: function with method",
24254          "line": " src/webgl/text.js:117"
24255        }, {
24256          "message": "replacing incorrect tag: returns with return",
24257          "line": " src/webgl/text.js:160"
24258        }, {
24259          "message": "replacing incorrect tag: function with method",
24260          "line": " src/webgl/text.js:193"
24261        }, {
24262          "message": "replacing incorrect tag: function with method",
24263          "line": " src/webgl/text.js:205"
24264        }, {
24265          "message": "replacing incorrect tag: function with method",
24266          "line": " src/webgl/text.js:235"
24267        }, {
24268          "message": "replacing incorrect tag: function with method",
24269          "line": " src/webgl/text.js:249"
24270        }, {
24271          "message": "replacing incorrect tag: function with method",
24272          "line": " src/webgl/text.js:387"
24273        }, {
24274          "message": "replacing incorrect tag: returns with return",
24275          "line": " src/webgl/text.js:387"
24276        }, {
24277          "message": "replacing incorrect tag: function with method",
24278          "line": " src/webgl/text.js:457"
24279        }, {
24280          "message": "replacing incorrect tag: function with method",
24281          "line": " src/webgl/text.js:472"
24282        }, {
24283          "message": "replacing incorrect tag: function with method",
24284          "line": " src/webgl/text.js:547"
24285        }, {
24286          "message": "unknown tag: alt",
24287          "line": " lib/addons/p5.dom.js:245"
24288        }, {
24289          "message": "unknown tag: alt",
24290          "line": " lib/addons/p5.dom.js:313"
24291        }, {
24292          "message": "replacing incorrect tag: returns with return",
24293          "line": " lib/addons/p5.dom.js:1453"
24294        }, {
24295          "message": "replacing incorrect tag: returns with return",
24296          "line": " lib/addons/p5.dom.js:1557"
24297        }, {
24298          "message": "replacing incorrect tag: returns with return",
24299          "line": " lib/addons/p5.dom.js:1596"
24300        }, {
24301          "message": "replacing incorrect tag: returns with return",
24302          "line": " lib/addons/p5.dom.js:1690"
24303        }, {
24304          "message": "replacing incorrect tag: params with param",
24305          "line": " lib/addons/p5.sound.js:1854"
24306        }, {
24307          "message": "replacing incorrect tag: returns with return",
24308          "line": " lib/addons/p5.sound.js:1854"
24309        }, {
24310          "message": "replacing incorrect tag: returns with return",
24311          "line": " lib/addons/p5.sound.js:2473"
24312        }, {
24313          "message": "replacing incorrect tag: returns with return",
24314          "line": " lib/addons/p5.sound.js:7653"
24315        }, {
24316          "message": "replacing incorrect tag: returns with return",
24317          "line": " lib/addons/p5.sound.js:9620"
24318        }, {
24319          "message": "Missing item type\nConversions adapted from <http://www.easyrgb.com/en/math.php>.\n\nIn these functions, hue is always in the range [0, 1], just like all other\ncomponents are in the range [0, 1]. 'Brightness' and 'value' are used\ninterchangeably.",
24320          "line": " src/color/color_conversion.js:10"
24321        }, {
24322          "message": "Missing item type\nConvert an HSBA array to HSLA.",
24323          "line": " src/color/color_conversion.js:21"
24324        }, {
24325          "message": "Missing item type\nConvert an HSBA array to RGBA.",
24326          "line": " src/color/color_conversion.js:47"
24327        }, {
24328          "message": "Missing item type\nConvert an HSLA array to HSBA.",
24329          "line": " src/color/color_conversion.js:102"
24330        }, {
24331          "message": "Missing item type\nConvert an HSLA array to RGBA.\n\nWe need to change basis from HSLA to something that can be more easily be\nprojected onto RGBA. We will choose hue and brightness as our first two\ncomponents, and pick a convenient third one ('zest') so that we don't need\nto calculate formal HSBA saturation.",
24332          "line": " src/color/color_conversion.js:125"
24333        }, {
24334          "message": "Missing item type\nConvert an RGBA array to HSBA.",
24335          "line": " src/color/color_conversion.js:189"
24336        }, {
24337          "message": "Missing item type\nConvert an RGBA array to HSLA.",
24338          "line": " src/color/color_conversion.js:228"
24339        }, {
24340          "message": "Missing item type\nHue is the same in HSB and HSL, but the maximum value may be different.\nThis function will return the HSB-normalized saturation when supplied with\nan HSB color object, but will default to the HSL-normalized saturation\notherwise.",
24341          "line": " src/color/p5.Color.js:410"
24342        }, {
24343          "message": "Missing item type\nSaturation is scaled differently in HSB and HSL. This function will return\nthe HSB saturation when supplied with an HSB color object, but will default\nto the HSL saturation otherwise.",
24344          "line": " src/color/p5.Color.js:441"
24345        }, {
24346          "message": "Missing item type\nCSS named colors.",
24347          "line": " src/color/p5.Color.js:460"
24348        }, {
24349          "message": "Missing item type\nThese regular expressions are used to build up the patterns for matching\nviable CSS color strings: fragmenting the regexes in this way increases the\nlegibility and comprehensibility of the code.\n\nNote that RGB values of .9 are not parsed by IE, but are supported here for\ncolor string consistency.",
24350          "line": " src/color/p5.Color.js:613"
24351        }, {
24352          "message": "Missing item type\nFull color string patterns. The capture groups are necessary.",
24353          "line": " src/color/p5.Color.js:626"
24354        }, {
24355          "message": "Missing item type\nFor a number of different inputs, returns a color formatted as [r, g, b, a]\narrays, with each component normalized between 0 and 1.",
24356          "line": " src/color/p5.Color.js:763"
24357        }, {
24358          "message": "Missing item type\nFor HSB and HSL, interpret the gray level as a brightness/lightness\nvalue (they are equivalent when chroma is zero). For RGB, normalize the\ngray level according to the blue maximum.",
24359          "line": " src/color/p5.Color.js:989"
24360        }, {
24361          "message": "Missing item type\nReturns the current framerate.",
24362          "line": " src/core/environment.js:255"
24363        }, {
24364          "message": "Missing item type\nSpecifies the number of frames to be displayed every second. For example,\nthe function call frameRate(30) will attempt to refresh 30 times a second.\nIf the processor is not fast enough to maintain the specified rate, the\nframe rate will not be achieved. Setting the frame rate within <a href=\"#/p5/setup\">setup()</a> is\nrecommended. The default rate is 60 frames per second.\n\nCalling <a href=\"#/p5/frameRate\">frameRate()</a> with no arguments returns the current framerate.",
24365          "line": " src/core/environment.js:265"
24366        }, {
24367          "message": "Missing item type",
24368          "line": " src/core/error_helpers.js:1"
24369        }, {
24370          "message": "Missing item type\nValidates parameters\nparam  {String}               func    the name of the function\nparam  {Array}                args    user input arguments\n\nexample:\n var a;\n ellipse(10,10,a,5);\nconsole ouput:\n \"It looks like ellipse received an empty variable in spot #2.\"\n\nexample:\n ellipse(10,\"foo\",5,5);\nconsole output:\n \"ellipse was expecting a number for parameter #1,\n          received \"foo\" instead.\"",
24371          "line": " src/core/error_helpers.js:584"
24372        }, {
24373          "message": "Missing item type\nPrints out all the colors in the color pallete with white text.\nFor color blindness testing.",
24374          "line": " src/core/error_helpers.js:645"
24375        }, {
24376          "message": "Missing item type",
24377          "line": " src/core/helpers.js:1"
24378        }, {
24379          "message": "Missing item type\n_globalInit\n\nTODO: ???\nif sketch is on window\nassume \"global\" mode\nand instantiate p5 automatically\notherwise do nothing",
24380          "line": " src/core/init.js:5"
24381        }, {
24382          "message": "Missing item type",
24383          "line": " src/core/legacy.js:1"
24384        }, {
24385          "message": "Missing item type\nHelper fxn for sharing pixel methods",
24386          "line": " src/core/p5.Element.js:969"
24387        }, {
24388          "message": "Missing item type\nResize our canvas element.",
24389          "line": " src/core/p5.Renderer.js:96"
24390        }, {
24391          "message": "Missing item type\nHelper fxn to check font type (syste
24391m or otf)",
24392          "line": " src/core/p5.Renderer.js:301"
24393        }, {
24394          "message": "Missing item type\nHelper fxn to measure ascent and descent.\nAdapted from http://stackoverflow.com/a/25355178",
24395          "line": " src/core/p5.Renderer.js:354"
24396        }, {
24397          "message": "Missing item type\np5.Renderer2D\nThe 2D graphics canvas renderer class.\nextends p5.Renderer",
24398          "line": " src/core/p5.Renderer2D.js:9"
24399        }, {
24400          "message": "Missing item type\nGenerate a cubic Bezier representing an arc on the unit circle of total\nangle `size` radians, beginning `start` radians above the x-axis. Up to\nfour of these curves are combined to make a full arc.\n\nSee www.joecridge.me/bezier.pdf for an explanation of the method.",
24401          "line": " src/core/p5.Renderer2D.js:392"
24402        }, {
24403          "message": "Missing item type\nshim for Uint8ClampedArray.slice\n(allows arrayCopy to work with pixels[])\nwith thanks to http://halfpapstudios.com/blog/tag/html5-canvas/\nEnumerable set to false to protect for...in from\nUint8ClampedArray.prototype pollution.",
24404          "line": " src/core/shim.js:23"
24405        }, {
24406          "message": "Missing item type\nthis is implementation of Object.assign() which is unavailable in\nIE11 and (non-Chrome) Android browsers.\nThe assign() method is used to copy the values of all enumerable\nown properties from one or more source objects to a target object.\nIt will return the target object.\nModified from https://github.com/ljharb/object.assign",
24407          "line": " src/core/shim.js:45"
24408        }, {
24409          "message": "Missing item type\nprivate helper function to handle the user passing in objects\nduring construction or calls to create()",
24410          "line": " src/data/p5.TypedDict.js:203"
24411        }, {
24412          "message": "Missing item type\nprivate helper function to ensure that the user passed in valid\nvalues for the Dictionary type",
24413          "line": " src/data/p5.TypedDict.js:394"
24414        }, {
24415          "message": "Missing item type\nprivate helper function to ensure that the user passed in valid\nvalues for the Dictionary type",
24416          "line": " src/data/p5.TypedDict.js:437"
24417        }, {
24418          "message": "Missing item type\nprivate helper function for finding lowest or highest value\nthe argument 'flip' is used to flip the comparison arrow\nfrom 'less than' to 'greater than'",
24419          "line": " src/data/p5.TypedDict.js:554"
24420        }, {
24421          "message": "Missing item type\nprivate helper function for finding lowest or highest key\nthe argument 'flip' is used to flip the comparison arrow\nfrom 'less than' to 'greater than'",
24422          "line": " src/data/p5.TypedDict.js:621"
24423        }, {
24424          "message": "Missing item type\n_updatePAccelerations updates the pAcceleration values",
24425          "line": " src/events/acceleration.js:124"
24426        }, {
24427          "message": "Missing item type\nHolds the key codes of currently pressed keys.",
24428          "line": " src/events/keyboard.js:12"
24429        }, {
24430          "message": "Missing item type\nThe onblur function is called when the user is no longer focused\non the p5 element. Because the keyup events will not fire if the user is\nnot focused on the element we must assume all keys currently down have\nbeen released.",
24431          "line": " src/events/keyboard.js:300"
24432        }, {
24433          "message": "Missing item type\nThe checkDownKeys function returns a boolean true if any keys pressed\nand a false if no keys are currently pressed.\n\nHelps avoid instances where a multiple keys are pressed simultaneously and\nreleasing a single key will then switch the\nkeyIsPressed property to true.",
24434          "line": " src/events/keyboard.js:387"
24435        }, {
24436          "message": "Missing item type\nThis module defines the filters for use with image buffers.\n\nThis module is basically a collection of functions stored in an object\nas opposed to modules. The functions are destructive, modifying\nthe passed in canvas rather than creating a copy.\n\nGenerally speaking users of this module will use the Filters.apply method\non a canvas to create an effect.\n\nA number of functions are borrowed/adapted from\nhttp://www.html5rocks.com/en/tutorials/canvas/imagefilters/\nor the java processing implementation.",
24437          "line": " src/image/filters.js:3"
24438        }, {
24439          "message": "Missing item type\nReturns the pixel buffer for a canvas",
24440          "line": " src/image/filters.js:26"
24441        }, {
24442          "message": "Missing item type\nReturns a 32 bit number containing ARGB data at ith pixel in the\n1D array containing pixels data.",
24443          "line": " src/image/filters.js:46"
24444        }, {
24445          "message": "Missing item type\nModifies pixels RGBA values to values contained in the data object.",
24446          "line": " src/image/filters.js:67"
24447        }, {
24448          "message": "Missing item type\nReturns the ImageData object for a canvas\nhttps://developer.mozilla.org/en-US/docs/Web/API/ImageData",
24449          "line": " src/image/filters.js:87"
24450        }, {
24451          "message": "Missing item type\nReturns a blank ImageData object.",
24452          "line": " src/image/filters.js:107"
24453        }, {
24454          "message": "Missing item type\nApplys a filter function to a canvas.\n\nThe difference between this and the actual filter functions defined below\nis that the filter functions generally modify the pixel buffer but do\nnot actually put that data back to the canvas (where it would actually\nupdate what is visible). By contrast this method does make the changes\nactually visible in the canvas.\n\nThe apply method is the method that callers of this module would generally\nuse. It has been separated from the actual filters to 
24454support an advanced\nuse case of creating a filter chain that executes without actually updating\nthe canvas in between everystep.",
24455          "line": " src/image/filters.js:122"
24456        }, {
24457          "message": "Missing item type\nConverts the image to black and white pixels depending if they are above or\nbelow the threshold defined by the level parameter. The parameter must be\nbetween 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used.\n\nBorrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/",
24458          "line": " src/image/filters.js:159"
24459        }, {
24460          "message": "Missing item type\nConverts any colors in the image to grayscale equivalents.\nNo parameter is used.\n\nBorrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/",
24461          "line": " src/image/filters.js:193"
24462        }, {
24463          "message": "Missing item type\nSets the alpha channel to entirely opaque. No parameter is used.",
24464          "line": " src/image/filters.js:216"
24465        }, {
24466          "message": "Missing item type\nSets each pixel to its inverse value. No parameter is used.",
24467          "line": " src/image/filters.js:232"
24468        }, {
24469          "message": "Missing item type\nLimits each channel of the image to the number of colors specified as\nthe parameter. The parameter can be set to values between 2 and 255, but\nresults are most noticeable in the lower ranges.\n\nAdapted from java based processing implementation",
24470          "line": " src/image/filters.js:247"
24471        }, {
24472          "message": "Missing item type\nreduces the bright areas in an image",
24473          "line": " src/image/filters.js:279"
24474        }, {
24475          "message": "Missing item type\nincreases the bright areas in an image",
24476          "line": " src/image/filters.js:367"
24477        }, {
24478          "message": "Missing item type\nThis module defines the p5 methods for the <a href=\"#/p5.Image\">p5.Image</a> class\nfor drawing images to the main display canvas.",
24479          "line": " src/image/image.js:8"
24480        }, {
24481          "message": "Missing item type\nValidates clipping params. Per drawImage spec sWidth and sHight cannot be\nnegative or greater than image intrinsic width and height",
24482          "line": " src/image/loading_displaying.js:110"
24483        }, {
24484          "message": "Missing item type\nApply the current tint color to the input image, return the resulting\ncanvas.",
24485          "line": " src/image/loading_displaying.js:427"
24486        }, {
24487          "message": "Missing item type\nThis module defines the <a href=\"#/p5.Image\">p5.Image</a> class and P5 methods for\ndrawing images to the main display canvas.",
24488          "line": " src/image/p5.Image.js:9"
24489        }, {
24490          "message": "Missing item type\nHelper fxn for sharing pixel methods",
24491          "line": " src/image/p5.Image.js:222"
24492        }, {
24493          "message": "Missing item type\nGenerate a blob of file data as a url to prepare for download.\nAccepts an array of data, a filename, and an extension (optional).\nThis is a private function because it does not do any formatting,\nbut it is used by <a href=\"#/p5/saveStrings\">saveStrings</a>, <a href=\"#/p5/saveJSON\">saveJSON</a>, <a href=\"#/p5/saveTable\">saveTable</a> etc.",
24494          "line": " src/io/files.js:1768"
24495        }, {
24496          "message": "Missing item type\nReturns a file extension, or another string\nif the provided parameter has no extension.",
24497          "line": " src/io/files.js:1837"
24498        }, {
24499          "message": "Missing item type\nReturns true if the browser is Safari, false if not.\nSafari makes trouble for downloading files.",
24500          "line": " src/io/files.js:1870"
24501        }, {
24502          "message": "Missing item type\nHelper function, a callback for download that deletes\nan invisible anchor element from the DOM once the file\nhas been automatically downloaded.",
24503          "line": " src/io/files.js:1882"
24504        }, {
24505          "message": "Missing item type\nTable Options\n<p>Generic class for handling tabular data, typically from a\nCSV, TSV, or other sort of spreadsheet file.</p>\n<p>CSV files are\n<a href=\"http://en.wikipedia.org/wiki/Comma-separated_values\">\ncomma separated values</a>, often with the data in quotes. TSV\nfiles use tabs as separators, and usually don't bother with the\nquotes.</p>\n<p>File names should end with .csv if they're comma separated.</p>\n<p>A rough \"spec\" for CSV can be found\n<a href=\"http://tools.ietf.org/html/rfc4180\">here</a>.</p>\n<p>To load files, use the <a href=\"#/p5/loadTable\">loadTable</a> method.</p>\n<p>To save tables to your computer, use the <a href=\"#/p5/save\">save</a> method\n or the <a href=\"#/p5/saveTable\">saveTable</a> method.</p>\n\nPossible options include:\n<ul>\n<li>csv - parse the table as comma-separated values\n<li>tsv - parse the table as tab-separated values\n<li>header - this table has a header (title) row\n</ul>",
24506          "line": " src/io/p5.Table.js:11"
24507        }, {
24508          "message": "Missing item type\nMultiplies a vector by a scalar and returns a new vector.",
24509          "line": " src/math/p5.Vector.js:1611"
24510        }, {
24511          "message": "Missing item type\nDivides a vector by a scalar and returns a new vector.",
24512          "line": " src/math/p5.Vector.js:1638"
24513        }, {
24514          "message": "Missing item type\nCalculates the dot product of two vectors.",
24515          "line": " src/math/p5.Vector.js:1665"
24516        }, {
24517          "message": "Missing item type\nCalculates the cross product of two vectors.",
24518          "line": " src/math/p5.Vector.js:1679"
24519        }, {
24520          "message": "Missing item type\nCalculates the Euclidean distance between two points (considering a\npoint as a vector object).",
24521          "line": " src/math/p5.Vector.js:1693"
24522        }, {
24523          "message": "Missing item type\nLinear interpolate a vector to another vector and return the result as a\nne
24523w vector.",
24524          "line": " src/math/p5.Vector.js:1708"
24525        }, {
24526          "message": "Missing item type\nHelper function to measure ascent and descent.",
24527          "line": " src/typography/attributes.js:284"
24528        }, {
24529          "message": "Missing item type\nReturns the set of opentype glyphs for the supplied string.\n\nNote that there is not a strict one-to-one mapping between characters\nand glyphs, so the list of returned glyphs can be larger or smaller\n than the length of the given string.",
24530          "line": " src/typography/p5.Font.js:255"
24531        }, {
24532          "message": "Missing item type\nReturns an opentype path for the supplied string and position.",
24533          "line": " src/typography/p5.Font.js:270"
24534        }, {
24535          "message": "Missing item type",
24536          "line": " src/webgl/3d_primitives.js:259"
24537        }, {
24538          "message": "Missing item type\nDraws a point, a coordinate in space at the dimension of one pixel,\ngiven x, y and z coordinates. The color of the point is determined\nby the current stroke, while the point size is determined by current\nstroke weight.",
24539          "line": " src/webgl/3d_primitives.js:745"
24540        }, {
24541          "message": "Missing item type\nDraw a line given two points",
24542          "line": " src/webgl/3d_primitives.js:1162"
24543        }, {
24544          "message": "Missing item type\nParse OBJ lines into model. For reference, this is what a simple model of a\nsquare might look like:\n\nv -0.5 -0.5 0.5\nv -0.5 -0.5 -0.5\nv -0.5 0.5 -0.5\nv -0.5 0.5 0.5\n\nf 4 3 2 1",
24545          "line": " src/webgl/loading.js:135"
24546        }, {
24547          "message": "Missing item type",
24548          "line": " src/webgl/material.js:479"
24549        }, {
24550          "message": "Missing item type\nCreate a 2D array for establishing stroke connections",
24551          "line": " src/webgl/p5.Geometry.js:190"
24552        }, {
24553          "message": "Missing item type\nCreate 4 vertices for each stroke line, two at the beginning position\nand two at the end position. These vertices are displaced relative to\nthat line's normal on the GPU",
24554          "line": " src/webgl/p5.Geometry.js:211"
24555        }, {
24556          "message": "Missing item type",
24557          "line": " src/webgl/p5.Matrix.js:1"
24558        }, {
24559          "message": "Missing item type\nPRIVATE",
24560          "line": " src/webgl/p5.Matrix.js:671"
24561        }, {
24562          "message": "Missing item type\nWelcome to RendererGL Immediate Mode.\nImmediate mode is used for drawing custom shapes\nfrom a set of vertices.  Immediate Mode is activated\nwhen you call <a href=\"#/p5/beginShape\">beginShape()</a> & de-activated when you call <a href=\"#/p5/endShape\">endShape()</a>.\nImmediate mode is a style of programming borrowed\nfrom OpenGL's (now-deprecated) immediate mode.\nIt differs from p5.js' default, Retained Mode, which caches\ngeometries and buffers on the CPU to reduce the number of webgl\ndraw calls. Retained mode is more efficient & performative,\nhowever, Immediate Mode is useful for sketching quick\ngeometric ideas.",
24563          "line": " src/webgl/p5.RendererGL.Immediate.js:1"
24564        }, {
24565          "message": "Missing item type\nEnd shape drawing and render vertices to screen.",
24566          "line": " src/webgl/p5.RendererGL.Immediate.js:132"
24567        }, {
24568          "message": "Missing item type\ninitializes buffer defaults. runs each time a new geometry is\nregistered",
24569          "line": " src/webgl/p5.RendererGL.Retained.js:8"
24570        }, {
24571          "message": "Missing item type\ncreateBuffers description",
24572          "line": " src/webgl/p5.RendererGL.Retained.js:47"
24573        }, {
24574          "message": "Missing item type\nDraws buffers given a geometry key ID",
24575          "line": " src/webgl/p5.RendererGL.Retained.js:191"
24576        }, {
24577          "message": "Missing item type\nmodel view, projection, & normal\nmatrices",
24578          "line": " src/webgl/p5.RendererGL.js:83"
24579        }, {
24580          "message": "Missing item type\n[background description]",
24581          "line": " src/webgl/p5.RendererGL.js:406"
24582        }, {
24583          "message": "Missing item type\n[resize description]",
24584          "line": " src/webgl/p5.RendererGL.js:676"
24585        }, {
24586          "message": "Missing item type\nclears color and depth buffers\nwith r,g,b,a",
24587          "line": " src/webgl/p5.RendererGL.js:702"
24588        }, {
24589          "message": "Missing item type\n[translate description]",
24590          "line": " src/webgl/p5.RendererGL.js:720"
24591        }, {
24592          "message": "Missing item type\nScales the Model View Matrix by a vector",
24593          "line": " src/webgl/p5.RendererGL.js:739"
24594        }, {
24595          "message": "Missing item type\nturn a two dimensional array into one dimensional array",
24596          "line": " src/webgl/p5.RendererGL.js:1060"
24597        }, {
24598          "message": "Missing item type\nturn a p5.Vector Array into a one dimensional number array",
24599          "line": " src/webgl/p5.RendererGL.js:1097"
24600        }, {
24601          "message": "Missing item type\nensures that p5 is using a 3d renderer. throws an error if not.",
24602          "line": " src/webgl/p5.RendererGL.js:1113"
24603        }, {
24604          "message": "Missing item type\nHelper function for select and selectAll",
24605          "line": " lib/addons/p5.dom.js:168"
24606        }, {
24607          "message": "Missing item type\nHelper function for getElement and getElements.",
24608          "line": " lib/addons/p5.dom.js:184"
24609        }, {
24610          "message": "Missing item type\nHelpers for create methods.",
24611          "line": " lib/addons/p5.dom.js:348"
24612        }, {
24613          "message": "Missing item type",
24614          "line": " lib/addons/p5.dom.js:487"
24615        }, {
24616          "message": "Missing item type",
24617          "line": " lib/addons/p5.dom.js:1066"
24618        }, {
24619          "message": "Missing item type",
24620          "line": " lib/addons/p5.dom.js:1147"
24621        }, {
24622          "message": "Missing item type",
24623          "line": " lib/addons/p5.dom.js:1187"
24624        }, {
24625          "message": "Missing item type",
24626          "line": " lib/addons/p5.dom.js:2864"
24627        }, {
24628          "message": "Missing item type",
24629          "line": " lib/addons/p5.dom.js:2930"
24630        }, {
24631          "message": "Missing item type",
24632          "line": " lib/addons/p5.dom.js:2992"
24633        }, {
24634          "message": "Missing item type\np5.sound \nhttps://p5js.org/reference/#/libraries/p5.sound\n\nFrom the Processing Foundation and contributors\nhttps://github.com/processing/p5.js-sound/graphs/contributors\n\nMIT License (MIT)\nhttps://github.com/processing/p5.js-sound/blob/master/LICENSE\n\nSome of the many audio libraries & resources that inspire p5.sound:\n - TONE.js (c) Yotam Mann. Licensed under The MIT License (MIT). https://github.com/TONEnoTONE/Tone.js\n - buzz.js (c) Jay Salvat. Licensed under The MIT License (MIT). http://buzz.jaysalvat.com/\n - Boris Smus Web Audio API book, 2013. Licensed under the Apache License http://www.apache.org/licenses/LICENSE-2.0\n - wavesurfer.js https://github.com/katspaugh/wavesurfer.js\n - Web Audio Components by Jordan Santell https://github.com/web-audio-components\n - Wilm Thoben's Sound library for Processing https://github.com/processing/processing/tree/master/java/libraries/sound\n\n Web Audio API: http://w3.org/TR/webaudio/",
24635          "line": " lib/addons/p5.sound.js:46"
24636        }, {
24637          "message": "Missing item type\nDetermine which filetypes are supported (inspired by buzz.js)\nThe audio element (el) will only be used to test browser support for various audio formats",
24638          "line": " lib/addons/p5.sound.js:214"
24639        }, {
24640          "message": "Missing item type\nMaster contains AudioContext and the master sound output.",
24641          "line": " lib/addons/p5.sound.js:458"
24642        }, {
24643          "message": "Missing item type\na silent connection to the DesinationNode\nwhich will ensure that anything connected to it\nwill not be garbage collected",
24644          "line": " lib/addons/p5.sound.js:554"
24645        }, {
24646          "message": "Missing item type",
24647          "line": " lib/addons/p5.sound.js:570"
24648        }, {
24649          "message": "Missing item type\nUsed by Osc and Envelope to chain signal math",
24650          "line": " lib/addons/p5.sound.js:775"
24651        }, {
24652          "message": "Missing item type\nThis is a helper function that the p5.SoundFile calls to load\nitself. Accepts a callback (the name of another function)\nas an optional parameter.",
24653          "line": " lib/addons/p5.sound.js:1171"
24654        }, {
24655          "message": "Missing item type\nStop playback on all of this soundfile's sources.",
24656          "line": " lib/addons/p5.sound.js:1591"
24657        }, {
24658          "message": "Missing item type",
24659          "line": " lib/addons/p5.sound.js:2030"
24660        }, {
24661          "message": "Missing item type",
24662          "line": " lib/addons/p5.sound.js:2313"
24663        }, {
24664          "message": "Missing item type",
24665          "line": " lib/addons/p5.sound.js:3409"
24666        }, {
24667          "message": "Missing item type",
24668          "line": " lib/addons/p5.sound.js:3786"
24669        }, {
24670          "message": "Missing item type",
24671          "line": " lib/addons/p5.sound.js:3807"
24672        }, {
24673          "message": "Missing item type",
24674          "line": " lib/addons/p5.sound.js:3866"
24675        }, {
24676          "message": "Missing item type",
24677          "line": " lib/addons/p5.sound.js:4184"
24678        }, {
24679          "message": "Missing item type",
24680          "line": " lib/addons/p5.sound.js:4356"
24681        }, {
24682          "message": "Missing item type",
24683          "line": " lib/addons/p5.sound.js:4514"
24684        }, {
24685          "message": "Missing item type",
24686          "line": " lib/addons/p5.sound.js:4555"
24687        }, {
24688          "message": "Missing item type",
24689          "line": " lib/addons/p5.sound.js:4625"
24690        }, {
24691          "message": "Missing item type",
24692          "line": " lib/addons/p5.sound.js:4813"
24693        }, {
24694          "message": "Missing item type",
24695          "line": " lib/addons/p5.sound.js:4870"
24696        }, {
24697          "message": "Missing item type",
24698          "line": " lib/addons/p5.sound.js:5038"
24699        }, {
24700          "message": "Missing item type",
24701          "line": " lib/addons/p5.sound.js:5086"
24702        }, {
24703          "message": "Missing item type",
24704          "line": " lib/addons/p5.sound.js:5117"
24705        }, {
24706          "message": "Missing item type",
24707          "line": " lib/addons/p5.sound.js:5138"
24708        }, {
24709          "message": "Missing item type",
24710          "line": " lib/addons/p5.sound.js:5158"
24711        }, {
24712          "message": "Missing item type",
24713          "line": " lib/addons/p5.sound.js:5871"
24714        }, {
24715          "message": "Missing item type",
24716          "line": " lib/addons/p5.sound.js:6074"
24717        }, {
24718          "message": "Missing item type",
24719          "line": " lib/addons/p5.sound.js:7744"
24720        }, {
24721          "message": "Missing item type",
24722          "line": " lib/addons/p5.sound.js:7760"
24723        }, {
24724          "message": "Missing item type",
24725          "line": " lib/addons/p5.sound.js:7784"
24726        }, {
24727          "message": "Missing item type",
24728          "line": " lib/addons/p5.sound.js:7810"
24729        }, {
24730          "message": "Missing item type",
24731          "line": " lib/addons/p5.sound.js:7832"
24732        }, {
24733          "message": "Missing item type",
24734          "line": " lib/addons/p5.sound.js:7854"
24735        }, {
24736          "message": "Missing item type",
24737          "line": " lib/addons/p5.sound.js:7900"
24738        }, {
24739          "message": "Missing item type",
24740          "line": " lib/addons/p5.sound.js:7931"
24741        }, {
24742          "message": "Missing item type",
24743          "line": " lib/addons/p5.sound.js:7949"
24744        }, {
24745          "message": "Missing item type",
24746          "line": " lib/addons/p5.sound.js:8286"
24747        }, {
24748          "message": "Missing item type",
24749          "line": " lib/addons/p5.sound.js:8308"
24750        }, {
24751          "message": "Missing item type\nThe p5.Effect class is built\n \tusing Tone.js CrossFade",
24752          "line": " lib/addons/p5.sound.js:8378"
24753        }, {
24754          "message": "Missing item type\nIn classes that extend\np5.Effect, connect effect nodes\nto the wet parameter",
24755          "line": " lib/addons/p5.sound.js:8384"
24756        }, {
24757          "message": "Missing item type\nEQFilter extends p5.Filter with constraints\nnecessary for the p5.EQ",
24758          "line": " lib/addons/p5.sound.js:8773"
24759        }, {
24760          "message": "Missing item type\nInspired by Simple Reverb by Jordan Santell\nhttps://github.com/web-audio-components/simple-reverb/blob/master/index.js\n\nUtility function for building an impulse response\nbased on the module parameters.",
24761          "line": " lib/addons/p5.sound.js:9883"
24762        }, {
24763          "message": "Missing item type\nPrivate method to load a buffer as an Impulse Response,\nassign it to the convolverNode, and add to the Array of .impulses.",
24764          "line": " lib/addons/p5.sound.js:10050"
24765        }, {
24766          "message": "Missing item type",
24767          "line": " lib/addons/p5.sound.js:10234"
24768        }, {
24769          "message": "Missing item type",
24770          "line": " lib/addons/p5.sound.js:10259"
24771        }, {
24772          "message": "Missing item type\nmusicalTimeMode variables\nmodify these only when the interval is specified in musicalTime format as a string",
24773          "line": " lib/addons/p5.sound.js:10983"
24774        }, {
24775          "message": "Missing item type\nDo not initiate the callback if timeFromNow is < 0\nThis ususually occurs for a few milliseconds when the page\
24775nis not fully loaded\n\nThe callback should only be called until maxIterations is reached",
24776          "line": " lib/addons/p5.sound.js:10999"
24777        }, {
24778          "message": "Missing item type\ncallback invoked when the recording is over",
24779          "line": " lib/addons/p5.sound.js:11489"
24780        }, {
24781          "message": "Missing item type\ninternal method called on audio process",
24782          "line": " lib/addons/p5.sound.js:11575"
24783        }, {
24784          "message": "Missing item type\nPrivate method to ensure accurate values of this._voicesInUse\nAny time a new value is scheduled, it is necessary to increment all subsequent\nscheduledValues after attack, and decrement all subsequent\nscheduledValues after release",
24785          "line": " lib/addons/p5.sound.js:12621"
24786        }, {
24787          "message": "Missing item type\np5.sound \nhttps://p5js.org/reference/#/libraries/p5.sound\n\nFrom the Processing Foundation and contributors\nhttps://github.com/processing/p5.js-sound/graphs/contributors\n\nMIT License (MIT)\nhttps://github.com/processing/p5.js-sound/blob/master/LICENSE\n\nSome of the many audio libraries & resources that inspire p5.sound:\n - TONE.js (c) Yotam Mann. Licensed under The MIT License (MIT). https://github.com/TONEnoTONE/Tone.js\n - buzz.js (c) Jay Salvat. Licensed under The MIT License (MIT). http://buzz.jaysalvat.com/\n - Boris Smus Web Audio API book, 2013. Licensed under the Apache License http://www.apache.org/licenses/LICENSE-2.0\n - wavesurfer.js https://github.com/katspaugh/wavesurfer.js\n - Web Audio Components by Jordan Santell https://github.com/web-audio-components\n - Wilm Thoben's Sound library for Processing https://github.com/processing/processing/tree/master/java/libraries/sound\n\n Web Audio API: http://w3.org/TR/webaudio/",
24788          "line": " lib/addons/p5.sound.min.js:3"
24789        }],
24790        "consts": {
24791          "RGB": ["p5.colorMode"],
24792          "HSB": ["p5.colorMode"],
24793          "HSL": ["p5.colorMode"],
24794          "CHORD": ["p5.arc"],
24795          "PIE": ["p5.arc"],
24796          "OPEN": ["p5.arc"],
24797          "CENTER": ["p5.ellipseMode", "p5.rectMode", "p5.imageMode", "p5.textAlign"],
24798          "RADIUS": ["p5.ellipseMode", "p5.rectMode"],
24799          "CORNER": ["p5.ellipseMode", "p5.rectMode", "p5.imageMode"],
24800          "CORNERS": ["p5.ellipseMode", "p5.rectMode", "p5.imageMode"],
24801          "SQUARE": ["p5.strokeCap"],
24802          "PROJECT": ["p5.strokeCap"],
24803          "ROUND": ["p5.strokeCap", "p5.strokeJoin"],
24804          "MITER": ["p5.strokeJoin"],
24805          "BEVEL": ["p5.strokeJoin"],
24806          "POINTS": ["p5.beginShape"],
24807          "LINES": ["p5.beginShape"],
24808          "TRIANGLES": ["p5.beginShape"],
24809          "TRIANGLE_FAN": ["p5.beginShape"],
24810          "TRIANGLE_STRIP": ["p5.beginShape"],
24811          "QUADS": ["p5.beginShape"],
24812          "QUAD_STRIP": ["p5.beginShape"],
24813          "CLOSE": ["p5.endShape"],
24814          "ARROW": ["p5.cursor"],
24815          "CROSS": ["p5.cursor"],
24816          "HAND": ["p5.cursor"],
24817          "MOVE": ["p5.cursor"],
24818          "TEXT": ["p5.cursor"],
24819          "P2D": ["p5.createCanvas", "p5.createGraphics"],
24820          "WEBGL": ["p5.createCanvas", "p5.createGraphics"],
24821          "BLEND": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24822          "DARKEST": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24823          "LIGHTEST": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24824          "DIFFERENCE": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24825          "MULTIPLY": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24826          "EXCLUSION": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24827          "SCREEN": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24828          "REPLACE": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24829          "OVERLAY": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24830          "HARD_LIGHT": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24831          "SOFT_LIGHT": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24832          "DODGE": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24833          "BURN": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24834          "ADD": ["p5.blendMode", "p5.Image.blend", "p5.blend"],
24835          "NORMAL": ["p5.blendMode", "p5.Image.blend", "p5.blend", "p5.textStyle", "p5.textureMode"],
24836          "THRESHOLD": ["p5.Image.filter", "p5.filter"],
24837          "GRAY": ["p5.Image.filter", "p5.filter"],
24838          "OPAQUE": ["p5.Image.filter", "p5.filter"],
24839          "INVERT": ["p5.Image.filter", "p5.filter"],
24840          "POSTERIZE": ["p5.Image.filter", "p5.filter"],
24841          "BLUR": ["p5.Image.filter", "p5.filter"],
24842          "ERODE": ["p5.Image.filter", "p5.filter"],
24843          "DILATE": ["p5.Image.filter", "p5.filter"],
24844          "RADIANS": ["p5.angleMode"],
24845          "DEGREES": ["p5.angleMode"],
24846          "LEFT": ["p5.textAlign"],
24847          "RIGHT": ["p5.textAlign"],
24848          "TOP": ["p5.textAlign"],
24849          "BOTTOM": ["p5.textAlign"],
24850          "BASELINE": ["p5.textAlign"],
24851          "ITALIC": ["p5.textStyle"],
24852          "BOLD": ["p5.textStyle"],
24853          "BOLDITALIC": ["p5.textStyle"],
24854          "IMAGE": ["p5.textureMode"],
24855          "VIDEO": ["p5.createCapture"],
24856          "AUDIO": ["p5.createCapture"]
24857        }
24858      };
24859    }, {}],
vendor: 4,382 bytes, lines 24860-24979
24860    2: [function (_dereq_, module, exports) {
24861      'use strict';
24862
24863      exports.byteLength = byteLength;
24864      exports.toByteArray = toByteArray;
24865      exports.fromByteArray = fromByteArray;
24866      var lookup = [];
24867      var revLookup = [];
24868      var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array;
24869      var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
24870
24871      for (var i = 0, len = code.length; i < len; ++i) {
24872        lookup[i] = code[i];
24873        revLookup[code.charCodeAt(i)] = i;
24874      } // Support decoding URL-safe base64 strings, as Node.js does.
24875      // See: https://en.wikipedia.org/wiki/Base64#URL_applications
24876
24877
24878      revLookup['-'.charCodeAt(0)] = 62;
24879      revLookup['_'.charCodeAt(0)] = 63;
24880
24881      function getLens(b64) {
24882        var len = b64.length;
24883
24884        if (len % 4 > 0) {
24885          throw new Error('Invalid string. Length must be a multiple of 4');
24886        } // Trim off extra bytes after placeholder bytes are found
24887        // See: https://github.com/beatgammit/base64-js/issues/42
24888
24889
24890        var validLen = b64.indexOf('=');
24891        if (validLen === -1) validLen = len;
24892        var placeHoldersLen = validLen === len ? 0 : 4 - validLen % 4;
24893        return [validLen, placeHoldersLen];
24894      } // base64 is 4/3 + up to two characters of the original data
24895
24896
24897      function byteLength(b64) {
24898        var lens = getLens(b64);
24899        var validLen = lens[0];
24900        var placeHoldersLen = lens[1];
24901        return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen;
24902      }
24903
24904      function _byteLength(b64, validLen, placeHoldersLen) {
24905        return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen;
24906      }
24907
24908      function toByteArray(b64) {
24909        var tmp;
24910        var lens = getLens(b64);
24911        var validLen = lens[0];
24912        var placeHoldersLen = lens[1];
24913        var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen));
24914        var curByte = 0; // if there are placeholders, only get up to the last complete 4 chars
24915
24916        var len = placeHoldersLen > 0 ? validLen - 4 : validLen;
24917
24918        for (var i = 0; i < len; i += 4) {
24919          tmp = revLookup[b64.charCodeAt(i)] << 18 | revLookup[b64.charCodeAt(i + 1)] << 12 | revLookup[b64.charCodeAt(i + 2)] << 6 | revLookup[b64.charCodeAt(i + 3)];
24920          arr[curByte++] = tmp >> 16 & 0xFF;
24921          arr[curByte++] = tmp >> 8 & 0xFF;
24922          arr[curByte++] = tmp & 0xFF;
24923        }
24924
24925        if (placeHoldersLen === 2) {
24926          tmp = revLookup[b64.charCodeAt(i)] << 2 | revLookup[b64.charCodeAt(i + 1)] >> 4;
24927          arr[curByte++] = tmp & 0xFF;
24928        }
24929
24930        if (placeHoldersLen === 1) {
24931          tmp = revLookup[b64.charCodeAt(i)] << 10 | revLookup[b64.charCodeAt(i + 1)] << 4 | revLookup[b64.charCodeAt(i + 2)] >> 2;
24932          arr[curByte++] = tmp >> 8 & 0xFF;
24933          arr[curByte++] = tmp & 0xFF;
24934        }
24935
24936        return arr;
24937      }
24938
24939      function tripletToBase64(num) {
24940        return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];
24941      }
24942
24943      function encodeChunk(uint8, start, end) {
24944        var tmp;
24945        var output = [];
24946
24947        for (var i = start; i < end; i += 3) {
24948          tmp = (uint8[i] << 16 & 0xFF0000) + (uint8[i + 1] << 8 & 0xFF00) + (uint8[i + 2] & 0xFF);
24949          output.push(tripletToBase64(tmp));
24950        }
24951
24952        return output.join('');
24953      }
24954
24955      function fromByteArray(uint8) {
24956        var tmp;
24957        var len = uint8.length;
24958        var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes
24959
24960        var parts = [];
24961        var maxChunkLength = 16383; // must be multiple of 3
24962        // go through the array every three bytes, we'll deal with trailing stuff later
24963
24964        for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
24965          parts.push(encodeChunk(uint8, i, i + maxChunkLength > len2 ? len2 : i + maxChunkLength));
24966        } // pad the end with zeros, but make sure to not forget the extra bytes
24967
24968
24969        if (extraBytes === 1) {
24970          tmp = uint8[len - 1];
24971          parts.push(lookup[tmp >> 2] + lookup[tmp << 4 & 0x3F] + '==');
24972        } else if (extraBytes === 2) {
24973          tmp = (uint8[len - 2] << 8) + uint8[len - 1];
24974          parts.push(lookup[tmp >> 10] + lookup[tmp >> 4 & 0x3F] + lookup[tmp << 2 & 0x3F] + '=');
24975        }
24976
24977        return parts.join('');
24978      }
24979    }, {}],
vendor: 6,512 bytes, lines 24980-25158
24980    3: [function (_dereq_, module, exports) {}, {}],
24981    4: [function (_dereq_, module, exports) {
24982      /*!
24983       * The buffer module from node.js, for the browser.
24984       *
24985       * @author   Feross Aboukhadijeh <https://feross.org>
24986       * @license  MIT
24987       */
24988
24989      /* eslint-disable no-proto */
24990      'use strict';
24991
24992      var base64 = _dereq_('base64-js');
24993
24994      var ieee754 = _dereq_('ieee754');
24995
24996      exports.Buffer = Buffer;
24997      exports.SlowBuffer = SlowBuffer;
24998      exports.INSPECT_MAX_BYTES = 50;
24999      var K_MAX_LENGTH = 0x7fffffff;
25000      exports.kMaxLength = K_MAX_LENGTH;
25001      /**
25002       * If `Buffer.TYPED_ARRAY_SUPPORT`:
25003       *   === true    Use Uint8Array implementation (fastest)
25004       *   === false   Print warning and recommend using `buffer` v4.x which has an Object
25005       *               implementation (most compatible, even IE6)
25006       *
25007       * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
25008       * Opera 11.6+, iOS 4.2+.
25009       *
25010       * We report that the browser does not support typed arrays if the are not subclassable
25011       * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`
25012       * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support
25013       * for __proto__ and has a buggy typed array implementation.
25014       */
25015
25016      Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport();
25017
25018      if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && typeof console.error === 'function') {
25019        console.error('This browser lacks typed array (Uint8Array) support which is required by ' + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.');
25020      }
25021
25022      function typedArraySupport() {
25023        // Can typed array instances can be augmented?
25024        try {
25025          var arr = new Uint8Array(1);
25026          arr.__proto__ = {
25027            __proto__: Uint8Array.prototype,
25028            foo: function () {
25029              return 42;
25030            }
25031          };
25032          return arr.foo() === 42;
25033        } catch (e) {
25034          return false;
25035        }
25036      }
25037
25038      Object.defineProperty(Buffer.prototype, 'parent', {
25039        enumerable: true,
25040        get: function () {
25041          if (!Buffer.isBuffer(this)) return undefined;
25042          return this.buffer;
25043        }
25044      });
25045      Object.defineProperty(Buffer.prototype, 'offset', {
25046        enumerable: true,
25047        get: function () {
25048          if (!Buffer.isBuffer(this)) return undefined;
25049          return this.byteOffset;
25050        }
25051      });
25052
25053      function createBuffer(length) {
25054        if (length > K_MAX_LENGTH) {
25055          throw new RangeError('The value "' + length + '" is invalid for option "size"');
25056        } // Return an augmented `Uint8Array` instance
25057
25058
25059        var buf = new Uint8Array(length);
25060        buf.__proto__ = Buffer.prototype;
25061        return buf;
25062      }
25063      /**
25064       * The Buffer constructor returns instances of `Uint8Array` that have their
25065       * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
25066       * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
25067       * and the `Uint8Array` methods. Square bracket notation works as expected -- it
25068       * returns a single octet.
25069       *
25070       * The `Uint8Array` prototype remains unmodified.
25071       */
25072
25073
25074      function Buffer(arg, encodingOrOffset, length) {
25075        // Common case.
25076        if (typeof arg === 'number') {
25077          if (typeof encodingOrOffset === 'string') {
25078            throw new TypeError('The "string" argument must be of type string. Received type number');
25079          }
25080
25081          return allocUnsafe(arg);
25082        }
25083
25084        return from(arg, encodingOrOffset, length);
25085      } // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
25086
25087
25088      if (typeof Symbol !== 'undefined' && Symbol.species != null && Buffer[Symbol.species] === Buffer) {
25089        Object.defineProperty(Buffer, Symbol.species, {
25090          value: null,
25091          configurable: true,
25092          enumerable: false,
25093          writable: false
25094        });
25095      }
25096
25097      Buffer.poolSize = 8192; // not used by this implementation
25098
25099      function from(value, encodingOrOffset, length) {
25100        if (typeof value === 'string') {
25101          return fromString(value, encodingOrOffset);
25102        }
25103
25104        if (ArrayBuffer.isView(value)) {
25105          return fromArrayLike(value);
25106        }
25107
25108        if (value == null) {
25109          throw TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + 'or Array-like Object. Received type ' + typeof value);
25110        }
25111
25112        if (isInstance(value, ArrayBuffer) || value && isInstance(value.buffer, ArrayBuffer)) {
25113          return fromArrayBuffer(value, encodingOrOffset, length);
25114        }
25115
25116        if (typeof value === 'number') {
25117          throw new TypeError('The "value" argument must not be of type number. Received type number');
25118        }
25119
25120        var valueOf = value.valueOf && value.valueOf();
25121
25122        if (valueOf != null && valueOf !== value) {
25123          return Buffer.from(valueOf, encodingOrOffset, length);
25124        }
25125
25126        var b = fromObject(value);
25127        if (b) return b;
25128
25129        if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && typeof value[Symbol.toPrimitive] === 'function') {
25130          return Buffer.from(value[Symbol.toPrimitive]('string'), encodingOrOffset, length);
25131        }
25132
25133        throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + 'or Array-like Object. Received type ' + typeof value);
25134      }
25135      /**
25136       * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
25137       * if value is a number.
25138       * Buffer.from(str[, encoding])
25139       * Buffer.from(array)
25140       * Buffer.from(buffer)
25141       * Buffer.from(arrayBuffer[, byteOffset[, length]])
25142       **/
25143
25144
25145      Buffer.from = function (value, encodingOrOffset, length) {
25146        return from(value, encodingOrOffset, length);
25147      }; // Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:
25148      // https://github.com/feross/buffer/pull/148
25149
25150
25151      Buffer.prototype.__proto__ = Uint8Array.prototype;
25152      Buffer.__proto__ = Uint8Array;
25153
25154      function assertSize(size) {
25155        if (typeof size !== 'number') {
25156          throw new TypeError('"size" argument must be of type number');
25157        } else if (size < 0) {
25158          throw new RangeError('The value "' + size + '" is invali
vendor: 4,462 bytes, lines 25158-25313
25158d for option "size"');
25159        }
25160      }
25161
25162      function alloc(size, fill, encoding) {
25163        assertSize(size);
25164
25165        if (size <= 0) {
25166          return createBuffer(size);
25167        }
25168
25169        if (fill !== undefined) {
25170          // Only pay attention to encoding if it's a string. This
25171          // prevents accidentally sending in a number that would
25172          // be interpretted as a start offset.
25173          return typeof encoding === 'string' ? createBuffer(size).fill(fill, encoding) : createBuffer(size).fill(fill);
25174        }
25175
25176        return createBuffer(size);
25177      }
25178      /**
25179       * Creates a new filled Buffer instance.
25180       * alloc(size[, fill[, encoding]])
25181       **/
25182
25183
25184      Buffer.alloc = function (size, fill, encoding) {
25185        return alloc(size, fill, encoding);
25186      };
25187
25188      function allocUnsafe(size) {
25189        assertSize(size);
25190        return createBuffer(size < 0 ? 0 : checked(size) | 0);
25191      }
25192      /**
25193       * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
25194       * */
25195
25196
25197      Buffer.allocUnsafe = function (size) {
25198        return allocUnsafe(size);
25199      };
25200      /**
25201       * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
25202       */
25203
25204
25205      Buffer.allocUnsafeSlow = function (size) {
25206        return allocUnsafe(size);
25207      };
25208
25209      function fromString(string, encoding) {
25210        if (typeof encoding !== 'string' || encoding === '') {
25211          encoding = 'utf8';
25212        }
25213
25214        if (!Buffer.isEncoding(encoding)) {
25215          throw new TypeError('Unknown encoding: ' + encoding);
25216        }
25217
25218        var length = byteLength(string, encoding) | 0;
25219        var buf = createBuffer(length);
25220        var actual = buf.write(string, encoding);
25221
25222        if (actual !== length) {
25223          // Writing a hex string, for example, that contains invalid characters will
25224          // cause everything after the first invalid character to be ignored. (e.g.
25225          // 'abxxcd' will be treated as 'ab')
25226          buf = buf.slice(0, actual);
25227        }
25228
25229        return buf;
25230      }
25231
25232      function fromArrayLike(array) {
25233        var length = array.length < 0 ? 0 : checked(array.length) | 0;
25234        var buf = createBuffer(length);
25235
25236        for (var i = 0; i < length; i += 1) {
25237          buf[i] = array[i] & 255;
25238        }
25239
25240        return buf;
25241      }
25242
25243      function fromArrayBuffer(array, byteOffset, length) {
25244        if (byteOffset < 0 || array.byteLength < byteOffset) {
25245          throw new RangeError('"offset" is outside of buffer bounds');
25246        }
25247
25248        if (array.byteLength < byteOffset + (length || 0)) {
25249          throw new RangeError('"length" is outside of buffer bounds');
25250        }
25251
25252        var buf;
25253
25254        if (byteOffset === undefined && length === undefined) {
25255          buf = new Uint8Array(array);
25256        } else if (length === undefined) {
25257          buf = new Uint8Array(array, byteOffset);
25258        } else {
25259          buf = new Uint8Array(array, byteOffset, length);
25260        } // Return an augmented `Uint8Array` instance
25261
25262
25263        buf.__proto__ = Buffer.prototype;
25264        return buf;
25265      }
25266
25267      function fromObject(obj) {
25268        if (Buffer.isBuffer(obj)) {
25269          var len = checked(obj.length) | 0;
25270          var buf = createBuffer(len);
25271
25272          if (buf.length === 0) {
25273            return buf;
25274          }
25275
25276          obj.copy(buf, 0, 0, len);
25277          return buf;
25278        }
25279
25280        if (obj.length !== undefined) {
25281          if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) {
25282            return createBuffer(0);
25283          }
25284
25285          return fromArrayLike(obj);
25286        }
25287
25288        if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
25289          return fromArrayLike(obj.data);
25290        }
25291      }
25292
25293      function checked(length) {
25294        // Note: cannot use `length < K_MAX_LENGTH` here because that fails when
25295        // length is NaN (which is otherwise coerced to zero.)
25296        if (length >= K_MAX_LENGTH) {
25297          throw new RangeError('Attempt to allocate Buffer larger than maximum ' + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes');
25298        }
25299
25300        return length | 0;
25301      }
25302
25303      function SlowBuffer(length) {
25304        if (+length != length) {
25305          // eslint-disable-line eqeqeq
25306          length = 0;
25307        }
25308
25309        return Buffer.alloc(+length);
25310      }
25311
25312      Buffer.isBuffer = function isBuffer(b) {
25313        return b != null && b._isBuffer === true && b !== Buffer.prototype;
vendor: 11,805 bytes, lines 25313-25718
25313 // so Buffer.isBuffer(Buffer.prototype) will be false
25314      };
25315
25316      Buffer.compare = function compare(a, b) {
25317        if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength);
25318        if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength);
25319
25320        if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
25321          throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');
25322        }
25323
25324        if (a === b) return 0;
25325        var x = a.length;
25326        var y = b.length;
25327
25328        for (var i = 0, len = Math.min(x, y); i < len; ++i) {
25329          if (a[i] !== b[i]) {
25330            x = a[i];
25331            y = b[i];
25332            break;
25333          }
25334        }
25335
25336        if (x < y) return -1;
25337        if (y < x) return 1;
25338        return 0;
25339      };
25340
25341      Buffer.isEncoding = function isEncoding(encoding) {
25342        switch (String(encoding).toLowerCase()) {
25343          case 'hex':
25344          case 'utf8':
25345          case 'utf-8':
25346          case 'ascii':
25347          case 'latin1':
25348          case 'binary':
25349          case 'base64':
25350          case 'ucs2':
25351          case 'ucs-2':
25352          case 'utf16le':
25353          case 'utf-16le':
25354            return true;
25355
25356          default:
25357            return false;
25358        }
25359      };
25360
25361      Buffer.concat = function concat(list, length) {
25362        if (!Array.isArray(list)) {
25363          throw new TypeError('"list" argument must be an Array of Buffers');
25364        }
25365
25366        if (list.length === 0) {
25367          return Buffer.alloc(0);
25368        }
25369
25370        var i;
25371
25372        if (length === undefined) {
25373          length = 0;
25374
25375          for (i = 0; i < list.length; ++i) {
25376            length += list[i].length;
25377          }
25378        }
25379
25380        var buffer = Buffer.allocUnsafe(length);
25381        var pos = 0;
25382
25383        for (i = 0; i < list.length; ++i) {
25384          var buf = list[i];
25385
25386          if (isInstance(buf, Uint8Array)) {
25387            buf = Buffer.from(buf);
25388          }
25389
25390          if (!Buffer.isBuffer(buf)) {
25391            throw new TypeError('"list" argument must be an Array of Buffers');
25392          }
25393
25394          buf.copy(buffer, pos);
25395          pos += buf.length;
25396        }
25397
25398        return buffer;
25399      };
25400
25401      function byteLength(string, encoding) {
25402        if (Buffer.isBuffer(string)) {
25403          return string.length;
25404        }
25405
25406        if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) {
25407          return string.byteLength;
25408        }
25409
25410        if (typeof string !== 'string') {
25411          throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + 'Received type ' + typeof string);
25412        }
25413
25414        var len = string.length;
25415        var mustMatch = arguments.length > 2 && arguments[2] === true;
25416        if (!mustMatch && len === 0) return 0; // Use a for loop to avoid recursion
25417
25418        var loweredCase = false;
25419
25420        for (;;) {
25421          switch (encoding) {
25422            case 'ascii':
25423            case 'latin1':
25424            case 'binary':
25425              return len;
25426
25427            case 'utf8':
25428            case 'utf-8':
25429              return utf8ToBytes(string).length;
25430
25431            case 'ucs2':
25432            case 'ucs-2':
25433            case 'utf16le':
25434            case 'utf-16le':
25435              return len * 2;
25436
25437            case 'hex':
25438              return len >>> 1;
25439
25440            case 'base64':
25441              return base64ToBytes(string).length;
25442
25443            default:
25444              if (loweredCase) {
25445                return mustMatch ? -1 : utf8ToBytes(string).length; // assume utf8
25446              }
25447
25448              encoding = ('' + encoding).toLowerCase();
25449              loweredCase = true;
25450          }
25451        }
25452      }
25453
25454      Buffer.byteLength = byteLength;
25455
25456      function slowToString(encoding, start, end) {
25457        var loweredCase = false; // No need to verify that "this.length <= MAX_UINT32" since it's a read-only
25458        // property of a typed array.
25459        // This behaves neither like String nor Uint8Array in that we set start/end
25460        // to their upper/lower bounds if the value passed is out of range.
25461        // undefined is handled specially as per ECMA-262 6th Edition,
25462        // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
25463
25464        if (start === undefined || start < 0) {
25465          start = 0;
25466        } // Return early if start > this.length. Done here to prevent potential uint32
25467        // coercion fail below.
25468
25469
25470        if (start > this.length) {
25471          return '';
25472        }
25473
25474        if (end === undefined || end > this.length) {
25475          end = this.length;
25476        }
25477
25478        if (end <= 0) {
25479          return '';
25480        } // Force coersion to uint32. This will also coerce falsey/NaN values to 0.
25481
25482
25483        end >>>= 0;
25484        start >>>= 0;
25485
25486        if (end <= start) {
25487          return '';
25488        }
25489
25490        if (!encoding) encoding = 'utf8';
25491
25492        while (true) {
25493          switch (encoding) {
25494            case 'hex':
25495              return hexSlice(this, start, end);
25496
25497            case 'utf8':
25498            case 'utf-8':
25499              return utf8Slice(this, start, end);
25500
25501            case 'ascii':
25502              return asciiSlice(this, start, end);
25503
25504            case 'latin1':
25505            case 'binary':
25506              return latin1Slice(this, start, end);
25507
25508            case 'base64':
25509              return base64Slice(this, start, end);
25510
25511            case 'ucs2':
25512            case 'ucs-2':
25513            case 'utf16le':
25514            case 'utf-16le':
25515              return utf16leSlice(this, start, end);
25516
25517            default:
25518              if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding);
25519              encoding = (encoding + '').toLowerCase();
25520              loweredCase = true;
25521          }
25522        }
25523      } // This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)
25524      // to detect a Buffer instance. It's not possible to use `instanceof Buffer`
25525      // reliably in a browserify context because there could be multiple different
25526      // copies of the 'buffer' package in use. This method works even for Buffer
25527      // instances that were created from another copy of the `buffer` package.
25528      // See: https://github.com/feross/buffer/issues/154
25529
25530
25531      Buffer.prototype._isBuffer = true;
25532
25533      function swap(b, n, m) {
25534        var i = b[n];
25535        b[n] = b[m];
25536        b[m] = i;
25537      }
25538
25539      Buffer.prototype.swap16 = function swap16() {
25540        var len = this.length;
25541
25542        if (len % 2 !== 0) {
25543          throw new RangeError('Buffer size must be a multiple of 16-bits');
25544        }
25545
25546        for (var i = 0; i < len; i += 2) {
25547          swap(this, i, i + 1);
25548        }
25549
25550        return this;
25551      };
25552
25553      Buffer.prototype.swap32 = function swap32() {
25554        var len = this.length;
25555
25556        if (len % 4 !== 0) {
25557          throw new RangeError('Buffer size must be a multiple of 32-bits');
25558        }
25559
25560        for (var i = 0; i < len; i += 4) {
25561          swap(this, i, i + 3);
25562          swap(this, i + 1, i + 2);
25563        }
25564
25565        return this;
25566      };
25567
25568      Buffer.prototype.swap64 = function swap64() {
25569        var len = this.length;
25570
25571        if (len % 8 !== 0) {
25572          throw new RangeError('Buffer size must be a multiple of 64-bits');
25573        }
25574
25575        for (var i = 0; i < len; i += 8) {
25576          swap(this, i, i + 7);
25577          swap(this, i + 1, i + 6);
25578          swap(this, i + 2, i + 5);
25579          swap(this, i + 3, i + 4);
25580        }
25581
25582        return this;
25583      };
25584
25585      Buffer.prototype.toString = function toString() {
25586        var length = this.length;
25587        if (length === 0) return '';
25588        if (arguments.length === 0) return utf8Slice(this, 0, length);
25589        return slowToString.apply(this, arguments);
25590      };
25591
25592      Buffer.prototype.toLocaleString = Buffer.prototype.toString;
25593
25594      Buffer.prototype.equals = function equals(b) {
25595        if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer');
25596        if (this === b) return true;
25597        return Buffer.compare(this, b) === 0;
25598      };
25599
25600      Buffer.prototype.inspect = function inspect() {
25601        var str = '';
25602        var max = exports.INSPECT_MAX_BYTES;
25603        str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim();
25604        if (this.length > max) str += ' ... ';
25605        return '<Buffer ' + str + '>';
25606      };
25607
25608      Buffer.prototype.compare = function compare(target, start, end, thisStart, thisEnd) {
25609        if (isInstance(target, Uint8Array)) {
25610          target = Buffer.from(target, target.offset, target.byteLength);
25611        }
25612
25613        if (!Buffer.isBuffer(target)) {
25614          throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. ' + 'Received type ' + typeof target);
25615        }
25616
25617        if (start === undefined) {
25618          start = 0;
25619        }
25620
25621        if (end === undefined) {
25622          end = target ? target.length : 0;
25623        }
25624
25625        if (thisStart === undefined) {
25626          thisStart = 0;
25627        }
25628
25629        if (thisEnd === undefined) {
25630          thisEnd = this.length;
25631        }
25632
25633        if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
25634          throw new RangeError('out of range index');
25635        }
25636
25637        if (thisStart >= thisEnd && start >= end) {
25638          return 0;
25639        }
25640
25641        if (thisStart >= thisEnd) {
25642          return -1;
25643        }
25644
25645        if (start >= end) {
25646          return 1;
25647        }
25648
25649        start >>>= 0;
25650        end >>>= 0;
25651        thisStart >>>= 0;
25652        thisEnd >>>= 0;
25653        if (this === target) return 0;
25654        var x = thisEnd - thisStart;
25655        var y = end - start;
25656        var len = Math.min(x, y);
25657        var thisCopy = this.slice(thisStart, thisEnd);
25658        var targetCopy = target.slice(start, end);
25659
25660        for (var i = 0; i < len; ++i) {
25661          if (thisCopy[i] !== targetCopy[i]) {
25662            x = thisCopy[i];
25663            y = targetCopy[i];
25664            break;
25665          }
25666        }
25667
25668        if (x < y) return -1;
25669        if (y < x) return 1;
25670        return 0;
25671      }; // Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
25672      // OR the last index of `val` in `buffer` at offset <= `byteOffset`.
25673      //
25674      // Arguments:
25675      // - buffer - a Buffer to search
25676      // - val - a string, Buffer, or number
25677      // - byteOffset - an index into `buffer`; will be clamped to an int32
25678      // - encoding - an optional encoding, relevant is val is a string
25679      // - dir - true for indexOf, false for lastIndexOf
25680
25681
25682      function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) {
25683        // Empty buffer means no match
25684        if (buffer.length === 0) return -1; // Normalize byteOffset
25685
25686        if (typeof byteOffset === 'string') {
25687          encoding = byteOffset;
25688          byteOffset = 0;
25689        } else if (byteOffset > 0x7fffffff) {
25690          byteOffset = 0x7fffffff;
25691        } else if (byteOffset < -0x80000000) {
25692          byteOffset = -0x80000000;
25693        }
25694
25695        byteOffset = +byteOffset; // Coerce to Number.
25696
25697        if (numberIsNaN(byteOffset)) {
25698          // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
25699          byteOffset = dir ? 0 : buffer.length - 1;
25700        } // Normalize byteOffset: negative offsets start from the end of the buffer
25701
25702
25703        if (byteOffset < 0) byteOffset = buffer.length + byteOffset;
25704
25705        if (byteOffset >= buffer.length) {
25706          if (dir) return -1;else byteOffset = buffer.length - 1;
25707        } else if (byteOffset < 0) {
25708          if (dir) byteOffset = 0;else return -1;
25709        } // Normalize val
25710
25711
25712        if (typeof val === 'string') {
25713          val = Buffer.from(val, encoding);
25714        } // Finally, search either indexOf (if dir is true) or lastIndexOf
25715
25716
25717        if (Buffer.isBuffer(val)) {
25718          // Special case: looking for empty string/buffer always fail
vendor: 9,503 bytes, lines 25718-26019
25718s
25719          if (val.length === 0) {
25720            return -1;
25721          }
25722
25723          return arrayIndexOf(buffer, val, byteOffset, encoding, dir);
25724        } else if (typeof val === 'number') {
25725          val = val & 0xFF; // Search for a byte value [0-255]
25726
25727          if (typeof Uint8Array.prototype.indexOf === 'function') {
25728            if (dir) {
25729              return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset);
25730            } else {
25731              return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset);
25732            }
25733          }
25734
25735          return arrayIndexOf(buffer, [val], byteOffset, encoding, dir);
25736        }
25737
25738        throw new TypeError('val must be string, number or Buffer');
25739      }
25740
25741      function arrayIndexOf(arr, val, byteOffset, encoding, dir) {
25742        var indexSize = 1;
25743        var arrLength = arr.length;
25744        var valLength = val.length;
25745
25746        if (encoding !== undefined) {
25747          encoding = String(encoding).toLowerCase();
25748
25749          if (encoding === 'ucs2' || encoding === 'ucs-2' || encoding === 'utf16le' || encoding === 'utf-16le') {
25750            if (arr.length < 2 || val.length < 2) {
25751              return -1;
25752            }
25753
25754            indexSize = 2;
25755            arrLength /= 2;
25756            valLength /= 2;
25757            byteOffset /= 2;
25758          }
25759        }
25760
25761        function read(buf, i) {
25762          if (indexSize === 1) {
25763            return buf[i];
25764          } else {
25765            return buf.readUInt16BE(i * indexSize);
25766          }
25767        }
25768
25769        var i;
25770
25771        if (dir) {
25772          var foundIndex = -1;
25773
25774          for (i = byteOffset; i < arrLength; i++) {
25775            if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
25776              if (foundIndex === -1) foundIndex = i;
25777              if (i - foundIndex + 1 === valLength) return foundIndex * indexSize;
25778            } else {
25779              if (foundIndex !== -1) i -= i - foundIndex;
25780              foundIndex = -1;
25781            }
25782          }
25783        } else {
25784          if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength;
25785
25786          for (i = byteOffset; i >= 0; i--) {
25787            var found = true;
25788
25789            for (var j = 0; j < valLength; j++) {
25790              if (read(arr, i + j) !== read(val, j)) {
25791                found = false;
25792                break;
25793              }
25794            }
25795
25796            if (found) return i;
25797          }
25798        }
25799
25800        return -1;
25801      }
25802
25803      Buffer.prototype.includes = function includes(val, byteOffset, encoding) {
25804        return this.indexOf(val, byteOffset, encoding) !== -1;
25805      };
25806
25807      Buffer.prototype.indexOf = function indexOf(val, byteOffset, encoding) {
25808        return bidirectionalIndexOf(this, val, byteOffset, encoding, true);
25809      };
25810
25811      Buffer.prototype.lastIndexOf = function lastIndexOf(val, byteOffset, encoding) {
25812        return bidirectionalIndexOf(this, val, byteOffset, encoding, false);
25813      };
25814
25815      function hexWrite(buf, string, offset, length) {
25816        offset = Number(offset) || 0;
25817        var remaining = buf.length - offset;
25818
25819        if (!length) {
25820          length = remaining;
25821        } else {
25822          length = Number(length);
25823
25824          if (length > remaining) {
25825            length = remaining;
25826          }
25827        }
25828
25829        var strLen = string.length;
25830
25831        if (length > strLen / 2) {
25832          length = strLen / 2;
25833        }
25834
25835        for (var i = 0; i < length; ++i) {
25836          var parsed = parseInt(string.substr(i * 2, 2), 16);
25837          if (numberIsNaN(parsed)) return i;
25838          buf[offset + i] = parsed;
25839        }
25840
25841        return i;
25842      }
25843
25844      function utf8Write(buf, string, offset, length) {
25845        return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length);
25846      }
25847
25848      function asciiWrite(buf, string, offset, length) {
25849        return blitBuffer(asciiToBytes(string), buf, offset, length);
25850      }
25851
25852      function latin1Write(buf, string, offset, length) {
25853        return asciiWrite(buf, string, offset, length);
25854      }
25855
25856      function base64Write(buf, string, offset, length) {
25857        return blitBuffer(base64ToBytes(string), buf, offset, length);
25858      }
25859
25860      function ucs2Write(buf, string, offset, length) {
25861        return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length);
25862      }
25863
25864      Buffer.prototype.write = function write(string, offset, length, encoding) {
25865        // Buffer#write(string)
25866        if (offset === undefined) {
25867          encoding = 'utf8';
25868          length = this.length;
25869          offset = 0; // Buffer#write(string, encoding)
25870        } else if (length === undefined && typeof offset === 'string') {
25871          encoding = offset;
25872          length = this.length;
25873          offset = 0; // Buffer#write(string, offset[, length][, encoding])
25874        } else if (isFinite(offset)) {
25875          offset = offset >>> 0;
25876
25877          if (isFinite(length)) {
25878            length = length >>> 0;
25879            if (encoding === undefined) encoding = 'utf8';
25880          } else {
25881            encoding = length;
25882            length = undefined;
25883          }
25884        } else {
25885          throw new Error('Buffer.write(string, encoding, offset[, length]) is no longer supported');
25886        }
25887
25888        var remaining = this.length - offset;
25889        if (length === undefined || length > remaining) length = remaining;
25890
25891        if (string.length > 0 && (length < 0 || offset < 0) || offset > this.length) {
25892          throw new RangeError('Attempt to write outside buffer bounds');
25893        }
25894
25895        if (!encoding) encoding = 'utf8';
25896        var loweredCase = false;
25897
25898        for (;;) {
25899          switch (encoding) {
25900            case 'hex':
25901              return hexWrite(this, string, offset, length);
25902
25903            case 'utf8':
25904            case 'utf-8':
25905              return utf8Write(this, string, offset, length);
25906
25907            case 'ascii':
25908              return asciiWrite(this, string, offset, length);
25909
25910            case 'latin1':
25911            case 'binary':
25912              return latin1Write(this, string, offset, length);
25913
25914            case 'base64':
25915              // Warning: maxLength not taken into account in base64Write
25916              return base64Write(this, string, offset, length);
25917
25918            case 'ucs2':
25919            case 'ucs-2':
25920            case 'utf16le':
25921            case 'utf-16le':
25922              return ucs2Write(this, string, offset, length);
25923
25924            default:
25925              if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding);
25926              encoding = ('' + encoding).toLowerCase();
25927              loweredCase = true;
25928          }
25929        }
25930      };
25931
25932      Buffer.prototype.toJSON = function toJSON() {
25933        return {
25934          type: 'Buffer',
25935          data: Array.prototype.slice.call(this._arr || this, 0)
25936        };
25937      };
25938
25939      function base64Slice(buf, start, end) {
25940        if (start === 0 && end === buf.length) {
25941          return base64.fromByteArray(buf);
25942        } else {
25943          return base64.fromByteArray(buf.slice(start, end));
25944        }
25945      }
25946
25947      function utf8Slice(buf, start, end) {
25948        end = Math.min(buf.length, end);
25949        var res = [];
25950        var i = start;
25951
25952        while (i < end) {
25953          var firstByte = buf[i];
25954          var codePoint = null;
25955          var bytesPerSequence = firstByte > 0xEF ? 4 : firstByte > 0xDF ? 3 : firstByte > 0xBF ? 2 : 1;
25956
25957          if (i + bytesPerSequence <= end) {
25958            var secondByte, thirdByte, fourthByte, tempCodePoint;
25959
25960            switch (bytesPerSequence) {
25961              case 1:
25962                if (firstByte < 0x80) {
25963                  codePoint = firstByte;
25964                }
25965
25966                break;
25967
25968              case 2:
25969                secondByte = buf[i + 1];
25970
25971                if ((secondByte & 0xC0) === 0x80) {
25972                  tempCodePoint = (firstByte & 0x1F) << 0x6 | secondByte & 0x3F;
25973
25974                  if (tempCodePoint > 0x7F) {
25975                    codePoint = tempCodePoint;
25976                  }
25977                }
25978
25979                break;
25980
25981              case 3:
25982                secondByte = buf[i + 1];
25983                thirdByte = buf[i + 2];
25984
25985                if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
25986                  tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | thirdByte & 0x3F;
25987
25988                  if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
25989                    codePoint = tempCodePoint;
25990                  }
25991                }
25992
25993                break;
25994
25995              case 4:
25996                secondByte = buf[i + 1];
25997                thirdByte = buf[i + 2];
25998                fourthByte = buf[i + 3];
25999
26000                if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
26001                  tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | fourthByte & 0x3F;
26002
26003                  if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
26004                    codePoint = tempCodePoint;
26005                  }
26006                }
26007
26008            }
26009          }
26010
26011          if (codePoint === null) {
26012            // we did not generate a valid codePoint so insert a
26013            // replacement char (U+FFFD) and advance only 1 byte
26014            codePoint = 0xFFFD;
26015            bytesPerSequence = 1;
26016          } else if (codePoint > 0xFFFF) {
26017            // encode to utf16 (surrogate pair dance)
26018            codePoint -= 0x10000;
26019            res.push(codePoint >>>
vendor: 25,189 bytes, lines 26019-26781
26019 10 & 0x3FF | 0xD800);
26020            codePoint = 0xDC00 | codePoint & 0x3FF;
26021          }
26022
26023          res.push(codePoint);
26024          i += bytesPerSequence;
26025        }
26026
26027        return decodeCodePointsArray(res);
26028      } // Based on http://stackoverflow.com/a/22747272/680742, the browser with
26029      // the lowest limit is Chrome, with 0x10000 args.
26030      // We go 1 magnitude less, for safety
26031
26032
26033      var MAX_ARGUMENTS_LENGTH = 0x1000;
26034
26035      function decodeCodePointsArray(codePoints) {
26036        var len = codePoints.length;
26037
26038        if (len <= MAX_ARGUMENTS_LENGTH) {
26039          return String.fromCharCode.apply(String, codePoints); // avoid extra slice()
26040        } // Decode in chunks to avoid "call stack size exceeded".
26041
26042
26043        var res = '';
26044        var i = 0;
26045
26046        while (i < len) {
26047          res += String.fromCharCode.apply(String, codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH));
26048        }
26049
26050        return res;
26051      }
26052
26053      function asciiSlice(buf, start, end) {
26054        var ret = '';
26055        end = Math.min(buf.length, end);
26056
26057        for (var i = start; i < end; ++i) {
26058          ret += String.fromCharCode(buf[i] & 0x7F);
26059        }
26060
26061        return ret;
26062      }
26063
26064      function latin1Slice(buf, start, end) {
26065        var ret = '';
26066        end = Math.min(buf.length, end);
26067
26068        for (var i = start; i < end; ++i) {
26069          ret += String.fromCharCode(buf[i]);
26070        }
26071
26072        return ret;
26073      }
26074
26075      function hexSlice(buf, start, end) {
26076        var len = buf.length;
26077        if (!start || start < 0) start = 0;
26078        if (!end || end < 0 || end > len) end = len;
26079        var out = '';
26080
26081        for (var i = start; i < end; ++i) {
26082          out += toHex(buf[i]);
26083        }
26084
26085        return out;
26086      }
26087
26088      function utf16leSlice(buf, start, end) {
26089        var bytes = buf.slice(start, end);
26090        var res = '';
26091
26092        for (var i = 0; i < bytes.length; i += 2) {
26093          res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256);
26094        }
26095
26096        return res;
26097      }
26098
26099      Buffer.prototype.slice = function slice(start, end) {
26100        var len = this.length;
26101        start = ~~start;
26102        end = end === undefined ? len : ~~end;
26103
26104        if (start < 0) {
26105          start += len;
26106          if (start < 0) start = 0;
26107        } else if (start > len) {
26108          start = len;
26109        }
26110
26111        if (end < 0) {
26112          end += len;
26113          if (end < 0) end = 0;
26114        } else if (end > len) {
26115          end = len;
26116        }
26117
26118        if (end < start) end = start;
26119        var newBuf = this.subarray(start, end); // Return an augmented `Uint8Array` instance
26120
26121        newBuf.__proto__ = Buffer.prototype;
26122        return newBuf;
26123      };
26124      /*
26125       * Need to make sure that buffer isn't trying to write out of bounds.
26126       */
26127
26128
26129      function checkOffset(offset, ext, length) {
26130        if (offset % 1 !== 0 || offset < 0) throw new RangeError('offset is not uint');
26131        if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length');
26132      }
26133
26134      Buffer.prototype.readUIntLE = function readUIntLE(offset, byteLength, noAssert) {
26135        offset = offset >>> 0;
26136        byteLength = byteLength >>> 0;
26137        if (!noAssert) checkOffset(offset, byteLength, this.length);
26138        var val = this[offset];
26139        var mul = 1;
26140        var i = 0;
26141
26142        while (++i < byteLength && (mul *= 0x100)) {
26143          val += this[offset + i] * mul;
26144        }
26145
26146        return val;
26147      };
26148
26149      Buffer.prototype.readUIntBE = function readUIntBE(offset, byteLength, noAssert) {
26150        offset = offset >>> 0;
26151        byteLength = byteLength >>> 0;
26152
26153        if (!noAssert) {
26154          checkOffset(offset, byteLength, this.length);
26155        }
26156
26157        var val = this[offset + --byteLength];
26158        var mul = 1;
26159
26160        while (byteLength > 0 && (mul *= 0x100)) {
26161          val += this[offset + --byteLength] * mul;
26162        }
26163
26164        return val;
26165      };
26166
26167      Buffer.prototype.readUInt8 = function readUInt8(offset, noAssert) {
26168        offset = offset >>> 0;
26169        if (!noAssert) checkOffset(offset, 1, this.length);
26170        return this[offset];
26171      };
26172
26173      Buffer.prototype.readUInt16LE = function readUInt16LE(offset, noAssert) {
26174        offset = offset >>> 0;
26175        if (!noAssert) checkOffset(offset, 2, this.length);
26176        return this[offset] | this[offset + 1] << 8;
26177      };
26178
26179      Buffer.prototype.readUInt16BE = function readUInt16BE(offset, noAssert) {
26180        offset = offset >>> 0;
26181        if (!noAssert) checkOffset(offset, 2, this.length);
26182        return this[offset] << 8 | this[offset + 1];
26183      };
26184
26185      Buffer.prototype.readUInt32LE = function readUInt32LE(offset, noAssert) {
26186        offset = offset >>> 0;
26187        if (!noAssert) checkOffset(offset, 4, this.length);
26188        return (this[offset] | this[offset + 1] << 8 | this[offset + 2] << 16) + this[offset + 3] * 0x1000000;
26189      };
26190
26191      Buffer.prototype.readUInt32BE = function readUInt32BE(offset, noAssert) {
26192        offset = offset >>> 0;
26193        if (!noAssert) checkOffset(offset, 4, this.length);
26194        return this[offset] * 0x1000000 + (this[offset + 1] << 16 | this[offset + 2] << 8 | this[offset + 3]);
26195      };
26196
26197      Buffer.prototype.readIntLE = function readIntLE(offset, byteLength, noAssert) {
26198        offset = offset >>> 0;
26199        byteLength = byteLength >>> 0;
26200        if (!noAssert) checkOffset(offset, byteLength, this.length);
26201        var val = this[offset];
26202        var mul = 1;
26203        var i = 0;
26204
26205        while (++i < byteLength && (mul *= 0x100)) {
26206          val += this[offset + i] * mul;
26207        }
26208
26209        mul *= 0x80;
26210        if (val >= mul) val -= Math.pow(2, 8 * byteLength);
26211        return val;
26212      };
26213
26214      Buffer.prototype.readIntBE = function readIntBE(offset, byteLength, noAssert) {
26215        offset = offset >>> 0;
26216        byteLength = byteLength >>> 0;
26217        if (!noAssert) checkOffset(offset, byteLength, this.length);
26218        var i = byteLength;
26219        var mul = 1;
26220        var val = this[offset + --i];
26221
26222        while (i > 0 && (mul *= 0x100)) {
26223          val += this[offset + --i] * mul;
26224        }
26225
26226        mul *= 0x80;
26227        if (val >= mul) val -= Math.pow(2, 8 * byteLength);
26228        return val;
26229      };
26230
26231      Buffer.prototype.readInt8 = function readInt8(offset, noAssert) {
26232        offset = offset >>> 0;
26233        if (!noAssert) checkOffset(offset, 1, this.length);
26234        if (!(this[offset] & 0x80)) return this[offset];
26235        return (0xff - this[offset] + 1) * -1;
26236      };
26237
26238      Buffer.prototype.readInt16LE = function readInt16LE(offset, noAssert) {
26239        offset = offset >>> 0;
26240        if (!noAssert) checkOffset(offset, 2, this.length);
26241        var val = this[offset] | this[offset + 1] << 8;
26242        return val & 0x8000 ? val | 0xFFFF0000 : val;
26243      };
26244
26245      Buffer.prototype.readInt16BE = function readInt16BE(offset, noAssert) {
26246        offset = offset >>> 0;
26247        if (!noAssert) checkOffset(offset, 2, this.length);
26248        var val = this[offset + 1] | this[offset] << 8;
26249        return val & 0x8000 ? val | 0xFFFF0000 : val;
26250      };
26251
26252      Buffer.prototype.readInt32LE = function readInt32LE(offset, noAssert) {
26253        offset = offset >>> 0;
26254        if (!noAssert) checkOffset(offset, 4, this.length);
26255        return this[offset] | this[offset + 1] << 8 | this[offset + 2] << 16 | this[offset + 3] << 24;
26256      };
26257
26258      Buffer.prototype.readInt32BE = function readInt32BE(offset, noAssert) {
26259        offset = offset >>> 0;
26260        if (!noAssert) checkOffset(offset, 4, this.length);
26261        return this[offset] << 24 | this[offset + 1] << 16 | this[offset + 2] << 8 | this[offset + 3];
26262      };
26263
26264      Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) {
26265        offset = offset >>> 0;
26266        if (!noAssert) checkOffset(offset, 4, this.length);
26267        return ieee754.read(this, offset, true, 23, 4);
26268      };
26269
26270      Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) {
26271        offset = offset >>> 0;
26272        if (!noAssert) checkOffset(offset, 4, this.length);
26273        return ieee754.read(this, offset, false, 23, 4);
26274      };
26275
26276      Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) {
26277        offset = offset >>> 0;
26278        if (!noAssert) checkOffset(offset, 8, this.length);
26279        return ieee754.read(this, offset, true, 52, 8);
26280      };
26281
26282      Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) {
26283        offset = offset >>> 0;
26284        if (!noAssert) checkOffset(offset, 8, this.length);
26285        return ieee754.read(this, offset, false, 52, 8);
26286      };
26287
26288      function checkInt(buf, value, offset, ext, max, min) {
26289        if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance');
26290        if (value > max || value < min) throw new RangeError('"value" argument is out of bounds');
26291        if (offset + ext > buf.length) throw new RangeError('Index out of range');
26292      }
26293
26294      Buffer.prototype.writeUIntLE = function writeUIntLE(value, offset, byteLength, noAssert) {
26295        value = +value;
26296        offset = offset >>> 0;
26297        byteLength = byteLength >>> 0;
26298
26299        if (!noAssert) {
26300          var maxBytes = Math.pow(2, 8 * byteLength) - 1;
26301          checkInt(this, value, offset, byteLength, maxBytes, 0);
26302        }
26303
26304        var mul = 1;
26305        var i = 0;
26306        this[offset] = value & 0xFF;
26307
26308        while (++i < byteLength && (mul *= 0x100)) {
26309          this[offset + i] = value / mul & 0xFF;
26310        }
26311
26312        return offset + byteLength;
26313      };
26314
26315      Buffer.prototype.writeUIntBE = function writeUIntBE(value, offset, byteLength, noAssert) {
26316        value = +value;
26317        offset = offset >>> 0;
26318        byteLength = byteLength >>> 0;
26319
26320        if (!noAssert) {
26321          var maxBytes = Math.pow(2, 8 * byteLength) - 1;
26322          checkInt(this, value, offset, byteLength, maxBytes, 0);
26323        }
26324
26325        var i = byteLength - 1;
26326        var mul = 1;
26327        this[offset + i] = value & 0xFF;
26328
26329        while (--i >= 0 && (mul *= 0x100)) {
26330          this[offset + i] = value / mul & 0xFF;
26331        }
26332
26333        return offset + byteLength;
26334      };
26335
26336      Buffer.prototype.writeUInt8 = function writeUInt8(value, offset, noAssert) {
26337        value = +value;
26338        offset = offset >>> 0;
26339        if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0);
26340        this[offset] = value & 0xff;
26341        return offset + 1;
26342      };
26343
26344      Buffer.prototype.writeUInt16LE = function writeUInt16LE(value, offset, noAssert) {
26345        value = +value;
26346        offset = offset >>> 0;
26347        if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0);
26348        this[offset] = value & 0xff;
26349        this[offset + 1] = value >>> 8;
26350        return offset + 2;
26351      };
26352
26353      Buffer.prototype.writeUInt16BE = function writeUInt16BE(value, offset, noAssert) {
26354        value = +value;
26355        offset = offset >>> 0;
26356        if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0);
26357        this[offset] = value >>> 8;
26358        this[offset + 1] = value & 0xff;
26359        return offset + 2;
26360      };
26361
26362      Buffer.prototype.writeUInt32LE = function writeUInt32LE(value, offset, noAssert) {
26363        value = +value;
26364        offset = offset >>> 0;
26365        if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0);
26366        this[offset + 3] = value >>> 24;
26367        this[offset + 2] = value >>> 16;
26368        this[offset + 1] = value >>> 8;
26369        this[offset] = value & 0xff;
26370        return offset + 4;
26371      };
26372
26373      Buffer.prototype.writeUInt32BE = function writeUInt32BE(value, offset, noAssert) {
26374        value = +value;
26375        offset = offset >>> 0;
26376        if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0);
26377        this[offset] = value >>> 24;
26378        this[offset + 1] = value >>> 16;
26379        this[offset + 2] = value >>> 8;
26380        this[offset + 3] = value & 0xff;
26381        return offset + 4;
26382      };
26383
26384      Buffer.prototype.writeIntLE = function writeIntLE(value, offset, byteLength, noAssert) {
26385        value = +value;
26386        offset = offset >>> 0;
26387
26388        if (!noAssert) {
26389          var limit = Math.pow(2, 8 * byteLength - 1);
26390          checkInt(this, value, offset, byteLength, limit - 1, -limit);
26391        }
26392
26393        var i = 0;
26394        var mul = 1;
26395        var sub = 0;
26396        this[offset] = value & 0xFF;
26397
26398        while (++i < byteLength && (mul *= 0x100)) {
26399          if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
26400            sub = 1;
26401          }
26402
26403          this[offset + i] = (value / mul >> 0) - sub & 0xFF;
26404        }
26405
26406        return offset + byteLength;
26407      };
26408
26409      Buffer.prototype.writeIntBE = function writeIntBE(value, offset, byteLength, noAssert) {
26410        value = +value;
26411        offset = offset >>> 0;
26412
26413        if (!noAssert) {
26414          var limit = Math.pow(2, 8 * byteLength - 1);
26415          checkInt(this, value, offset, byteLength, limit - 1, -limit);
26416        }
26417
26418        var i = byteLength - 1;
26419        var mul = 1;
26420        var sub = 0;
26421        this[offset + i] = value & 0xFF;
26422
26423        while (--i >= 0 && (mul *= 0x100)) {
26424          if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
26425            sub = 1;
26426          }
26427
26428          this[offset + i] = (value / mul >> 0) - sub & 0xFF;
26429        }
26430
26431        return offset + byteLength;
26432      };
26433
26434      Buffer.prototype.writeInt8 = function writeInt8(value, offset, noAssert) {
26435        value = +value;
26436        offset = offset >>> 0;
26437        if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80);
26438        if (value < 0) value = 0xff + value + 1;
26439        this[offset] = value & 0xff;
26440        return offset + 1;
26441      };
26442
26443      Buffer.prototype.writeInt16LE = function writeInt16LE(value, offset, noAssert) {
26444        value = +value;
26445        offset = offset >>> 0;
26446        if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000);
26447        this[offset] = value & 0xff;
26448        this[offset + 1] = value >>> 8;
26449        return offset + 2;
26450      };
26451
26452      Buffer.prototype.writeInt16BE = function writeInt16BE(value, offset, noAssert) {
26453        value = +value;
26454        offset = offset >>> 0;
26455        if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000);
26456        this[offset] = value >>> 8;
26457        this[offset + 1] = value & 0xff;
26458        return offset + 2;
26459      };
26460
26461      Buffer.prototype.writeInt32LE = function writeInt32LE(value, offset, noAssert) {
26462        value = +value;
26463        offset = offset >>> 0;
26464        if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
26465        this[offset] = value & 0xff;
26466        this[offset + 1] = value >>> 8;
26467        this[offset + 2] = value >>> 16;
26468        this[offset + 3] = value >>> 24;
26469        return offset + 4;
26470      };
26471
26472      Buffer.prototype.writeInt32BE = function writeInt32BE(value, offset, noAssert) {
26473        value = +value;
26474        offset = offset >>> 0;
26475        if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
26476        if (value < 0) value = 0xffffffff + value + 1;
26477        this[offset] = value >>> 24;
26478        this[offset + 1] = value >>> 16;
26479        this[offset + 2] = value >>> 8;
26480        this[offset + 3] = value & 0xff;
26481        return offset + 4;
26482      };
26483
26484      function checkIEEE754(buf, value, offset, ext, max, min) {
26485        if (offset + ext > buf.length) throw new RangeError('Index out of range');
26486        if (offset < 0) throw new RangeError('Index out of range');
26487      }
26488
26489      function writeFloat(buf, value, offset, littleEndian, noAssert) {
26490        value = +value;
26491        offset = offset >>> 0;
26492
26493        if (!noAssert) {
26494          checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38);
26495        }
26496
26497        ieee754.write(buf, value, offset, littleEndian, 23, 4);
26498        return offset + 4;
26499      }
26500
26501      Buffer.prototype.writeFloatLE = function writeFloatLE(value, offset, noAssert) {
26502        return writeFloat(this, value, offset, true, noAssert);
26503      };
26504
26505      Buffer.prototype.writeFloatBE = function writeFloatBE(value, offset, noAssert) {
26506        return writeFloat(this, value, offset, false, noAssert);
26507      };
26508
26509      function writeDouble(buf, value, offset, littleEndian, noAssert) {
26510        value = +value;
26511        offset = offset >>> 0;
26512
26513        if (!noAssert) {
26514          checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308);
26515        }
26516
26517        ieee754.write(buf, value, offset, littleEndian, 52, 8);
26518        return offset + 8;
26519      }
26520
26521      Buffer.prototype.writeDoubleLE = function writeDoubleLE(value, offset, noAssert) {
26522        return writeDouble(this, value, offset, true, noAssert);
26523      };
26524
26525      Buffer.prototype.writeDoubleBE = function writeDoubleBE(value, offset, noAssert) {
26526        return writeDouble(this, value, offset, false, noAssert);
26527      }; // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
26528
26529
26530      Buffer.prototype.copy = function copy(target, targetStart, start, end) {
26531        if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer');
26532        if (!start) start = 0;
26533        if (!end && end !== 0) end = this.length;
26534        if (targetStart >= target.length) targetStart = target.length;
26535        if (!targetStart) targetStart = 0;
26536        if (end > 0 && end < start) end = start; // Copy 0 bytes; we're done
26537
26538        if (end === start) return 0;
26539        if (target.length === 0 || this.length === 0) return 0; // Fatal error conditions
26540
26541        if (targetStart < 0) {
26542          throw new RangeError('targetStart out of bounds');
26543        }
26544
26545        if (start < 0 || start >= this.length) throw new RangeError('Index out of range');
26546        if (end < 0) throw new RangeError('sourceEnd out of bounds'); // Are we oob?
26547
26548        if (end > this.length) end = this.length;
26549
26550        if (target.length - targetStart < end - start) {
26551          end = target.length - targetStart + start;
26552        }
26553
26554        var len = end - start;
26555
26556        if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') {
26557          // Use built-in when available, missing from IE11
26558          this.copyWithin(targetStart, start, end);
26559        } else if (this === target && start < targetStart && targetStart < end) {
26560          // descending copy from end
26561          for (var i = len - 1; i >= 0; --i) {
26562            target[i + targetStart] = this[i + start];
26563          }
26564        } else {
26565          Uint8Array.prototype.set.call(target, this.subarray(start, end), targetStart);
26566        }
26567
26568        return len;
26569      }; // Usage:
26570      //    buffer.fill(number[, offset[, end]])
26571      //    buffer.fill(buffer[, offset[, end]])
26572      //    buffer.fill(string[, offset[, end]][, encoding])
26573
26574
26575      Buffer.prototype.fill = function fill(val, start, end, encoding) {
26576        // Handle string cases:
26577        if (typeof val === 'string') {
26578          if (typeof start === 'string') {
26579            encoding = start;
26580            start = 0;
26581            end = this.length;
26582          } else if (typeof end === 'string') {
26583            encoding = end;
26584            end = this.length;
26585          }
26586
26587          if (encoding !== undefined && typeof encoding !== 'string') {
26588            throw new TypeError('encoding must be a string');
26589          }
26590
26591          if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
26592            throw new TypeError('Unknown encoding: ' + encoding);
26593          }
26594
26595          if (val.length === 1) {
26596            var code = val.charCodeAt(0);
26597
26598            if (encoding === 'utf8' && code < 128 || encoding === 'latin1') {
26599              // Fast path: If `val` fits into a single byte, use that numeric value.
26600              val = code;
26601            }
26602          }
26603        } else if (typeof val === 'number') {
26604          val = val & 255;
26605        } // Invalid ranges are not set to a default, so can range check early.
26606
26607
26608        if (start < 0 || this.length < start || this.length < end) {
26609          throw new RangeError('Out of range index');
26610        }
26611
26612        if (end <= start) {
26613          return this;
26614        }
26615
26616        start = start >>> 0;
26617        end = end === undefined ? this.length : end >>> 0;
26618        if (!val) val = 0;
26619        var i;
26620
26621        if (typeof val === 'number') {
26622          for (i = start; i < end; ++i) {
26623            this[i] = val;
26624          }
26625        } else {
26626          var bytes = Buffer.isBuffer(val) ? val : Buffer.from(val, encoding);
26627          var len = bytes.length;
26628
26629          if (len === 0) {
26630            throw new TypeError('The value "' + val + '" is invalid for argument "value"');
26631          }
26632
26633          for (i = 0; i < end - start; ++i) {
26634            this[i + start] = bytes[i % len];
26635          }
26636        }
26637
26638        return this;
26639      }; // HELPER FUNCTIONS
26640      // ================
26641
26642
26643      var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g;
26644
26645      function base64clean(str) {
26646        // Node takes equal signs as end of the Base64 encoding
26647        str = str.split('=')[0]; // Node strips out invalid characters like \n and \t from the string, base64-js does not
26648
26649        str = str.trim().replace(INVALID_BASE64_RE, ''); // Node converts strings with length < 2 to ''
26650
26651        if (str.length < 2) return ''; // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
26652
26653        while (str.length % 4 !== 0) {
26654          str = str + '=';
26655        }
26656
26657        return str;
26658      }
26659
26660      function toHex(n) {
26661        if (n < 16) return '0' + n.toString(16);
26662        return n.toString(16);
26663      }
26664
26665      function utf8ToBytes(string, units) {
26666        units = units || Infinity;
26667        var codePoint;
26668        var length = string.length;
26669        var leadSurrogate = null;
26670        var bytes = [];
26671
26672        for (var i = 0; i < length; ++i) {
26673          codePoint = string.charCodeAt(i); // is surrogate component
26674
26675          if (codePoint > 0xD7FF && codePoint < 0xE000) {
26676            // last char was a lead
26677            if (!leadSurrogate) {
26678              // no lead yet
26679              if (codePoint > 0xDBFF) {
26680                // unexpected trail
26681                if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD);
26682                continue;
26683              } else if (i + 1 === length) {
26684                // unpaired lead
26685                if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD);
26686                continue;
26687              } // valid lead
26688
26689
26690              leadSurrogate = codePoint;
26691              continue;
26692            } // 2 leads in a row
26693
26694
26695            if (codePoint < 0xDC00) {
26696              if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD);
26697              leadSurrogate = codePoint;
26698              continue;
26699            } // valid surrogate pair
26700
26701
26702            codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000;
26703          } else if (leadSurrogate) {
26704            // valid bmp char, but last char was a lead
26705            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD);
26706          }
26707
26708          leadSurrogate = null; // encode utf8
26709
26710          if (codePoint < 0x80) {
26711            if ((units -= 1) < 0) break;
26712            bytes.push(codePoint);
26713          } else if (codePoint < 0x800) {
26714            if ((units -= 2) < 0) break;
26715            bytes.push(codePoint >> 0x6 | 0xC0, codePoint & 0x3F | 0x80);
26716          } else if (codePoint < 0x10000) {
26717            if ((units -= 3) < 0) break;
26718            bytes.push(codePoint >> 0xC | 0xE0, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80);
26719          } else if (codePoint < 0x110000) {
26720            if ((units -= 4) < 0) break;
26721            bytes.push(codePoint >> 0x12 | 0xF0, codePoint >> 0xC & 0x3F | 0x80, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80);
26722          } else {
26723            throw new Error('Invalid code point');
26724          }
26725        }
26726
26727        return bytes;
26728      }
26729
26730      function asciiToBytes(str) {
26731        var byteArray = [];
26732
26733        for (var i = 0; i < str.length; ++i) {
26734          // Node's code seems to be doing this and not & 0x7F..
26735          byteArray.push(str.charCodeAt(i) & 0xFF);
26736        }
26737
26738        return byteArray;
26739      }
26740
26741      function utf16leToBytes(str, units) {
26742        var c, hi, lo;
26743        var byteArray = [];
26744
26745        for (var i = 0; i < str.length; ++i) {
26746          if ((units -= 2) < 0) break;
26747          c = str.charCodeAt(i);
26748          hi = c >> 8;
26749          lo = c % 256;
26750          byteArray.push(lo);
26751          byteArray.push(hi);
26752        }
26753
26754        return byteArray;
26755      }
26756
26757      function base64ToBytes(str) {
26758        return base64.toByteArray(base64clean(str));
26759      }
26760
26761      function blitBuffer(src, dst, offset, length) {
26762        for (var i = 0; i < length; ++i) {
26763          if (i + offset >= dst.length || i >= src.length) break;
26764          dst[i + offset] = src[i];
26765        }
26766
26767        return i;
26768      } // ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass
26769      // the `instanceof` check but they should be treated as of that type.
26770      // See: https://github.com/feross/buffer/issues/166
26771
26772
26773      function isInstance(obj, type) {
26774        return obj instanceof type || obj != null && obj.constructor != null && obj.constructor.name != null && obj.constructor.name === type.name;
26775      }
26776
26777      function numberIsNaN(obj) {
26778        // For IE11 support
26779        return obj !== obj; // eslint-disable-line no-self-compare
26780      }
26781    }, {
vendor: 22,463 bytes, lines 26782-27459
26782      "base64-js": 2,
26783      "ieee754": 8
26784    }],
26785    5: [function (_dereq_, module, exports) {
26786      (function (process, global) {
26787        /*!
26788         * @overview es6-promise - a tiny implementation of Promises/A+.
26789         * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
26790         * @license   Licensed under MIT license
26791         *            See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
26792         * @version   4.1.1
26793         */
26794        (function (global, factory) {
26795          typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : global.ES6Promise = factory();
26796        })(this, function () {
26797          'use strict';
26798
26799          function objectOrFunction(x) {
26800            var type = typeof x;
26801            return x !== null && (type === 'object' || type === 'function');
26802          }
26803
26804          function isFunction(x) {
26805            return typeof x === 'function';
26806          }
26807
26808          var _isArray = undefined;
26809
26810          if (Array.isArray) {
26811            _isArray = Array.isArray;
26812          } else {
26813            _isArray = function (x) {
26814              return Object.prototype.toString.call(x) === '[object Array]';
26815            };
26816          }
26817
26818          var isArray = _isArray;
26819          var len = 0;
26820          var vertxNext = undefined;
26821          var customSchedulerFn = undefined;
26822
26823          var asap = function asap(callback, arg) {
26824            queue[len] = callback;
26825            queue[len + 1] = arg;
26826            len += 2;
26827
26828            if (len === 2) {
26829              // If len is 2, that means that we need to schedule an async flush.
26830              // If additional callbacks are queued before the queue is flushed, they
26831              // will be processed by this flush that we are scheduling.
26832              if (customSchedulerFn) {
26833                customSchedulerFn(flush);
26834              } else {
26835                scheduleFlush();
26836              }
26837            }
26838          };
26839
26840          function setScheduler(scheduleFn) {
26841            customSchedulerFn = scheduleFn;
26842          }
26843
26844          function setAsap(asapFn) {
26845            asap = asapFn;
26846          }
26847
26848          var browserWindow = typeof window !== 'undefined' ? window : undefined;
26849          var browserGlobal = browserWindow || {};
26850          var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
26851          var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]'; // test for web worker but not in IE10
26852
26853          var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; // node
26854
26855          function useNextTick() {
26856            // node version 0.10.x displays a deprecation warning when nextTick is used recursively
26857            // see https://github.com/cujojs/when/issues/410 for details
26858            return function () {
26859              return process.nextTick(flush);
26860            };
26861          } // vertx
26862
26863
26864          function useVertxTimer() {
26865            if (typeof vertxNext !== 'undefined') {
26866              return function () {
26867                vertxNext(flush);
26868              };
26869            }
26870
26871            return useSetTimeout();
26872          }
26873
26874          function useMutationObserver() {
26875            var iterations = 0;
26876            var observer = new BrowserMutationObserver(flush);
26877            var node = document.createTextNode('');
26878            observer.observe(node, {
26879              characterData: true
26880            });
26881            return function () {
26882              node.data = iterations = ++iterations % 2;
26883            };
26884          } // web worker
26885
26886
26887          function useMessageChannel() {
26888            var channel = new MessageChannel();
26889            channel.port1.onmessage = flush;
26890            return function () {
26891              return channel.port2.postMessage(0);
26892            };
26893          }
26894
26895          function useSetTimeout() {
26896            // Store setTimeout reference so es6-promise will be unaffected by
26897            // other code modifying setTimeout (like sinon.useFakeTimers())
26898            var globalSetTimeout = setTimeout;
26899            return function () {
26900              return globalSetTimeout(flush, 1);
26901            };
26902          }
26903
26904          var queue = new Array(1000);
26905
26906          function flush() {
26907            for (var i = 0; i < len; i += 2) {
26908              var callback = queue[i];
26909              var arg = queue[i + 1];
26910              callback(arg);
26911              queue[i] = undefined;
26912              queue[i + 1] = undefined;
26913            }
26914
26915            len = 0;
26916          }
26917
26918          function attemptVertx() {
26919            try {
26920              var r = _dereq_;
26921              var vertx = r('vertx');
26922              vertxNext = vertx.runOnLoop || vertx.runOnContext;
26923              return useVertxTimer();
26924            } catch (e) {
26925              return useSetTimeout();
26926            }
26927          }
26928
26929          var scheduleFlush = undefined; // Decide what async method to use to triggering processing of queued callbacks:
26930
26931          if (isNode) {
26932            scheduleFlush = useNextTick();
26933          } else if (BrowserMutationObserver) {
26934            scheduleFlush = useMutationObserver();
26935          } else if (isWorker) {
26936            scheduleFlush = useMessageChannel();
26937          } else if (browserWindow === undefined && typeof _dereq_ === 'function') {
26938            scheduleFlush = attemptVertx();
26939          } else {
26940            scheduleFlush = useSetTimeout();
26941          }
26942
26943          function then(onFulfillment, onRejection) {
26944            var _arguments = arguments;
26945            var parent = this;
26946            var child = new this.constructor(noop);
26947
26948            if (child[PROMISE_ID] === undefined) {
26949              makePromise(child);
26950            }
26951
26952            var _state = parent._state;
26953
26954            if (_state) {
26955              (function () {
26956                var callback = _arguments[_state - 1];
26957                asap(function () {
26958                  return invokeCallback(_state, child, callback, parent._result);
26959                });
26960              })();
26961            } else {
26962              subscribe(parent, child, onFulfillment, onRejection);
26963            }
26964
26965            return child;
26966          }
26967          /**
26968            `Promise.resolve` returns a promise that will become resolved with the
26969            passed `value`. It is shorthand for the following:
26970          
26971            ```javascript
26972            let promise = new Promise(function(resolve, reject){
26973              resolve(1);
26974            });
26975          
26976            promise.then(function(value){
26977              // value === 1
26978            });
26979            ```
26980          
26981            Instead of writing the above, your code now simply becomes the following:
26982          
26983            ```javascript
26984            let promise = Promise.resolve(1);
26985          
26986            promise.then(function(value){
26987              // value === 1
26988            });
26989            ```
26990          
26991            @method resolve
26992            @static
26993            @param {Any} value value that the returned promise will be resolved with
26994            Useful for tooling.
26995            @return {Promise} a promise that will become fulfilled with the given
26996            `value`
26997          */
26998
26999
27000          function resolve$1(object) {
27001            /*jshint validthis:true */
27002            var Constructor = this;
27003
27004            if (object && typeof object === 'object' && object.constructor === Constructor) {
27005              return object;
27006            }
27007
27008            var promise = new Constructor(noop);
27009            resolve(promise, object);
27010            return promise;
27011          }
27012
27013          var PROMISE_ID = Math.random().toString(36).substring(16);
27014
27015          function noop() {}
27016
27017          var PENDING = void 0;
27018          var FULFILLED = 1;
27019          var REJECTED = 2;
27020          var GET_THEN_ERROR = new ErrorObject();
27021
27022          function selfFulfillment() {
27023            return new TypeError("You cannot resolve a promise with itself");
27024          }
27025
27026          function cannotReturnOwn() {
27027            return new TypeError('A promises callback cannot return that same promise.');
27028          }
27029
27030          function getThen(promise) {
27031            try {
27032              return promise.then;
27033            } catch (error) {
27034              GET_THEN_ERROR.error = error;
27035              return GET_THEN_ERROR;
27036            }
27037          }
27038
27039          function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) {
27040            try {
27041              then$$1.call(value, fulfillmentHandler, rejectionHandler);
27042            } catch (e) {
27043              return e;
27044            }
27045          }
27046
27047          function handleForeignThenable(promise, thenable, then$$1) {
27048            asap(function (promise) {
27049              var sealed = false;
27050              var error = tryThen(then$$1, thenable, function (value) {
27051                if (sealed) {
27052                  return;
27053                }
27054
27055                sealed = true;
27056
27057                if (thenable !== value) {
27058                  resolve(promise, value);
27059                } else {
27060                  fulfill(promise, value);
27061                }
27062              }, function (reason) {
27063                if (sealed) {
27064                  return;
27065                }
27066
27067                sealed = true;
27068                reject(promise, reason);
27069              }, 'Settle: ' + (promise._label || ' unknown promise'));
27070
27071              if (!sealed && error) {
27072                sealed = true;
27073                reject(promise, error);
27074              }
27075            }, promise);
27076          }
27077
27078          function handleOwnThenable(promise, thenable) {
27079            if (thenable._state === FULFILLED) {
27080              fulfill(promise, thenable._result);
27081            } else if (thenable._state === REJECTED) {
27082              reject(promise, thenable._result);
27083            } else {
27084              subscribe(thenable, undefined, function (value) {
27085                return resolve(promise, value);
27086              }, function (reason) {
27087                return reject(promise, reason);
27088              });
27089            }
27090          }
27091
27092          function handleMaybeThenable(promise, maybeThenable, then$$1) {
27093            if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) {
27094              handleOwnThenable(promise, maybeThenable);
27095            } else {
27096              if (then$$1 === GET_THEN_ERROR) {
27097                reject(promise, GET_THEN_ERROR.error);
27098                GET_THEN_ERROR.error = null;
27099              } else if (then$$1 === undefined) {
27100                fulfill(promise, maybeThenable);
27101              } else if (isFunction(then$$1)) {
27102                handleForeignThenable(promise, maybeThenable, then$$1);
27103              } else {
27104                fulfill(promise, maybeThenable);
27105              }
27106            }
27107          }
27108
27109          function resolve(promise, value) {
27110            if (promise === value) {
27111              reject(promise, selfFulfillment());
27112            } else if (objectOrFunction(value)) {
27113              handleMaybeThenable(promise, value, getThen(value));
27114            } else {
27115              fulfill(promise, value);
27116            }
27117          }
27118
27119          function publishRejection(promise) {
27120            if (promise._onerror) {
27121              promise._onerror(promise._result);
27122            }
27123
27124            publish(promise);
27125          }
27126
27127          function fulfill(promise, value) {
27128            if (promise._state !== PENDING) {
27129              return;
27130            }
27131
27132            promise._result = value;
27133            promise._state = FULFILLED;
27134
27135            if (promise._subscribers.length !== 0) {
27136              asap(publish, promise);
27137            }
27138          }
27139
27140          function reject(promise, reason) {
27141            if (promise._state !== PENDING) {
27142              return;
27143            }
27144
27145            promise._state = REJECTED;
27146            promise._result = reason;
27147            asap(publishRejection, promise);
27148          }
27149
27150          function subscribe(parent, child, onFulfillment, onRejection) {
27151            var _subscribers = parent._subscribers;
27152            var length = _subscribers.length;
27153            parent._onerror = null;
27154            _subscribers[length] = child;
27155            _subscribers[length + FULFILLED] = onFulfillment;
27156            _subscribers[length + REJECTED] = onRejection;
27157
27158            if (length === 0 && parent._state) {
27159              asap(publish, parent);
27160            }
27161          }
27162
27163          function publish(promise) {
27164            var subscribers = promise._subscribers;
27165            var settled = promise._state;
27166
27167            if (subscribers.length === 0) {
27168              return;
27169            }
27170
27171            var child = undefined,
27172                callback = undefined,
27173                detail = promise._result;
27174
27175            for (var i = 0; i < subscribers.length; i += 3) {
27176              child = subscribers[i];
27177              callback = subscribers[i + settled];
27178
27179              if (child) {
27180                invokeCallback(settled, child, callback, detail);
27181              } else {
27182                callback(detail);
27183              }
27184            }
27185
27186            promise._subscribers.length = 0;
27187          }
27188
27189          function ErrorObject() {
27190            this.error = null;
27191          }
27192
27193          var TRY_CATCH_ERROR = new ErrorObject();
27194
27195          function tryCatch(callback, detail) {
27196            try {
27197              return callback(detail);
27198            } catch (e) {
27199              TRY_CATCH_ERROR.error = e;
27200              return TRY_CATCH_ERROR;
27201            }
27202          }
27203
27204          function invokeCallback(settled, promise, callback, detail) {
27205            var hasCallback = isFunction(callback),
27206                value = undefined,
27207                error = undefined,
27208                succeeded = undefined,
27209                failed = undefined;
27210
27211            if (hasCallback) {
27212              value = tryCatch(callback, detail);
27213
27214              if (value === TRY_CATCH_ERROR) {
27215                failed = true;
27216                error = value.error;
27217                value.error = null;
27218              } else {
27219                succeeded = true;
27220              }
27221
27222              if (promise === value) {
27223                reject(promise, cannotReturnOwn());
27224                return;
27225              }
27226            } else {
27227              value = detail;
27228              succeeded = true;
27229            }
27230
27231            if (promise._state !== PENDING) {// noop
27232            } else if (hasCallback && succeeded) {
27233              resolve(promise, value);
27234            } else if (failed) {
27235              reject(promise, error);
27236            } else if (settled === FULFILLED) {
27237              fulfill(promise, value);
27238            } else if (settled === REJECTED) {
27239              reject(promise, value);
27240            }
27241          }
27242
27243          function initializePromise(promise, resolver) {
27244            try {
27245              resolver(function resolvePromise(value) {
27246                resolve(promise, value);
27247              }, function rejectPromise(reason) {
27248                reject(promise, reason);
27249              });
27250            } catch (e) {
27251              reject(promise, e);
27252            }
27253          }
27254
27255          var id = 0;
27256
27257          function nextId() {
27258            return id++;
27259          }
27260
27261          function makePromise(promise) {
27262            promise[PROMISE_ID] = id++;
27263            promise._state = undefined;
27264            promise._result = undefined;
27265            promise._subscribers = [];
27266          }
27267
27268          function Enumerator$1(Constructor, input) {
27269            this._instanceConstructor = Constructor;
27270            this.promise = new Constructor(noop);
27271
27272            if (!this.promise[PROMISE_ID]) {
27273              makePromise(this.promise);
27274            }
27275
27276            if (isArray(input)) {
27277              this.length = input.length;
27278              this._remaining = input.length;
27279              this._result = new Array(this.length);
27280
27281              if (this.length === 0) {
27282                fulfill(this.promise, this._result);
27283              } else {
27284                this.length = this.length || 0;
27285
27286                this._enumerate(input);
27287
27288                if (this._remaining === 0) {
27289                  fulfill(this.promise, this._result);
27290                }
27291              }
27292            } else {
27293              reject(this.promise, validationError());
27294            }
27295          }
27296
27297          function validationError() {
27298            return new Error('Array Methods must be provided an Array');
27299          }
27300
27301          Enumerator$1.prototype._enumerate = function (input) {
27302            for (var i = 0; this._state === PENDING && i < input.length; i++) {
27303              this._eachEntry(input[i], i);
27304            }
27305          };
27306
27307          Enumerator$1.prototype._eachEntry = function (entry, i) {
27308            var c = this._instanceConstructor;
27309            var resolve$$1 = c.resolve;
27310
27311            if (resolve$$1 === resolve$1) {
27312              var _then = getThen(entry);
27313
27314              if (_then === then && entry._state !== PENDING) {
27315                this._settledAt(entry._state, i, entry._result);
27316              } else if (typeof _then !== 'function') {
27317                this._remaining--;
27318                this._result[i] = entry;
27319              } else if (c === Promise$2) {
27320                var promise = new c(noop);
27321                handleMaybeThenable(promise, entry, _then);
27322
27323                this._willSettleAt(promise, i);
27324              } else {
27325                this._willSettleAt(new c(function (resolve$$1) {
27326                  return resolve$$1(entry);
27327                }), i);
27328              }
27329            } else {
27330              this._willSettleAt(resolve$$1(entry), i);
27331            }
27332          };
27333
27334          Enumerator$1.prototype._settledAt = function (state, i, value) {
27335            var promise = this.promise;
27336
27337            if (promise._state === PENDING) {
27338              this._remaining--;
27339
27340              if (state === REJECTED) {
27341                reject(promise, value);
27342              } else {
27343                this._result[i] = value;
27344              }
27345            }
27346
27347            if (this._remaining === 0) {
27348              fulfill(promise, this._result);
27349            }
27350          };
27351
27352          Enumerator$1.prototype._willSettleAt = function (promise, i) {
27353            var enumerator = this;
27354            subscribe(promise, undefined, function (value) {
27355              return enumerator._settledAt(FULFILLED, i, value);
27356            }, function (reason) {
27357              return enumerator._settledAt(REJECTED, i, reason);
27358            });
27359          };
27360          /**
27361            `Promise.all` accepts an array of promises, and returns a new promise which
27362            is fulfilled with an array of fulfillment values for the passed promises, or
27363            rejected with the reason of the first passed promise to be rejected. It casts all
27364            elements of the passed iterable to promises as it runs this algorithm.
27365          
27366            Example:
27367          
27368            ```javascript
27369            let promise1 = resolve(1);
27370            let promise2 = resolve(2);
27371            let promise3 = resolve(3);
27372            let promises = [ promise1, promise2, promise3 ];
27373          
27374            Promise.all(promises).then(function(array){
27375              // The array here would be [ 1, 2, 3 ];
27376            });
27377            ```
27378          
27379            If any of the `promises` given to `all` are rejected, the first promise
27380            that is rejected will be given as an argument to the returned promises's
27381            rejection handler. For example:
27382          
27383            Example:
27384          
27385            ```javascript
27386            let promise1 = resolve(1);
27387            let promise2 = reject(new Error("2"));
27388            let promise3 = reject(new Error("3"));
27389            let promises = [ promise1, promise2, promise3 ];
27390          
27391            Promise.all(promises).then(function(array){
27392              // Code here never runs because there are rejected promises!
27393            }, function(error) {
27394              // error.message === "2"
27395            });
27396            ```
27397          
27398            @method all
27399            @static
27400            @param {Array} entries array of promises
27401            @param {String} label optional string for labeling the promise.
27402            Useful for tooling.
27403            @return {Promise} promise that is fulfilled when all `promises` have been
27404            fulfilled, or rejected if any of them become rejected.
27405            @static
27406          */
27407
27408
27409          function all$1(entries) {
27410            return new Enumerator$1(this, entries).promise;
27411          }
27412          /**
27413            `Promise.race` returns a new promise which is settled in the same way as the
27414            first passed promise to settle.
27415          
27416            Example:
27417          
27418            ```javascript
27419            let promise1 = new Promise(function(resolve, reject){
27420              setTimeout(function(){
27421                resolve('promise 1');
27422              }, 200);
27423            });
27424          
27425            let promise2 = new Promise(function(resolve, reject){
27426              setTimeout(function(){
27427                resolve('promise 2');
27428              }, 100);
27429            });
27430          
27431            Promise.race([promise1, promise2]).then(function(result){
27432              // result === 'promise 2' because it was resolved before promise1
27433              // was resolved.
27434            });
27435            ```
27436          
27437            `Promise.race` is deterministic in that only the state of the first
27438            settled promise matters. For example, even if other promises given to the
27439            `promises` array argument are resolved, but the first settled promise has
27440            become rejected before the other promises became fulfilled, the returned
27441            promise will become rejected:
27442          
27443            ```javascript
27444            let promise1 = new Promise(function(resolve, reject){
27445              setTimeout(function(){
27446                resolve('promise 1');
27447              }, 200);
27448            });
27449          
27450            let promise2 = new Promise(function(resolve, reject){
27451              setTimeout(function(){
27452                reject(new Error('promise 2'));
27453              }, 100);
27454            });
27455          
27456            Promise.race([promise1, promise2]).then(function(result){
27457              // Code here never runs
27458            }, function(reason){
27459              // reason.message === 'promise 2' because promise 2 be
27459came rejected before
27460              // promise 1 became fulfilled
27461            });
27462            ```
27463          
27464            An example real-world use case is implementing timeouts:
27465          
27466            ```javascript
27467            Promise.race([ajax('foo.json'), timeout(5000)])
27468            ```
27469          
27470            @method race
27471            @static
27472            @param {Array} promises array of promises to observe
27473            Useful for tooling.
27474            @return {Promise} a promise which settles in the same way as the first passed
27475            promise to settle.
27476          */
27477
27478
27479          function race$1(entries) {
27480            /*jshint validthis:true */
27481            var Constructor = this;
27482
27483            if (!isArray(entries)) {
27484              return new Constructor(function (_, reject) {
27485                return reject(new TypeError('You must pass an array to race.'));
27486              });
27487            } else {
27488              return new Constructor(function (resolve, reject) {
27489                var length = entries.length;
27490
27491                for (var i = 0; i < length; i++) {
27492                  Constructor.resolve(entries[i]).then(resolve, reject);
27493                }
27494              });
27495            }
27496          }
27497          /**
27498            `Promise.reject` returns a promise rejected with the passed `reason`.
27499            It is shorthand for the following:
27500          
27501            ```javascript
27502            let promise = new Promise(function(resolve, reject){
27503              reject(new Error('WHOOPS'));
27504            });
27505          
27506            promise.then(function(value){
27507              // Code here doesn't run because the promise is rejected!
27508            }, function(reason){
27509              // reason.message === 'WHOOPS'
27510            });
27511            ```
27512          
27513            Instead of writing the above, your code now simply becomes the following:
27514          
27515            ```javascript
27516            let promise = Promise.reject(new Error('WHOOPS'));
27517          
27518            promise.then(function(value){
27519              // Code here doesn't run because the promise is rejected!
27520            }, function(reason){
27521              // reason.message === 'WHOOPS'
27522            });
27523            ```
27524          
27525            @method reject
27526            @static
27527            @param {Any} reason value that the returned promise will be rejected with.
27528            Useful for tooling.
27529            @return {Promise} a promise rejected with the given `reason`.
27530          */
27531
27532
27533          function reject$1(reason) {
27534            /*jshint validthis:true */
27535            var Constructor = this;
27536            var promise = new Constructor(noop);
27537            reject(promise, reason);
27538            return promise;
27539          }
27540
27541          function needsResolver() {
27542            throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
27543          }
27544
27545          function needsNew() {
27546            throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object c
27546onstructor cannot be called as a function.");
27547          }
27548          /**
27549            Promise objects represent the eventual result of an asynchronous operation. The
27550            primary way of interacting with a promise is through its `then` method, which
27551            registers callbacks to receive either a promise's eventual value or the reason
27552            why the promise cannot be fulfilled.
27553          
27554            Terminology
27555            -----------
27556          
27557            - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
27558            - `thenable` is an object or function that defines a `then` method.
27559            - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
27560            - `exception` is a value that is thrown using the throw statement.
27561            - `reason` is a value that indicates why a promise was rejected.
27562            - `settled` the final resting state of a promise, fulfilled or rejected.
27563          
27564            A promise can be in one of three states: pending, fulfilled, or rejected.
27565          
27566            Promises that are fulfilled have a fulfillment value and are in the fulfilled
27567            state.  Promises that are rejected have a rejection reason and are in the
27568            rejected state.  A fulfillment value is never a thenable.
27569          
27570            Promises can also be said to *resolve* a value.  If this value is also a
27571            promise, then the original promise's settled state will match the value's
27572            settled state.  So a promise that *resolves* a promise that rejects will
27573            itself reject, and a promise that *resolves* a promise that fulfills will
27574            itself fulfill.
27575          
27576          
27577            Basic Usage:
27578            ------------
27579          
27580            ```js
27581            let promise = new Promise(function(resolve, reject) {
27582              // on success
27583              resolve(value);
27584          
27585              // on failure
27586              reject(reason);
27587            });
27588          
27589            promise.then(function(value) {
27590              // on fulfillment
27591            }, function(reason) {
27592              // on rejection
27593            });
27594            ```
27595          
27596            Advanced Usage:
27597            ---------------
27598          
27599            Promises shine when abstracting away asynchronous interactions such as
27600            `XMLHttpRequest`s.
27601          
27602            ```js
27603            function getJSON(url) {
27604              return new Promise(function(resolve, reject){
27605                let xhr = new XMLHttpRequest();
27606          
27607                xhr.open('GET', url);
27608                xhr.onreadystatechange = handler;
27609                xhr.responseType = 'json';
27610                xhr.setRequestHeader('Accept', 'application/json');
27611                xhr.send();
27612          
27613                function handler() {
27614                  if (this.readyState === this.DONE) {
27615                    if (this.status === 200) {
27616                      resolve(this.response);
27617                    } else {
27618                      reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
27619                    }
27620                  }
27621                };
27622              });
27623            }
27624          
27625            getJSON('/posts.json').then(function(json) {
27626              // on fulfillment
27627            }, function(reason) {
27628              // on rejection
27629            });
27630            ```
27631          
27632            Unlike callbacks, promises are great composable primitives.
27633          
27634            ```js
27635            Promise.all([
27636              getJSON('/posts'),
27637              getJSON('/comments')
27638            ]).then(function(values){
27639              values[0] // => postsJSON
27640              values[1] // => commentsJSON
27641          
27642              return values;
27643            });
27644            ```
27645          
27646            @class Promise
27647            @param {function} resolver
27648            Useful for tooling.
27649            @constructor
27650          */
27651
27652
27653          function Promise$2(resolver) {
27654            this[PROMISE_ID] = nextId();
27655            this._result = this._state = undefined;
27656            this._subscribers = [];
27657
27658            if (noop !== resolver) {
27659              typeof resolver !== 'function' && needsResolver();
27660              this instanceof Promise$2 ? initializePromise(this, resolver) : needsNew();
27661            }
27662          }
27663
27664          Promise$2.all = all$1;
27665          Promise$2.race = race$1;
27666          Promise$2.resolve = resolve$1;
27667          Promise$2.reject = reject$1;
27668          Promise$2._setScheduler = setScheduler;
27669          Promise$2._setAsap = setAsap;
27670          Promise$2._asap = asap;
27671          Promise$2.prototype = {
27672            constructor: Promise$2,
27673
27674            /**
27675              The primary way of interacting with a promise is through its `then` method,
27676              which registers callbacks to receive either a promise's eventual value or the
27677              reason why the promise cannot be fulfilled.
27678            
27679              ```js
27680              findUser().then(function(user){
27681                // user is available
27682              }, function(reason){
27683                // user is unavailable, and you are given the reason why
27684              });
27685              ```
27686            
27687              Chaining
27688              --------
27689            
27690              The return value of `then` is itself a promise.  This second, 'downstream'
27691              promise is resolved with the return value of the first promise's fulfillment
27692              or rejection handler, or rejected if the handler throws an exception.
27693            
27694              ```js
27695              findUser().then(function (user) {
27696                return user.name;
27697              }, function (reason) {
27698                return 'default name';
27699              }).then(function (userName) {
27700                // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
27701                // will be `'default name'`
27702              });
27703            
27704              findUser().then(function (user) {
27705                throw new Error('Found user, but still unhappy');
27706              }, function (reason) {
27707                throw new Error('`findUser` rejected and we're unhappy');
27708              }).then(function (value) {
27709                // never reached
27710              }, function (reason) {
27711                // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
27712                // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
27713              });
27714              ```
27715              If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
27716            
27717              ```js
27718              findUser().then(function (user) {
27719                throw new PedagogicalException('Upstream error');
27720              }).then(function (value) {
27721                // never reached
27722              }).then(function (value) {
27723                // never reached
27724              }, function (reason) {
27725                // The `PedgagocialException` is propagated all the way down to here
27726              });
27727              ```
27728            
27729              Assimilation
27730              ------------
27731            
27732              Sometimes the value you want to propagate to a downstream promise can only be
27733              retrieved asynchronously. This can be achieved by returning a promise in the
27734              fulfillment or rejection handler. The downstream promise will then be pending
27735              until the returned promise is settled. This is called *assimilation*.
27736            
27737              ```js
27738              findUser().then(function (user) {
27739                return findCommentsByAuthor(user);
27740              }).then(function (comments) {
27741                // The user's comments are now available
27742              });
27743              ```
27744            
27745              If the assimliated promise rejects, then the downstream promise will also reject.
27746            
27747              ```js
27748              findUser().then(function (user) {
27749                return findCommentsByAuthor(user);
27750              }).then(function (comments) {
27751                // If `findCommentsByAuthor` fulfills, we'll have the value here
27752              }, function (reason) {
27753                // If `findCommentsByAuthor` rejects, we'll have the reason here
27754              });
27755              ```
27756            
27757              Simple Example
27758              --------------
27759            
27760              Synchronous Example
27761            
27762              ```javascript
27763              let result;
27764            
27765              try {
27766                result = findResult();
27767                // success
27768              } catch(reason) {
27769                // failure
27770              }
27771              ```
27772            
27773              Errback Example
27774            
27775              ```js
27776              findResult(function(result, err){
27777                if (err) {
27778                  // failure
27779                } else {
27780                  // success
27781                }
27782              });
27783              ```
27784            
27785              Promise Example;
27786            
27787              ```javascript
27788              findResult().then(function(result){
27789                // success
27790              }, function(reason){
27791                // failure
27792              });
27793              ```
27794            
27795              Advanced Example
27796              --------------
27797            
27798              Synchronous Example
27799            
27800              ```javascript
27801              let author, books;
27802            
27803              try {
27804                author = findAuthor();
27805                books  = findBooksByAuthor(author);
27806                // success
27807              } catch(reason) {
27808                // failure
27809              }
27810              ```
27811            
27812              Errback Example
27813            
27814              ```js
27815            
27816              function foundBooks(books) {
27817            
27818              }
27819            
27820              function failure(reason) {
27821            
27822              }
27823            
27824              findAuthor(function(author, err){
27825                if (err) {
27826                  failure(err);
27827                  // failure
27828                } else {
27829                  try {
27830                    findBoooksByAuthor(author, function(books, err) {
27831                      if (err) {
27832                        failure(err);
27833                      } else {
27834                        try {
27835                          foundBooks(books);
27836                        } catch(reason) {
27837                          failure(reason);
27838                        }
27839                      }
27840                    });
27841                  } catch(error) {
27842                    failure(err);
27843                  }
27844                  // success
27845                }
27846              });
27847              ```
27848            
27849              Promise Example;
27850            
27851              ```javascript
27852              findAuthor().
27853                then(findBooksByAuthor).
27854                then(function(books){
27855                  // found books
27856              }).catch(function(reason){
27857                // something went wrong
27858              });
27859              ```
27860            
27861              @method then
27862              @param {Function} onFulfilled
27863              @param {Function} onRejected
27864              Useful for tooling.
27865              @return {Promise}
27866            */
27867            then: then,
27868
27869            /**
27870              `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
27871              as the catch block of a try/catch statement.
27872            
27873              ```js
27874              function findAuthor(){
27875                throw new Error('couldn't find that author');
27876              }
27877            
27878              // synchronous
27879              try {
27880                findAuthor();
27881              } catch(reason) {
27882                // something went wrong
27883              }
27884            
27885              // async with promises
27886              findAuthor().catch(function(reason){
27887                // something went wrong
27888              });
27889              ```
27890            
27891              @method catch
27892              @param {Function} onRejection
27893              Useful for tooling.
27894              @return {Promise}
27895            */
27896            'catch': function _catch(onRejection) {
27897              return this.then(null, onRejection);
27898            }
27899          };
27900          /*global self*/
27901
27902          function polyfill$1() {
27903            var local = undefined;
27904
27905            if (typeof global !== 'undefined') {
27906              local = global;
27907            } else if (typeof self !== 'undefined') {
27908              local = self;
27909            } else {
27910              try {
27911                local = Function('return this')();
27912              } catch (e) {
27913                throw new Error('polyfill failed because global object is unavailable in this environment');
27914              }
27915            }
27916
27917            var P = local.Promise;
27918
27919            if (P) {
27920              var promiseToString = null;
27921
27922              try {
27923                promiseToString = Object.prototype.toString.call(P.resolve());
27924              } catch (e) {// silently ignored
27925              }
27926
27927              if (promiseToString === '[object Promise]' && !P.cast) {
27928                return;
27929              }
27930            }
27931
27932            local.Promise = Promise$2;
27933          } // Strange compat..
27934
27935
27936          Promise$2.polyfill = polyfill$1;
27937          Promise$2.Promise = Promise$2;
27938          return Promise$2;
27939        });
27940      }).call(this, _dereq_('_process'), typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {});
27941    }, {
vendor: 4,224 bytes, lines 27942-28061
27942      "_process": 11
27943    }],
27944    6: [function (_dereq_, module, exports) {
27945      (function (global, factory) {
27946        if (typeof define === 'function' && define.amd) {
27947          define(['exports', 'module'], factory);
27948        } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
27949          factory(exports, module);
27950        } else {
27951          var mod = {
27952            exports: {}
27953          };
27954          factory(mod.exports, mod);
27955          global.fetchJsonp = mod.exports;
27956        }
27957      })(this, function (exports, module) {
27958        'use strict';
27959
27960        var defaultOptions = {
27961          timeout: 5000,
27962          jsonpCallback: 'callback',
27963          jsonpCallbackFunction: null
27964        };
27965
27966        function generateCallbackFunction() {
27967          return 'jsonp_' + Date.now() + '_' + Math.ceil(Math.random() * 100000);
27968        }
27969
27970        function clearFunction(functionName) {
27971          // IE8 throws an exception when you try to delete a property on window
27972          // http://stackoverflow.com/a/1824228/751089
27973          try {
27974            delete window[functionName];
27975          } catch (e) {
27976            window[functionName] = undefined;
27977          }
27978        }
27979
27980        function removeScript(scriptId) {
27981          var script = document.getElementById(scriptId);
27982
27983          if (script) {
27984            document.getElementsByTagName('head')[0].removeChild(script);
27985          }
27986        }
27987
27988        function fetchJsonp(_url) {
27989          var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; // to avoid param reassign
27990
27991          var url = _url;
27992          var timeout = options.timeout || defaultOptions.timeout;
27993          var jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback;
27994          var timeoutId = undefined;
27995          return new Promise(function (resolve, reject) {
27996            var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction();
27997            var scriptId = jsonpCallback + '_' + callbackFunction;
27998
27999            window[callbackFunction] = function (response) {
28000              resolve({
28001                ok: true,
28002                // keep consistent with fetch API
28003                json: function json() {
28004                  return Promise.resolve(response);
28005                }
28006              });
28007              if (timeoutId) clearTimeout(timeoutId);
28008              removeScript(scriptId);
28009              clearFunction(callbackFunction);
28010            }; // Check if the user set their own params, and if not add a ? to start a list of params
28011
28012
28013            url += url.indexOf('?') === -1 ? '?' : '&';
28014            var jsonpScript = document.createElement('script');
28015            jsonpScript.setAttribute('src', '' + url + jsonpCallback + '=' + callbackFunction);
28016
28017            if (options.charset) {
28018              jsonpScript.setAttribute('charset', options.charset);
28019            }
28020
28021            jsonpScript.id = scriptId;
28022            document.getElementsByTagName('head')[0].appendChild(jsonpScript);
28023            timeoutId = setTimeout(function () {
28024              reject(new Error('JSONP request to ' + _url + ' timed out'));
28025              clearFunction(callbackFunction);
28026              removeScript(scriptId);
28027
28028              window[callbackFunction] = function () {
28029                clearFunction(callbackFunction);
28030              };
28031            }, timeout); // Caught if got 404/500
28032
28033            jsonpScript.onerror = function () {
28034              reject(new Error('JSONP request to ' + _url + ' failed'));
28035              clearFunction(callbackFunction);
28036              removeScript(scriptId);
28037              if (timeoutId) clearTimeout(timeoutId);
28038            };
28039          });
28040        } // export as global function
28041
28042        /*
28043        let local;
28044        if (typeof global !== 'undefined') {
28045          local = global;
28046        } else if (typeof self !== 'undefined') {
28047          local = self;
28048        } else {
28049          try {
28050            local = Function('return this')();
28051          } catch (e) {
28052            throw new Error('polyfill failed because global object is unavailable in this environment');
28053          }
28054        }
28055        local.fetchJsonp = fetchJsonp;
28056        */
28057
28058
28059        module.exports = fetchJsonp;
28060      });
28061    }, {}],
28062    7: [function (_dereq_, module, exports) {
28063      /* FileSaver.js
28064       * A saveAs() FileSaver implementation.
28065       * 1.3.2
28066       * 2016-06-16 18:25:19
28067       *
28068       * By Eli Grey, http://eligrey.com
28069       * License: MIT
28070       *   See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
28071       */
28072
28073      /*global self */
28074
28075      /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
28076
28077      /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
28078      var saveAs = saveAs || function (view) {
28079        "use strict"; // IE <10 is explicitly unsupported
28080
28081        if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
28082          return;
28083        }
28084
28085        var doc = view.document // only get URL when necessary in case Blob.js hasn't overridden it yet
28086        ,
28087            get_URL = function () {
28088          return view.URL || view.webkitURL || view;
28089        },
28090            save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"),
28091            can_use_save_link = "download" in save_link,
28092            click = function (node) {
28093          var event = new MouseEvent("click");
28094          node.dispatchEvent(event);
28095        },
28096            is_safari = /constructor/i.test(view.HTMLElement) || view.safari,
28097            is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent),
28098            throw_outside = function (ex) {
28099          (view.setImmediate || view.setTimeout)(function () {
28100            throw ex;
28101          }, 0);
28102        },
28103            force_saveable_type = "application/octet-stream" // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
28104        ,
28105            arbitrary_revoke_timeout = 1000 * 40 // in ms
28106        ,
28107            revoke = function (file) {
28108          var revoker = function () {
28109            if (typeof file === "string") {
28110              // file is an object URL
28111              get_URL().revokeObjectURL(file);
28112            } else {
28113              // file is a File
28114              file.remove();
28115            }
28116          };
28117
28118          setTimeout(revoker, arbitrary_revoke_timeout);
28119        },
28120            dispatch = function (filesaver, event_types, event) {
28121          event_types = [].concat(event_types);
28122          var i = event_types.length;
28123
28124          while (i--) {
28125            var listener = filesaver["on" + event_types[i]];
28126
28127            if (typeof listener === "function") {
28128              try {
28129                listener.call(filesaver, event || filesaver);
28130              } catch (ex) {
28131                throw_outside(ex);
28132              }
28133            }
28134          }
28135        },
28136            auto_bom = function (blob) {
28137          // prepend BOM for UTF-8 XML and text/* types (including HTML)
28138          // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
28139          if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
28140            return new Blob([String.fromCharCode(0xFEFF), blob], {
28141              type: blob.type
28142            });
28143          }
28144
28145          return blob;
28146        },
28147            FileSaver = function (blob, name, no_auto_bom) {
28148          if (!no_auto_bom) {
28149            blob = auto_bom(blob);
28150          } // First try a.download, then web filesystem, then object URLs
28151
28152
28153          var filesaver = this,
28154              type = blob.type,
28155              force = type === force_saveable_type,
28156              object_url,
28157              dispatch_all = function () {
28158            dispatch(filesaver, "writestart progress write writeend".split(" "));
28159          } // on any filesys errors revert to saving with object URLs
28160          ,
28161              fs_error = function () {
28162            if ((is_chrome_ios || force && is_safari) && view.FileReader) {
28163              // Safari doesn't allow downloading of blob urls
28164              var reader = new FileReader();
28165
28166              reader.onloadend = function () {
28167                var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
28168                var popup = view.open(url, '_blank');
28169                if (!popup) view.location.href = url;
28170                url = undefined; // release reference before dispatching
28171
28172                filesaver.readyState = filesaver.DONE;
28173                dispatch_all();
28174              };
28175
vendor: 1,104 bytes, lines 28176-28207
28176              reader.readAsDataURL(blob);
28177              filesaver.readyState = filesaver.INIT;
28178              return;
28179            } // don't create more object URLs than needed
28180
28181
28182            if (!object_url) {
28183              object_url = get_URL().createObjectURL(blob);
28184            }
28185
28186            if (force) {
28187              view.location.href = object_url;
28188            } else {
28189              var opened = view.open(object_url, "_blank");
28190
28191              if (!opened) {
28192                // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
28193                view.location.href = object_url;
28194              }
28195            }
28196
28197            filesaver.readyState = filesaver.DONE;
28198            dispatch_all();
28199            revoke(object_url);
28200          };
28201
28202          filesaver.readyState = filesaver.INIT;
28203
28204          if (can_use_save_link) {
28205            object_url = get_URL().createObjectURL(blob);
28206            setTimeout(function () {
28207              save_link.href = object_url;
28208              save_link.download = name;
28209              click(save_link);
28210              dispatch_all();
28211              revoke(object_url);
28212              filesaver.readyState = filesaver.DONE;
28213            });
28214            return;
28215          }
28216
28217          fs_error();
28218        },
28219            FS_proto = FileSaver.prototype,
28220            saveAs = function (blob, name, no_auto_bom) {
28221          return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
28222        }; // IE 10+ (native saveAs)
28223
28224
28225        if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
28226          return function (blob, name, no_auto_bom) {
28227            name = name || blob.name || "download";
28228
28229            if (!no_auto_bom) {
28230              blob = auto_bom(blob);
28231            }
28232
28233            return navigator.msSaveOrOpenBlob(blob, name);
28234          };
28235        }
28236
28237        FS_proto.abort = function () {};
28238
28239        FS_proto.readyState = FS_proto.INIT = 0;
28240        FS_proto.WRITING = 1;
28241        FS_proto.DONE = 2;
28242        FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null;
28243        return saveAs;
28244      }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content); // `self` is undefined in Firefox for Android content script context
28245      // while `this` is nsIContentFrameMessageManager
28246      // with an attribute `content` that corresponds to the window
28247
28248
28249      if (typeof module !== "undefined" && module.exports) {
28250        module.exports.saveAs = saveAs;
28251      } else if (typeof define !== "undefined" && define !== null && define.amd !== null) {
28252        define("FileSaver.js", function () {
28253          return saveAs;
28254        });
28255      }
28256    }, {}],
28257    8: [function (_dereq_, module, exports) {
28258      exports.read = function (buffer, offset, isLE, mLen, nBytes) {
28259        var e, m;
28260        var eLen = nBytes * 8 - mLen - 1;
28261        var eMax = (1 << eLen) - 1;
28262        var eBias = eMax >> 1;
28263        var nBits = -7;
28264        var i = isLE ? nBytes - 1 : 0;
28265        var d = isLE ? -1 : 1;
28266        var s = buffer[offset + i];
28267        i += d;
28268        e = s & (1 << -nBits) - 1;
28269        s >>= -nBits;
28270        nBits += eLen;
28271
28272        for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
28273
28274        m = e & (1 << -nBits) - 1;
28275        e >>= -nBits;
28276        nBits += mLen;
28277
28278        for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
28279
28280        if (e === 0) {
28281          e = 1 - eBias;
28282        } else if (e === eMax) {
28283          return m ? NaN : (s ? -1 : 1) * Infinity;
28284        } else {
28285          m = m + Math.pow(2, mLen);
28286          e = e - eBias;
28287        }
28288
28289        return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
28290      };
28291
28292      exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
28293        var e, m, c;
28294        var eLen = nBytes * 8 - mLen - 1;
28295        var eMax = (1 << eLen) - 1;
28296        var eBias = eMax >> 1;
28297        var rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0;
28298        var i = isLE ? 0 : nBytes - 1;
28299        var d = isLE ? 1 : -1;
28300        var s = value < 0 || value === 0 && 1 / value < 0 ? 1 : 0;
28301        value = Math.abs(value);
28302
28303        if (isNaN(value) || value === Infinity) {
28304          m = isNaN(value) ? 1 : 0;
28305          e = eMax;
28306        } else {
28307          e = Math.floor(Math.log(value) / Math.LN2);
28308
28309          if (value * (c = Math.pow(2, -e)) < 1) {
28310            e--;
28311            c *= 2;
28312          }
28313
28314          if (e + eBias >= 1) {
28315            value += rt / c;
28316          } else {
28317            value += rt * Math.pow(2, 1 - eBias);
28318          }
28319
28320          if (value * c >= 2) {
28321            e++;
28322            c /= 2;
28323          }
28324
28325          if (e + eBias >= eMax) {
28326            m = 0;
28327            e = eMax;
28328          } else if (e + eBias >= 1) {
28329            m = (value * c - 1) * Math.pow(2, mLen);
28330            e = e + eBias;
28331          } else {
28332            m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
28333            e = 0;
28334          }
28335        }
28336
28337        for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
28338
28339        e = e << mLen | m;
28340        eLen += mLen;
28341
28342        for (; eLen > 0;
28342 buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
28343
28344        buffer[offset + i - d] |= s * 128;
28345      };
28346    }, {}],
28347    9: [function (_dereq_, module, exports) {
28348      /*
28349      
28350       Copyright 2000, Silicon Graphics, Inc. All Rights Reserved.
28351       Copyright 2015, Google Inc. All Rights Reserved.
28352      
28353       Permission is hereby granted, free of charge, to any person obtaining a copy
28354       of this software and associated documentation files (the "Software"), to
28355       deal in the Software without restriction, including without limitation the
28356       rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
28357       sell copies of the Software, and to permit persons to whom the Software is
28358       furnished to do so, subject to the following conditions:
28359      
28360       The above copyright notice including the dates of first publication and
28361       either this permission notice or a reference to http://oss.sgi.com/projects/FreeB/
28362       shall be included in all copies or substantial portions of the Software.
28363      
28364       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28365       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28366       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28367       SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28368       WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
28369       IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28370      
28371       Original Code. The Original Code is: OpenGL Sample Implementation,
28372       Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
28373       Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
28374       Copyright in any portions created by third parties is as indicated
28375       elsewhere herein. All Rights Reserved.
28376      */
28377      'use strict';
28378
28379      var n;
28380
28381      function t(a, b) {
28382        return a.b === b.b && a.a === b.a;
28383      }
28384
28385      function u(a, b) {
28386        return a.b < b.b || a.b === b.b && a.a <= b.a;
28387      }
28388
28389      function v(a, b, c) {
28390        var d = b.b - a.b,
28391            e = c.b - b.b;
28392        return 0 < d + e ? d < e ? b.a - a.a + d / (d + e) * (a.a - c.a) : b.a - c.a + e / (d + e) * (c.a - a.a) : 0;
28393      }
28394
28395      function x(a, b, c) {
28396        var d = b.b - a.b,
28397            e = c.b - b.b;
28398        return 0 < d + e ? (b.a - c.a) * d + (b.a - a.a) * e : 0;
28399      }
28400
28401      function z(a, b) {
28402        return a.a < b.a || a.a === b.a && a.b <= b.b;
28403      }
28404
28405      function aa(a, b, c) {
28406        var d = b.a - a.a,
28407            e = c.a - b.a;
28408        return 0 < d + e ? d < e ? b.b - a.b + d / (d + e) * (a.b - c.b) : b.b - c.b + e / (d + e) * (c.b - a.b) : 0;
28409      }
28410
28411      function ba(a, b, c) {
28412        var d = b.a - a.a,
28413            e = c.a - b.a;
28414        return 0 < d + e ? (b.b - c.b) * d + (b.b - a.b) * e : 0;
28415      }
28416
28417      function ca(a) {
28418        return u(a.b.a, a.a);
28419      }
28420
28421      function da(a) {
28422        return u(a.a, a.b.a);
28423      }
28424
28425      function A(a, b, c, d) {
28426        a = 0 > a ? 0 : a;
28427        c = 0 > c ? 0 : c;
28428        return a <= c ? 0 === c ? (b + d) / 2 : b + a / (a + c) * (d - b) : d + c / (a + c) * (b - d);
28429      }
28430
28431      ;
28432
28433      function ea(a) {
28434        var b = B(a.b);
28435        C(b, a.c);
28436        C(b.b, a.c);
28437        D(b, a.a);
28438        return b;
28439      }
28440
28441      function E(a, b) {
28442        var c = !1,
28443            d = !1;
28444        a !== b && (b.a !== a.a && (d = !0, F(b.a, a.a)), b.d !== a.d && (c = !0, G(b.d, a.d)), H(b, a), d || (C(b, a.a), a.a.c = a), c || (D(b, a.d), a.d.a = a));
28445      }
28446
28447      function I(a) {
28448        var b = a.b,
28449            c = !1;
28450        a.d !== a.b.d && (c = !0, G(a.d, a.b.d));
28451        a.c === a ? F(a.a, null) : (a.b.d.a = J(a), a.a.c = a.c, H(a, J(a)), c || D(a, a.d));
28452        b.c === b ? (F(b.a, null), G(b.d, null)) : (a.d.a = J(b), b.a.c = b.c, H(b, J(b)));
28453        fa(a);
28454      }
28455
28456      function K(a) {
28457        var b = B(a),
28458            c = b.b;
28459        H(b, a.e);
28460        b.a = a.b.a;
28461        C(c, b.a);
28462        b.d = c.d = a.d;
28463        b = b.b;
28464        H(a.b, J(a.b));
28465        H(a.b, b);
28466        a.b.a = b.a;
28467        b.b.a.c = b.b;
28468        b.b.d = a.b.d;
28469        b.f = a.f;
28470        b.b.f = a.b.f;
28471        return b;
28472      }
28473
28474      function L(a, b) {
28475        var c = !1,
28476            d = B(a),
28477            e = d.b;
28478        b.d !== a.d && (c = !0, G(b.d, a.d));
28479        H(d, a.e);
28480        H(e, b);
28481        d.a = a.b.a;
28482        e.a = b.a;
28483        d.d = e.d = a.d;
28484        a.d.a = e;
28485        c || D(d, a.d);
28486        return d;
28487      }
28488
28489      function B(a) {
28490        var b = new M(),
28491            c = new M(),
28492            d = a.b.h;
28493        c.h = d;
28494        d.b.h = b;
28495        b.h = a;
28496        a.b.h = c;
28497        b.b = c;
28498        b.c = b;
28499        b.e = c;
28500        c.b = b;
28501        c.c = c;
28502        return c.e = b;
28503      }
28504
28505      function H(a, b) {
28506        var c = a.c,
28507            d = b.c;
28508        c.b.e = b;
28509        d.b.e = a;
28510        a.c = d;
28511        b.c = c;
28512      }
28513
28514      function C(a, b) {
28515        var c = b.f,
28516            d = new N(b, c);
28517        c.e = d;
28518        b.f = d;
28519        c = d.c = a;
28520
28521        do c.a = d, c = c.c; while (c !== a);
28522      }
28523
28524      function D(a, b) {
28525        var c = b.d,
28526            d = new ga(b, c);
28527        c.b = d;
28528        b.d = d;
28529        d.a = a;
28530        d.c = b.c;
28531        c = a;
28532
28533        do c.d = d, c = c.e; while (c !== a);
28534      }
28535
28536      function fa(a) {
28537        var b = a.h;
28538        a = a.b.h;
28539        b.b.h = a;
28540        a.b.h = b;
28541      }
28542
28543      function F(a, b) {
28544        var c = a.c,
28545            d = c;
28546
28547        do d.a = b, d = d.c; while (d !== c);
28548
28549        c = a.f;
28550        d = a.e;
28551        d.f = c;
28552        c.e = d;
28553      }
28554
28555      function G(a, b) {
28556        var c = a.a,
28557            d = c;
28558
28559        do d.d = b, d = d.e; while (d !== c);
28560
28561        c = a.d;
28562        d = a.b;
28563        d.d = c;
28564        c.b = d;
28565      }
28566
28567      ;
28568
28569      function ha(a) {
28570        var b = 0;
28571        Math.abs(a[1]) > Math.abs(a[0]) && (b = 1);
28572        Math.abs(a[2]) > Math.abs(a[b]) && (b = 2);
28573        return b;
28574      }
28575
28576      ;
28577      var O = 4 * 1E150;
28578
28579      function P(a, b) {
28580        a.f += b.f;
28581        a.b.f += b.b.f;
28582      }
28583
28584      function ia(a, b, c) {
28585        a = a.a;
28586        b = b.a;
28587        c = c.a;
28588        if (b.b.a === a) return c.b.a === a ? u(b.a, c.a) ? 0 >= x(c.b.a, b.a, c.a) : 0 <= x(b.b.a, c.a, b.a) : 0 >= x(c.b.a, a, c.a);
28589        if (c.b.a === a) return 0 <= x(b.b.a, a, b.a);
28590        b = v(b.b.a, a, b.a);
28591        a = v(c.b.a, a, c.a);
28592        return b >= a;
28593      }
28594
28595      function Q(a) {
28596        a.a.i = null;
28597        var b = a.e;
28598        b.a.c = b.c;
28599        b.c.a = b.a;
28600        a.e = null;
28601      }
28602
28603      function ja(a, b) {
28604        I(a.a);
28605        a.c = !1;
28606        a.a = b;
28607        b.i = a;
28608      }
28609
28610      function ka(a) {
28611        var b = a.a.a;
28612
28613        do a = R(a); while (a.a.a === b);
28614
28615        a.c && (b = L(S(a).a.b, a.a.e), ja(a, b), a = R(a));
28616        return a;
28617      }
28618
28619      function la(a, b, c) {
28620        var d = new ma();
28621        d.a = c;
28622        d.e = na(a.f, b.e, d);
28623        return c.i = d;
28624      }
28625
28626      function oa(a, b) {
28627        switch (a.s) {
28628          case 100130:
28629            return 0 !== (b & 1);
28630
28631          case 100131:
28632            return 0 !== b;
28633
28634          case 100132:
28635            return 0 < b;
28636
28637          case 100133:
28638            return 0 > b;
28639
28640          case 100134:
28641            return 2 <= b || -2 >= b;
28642        }
28643
28644        return !1;
28645      }
28646
28647      function pa(a) {
28648        var b = a.a,
28649            c = b.d;
28650        c.c = a.d;
28651        c.a = b;
28652        Q(a);
28653      }
28654
28655      function T(a, b, c) {
28656        a = b;
28657
28658        for (b = b.a; a !== c;) {
28659          a.c = !1;
28660          var d = S(a),
28661              e = d.a;
28662
28663          if (e.a !== b.a) {
28664            if (!d.c) {
28665              pa(a);
28666              break;
28667            }
28668
28669            e = L(b.c.b, e.b);
28670            ja(d, e);
28671          }
28672
28673          b.c !== e && (E(J(e), e), E(b, e));
28674          pa(a);
28675          b = d.a;
28676          a = d;
28677        }
28678
28679        return b;
28680      }
28681
28682      function U(a, b, c, d, e, f) {
28683        var g = !0;
28684
28685        do la(a, b, c.b), c = c.c; while (c !== d);
28686
28687        for (null === e && (e = S(b).a.b.c);;) {
28688          d = S(b);
28689          c = d.a.b;
28690          if (c.a !== e.a) break;
28691          c.c !== e && (E(J(c), c), E(J(e), c));
28692          d.f = b.f - c.f;
28693          d.d = oa(a, d.f);
28694          b.b = !0;
28695          !g && qa(a, b) && (P(c, e), Q(b), I(e));
28696          g = !1;
28697          b = d;
28698          e = c;
28699        }
28700
28701        b.b = !0;
28702        f && ra(a, b);
28703      }
28704
28705      function sa(a, b, c, d, e) {
28706        var f = [b.g[0], b.g[1], b.g[2]];
28707        b.d = null;
28708        b.d = a.o ? a.o(f, c, d, a.c) || null : null;
28709        null === b.d && (e ? a.n || (V(a, 100156), a.n = !0) : b.d = c[0]);
28710      }
28711
28712      function ta(a, b, c) {
28713        var d = [null, null, null, null];
28714        d[0] = b.a.d;
28715        d[1] = c.a.d;
28716        sa(a, b.a, d, [.5, .5, 0, 0], !1);
28717        E(b, c);
28718      }
28719
28720      function ua(a, b, c, d, e) {
28721        var f = Math.abs(b.b - a.b) + Math.abs(b.a - a.a),
28722            g = Math.abs(c.b - a.b) + Math.abs(c.a - a.a),
28723            h = e + 1;
28724        d[e] = .5 * g / (f + g);
28725        d[h] = .5 * f / (f + g);
28726        a.g[0] += d[e] * b.g[0] + d[h] * c.g[0];
28727        a.g[1] += d[e] * b.g[1] + d[h] * c.g[1];
28728        a.g[2] += d[e] * b.g[2] + d[h] * c.g[2];
28729      }
28730
28731      function qa(a, b) {
28732        var c = S(b),
28733            d = b.a,
28734            e = c.a;
28735
28736        if (u(d.a, e.a)) {
28737          if (0 < x(e.b.a, d.a, e.a)) return !1;
28738          if (!t(d.a, e.a)) K(e.b), E(d, J(e)), b.b = c.b = !0;else if (d.a !== e.a) {
28739            var c = a.e,
28740                f = d.a.h;
28741
28742            if (0 <= f) {
28743              var c = c.b,
28744                  g = c.d,
28745                  h = c.e,
28746                  k = c.c,
28747                  l = k[f];
28748              g[l] = g[c.a];
28749              k[g[l]] = l;
28750              l <= --c.a && (1 >= l ? W(c, l) : u(h[g[l >> 1]], h[g[l]]) ? W(c, l) : va(c, l));
28751              h[f] = null;
28752              k[f] = c.b;
28753              c.b = f;
28754            } else for (c.c[-(f + 1)] = null; 0 < c.a && null === c.c[c.d[c.a - 1]];) --c.a;
28755
28756            ta(a, J(e), d);
28757          }
28758        } else {
28759          if (0 > x(d.b.a, e.a, d.a)) return !1;
28760          R(b).b = b.b = !0;
28761          K(d.b);
28762          E(J(e), d);
28763        }
28764
28765        return !0;
28766      }
28767
28768      function wa(a, b) {
28769        var c = S(b),
28770            d = b.a,
28771            e = c.a,
28772            f = d.a,
28773            g = e.a,
28774            h = d.b.a,
28775            k = e.b.a,
28776            l = new N();
28777        x(h, a.a, f);
28778        x(k, a.a, g);
28779        if (f === g || Math.min(f.a, h.a) > Math.max(g.a, k.a)) return !1;
28780
28781        if (u(f, g)) {
28782          if (0 < x(k, f, g)) return !1;
28783        } else if (0 > x(h, g, f)) return !1;
28784
28785        var r = h,
28786            p = f,
28787            q = k,
28788            y = g,
28789            m,
28790            w;
28791        u(r, p) || (m = r, r = p, p = m);
28792        u(q, y) || (m = q, q = y, y = m);
28793        u(r, q) || (m = r, r = q, q = m, m = p, p = y, y = m);
28794        u(q, p) ? u(p, y) ? (m = v(r, q, p), w = v(q, p, y), 0 > m + w && (m = -m, w = -w), l.b = A(m, q.b, w, p.b)) : (m = x(r, q, p), w = -x(r, y, p), 0 > m + w && (m = -m, w = -w), l.b = A(m, q.b, w, y.b)) : l.b = (q.b + p.b) / 2;
28795        z(r, p) || (m = r, r = p, p = m);
28796        z(q, y) || (m = q, q = y, y = m);
28797        z(r, q) || (m = r, r = q, q = m, m = p, p = y, y = m);
28798        z(q, p) ? z(p, y) ? (m = aa(r, q, p), w = aa(q, p, y), 0 > m + w && (m = -m, w = -w), l.a = A(m, q.a, w, p.a)) : (m = ba(r, q, p), w = -ba(r, y, p), 0 > m + w && (m = -m, w = -w), l.a = A(m, q.a, w, y.a)) : l.a = (q.a + p.a) / 2;
28799        u(l, a.a) && (l.b = a.a.b, l.a = a.a.a);
28800        r = u(f, g) ? f : g;
28801        u(r, l) && (l.b = r.b, l.a = r.a);
28802        if (t(l, f) || t(l, g)) return qa(a, b), !1;
28803
28804        if (!t(h, a.a) && 0 <= x(h, a.a, l) || !t(k, a.a) && 0 >= x(k, a.a, l)) {
28805          if (k === a.a) return K(d.b), E(e.b, d), b = ka(b), d = S(b).a, T(a, S(b), c), U(a, b, J(d), d, d, !0), !0;
28806
28807          if (h === a.a) {
28808            K(e.b);
28809            E(d.e, J(e));
28810            f = c = b;
28811            g = f.a.b.a;
28812
28813            do f = R(f); while (f.a.b.a === g);
28814
28815            b = f;
28816            f = S(b).a.b.c;
28817            c.a = J(e);
28818            e = T(a, c, null);
28819            U(a, b, e.c, d.b.c, f, !0);
28820            return !0;
28821          }
28822
28823          0 <= x(h, a.a, l) && (R(b).b = b.b = !0, K(d.b), d.a.b = a.a.b, d.a.a = a.a.a);
28824          0 >= x(k, a.a, l) && (b.b = c.b = !0, K(e.b), e.a.b = a.a.b, e.a.a = a.a.a);
28825          return !1;
28826        }
28827
28828        K(d.b);
28829        K(e.b);
28830        E(J(e), d);
28831        d.a.b = l.b;
28832        d.a.a = l.a;
28833        d.a.h = xa(a.e, d.a);
28834        d = d.a;
28835        e = [0, 0, 0, 0];
28836        l = [f.d, h.d, g.d, k.d];
28837        d.g[0] = d.g[1] = d.g[2] = 0;
28838        ua(d, f, h, e, 0);
28839        ua(d, g, k, e, 2);
28840        sa(a, d, l, e, !0);
28841        R(b).b = b.b = c.b = !0;
28842        return !1;
28843      }
28844
28845      function ra(a, b) {
28846        for (var c = S(b);;) {
28847          for (; c.b;) b = c, c = S(c);
28848
28849          if (!b.b && (c = b, b = R(b), null === b || !b.b)) break;
28850          b.b = !1;
28851          var d = b.a,
28852              e = c.a,
28853              f;
28854          if (f = d.b.a !== e.b.a) a: {
28855            f = b;
28856            var g = S(f),
28857                h = f.a,
28858                k = g.a,
28859                l = void 0;
28860
28861            if (u(h.b.a, k.b.a)) {
28862              if (0 > x(h.b.a, k.b.a, h.a)) {
28863                f = !1;
28864                break a;
28865              }
28866
28867              R(f).b = f.b = !0;
28868              l = K(h);
28869              E(k.b, l);
28870              l.d.c = f.d;
28871            } else {
28872              if (0 < x(k.b.a, h.b.a, k.a)) {
28873                f = !1;
28874                break a;
28875              }
28876
28877              f.b = g.b = !0;
28878              l = K(k);
28879              E(h.e, k.b);
28880              l.b.d.c = f.d;
28881            }
28882
28883            f = !0;
28884          }
28885          f && (c.c ? (Q(c), I(e), c = S(b), e = c.a) : b.c && (Q(b), I(d), b = R(c), d = b.a));
28886          if (d.a !== e.a) if (d.b.a === e.b.a || b.c || c.c || d.b.a !== a.a && e.b.a !== a.a) qa(a, b);else if (wa(a, b)) break;
28887          d.a === e.a && d.b.a === e.b.a && (P(e, d), Q(b), I(d), b = R(c));
28888        }
28889      }
28890
28891      function ya(a, b) {
28892        a.a = b;
28893
28894        for (var c = b.c; null === c.i;) if (c = c.c, c === b.c) {
28895          var c = a,
28896              d = b,
28897              e = new ma();
28898          e.a = d.c.b;
28899          var f = c.f,
28900              g = f.a;
28901
28902          do g = g.a; while (null !== g.b && !f.c(f.b, e, g.b));
28903
28904          var f = g.b,
28905              h = S(f),
28906              e = f.a,
28907              g = h.a;
28908          if (0 === x(e.b.a, d, e.a)) e = f.a, t(e.a, d) || t(e.b.a, d) || (K(e.b), f.c && (I(e.c), f.c = !1), E(d.c, e), ya(c, d));else {
28909            var k = u(g.b.a, e.b.a) ? f : h,
28910                h = void 0;
28911            f.d || k.c ? (k === f ? h = L(d.c.b, e.e) : h = L(g.b.c.b, d.c).b, k.c ? ja(k, h) : (e = c, f = la(c, f, h), f.f = R(f).f + f.a.f, f.d = oa(e, f.f)), ya(c, d)) : U(c, f, d.c, d.c, null, !0);
28912          }
28913          return;
28914        }
28915
28916        c = ka(c.i);
28917        e = S(c);
28918        f = e.a;
28919        e = T(a, e, null);
28920
28921        if (e.c === f) {
28922          var f = e,
28923              e = f.c,
28924              g = S(c),
28925              h = c.a,
28926              k = g.a,
28927              l = !1;
28928          h.b.a !== k.b.a && wa(a, c);
28929          t(h.a, a.a) && (E(J(e), h), c = ka(c), e = S(c).a, T(a, S(c), g), l = !0);
28930          t(k.a, a.a) && (E(f, J(k)), f = T(a, g, null), l = !0);
28931          l ? U(a, c, f.c, e, e, !0) : (u(k.a, h.a) ? d = J(k) : d = h, d = L(f.c.b, d), U(a, c, d, d.c, d.c, !1), d.b.i.c = !0, ra(a, c));
28932        } else U(a, c, e.c, f, f, !0);
28933      }
28934
28935      function za(a, b) {
28936        var c = new ma(),
28937            d = ea(a.b);
28938        d.a.b = O;
28939        d.a.a = b;
28940        d.b.a.b = -O;
28941        d.b.a.a = b;
28942        a.a = d.b.a;
28943        c.a = d;
28944        c.f = 0;
28945        c.d = !1;
28946        c.c = !1;
28947        c.h = !0;
28948        c.b = !1;
28949        d = a.f;
28950        d = na(d, d.a, c);
28951        c.e = d;
28952      }
28953
28954      ;
28955
28956      function Aa(a) {
28957        this.a = new Ba();
28958        this.b = a;
28959        this.c = ia;
28960      }
28961
28962      function na(a, b, c) {
28963        do b = b.c; while (null !== b.b && !a.c(a.b, b.b, c));
28964
28965        a = new Ba(c, b.a, b);
28966        b.a.c = a;
28967        return b.a = a;
28968      }
28969
28970      ;
28971
28972      function Ba(a, b, c) {
28973        this.b = a || null;
28974        this.a = b || this;
28975        this.c = c || this;
28976      }
28977
28978      ;
28979
28980      function X() {
28981        this.d = Y;
28982        this.p = this.b = this.q = null;
28983        this.j = [0, 0, 0];
28984        this.s = 100130;
28985        this.n = !1;
28986        this.o = this.a = this.e = this.f = null;
28987        this.m = !1;
28988        this.c = this.r = this.i = this.k = this.l = this.h = null;
28989      }
28990
28991      var Y = 0;
28992      n = X.prototype;
28993
28994      n.x = function () {
28995        Z(this, Y);
28996      };
28997
28998      n.B = function (a, b) {
28999        switch (a) {
29000          case 100142:
29001            return;
29002
29003          case 100140:
29004            switch (b) {
29005              case 100130:
29006              case 100131:
29007              case 100132:
29008              case 100133:
29009              case 100134:
29010                this.s = b;
29011                return;
29012            }
29013
29014            break;
29015
29016          case 100141:
29017            this.m = !!b;
29018            return;
29019
29020          default:
29021            V(this, 100900);
29022            return;
29023        }
29024
29025        V(this, 100901);
29026      };
29027
29028      n.y = function (a) {
29029        switch (a) {
29030          case 100142:
29031            return 0;
29032
29033          case 100140:
29034            return this.s;
29035
29036          case 100141:
29037            return this.m;
29038
29039          default:
29040            V(this, 100900);
29041        }
29042
29043        return !1;
29044      };
29045
29046      n.A = function (a, b, c) {
29047        this.j[0] = a;
29048        this.j[1] = b;
29049        this.j[2] = c;
29050      };
29051
29052      n.z = function (a, b) {
29053        var c = b ? b : null;
29054
29055        switch (a) {
29056          case 100100:
29057          case 100106:
29058            this.h = c;
29059            break;
29060
29061          case 100104:
29062          case 100110:
29063            this.l = c;
29064            break;
29065
29066          case 100101:
29067          case 100107:
29068            this.k = c;
29069            break;
29070
29071          case 100102:
29072          case 100108:
29073            this.i = c;
29074            break;
29075
29076          case 100103:
29077          case 100109:
29078            this.p = c;
29079            break;
29080
29081          case 100105:
29082          case 100111:
29083            this.o = c;
29084            break;
29085
29086          case 100112:
29087            this.r = c;
29088            break;
29089
29090          default:
29091            V(this, 100900);
29092        }
29093      };
29094
29095      n.C = function (a, b) {
29096        var c = !1,
29097            d = [0, 0, 0];
29098        Z(this, 2);
29099
29100        for (var e = 0; 3 > e; ++e) {
29101          var f = a[e];
29102          -1E150 > f && (f = -1E150, c = !0);
29103          1E150 < f && (f = 1E150, c = !0);
29104          d[e] = f;
29105        }
29106
29107        c && V(this, 100155);
29108        c = this.q;
29109        null === c ? (c = ea(this.b), E(c, c.b)) : (K(c), c = c.e);
29110        c.a.d = b;
29111        c.a.g[0] = d[0];
29112        c.a.g[1] = d[1];
29113        c.a.g[2] = d[2];
29114        c.f = 1;
29115        c.b.f = -1;
29116        this.q = c;
29117      };
29118
29119      n.u = function (a) {
29120        Z(this, Y);
29121        this.d = 1;
29122        this.b = new Ca();
29123        this.c = a;
29124      };
29125
29126      n.t = function () {
29127        Z(this, 1);
29128        this.d = 2;
29129        this.q = null;
29130      };
29131
29132      n.v = function () {
29133        Z(this, 2);
29134        this.d = 1;
29135      };
29136
29137      n.w = function () {
29138        Z(this, 1);
29139        this.d = Y;
29140        var a = this.j[0],
29141            b = this.j[1],
29142            c = this.j[2],
29143            d = !1,
29144            e = [a, b, c];
29145
29146        if (0 === a && 0 === b && 0 === c) {
29147          for (var b = [-2 * 1E150, -2 * 1E150, -2 * 1E150], f = [2 * 1E150, 2 * 1E150, 2 * 1E150], c = [], g = [], d = this.b.c, a = d.e; a !== d; a = a.e) for (var h = 0; 3 > h; ++h) {
29148            var k = a.g[h];
29149            k < f[h] && (f[h] = k, g[h] = a);
29150            k > b[h] && (b[h] = k, c[h] = a);
29151          }
29152
29153          a = 0;
29154          b[1] - f[1] > b[0] - f[0] && (a = 1);
29155          b[2] - f[2] > b[a] - f[a] && (a = 2);
29156          if (f[a] >= b[a]) e[0] = 0, e[1] = 0, e[2] = 1;else {
29157            b = 0;
29158            f = g[a];
29159            c = c[a];
29160            g = [0, 0, 0];
29161            f = [f.g[0] - c.g[0], f.g[1] - c.g[1], f.g[2] - c.g[2]];
29162            h = [0, 0, 0];
29163
29164            for (a = d.e; a !== d; a = a.e) h[0] = a.g[0] - c.g[0], h[1] = a.g[1] - c.g[1], h[2] = a.g[2] - c.g[2], g[0] = f[1] * h[2] - f[2] * h[1], g[1] = f[2] * h[0] - f[0] * h[2], g[2] = f[0] * h[1] - f[1] * h[0], k = g[0] * g[0] + g[1] * g[1] + g[2] * g[2], k > b && (b = k, e[0] = g[0], e[1] = g[1], e[2] = g[2]);
29165
29166            0 >= b && (e[0] = e[1] = e[2] = 0, e[ha(f)] = 1);
29167          }
29168          d = !0;
29169        }
29170
29171        g = ha(e);
29172        a = this.b.c;
29173        b = (g + 1) % 3;
29174        c = (g + 2) % 3;
29175        g = 0 < e[g] ? 1 : -1;
29176
29177        for (e = a.e; e !== a; e = e.e) e.b = e.g[b], e.a = g * e.g[c];
29178
29179        if (d) {
29180          e = 0;
29181          d = this.b.a;
29182
29183          for (a = d.b; a !== d; a = a.b) if (b = a.a, !(0 >= b.f)) {
29184            do e += (b.a.b - b.b.a.b) * (b.a.a + b.b.a.a), b = b.e; while (b !== a.a);
29185          }
29186
29187          if (0 > e) for (e = this.b.c, d = e.e; d !== e; d = d.e) d.a = -d.a;
29188        }
29189
29190        this.n = !1;
29191        e = this.b.b;
29192
29193        for (a = e.h; a !== e; a = d) if (d = a.h, b = a.e, t(a.a, a.b.a) && a.e.e !== a && (ta(this, b, a), I(a), a = b, b = a.e), b.e === a) {
29194          if (b !== a) {
29195            if (b === d || b === d.b) d = d.h;
29196            I(b);
29197          }
29198
29199          if (a === d || a === d.b) d = d.h;
29200          I(a);
29201        }
29202
29203        this.e = e = new Da();
29204        d = this.b.c;
29205
29206        for (a = d.e; a !== d; a = a.e) a.h = xa(e, a);
29207
29208        Ea(e);
29209        this.f = new Aa(this);
29210        za(this, -O);
29211
29212        for (za(this, O); null !== (e = Fa(this.e));) {
29213          for (;;) {
29214            a: if (a = this.e, 0 === a.a) d = Ga(a.b);else if (d = a.c[a.d[a.a - 1]], 0 !== a.b.a && (a = Ga(a.b), u(a, d))) {
29215              d = a;
29216              break a;
29217            }
29218
29219            if (null === d || !t(d, e)) break;
29220            d = Fa(this.e);
29221            ta(this, e.c, d.c);
29222          }
29223
29224          ya(this, e);
29225        }
29226
29227        this.a = this.f.a.a.b.a.a;
29228
29229        for (e = 0; null !== (d = this.f.a.a.b);) d.h || ++e, Q(d);
29230
29231        this.f = null;
29232        e = this.e;
29233        e.b = null;
29234        e.d = null;
29235        this.e = e.c = null;
29236        e = this.b;
29237
29238        for (a = e.a.b; a !== e.a; a = d) d = a.b, a = a.a, a.e.e === a && (P(a.c, a), I(a));
29239
29240        if (!this.n) {
29241          e = this.b;
29242          if (this.m) for (a = e.b.h; a !== e.b; a = d) d = a.h, a.b.d.c !== a.d.c ? a.f = a.d.c ? 1 : -1 : I(a);else for (a = e.a.b; a !== e.a; a = d) if (d = a.b, a.c) {
29243            for (a = a.a; u(a.b.a, a.a); a = a.c.b);
29244
29245            for (; u(a.a, a.b.a); a = a.e);
29246
29247            b = a.c.b;
29248
29249            for (c = void 0; a.e !== b;) if (u(a.b.a, b.a)) {
29250              for (; b.e !== a && (ca(b.e) || 0 >= x(b.a, b.b.a, b.e.b.a));) c = L(b.e, b), b = c.b;
29251
29252              b = b.c.b;
29253            } else {
29254              for (; b.e !== a && (da(a.c.b) || 0 <= x(a.b.a, a.a, a.c.b.a));) c = L(a, a.c.b), a = c.b;
29255
29256              a = a.e;
29257            }
29258
29259            for (; b.e.e !== a;) c = L(b.e, b), b = c.b;
29260          }
29261          if (this.h || this.i || this.k || this.l) if (this.m) for (e = this.b, d = e.a.b; d !== e.a; d = d.b) {
29262            if (d.c) {
29263              this.h && this.h(2, this.c);
29264              a = d.a;
29265
29266              do this.k && this.k(a.a.d, this.c), a = a.e; while (a !== d.a);
29267
29268              this.i && this.i(this.c);
29269            }
29270          } else {
29271            e = this.b;
29272            d = !!this.l;
29273            a = !1;
29274            b = -1;
29275
29276            for (c = e.a.d; c !== e.a; c = c.d) if (c.c) {
29277              a || (this.h && this.h(4, this.c), a = !0);
29278              g = c.a;
29279
29280              do d && (f = g.b.d.c ? 0 : 1, b !== f && (b = f, this.l && this.l(!!b, this.c))), this.k && this.k(g.a.d, this.c), g = g.e; while (g !== c.a);
29281            }
29282
29283            a && this.i && this.i(this.c);
29284          }
29285
29286          if (this.r) {
29287            e = this.b;
29288
29289            for (a = e.a.b; a !== e.a; a = d) if (d = a.b, !a.c) {
29290              b = a.a;
29291              c = b.e;
29292              g = void 0;
29293
29294              do g = c, c = g.e, g.d = null, null === g.b.d && (g.c === g ? F(g.a, null) : (g.a.c = g.c, H(g, J(g))), f = g.b, f.c === f ? F(f.a, null) : (f.a.c = f.c, H(f, J(f))), fa(g)); while (g !== b);
29295
29296              b = a.d;
29297              a = a.b;
29298              a.d = b;
29299              b.b = a;
29300            }
29301
29302            this.r(this.b);
29303            this.c = this.b = null;
29304            return;
29305          }
29306        }
29307
29308        this.b = this.c = null;
29309      };
29310
29311      function Z(a, b) {
29312        if (a.d !== b) for (; a.d !== b;) if (a.d < b) switch (a.d) {
29313          case Y:
29314            V(a, 100151);
29315            a.u(null);
29316            break;
29317
29318          case 1:
29319            V(a, 100152), a.t();
29320        } else switch (a.d) {
29321          case 2:
29322            V(a, 100154);
29323            a.v();
29324            break;
29325
29326          case 1:
29327            V(a, 100153), a.w();
29328        }
29329      }
29330
29331      function V(a, b) {
29332        a.p && a.p(b, a.c);
29333      }
29334
29335      ;
29336
29337      function ga(a, b) {
29338        this.b = a || this;
29339        this.d = b || this;
29340        this.a = null;
29341        this.c = !1;
29342      }
29343
29344      ;
29345
29346      function M() {
29347        this.h = this;
29348        this.i = this.d = this.a = this.e = this.c = this.b = null;
29349        this.f = 0;
29350      }
29351
29352      function J(a) {
29353        return a.b.e;
29354      }
29355
29356      ;
29357
29358      function Ca() {
29359        this.c = new N();
29360        this.a = new ga();
29361        this.b = new M();
29362        this.d = new M();
29363        this.b.b = this.d;
29364        this.d.b = this.b;
29365      }
29366
29367      ;
29368
29369      function N(a, b) {
29370        this.e = a || this;
29371        this.f = b || this;
29372        this.d = this.c = null;
29373        this.g = [0, 0, 0];
29374        this.h = this.a = this.b = 0;
29375      }
29376
29377      ;
29378
29379      function Da() {
29380        this.c = [];
29381        this.d = null;
29382        this.a = 0;
29383        this.e = !1;
29384        this.b = new Ha();
29385      }
29386
29387      function Ea(a) {
29388        a.d = [];
29389
29390        for (var b = 0; b < a.a; b++) a.d[b] = b;
29391
29392        a.d.sort(function (a) {
29393          return function (b, e) {
29394            return u(a[b], a[e]) ? 1 : -1;
29395          };
29396        }(a.c));
29397        a.e = !0;
29398        Ia(a.b);
29399      }
29400
29401      function xa(a, b) {
29402        if (a.e) {
29403          var c = a.b,
29404              d = ++c.a;
29405          2 * d > c.f && (c.f *= 2, c.c = Ja(c.c, c.f + 1));
29406          var e;
29407          0 === c.b ? e = d : (e = c.b, c.b = c.c[c.b]);
29408          c.e[e] = b;
29409          c.c[e] = d;
29410          c.d[d] = e;
29411          c.h && va(c, d);
29412          return e;
29413        }
29414
29415        c = a.a++;
29416        a.c[c] = b;
29417        return -(c + 1);
29418      }
29419
29420      function Fa(a) {
29421        if (0 === a.a) return Ka(a.b);
29422        var b = a.c[a.d[a.a - 1]];
29423        if (0 !== a.b.a && u(Ga(a.b), b)) return Ka(a.b);
29424
29425        do --a.a; while (0 < a.a && null === a.c[a.d[a.a - 1]]);
29426
29427        return b;
29428      }
29429
29430      ;
29431
29432      function Ha() {
29433        this.d = Ja([0], 33);
29434        this.e = [null, null];
29435        this.c = [0, 0];
29436        this.a = 0;
29437        this.f = 32;
29438        this.b = 0;
29439        this.h = !1;
29440        this.d[1] = 1;
29441      }
29442
29443      function Ja(a, b) {
29444        for (var c = Array(b), d = 0; d < a.length; d++) c[d] = a[d];
29445
29446        for (; d < b; d++) c[d] = 0;
29447
29448        return c;
29449      }
29450
29451      function Ia(a) {
29452        for (var b = a.a; 1 <= b; --b) W(a, b);
29453
29454        a.h = !0;
29455      }
29456
29457      function Ga(a) {
29458        return a.e[a.d[1]];
29459      }
29460
29461      function Ka(a) {
29462        var b = a.d,
29463            c = a.e,
29464            d = a.c,
29465            e = b[1],
29466            f = c[e];
29467        0 < a.a && (b[1] = b[a.a], d[b[1]] = 1, c[e] = null, d[e] = a.b, a.b = e, 0 < --a.a && W(a, 1));
29468        return f;
29469      }
29470
29471      function W(a, b) {
29472        for (var c = a.d, d = a.e, e = a.c, f = b, g = c[f];;) {
29473          var h = f << 1;
29474          h < a.a && u(d[c[h + 1]], d[c[h]]) && (h += 1);
29475          var k = c[h];
29476
29477          if (h > a.a || u(d[g], d[k])) {
29478            c[f] = g;
29479            e[g] = f;
29480            break;
29481          }
29482
29483          c[f] = k;
29484          e[k] = f;
29485          f = h;
29486        }
29487      }
29488
29489      function va(a, b) {
29490        for (var c = a.d, d = a.e, e = a.c, f = b, g = c[f];;) {
29491          var h = f >> 1,
29492              k = c[h];
29493
29494          if (0 === h || u(d[k], d[g])) {
29495            c[f] = g;
29496            e[g] = f;
29497            break;
29498          }
29499
29500          c[f] = k;
29501          e[k] = f;
29502          f = h;
29503        }
29504      }
29505
29506      ;
29507
29508      function ma() {
29509        this.e = this.a = null;
29510        this.f = 0;
29511        this.c = this.b = this.h = this.d = !1;
29512      }
29513
29514      function S(a) {
29515        return a.e.c.b;
29516      }
29517
29518      function R(a) {
29519        return a.e.a.b;
29520      }
29521
29522      ;
29523      this.libtess = {
29524        GluTesselator: X,
29525        windingRule: {
29526          GLU_TESS_WINDING_ODD: 100130,
29527          GLU_TESS_WINDING_NONZERO: 100131,
29528          GLU_TESS_WINDING_POSITIVE: 100132,
29529          GLU_TESS_WINDING_NEGATIVE: 100133,
29530          GLU_TESS_WINDING_ABS_GEQ_TWO: 100134
29531        },
29532        primitiveType: {
29533          GL_LINE_LOOP: 2,
29534          GL_TRIANGLES: 4,
29535          GL_TRIANGLE_STRIP: 5,
29536          GL_TRIANGLE_FAN: 6
29537        },
29538        errorType: {
29539          GLU_TESS_MISSING_BEGIN_POLYGON: 100151,
29540          GLU_TESS_MISSING_END_POLYGON: 100153,
29541          GLU_TESS_MISSING_BEGIN_CONTOUR: 100152,
29542          GLU_TESS_MISSING_END_CONTOUR: 100154,
29543          GLU_TESS_COORD_TOO_LARGE: 100155,
29544          GLU_TESS_NEED_COMBINE_CALLBACK: 100156
29545        },
29546        gluEnum: {
29547          GLU_TESS_MESH: 100112,
29548          GLU_TESS_TOLERANCE: 100142,
29549          GLU_TESS_WINDING_RULE: 100140,
29550          GLU_TESS_BOUNDARY_ONLY: 100141,
29551          GLU_INVALID_ENUM: 100900,
29552          GLU_INVALID_VALUE: 100901,
29553          GLU_TESS_BEGIN: 100100,
29554          GLU_TESS_VERTEX: 100101,
29555          GLU_TESS_END: 100102,
29556          GLU_TESS_ERROR: 100103,
29557          GLU_TESS_EDGE_FLAG: 100104,
29558          GLU_TESS_COMBINE: 100105,
29559          GLU_TESS_BEGIN_DATA: 100106,
29560          GLU_TESS_VERTEX_DATA: 100107,
29561          GLU_TESS_END_DATA: 100108,
29562          GLU_TESS_ERROR_DATA: 100109,
29563          GLU_TESS_EDGE_FLAG_DATA: 100110,
29564          GLU_TESS_COMBINE_DATA: 100111
29565        }
29566      };
29567      X.prototype.gluDeleteTess = X.prototype.x;
29568      X.prototype.gluTessProperty = X.prototype.B;
29569      X.prototype.gluGetTessProperty = X.prototype.y;
29570      X.prototype.gluTessNormal = X.prototype.A;
29571      X.prototype.gluTessCallback = X.prototype.z;
29572      X.prototype.gluTessVertex = X.prototype.C;
29573      X.prototype.gluTessBeginPolygon = X.prototype.u;
29574      X.prototype.gluTessBeginContour = X.prototype.t;
29575      X.prototype.gluTessEndContour = X.prototype.v;
29576      X.prototype.gluTessEndPolygon = X.prototype.w;
29577
29578      if (typeof module !== 'undefined') {
29579        module.exports = this.libtess;
29580      }
29581    }, {}],
29582    10: [function (_dereq_, module, exports) {
29583      (function (Buffer) {
29584        /**
29585         * https://opentype.js.org v0.9.0 | (c) Frederik De Bleser and other contributors | MIT License | Uses tiny-inflate by Devon Govett and string.prototype.codepointat polyfill by Mathias Bynens
29586         */
29587        (function (global, factory) {
29588          typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : factory(global.opentype = {});
29589        })(this, function (exports) {
29590          'use strict';
29591          /*! https://mths.be/codepointat v0.2.0 by @mathias */
29592
29593          if (!String.prototype.codePointAt) {
29594            (function () {
29595              var defineProperty = function () {
29596                // IE 8 only supports `Object.defineProperty` on DOM elements
29597                try {
29598                  var object = {};
29599                  var $defineProperty = Object.defineProperty;
29600                  var result = $defineProperty(object, object, object) && $defineProperty;
29601                } catch (error) {}
29602
29603                return result;
29604              }();
29605
29606              var codePointAt = function (position) {
29607                if (this == null) {
29608                  throw TypeError();
29609                }
29610
29611                var string = String(this);
29612                var size = string.length; // `ToInteger`
29613
29614                var index = position ? Number(position) : 0;
29615
29616                if (index != index) {
29617                  // better `isNaN`
29618                  index = 0;
29619                } // Account for out-of-bounds indices:
29620
29621
29622                if (index < 0 || index >= size) {
29623                  return undefined;
29624                } // Get the first code unit
29625
29626
29627                var first = string.charCodeAt(index);
29628                var second;
29629
29630                if ( // check if it’s the start of a surrogate pair
29631                first >= 0xD800 && first <= 0xDBFF && // high surrogate
29632                size > index + 1 // there is a next code unit
29633                ) {
29634                    second = string.charCodeAt(index + 1);
29635
29636                    if (second >= 0xDC00 && second <= 0xDFFF) {
29637                      // low surrogate
29638                      // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
29639                      return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
29640                    }
29641                  }
29642
29643                return first;
29644              };
29645
29646              if (defineProperty) {
29647                defineProperty(String.prototype, 'codePointAt', {
29648                  'value': codePointAt,
29649                  'configurable': true,
29650                  'writable': true
29651                });
29652              } else {
29653                String.prototype.codePointAt = codePointAt;
29654              }
29655            })();
29656          }
29657
29658          var TINF_OK = 0;
29659          var TINF_DATA_ERROR = -3;
29660
29661          function Tree() {
29662            this.table = new Uint16Array(16);
29663            /* table of code length counts */
29664
29665            this.trans = new Uint16Array(288);
29666            /* code -> symbol translation table */
29667          }
29668
29669          function Data(source, dest) {
29670            this.source = source;
29671            this.sourceIndex = 0;
29672            this.tag = 0;
29673            this.bitcount = 0;
29674            this.dest = dest;
29675            this.destLen = 0;
29676            this.ltree = new Tree();
29677            /* dynamic length/symbol tree */
29678
29679            this.dtree = new Tree();
29680            /* dynamic distance tree */
29681          }
29682          /* --------------------------------------------------- *
vendor: 9,999 bytes, lines 29683-30031
29683           * -- uninitialized global data (static structures) -- *
29684           * --------------------------------------------------- */
29685
29686
29687          var sltree = new Tree();
29688          var sdtree = new Tree();
29689          /* extra bits and base tables for length codes */
29690
29691          var length_bits = new Uint8Array(30);
29692          var length_base = new Uint16Array(30);
29693          /* extra bits and base tables for distance codes */
29694
29695          var dist_bits = new Uint8Array(30);
29696          var dist_base = new Uint16Array(30);
29697          /* special ordering of code length codes */
29698
29699          var clcidx = new Uint8Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
29700          /* used by tinf_decode_trees, avoids allocations every call */
29701
29702          var code_tree = new Tree();
29703          var lengths = new Uint8Array(288 + 32);
29704          /* ----------------------- *
29705           * -- utility functions -- *
29706           * ----------------------- */
29707
29708          /* build extra bits and base tables */
29709
29710          function tinf_build_bits_base(bits, base, delta, first) {
29711            var i, sum;
29712            /* build bits table */
29713
29714            for (i = 0; i < delta; ++i) {
29715              bits[i] = 0;
29716            }
29717
29718            for (i = 0; i < 30 - delta; ++i) {
29719              bits[i + delta] = i / delta | 0;
29720            }
29721            /* build base table */
29722
29723
29724            for (sum = first, i = 0; i < 30; ++i) {
29725              base[i] = sum;
29726              sum += 1 << bits[i];
29727            }
29728          }
29729          /* build the fixed huffman trees */
29730
29731
29732          function tinf_build_fixed_trees(lt, dt) {
29733            var i;
29734            /* build fixed length tree */
29735
29736            for (i = 0; i < 7; ++i) {
29737              lt.table[i] = 0;
29738            }
29739
29740            lt.table[7] = 24;
29741            lt.table[8] = 152;
29742            lt.table[9] = 112;
29743
29744            for (i = 0; i < 24; ++i) {
29745              lt.trans[i] = 256 + i;
29746            }
29747
29748            for (i = 0; i < 144; ++i) {
29749              lt.trans[24 + i] = i;
29750            }
29751
29752            for (i = 0; i < 8; ++i) {
29753              lt.trans[24 + 144 + i] = 280 + i;
29754            }
29755
29756            for (i = 0; i < 112; ++i) {
29757              lt.trans[24 + 144 + 8 + i] = 144 + i;
29758            }
29759            /* build fixed distance tree */
29760
29761
29762            for (i = 0; i < 5; ++i) {
29763              dt.table[i] = 0;
29764            }
29765
29766            dt.table[5] = 32;
29767
29768            for (i = 0; i < 32; ++i) {
29769              dt.trans[i] = i;
29770            }
29771          }
29772          /* given an array of code lengths, build a tree */
29773
29774
29775          var offs = new Uint16Array(16);
29776
29777          function tinf_build_tree(t, lengths, off, num) {
29778            var i, sum;
29779            /* clear code length count table */
29780
29781            for (i = 0; i < 16; ++i) {
29782              t.table[i] = 0;
29783            }
29784            /* scan symbol lengths, and sum code length counts */
29785
29786
29787            for (i = 0; i < num; ++i) {
29788              t.table[lengths[off + i]]++;
29789            }
29790
29791            t.table[0] = 0;
29792            /* compute offset table for distribution sort */
29793
29794            for (sum = 0, i = 0; i < 16; ++i) {
29795              offs[i] = sum;
29796              sum += t.table[i];
29797            }
29798            /* create code->symbol translation table (symbols sorted by code) */
29799
29800
29801            for (i = 0; i < num; ++i) {
29802              if (lengths[off + i]) {
29803                t.trans[offs[lengths[off + i]]++] = i;
29804              }
29805            }
29806          }
29807          /* ---------------------- *
29808           * -- decode functions -- *
29809           * ---------------------- */
29810
29811          /* get one bit from source stream */
29812
29813
29814          function tinf_getbit(d) {
29815            /* check if tag is empty */
29816            if (!d.bitcount--) {
29817              /* load next tag */
29818              d.tag = d.source[d.sourceIndex++];
29819              d.bitcount = 7;
29820            }
29821            /* shift bit out of tag */
29822
29823
29824            var bit = d.tag & 1;
29825            d.tag >>>= 1;
29826            return bit;
29827          }
29828          /* read a num bit value from a stream and add base */
29829
29830
29831          function tinf_read_bits(d, num, base) {
29832            if (!num) {
29833              return base;
29834            }
29835
29836            while (d.bitcount < 24) {
29837              d.tag |= d.source[d.sourceIndex++] << d.bitcount;
29838              d.bitcount += 8;
29839            }
29840
29841            var val = d.tag & 0xffff >>> 16 - num;
29842            d.tag >>>= num;
29843            d.bitcount -= num;
29844            return val + base;
29845          }
29846          /* given a data stream and a tree, decode a symbol */
29847
29848
29849          function tinf_decode_symbol(d, t) {
29850            while (d.bitcount < 24) {
29851              d.tag |= d.source[d.sourceIndex++] << d.bitcount;
29852              d.bitcount += 8;
29853            }
29854
29855            var sum = 0,
29856                cur = 0,
29857                len = 0;
29858            var tag = d.tag;
29859            /* get more bits while code value is above sum */
29860
29861            do {
29862              cur = 2 * cur + (tag & 1);
29863              tag >>>= 1;
29864              ++len;
29865              sum += t.table[len];
29866              cur -= t.table[len];
29867            } while (cur >= 0);
29868
29869            d.tag = tag;
29870            d.bitcount -= len;
29871            return t.trans[sum + cur];
29872          }
29873          /* given a data stream, decode dynamic trees from it */
29874
29875
29876          function tinf_decode_trees(d, lt, dt) {
29877            var hlit, hdist, hclen;
29878            var i, num, length;
29879            /* get 5 bits HLIT (257-286) */
29880
29881            hlit = tinf_read_bits(d, 5, 257);
29882            /* get 5 bits HDIST (1-32) */
29883
29884            hdist = tinf_read_bits(d, 5, 1);
29885            /* get 4 bits HCLEN (4-19) */
29886
29887            hclen = tinf_read_bits(d, 4, 4);
29888
29889            for (i = 0; i < 19; ++i) {
29890              lengths[i] = 0;
29891            }
29892            /* read code lengths for code length alphabet */
29893
29894
29895            for (i = 0; i < hclen; ++i) {
29896              /* get 3 bits code length (0-7) */
29897              var clen = tinf_read_bits(d, 3, 0);
29898              lengths[clcidx[i]] = clen;
29899            }
29900            /* build code length tree */
29901
29902
29903            tinf_build_tree(code_tree, lengths, 0, 19);
29904            /* decode code lengths for the dynamic trees */
29905
29906            for (num = 0; num < hlit + hdist;) {
29907              var sym = tinf_decode_symbol(d, code_tree);
29908
29909              switch (sym) {
29910                case 16:
29911                  /* copy previous code length 3-6 times (read 2 bits) */
29912                  var prev = lengths[num - 1];
29913
29914                  for (length = tinf_read_bits(d, 2, 3); length; --length) {
29915                    lengths[num++] = prev;
29916                  }
29917
29918                  break;
29919
29920                case 17:
29921                  /* repeat code length 0 for 3-10 times (read 3 bits) */
29922                  for (length = tinf_read_bits(d, 3, 3); length; --length) {
29923                    lengths[num++] = 0;
29924                  }
29925
29926                  break;
29927
29928                case 18:
29929                  /* repeat code length 0 for 11-138 times (read 7 bits) */
29930                  for (length = tinf_read_bits(d, 7, 11); length; --length) {
29931                    lengths[num++] = 0;
29932                  }
29933
29934                  break;
29935
29936                default:
29937                  /* values 0-15 represent the actual code lengths */
29938                  lengths[num++] = sym;
29939                  break;
29940              }
29941            }
29942            /* build dynamic trees */
29943
29944
29945            tinf_build_tree(lt, lengths, 0, hlit);
29946            tinf_build_tree(dt, lengths, hlit, hdist);
29947          }
29948          /* ----------------------------- *
29949           * -- block inflate functions -- *
29950           * ----------------------------- */
29951
29952          /* given a stream and two trees, inflate a block of data */
29953
29954
29955          function tinf_inflate_block_data(d, lt, dt) {
29956            while (1) {
29957              var sym = tinf_decode_symbol(d, lt);
29958              /* check for end of block */
29959
29960              if (sym === 256) {
29961                return TINF_OK;
29962              }
29963
29964              if (sym < 256) {
29965                d.dest[d.destLen++] = sym;
29966              } else {
29967                var length, dist, offs;
29968                var i;
29969                sym -= 257;
29970                /* possibly get more bits from length code */
29971
29972                length = tinf_read_bits(d, length_bits[sym], length_base[sym]);
29973                dist = tinf_decode_symbol(d, dt);
29974                /* possibly get more bits from distance code */
29975
29976                offs = d.destLen - tinf_read_bits(d, dist_bits[dist], dist_base[dist]);
29977                /* copy match */
29978
29979                for (i = offs; i < offs + length; ++i) {
29980                  d.dest[d.destLen++] = d.dest[i];
29981                }
29982              }
29983            }
29984          }
29985          /* inflate an uncompressed block of data */
29986
29987
29988          function tinf_inflate_uncompressed_block(d) {
29989            var length, invlength;
29990            var i;
29991            /* unread from bitbuffer */
29992
29993            while (d.bitcount > 8) {
29994              d.sourceIndex--;
29995              d.bitcount -= 8;
29996            }
29997            /* get length */
29998
29999
30000            length = d.source[d.sourceIndex + 1];
30001            length = 256 * length + d.source[d.sourceIndex];
30002            /* get one's complement of length */
30003
30004            invlength = d.source[d.sourceIndex + 3];
30005            invlength = 256 * invlength + d.source[d.sourceIndex + 2];
30006            /* check length */
30007
30008            if (length !== (~invlength & 0x0000ffff)) {
30009              return TINF_DATA_ERROR;
30010            }
30011
30012            d.sourceIndex += 4;
30013            /* copy block */
30014
30015            for (i = length; i; --i) {
30016              d.dest[d.destLen++] = d.source[d.sourceIndex++];
30017            }
30018            /* make sure we start next block on a byte boundary */
30019
30020
30021            d.bitcount = 0;
30022            return TINF_OK;
30023          }
30024          /* inflate stream from source to dest */
30025
30026
30027          function tinf_uncompress(source, dest) {
30028            var d = new Data(source, dest);
30029            var bfinal, btype, res;
30030
30031            do {
30032              /* read final block flag */
30033              bfinal = tinf_getbit(d);
30034              /* read block type (2 bits) */
30035
30036              btype = tinf_read_bits(d, 2, 0);
30037              /* decompress block */
30038
30039              switch (btype) {
30040                case 0:
30041                  /* decompress uncompressed block */
30042                  res = tinf_inflate_uncompressed_block(d);
30043                  break;
30044
30045                case 1:
30046                  /* decompress block with fixed huffman trees */
30047                  res = tinf_inflate_block_data(d, sltree, sdtree);
30048                  break;
30049
30050                case 2:
30051                  /* decompress block with dynamic huffman trees */
30052                  tinf_decode_trees(d, d.ltree, d.dtree);
30053                  res = tinf_inflate_block_data(d, d.ltree, d.dtree);
30054                  break;
30055
30056                default:
30057                  res = TINF_DATA_ERROR;
30058              }
30059
30060              if (res !== TINF_OK) {
30061                throw new Error('Data error');
30062              }
30063            } while (!bfinal);
30064
30065            if (d.destLen < d.dest.length) {
30066              if (typeof d.dest.slice === 'function') {
30067                return d.dest.slice(0, d.destLen);
30068              } else {
30069                return d.dest.subarray(0, d.destLen);
30070              }
30071            }
30072
30073            return d.dest;
30074          }
30075          /* -------------------- *
30076           * -- initialization -- *
30077           * -------------------- */
30078
30079          /* build fixed huffman trees */
30080
30081
30082          tinf_build_fixed_trees(sltree, sdtree);
30083          /* build extra bits and base tables */
30084
30085          tinf_build_bits_base(length_bits, length_base, 4, 3);
30086          tinf_build_bits_base(dist_bits, dist_base, 2, 1);
30087          /* fix a special case */
30088
30089          length_bits[28] = 0;
30090          length_base[28] = 258;
30091          var tinyInflate = tinf_uncompress; // The Bounding Box object
30092
30093          function derive(v0, v1, v2, v3, t) {
30094            return Math.pow(1 - t, 3) * v0 + 3 * Math.pow(1 - t, 2) * t * v1 + 3 * (1 - t) * Math.pow(t, 2) * v2 + Math.pow(t, 3) * v3;
30095          }
30096          /**
30097           * A bounding box is an enclosing box that describes the smallest measure within which all the points lie.
30098           * It is used to calculate the bounding box of a glyph or text path.
30099           *
30100           * On initialization, x1/y1/x2/y2 will be NaN. Check if the bounding box is empty using `isEmpty()`.
30101           *
30102           * @exports opentype.BoundingBox
30103           * @class
30104           * @constructor
30105           */
30106
30107
30108          function BoundingBox() {
30109            this.x1 = Number.NaN;
30110            this.y1 = Number.NaN;
30111            this.x2 = Number.NaN;
30112            this.y2 = Number.NaN;
30113          }
30114          /**
30115           * Returns true if the bounding box is empty, that is, no points have been added to the box yet.
30116           */
30117
30118
30119          BoundingBox.prototype.isEmpty = function () {
30120            return isNaN(this.x1) || isNaN(this.y1) || isNaN(this.x2) || isNaN(this.y2);
30121          };
30122          /**
30123           * Add the point to the bounding box.
30124           * The x1/y1/x2/y2 coordinates of the bounding box will now encompass the given point.
30125           * @param {number} x - The X coordinate of the point.
30126           * @param {number} y - The Y coordinate of the point.
30127           */
30128
30129
30130          BoundingBox.prototype.addPoint = function (x, y) {
30131            if (typeof x === 'number') {
30132              if (isNaN(this.x1) || isNaN(this.x2)) {
30133                this.x1 = x;
30134                this.x2 = x;
30135              }
30136
30137              if (x < this.x1) {
30138                this.x1 = x;
30139              }
30140
30141              if (x > this.x2) {
30142                this.x2 = x;
30143              }
30144            }
30145
30146            if (typeof y === 'number') {
30147              if (isNaN(this.y1) || isNaN(this.y2)) {
30148                this.y1 = y;
30149                this.y2 = y;
30150              }
30151
30152              if (y < this.y1) {
30153                this.y1 = y;
30154              }
30155
30156              if (y > this.y2) {
30157                this.y2 = y;
30158              }
30159            }
30160          };
30161          /**
30162           * Add a X coordinate to the bounding box.
30163           * This extends the bounding box to include the X coordinate.
30164           * This function is used internally inside of addBezier.
30165           * @param {number} x - The X coordinate of the point.
30166           */
30167
30168
30169          BoundingBox.prototype.addX = function (x) {
30170            this.addPoint(x, null);
30171          };
30172          /**
30173           * Add a Y coordinate to the bounding box.
30174           * This extends the bounding box to include the Y coordinate.
30175           * This function is used internally inside of addBezier.
30176           * @param {number} y - The Y coordinate of the point.
30177           */
30178
30179
30180          BoundingBox.prototype.addY = function (y) {
30181            this.addPoint(null, y);
30182          };
30183          /**
30184           * Add a Bézier curve to the bounding box.
30185           * This extends the bounding box to include the entire Bézier.
30186           * @param {number} x0 - The starting X coordinate.
30187           * @param {number} y0 - The starting Y coordinate.
30188           * @param {number} x1 - The X coordinate of the first control point.
30189           * @param {number} y1 - The Y coordinate of the first control point.
30190           * @param {number} x2 - The X coordinate of the second control point.
30191           * @param {number} y2 - The Y coordinate of the second control point.
30192           * @param {number} x - The ending X coordinate.
30193           * @param {number} y - The ending Y coordinate.
30194           */
30195
30196
30197          BoundingBox.prototype.addBezier = function (x0, y0, x1, y1, x2, y2, x, y) {
30198            var this$1 = this; // This code is based on http://nishiohirokazu.blogspot.com/2009/06/how-to-calculate-bezier-curves-bounding.html
30199            // and https://github.com/icons8/svg-path-bounding-box
30200
30201            var p0 = [x0, y0];
30202            var p1 = [x1, y1];
30203            var p2 = [x2, y2];
30204            var p3 = [x, y];
30205            this.addPoint(x0, y0);
30206            this.addPoint(x, y);
30207
30208            for (var i = 0; i <= 1; i++) {
30209              var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];
30210              var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];
30211              var c = 3 * p1[i] - 3 * p0[i];
30212
30213              if (a === 0) {
30214                if (b === 0) {
30215                  continue;
30216                }
30217
30218                var t = -c / b;
30219
30220                if (0 < t && t < 1) {
30221                  if (i === 0) {
30222                    this$1.addX(derive(p0[i], p1[i], p2[i], p3[i], t));
30223                  }
30224
30225                  if (i === 1) {
30226                    this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t));
30227                  }
30228                }
30229
30230                continue;
30231              }
30232
30233              var b2ac = Math.pow(b, 2) - 4 * c * a;
30234
30235              if (b2ac < 0) {
30236                continue;
30237              }
30238
30239              var t1 = (-b + Math.sqrt(b2ac)) / (2 * a);
30240
30241              if (0 < t1 && t1 < 1) {
30242                if (i === 0) {
30243                  this$1.addX(derive(p0[i], p1[i], p2[i], p3[i], t1));
30244                }
30245
30246                if (i === 1) {
30247                  this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t1));
30248                }
30249              }
30250
30251              var t2 = (-b - Math.sqrt(b2ac)) / (2 * a);
30252
30253              if (0 < t2 && t2 < 1) {
30254                if (i === 0) {
30255                  this$1.addX(derive(p0[i], p1[i], p2[i], p3[i], t2));
30256                }
30257
30258                if (i === 1) {
30259                  this$1.addY(derive(p0[i], p1[i], p2[i], p3[i], t2));
30260                }
30261              }
30262            }
30263          };
30264          /**
30265           * Add a quadratic curve to the bounding box.
30266           * This extends the bounding box to include the entire quadratic curve.
30267           * @param {number} x0 - The starting X coordinate.
30268           * @param {number} y0 - The starting Y coordinate.
30269           * @param {number} x1 - The X coordinate of the control point.
30270           * @param {number} y1 - The Y coordinate of the control point.
30271           * @param {number} x - The ending X coordinate.
30272           * @param {number} y - The ending Y coordinate.
30273           */
30274
30275
30276          BoundingBox.prototype.addQuad = function (x0, y0, x1, y1, x, y) {
30277            var cp1x = x0 + 2 / 3 * (x1 - x0);
30278            var cp1y = y0 + 2 / 3 * (y1 - y0);
30279            var cp2x = cp1x + 1 / 3 * (x - x0);
30280            var cp2y = cp1y + 1 / 3 * (y - y0);
30281            this.addBezier(x0, y0, cp1x, cp1y, cp2x, cp2y, x, y);
30282          }; // Geometric objects
30283
30284          /**
30285           * A bézier path containing a set of path commands similar to a SVG path.
30286           * Paths can be drawn on a context using `draw`.
30287           * @exports opentype.Path
30288           * @class
30289           * @constructor
30290           */
30291
30292
30293          function Path() {
30294            this.commands = [];
30295            this.fill = 'black';
30296            this.stroke = null;
30297            this.strokeWidth = 1;
30298          }
30299          /**
30300           * @param  {number} x
30301           * @param  {number} y
30302           */
30303
30304
30305          Path.prototype.moveTo = function (x, y) {
30306            this.commands.push({
30307              type: 'M',
30308              x: x,
30309              y: y
30310            });
30311          };
30312          /**
30313           * @param  {number} x
30314           * @param  {number} y
30315           */
30316
30317
30318          Path.prototype.lineTo = function (x, y) {
30319            this.commands.push({
30320              type: 'L',
30321              x: x,
30322              y: y
30323            });
30324          };
30325          /**
30326           * Draws cubic curve
30327           * @function
30328           * curveTo
30329           * @memberof opentype.Path.prototype
30330           * @param  {number} x1 - x of control 1
30331           * @param  {number} y1 - y of control 1
30332           * @param  {number} x2 - x of control 2
30333           * @param  {number} y2 - y of control 2
30334           * @param  {number} x - x of path point
30335           * @param  {number} y - y of path point
30336           */
30337
30338          /**
30339           * Draws cubic curve
30340           * @function
30341           * bezierCurveTo
30342           * @memberof opentype.Path.prototype
30343           * @param  {number} x1 - x of control 1
30344           * @param  {number} y1 - y of control 1
30345           * @param  {number} x2 - x of control 2
30346           * @param  {number} y2 - y of control 2
30347           * @param  {number} x - x of path point
30348           * @param  {number} y - y of path point
30349           * @see curveTo
30350           */
30351
30352
30353          Path.prototype.curveTo = Path.prototype.bezierCurveTo = function (x1, y1, x2, y2, x, y) {
30354            this.commands.push({
30355              type: 'C',
30356              x1: x1,
30357              y1: y1,
30358              x2: x2,
30359              y2: y2,
30360              x: x,
30361              y: y
30362            });
30363          };
30364          /**
30365           * Draws quadratic curve
30366           * @function
30367           * quadraticCurveTo
30368           * @memberof opentype.Path.prototype
30369           * @param  {number} x1 - x of control
30370           * @param  {number} y1 - y of control
30371           * @param  {number} x - x of path point
30372           * @param  {number} y - y of path point
30373           */
30374
30375          /**
30376           * Draws quadratic curve
30377           * @function
30378           * quadTo
30379           * @memberof opentype.Path.prototype
30380           * @param  {number} x1 - x of control
30381           * @param  {number} y1 - y of control
30382           * @param  {number} x - x of path point
30383           * @param  {number} y - y of path point
30384           */
30385
30386
30387          Path.prototype.quadTo = Path.prototype.quadraticCurveTo = function (x1, y1, x, y) {
30388            this.commands.push({
30389              type: 'Q',
30390              x1: x1,
30391              y1: y1,
30392              x: x,
30393              y: y
30394            });
30395          };
30396          /**
30397           * Closes the path
30398           * @function closePath
30399           * @memberof opentype.Path.prototype
30400           */
30401
30402          /**
30403           * Close the path
30404           * @function close
30405           * @memberof opentype.Path.prototype
30406           */
30407
30408
30409          Path.prototype.close = Path.prototype.closePath = function () {
30410            this.commands.push({
30411              type: 'Z'
30412            });
30413          };
30414          /**
30415           * Add the given path or list of commands to the commands of this path.
30416           * @param  {Array} pathOrCommands - another opentype.Path, an opentype.BoundingBox, or an array of commands.
30417           */
30418
30419
30420          Path.prototype.extend = function (pathOrCommands) {
30421            if (pathOrCommands.commands) {
30422              pathOrCommands = pathOrCommands.commands;
30423            } else if (pathOrCommands instanceof BoundingBox) {
30424              var box = pathOrCommands;
30425              this.moveTo(box.x1, box.y1);
30426              this.lineTo(box.x2, box.y1);
30427              this.lineTo(box.x2, box.y2);
30428              this.lineTo(box.x1, box.y2);
30429              this.close();
30430              return;
30431            }
30432
30433            Array.prototype.push.apply(this.commands, pathOrCommands);
30434          };
30435          /**
30436           * Calculate the bounding box of the path.
30437           * @returns {opentype.BoundingBox}
30438           */
30439
30440
30441          Path.prototype.getBoundingBox = function () {
30442            var this$1 = this;
30443            var box = new BoundingBox();
30444            var startX = 0;
30445            var startY = 0;
30446            var prevX = 0;
30447            var prevY = 0;
30448
30449            for (var i = 0; i < this.commands.length; i++) {
30450              var cmd = this$1.commands[i];
30451
30452              switch (cmd.type) {
30453                case 'M':
30454                  box.addPoint(cmd.x, cmd.y);
30455                  startX = prevX = cmd.x;
30456                  startY = prevY = cmd.y;
30457                  break;
30458
30459                case 'L':
30460                  box.addPoint(cmd.x, cmd.y);
30461                  prevX = cmd.x;
30462                  prevY = cmd.y;
30463                  break;
30464
30465                case 'Q':
30466                  box.addQuad(prevX, prevY, cmd.x1, cmd.y1, cmd.x, cmd.y);
30467                  prevX = cmd.x;
30468                  prevY = cmd.y;
30469                  break;
30470
30471                case 'C':
30472                  box.addBezier(prevX, prevY, cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
30473                  prevX = cmd.x;
30474                  prevY = cmd.y;
30475                  break;
30476
30477                case 'Z':
30478                  prevX = startX;
30479                  prevY = startY;
30480                  break;
30481
30482                default:
30483                  throw new Error('Unexpected path command ' + cmd.type);
30484              }
30485            }
30486
30487            if (box.isEmpty()) {
30488              box.addPoint(0, 0);
30489            }
30490
30491            return box;
30492          };
30493          /**
30494           * Draw the path to a 2D context.
30495           * @param {CanvasRenderingContext2D} ctx - A 2D drawing context.
30496           */
30497
30498
30499          Path.prototype.draw = function (ctx) {
30500            var this$1 = this;
30501            ctx.beginPath();
30502
30503            for (var i = 0; i < this.commands.length; i += 1) {
30504              var cmd = this$1.commands[i];
30505
30506              if (cmd.type === 'M') {
30507                ctx.moveTo(cmd.x, cmd.y);
30508              } else if (cmd.type === 'L') {
30509                ctx.lineTo(cmd.x, cmd.y);
30510              } else if (cmd.type === 'C') {
30511                ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
30512              } else if (cmd.type === 'Q') {
30513                ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);
30514              } else if (cmd.type === 'Z') {
30515                ctx.closePath();
30516              }
30517            }
30518
30519            if (this.fill) {
30520              ctx.fillStyle = this.fill;
30521              ctx.fill();
30522            }
30523
30524            if (this.stroke) {
30525              ctx.strokeStyle = this.stroke;
30526              ctx.lineWidth = this.strokeWidth;
30527              ctx.stroke();
30528            }
30529          };
30530          /**
30531           * Convert the Path to a string of path data instructions
30532           * See http://www.w3.org/TR/SVG/paths.html#PathData
30533           * @param  {number} [decimalPlaces=2] - The amount of decimal places for floating-point values
30534           * @return {string}
30535           */
30536
30537
30538          Path.prototype.toPathData = function (decimalPlaces) {
30539            var this$1 = this;
30540            decimalPlaces = decimalPlaces !== undefined ? decimalPlaces : 2;
30541
30542            function floatToString(v) {
30543              if (Math.round(v) === v) {
30544                return '' + Math.round(v);
30545              } else {
30546                return v.toFixed(decimalPlaces);
30547              }
30548            }
30549
30550            function packValues() {
30551              var arguments$1 = arguments;
30552              var s = '';
30553
30554              for (var i = 0; i < arguments.length; i += 1) {
30555                var v = arguments$1[i];
30556
30557                if (v >= 0 && i > 0) {
30558                  s += ' ';
30559                }
30560
30561                s += floatToString(v);
30562              }
30563
30564              return s;
30565            }
30566
30567            var d = '';
30568
30569            for (var i = 0; i < this.commands.length; i += 1) {
30570              var cmd = this$1.commands[i];
30571
30572              if (cmd.type === 'M') {
30573                d += 'M' + packValues(cmd.x, cmd.y);
30574              } else if (cmd.type === 'L') {
30575                d += 'L' + packValues(cmd.x, cmd.y);
30576              } else if (cmd.type === 'C') {
30577                d += 'C' + packValues(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
30578              } else if (cmd.type === 'Q') {
30579                d += 'Q' + packValues(cmd.x1, cmd.y1, cmd.x, cmd.y);
30580              } else if (cmd.type === 'Z') {
30581                d += 'Z';
30582              }
30583            }
30584
30585            return d;
30586          };
30587          /**
30588           * Convert the path to an SVG <path> element, as a string.
30589           * @param  {number} [decimalPlaces=2] - The amount of decimal places for floating-point values
30590           * @return {string}
30591           */
30592
30593
30594          Path.prototype.toSVG = function (decimalPlaces) {
30595            var svg = '<path d="';
30596            svg += this.toPathData(decimalPlaces);
30597            svg += '"';
30598
30599            if (this.fill && this.fill !== 'black') {
30600              if (this.fill === null) {
30601                svg += ' fill="none"';
30602              } else {
30603                svg += ' fill="' + this.fill + '"';
30604              }
30605            }
30606
30607            if (this.stroke) {
30608              svg += ' stroke="' + this.stroke + '" stroke-width="' + this.strokeWidth + '"';
30609            }
30610
30611            svg += '/>';
30612            return svg;
30613          };
30614          /**
30615           * Convert the path to a DOM element.
30616           * @param  {number} [decimalPlaces=2] - The amount of decimal places for floating-point values
30617           * @return {SVGPathElement}
30618           */
30619
30620
30621          Path.prototype.toDOMElement = function (decimalPlaces) {
30622            var temporaryPath = this.toPathData(decimalPlaces);
30623            var newPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
30624            newPath.setAttribute('d', temporaryPath);
30625            return newPath;
30626          }; // Run-time checking of preconditions.
30627
30628
30629          function fail(message) {
30630            throw new Error(message);
30631          }
vendor: 6,278 bytes, lines 30631-30871
30631 // Precondition function that checks if the given predicate is true.
30632          // If not, it will throw an error.
30633
30634
30635          function argument(predicate, message) {
30636            if (!predicate) {
30637              fail(message);
30638            }
30639          }
30640
30641          var check = {
30642            fail: fail,
30643            argument: argument,
30644            assert: argument
30645          }; // Data types used in the OpenType font file.
30646
30647          var LIMIT16 = 32768; // The limit at which a 16-bit number switches signs == 2^15
30648
30649          var LIMIT32 = 2147483648; // The limit at which a 32-bit number switches signs == 2 ^ 31
30650
30651          /**
30652           * @exports opentype.decode
30653           * @class
30654           */
30655
30656          var decode = {};
30657          /**
30658           * @exports opentype.encode
30659           * @class
30660           */
30661
30662          var encode = {};
30663          /**
30664           * @exports opentype.sizeOf
30665           * @class
30666           */
30667
30668          var sizeOf = {}; // Return a function that always returns the same value.
30669
30670          function constant(v) {
30671            return function () {
30672              return v;
30673            };
30674          } // OpenType data types //////////////////////////////////////////////////////
30675
30676          /**
30677           * Convert an 8-bit unsigned integer to a list of 1 byte.
30678           * @param {number}
30679           * @returns {Array}
30680           */
30681
30682
30683          encode.BYTE = function (v) {
30684            check.argument(v >= 0 && v <= 255, 'Byte value should be between 0 and 255.');
30685            return [v];
30686          };
30687          /**
30688           * @constant
30689           * @type {number}
30690           */
30691
30692
30693          sizeOf.BYTE = constant(1);
30694          /**
30695           * Convert a 8-bit signed integer to a list of 1 byte.
30696           * @param {string}
30697           * @returns {Array}
30698           */
30699
30700          encode.CHAR = function (v) {
30701            return [v.charCodeAt(0)];
30702          };
30703          /**
30704           * @constant
30705           * @type {number}
30706           */
30707
30708
30709          sizeOf.CHAR = constant(1);
30710          /**
30711           * Convert an ASCII string to a list of bytes.
30712           * @param {string}
30713           * @returns {Array}
30714           */
30715
30716          encode.CHARARRAY = function (v) {
30717            var b = [];
30718
30719            for (var i = 0; i < v.length; i += 1) {
30720              b[i] = v.charCodeAt(i);
30721            }
30722
30723            return b;
30724          };
30725          /**
30726           * @param {Array}
30727           * @returns {number}
30728           */
30729
30730
30731          sizeOf.CHARARRAY = function (v) {
30732            return v.length;
30733          };
30734          /**
30735           * Convert a 16-bit unsigned integer to a list of 2 bytes.
30736           * @param {number}
30737           * @returns {Array}
30738           */
30739
30740
30741          encode.USHORT = function (v) {
30742            return [v >> 8 & 0xFF, v & 0xFF];
30743          };
30744          /**
30745           * @constant
30746           * @type {number}
30747           */
30748
30749
30750          sizeOf.USHORT = constant(2);
30751          /**
30752           * Convert a 16-bit signed integer to a list of 2 bytes.
30753           * @param {number}
30754           * @returns {Array}
30755           */
30756
30757          encode.SHORT = function (v) {
30758            // Two's complement
30759            if (v >= LIMIT16) {
30760              v = -(2 * LIMIT16 - v);
30761            }
30762
30763            return [v >> 8 & 0xFF, v & 0xFF];
30764          };
30765          /**
30766           * @constant
30767           * @type {number}
30768           */
30769
30770
30771          sizeOf.SHORT = constant(2);
30772          /**
30773           * Convert a 24-bit unsigned integer to a list of 3 bytes.
30774           * @param {number}
30775           * @returns {Array}
30776           */
30777
30778          encode.UINT24 = function (v) {
30779            return [v >> 16 & 0xFF, v >> 8 & 0xFF, v & 0xFF];
30780          };
30781          /**
30782           * @constant
30783           * @type {number}
30784           */
30785
30786
30787          sizeOf.UINT24 = constant(3);
30788          /**
30789           * Convert a 32-bit unsigned integer to a list of 4 bytes.
30790           * @param {number}
30791           * @returns {Array}
30792           */
30793
30794          encode.ULONG = function (v) {
30795            return [v >> 24 & 0xFF, v >> 16 & 0xFF, v >> 8 & 0xFF, v & 0xFF];
30796          };
30797          /**
30798           * @constant
30799           * @type {number}
30800           */
30801
30802
30803          sizeOf.ULONG = constant(4);
30804          /**
30805           * Convert a 32-bit unsigned integer to a list of 4 bytes.
30806           * @param {number}
30807           * @returns {Array}
30808           */
30809
30810          encode.LONG = function (v) {
30811            // Two's complement
30812            if (v >= LIMIT32) {
30813              v = -(2 * LIMIT32 - v);
30814            }
30815
30816            return [v >> 24 & 0xFF, v >> 16 & 0xFF, v >> 8 & 0xFF, v & 0xFF];
30817          };
30818          /**
30819           * @constant
30820           * @type {number}
30821           */
30822
30823
30824          sizeOf.LONG = constant(4);
30825          encode.FIXED = encode.ULONG;
30826          sizeOf.FIXED = sizeOf.ULONG;
30827          encode.FWORD = encode.SHORT;
30828          sizeOf.FWORD = sizeOf.SHORT;
30829          encode.UFWORD = encode.USHORT;
30830          sizeOf.UFWORD = sizeOf.USHORT;
30831          /**
30832           * Convert a 32-bit Apple Mac timestamp integer to a list of 8 bytes, 64-bit timestamp.
30833           * @param {number}
30834           * @returns {Array}
30835           */
30836
30837          encode.LONGDATETIME = function (v) {
30838            return [0, 0, 0, 0, v >> 24 & 0xFF, v >> 16 & 0xFF, v >> 8 & 0xFF, v & 0xFF];
30839          };
30840          /**
30841           * @constant
30842           * @type {number}
30843           */
30844
30845
30846          sizeOf.LONGDATETIME = constant(8);
30847          /**
30848           * Convert a 4-char tag to a list of 4 bytes.
30849           * @param {string}
30850           * @returns {Array}
30851           */
30852
30853          encode.TAG = function (v) {
30854            check.argument(v.length === 4, 'Tag should be exactly 4 ASCII characters.');
30855            return [v.charCodeAt(0), v.charCodeAt(1), v.charCodeAt(2), v.charCodeAt(3)];
30856          };
30857          /**
30858           * @constant
30859           * @type {number}
30860           */
30861
30862
30863          sizeOf.TAG = constant(4); // CFF data types ///////////////////////////////////////////////////////////
30864
30865          encode.Card8 = encode.BYTE;
30866          sizeOf.Card8 = sizeOf.BYTE;
30867          encode.Card16 = encode.USHORT;
30868          sizeOf.Card16 = sizeOf.USHORT;
30869          encode.OffSize = encode.BYTE;
30870          sizeOf.OffSize = sizeOf.BYTE;
30871          encode.SID = encode.USHORT;
30872          sizeOf.SID = sizeOf.USHORT; // Convert a numeric operand or charstring number to a variable-size list of bytes.
30873
30874          /**
30875           * Convert a numeric operand or charstring number to a variable-size list of bytes.
30876           * @param {number}
30877           * @returns {Array}
30878           */
30879
30880          encode.NUMBER = function (v) {
30881            if (v >= -107 && v <= 107) {
30882              return [v + 139];
30883            } else if (v >= 108 && v <= 1131) {
30884              v = v - 108;
30885              return [(v >> 8) + 247, v & 0xFF];
30886            } else if (v >= -1131 && v <= -108) {
30887              v = -v - 108;
30888              return [(v >> 8) + 251, v & 0xFF];
30889            } else if (v >= -32768 && v <= 32767) {
30890              return encode.NUMBER16(v);
30891            } else {
30892              return encode.NUMBER32(v);
30893            }
30894          };
30895          /**
30896           * @param {number}
30897           * @returns {number}
30898           */
30899
30900
30901          sizeOf.NUMBER = function (v) {
30902            return encode.NUMBER(v).length;
30903          };
30904          /**
30905           * Convert a signed number between -32768 and +32767 to a three-byte value.
30906           * This ensures we always use three bytes, but is not the most compact format.
30907           * @param {number}
30908           * @returns {Array}
30909           */
30910
30911
30912          encode.NUMBER16 = function (v) {
30913            return [28, v >> 8 & 0xFF, v & 0xFF];
30914          };
30915          /**
30916           * @constant
30917           * @type {number}
30918           */
30919
30920
30921          sizeOf.NUMBER16 = constant(3);
30922          /**
30923           * Convert a signed number between -(2^31) and +(2^31-1) to a five-byte value.
30924           * This is useful if you want to be sure you always use four bytes,
30925           * at the expense of wasting a few bytes for smaller numbers.
30926           * @param {number}
30927           * @returns {Array}
30928           */
30929
30930          encode.NUMBER32 = function (v) {
30931            return [29, v >> 24 & 0xFF, v >> 16 & 0xFF, v >> 8 & 0xFF, v & 0xFF];
30932          };
30933          /**
30934           * @constant
30935           * @type {number}
30936           */
30937
30938
30939          sizeOf.NUMBER32 = constant(5);
30940          /**
30941           * @param {number}
30942           * @returns {Array}
30943           */
30944
30945          encode.REAL = function (v) {
30946            var value = v.toString(); // Some numbers use an epsilon to encode the value. (e.g. JavaScript will store 0.0000001 as 1e-7)
30947            // This code converts it back to a number without the epsilon.
30948
30949            var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value);
30950
30951            if (m) {
30952              var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));
30953              value = (Math.round(v * epsilon) / epsilon).toString();
30954            }
30955
30956            var nibbles = '';
30957
30958            for (var i = 0, ii = value.length; i < ii; i += 1) {
30959              var c = value[i];
30960
30961              if (c === 'e') {
30962                nibbles += value[++i] === '-' ? 'c' : 'b';
30963              } else if (c === '.') {
30964                nibbles += 'a';
30965              } else if (c === '-') {
30966                nibbles += 'e';
30967              } else {
30968                nibbles += c;
30969              }
30970            }
30971
30972            nibbles += nibbles.length & 1 ? 'f' : 'ff';
30973            var out = [30];
30974
30975            for (var i$1 = 0, ii$1 = nibbles.length; i$1 < ii$1; i$1 += 2) {
30976              out.push(parseInt(nibbles.substr(i$1, 2), 16));
30977            }
30978
30979            return out;
30980          };
30981          /**
30982           * @param {number}
30983           * @returns {number}
30984           */
30985
30986
30987          sizeOf.REAL = function (v) {
30988            return encode.REAL(v).length;
30989          };
30990
30991          encode.NAME = encode.CHARARRAY;
30992          sizeOf.NAME = sizeOf.CHARARRAY;
30993          encode.STRING = encode.CHARARRAY;
30994          sizeOf.STRING = sizeOf.CHARARRAY;
30995          /**
30996           * @param {DataView} data
30997           * @param {number} offset
30998           * @param {number} numBytes
30999           * @returns {string}
31000           */
31001
31002          decode.UTF8 = function (data, offset, numBytes) {
31003            var codePoints = [];
31004            var numChars = numBytes;
31005
31006            for (var j = 0; j < numChars; j++, offset += 1) {
31007              codePoints[j] = data.getUint8(offset);
31008            }
31009
31010            return String.fromCharCode.apply(null, codePoints);
31011          };
31012          /**
31013           * @param {DataView} data
31014           * @param {number} offset
31015           * @param {number} numBytes
31016           * @returns {string}
31017           */
31018
31019
31020          decode.UTF16 = function (data, offset, numBytes) {
31021            var codePoints = [];
31022            var numChars = numBytes / 2;
31023
31024            for (var j = 0; j < numChars; j++, offset += 2) {
31025              codePoints[j] = data.getUint16(offset);
31026            }
31027
31028            return String.fromCharCode.apply(null, codePoints);
31029          };
31030          /**
31031           * Convert a JavaScript string to UTF16-BE.
31032           * @param {string}
31033           * @returns {Array}
31034           */
31035
31036
31037          encode.UTF16 = function (v) {
31038            var b = [];
31039
31040            for (var i = 0; i < v.length; i += 1) {
31041              var codepoint = v.charCodeAt(i);
31042              b[b.length] = codepoint >> 8 & 0xFF;
31043              b[b.length] = codepoint & 0xFF;
31044            }
31045
31046            return b;
31047          };
31048          /**
31049           * @param {string}
31050           * @returns {number}
31051           */
31052
31053
31054          sizeOf.UTF16 = function (v) {
31055            return v.length * 2;
31056          }; // Data for converting old eight-bit Macintosh encodings to Unicode.
31057          // This representation is optimized for decoding; encoding is slower
31058          // and needs more memory. The assumption is that all opentype.js users
31059          // want to open fonts, but saving a font will be comparatively rare
31060          // so it can be more expensive. Keyed by IANA character set name.
31061          //
31062          // Python script for generating these strings:
31063          //
31064          //     s = u''.join([chr(c).decode('mac_greek') for c in range(128, 256)])
31065          //     print(s.encode('utf-8'))
31066
31067          /**
31068           * @private
31069           */
31070
31071
31072          var eightBitMacEncodings = {
31073            'x-mac-croatian': // Python: 'mac_croatian'
31074            'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø' + '¿¡¬√ƒ≈ƫȅ ÀÃÕŒœĐ—“”‘’÷◊©⁄€‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ',
31075            'x-mac-cyrillic': // Python: 'mac_cyrillic'
31076            'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњ' + 'јЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю',
31077            'x-mac-gaelic': // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/GAELIC.TXT
31078            'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØḂ±≤≥ḃĊċḊḋḞḟĠġṀæø' + 'ṁṖṗɼƒſṠ«»… ÀÃÕŒœ–—“”‘’ṡẛÿŸṪ€‹›Ŷŷṫ·Ỳỳ⁊ÂÊÁËÈÍÎÏÌÓÔ♣ÒÚÛÙıÝýŴŵẄẅẀẁẂẃ',
31079            'x-mac-greek': // Python: 'mac_greek'
31080            'Ĺ²É³ÖÜ΅àâä΄¨çéèê룙î‰ôö¦€ùûü†ΓΔΘΛΞΠß®©ΣΪ§≠°·Α±≤≥¥ΒΕΖΗΙΚΜΦΫΨΩ' + 'άΝ¬ΟΡ≈Τ«»… ΥΧΆΈœ–―“”‘’÷ΉΊΌΎέήίόΏύαβψδεφγηιξκλμνοπώρστθωςχυζϊϋΐΰ\u00AD',
31081            'x-mac-icelandic': // Python: 'mac_iceland'
31082            'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûüݰ¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' + '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€ÐðÞþý·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',
31083            'x-mac-inuit': // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/INUIT.TXT
31084            'ᐃᐄᐅᐆᐊᐋᐱᐲᐳᐴᐸᐹᑉᑎᑏᑐᑑᑕᑖᑦᑭᑮᑯᑰᑲᑳᒃᒋᒌᒍᒎᒐᒑ°ᒡᒥᒦ•¶ᒧ®©™ᒨᒪᒫᒻᓂᓃᓄᓅᓇᓈᓐᓯᓰᓱᓲᓴᓵᔅᓕᓖᓗ' + 'ᓘᓚᓛᓪᔨᔩᔪᔫᔭ… ᔮᔾᕕᕖᕗ–—“”‘’ᕘᕙᕚᕝᕆᕇᕈᕉᕋᕌᕐᕿᖀᖁᖂᖃᖄᖅᖏᖐᖑᖒᖓᖔᖕᙱᙲᙳᙴᙵᙶᖖᖠᖡᖢᖣᖤᖥᖦᕼŁł',
31085            'x-mac-ce': // Python: 'mac_latin2'
31086            'ÄĀāÉĄÖÜáąČäčĆć鏟ĎíďĒēĖóėôöõúĚěü†°Ę£§•¶ß®©™ę¨≠ģĮįĪ≤≥īĶ∂∑łĻļĽľĹĺŅ' + 'ņѬ√ńŇ∆«»… ňŐÕőŌ–—“”‘’÷◊ōŔŕŘ‹›řŖŗŠ‚„šŚśÁŤťÍŽžŪÓÔūŮÚůŰűŲųÝýķŻŁżĢˇ',
31087            macintosh: // Python: 'mac_roman'
31088            'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' + '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',
31089            'x-mac-romanian': // Python: 'mac_romanian'
31090            'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ĂȘ∞±≤≥¥µ∂∑∏π∫ªºΩăș' + '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›Țț‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ',
31091            'x-mac-turkish': // Python: 'mac_turkish'
31092            'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø' + '¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙˆ˜¯˘˙˚¸˝˛ˇ'
31093          };
31094          /**
31095           * Decodes an old-style Macintosh string. Returns either a Unicode JavaScript
31096           * string, or 'undefined' if the encoding is unsupported. For example, we do
31097           * not support Chinese, Japanese or Korean because these would need large
31098           * mapping tables.
31099           * @param {DataView} dataView
31100           * @param {number} offset
31101           * @param {number} dataLength
31102           * @param {string} encoding
31103           * @returns {string}
31104           */
31105
31106          decode.MACSTRING = function (dataView, offset, dataLength, encoding) {
31107            var table = eightBitMacEncodings[encoding];
31108
31109            if (table === undefined) {
31110              return undefined;
31111            }
31112
31113            var result = '';
31114
31115            for (var i = 0; i < dataLength; i++) {
31116              var c = dataView.getUint8(offset + i); // In all eight-bit Mac encodings, the characters 0x00..0x7F are
31117              // mapped to U+0000..U+007F; we only need to look up the others.
31118
31119              if (c <= 0x7F) {
31120                result += String.fromCharCode(c);
31121              } else {
31122                result += table[c & 0x7F];
31123              }
31124            }
31125
31126            return result;
31127          }; // Helper function for encode.MACSTRING. Returns a dictionary for mapping
31128          // Unicode character codes to their 8-bit MacOS equivalent. This table
31129          // is not exactly a super cheap data structure, but we do not care because
31130          // encoding Macintosh strings is only rarely needed in typical applications.
31131
31132
31133          var macEncodingTableCache = typeof WeakMap === 'function' && new WeakMap();
31134          var macEncodingCacheKeys;
31135
31136          var getMacEncodingTable = function (encoding) {
31137            // Since we use encoding as a cache key for WeakMap, it has to be
31138            // a String object and not a literal. And at least on NodeJS 2.10.1,
31139            // WeakMap requires that the same String instance is passed for cache hits.
31140            if (!macEncodingCacheKeys) {
31141              macEncodingCacheKeys = {};
31142
31143              for (var e in eightBitMacEncodings) {
31144                /*jshint -W053 */
31145                // Suppress "Do not use String as a constructor."
31146                macEncodingCacheKeys[e] = new String(e);
31147              }
31148            }
31149
31150            var cacheKey = macEncodingCacheKeys[encoding];
31151
31152            if (cacheKey === undefined) {
31153              return undefined;
31154            } // We can't do "if (cache.has(key)) {return cache.get(key)}" here:
31155            // since garbage collection may run at any time, it could also kick in
31156            // between the calls to cache.has() and cache.get(). In that case,
31157            // we would return 'undefined' even though we do support the encoding.
31158
31159
31160            if (macEncodingTableCache) {
31161              var cachedTable = macEncodingTableCache.get(cacheKey);
31162
31163              if (cachedTable !== undefined) {
31164                return cachedTable;
31165              }
31166            }
31167
31168            var decodingTable = eightBitMacEncodings[encoding];
31169
31170            if (decodingTable === undefined) {
31171              return undefined;
31172            }
31173
31174            var encodingTable = {};
31175
31176            for (var i = 0; i < decodingTable.length; i++) {
31177              encodingTable[decodingTable.charCodeAt(i)] = i + 0x80;
31178            }
31179
31180            if (macEncodingTableCache) {
31181              macEncodingTableCache.set(cacheKey, encodingTable);
31182            }
31183
31184            return encodingTable;
31185          };
31186          /**
31187           * Encodes an old-style Macintosh string. Returns a byte array upon success.
31188           * If the requested encoding is unsupported, or if the input string contains
31189           * a character that cannot be expressed in the encoding, the function returns
31190           * 'undefined'.
31191           * @param {string} str
31192           * @param {string} encoding
31193           * @returns {Array}
31194           */
31195
31196
31197          encode.MACSTRING = function (str, encoding) {
31198            var table = getMacEncodingTable(encoding);
31199
31200            if (table === undefined) {
31201              return undefined;
31202            }
31203
31204            var result = [];
31205
31206            for (var i = 0; i < str.length; i++) {
31207              var c = str.charCodeAt(i); // In all eight-bit Mac encodings, the characters 0x00..0x7F are
31208              // mapped to U+0000..U+007F; we only need to look up the others.
31209
31210              if (c >= 0x80) {
31211                c = table[c];
31212
31213                if (c === undefined) {
31214                  // str contains a Unicode character that cannot be encoded
31215                  // in the requested encoding.
31216                  return undefined;
31217                }
31218              }
31219
31220              result[i] = c; // result.push(c);
31221            }
31222
31223            return result;
31224          };
31225          /**
31226           * @param {string} str
31227           * @param {string} encoding
31228           * @returns {number}
31229           */
31230
31231
31232          sizeOf.MACSTRING = function (str, encoding) {
31233            var b = encode.MACSTRING(str, encoding);
31234
31235            if (b !== undefined) {
31236              return b.length;
31237            } else {
31238              return 0;
31239            }
31240          }; // Helper for encode.VARDELTAS
31241
31242
31243          function isByteEncodable(value) {
31244            return value >= -128 && value <= 127;
31245          } // Helper for encode.VARDELTAS
31246
31247
31248          function encodeVarDeltaRunAsZeroes(deltas, pos, result) {
31249            var runLength = 0;
31250            var numDeltas = deltas.length;
31251
31252            while (pos < numDeltas && runLength < 64 && deltas[pos] === 0) {
31253              ++pos;
31254              ++runLength;
31255            }
31256
31257            result.push(0x80 | runLength - 1);
31258            return pos;
31259          } // Helper for encode.VARDELTAS
31260
31261
31262          function encodeVarDeltaRunAsBytes(deltas, offset, result) {
31263            var runLength = 0;
31264            var numDeltas = deltas.length;
31265            var pos = offset;
31266
31267            while (pos < numDeltas && runLength < 64) {
31268              var value = deltas[pos];
31269
31270              if (!isByteEncodable(value)) {
31271                break;
31272              } // Within a byte-encoded run of deltas, a single zero is best
31273              // stored literally as 0x00 value. However, if we have two or
31274              // more zeroes in a sequence, it is better to start a new run.
31275              // Fore example, the sequence of deltas [15, 15, 0, 15, 15]
31276              // becomes 6 bytes (04 0F 0F 00 0F 0F) when storing the zero
31277              // within the current run, but 7 bytes (01 0F 0F 80 01 0F 0F)
31278              // when starting a new run.
31279
31280
31281              if (value === 0 && pos + 1 < numDeltas && deltas[pos + 1] === 0) {
31282                break;
31283              }
31284
31285              ++pos;
31286              ++runLength;
31287            }
31288
31289            result.push(runLength - 1);
31290
31291            for (var i = offset; i < pos; ++i) {
31292              result.push(deltas[i] + 256 & 0xff);
31293            }
31294
31295            return pos;
31296          } // Helper for encode.VARDELTAS
31297
31298
31299          function encodeVarDeltaRunAsWords(deltas, offset, result) {
31300            var runLength = 0;
31301            var numDeltas = deltas.length;
31302            var pos = offset;
31303
31304            while (pos < numDeltas && runLength < 64) {
31305              var value = deltas[pos]; // Within a word-encoded run of deltas, it is easiest to start
31306              // a new run (with a different encoding) whenever we encounter
31307              // a zero value. For example, the sequence [0x6666, 0, 0x7777]
31308              // needs 7 bytes when storing the zero inside the current run
31309              // (42 66 66 00 00 77 77), and equally 7 bytes when starting a
31310              // new run (40 66 66 80 40 77 77).
31311
31312              if (value === 0) {
31313                break;
31314              } // Within a word-encoded run of deltas, a single value in the
31315              // range (-128..127) should be encoded within the current run
31316              // because it is more compact. For example, the sequence
31317              // [0x6666, 2, 0x7777] becomes 7 bytes when storing the value
31318              // literally (42 66 66 00 02 77 77), but 8 bytes when starting
31319              // a new run (40 66 66 00 02 40 77 77).
31320
31321
31322              if (isByteEncodable(value) && pos + 1 < numDeltas && isByteEncodable(deltas[pos + 1])) {
31323                break;
31324              }
31325
31326              ++pos;
31327              ++runLength;
31328            }
31329
31330            result.push(0x40 | runLength - 1);
31331
31332            for (var i = offset; i < pos; ++i) {
31333              var val = deltas[i];
31334              result.push(val + 0x10000 >> 8 & 0xff, val + 0x100 & 0xff);
31335            }
31336
31337            return pos;
31338          }
31339          /**
31340           * Encode a list of variation adjustment deltas.
31341           *
31342           * Variation adjustment deltas are used in ‘gvar’ and ‘cvar’ tables.
31343           * They indicate how points (in ‘gvar’) or values (in ‘cvar’) get adjusted
31344           * when generating instances of variation fonts.
31345           *
31346           * @see https://www.microsoft.com/typography/otspec/gvar.htm
31347           * @see https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6gvar.html
31348           * @param {Array}
31349           * @return {Array}
31350           */
31351
31352
31353          encode.VARDELTAS = function (deltas) {
31354            var pos = 0;
31355            var result = [];
31356
31357            while (pos < deltas.length) {
31358              var value = deltas[pos];
31359
31360              if (value === 0) {
31361                pos = encodeVarDeltaRunAsZeroes(deltas, pos, result);
31362              } else if (value >= -128 && value <= 127) {
31363                pos = encodeVarDeltaRunAsBytes(deltas, pos, result);
31364              } else {
31365                pos = encodeVarDeltaRunAsWords(deltas, pos, result);
31366              }
31367            }
31368
31369            return result;
31370          }; // Convert a list of values to a CFF INDEX structure.
31371          // The values should be objects containing name / type / value.
31372
31373          /**
31374           * @param {Array} l
31375           * @returns {Array}
31376           */
31377
31378
31379          encode.INDEX = function (l) {
31380            //var offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data,
31381            //    i, v;
31382            // Because we have to know which data type to use to encode the offsets,
31383        
31383    // we have to go through the values twice: once to encode the data and
31384            // calculate the offsets, then again to encode the offsets using the fitting data type.
31385            var offset = 1; // First offset is always 1.
31386
31387            var offsets = [offset];
31388            var data = [];
31389
31390            for (var i = 0; i < l.length; i += 1) {
31391              var v = encode.OBJECT(l[i]);
31392              Array.prototype.push.apply(data, v);
31393              offset += v.length;
31394              offsets.push(offset);
31395            }
31396
31397            if (data.length === 0) {
31398              return [0, 0];
31399            }
31400
31401            var encodedOffsets = [];
31402            var offSize = 1 + Math.floor(Math.log(offset) / Math.log(2)) / 8 | 0;
31403            var offsetEncoder = [undefined, encode.BYTE, encode.USHORT, encode.UINT24, encode.ULONG][offSize];
31404
31405            for (var i$1 = 0; i$1 < offsets.length; i$1 += 1) {
31406              var encodedOffset = offsetEncoder(offsets[i$1]);
31407              Array.prototype.push.apply(encodedOffsets, encodedOffset);
31408            }
31409
31410            return Array.prototype.concat(encode.Card16(l.length), encode.OffSize(offSize), encodedOffsets, data);
31411          };
31412          /**
31413           * @param {Array}
31414           * @returns {number}
31415           */
31416
31417
31418          sizeOf.INDEX = function (v) {
31419            return encode.INDEX(v).length;
31420          };
31421          /**
31422           * Convert an object to a CFF DICT structure.
31423           * The keys should be numeric.
31424           * The values should be objects containing name / type / value.
31425           * @param {Object} m
31426           * @returns {Array}
31427           */
31428
31429
31430          encode.DICT = function (m) {
31431            var d = [];
31432            var keys = Object.keys(m);
31433            var length = keys.length;
31434
31435            for (var i = 0; i < length; i += 1) {
31436              // Object.keys() return string keys, but our keys are always numeric.
31437              var k = parseInt(keys[i], 0);
31438              var v = m[k]; // Value comes before the key.
31439
31440              d = d.concat(encode.OPERAND(v.value, v.type));
31441              d = d.concat(encode.OPERATOR(k));
31442            }
31443
31444            return d;
31445          };
31446          /**
31447           * @param {Object}
31448           * @returns {number}
31449           */
31450
31451
31452          sizeOf.DICT = function (m) {
31453            return encode.DICT(m).length;
31454          };
31455          /**
31456           * @param {number}
31457           * @returns {Array}
31458           */
31459
31460
31461          encode.OPERATOR = function (v) {
31462            if (v < 1200) {
31463              return [v];
31464            } else {
31465              return [12, v - 1200];
31466            }
31467          };
31468          /**
31469           * @param {Array} v
31470           * @param {string}
31471           * @returns {Array}
31472           */
31473
31474
31475          encode.OPERAND = function (v, type) {
31476            var d = [];
31477
31478            if (Array.isArray(type)) {
31479              for (var i = 0; i < type.length; i += 1) {
31480                check.argument(v.length === type.length, 'Not enough arguments given for type' + type);
31481                d = d.concat(encode.OPERAND(v[i], type[i]));
31482              }
31483            } else {
31484              if (type === 'SID') {
31485                d = d.concat(encode.NUMBER(v));
31486              } else if (type === 'offset') {
31487                // We make it easy for ourselves and always encode offsets as
31488                // 4 bytes. This makes offset calculation for the top dict easier.
31489                d = d.concat(encode.NUMBER32(v));
31490              } else if (type === 'number') {
31491                d = d.concat(encode.NUMBER(v));
31492              } else if (type === 'real') {
31493                d = d.concat(encode.REAL(v));
31494              } else {
31495                throw new Error('Unknown operand type ' + type); // FIXME Add support for booleans
31496              }
31497            }
31498
31499            return d;
31500          };
31501
31502          encode.OP = encode.BYTE;
31503          sizeOf.OP = sizeOf.BYTE; // memoize charstring encoding using WeakMap if available
31504
31505          var wmm = typeof WeakMap === 'function' && new WeakMap();
31506          /**
31507           * Convert a list of CharString operations to bytes.
31508           * @param {Array}
31509           * @returns {Array}
31510           */
31511
31512          encode.CHARSTRING = function (ops) {
31513            // See encode.MACSTRING for why we don't do "if (wmm && wmm.has(ops))".
31514            if (wmm) {
31515              var cachedValue = wmm.get(ops);
31516
31517              if (cachedValue !== undefined) {
31518                return cachedValue;
31519              }
31520            }
31521
31522            var d = [];
31523            var length = ops.length;
31524
31525            for (var i = 0; i < length; i += 1) {
31526              var op = ops[i];
31527              d = d.concat(encode[op.type](op.value));
31528            }
31529
31530            if (wmm) {
31531              wmm.set(ops, d);
31532            }
31533
31534            return d;
31535          };
31536          /**
31537           * @param {Array}
31538           * @returns {number}
31539           */
31540
31541
31542          sizeOf.CHARSTRING = function (ops) {
31543            return encode.CHARSTRING(ops).length;
31544          }; // Utility functions ////////////////////////////////////////////////////////
31545
31546          /**
31547           * Convert an object containing name / type / value to bytes.
31548           * @param {Object}
31549           * @returns {Array}
31550           */
31551
31552
31553          encode.OBJECT = function (v) {
31554            var encodingFunction = encode[v.type];
31555            check.argument(encodingFunction !== undefined, 'No encoding function for type ' + v.type);
31556            return encodingFunction(v.value);
31557          };
31558          /**
31559           * @param {Object}
31560           * @returns {number}
31561           */
31562
31563
31564          sizeOf.OBJECT = function (v) {
31565            var sizeOfFunction = sizeOf[v.type];
31566            check.argument(sizeOfFunction !== undefined, 'No sizeOf function for type ' + v.type);
31567            return sizeOfFunction(v.value);
31568          };
31569          /**
31570           * Convert a table object to bytes.
31571           * A table contains a list of fields containing the metadata (name, type and default value).
31572           * The table itself has the field values set as attributes.
31573           * @param {opentype.Table}
31574           * @returns {Array}
31575           */
31576
31577
31578          encode.TABLE = function (table) {
31579            var d = [];
31580            var length = table.fields.length;
31581            var subtables = [];
31582            var subtableOffsets = [];
31583
31584            for (var i = 0; i < length; i += 1) {
31585              var field = table.fields[i];
31586              var encodingFunction = encode[field.type];
31587              check.argument(encodingFunction !== undefined, 'No encoding function for field type ' + field.type + ' (' + field.name + ')');
31588              var value = table[field.name];
31589
31590              if (value === undefined) {
31591                value = field.value;
31592              }
31593
31594              var bytes = encodingFunction(value);
31595
31596              if (field.type === 'TABLE') {
31597                subtableOffsets.push(d.length);
31598                d = d.concat([0, 0]);
31599                subtables.push(bytes);
31600              } else {
31601                d = d.concat(bytes);
31602              }
31603            }
31604
31605            for (var i$1 = 0; i$1 < subtables.length; i$1 += 1) {
31606              var o = subtableOffsets[i$1];
31607              var offset = d.length;
31608              check.argument(offset < 65536, 'Table ' + table.tableName + ' too big.');
31609              d[o] = offset >> 8;
31610              d[o + 1] = offset & 0xff;
31611              d = d.concat(subtables[i$1]);
31612            }
31613
31614            return d;
31615          };
31616          /**
31617           * @param {opentype.Table}
31618           * @returns {number}
31619           */
31620
31621
31622          sizeOf.TABLE = function (table) {
31623            var numBytes = 0;
31624            var length = table.fields.length;
31625
31626            for (var i = 0; i < length; i += 1) {
31627              var field = table.fields[i];
31628              var sizeOfFunction = sizeOf[field.type];
31629              check.argument(sizeOfFunction !== undefined, 'No sizeOf function for field type ' + field.type + ' (' + field.name + ')');
31630              var value = table[field.name];
31631
31632              if (value === undefined) {
31633                value = field.value;
31634              }
31635
31636              numBytes += sizeOfFunction(value); // Subtables take 2 more bytes for offsets.
31637
31638              if (field.type === 'TABLE') {
31639                numBytes += 2;
31640              }
31641            }
31642
31643            return numBytes;
31644          };
31645
31646          encode.RECORD = encode.TABLE;
31647          sizeOf.RECORD = sizeOf.TABLE; // Merge in a list of bytes.
31648
31649          encode.LITERAL = function (v) {
31650            return v;
31651          };
31652
31653          sizeOf.LITERAL = function (v) {
31654            return v.length;
31655          }; // Table metadata
31656
31657          /**
31658           * @exports opentype.Table
31659           * @class
31660           * @param {string} tableName
31661           * @param {Array} fields
31662           * @param {Object} options
31663           * @constructor
31664           */
31665
31666
31667          function Table(tableName, fields, options) {
31668            var this$1 = this;
31669
31670            for (var i = 0; i < fields.length; i += 1) {
31671              var field = fields[i];
31672              this$1[field.name] = field.value;
31673            }
31674
31675            this.tableName = tableName;
31676            this.fields = fields;
31677
31678            if (options) {
31679              var optionKeys = Object.keys(options);
31680
31681              for (var i$1 = 0; i$1 < optionKeys.length; i$1 += 1) {
31682                var k = optionKeys[i$1];
31683                var v = options[k];
31684
31685                if (this$1[k] !== undefined) {
31686                  this$1[k] = v;
31687                }
31688              }
31689            }
31690          }
31691          /**
31692           * Encodes the table and returns an array of bytes
31693           * @return {Array}
31694           */
31695
31696
31697          Table.prototype.encode = function () {
31698            return encode.TABLE(this);
31699          };
31700          /**
31701           * Get the size of the table.
31702           * @return {number}
31703           */
31704
31705
31706          Table.prototype.sizeOf = function () {
31707            return sizeOf.TABLE(this);
31708          };
31709          /**
31710           * @private
31711           */
31712
31713
31714          function ushortList(itemName, list, count) {
31715            if (count === undefined) {
31716              count = list.length;
31717            }
31718
31719            var fields = new Array(list.length + 1);
31720            fields[0] = {
31721              name: itemName + 'Count',
31722              type: 'USHORT',
31723              value: count
31724            };
31725
31726            for (var i = 0; i < list.length; i++) {
31727              fields[i + 1] = {
31728                name: itemName + i,
31729                type: 'USHORT',
31730                value: list[i]
31731              };
31732            }
31733
31734            return fields;
31735          }
31736          /**
31737           * @private
31738           */
31739
31740
31741          function tableList(itemName, records, itemCallback) {
31742            var count = records.length;
31743            var fields = new Array(count + 1);
31744            fields[0] = {
31745              name: itemName + 'Count',
31746              type: 'USHORT',
31747              value: count
31748            };
31749
31750            for (var i = 0; i < count; i++) {
31751              fields[i + 1] = {
31752                name: itemName + i,
31753                type: 'TABLE',
31754                value: itemCallback(records[i], i)
31755              };
31756            }
31757
31758            return fields;
31759          }
31760          /**
31761           * @private
31762           */
31763
31764
31765          function recordList(itemName, records, itemCallback) {
31766            var count = records.length;
31767            var fields = [];
31768            fields[0] = {
31769              name: itemName + 'Count',
31770              type: 'USHORT',
31771              value: count
31772            };
31773
31774            for (var i = 0; i < count; i++) {
31775              fields = fields.concat(itemCallback(records[i], i));
31776            }
31777
31778            return fields;
31779          } // Common Layout Tables
31780
31781          /**
31782           * @exports opentype.Coverage
31783           * @class
31784           * @param {opentype.Table}
31785           * @constructor
31786           * @extends opentype.Table
31787           */
31788
31789
31790          function Coverage(coverageTable) {
31791            if (coverageTable.format === 1) {
31792              Table.call(this, 'coverageTable', [{
31793                name: 'coverageFormat',
31794                type: 'USHORT',
31795                value: 1
31796              }].concat(ushortList('glyph', coverageTable.glyphs)));
31797            } else {
31798              check.assert(false, 'Can\'t create coverage table format 2 yet.');
31799            }
31800          }
31801
31802          Coverage.prototype = Object.create(Table.prototype);
31803          Coverage.prototype.constructor = Coverage;
31804
31805          function ScriptList(scriptListTable) {
31806            Table.call(this, 'scriptListTable', recordList('scriptRecord', scriptListTable, function (scriptRecord, i) {
31807              var script = scriptRecord.script;
31808              var defaultLangSys = script.defaultLangSys;
31809              check.assert(!!defaultLangSys, 'Unable to write GSUB: script ' + scriptRecord.tag + ' has no default language system.');
31810              return [{
31811                name: 'scriptTag' + i,
31812                type: 'TAG',
31813                value: scriptRecord.tag
31814              }, {
31815                name: 'script' + i,
31816                type: 'TABLE',
31817                value: new Table('scriptTable', [{
31818                  name: 'defaultLangSys',
31819                  type: 'TABLE',
31820                  value: new Table('defaultLangSys', [{
31821                    name: 'lookupOrder',
31822                    type: 'USHORT',
31823                    value: 0
31824                  }, {
31825                    name: 'reqFeatureIndex',
31826                    type: 'USHORT',
31827                    value: defaultLangSys.reqFeatureIndex
31828                  }].concat(ushortList('featureIndex', defaultLangSys.featureIndexes)))
31829                }].concat(recordList('langSys', script.langSysRecords, function (langSysRecord, i) {
31830                  var langSys = langSysRecord.langSys;
31831                  return [{
31832                    name: 'langSysTag' + i,
31833                    type: 'TAG',
31834                    value: langSysRecord.tag
31835                  }, {
31836                    name: 'langSys' + i,
31837                    type: 'TABLE',
31838                    value: new Table('langSys', [{
31839                      name: 'lookupOrder',
31840                      type: 'USHORT',
31841                      value: 0
31842                    }, {
31843                      name: 'reqFeatureIndex',
31844                      type: 'USHORT',
31845                      value: langSys.reqFeatureIndex
31846                    }].concat(ushortList('featureIndex', langSys.featureIndexes)))
31847                  }];
31848                })))
31849              }];
31850            }));
31851          }
31852
31853          ScriptList.prototype = Object.create(Table.prototype);
31854          ScriptList.prototype.constructor = ScriptList;
31855          /**
31856           * @exports opentype.FeatureList
31857           * @class
31858           * @param {opentype.Table}
31859           * @constructor
31860           * @extends opentype.Table
31861           */
31862
31863          function FeatureList(featureListTable) {
31864            Table.call(this, 'featureListTable', recordList('featureRecord', featureListTable, function (featureRecord, i) {
31865              var feature = featureRecord.feature;
31866              return [{
31867                name: 'featureTag' + i,
31868                type: 'TAG',
31869                value: featureRecord.tag
31870              }, {
31871                name: 'feature' + i,
31872                type: 'TABLE',
31873                value: new Table('featureTable', [{
31874                  name: 'featureParams',
31875                  type: 'USHORT',
31876                  value: feature.featureParams
31877                }].concat(ushortList('lookupListIndex', feature.lookupListIndexes)))
31878              }];
31879            }));
31880          }
31881
31882          FeatureList.prototype = Object.create(Table.prototype);
31883          FeatureList.prototype.constructor = FeatureList;
31884          /**
31885           * @exports opentype.LookupList
31886           * @class
31887           * @param {opentype.Table}
31888           * @param {Object}
31889           * @constructor
31890           * @extends opentype.Table
31891           */
31892
31893          function LookupList(lookupListTable, subtableMakers) {
31894            Table.call(this, 'lookupListTable', tableList('lookup', lookupListTable, function (lookupTable) {
31895              var subtableCallback = subtableMakers[lookupTable.lookupType];
31896              check.assert(!!subtableCallback, 'Unable to write GSUB lookup type ' + lookupTable.lookupType + ' tables.');
31897              return new Table('lookupTable', [{
31898                name: 'lookupType',
31899                type: 'USHORT',
31900                value: lookupTable.lookupType
31901              }, {
31902                name: 'lookupFlag',
31903                type: 'USHORT',
31904                value: lookupTable.lookupFlag
31905              }].concat(tableList('subtable', lookupTable.subtables, subtableCallback)));
31906            }));
31907          }
31908
31909          LookupList.prototype = Object.create(Table.prototype);
31910          LookupList.prototype.constructor = LookupList; // Record = same as Table, but inlined (a Table has an offset and its data is further in the stream)
31911          // Don't use offsets inside Records (probable bug), only in Tables.
31912
31913          var table = {
31914            Table: Table,
31915            Record: Table,
31916            Coverage: Coverage,
31917            ScriptList: ScriptList,
31918            FeatureList: FeatureList,
31919            LookupList: LookupList,
31920            ushortList: ushortList,
31921            tableList: tableList,
31922            recordList: recordList
31923          }; // Parsing utility functions
31924          // Retrieve an unsigned byte from the DataView.
31925
31926          function getByte(dataView, offset) {
31927            return dataView.getUint8(offset);
31928          } // Retrieve an unsigned 16-bit short from the DataView.
31929          // The value is stored in big endian.
31930
31931
31932          function getUShort(dataView, offset) {
31933            return dataView.getUint16(offset, false);
31934          } // Retrieve a signed 16-bit short from the DataView.
31935          // The value is stored in big endian.
31936
31937
31938          function getShort(dataView, offset) {
31939            return dataView.getInt16(offset, false);
31940          } // Retrieve an unsigned 32-bit long from the DataView.
31941          // The value is stored in big endian.
31942
31943
31944          function getULong(dataView, offset) {
31945            return dataView.getUint32(offset, false);
31946          } // Retrieve a 32-bit signed fixed-point number (16.16) from the DataView.
31947          // The value is stored in big endian.
31948
31949
31950          function getFixed(dataView, offset) {
31951            var decimal = dataView.getInt16(offset, false);
31952            var fraction = dataView.getUint16(offset + 2, false);
31953            return decimal + fraction / 65535;
31954          } // Retrieve a 4-character tag from the DataView.
31955          // Tags are used to identify tables.
31956
31957
31958          function getTag(dataView, offset) {
31959            var tag = '';
31960
31961            for (var i = offset; i < offset + 4; i += 1) {
31962              tag += String.fromCharCode(dataView.getInt8(i));
31963            }
31964
31965            return tag;
31966          } // Retrieve an offset from the DataView.
31967          // Offsets are 1 to 4 bytes in length, depending on the offSize argument.
31968
31969
31970          function getOffset(dataView, offset, offSize) {
31971            var v = 0;
31972
31973            for (var i = 0; i < offSize; i += 1) {
31974              v <<= 8;
31975              v += dataView.getUint8(offset + i);
31976            }
31977
31978            return v;
31979          } // Retrieve a number of bytes from start offset to the end offset from the DataView.
31980
31981
31982          function getBytes(dataView, startOffset, endOffset) {
31983            var bytes = [];
31984
31985            for (var i = startOffset; i < endOffset; i += 1) {
31986              bytes.push(dataView.getUint8(i));
31987            }
31988
31989            return bytes;
31990          }
31990 // Convert the list of bytes to a string.
31991
31992
31993          function bytesToString(bytes) {
31994            var s = '';
31995
31996            for (var i = 0; i < bytes.length; i += 1) {
31997              s += String.fromCharCode(bytes[i]);
31998            }
31999
32000            return s;
32001          }
32002
32003          var typeOffsets = {
32004            byte: 1,
32005            uShort: 2,
32006            short: 2,
32007            uLong: 4,
32008            fixed: 4,
32009            longDateTime: 8,
32010            tag: 4
32011          }; // A stateful parser that changes the offset whenever a value is retrieved.
32012          // The data is a DataView.
32013
32014          function Parser(data, offset) {
32015            this.data = data;
32016            this.offset = offset;
32017            this.relativeOffset = 0;
32018          }
32019
32020          Parser.prototype.parseByte = function () {
32021            var v = this.data.getUint8(this.offset + this.relativeOffset);
32022            this.relativeOffset += 1;
32023            return v;
32024          };
32025
32026          Parser.prototype.parseChar = function () {
32027            var v = this.data.getInt8(this.offset + this.relativeOffset);
32028            this.relativeOffset += 1;
32029            return v;
32030          };
32031
32032          Parser.prototype.parseCard8 = Parser.prototype.parseByte;
32033
32034          Parser.prototype.parseUShort = function () {
32035            var v = this.data.getUint16(this.offset + this.relativeOffset);
32036            this.relativeOffset += 2;
32037            return v;
32038          };
32039
32040          Parser.prototype.parseCard16 = Parser.prototype.parseUShort;
32041          Parser.prototype.parseSID = Parser.prototype.parseUShort;
32042          Parser.prototype.parseOffset16 = Parser.prototype.parseUShort;
32043
32044          Parser.prototype.parseShort = function () {
32045            var v = this.data.getInt16(this.offset + this.relativeOffset);
32046            this.relativeOffset += 2;
32047            return v;
32048          };
32049
32050          Parser.prototype.parseF2Dot14 = function () {
32051            var v = this.data.getInt16(this.offset + this.relativeOffset) / 16384;
32052            this.relativeOffset += 2;
32053            return v;
32054          };
32055
32056          Parser.prototype.parseULong = function () {
32057            var v = getULong(this.data, this.offset + this.relativeOffset);
32058            this.relativeOffset += 4;
32059            return v;
32060          };
32061
32062          Parser.prototype.parseOffset32 = Parser.prototype.parseULong;
32063
32064          Parser.prototype.parseFixed = function () {
32065            var v = getFixed(this.data, this.offset + this.relativeOffset);
32066            this.relativeOffset += 4;
32067            return v;
32068          };
32069
32070          Parser.prototype.parseString = function (length) {
32071            var dataView = this.data;
32072            var offset = this.offset + this.relativeOffset;
32073            var string = '';
32074            this.relativeOffset += length;
32075
32076            for (var i = 0; i < length; i++) {
32077              string += String.fromCharCode(dataView.getUint8(offset + i));
32078            }
32079
32080            return string;
32081          };
32082
32083          Parser.prototype.parseTag = function () {
32084            return this.parseString(4);
32085          }; // LONGDATETIME is a 64-bit integer.
32086          // JavaScript and unix timestamps traditionally use 32 bits, so we
32087          // only take the last 32 bits.
32088          // + Since until 2038 those bits will be filled by zeros we can ignore them.
32089
32090
32091          Parser.prototype.parseLongDateTime = function () {
32092            var v = getULong(this.data, this.offset + this.relativeOffset + 4); // Subtract seconds between 01/01/1904 and 01/01/1970
32093            // to convert Apple Mac timestamp to Standard Unix timestamp
32094
32095            v -= 2082844800;
32096            this.relativeOffset += 8;
32097            return v;
32098          };
32099
32100          Parser.prototype.parseVersion = function (minorBase) {
32101            var major = getUShort(this.data, this.offset + this.relativeOffset); // How to interpret the minor version is very vague in the spec. 0x5000 is 5, 0x1000 is 1
32102            // Default returns the correct number if minor = 0xN000 where N is 0-9
32103            // Set minorBase to 1 for tables that use minor = N where N is 0-9
32104
32105            var minor = getUShort(this.data, this.offset + this.relativeOffset + 2);
32106            this.relativeOffset += 4;
32107
32108            if (minorBase === undefined) {
32109              minorBase = 0x1000;
32110            }
32111
32112            return major + minor / minorBase / 10;
32113          };
32114
32115          Parser.prototype.skip = function (type, amount) {
32116            if (amount === undefined) {
32117              amount = 1;
32118            }
32119
32120            this.relativeOffset += typeOffsets[type] * amount;
32121          }; ///// Parsing lists and records ///////////////////////////////
32122          // Parse a list of 32 bit unsigned integers.
32123
32124
32125          Parser.prototype.parseULongList = function (count) {
32126            if (count === undefined) {
32127              count = this.parseULong();
32128            }
32129
32130            var offsets = new Array(count);
32131            var dataView = this.data;
32132            var offset = this.offset + this.relativeOffset;
32133
32134            for (var i = 0; i < count; i++) {
32135              offsets[i] = dataView.getUint32(offset);
32136              offset += 4;
32137            }
32138
32139            this.relativeOffset += count * 4;
32140            return offsets;
32141          }; // Parse a list of 16 bit unsigned integers. The length of the list can be read on the stream
32142          // or provided as an argument.
32143
32144
32145          Parser.prototype.parseOffset16List = Parser.prototype.parseUShortList = function (count) {
32146            if (count === undefined) {
32147              count = this.parseUShort();
32148            }
32149
32150            var offsets = new Array(count);
32151            var dataView = this.data;
32152            var offset = this.offset + this.relativeOffset;
32153
32154            for (var i = 0; i < count; i++) {
32155              offsets[i] = dataView.getUint16(offset);
32156              offset += 2;
32157            }
32158
32159            this.relativeOffset += count * 2;
32160            return offsets;
32161          }; // Parses a list of 16 bit signed integers.
32162
32163
32164          Parser.prototype.parseShortList = function (count) {
32165            var list = new Array(count);
32166            var dataView = this.data;
32167            var offset = this.offset + this.relativeOffset;
32168
32169            for (var i = 0; i < count; i++) {
32170              list[i] = dataView.getInt16(offset);
32171              offset += 2;
32172            }
32173
32174            this.relativeOffset += count * 2;
32175            return list;
32176          };
32176 // Parses a list of bytes.
32177
32178
32179          Parser.prototype.parseByteList = function (count) {
32180            var list = new Array(count);
32181            var dataView = this.data;
32182            var offset = this.offset + this.relativeOffset;
32183
32184            for (var i = 0; i < count; i++) {
32185              list[i] = dataView.getUint8(offset++);
32186            }
32187
32188            this.relativeOffset += count;
32189            return list;
32190          };
32191          /**
32192           * Parse a list of items.
32193           * Record count is optional, if omitted it is read from the stream.
32194           * itemCallback is one of the Parser methods.
32195           */
32196
32197
32198          Parser.prototype.parseList = function (count, itemCallback) {
32199            var this$1 = this;
32200
32201            if (!itemCallback) {
32202              itemCallback = count;
32203              count = this.parseUShort();
32204            }
32205
32206            var list = new Array(count);
32207
32208            for (var i = 0; i < count; i++) {
32209              list[i] = itemCallback.call(this$1);
32210            }
32211
32212            return list;
32213          };
32214
32215          Parser.prototype.parseList32 = function (count, itemCallback) {
32216            var this$1 = this;
32217
32218            if (!itemCallback) {
32219              itemCallback = count;
32220              count = this.parseULong();
32221            }
32222
32223            var list = new Array(count);
32224
32225            for (var i = 0; i < count; i++) {
32226              list[i] = itemCallback.call(this$1);
32227            }
32228
32229            return list;
32230          };
32231          /**
32232           * Parse a list of records.
32233           * Record count is optional, if omitted it is read from the stream.
32234           * Example of recordDescription: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort }
32235           */
32236
32237
32238          Parser.prototype.parseRecordList = function (count, recordDescription) {
32239            var this$1 = this; // If the count argument is absent, read it in the stream.
32240
32241            if (!recordDescription) {
32242              recordDescription = count;
32243              count = this.parseUShort();
32244            }
32245
32246            var records = new Array(count);
32247            var fields = Object.keys(recordDescription);
32248
32249            for (var i = 0; i < count; i++) {
32250              var rec = {};
32251
32252              for (var j = 0; j < fields.length; j++) {
32253                var fieldName = fields[j];
32254                var fieldType = recordDescription[fieldName];
32255                rec[fieldName] = fieldType.call(this$1);
32256              }
32257
32258              records[i] = rec;
32259            }
32260
32261            return records;
32262          };
32263
32264          Parser.prototype.parseRecordList32 = function (count, recordDescription) {
32265            var this$1 = this; // If the count argument is absent, read it in the stream.
32266
32267            if (!recordDescription) {
32268              recordDescription = count;
32269              count = this.parseULong();
32270            }
32271
32272            var records = new Array(count);
32273            var fields = Object.keys(recordDescription);
32274
32275            for (var i = 0; i < count; i++) {
32276              var rec = {};
32277
32278              for (var j = 0; j < fields.length; j++) {
32279                var fieldName = fields[j];
32280                var fieldType = recordDescription[fieldName];
32281                rec[fieldName] = fieldType.call(this$1);
32282              }
32283
32284              records[i] = rec;
32285            }
32286
32287            return records;
32288          }; // Parse a data structure into an object
32289          // Example of description: { sequenceIndex: Parser.uShort, lookupListIndex: Parser.uShort }
32290
32291
32292          Parser.prototype.parseStruct = function (description) {
32293            var this$1 = this;
32294
32295            if (typeof description === 'function') {
32296              return description.call(this);
32297            } else {
32298              var fields = Object.keys(description);
32299              var struct = {};
32300
32301              for (var j = 0; j < fields.length; j++) {
32302                var fieldName = fields[j];
32303                var fieldType = description[fieldName];
32304                struct[fieldName] = fieldType.call(this$1);
32305              }
32306
32307              return struct;
32308            }
32309          };
32310          /**
32311           * Parse a GPOS valueRecord
32312           * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#value-record
32313           * valueFormat is optional, if omitted it is read from the stream.
32314           */
32315
32316
32317          Parser.prototype.parseValueRecord = function (valueFormat) {
32318            if (valueFormat === undefined) {
32319              valueFormat = this.parseUShort();
32320            }
32321
32322            if (valueFormat === 0) {
32323              // valueFormat2 in kerning pairs is most often 0
32324              // in this case return undefined instead of an empty object, to save space
32325              return;
32326            }
32327
32328            var valueRecord = {};
32329
32330            if (valueFormat & 0x0001) {
32331              valueRecord.xPlacement = this.parseShort();
32332            }
32333
32334            if (valueFormat & 0x0002) {
32335              valueRecord.yPlacement = this.parseShort();
32336            }
32337
32338            if (valueFormat & 0x0004) {
32339              valueRecord.xAdvance = this.parseShort();
32340            }
32341
32342            if (valueFormat & 0x0008) {
32343              valueRecord.yAdvance = this.parseShort();
32344            } // Device table (non-variable font) / VariationIndex table (variable font) not supported
32345            // https://docs.microsoft.com/fr-fr/typography/opentype/spec/chapter2#devVarIdxTbls
32346
32347
32348            if (valueFormat & 0x0010) {
32349              valueRecord.xPlaDevice = undefined;
32350              this.parseShort();
32351            }
32352
32353            if (valueFormat & 0x0020) {
32354              valueRecord.yPlaDevice = undefined;
32355              this.parseShort();
32356            }
32357
32358            if (valueFormat & 0x0040) {
32359              valueRecord.xAdvDevice = undefined;
32360              this.parseShort();
32361            }
32362
32363            if (valueFormat & 0x0080) {
32364              valueRecord.yAdvDevice = undefined;
32365              this.parseShort();
32366            }
32367
32368            return valueRecord;
32369          };
32370          /**
32371           * Parse a list of GPOS valueRecords
32372           * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#value-record
32373           * valueFormat and valueCount are read from the stream.
32374           */
32375
32376
32377          Parser.prototype.parseValueRecordList = function () {
32378            var this$1 = this;
32379            var valueFormat = this.parseUShort();
32380            var valueCount = this.parseUShort();
32381            var values = new Array(valueCount);
32382
32383            for (var i = 0; i < valueCount; i++) {
32384              values[i] = this$1.parseValueRecord(valueFormat);
32385            }
32386
32387            return values;
32388          };
32389
32390          Parser.prototype.parsePointer = function (description) {
32391            var structOffset = this.parseOffset16();
32392
32393            if (structOffset > 0) {
32394              // NULL offset => return undefined
32395              return new Parser(this.data, this.offset + structOffset).parseStruct(description);
32396            }
32397
32398            return undefined;
32399          };
32400
32401          Parser.prototype.parsePointer32 = function (description) {
32402            var structOffset = this.parseOffset32();
32403
32404            if (structOffset > 0) {
32405              // NULL offset => return undefined
32406              return new Parser(this.data, this.offset + structOffset).parseStruct(description);
32407            }
32408
32409            return undefined;
32410          };
32411          /**
32412           * Parse a list of offsets to lists of 16-bit integers,
32413           * or a list of offsets to lists of offsets to any kind of items.
32414           * If itemCallback is not provided, a list of list of UShort is assumed.
32415           * If provided, itemCallback is called on each item and must parse the item.
32416           * See examples in tables/gsub.js
32417           */
32418
32419
32420          Parser.prototype.parseListOfLists = function (itemCallback) {
32421            var this$1 = this;
32422            var offsets = this.parseOffset16List();
32423            var count = offsets.length;
32424            var relativeOffset = this.relativeOffset;
32425            var list = new Array(count);
32426
32427            for (var i = 0; i < count; i++) {
32428              var start = offsets[i];
32429
32430              if (start === 0) {
32431                // NULL offset
32432                // Add i as owned property to list. Convenient with assert.
32433                list[i] = undefined;
32434                continue;
32435              }
32436
32437              this$1.relativeOffset = start;
32438
32439              if (itemCallback) {
32440                var subOffsets = this$1.parseOffset16List();
32441                var subList = new Array(subOffsets.length);
32442
32443                for (var j = 0; j < subOffsets.length; j++) {
32444                  this$1.relativeOffset = start + subOffsets[j];
32445                  subList[j] = itemCallback.call(this$1);
32446                }
32447
32448                list[i] = subList;
32449              } else {
32450                list[i] = this$1.parseUShortList();
32451              }
32452            }
32453
32454            this.relativeOffset = relativeOffset;
32455            return list;
32456          };
vendor: 9,140 bytes, lines 32456-32686
32456 ///// Complex tables parsing //////////////////////////////////
32457          // Parse a coverage table in a GSUB, GPOS or GDEF table.
32458          // https://www.microsoft.com/typography/OTSPEC/chapter2.htm
32459          // parser.offset must point to the start of the table containing the coverage.
32460
32461
32462          Parser.prototype.parseCoverage = function () {
32463            var this$1 = this;
32464            var startOffset = this.offset + this.relativeOffset;
32465            var format = this.parseUShort();
32466            var count = this.parseUShort();
32467
32468            if (format === 1) {
32469              return {
32470                format: 1,
32471                glyphs: this.parseUShortList(count)
32472              };
32473            } else if (format === 2) {
32474              var ranges = new Array(count);
32475
32476              for (var i = 0; i < count; i++) {
32477                ranges[i] = {
32478                  start: this$1.parseUShort(),
32479                  end: this$1.parseUShort(),
32480                  index: this$1.parseUShort()
32481                };
32482              }
32483
32484              return {
32485                format: 2,
32486                ranges: ranges
32487              };
32488            }
32489
32490            throw new Error('0x' + startOffset.toString(16) + ': Coverage format must be 1 or 2.');
32491          }; // Parse a Class Definition Table in a GSUB, GPOS or GDEF table.
32492          // https://www.microsoft.com/typography/OTSPEC/chapter2.htm
32493
32494
32495          Parser.prototype.parseClassDef = function () {
32496            var startOffset = this.offset + this.relativeOffset;
32497            var format = this.parseUShort();
32498
32499            if (format === 1) {
32500              return {
32501                format: 1,
32502                startGlyph: this.parseUShort(),
32503                classes: this.parseUShortList()
32504              };
32505            } else if (format === 2) {
32506              return {
32507                format: 2,
32508                ranges: this.parseRecordList({
32509                  start: Parser.uShort,
32510                  end: Parser.uShort,
32511                  classId: Parser.uShort
32512                })
32513              };
32514            }
32515
32516            throw new Error('0x' + startOffset.toString(16) + ': ClassDef format must be 1 or 2.');
32517          }; ///// Static methods ///////////////////////////////////
32518          // These convenience methods can be used as callbacks and should be called with "this" context set to a Parser instance.
32519
32520
32521          Parser.list = function (count, itemCallback) {
32522            return function () {
32523              return this.parseList(count, itemCallback);
32524            };
32525          };
32526
32527          Parser.list32 = function (count, itemCallback) {
32528            return function () {
32529              return this.parseList32(count, itemCallback);
32530            };
32531          };
32532
32533          Parser.recordList = function (count, recordDescription) {
32534            return function () {
32535              return this.parseRecordList(count, recordDescription);
32536            };
32537          };
32538
32539          Parser.recordList32 = function (count, recordDescription) {
32540            return function () {
32541              return this.parseRecordList32(count, recordDescription);
32542            };
32543          };
32544
32545          Parser.pointer = function (description) {
32546            return function () {
32547              return this.parsePointer(description);
32548            };
32549          };
32550
32551          Parser.pointer32 = function (description) {
32552            return function () {
32553              return this.parsePointer32(description);
32554            };
32555          };
32556
32557          Parser.tag = Parser.prototype.parseTag;
32558          Parser.byte = Parser.prototype.parseByte;
32559          Parser.uShort = Parser.offset16 = Parser.prototype.parseUShort;
32560          Parser.uShortList = Parser.prototype.parseUShortList;
32561          Parser.uLong = Parser.offset32 = Parser.prototype.parseULong;
32562          Parser.uLongList = Parser.prototype.parseULongList;
32563          Parser.struct = Parser.prototype.parseStruct;
32564          Parser.coverage = Parser.prototype.parseCoverage;
32565          Parser.classDef = Parser.prototype.parseClassDef; ///// Script, Feature, Lookup lists ///////////////////////////////////////////////
32566          // https://www.microsoft.com/typography/OTSPEC/chapter2.htm
32567
32568          var langSysTable = {
32569            reserved: Parser.uShort,
32570            reqFeatureIndex: Parser.uShort,
32571            featureIndexes: Parser.uShortList
32572          };
32573
32574          Parser.prototype.parseScriptList = function () {
32575            return this.parsePointer(Parser.recordList({
32576              tag: Parser.tag,
32577              script: Parser.pointer({
32578                defaultLangSys: Parser.pointer(langSysTable),
32579                langSysRecords: Parser.recordList({
32580                  tag: Parser.tag,
32581                  langSys: Parser.pointer(langSysTable)
32582                })
32583              })
32584            })) || [];
32585          };
32586
32587          Parser.prototype.parseFeatureList = function () {
32588            return this.parsePointer(Parser.recordList({
32589              tag: Parser.tag,
32590              feature: Parser.pointer({
32591                featureParams: Parser.offset16,
32592                lookupListIndexes: Parser.uShortList
32593              })
32594            })) || [];
32595          };
32596
32597          Parser.prototype.parseLookupList = function (lookupTableParsers) {
32598            return this.parsePointer(Parser.list(Parser.pointer(function () {
32599              var lookupType = this.parseUShort();
32600              check.argument(1 <= lookupType && lookupType <= 9, 'GPOS/GSUB lookup type ' + lookupType + ' unknown.');
32601              var lookupFlag = this.parseUShort();
32602              var useMarkFilteringSet = lookupFlag & 0x10;
32603              return {
32604                lookupType: lookupType,
32605                lookupFlag: lookupFlag,
32606                subtables: this.parseList(Parser.pointer(lookupTableParsers[lookupType])),
32607                markFilteringSet: useMarkFilteringSet ? this.parseUShort() : undefined
32608              };
32609            }))) || [];
32610          };
32611
32612          Parser.prototype.parseFeatureVariationsList = function () {
32613            return this.parsePointer32(function () {
32614              var majorVersion = this.parseUShort();
32615              var minorVersion = this.parseUShort();
32616              check.argument(majorVersion === 1 && minorVersion < 1, 'GPOS/GSUB feature variations table unknown.');
32617              var featureVariations = this.parseRecordList32({
32618                conditionSetOffset: Parser.offset32,
32619                featureTableSubstitutionOffset: Parser.offset32
32620              });
32621              return featureVariations;
32622            }) || [];
32623          };
32624
32625          var parse = {
32626            getByte: getByte,
32627            getCard8: getByte,
32628            getUShort: getUShort,
32629            getCard16: getUShort,
32630            getShort: getShort,
32631            getULong: getULong,
32632            getFixed: getFixed,
32633            getTag: getTag,
32634            getOffset: getOffset,
32635            getBytes: getBytes,
32636            bytesToString: bytesToString,
32637            Parser: Parser
32638          }; // The `cmap` table stores the mappings from characters to glyphs.
32639
32640          function parseCmapTableFormat12(cmap, p) {
32641            //Skip reserved.
32642            p.parseUShort(); // Length in bytes of the sub-tables.
32643
32644            cmap.length = p.parseULong();
32645            cmap.language = p.parseULong();
32646            var groupCount;
32647            cmap.groupCount = groupCount = p.parseULong();
32648            cmap.glyphIndexMap = {};
32649
32650            for (var i = 0; i < groupCount; i += 1) {
32651              var startCharCode = p.parseULong();
32652              var endCharCode = p.parseULong();
32653              var startGlyphId = p.parseULong();
32654
32655              for (var c = startCharCode; c <= endCharCode; c += 1) {
32656                cmap.glyphIndexMap[c] = startGlyphId;
32657                startGlyphId++;
32658              }
32659            }
32660          }
32661
32662          function parseCmapTableFormat4(cmap, p, data, start, offset) {
32663            // Length in bytes of the sub-tables.
32664            cmap.length = p.parseUShort();
32665            cmap.language = p.parseUShort(); // segCount is stored x 2.
32666
32667            var segCount;
32668            cmap.segCount = segCount = p.parseUShort() >> 1; // Skip searchRange, entrySelector, rangeShift.
32669
32670            p.skip('uShort', 3); // The "unrolled" mapping from character codes to glyph indices.
32671
32672            cmap.glyphIndexMap = {};
32673            var endCountParser = new parse.Parser(data, start + offset + 14);
32674            var startCountParser = new parse.Parser(data, start + offset + 16 + segCount * 2);
32675            var idDeltaParser = new parse.Parser(data, start + offset + 16 + segCount * 4);
32676            var idRangeOffsetParser = new parse.Parser(data, start + offset + 16 + segCount * 6);
32677            var glyphIndexOffset = start + offset + 16 + segCount * 8;
32678
32679            for (var i = 0; i < segCount - 1; i += 1) {
32680              var glyphIndex = void 0;
32681              var endCount = endCountParser.parseUShort();
32682              var startCount = startCountParser.parseUShort();
32683              var idDelta = idDeltaParser.parseShort();
32684              var idRangeOffset = idRangeOffsetParser.parseUShort();
32685
32686              for (var c = startCount; c <= endCount; c += 1) {
32687                if (idRangeOffset !== 0) {
32688                  // The idRangeOffset is relative to the current position in the idRangeOffset array.
32689                  // Take the current offset in the idRangeOffset array.
32690                  glyphIndexOffset = idRangeOffsetParser.offset + idRangeOffsetParser.relativeOffset - 2; // Add the value of the idRangeOffset, which will move us into the glyphIndex array.
32691
32692                  glyphIndexOffset += idRangeOffset; // Then add the character index of the current segment, multiplied by 2 for USHORTs.
32693
32694                  glyphIndexOffset += (c - startCount) * 2;
32695                  glyphIndex = parse.getUShort(data, glyphIndexOffset);
32696
32697                  if (glyphIndex !== 0) {
32698                    glyphIndex = glyphIndex + idDelta & 0xFFFF;
32699                  }
32700                } else {
32701                  glyphIndex = c + idDelta & 0xFFFF;
32702                }
32703
32704                cmap.glyphIndexMap[c] = glyphIndex;
32705              }
32706            }
32707          } // Parse the `cmap` table. This table stores the mappings from characters to glyphs.
32708          // There are many available formats, but we only support the Windows format 4 and 12.
32709          // This function returns a `CmapEncoding` object or null if no supported format could be found.
32710
32711
32712          function parseCmapTable(data, start) {
32713            var cmap = {};
32714            cmap.version = parse.getUShort(data, start);
32715            check.argument(cmap.version === 0, 'cmap table version should be 0.'); // The cmap table can contain many sub-tables, each with their own format.
32716            // We're only interested in a "platform 0" (Unicode format) and "platform 3" (Windows format) table.
32717
32718            cmap.numTables = parse.getUShort(data, start + 2);
32719            var offset = -1;
32720
32721            for (var i = cmap.numTables - 1; i >= 0; i -= 1) {
32722              var platformId = parse.getUShort(data, start + 4 + i * 8);
32723              var encodingId = parse.getUShort(data, start + 4 + i * 8 + 2);
32724
32725              if (platformId === 3 && (encodingId === 0 || encodingId === 1 || encodingId === 10) || platformId === 0 && (encodingId === 0 || encodingId === 1 || encodingId === 2 || encodingId === 3 || encodingId === 4)) {
32726                offset = parse.getULong(data, start + 4 + i * 8 + 4);
32727                break;
32728              }
32729            }
32730
32731            if (offset === -1) {
32732              // There is no cmap table in the font that we support.
32733              throw new Error('No valid cmap sub-tables found.');
32734            }
32735
32736            var p = new parse.Parser(data, start + offset);
32737            cmap.format = p.parseUShort();
32738
32739            if (cmap.format === 12) {
32740              parseCmapTableFormat12(cmap, p);
32741            } else if (cmap.format === 4) {
32742              parseCmapTableFormat4(cmap, p, data, start, offset);
32743            } else {
32744              throw new Error('Only format 4 and 12 cmap tables are supported (found format ' + cmap.format + ').');
32745            }
32746
32747            return cmap;
32748          }
32749
32750          function addSegment(t, code, glyphIndex) {
32751            t.segments.push({
32752              end: code,
32753              start: code,
32754              delta: -(code - glyphIndex),
32755              offset: 0,
32756              glyphIndex: glyphIndex
32757            });
32758          }
32759
32760          function addTerminatorSegment(t) {
32761            t.segments.push({
32762              end: 0xFFFF,
32763              start: 0xFFFF,
32764              delta: 1,
32765              offset: 0
32766            });
32767          } // Make cmap table, format 4 by default, 12 if needed only
32768
32769
32770          function makeCmapTable(glyphs) {
32771            // Plan 0 is the base Unicode Plan but emojis, for example are on another plan, and needs cmap 12 format (with 32bit)
32772            var isPlan0Only = true;
32773            var i; // Check if we need to add cmap format 12 or if format 4 only is fine
32774
32775            for (i = glyphs.length - 1; i > 0; i -= 1) {
32776              var g = glyphs.get(i);
32777
32778              if (g.unicode > 65535) {
32779                console.log('Adding CMAP format 12 (needed!)');
32780                isPlan0Only = false;
32781                break;
32782              }
32783            }
32784
32785            var cmapTable = [{
32786              name: 'version',
32787              type: 'USHORT',
32788              value: 0
32789            }, {
32790              name: 'numTables',
32791              type: 'USHORT',
32792              value: isPlan0Only ? 1 : 2
32793            }, // CMAP 4 header
32794            {
32795              name: 'platformID',
32796              type: 'USHORT',
32797              value: 3
32798            }, {
32799              name: 'encodingID',
32800              type: 'USHORT',
32801              value: 1
32802            }, {
32803              name: 'offset',
32804              type: 'ULONG',
32805              value: isPlan0Only ? 12 : 12 + 8
32806            }];
32807
32808            if (!isPlan0Only) {
32809              cmapTable = cmapTable.concat([// CMAP 12 header
32810              {
32811                name: 'cmap12PlatformID',
32812                type: 'USHORT',
32813                value: 3
32814              }, // We encode only for PlatformID = 3 (Windows) because it is supported everywhere
32815              {
32816                name: 'cmap12EncodingID',
32817                type: 'USHORT',
32818                value: 10
32819              }, {
32820                name: 'cmap12Offset',
32821                type: 'ULONG',
32822                value: 0
32823              }]);
32824            }
32825
32826            cmapTable = cmapTable.concat([// CMAP 4 Subtable
32827            {
32828              name: 'format',
32829              type: 'USHORT',
32830              value: 4
32831            }, {
32832              name: 'cmap4Length',
32833              type: 'USHORT',
32834              value: 0
32835            }, {
32836              name: 'language',
32837              type: 'USHORT',
32838              value: 0
32839            }, {
32840              name: 'segCountX2',
32841              type: 'USHORT',
32842              value: 0
32843            }, {
32844              name: 'searchRange',
32845              type: 'USHORT',
32846              value: 0
32847            }, {
32848              name: 'entrySelector',
32849              type: 'USHORT',
32850              value: 0
32851            }, {
32852              name: 'rangeShift',
32853              type: 'USHORT',
32854              value: 0
32855            }]);
32856            var t = new table.Table('cmap', cmapTable);
32857            t.segments = [];
32858
32859            for (i = 0; i < glyphs.length; i += 1) {
32860              var glyph = glyphs.get(i);
32861
32862              for (var j = 0; j < glyph.unicodes.length; j += 1) {
32863                addSegment(t, glyph.unicodes[j], i);
32864              }
32865
32866              t.segments = t.segments.sort(function (a, b) {
32867                return a.start - b.start;
32868              });
32869            }
32870
32871            addTerminatorSegment(t);
32872            var segCount = t.segments.length;
32873            var segCountToRemove = 0; // CMAP 4
32874            // Set up parallel segment arrays.
32875
32876            var endCounts = [];
32877            var startCounts = [];
32878            var idDeltas = [];
32879            var idRangeOffsets = [];
32880            var glyphIds = []; // CMAP 12
32881
32882            var cmap12Groups = []; // Reminder this loop is not following the specification at 100%
32883            // The specification -> find suites of characters and make a group
32884            // Here we're doing one group for each letter
32885            // Doing as the spec can save 8 times (or more) space
32886
32887            for (i = 0; i < segCount; i += 1) {
32888              var segment = t.segments[i]; // CMAP 4
32889
32890              if (segment.end <= 65535 && segment.start <= 65535) {
32891                endCounts = endCounts.concat({
32892                  name: 'end_' + i,
32893                  type: 'USHORT',
32894                  value: segment.end
32895                });
32896                startCounts = startCounts.concat({
32897                  name: 'start_' + i,
32898                  type: 'USHORT',
32899                  value: segment.start
32900                });
32901                idDeltas = idDeltas.concat({
32902                  name: 'idDelta_' + i,
32903                  type: 'SHORT',
32904                  value: segment.delta
32905                });
32906                idRangeOffsets = idRangeOffsets.concat({
32907                  name: 'idRangeOffset_' + i,
32908                  type: 'USHORT',
32909                  value: segment.offset
32910                });
32911
32912                if (segment.glyphId !== undefined) {
32913                  glyphIds = glyphIds.concat({
32914                    name: 'glyph_' + i,
32915                    type: 'USHORT',
32916                    value: segment.glyphId
32917                  });
32918                }
32919              } else {
32920                // Skip Unicode > 65535 (16bit unsigned max) for CMAP 4, will be added in CMAP 12
32921                segCountToRemove += 1;
32922              } // CMAP 12
32923              // Skip Terminator Segment
32924
32925
32926              if (!isPlan0Only && segment.glyphIndex !== undefined) {
32927                cmap12Groups = cmap12Groups.concat({
32928                  name: 'cmap12Start_' + i,
32929                  type: 'ULONG',
32930                  value: segment.start
32931                });
32932                cmap12Groups = cmap12Groups.concat({
32933                  name: 'cmap12End_' + i,
32934                  type: 'ULONG',
32935                  value: segment.end
32936                });
32937                cmap12Groups = cmap12Groups.concat({
32938                  name: 'cmap12Glyph_' + i,
32939                  type: 'ULONG',
32940                  value: segment.glyphIndex
32941                });
32942              }
32943            } // CMAP 4 Subtable
32944
32945
32946            t.segCountX2 = (segCount - segCountToRemove) * 2;
32947            t.searchRange = Math.pow(2, Math.floor(Math.log(segCount - segCountToRemove) / Math.log(2))) * 2;
32948            t.entrySelector = Math.log(t.searchRange / 2) / Math.log(2);
32949            t.rangeShift = t.segCountX2 - t.searchRange;
32950            t.fields = t.fields.concat(endCounts);
32951            t.fields.push({
32952              name: 'reservedPad',
32953              type: 'USHORT',
32954              value: 0
32955            });
32956            t.fields = t.fields.concat(startCounts);
32957            t.fields = t.fields.concat(idDeltas);
32958            t.fields = t.fields.concat(idRangeOffsets);
32959            t.fields = t.fields.concat(glyphIds);
32960            t.cmap4Length = 14 + // Subtable header
32961            endCounts.length * 2 + 2 + // reservedPad
32962            startCounts.length * 2 + idDeltas.length * 2 + idRangeOffsets.length * 2 + glyphIds.length * 2;
32963
32964            if (!isPlan0Only) {
32965              // CMAP 12 Subtable
32966              var cmap12Length = 16 + // Subtable header
32967              cmap12Groups.length * 4;
32968              t.cmap12Offset = 12 + 2 * 2 + 4 + t.cmap4Length;
32969              t.fields = t.fields.concat([{
32970                name: 'cmap12Format',
32971                type: 'USHORT',
32972                value: 12
32973              }, {
32974                name: 'cmap12Reserved',
32975                type: 'USHORT',
32976                value: 0
32977              }, {
32978                name: 'cmap12Length',
32979                type: 'ULONG',
32980                value: cmap12Length
32981              }, {
32982                name: 'cmap12Language',
32983                type: 'ULONG',
32984                value: 0
32985              }, {
32986                name: 'cmap12nGroups',
32987                type: 'ULONG',
32988                value: cmap12Groups.length / 3
32989              }]);
32990              t.fields = t.fields.concat(cmap12Groups);
32991            }
32992
32993            return t;
32994          }
32995
32996          var cmap = {
32997            parse: parseCmapTable,
32998            make: makeCmapTable
32999          }; // Glyph encoding
33000
33001          var cffStandardStrings = ['.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', 'periodce
33001ntered', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', 'ugrave', 'yacute', 'ydieresis', 'zcaron', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', '266 ff', 'onedotenleader', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall', '001.000', '001.001', '001.002', '001.003', 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'];
33002          var cffStandardEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl', 'periodce
33002ntered', '', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla', '', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '', '', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae', '', '', '', 'dotlessi', '', '', 'lslash', 'oslash', 'oe', 'germandbls'];
33003          var cffExpertEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', '', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', '', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '', 'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters', 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall'];
33004          var standardNames = ['.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot', 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', 'guillemotright', 'ellipsis', 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodce
33004ntered', 'quotesinglbase', 'quotedblbase', 'perthousand', 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar', 'Eth', 'eth', 'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply', 'onesuperior', 'twosuperior', 'threesuperior', 'onehalf', 'onequarter', 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla', 'scedilla', 'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat'];
33005          /**
33006           * This is the encoding used for fonts created from scratch.
33007           * It loops through all glyphs and finds the appropriate unicode value.
33008           * Since it's linear time, other encodings will be faster.
33009           * @exports opentype.DefaultEncoding
33010           * @class
33011           * @constructor
33012           * @param {opentype.Font}
33013           */
33014
33015          function DefaultEncoding(font) {
33016            this.font = font;
33017          }
33018
33019          DefaultEncoding.prototype.charToGlyphIndex = function (c) {
33020            var code = c.codePointAt(0);
33021            var glyphs = this.font.glyphs;
33022
33023            if (glyphs) {
33024              for (var i = 0; i < glyphs.length; i += 1) {
33025                var glyph = glyphs.get(i);
33026
33027                for (var j = 0; j < glyph.unicodes.length; j += 1) {
33028                  if (glyph.unicodes[j] === code) {
33029                    return i;
33030                  }
33031                }
33032              }
33033            }
33034
33035            return null;
33036          };
33037          /**
33038           * @exports opentype.CmapEncoding
33039           * @class
33040           * @constructor
33041           * @param {Object} cmap - a object with the cmap encoded data
33042           */
33043
33044
33045          function CmapEncoding(cmap) {
33046            this.cmap = cmap;
33047          }
33048          /**
33049           * @param  {string} c - the character
33050           * @return {number} The glyph index.
33051           */
33052
33053
33054          CmapEncoding.prototype.charToGlyphIndex = function (c) {
33055            return this.cmap.glyphIndexMap[c.codePointAt(0)] || 0;
33056          };
33057          /**
33058           * @exports opentype.CffEncoding
33059           * @class
33060           * @constructor
33061           * @param {string} encoding - The encoding
33062           * @param {Array} charset - The character set.
33063           */
33064
33065
33066          function CffEncoding(encoding, charset) {
33067            this.encoding = encoding;
33068            this.charset = charset;
33069          }
33070          /**
33071           * @param  {string} s - The character
33072           * @return {number} The index.
33073           */
33074
33075
33076          CffEncoding.prototype.charToGlyphIndex = function (s) {
33077            var code = s.codePointAt(0);
33078            var charName = this.encoding[code];
33079            return this.charset.indexOf(charName);
33080          };
33081          /**
33082           * @exports opentype.GlyphNames
33083           * @class
33084           * @constructor
33085           * @param {Object} post
33086           */
33087
33088
33089          function GlyphNames(post) {
33090            var this$1 = this;
33091
33092            switch (post.version) {
33093              case 1:
33094                this.names = standardNames.slice();
33095                break;
33096
33097              case 2:
33098                this.names = new Array(post.numberOfGlyphs);
33099
33100                for (var i = 0; i < post.numberOfGlyphs; i++) {
33101                  if (post.glyphNameIndex[i] < standardNames.length) {
33102                    this$1.names[i] = standardNames[post.glyphNameIndex[i]];
33103                  } else {
33104                    this$1.names[i] = post.names[post.glyphNameIndex[i] - standardNames.length];
33105                  }
33106                }
33107
33108                break;
33109
33110              case 2.5:
33111                this.names = new Array(post.numberOfGlyphs);
33112
33113                for (var i$1 = 0; i$1 < post.numberOfGlyphs; i$1++) {
33114                  this$1.names[i$1] = standardNames[i$1 + post.glyphNameIndex[i$1]];
33115                }
33116
33117                break;
33118
33119              case 3:
33120                this.names = [];
33121                break;
33122
33123              default:
33124                this.names = [];
33125                break;
33126            }
33127          }
33128          /**
33129           * Gets the index of a glyph by name.
33130           * @param  {string} name - The glyph name
33131           * @return {number} The index
33132           */
33133
33134
33135          GlyphNames.prototype.nameToGlyphIndex = function (name) {
33136            return this.names.indexOf(name);
33137          };
33138          /**
33139           * @param  {number} gid
33140           * @return {string}
33141           */
33142
33143
33144          GlyphNames.prototype.glyphIndexToName = function (gid) {
33145            return this.names[gid];
33146          };
33147          /**
33148           * @alias opentype.addGlyphNames
33149           * @param {opentype.Font}
33150           */
33151
33152
33153          function addGlyphNames(font) {
33154            var glyph;
33155            var glyphIndexMap = font.tables.cmap.glyphIndexMap;
33156            var charCodes = Object.keys(glyphIndexMap);
33157
33158            for (var i = 0; i < charCodes.length; i += 1) {
33159              var c = charCodes[i];
33160              var glyphIndex = glyphIndexMap[c];
33161              glyph = font.glyphs.get(glyphIndex);
33162              glyph.addUnicode(parseInt(c));
33163            }
33164
33165            for (var i$1 = 0; i$1 < font.glyphs.length; i$1 += 1) {
33166              glyph = font.glyphs.get(i$1);
33167
33168              if (font.cffEncoding) {
33169                if (font.isCIDFont) {
33170                  glyph.name = 'gid' + i$1;
33171                } else {
33172                  glyph.name = font.cffEncoding.charset[i$1];
33173                }
33174              } else if (font.glyphNames.names) {
33175                glyph.name = font.glyphNames.glyphIndexToName(i$1);
33176              }
33177            }
33178          } // Drawing utility functions.
33179          // Draw a line on the given context from point `x1,y1` to point `x2,y2`.
33180
33181
33182          function line(ctx, x1, y1, x2, y2) {
33183            ctx.beginPath();
33184            ctx.moveTo(x1, y1);
33185            ctx.lineTo(x2, y2);
33186            ctx.stroke();
33187          }
33188
33189          var draw = {
33190            line: line
33191          }; // The Glyph object
33192          // import glyf from './tables/glyf' Can't be imported here, because it's a circular dependency
33193
33194          function getPathDefinition(glyph, path) {
33195            var _path = path || new Path();
33196
33197            return {
33198              configurable: true,
33199              get: function () {
33200                if (typeof _path === 'function') {
33201                  _path = _path();
33202                }
33203
33204                return _path;
33205              },
33206              set: function (p) {
33207                _path = p;
33208              }
33209            };
33210          }
33211          /**
33212           * @typedef GlyphOptions
33213           * @type Object
33214           * @property {string} [name] - The glyph name
33215           * @property {number} [unicode]
33216           * @property {Array} [unicodes]
33217           * @property {number} [xMin]
33218           * @property {number} [yMin]
33219           * @property {number} [xMax]
33220           * @property {number} [yMax]
33221           * @property {number} [advanceWidth]
33222           */
33223          // A Glyph is an individual mark that often corresponds to a character.
33224          // Some glyphs, such as ligatures, are a combination of many characters.
33225          // Glyphs are the basic building blocks of a font.
33226          //
33227          // The `Glyph` class contains utility methods for drawing the path and its points.
33228
33229          /**
33230           * @exports opentype.Glyph
33231           * @class
33232           * @param {GlyphOptions}
33233           * @constructor
33234           */
33235
33236
33237          function Glyph(options) {
33238            // By putting all the code on a prototype function (which is only declared once)
33239            // we reduce the memory requirements for larger fonts by some 2%
33240            this.bindConstructorValues(options);
33241          }
33242          /**
33243           * @param  {GlyphOptions}
33244           */
33245
33246
33247          Glyph.prototype.bindConstructorValues = function (options) {
33248            this.index = options.index || 0; // These three values cannot be deferred for memory optimization:
33249
33250            this.name = options.name || null;
33251            this.unicode = options.unicode || undefined;
33252            this.unicodes = options.unicodes || options.unicode !== undefined ? [options.unicode] : []; // But by binding these values only when necessary, we reduce can
33253            // the memory requirements by almost 3% for larger fonts.
33254
33255            if (options.xMin) {
33256              this.xMin = options.xMin;
33257            }
33258
33259            if (options.yMin) {
33260              this.yMin = options.yMin;
33261            }
33262
33263            if (options.xMax) {
33264              this.xMax = options.xMax;
33265            }
33266
33267            if (options.yMax) {
33268              this.yMax = options.yMax;
33269            }
33270
33271            if (options.advanceWidth) {
33272              this.advanceWidth = options.advanceWidth;
33273            } // The path for a glyph is the most memory intensive, and is bound as a value
33274            // with a getter/setter to ensure we actually do path parsing only once the
33275            // path is actually needed by anything.
33276
33277
33278            Object.defineProperty(this, 'path', getPathDefinition(this, options.path));
33279          };
33280          /**
33281           * @param {number}
33282           */
33283
33284
33285          Glyph.prototype.addUnicode = function (unicode) {
33286            if (this.unicodes.length === 0) {
33287              this.unicode = unicode;
33288            }
33289
33290            this.unicodes.push(unicode);
33291          };
33292          /**
33293           * Calculate the minimum bounding box for this glyph.
33294           * @return {opentype.BoundingBox}
33295           */
33296
33297
33298          Glyph.prototype.getBoundingBox = function () {
33299            return this.path.getBoundingBox();
33300          };
33301          /**
33302           * Convert the glyph to a Path we can draw on a drawing context.
33303           * @param  {number} [x=0] - Horizontal position of the beginning of the text.
33304           * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
33305           * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
33306           * @param  {Object=} options - xScale, yScale to stretch the glyph.
33307           * @param  {opentype.Font} if hinting is to be used, the font
33308           * @return {opentype.Path}
33309           */
33310
33311
33312          Glyph.prototype.getPath = function (x, y, fontSize, options, font) {
33313            x = x !== undefined ? x : 0;
33314            y = y !== undefined ? y : 0;
33315            fontSize = fontSize !== undefined ? fontSize : 72;
33316            var commands;
33317            var hPoints;
33318
33319            if (!options) {
33320              options = {};
33321            }
33322
33323            var xScale = options.xScale;
33324            var yScale = options.yScale;
33325
33326            if (options.hinting && font && font.hinting) {
33327              // in case of hinting, the hinting engine takes care
33328              // of scaling the points (not the path) before hinting.
33329              hPoints = this.path && font.hinting.exec(this, fontSize); // in case the hinting engine failed hPoints is undefined
33330              // and thus reverts to plain rending
33331            }
33332
33333            if (hPoints) {
33334              // Call font.hinting.getCommands instead of `glyf.getPath(hPoints).commands` to avoid a circular dependency
33335              commands = font.hinting.getCommands(hPoints);
33336              x = Math.round(x);
33337              y = Math.round(y); // TODO in case of hinting xyScaling is not yet supported
33338
33339              xScale = yScale = 1;
33340            } else {
33341              commands = this.path.commands;
33342              var scale = 1 / this.path.unitsPerEm * fontSize;
33343
33344              if (xScale === undefined) {
33345                xScale = scale;
33346              }
33347
33348              if (yScale === undefined) {
33349                yScale = scale;
33350              }
33351            }
33352
33353            var p = new Path();
33354
33355            for (var i = 0; i < commands.length; i += 1) {
33356              var cmd = commands[i];
33357
33358              if (cmd.type === 'M') {
33359                p.moveTo(x + cmd.x * xScale, y + -cmd.y * yScale);
33360              } else if (cmd.type === 'L') {
33361                p.lineTo(x + cmd.x * xScale, y + -cmd.y * yScale);
33362              } else if (cmd.type === 'Q') {
33363                p.quadraticCurveTo(x + cmd.x1 * xScale, y + -cmd.y1 * yScale, x + cmd.x * xScale, y + -cmd.y * yScale);
33364              } else if (cmd.type === 'C') {
33365                p.curveTo(x + cmd.x1 * xScale, y + -cmd.y1 * yScale, x + cmd.x2 * xScale, y + -cmd.y2 * yScale, x + cmd.x * xScale, y + -cmd.y * yScale);
33366              } else if (cmd.type === 'Z') {
33367                p.closePath();
33368              }
33369            }
33370
33371            return p;
33372          };
33373          /**
33374           * Split the glyph into contours.
33375           * This function is here for backwards compatibility, and to
33376           * provide raw access to the TrueType glyph outlines.
33377           * @return {Array}
33378           */
33379
33380
33381          Glyph.prototype.getContours = function () {
33382            var this$1 = this;
33383
33384            if (this.points === undefined) {
33385              return [];
33386            }
33387
33388            var contours = [];
33389            var currentContour = [];
33390
33391            for (var i = 0; i < this.points.length; i += 1) {
33392              var pt = this$1.points[i];
33393              currentContour.push(pt);
33394
33395              if (pt.lastPointOfContour) {
33396                contours.push(currentContour);
33397                currentContour = [];
33398              }
33399            }
33400
33401            check.argument(currentContour.length === 0, 'There are still points left in the current contour.');
33402            return contours;
33403          };
33404          /**
33405           * Calculate the xMin/yMin/xMax/yMax/lsb/rsb for a Glyph.
33406           * @return {Object}
33407           */
33408
33409
33410          Glyph.prototype.getMetrics = function () {
33411            var commands = this.path.commands;
33412            var xCoords = [];
33413            var yCoords = [];
33414
33415            for (var i = 0; i < commands.length; i += 1) {
33416              var cmd = commands[i];
33417
33418              if (cmd.type !== 'Z') {
33419                xCoords.push(cmd.x);
33420                yCoords.push(cmd.y);
33421              }
33422
33423              if (cmd.type === 'Q' || cmd.type === 'C') {
33424                xCoords.push(cmd.x1);
33425                yCoords.push(cmd.y1);
33426              }
33427
33428              if (cmd.type === 'C') {
33429                xCoords.push(cmd.x2);
33430                yCoords.push(cmd.y2);
33431              }
33432            }
33433
33434            var metrics = {
33435              xMin: Math.min.apply(null, xCoords),
33436              yMin: Math.min.apply(null, yCoords),
33437              xMax: Math.max.apply(null, xCoords),
33438              yMax: Math.max.apply(null, yCoords),
33439              leftSideBearing: this.leftSideBearing
33440            };
33441
33442            if (!isFinite(metrics.xMin)) {
33443              metrics.xMin = 0;
33444            }
33445
33446            if (!isFinite(metrics.xMax)) {
33447              metrics.xMax = this.advanceWidth;
33448            }
33449
33450            if (!isFinite(metrics.yMin)) {
33451              metrics.yMin = 0;
33452            }
33453
33454            if (!isFinite(metrics.yMax)) {
33455              metrics.yMax = 0;
33456            }
33457
33458            metrics.rightSideBearing = this.advanceWidth - metrics.leftSideBearing - (metrics.xMax - metrics.xMin);
33459            return metrics;
33460          };
33461          /**
33462           * Draw the glyph on the given context.
33463           * @param  {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
33464           * @param  {number} [x=0] - Horizontal position of the beginning of the text.
33465           * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
33466           * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
33467           * @param  {Object=} options - xScale, yScale to stretch the glyph.
33468           */
33469
33470
33471          Glyph.prototype.draw = function (ctx, x, y, fontSize, options) {
33472            this.getPath(x, y, fontSize, options).draw(ctx);
33473          };
33474          /**
33475           * Draw the points of the glyph.
33476           * On-curve points will be drawn in blue, off-curve points will be drawn in red.
33477           * @param  {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
33478           * @param  {number} [x=0] - Horizontal position of the beginning of the text.
33479           * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
33480           * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
33481           */
33482
33483
33484          Glyph.prototype.drawPoints = function (ctx, x, y, fontSize) {
33485            function drawCircles(l, x, y, scale) {
33486              var PI_SQ = Math.PI * 2;
33487              ctx.beginPath();
33488
33489              for (var j = 0; j < l.length; j += 1) {
33490                ctx.moveTo(x + l[j].x * scale, y + l[j].y * scale);
33491                ctx.arc(x + l[j].x * scale, y + l[j].y * scale, 2, 0, PI_SQ, false);
33492              }
33493
33494              ctx.closePath();
33495              ctx.fill();
33496            }
33497
33498            x = x !== undefined ? x : 0;
33499            y = y !== undefined ? y : 0;
33500            fontSize = fontSize !== undefined ? fontSize : 24;
33501            var scale = 1 / this.path.unitsPerEm * fontSize;
33502            var blueCircles = [];
33503            var redCircles = [];
33504            var path = this.path;
33505
33506            for (var i = 0; i < path.commands.length; i += 1) {
33507              var cmd = path.commands[i];
33508
33509              if (cmd.x !== undefined) {
33510                blueCircles.push({
33511                  x: cmd.x,
33512                  y: -cmd.y
33513                });
33514              }
33515
33516              if (cmd.x1 !== undefined) {
33517                redCircles.push({
33518                  x: cmd.x1,
33519                  y: -cmd.y1
33520                });
33521              }
33522
33523              if (cmd.x2 !== undefined) {
33524                redCircles.push({
33525                  x: cmd.x2,
33526                  y: -cmd.y2
33527                });
33528              }
33529            }
33530
33531            ctx.fillStyle = 'blue';
33532            drawCircles(blueCircles, x, y, scale);
33533            ctx.fillStyle = 'red';
33534            drawCircles(redCircles, x, y, scale);
33535          };
33536          /**
33537           * Draw lines indicating important font measurements.
33538           * Black lines indicate the origin of the coordinate system (point 0,0).
33539           * Blue lines indicate the glyph bounding box.
33540           * Green line indicates the advance width of the glyph.
33541           * @param  {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
33542           * @param  {number} [x=0] - Horizontal position of the beginning of the text.
33543           * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
33544           * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
33545           */
33546
33547
33548          Glyph.prototype.drawMetrics = function (ctx, x, y, fontSize) {
33549            var scale;
33550            x = x !== undefined ? x : 0;
33551            y = y !== undefined ? y : 0;
33552            fontSize = fontSize !== undefined ? fontSize : 24;
33553            scale = 1 / this.path.unitsPerEm * fontSize;
33554            ctx.lineWidth = 1; // Draw the origin
33555
33556            ctx.strokeStyle = 'black';
33557            draw.line(ctx, x, -10000, x, 10000);
33558            draw.line(ctx, -10000, y, 10000, y); // This code is here due to memory optimization: by not using
33559            // defaults in the constructor, we save a notable amount of memory.
33560
33561            var xMin = this.xMin || 0;
33562            var yMin = this.yMin || 0;
33563            var xMax = this.xMax || 0;
33564            var yMax = this.yMax || 0;
33565            var advanceWidth = this.advanceWidth || 0; // Draw the glyph box
33566
33567            ctx.strokeStyle = 'blue';
33568            draw.line(ctx, x + xMin * scale, -10000, x + xMin * scale, 10000);
33569            draw.line(ctx, x + xMax * scale, -10000, x + xMax * scale, 10000);
33570            draw.line(ctx, -10000, y + -yMin * scale, 10000, y + -yMin * scale);
33571            draw.line(ctx, -10000, y + -yMax * scale, 10000, y + -yMax * scale); // Draw the advance width
33572
33573            ctx.strokeStyle = 'green';
33574            draw.line(ctx, x + advanceWidth * scale, -10000, x + advanceWidth * scale, 10000);
33575          }; // The GlyphSet object
33576          // Define a property on the glyph that depends on the path being loaded.
33577
33578
33579          function defineDependentProperty(glyph, externalName, internalName) {
33580            Object.defineProperty(glyph, externalName, {
33581              get: function () {
33582                // Request the path property to make sure the path is loaded.
33583                glyph.path; // jshint ignore:line
33584
33585                return glyph[internalName];
33586              },
33587              set: function (newValue) {
33588                glyph[internalName] = newValue;
33589              },
33590              enumerable: true,
33591              configurable: true
33592            });
33593          }
33594          /**
33595           * A GlyphSet represents all glyphs available in the font, but modelled using
33596           * a deferred glyph loader, for retrieving glyphs only once they are absolutely
33597           * necessary, to keep the memory footprint down.
33598           * @exports opentype.GlyphSet
33599           * @class
33600           * @param {opentype.Font}
33601           * @param {Array}
33602           */
33603
33604
33605          function GlyphSet(font, glyphs) {
33606            var this$1 = this;
33607            this.font = font;
33608            this.glyphs = {};
33609
33610            if (Array.isArray(glyphs)) {
33611              for (var i = 0; i < glyphs.length; i++) {
33612                this$1.glyphs[i] = glyphs[i];
33613              }
33614            }
33615
33616            this.length = glyphs && glyphs.length || 0;
33617          }
33618          /**
33619           * @param  {number} index
33620           * @return {opentype.Glyph}
33621           */
33622
33623
33624          GlyphSet.prototype.get = function (index) {
33625            if (typeof this.glyphs[index] === 'function') {
33626              this.glyphs[index] = this.glyphs[index]();
33627            }
33628
33629            return this.glyphs[index];
33630          };
33631          /**
33632           * @param  {number} index
33633           * @param  {Object}
33634           */
33635
33636
33637          GlyphSet.prototype.push = function (index, loader) {
33638            this.glyphs[index] = loader;
33639            this.length++;
33640          };
33641          /**
33642           * @alias opentype.glyphLoader
33643           * @param  {opentype.Font} font
33644           * @param  {number} index
33645           * @return {opentype.Glyph}
33646           */
33647
33648
33649          function glyphLoader(font, index) {
33650            return new Glyph({
33651              index: index,
33652              font: font
33653            });
33654          }
33655          /**
33656           * Generate a stub glyph that can be filled with all metadata *except*
33657           * the "points" and "path" properties, which must be loaded only once
33658           * the glyph's path is actually requested for text shaping.
33659           * @alias opentype.ttfGlyphLoader
33660           * @param  {opentype.Font} font
33661           * @param  {number} index
33662           * @param  {Function} parseGlyph
33663           * @param  {Object} data
33664           * @param  {number} position
33665           * @param  {Function} buildPath
33666           * @return {opentype.Glyph}
33667           */
33668
33669
33670          function ttfGlyphLoader(font, index, parseGlyph, data, position, buildPath) {
33671            return function () {
33672              var glyph = new Glyph({
33673                index: index,
33674                font: font
33675              });
33676
33677              glyph.path = function () {
33678                parseGlyph(glyph, data, position);
33679                var path = buildPath(font.glyphs, glyph);
33680                path.unitsPerEm = font.unitsPerEm;
33681                return path;
33682              };
33683
33684              defineDependentProperty(glyph, 'xMin', '_xMin');
33685              defineDependentProperty(glyph, 'xMax', '_xMax');
33686              defineDependentProperty(glyph, 'yMin', '_yMin');
33687              defineDependentProperty(glyph, 'yMax', '_yMax');
33688              return glyph;
33689            };
33690          }
33691          /**
33692           * @alias opentype.cffGlyphLoader
33693           * @param  {opentype.Font} font
33694           * @param  {number} index
33695           * @param  {Function} parseCFFCharstring
33696           * @param  {string} charstring
33697           * @return {opentype.Glyph}
33698           */
33699
33700
33701          function cffGlyphLoader(font, index, parseCFFCharstring, charstring) {
33702            return function () {
33703              var glyph = new Glyph({
33704                index: index,
33705                font: font
33706              });
33707
33708              glyph.path = function () {
33709                var path = parseCFFCharstring(font, glyph, charstring);
33710                path.unitsPerEm = font.unitsPerEm;
33711                return path;
33712              };
33713
33714              return glyph;
33715            };
33716          }
33717
33718          var glyphset = {
33719            GlyphSet: GlyphSet,
33720            glyphLoader: glyphLoader,
33721            ttfGlyphLoader: ttfGlyphLoader,
33722            cffGlyphLoader: cffGlyphLoader
33723          }; // The `CFF` table contains the glyph outlines in PostScript format.
33724          // Custom equals function that can also check lists.
33725
33726          function equals(a, b) {
33727            if (a === b) {
33728              return true;
33729            } else if (Array.isArray(a) && Array.isArray(b)) {
33730              if (a.length !== b.length) {
33731                return false;
33732              }
33733
33734              for (var i = 0; i < a.length; i += 1) {
33735                if (!equals(a[i], b[i])) {
33736                  return false;
33737                }
33738              }
33739
33740              return true;
33741            } else {
33742              return false;
33743            }
33744          } // Subroutines are encoded using the negative half of the number space.
33745          // See type 2 chapter 4.7 "Subroutine operators".
33746
33747
33748          function calcCFFSubroutineBias(subrs) {
33749            var bias;
33750
33751            if (subrs.length < 1240) {
33752              bias = 107;
33753            } else if (subrs.length < 33900) {
33754              bias = 1131;
33755            } else {
33756              bias = 32768;
33757            }
33758
33759            return bias;
33760          } // Parse a `CFF` INDEX array.
33761          // An index array consists of a list of offsets, then a list of objects at those offsets.
33762
33763
33764          function parseCFFIndex(data, start, conversionFn) {
33765            var offsets = [];
33766            var objects = [];
33767            var count = parse.getCard16(data, start);
33768            var objectOffset;
33769            var endOffset;
33770
33771            if (count !== 0) {
33772              var offsetSize = parse.getByte(data, start + 2);
33773              objectOffset = start + (count + 1) * offsetSize + 2;
33774              var pos = start + 3;
33775
33776              for (var i = 0; i < count + 1; i += 1) {
33777                offsets.push(parse.getOffset(data, pos, offsetSize));
33778                pos += offsetSize;
33779              } // The total size of the index array is 4 header bytes + the value of the last offset.
33780
33781
33782              endOffset = objectOffset + offsets[count];
33783            } else {
33784              endOffset = start + 2;
33785            }
33786
33787            for (var i$1 = 0; i$1 < offsets.length - 1; i$1 += 1) {
33788              var value = parse.getBytes(data, objectOffset + offsets[i$1], objectOffset + offsets[i$1 + 1]);
33789
33790              if (conversionFn) {
33791                value = conversionFn(value);
33792              }
33793
33794              objects.push(value);
33795            }
33796
33797            return {
33798              objects: objects,
33799              startOffset: start,
33800              endOffset: endOffset
33801            };
33802          } // Parse a `CFF` DICT real value.
33803
33804
33805          function parseFloatOperand(parser) {
33806            var s = '';
33807            var eof = 15;
33808            var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'E', 'E-', null, '-'];
33809
33810            while (true) {
33811              var b = parser.parseByte();
33812              var n1 = b >> 4;
33813              var n2 = b & 15;
33814
33815              if (n1 === eof) {
33816                break;
33817              }
33818
33819              s += lookup[n1];
33820
33821              if (n2 === eof) {
33822                break;
33823              }
33824
33825              s += lookup[n2];
33826            }
33827
33828            return parseFloat(s);
33829          } // Parse a `CFF` DICT operand.
33830
33831
33832          function parseOperand(parser, b0) {
33833            var b1;
33834            var b2;
33835            var b3;
33836            var b4;
33837
33838            if (b0 === 28) {
33839              b1 = parser.parseByte();
33840              b2 = parser.parseByte();
33841              return b1 << 8 | b2;
33842            }
33843
33844            if (b0 === 29) {
33845              b1 = parser.parseByte();
33846              b2 = parser.parseByte();
33847              b3 = parser.parseByte();
33848              b4 = parser.parseByte();
33849              return b1 << 24 | b2 << 16 | b3 << 8 | b4;
33850            }
33851
33852            if (b0 === 30) {
33853              return parseFloatOperand(parser);
33854            }
33855
33856            if (b0 >= 32 && b0 <= 246) {
33857              return b0 - 139;
33858            }
33859
33860            if (b0 >= 247 && b0 <= 250) {
33861              b1 = parser.parseByte();
33862              return (b0 - 247) * 256 + b1 + 108;
33863            }
33864
33865            if (b0 >= 251 && b0 <= 254) {
33866              b1 = parser.parseByte();
33867              return -(b0 - 251) * 256 - b1 - 108;
33868            }
33869
33870            throw new Error('Invalid b0 ' + b0);
33871          } // Convert the entries returned by `parseDict` to a proper dictionary.
33872          // If a value is a list of one, it is unpacked.
33873
33874
33875          function entriesToObject(entries) {
33876            var o = {};
33877
33878            for (var i = 0; i < entries.length; i += 1) {
33879              var key = entries[i][0];
33880              var values = entries[i][1];
33881              var value = void 0;
33882
33883              if (values.length === 1) {
33884                value = values[0];
33885              } else {
33886                value = values;
33887              }
33888
33889              if (o.hasOwnProperty(key) && !isNaN(o[key])) {
33890                throw new Error('Object ' + o + ' already has key ' + key);
33891              }
33892
33893              o[key] = value;
33894            }
33895
33896            return o;
33897          } // Parse a `CFF` DICT object.
33898          // A dictionary contains key-value pairs in a compact tokenized format.
33899
33900
33901          function parseCFFDict(data, start, size) {
33902            start = start !== undefined ? start : 0;
33903            var parser = new parse.Parser(data, start);
33904            var entries = [];
33905            var operands = [];
33906            size = size !== undefined ? size : data.length;
33907
33908            while (parser.relativeOffset < size) {
33909              var op = parser.parseByte(); // The first byte for each dict item distinguishes between operator (key) and operand (value).
33910              // Values <= 21 are operators.
33911
33912              if (op <= 21) {
33913                // Two-byte operators have an initial escape byte of 12.
33914                if (op === 12) {
33915                  op = 1200 + parser.parseByte();
33916                }
33917
33918                entries.push([op, operands]);
33919                operands = [];
33920              } else {
33921                // Since the operands (values) come before the operators (keys), we store all operands in a list
33922                // until we encounter an operator.
33923                operands.push(parseOperand(parser, op));
33924              }
33925            }
33926
33927            return entriesToObject(entries);
33928          } // Given a String Index (SID), return the value of the string.
33929          // Strings below index 392 are standard CFF strings and are not encoded in the font.
33930
33931
33932          function getCFFString(strings, index) {
33933            if (index <= 390) {
33934              index = cffStandardStrings[index];
33935            } else {
33936              index = strings[index - 391];
33937            }
33938
33939            return index;
33940          } // Interpret a dictionary and return a new dictionary with readable keys and values for missing entries.
33941          // This function takes `meta` which is a list of objects containing `operand`, `name` and `default`.
33942
33943
33944          function interpretDict(dict, meta, strings) {
33945            var newDict = {};
33946            var value; // Because we also want to include missing values, we start out from the meta list
33947            // and lookup values in the dict.
33948
33949            for (var i = 0; i < meta.length; i += 1) {
33950              var m = meta[i];
33951
33952              if (Array.isArray(m.type)) {
33953                var values = [];
33954                values.length = m.type.length;
33955
33956                for (var j = 0; j < m.type.length; j++) {
33957                  value = dict[m.op] !== undefined ? dict[m.op][j] : undefined;
33958
33959                  if (value === undefined) {
33960                    value = m.value !== undefined && m.value[j] !== undefined ? m.value[j] : null;
33961                  }
33962
33963                  if (m.type[j] === 'SID') {
33964                    value = getCFFString(strings, value);
33965                  }
33966
33967                  values[j] = value;
33968                }
33969
33970                newDict[m.name] = values;
33971              } else {
33972                value = dict[m.op];
33973
33974                if (value === undefined) {
33975                  value = m.value !== undefined ? m.value : null;
33976                }
33977
33978                if (m.type === 'SID') {
33979                  value = getCFFString(strings, value);
33980                }
33981
33982                newDict[m.name] = value;
33983              }
33984            }
33985
33986            return newDict;
33987          } // Parse the CFF header.
33988
33989
33990          function parseCFFHeader(data, start) {
33991            var header = {};
33992            header.formatMajor = parse.getCard8(data, start);
33993            header.formatMinor = parse.getCard8(data, start + 1);
33994            header.size = parse.getCard8(data, start + 2);
33995            header.offsetSize = parse.getCard8(data, start + 3);
33996            header.startOffset = start;
33997            header.endOffset = start + 4;
33998            return header;
33999          }
34000
34001          var TOP_DICT_META = [{
34002            name: 'version',
34003            op: 0,
34004            type: 'SID'
34005          }, {
34006            name: 'notice',
34007            op: 1,
34008            type: 'SID'
34009          }, {
34010            name: 'copyright',
34011            op: 1200,
34012            type: 'SID'
34013          }, {
34014            name: 'fullName',
34015            op: 2,
34016            type: 'SID'
34017          }, {
34018            name: 'familyName',
34019            op: 3,
34020            type: 'SID'
34021          }, {
34022            name: 'weight',
34023            op: 4,
34024            type: 'SID'
34025          }, {
34026            name: 'isFixedPitch',
34027            op: 1201,
34028            type: 'number',
34029            value: 0
34030          }, {
34031            name: 'italicAngle',
34032            op: 1202,
34033            type: 'number',
34034            value: 0
34035          }, {
34036            name: 'underlinePosition',
34037            op: 1203,
34038            type: 'number',
34039            value: -100
34040          }, {
34041            name: 'underlineThickness',
34042            op: 1204,
34043            type: 'number',
34044            value: 50
34045          }, {
34046            name: 'paintType',
34047            op: 1205,
34048            type: 'number',
34049            value: 0
34050          }, {
34051            name: 'charstringType',
34052            op: 1206,
34053            type: 'number',
34054            value: 2
34055          }, {
34056            name: 'fontMatrix',
34057            op: 1207,
34058            type: ['real', 'real', 'real', 'real', 'real', 'real'],
34059            value: [0.001, 0, 0, 0.001, 0, 0]
34060          }, {
34061            name: 'uniqueId',
34062            op: 13,
34063            type: 'number'
34064          }, {
34065            name: 'fontBBox',
34066            op: 5,
34067            type: ['number', 'number', 'number', 'number'],
34068            value: [0, 0, 0, 0]
34069          }, {
34070            name: 'strokeWidth',
34071            op: 1208,
34072            type: 'number',
34073            value: 0
34074          }, {
34075            name: 'xuid',
34076            op: 14,
34077            type: [],
34078            value: null
34079          }, {
34080            name: 'charset',
34081            op: 15,
34082            type: 'offset',
34083            value: 0
34084          }, {
34085            name: 'encoding',
34086            op: 16,
34087            type: 'offset',
34088            value: 0
34089          }, {
34090            name: 'charStrings',
34091            op: 17,
34092            type: 'offset',
34093            value: 0
34094          }, {
34095            name: 'private',
34096            op: 18,
34097            type: ['number', 'offset'],
34098            value: [0, 0]
34099          }, {
34100            name: 'ros',
34101            op: 1230,
34102            type: ['SID', 'SID', 'number']
34103          }, {
34104            name: 'cidFontVersion',
34105            op: 1231,
34106            type: 'number',
34107            value: 0
34108          }, {
34109            name: 'cidFontRevision',
34110            op: 1232,
34111            type: 'number',
34112            value: 0
34113          }, {
34114            name: 'cidFontType',
34115            op: 1233,
34116            type: 'number',
34117            value: 0
34118          }, {
34119            name: 'cidCount',
34120            op: 1234,
34121            type: 'number',
34122            value: 8720
34123          }, {
34124            name: 'uidBase',
34125            op: 1235,
34126            type: 'number'
34127          }, {
34128            name: 'fdArray',
34129            op: 1236,
34130            type: 'offset'
34131          }, {
34132            name: 'fdSelect',
34133            op: 1237,
34134            type: 'offset'
34135          }, {
34136            name: 'fontName',
34137            op: 1238,
34138            type: 'SID'
34139          }];
34140          var PRIVATE_DICT_META = [{
34141            name: 'subrs',
34142            op: 19,
34143            type: 'offset',
34144            value: 0
34145          }, {
34146            name: 'defaultWidthX',
34147            op: 20,
34148            type: 'number',
34149            value: 0
34150          }, {
34151            name: 'nominalWidthX',
34152            op: 21,
34153            type: 'number',
34154            value: 0
34155          }]; // Parse the CFF top dictionary. A CFF table can contain multiple fonts, each with their own top dictionary.
34156          // The top dictionary contains the essential metadata for the font, together with the private dictionary.
34157
34158          function parseCFFTopDict(data, strings) {
34159            var dict = parseCFFDict(data, 0, data.byteLength);
34160            return interpretDict(dict, TOP_DICT_META, strings);
34161          } // Parse the CFF private dictionary. We don't fully parse out all the values, only the ones we need.
34162
34163
34164          function parseCFFPrivateDict(data, start, size, strings) {
34165            var dict = parseCFFDict(data, start, size);
34166            return interpretDict(dict, PRIVATE_DICT_META, strings);
34167          } // Returns a list of "Top DICT"s found using an INDEX list.
34168          // Used to read both the usual high-level Top DICTs and also the FDArray
34169          // discovered inside CID-keyed fonts.  When a Top DICT has a reference to
34170          // a Private DICT that is read and saved into the Top DICT.
34171          //
34172          // In addition to the expected/optional values as outlined in TOP_DICT_META
34173          // the following values might be saved into the Top DICT.
34174          //
vendor: 24,377 bytes, lines 34175-34898
34175          //    _subrs []        array of local CFF subroutines from Private DICT
34176          //    _subrsBias       bias value computed from number of subroutines
34177          //                      (see calcCFFSubroutineBias() and parseCFFCharstring())
34178          //    _defaultWidthX   default widths for CFF characters
34179          //    _nominalWidthX   bias added to width embedded within glyph description
34180          //
34181          //    _privateDict     saved copy of parsed Private DICT from Top DICT
34182
34183
34184          function gatherCFFTopDicts(data, start, cffIndex, strings) {
34185            var topDictArray = [];
34186
34187            for (var iTopDict = 0; iTopDict < cffIndex.length; iTopDict += 1) {
34188              var topDictData = new DataView(new Uint8Array(cffIndex[iTopDict]).buffer);
34189              var topDict = parseCFFTopDict(topDictData, strings);
34190              topDict._subrs = [];
34191              topDict._subrsBias = 0;
34192              var privateSize = topDict.private[0];
34193              var privateOffset = topDict.private[1];
34194
34195              if (privateSize !== 0 && privateOffset !== 0) {
34196                var privateDict = parseCFFPrivateDict(data, privateOffset + start, privateSize, strings);
34197                topDict._defaultWidthX = privateDict.defaultWidthX;
34198                topDict._nominalWidthX = privateDict.nominalWidthX;
34199
34200                if (privateDict.subrs !== 0) {
34201                  var subrOffset = privateOffset + privateDict.subrs;
34202                  var subrIndex = parseCFFIndex(data, subrOffset + start);
34203                  topDict._subrs = subrIndex.objects;
34204                  topDict._subrsBias = calcCFFSubroutineBias(topDict._subrs);
34205                }
34206
34207                topDict._privateDict = privateDict;
34208              }
34209
34210              topDictArray.push(topDict);
34211            }
34212
34213            return topDictArray;
34214          } // Parse the CFF charset table, which contains internal names for all the glyphs.
34215          // This function will return a list of glyph names.
34216          // See Adobe TN #5176 chapter 13, "Charsets".
34217
34218
34219          function parseCFFCharset(data, start, nGlyphs, strings) {
34220            var sid;
34221            var count;
34222            var parser = new parse.Parser(data, start); // The .notdef glyph is not included, so subtract 1.
34223
34224            nGlyphs -= 1;
34225            var charset = ['.notdef'];
34226            var format = parser.parseCard8();
34227
34228            if (format === 0) {
34229              for (var i = 0; i < nGlyphs; i += 1) {
34230                sid = parser.parseSID();
34231                charset.push(getCFFString(strings, sid));
34232              }
34233            } else if (format === 1) {
34234              while (charset.length <= nGlyphs) {
34235                sid = parser.parseSID();
34236                count = parser.parseCard8();
34237
34238                for (var i$1 = 0; i$1 <= count; i$1 += 1) {
34239                  charset.push(getCFFString(strings, sid));
34240                  sid += 1;
34241                }
34242              }
34243            } else if (format === 2) {
34244              while (charset.length <= nGlyphs) {
34245                sid = parser.parseSID();
34246                count = parser.parseCard16();
34247
34248                for (var i$2 = 0; i$2 <= count; i$2 += 1) {
34249                  charset.push(getCFFString(strings, sid));
34250                  sid += 1;
34251                }
34252              }
34253            } else {
34254              throw new Error('Unknown charset format ' + format);
34255            }
34256
34257            return charset;
34258          } // Parse the CFF encoding data. Only one encoding can be specified per font.
34259          // See Adobe TN #5176 chapter 12, "Encodings".
34260
34261
34262          function parseCFFEncoding(data, start, charset) {
34263            var code;
34264            var enc = {};
34265            var parser = new parse.Parser(data, start);
34266            var format = parser.parseCard8();
34267
34268            if (format === 0) {
34269              var nCodes = parser.parseCard8();
34270
34271              for (var i = 0; i < nCodes; i += 1) {
34272                code = parser.parseCard8();
34273                enc[code] = i;
34274              }
34275            } else if (format === 1) {
34276              var nRanges = parser.parseCard8();
34277              code = 1;
34278
34279              for (var i$1 = 0; i$1 < nRanges; i$1 += 1) {
34280                var first = parser.parseCard8();
34281                var nLeft = parser.parseCard8();
34282
34283                for (var j = first; j <= first + nLeft; j += 1) {
34284                  enc[j] = code;
34285                  code += 1;
34286                }
34287              }
34288            } else {
34289              throw new Error('Unknown encoding format ' + format);
34290            }
34291
34292            return new CffEncoding(enc, charset);
34293          } // Take in charstring code and return a Glyph object.
34294          // The encoding is described in the Type 2 Charstring Format
34295          // https://www.microsoft.com/typography/OTSPEC/charstr2.htm
34296
34297
34298          function parseCFFCharstring(font, glyph, code) {
34299            var c1x;
34300            var c1y;
34301            var c2x;
34302            var c2y;
34303            var p = new Path();
34304            var stack = [];
34305            var nStems = 0;
34306            var haveWidth = false;
34307            var open = false;
34308            var x = 0;
34309            var y = 0;
34310            var subrs;
34311            var subrsBias;
34312            var defaultWidthX;
34313            var nominalWidthX;
34314
34315            if (font.isCIDFont) {
34316              var fdIndex = font.tables.cff.topDict._fdSelect[glyph.index];
34317              var fdDict = font.tables.cff.topDict._fdArray[fdIndex];
34318              subrs = fdDict._subrs;
34319              subrsBias = fdDict._subrsBias;
34320              defaultWidthX = fdDict._defaultWidthX;
34321              nominalWidthX = fdDict._nominalWidthX;
34322            } else {
34323              subrs = font.tables.cff.topDict._subrs;
34324              subrsBias = font.tables.cff.topDict._subrsBias;
34325              defaultWidthX = font.tables.cff.topDict._defaultWidthX;
34326              nominalWidthX = font.tables.cff.topDict._nominalWidthX;
34327            }
34328
34329            var width = defaultWidthX;
34330
34331            function newContour(x, y) {
34332              if (open) {
34333                p.closePath();
34334              }
34335
34336              p.moveTo(x, y);
34337              open = true;
34338            }
34339
34340            function parseStems() {
34341              var hasWidthArg; // The number of stem operators on the stack is always even.
34342              // If the value is uneven, that means a width is specified.
34343
34344              hasWidthArg = stack.length % 2 !== 0;
34345
34346              if (hasWidthArg && !haveWidth) {
34347                width = stack.shift() + nominalWidthX;
34348              }
34349
34350              nStems += stack.length >> 1;
34351              stack.length = 0;
34352              haveWidth = true;
34353            }
34354
34355            function parse$$1(code) {
34356              var b1;
34357              var b2;
34358              var b3;
34359              var b4;
34360              var codeIndex;
34361              var subrCode;
34362              var jpx;
34363              var jpy;
34364              var c3x;
34365              var c3y;
34366              var c4x;
34367              var c4y;
34368              var i = 0;
34369
34370              while (i < code.length) {
34371                var v = code[i];
34372                i += 1;
34373
34374                switch (v) {
34375                  case 1:
34376                    // hstem
34377                    parseStems();
34378                    break;
34379
34380                  case 3:
34381                    // vstem
34382                    parseStems();
34383                    break;
34384
34385                  case 4:
34386                    // vmoveto
34387                    if (stack.length > 1 && !haveWidth) {
34388                      width = stack.shift() + nominalWidthX;
34389                      haveWidth = true;
34390                    }
34391
34392                    y += stack.pop();
34393                    newContour(x, y);
34394                    break;
34395
34396                  case 5:
34397                    // rlineto
34398                    while (stack.length > 0) {
34399                      x += stack.shift();
34400                      y += stack.shift();
34401                      p.lineTo(x, y);
34402                    }
34403
34404                    break;
34405
34406                  case 6:
34407                    // hlineto
34408                    while (stack.length > 0) {
34409                      x += stack.shift();
34410                      p.lineTo(x, y);
34411
34412                      if (stack.length === 0) {
34413                        break;
34414                      }
34415
34416                      y += stack.shift();
34417                      p.lineTo(x, y);
34418                    }
34419
34420                    break;
34421
34422                  case 7:
34423                    // vlineto
34424                    while (stack.length > 0) {
34425                      y += stack.shift();
34426                      p.lineTo(x, y);
34427
34428                      if (stack.length === 0) {
34429                        break;
34430                      }
34431
34432                      x += stack.shift();
34433                      p.lineTo(x, y);
34434                    }
34435
34436                    break;
34437
34438                  case 8:
34439                    // rrcurveto
34440                    while (stack.length > 0) {
34441                      c1x = x + stack.shift();
34442                      c1y = y + stack.shift();
34443                      c2x = c1x + stack.shift();
34444                      c2y = c1y + stack.shift();
34445                      x = c2x + stack.shift();
34446                      y = c2y + stack.shift();
34447                      p.curveTo(c1x, c1y, c2x, c2y, x, y);
34448                    }
34449
34450                    break;
34451
34452                  case 10:
34453                    // callsubr
34454                    codeIndex = stack.pop() + subrsBias;
34455                    subrCode = subrs[codeIndex];
34456
34457                    if (subrCode) {
34458                      parse$$1(subrCode);
34459                    }
34460
34461                    break;
34462
34463                  case 11:
34464                    // return
34465                    return;
34466
34467                  case 12:
34468                    // flex operators
34469                    v = code[i];
34470                    i += 1;
34471
34472                    switch (v) {
34473                      case 35:
34474                        // flex
34475                        // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd flex (12 35) |-
34476                        c1x = x + stack.shift(); // dx1
34477
34478                        c1y = y + stack.shift(); // dy1
34479
34480                        c2x = c1x + stack.shift(); // dx2
34481
34482                        c2y = c1y + stack.shift(); // dy2
34483
34484                        jpx = c2x + stack.shift(); // dx3
34485
34486                        jpy = c2y + stack.shift(); // dy3
34487
34488                        c3x = jpx + stack.shift(); // dx4
34489
34490                        c3y = jpy + stack.shift(); // dy4
34491
34492                        c4x = c3x + stack.shift(); // dx5
34493
34494                        c4y = c3y + stack.shift(); // dy5
34495
34496                        x = c4x + stack.shift(); // dx6
34497
34498                        y = c4y + stack.shift(); // dy6
34499
34500                        stack.shift(); // flex depth
34501
34502                        p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
34503                        p.curveTo(c3x, c3y, c4x, c4y, x, y);
34504                        break;
34505
34506                      case 34:
34507                        // hflex
34508                        // |- dx1 dx2 dy2 dx3 dx4 dx5 dx6 hflex (12 34) |-
34509                        c1x = x + stack.shift(); // dx1
34510
34511                        c1y = y; // dy1
34512
34513                        c2x = c1x + stack.shift(); // dx2
34514
34515                        c2y = c1y + stack.shift(); // dy2
34516
34517                        jpx = c2x + stack.shift(); // dx3
34518
34519                        jpy = c2y; // dy3
34520
34521                        c3x = jpx + stack.shift(); // dx4
34522
34523                        c3y = c2y; // dy4
34524
34525                        c4x = c3x + stack.shift(); // dx5
34526
34527                        c4y = y; // dy5
34528
34529                        x = c4x + stack.shift(); // dx6
34530
34531                        p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
34532                        p.curveTo(c3x, c3y, c4x, c4y, x, y);
34533                        break;
34534
34535                      case 36:
34536                        // hflex1
34537                        // |- dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6 hflex1 (12 36) |-
34538                        c1x = x + stack.shift(); // dx1
34539
34540                        c1y = y + stack.shift(); // dy1
34541
34542                        c2x = c1x + stack.shift(); // dx2
34543
34544                        c2y = c1y + stack.shift(); // dy2
34545
34546                        jpx = c2x + stack.shift(); // dx3
34547
34548                        jpy = c2y; // dy3
34549
34550                        c3x = jpx + stack.shift(); // dx4
34551
34552                        c3y = c2y; // dy4
34553
34554                        c4x = c3x + stack.shift(); // dx5
34555
34556                        c4y = c3y + stack.shift(); // dy5
34557
34558                        x = c4x + stack.shift(); // dx6
34559
34560                        p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
34561                        p.curveTo(c3x, c3y, c4x, c4y, x, y);
34562                        break;
34563
34564                      case 37:
34565                        // flex1
34566                        // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 d6 flex1 (12 37) |-
34567                        c1x = x + stack.shift(); // dx1
34568
34569                        c1y = y + stack.shift(); // dy1
34570
34571                        c2x = c1x + stack.shift(); // dx2
34572
34573                        c2y = c1y + stack.shift(); // dy2
34574
34575                        jpx = c2x + stack.shift(); // dx3
34576
34577                        jpy = c2y + stack.shift(); // dy3
34578
34579                        c3x = jpx + stack.shift(); // dx4
34580
34581                        c3y = jpy + stack.shift(); // dy4
34582
34583                        c4x = c3x + stack.shift(); // dx5
34584
34585                        c4y = c3y + stack.shift(); // dy5
34586
34587                        if (Math.abs(c4x - x) > Math.abs(c4y - y)) {
34588                          x = c4x + stack.shift();
34589                        } else {
34590                          y = c4y + stack.shift();
34591                        }
34592
34593                        p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
34594                        p.curveTo(c3x, c3y, c4x, c4y, x, y);
34595                        break;
34596
34597                      default:
34598                        console.log('Glyph ' + glyph.index + ': unknown operator ' + 1200 + v);
34599                        stack.length = 0;
34600                    }
34601
34602                    break;
34603
34604                  case 14:
34605                    // endchar
34606                    if (stack.length > 0 && !haveWidth) {
34607                      width = stack.shift() + nominalWidthX;
34608                      haveWidth = true;
34609                    }
34610
34611                    if (open) {
34612                      p.closePath();
34613                      open = false;
34614                    }
34615
34616                    break;
34617
34618                  case 18:
34619                    // hstemhm
34620                    parseStems();
34621                    break;
34622
34623                  case 19: // hintmask
34624
34625                  case 20:
34626                    // cntrmask
34627                    parseStems();
34628                    i += nStems + 7 >> 3;
34629                    break;
34630
34631                  case 21:
34632                    // rmoveto
34633                    if (stack.length > 2 && !haveWidth) {
34634                      width = stack.shift() + nominalWidthX;
34635                      haveWidth = true;
34636                    }
34637
34638                    y += stack.pop();
34639                    x += stack.pop();
34640                    newContour(x, y);
34641                    break;
34642
34643                  case 22:
34644                    // hmoveto
34645                    if (stack.length > 1 && !haveWidth) {
34646                      width = stack.shift() + nominalWidthX;
34647                      haveWidth = true;
34648                    }
34649
34650                    x += stack.pop();
34651                    newContour(x, y);
34652                    break;
34653
34654                  case 23:
34655                    // vstemhm
34656                    parseStems();
34657                    break;
34658
34659                  case 24:
34660                    // rcurveline
34661                    while (stack.length > 2) {
34662                      c1x = x + stack.shift();
34663                      c1y = y + stack.shift();
34664                      c2x = c1x + stack.shift();
34665                      c2y = c1y + stack.shift();
34666                      x = c2x + stack.shift();
34667                      y = c2y + stack.shift();
34668                      p.curveTo(c1x, c1y, c2x, c2y, x, y);
34669                    }
34670
34671                    x += stack.shift();
34672                    y += stack.shift();
34673                    p.lineTo(x, y);
34674                    break;
34675
34676                  case 25:
34677                    // rlinecurve
34678                    while (stack.length > 6) {
34679                      x += stack.shift();
34680                      y += stack.shift();
34681                      p.lineTo(x, y);
34682                    }
34683
34684                    c1x = x + stack.shift();
34685                    c1y = y + stack.shift();
34686                    c2x = c1x + stack.shift();
34687                    c2y = c1y + stack.shift();
34688                    x = c2x + stack.shift();
34689                    y = c2y + stack.shift();
34690                    p.curveTo(c1x, c1y, c2x, c2y, x, y);
34691                    break;
34692
34693                  case 26:
34694                    // vvcurveto
34695                    if (stack.length % 2) {
34696                      x += stack.shift();
34697                    }
34698
34699                    while (stack.length > 0) {
34700                      c1x = x;
34701                      c1y = y + stack.shift();
34702                      c2x = c1x + stack.shift();
34703                      c2y = c1y + stack.shift();
34704                      x = c2x;
34705                      y = c2y + stack.shift();
34706                      p.curveTo(c1x, c1y, c2x, c2y, x, y);
34707                    }
34708
34709                    break;
34710
34711                  case 27:
34712                    // hhcurveto
34713                    if (stack.length % 2) {
34714                      y += stack.shift();
34715                    }
34716
34717                    while (stack.length > 0) {
34718                      c1x = x + stack.shift();
34719                      c1y = y;
34720                      c2x = c1x + stack.shift();
34721                      c2y = c1y + stack.shift();
34722                      x = c2x + stack.shift();
34723                      y = c2y;
34724                      p.curveTo(c1x, c1y, c2x, c2y, x, y);
34725                    }
34726
34727                    break;
34728
34729                  case 28:
34730                    // shortint
34731                    b1 = code[i];
34732                    b2 = code[i + 1];
34733                    stack.push((b1 << 24 | b2 << 16) >> 16);
34734                    i += 2;
34735                    break;
34736
34737                  case 29:
34738                    // callgsubr
34739                    codeIndex = stack.pop() + font.gsubrsBias;
34740                    subrCode = font.gsubrs[codeIndex];
34741
34742                    if (subrCode) {
34743                      parse$$1(subrCode);
34744                    }
34745
34746                    break;
34747
34748                  case 30:
34749                    // vhcurveto
34750                    while (stack.length > 0) {
34751                      c1x = x;
34752                      c1y = y + stack.shift();
34753                      c2x = c1x + stack.shift();
34754                      c2y = c1y + stack.shift();
34755                      x = c2x + stack.shift();
34756                      y = c2y + (stack.length === 1 ? stack.shift() : 0);
34757                      p.curveTo(c1x, c1y, c2x, c2y, x, y);
34758
34759                      if (stack.length === 0) {
34760                        break;
34761                      }
34762
34763                      c1x = x + stack.shift();
34764                      c1y = y;
34765                      c2x = c1x + stack.shift();
34766                      c2y = c1y + stack.shift();
34767                      y = c2y + stack.shift();
34768                      x = c2x + (stack.length === 1 ? stack.shift() : 0);
34769                      p.curveTo(c1x, c1y, c2x, c2y, x, y);
34770                    }
34771
34772                    break;
34773
34774                  case 31:
34775                    // hvcurveto
34776                    while (stack.length > 0) {
34777                      c1x = x + stack.shift();
34778                      c1y = y;
34779                      c2x = c1x + stack.shift();
34780                      c2y = c1y + stack.shift();
34781                      y = c2y + stack.shift();
34782                      x = c2x + (stack.length === 1 ? stack.shift() : 0);
34783                      p.curveTo(c1x, c1y, c2x, c2y, x, y);
34784
34785                      if (stack.length === 0) {
34786                        break;
34787                      }
34788
34789                      c1x = x;
34790                      c1y = y + stack.shift();
34791                      c2x = c1x + stack.shift();
34792                      c2y = c1y + stack.shift();
34793                      x = c2x + stack.shift();
34794                      y = c2y + (stack.length === 1 ? stack.shift() : 0);
34795                      p.curveTo(c1x, c1y, c2x, c2y, x, y);
34796                    }
34797
34798                    break;
34799
34800                  default:
34801                    if (v < 32) {
34802                      console.log('Glyph ' + glyph.index + ': unknown operator ' + v);
34803                    } else if (v < 247) {
34804                      stack.push(v - 139);
34805                    } else if (v < 251) {
34806                      b1 = code[i];
34807                      i += 1;
34808                      stack.push((v - 247) * 256 + b1 + 108);
34809                    } else if (v < 255) {
34810                      b1 = code[i];
34811                      i += 1;
34812                      stack.push(-(v - 251) * 256 - b1 - 108);
34813                    } else {
34814                      b1 = code[i];
34815                      b2 = code[i + 1];
34816                      b3 = code[i + 2];
34817                      b4 = code[i + 3];
34818                      i += 4;
34819                      stack.push((b1 << 24 | b2 << 16 | b3 << 8 | b4) / 65536);
34820                    }
34821
34822                }
34823              }
34824            }
34825
34826            parse$$1(code);
34827            glyph.advanceWidth = width;
34828            return p;
34829          }
34830
34831          function parseCFFFDSelect(data, start, nGlyphs, fdArrayCount) {
34832            var fdSelect = [];
34833            var fdIndex;
34834            var parser = new parse.Parser(data, start);
34835            var format = parser.parseCard8();
34836
34837            if (format === 0) {
34838              // Simple list of nGlyphs elements
34839              for (var iGid = 0; iGid < nGlyphs; iGid++) {
34840                fdIndex = parser.parseCard8();
34841
34842                if (fdIndex >= fdArrayCount) {
34843                  throw new Error('CFF table CID Font FDSelect has bad FD index value ' + fdIndex + ' (FD count ' + fdArrayCount + ')');
34844                }
34845
34846                fdSelect.push(fdIndex);
34847              }
34848            } else if (format === 3) {
34849              // Ranges
34850              var nRanges = parser.parseCard16();
34851              var first = parser.parseCard16();
34852
34853              if (first !== 0) {
34854                throw new Error('CFF Table CID Font FDSelect format 3 range has bad initial GID ' + first);
34855              }
34856
34857              var next;
34858
34859              for (var iRange = 0; iRange < nRanges; iRange++) {
34860                fdIndex = parser.parseCard8();
34861                next = parser.parseCard16();
34862
34863                if (fdIndex >= fdArrayCount) {
34864                  throw new Error('CFF table CID Font FDSelect has bad FD index value ' + fdIndex + ' (FD count ' + fdArrayCount + ')');
34865                }
34866
34867                if (next > nGlyphs) {
34868                  throw new Error('CFF Table CID Font FDSelect format 3 range has bad GID ' + next);
34869                }
34870
34871                for (; first < next; first++) {
34872                  fdSelect.push(fdIndex);
34873                }
34874
34875                first = next;
34876              }
34877
34878              if (next !== nGlyphs) {
34879                throw new Error('CFF Table CID Font FDSelect format 3 range has bad final GID ' + next);
34880              }
34881            } else {
34882              throw new Error('CFF Table CID Font FDSelect table has unsupported format ' + format);
34883            }
34884
34885            return fdSelect;
34886          } // Parse the `CFF` table, which contains the glyph outlines in PostScript format.
34887
34888
34889          function parseCFFTable(data, start, font) {
34890            font.tables.cff = {};
34891            var header = parseCFFHeader(data, start);
34892            var nameIndex = parseCFFIndex(data, header.endOffset, parse.bytesToString);
34893            var topDictIndex = parseCFFIndex(data, nameIndex.endOffset);
34894            var stringIndex = parseCFFIndex(data, topDictIndex.endOffset, parse.bytesToString);
34895            var globalSubrIndex = parseCFFIndex(data, stringIndex.endOffset);
34896            font.gsubrs = globalSubrIndex.objects;
34897            font.gsubrsBias = calcCFFSubroutineBias(font.gsubrs);
34898            var topDictArray = gatherCFFTopDicts(data, start, topDictIndex.objects, str
34898ingIndex.objects);
34899
34900            if (topDictArray.length !== 1) {
34901              throw new Error('CFF table has too many fonts in \'FontSet\' - count of fonts NameIndex.length = ' + topDictArray.length);
34902            }
34903
34904            var topDict = topDictArray[0];
34905            font.tables.cff.topDict = topDict;
34906
34907            if (topDict._privateDict) {
34908              font.defaultWidthX = topDict._privateDict.defaultWidthX;
34909              font.nominalWidthX = topDict._privateDict.nominalWidthX;
34910            }
34911
34912            if (topDict.ros[0] !== undefined && topDict.ros[1] !== undefined) {
34913              font.isCIDFont = true;
34914            }
34915
34916            if (font.isCIDFont) {
34917              var fdArrayOffset = topDict.fdArray;
34918              var fdSelectOffset = topDict.fdSelect;
34919
34920              if (fdArrayOffset === 0 || fdSelectOffset === 0) {
34921                throw new Error('Font is marked as a CID font, but FDArray and/or FDSelect information is missing');
34922              }
34923
34924              fdArrayOffset += start;
34925              var fdArrayIndex = parseCFFIndex(data, fdArrayOffset);
34926              var fdArray = gatherCFFTopDicts(data, start, fdArrayIndex.objects, stringIndex.objects);
34927              topDict._fdArray = fdArray;
34928              fdSelectOffset += start;
34929              topDict._fdSelect = parseCFFFDSelect(data, fdSelectOffset, font.numGlyphs, fdArray.length);
34930            }
34931
34932            var privateDictOffset = start + topDict.private[1];
34933            var privateDict = parseCFFPrivateDict(data, privateDictOffset, topDict.private[0], stringIndex.objects);
34934            font.defaultWidthX = privateDict.defaultWidthX;
34935            font.nominalWidthX = privateDict.nominalWidthX;
34936
34937            if (privateDict.subrs !== 0) {
34938              var subrOffset = privateDictOffset + privateDict.subrs;
34939              var subrIndex = parseCFFIndex(data, subrOffset);
34940              font.subrs = subrIndex.objects;
34941              font.subrsBias = calcCFFSubroutineBias(font.subrs);
34942            } else {
34943              font.subrs = [];
34944              font.subrsBias = 0;
34945            } // Offsets in the top dict are relative to the beginning of the CFF data, so add the CFF start offset.
34946
34947
34948            var charStringsIndex = parseCFFIndex(data, start + topDict.charStrings);
34949            font.nGlyphs = charStringsIndex.objects.length;
34950            var charset = parseCFFCharset(data, start + topDict.charset, font.nGlyphs, stringIndex.objects);
34951
34952            if (topDict.encoding === 0) {
34953              // Standard encoding
34954              font.cffEncoding = new CffEncoding(cffStandardEncoding, charset);
34955            } else if (topDict.encoding === 1) {
34956              // Expert encoding
34957              font.cffEncoding = new CffEncoding(cffExpertEncoding, charset);
34958            } else {
34959              font.cffEncoding = parseCFFEncoding(data, start + topDict.encoding, charset);
34960            } // Prefer the CMAP encoding to the CFF encoding.
34961
34962
34963            font.encoding = font.encoding || font.cffEncoding;
34964            font.glyphs = new glyphset.GlyphSet(font);
34965
34966            for (var i = 0; i < font.nGlyphs; i += 1) {
34967              var charString = charStringsIndex.objects[i];
34968              font.glyphs.push(i, glyphset.cffGlyphLoader(font, i, parseCFFCharstring, charString));
34969            }
34970          } // Convert a string to a String ID (SID).
34971          // The list of strings is modified in place.
34972
34973
34974          function encodeString(s, strings) {
34975            var sid; // Is the string in the CFF standard strings?
34976
34977            var i = cffStandardStrings.indexOf(s);
34978
34979            if (i >= 0) {
34980              sid = i;
34981            } // Is the string already in the string index?
34982
34983
34984            i = strings.indexOf(s);
34985
34986            if (i >= 0) {
34987              sid = i + cffStandardStrings.length;
34988            } else {
34989              sid = cffStandardStrings.length + strings.length;
34990              strings.push(s);
34991            }
34992
34993            return sid;
34994          }
34995
34996          function makeHeader() {
34997            return new table.Record('Header', [{
34998              name: 'major',
34999              type: 'Card8',
35000              value: 1
35001            }, {
35002              name: 'minor',
35003              type: 'Card8',
35004              value: 0
35005            }, {
35006              name: 'hdrSize',
35007              type: 'Card8',
35008              value: 4
35009            }, {
35010              name: 'major',
35011              type: 'Card8',
35012              value: 1
35013            }]);
35014          }
35015
35016          function makeNameIndex(fontNames) {
35017            var t = new table.Record('Name INDEX', [{
35018              name: 'names',
35019              type: 'INDEX',
35020              value: []
35021            }]);
35022            t.names = [];
35023
35024            for (var i = 0; i < fontNames.length; i += 1) {
35025              t.names.push({
35026                name: 'name_' + i,
35027                type: 'NAME',
35028                value: fontNames[i]
35029              });
35030            }
35031
35032            return t;
35033          } // Given a dictionary's metadata, create a DICT structure.
35034
35035
35036          function makeDict(meta, attrs, strings) {
35037            var m = {};
35038
35039            for (var i = 0; i < meta.length; i += 1) {
35040              var entry = meta[i];
35041              var value = attrs[entry.name];
35042
35043              if (value !== undefined && !equals(value, entry.value)) {
35044                if (entry.type === 'SID') {
35045                  value = encodeString(value, strings);
35046                }
35047
35048                m[entry.op] = {
35049                  name: entry.name,
35050                  type: entry.type,
35051                  value: value
35052                };
35053              }
35054            }
35055
35056            return m;
35057          } // The Top DICT houses the global font attributes.
35058
35059
35060          function makeTopDict(attrs, strings) {
35061            var t = new table.Record('Top DICT', [{
35062              name: 'dict',
35063              type: 'DICT',
35064              value: {}
35065            }]);
35066            t.dict = makeDict(TOP_DICT_META, attrs, strings);
35067            return t;
35068          }
35069
35070          function makeTopDictIndex(topDict) {
35071            var t = new table.Record('Top DICT INDEX', [{
35072              name: 'topDicts',
35073              type: 'INDEX',
35074              value: []
35075            }]);
35076            t.topDicts = [{
35077              name: 'topDict_0',
35078              type: 'TABLE',
35079              value: topDict
35080            }];
35081            return t;
35082          }
35083
35084          function makeStringIndex(strings) {
35085            var t = new table.Record('String INDEX', [{
35086              name: 'strings',
35087              type: 'INDEX',
35088              value: []
35089            }]);
35090            t.strings = [];
35091
35092            for (var i = 0; i < strings.length; i += 1) {
35093              t.strings.push({
35094                name: 'string_' + i,
35095                type: 'STRING',
35096                value: strings[i]
35097              });
35098            }
35099
35100            return t;
35101          }
35102
35103          function makeGlobalSubrIndex() {
35104            // Currently we don't use subroutines.
35105            return new table.Record('Global Subr INDEX', [{
35106              name: 'subrs',
35107              type: 'INDEX',
35108              value: []
35109            }]);
35110          }
35111
35112          function makeCharsets(glyphNames, strings) {
35113            var t = new table.Record('Charsets', [{
35114              name: 'format',
35115              type: 'Card8',
35116              value: 0
35117            }]);
35118
35119            for (var i = 0; i < glyphNames.length; i += 1) {
35120              var glyphName = glyphNames[i];
35121              var glyphSID = encodeString(glyphName, strings);
35122              t.fields.push({
35123                name: 'glyph_' + i,
35124                type: 'SID',
35125                value: glyphSID
35126              });
35127            }
35128
35129            return t;
35130          }
35131
35132          function glyphToOps(glyph) {
35133            var ops = [];
35134            var path = glyph.path;
35135            ops.push({
35136              name: 'width',
35137              type: 'NUMBER',
35138              value: glyph.advanceWidth
35139            });
35140            var x = 0;
35141            var y = 0;
35142
35143            for (var i = 0; i < path.commands.length; i += 1) {
35144              var dx = void 0;
35145              var dy = void 0;
35146              var cmd = path.commands[i];
35147
35148              if (cmd.type === 'Q') {
35149                // CFF only supports bézier curves, so convert the quad to a bézier.
35150                var _13 = 1 / 3;
35151
35152                var _23 = 2 / 3; // We're going to create a new command so we don't change the original path.
35153
35154
35155                cmd = {
35156                  type: 'C',
35157                  x: cmd.x,
35158                  y: cmd.y,
35159                  x1: _13 * x + _23 * cmd.x1,
35160                  y1: _13 * y + _23 * cmd.y1,
35161                  x2: _13 * cmd.x + _23 * cmd.x1,
35162                  y2: _13 * cmd.y + _23 * cmd.y1
35163                };
35164              }
35165
35166              if (cmd.type === 'M') {
35167                dx = Math.round(cmd.x - x);
35168                dy = Math.round(cmd.y - y);
35169                ops.push({
35170                  name: 'dx',
35171                  type: 'NUMBER',
35172                  value: dx
35173                });
35174                ops.push({
35175                  name: 'dy',
35176                  type: 'NUMBER',
35177                  value: dy
35178                });
35179                ops.push({
35180                  name: 'rmoveto',
35181                  type: 'OP',
35182                  value: 21
35183                });
35184                x = Math.round(cmd.x);
35185                y = Math.round(cmd.y);
35186              } else if (cmd.type === 'L') {
35187                dx = Math.round(cmd.x - x);
35188                dy = Math.round(cmd.y - y);
35189                ops.push({
35190                  name: 'dx',
35191                  type: 'NUMBER',
35192                  value: dx
35193                });
35194                ops.push({
35195                  name: 'dy',
35196                  type: 'NUMBER',
35197                  value: dy
35198                });
35199                ops.push({
35200                  name: 'rlineto',
35201                  type: 'OP',
35202                  value: 5
35203                });
35204                x = Math.round(cmd.x);
35205                y = Math.round(cmd.y);
35206              } else if (cmd.type === 'C') {
35207                var dx1 = Math.round(cmd.x1 - x);
35208                var dy1 = Math.round(cmd.y1 - y);
35209                var dx2 = Math.round(cmd.x2 - cmd.x1);
35210                var dy2 = Math.round(cmd.y2 - cmd.y1);
35211                dx = Math.round(cmd.x - cmd.x2);
35212                dy = Math.round(cmd.y - cmd.y2);
35213                ops.push({
35214                  name: 'dx1',
35215                  type: 'NUMBER',
35216                  value: dx1
35217                });
35218                ops.push({
35219                  name: 'dy1',
35220                  type: 'NUMBER',
35221                  value: dy1
35222                });
35223                ops.push({
35224                  name: 'dx2',
35225                  type: 'NUMBER',
35226                  value: dx2
35227                });
35228                ops.push({
35229                  name: 'dy2',
35230                  type: 'NUMBER',
35231                  value: dy2
35232                });
35233                ops.push({
35234                  name: 'dx',
35235                  type: 'NUMBER',
35236                  value: dx
35237                });
35238                ops.push({
35239                  name: 'dy',
35240                  type: 'NUMBER',
35241                  value: dy
35242                });
35243                ops.push({
35244                  name: 'rrcurveto',
35245                  type: 'OP',
35246                  value: 8
35247                });
35248                x = Math.round(cmd.x);
35249                y = Math.round(cmd.y);
35250              } // Contours are closed automatically.
35251
35252            }
35253
35254            ops.push({
35255              name: 'endchar',
35256              type: 'OP',
35257              value: 14
35258            });
35259            return ops;
35260          }
35261
35262          function makeCharStringsIndex(glyphs) {
35263            var t = new table.Record('CharStrings INDEX', [{
35264              name: 'charStrings',
35265              type: 'INDEX',
35266              value: []
35267            }]);
35268
35269            for (var i = 0; i < glyphs.length; i += 1) {
35270              var glyph = glyphs.get(i);
35271              var ops = glyphToOps(glyph);
35272              t.charStrings.push({
35273                name: glyph.name,
35274                type: 'CHARSTRING',
35275                value: ops
35276              });
35277            }
35278
35279            return t;
35280          }
35281
35282          function makePrivateDict(attrs, strings) {
35283            var t = new table.Record('Private DICT', [{
35284              name: 'dict',
35285              type: 'DICT',
35286              value: {}
35287            }]);
35288            t.dict = makeDict(PRIVATE_DICT_META, attrs, strings);
35289            return t;
35290          }
35291
35292          function makeCFFTable(glyphs, options) {
35293            var t = new table.Table('CFF ', [{
35294              name: 'header',
35295              type: 'RECORD'
35296            }, {
35297              name: 'nameIndex',
35298              type: 'RECORD'
35299            }, {
35300              name: 'topDictIndex',
35301              type: 'RECORD'
35302            }, {
35303              name: 'stringIndex',
35304              type: 'RECORD'
35305            }, {
35306              name: 'globalSubrIndex',
35307              type: 'RECORD'
35308            }, {
35309              name: 'charsets',
35310              type: 'RECORD'
35311            }, {
35312              name: 'charStringsIndex',
35313              type: 'RECORD'
35314            }, {
35315              name: 'privateDict',
35316              type: 'RECORD'
35317            }]);
35318            var fontScale = 1 / options.unitsPerEm; // We use non-zero values for the offsets so that the DICT encodes them.
35319            // This is important because the size of the Top DICT plays a role in offset calculation,
35320            // and the size shouldn't change after we've written correct offsets.
35321
35322            var attrs = {
35323              version: options.version,
35324              fullName: options.fullName,
35325              familyName: options.familyName,
35326              weight: options.weightName,
35327              fontBBox: options.fontBBox || [0, 0, 0, 0],
35328              fontMatrix: [fontScale, 0, 0, fontScale, 0, 0],
35329              charset: 999,
35330              encoding: 0,
35331              charStrings: 999,
35332              private: [0, 999]
35333            };
35334            var privateAttrs = {};
35335            var glyphNames = [];
35336            var glyph; // Skip first glyph (.notdef)
35337
35338            for (var i = 1; i < glyphs.length; i += 1) {
35339              glyph = glyphs.get(i);
35340              glyphNames.push(glyph.name);
35341            }
35342
35343            var strings = [];
35344            t.header = makeHeader();
35345            t.nameIndex = makeNameIndex([options.postScriptName]);
35346            var topDict = makeTopDict(attrs, strings);
35347            t.topDictIndex = makeTopDictIndex(topDict);
35348            t.globalSubrIndex = makeGlobalSubrIndex();
35349            t.charsets = makeCharsets(glyphNames, strings);
35350            t.charStringsIndex = makeCharStringsIndex(glyphs);
35351            t.privateDict = makePrivateDict(privateAttrs, strings); // Needs to come at the end, to encode all custom strings used in the font.
35352
35353            t.stringIndex = makeStringIndex(strings);
35354            var startOffset = t.header.sizeOf() + t.nameIndex.sizeOf() + t.topDictIndex.sizeOf() + t.stringIndex.sizeOf() + t.globalSubrIndex.sizeOf();
35355            attrs.charset = startOffset; // We use the CFF standard encoding; proper encoding will be handled in cmap.
35356
35357            attrs.encoding = 0;
35358            attrs.charStrings = attrs.charset + t.charsets.sizeOf();
35359            attrs.private[1] = attrs.charStrings + t.charStringsIndex.sizeOf(); // Recreate the Top DICT INDEX with the correct offsets.
35360
35361            topDict = makeTopDict(attrs, strings);
35362            t.topDictIndex = makeTopDictIndex(topDict);
35363            return t;
35364          }
35365
35366          var cff = {
35367            parse: parseCFFTable,
35368            make: makeCFFTable
35369          }; // The `head` table contains global information about the font.
35370          // Parse the header `head` table
35371
35372          function parseHeadTable(data, start) {
35373            var head = {};
35374            var p = new parse.Parser(data, start);
35375            head.version = p.parseVersion();
35376            head.fontRevision = Math.round(p.parseFixed() * 1000) / 1000;
35377            head.checkSumAdjustment = p.parseULong();
35378            head.magicNumber = p.parseULong();
35379            check.argument(head.magicNumber === 0x5F0F3CF5, 'Font header has wrong magic number.');
35380            head.flags = p.parseUShort();
35381            head.unitsPerEm = p.parseUShort();
35382            head.created = p.parseLongDateTime();
35383            head.modified = p.parseLongDateTime();
35384            head.xMin = p.parseShort();
35385            head.yMin = p.parseShort();
35386            head.xMax = p.parseShort();
35387            head.yMax = p.parseShort();
35388            head.macStyle = p.parseUShort();
35389            head.lowestRecPPEM = p.parseUShort();
35390            head.fontDirectionHint = p.parseShort();
35391            head.indexToLocFormat = p.parseShort();
35392            head.glyphDataFormat = p.parseShort();
35393            return head;
35394          }
35395
35396          function makeHeadTable(options) {
35397            // Apple Mac timestamp epoch is 01/01/1904 not 01/01/1970
35398            var timestamp = Math.round(new Date().getTime() / 1000) + 2082844800;
35399            var createdTimestamp = timestamp;
35400
35401            if (options.createdTimestamp) {
35402              createdTimestamp = options.createdTimestamp + 2082844800;
35403            }
35404
35405            return new table.Table('head', [{
35406              name: 'version',
35407              type: 'FIXED',
35408              value: 0x00010000
35409            }, {
35410              name: 'fontRevision',
35411              type: 'FIXED',
35412              value: 0x00010000
35413            }, {
35414              name: 'checkSumAdjustment',
35415              type: 'ULONG',
35416              value: 0
35417            }, {
35418              name: 'magicNumber',
35419              type: 'ULONG',
35420              value: 0x5F0F3CF5
35421            }, {
35422              name: 'flags',
35423              type: 'USHORT',
35424              value: 0
35425            }, {
35426              name: 'unitsPerEm',
35427              type: 'USHORT',
35428              value: 1000
35429            }, {
35430              name: 'created',
35431              type: 'LONGDATETIME',
35432              value: createdTimestamp
35433            }, {
35434              name: 'modified',
35435              type: 'LONGDATETIME',
35436              value: timestamp
35437            }, {
35438              name: 'xMin',
35439              type: 'SHORT',
35440              value: 0
35441            }, {
35442              name: 'yMin',
35443              type: 'SHORT',
35444              value: 0
35445            }, {
35446              name: 'xMax',
35447              type: 'SHORT',
35448              value: 0
35449            }, {
35450              name: 'yMax',
35451              type: 'SHORT',
35452              value: 0
35453            }, {
35454              name: 'macStyle',
35455              type: 'USHORT',
35456              value: 0
35457            }, {
35458              name: 'lowestRecPPEM',
35459              type: 'USHORT',
35460              value: 0
35461            }, {
35462              name: 'fontDirectionHint',
35463              type: 'SHORT',
35464              value: 2
35465            }, {
35466              name: 'indexToLocFormat',
35467              type: 'SHORT',
35468              value: 0
35469            }, {
35470              name: 'glyphDataFormat',
35471              type: 'SHORT',
35472              value: 0
35473            }], options);
35474          }
35475
35476          var head = {
35477            parse: parseHeadTable,
35478            make: makeHeadTable
35479          }; // The `hhea` table contains information for horizontal layout.
35480          // Parse the horizontal header `hhea` table
35481
35482          function parseHheaTable(data, start) {
35483            var hhea = {};
35484            var p = new parse.Parser(data, start);
35485            hhea.version = p.parseVersion();
35486            hhea.ascender = p.parseShort();
35487            hhea.descender = p.parseShort();
35488            hhea.lineGap = p.parseShort();
35489            hhea.advanceWidthMax = p.parseUShort();
35490            hhea.minLeftSideBearing = p.parseShort();
35491            hhea.minRightSideBearing = p.parseShort();
35492            hhea.xMaxExtent = p.parseShort();
35493            hhea.caretSlopeRise = p.parseShort();
35494            hhea.caretSlopeRun = p.parseShort();
35495            hhea.caretOffset = p.parseShort();
35496            p.relativeOffset += 8;
35497            hhea.metricDataFormat = p.parseShort();
35498            hhea.numberOfHMetrics = p.parseUShort();
35499            return hhea;
35500          }
35501
35502          function makeHheaTable(options) {
35503            return new table.Table('hhea', [{
35504              name: 'version',
35505              type: 'FIXED',
35506              value: 0x00010000
35507            }, {
35508              name: 'ascender',
35509              type: 'FWORD',
35510              value: 0
35511            }, {
35512              name: 'descender',
35513              type: 'FWORD',
35514              value: 0
35515            }, {
35516              name: 'lineGap',
35517              type: 'FWORD',
35518              value: 0
35519            }, {
35520              name: 'advanceWidthMax',
35521              type: 'UFWORD',
35522              value: 0
35523            }, {
35524              name: 'minLeftSideBearing',
35525              type: 'FWORD',
35526              value: 0
35527            }, {
35528              name: 'minRightSideBearing',
35529              type: 'FWORD',
35530              value: 0
35531            }, {
35532              name: 'xMaxExtent',
35533              type: 'FWORD',
35534              value: 0
35535            }, {
35536              name: 'caretSlopeRise',
35537              type: 'SHORT',
35538              value: 1
35539            }, {
35540              name: 'caretSlopeRun',
35541              type: 'SHORT',
35542              value: 0
35543            }, {
35544              name: 'caretOffset',
35545              type: 'SHORT',
35546              value: 0
35547            }, {
35548              name: 'reserved1',
35549              type: 'SHORT',
35550              value: 0
35551            }, {
35552              name: 'reserved2',
35553              type: 'SHORT',
35554              value: 0
35555            }, {
35556              name: 'reserved3',
35557              type: 'SHORT',
35558              value: 0
35559            }, {
35560              name: 'reserved4',
35561              type: 'SHORT',
35562              value: 0
35563            }, {
35564              name: 'metricDataFormat',
35565              type: 'SHORT',
35566              value: 0
35567            }, {
35568              name: 'numberOfHMetrics',
35569              type: 'USHORT',
35570              value: 0
35571            }], options);
35572          }
35573
35574          var hhea = {
35575            parse: parseHheaTable,
35576            make: makeHheaTable
35577          }; // The `hmtx` table contains the horizontal metrics for all glyphs.
35578          // Parse the `hmtx` table, which contains the horizontal metrics for all glyphs.
35579          // This function augments the glyph array, adding the advanceWidth and leftSideBearing to each glyph.
35580
35581          function parseHmtxTable(data, start, numMetrics, numGlyphs, glyphs) {
35582            var advanceWidth;
35583            var leftSideBearing;
35584            var p = new parse.Parser(data, start);
35585
35586            for (var i = 0; i < numGlyphs; i += 1) {
35587              // If the font is monospaced, only one entry is needed. This last entry applies to all subsequent glyphs.
35588              if (i < numMetrics) {
35589                advanceWidth = p.parseUShort();
35590                leftSideBearing = p.parseShort();
35591              }
35592
35593              var glyph = glyphs.get(i);
35594              glyph.advanceWidth = advanceWidth;
35595              glyph.leftSideBearing = leftSideBearing;
35596            }
35597          }
35598
35599          function makeHmtxTable(glyphs) {
35600            var t = new table.Table('hmtx', []);
35601
35602            for (var i = 0; i < glyphs.length; i += 1) {
35603              var glyph = glyphs.get(i);
35604              var advanceWidth = glyph.advanceWidth || 0;
35605              var leftSideBearing = glyph.leftSideBearing || 0;
35606              t.fields.push({
35607                name: 'advanceWidth_' + i,
35608                type: 'USHORT',
35609                value: advanceWidth
35610              });
35611              t.fields.push({
35612                name: 'leftSideBearing_' + i,
35613                type: 'SHORT',
35614                value: leftSideBearing
35615              });
35616            }
35617
35618            return t;
35619          }
35620
35621          var hmtx = {
35622            parse: parseHmtxTable,
35623            make: makeHmtxTable
35624          }; // The `ltag` table stores IETF BCP-47 language tags. It allows supporting
35625
35626          function makeLtagTable(tags) {
35627            var result = new table.Table('ltag', [{
35628              name: 'version',
35629              type: 'ULONG',
35630              value: 1
35631            }, {
35632              name: 'flags',
35633              type: 'ULONG',
35634              value: 0
35635            }, {
35636              name: 'numTags',
35637              type: 'ULONG',
35638              value: tags.length
35639            }]);
35640            var stringPool = '';
35641            var stringPoolOffset = 12 + tags.length * 4;
35642
35643            for (var i = 0; i < tags.length; ++i) {
35644              var pos = stringPool.indexOf(tags[i]);
35645
35646              if (pos < 0) {
35647                pos = stringPool.length;
35648                stringPool += tags[i];
35649              }
35650
35651              result.fields.push({
35652                name: 'offset ' + i,
35653                type: 'USHORT',
35654                value: stringPoolOffset + pos
35655              });
35656              result.fields.push({
35657                name: 'length ' + i,
35658                type: 'USHORT',
35659                value: tags[i].length
35660              });
35661            }
35662
35663            result.fields.push({
35664              name: 'stringPool',
35665              type: 'CHARARRAY',
35666              value: stringPool
35667            });
35668            return result;
35669          }
35670
35671          function parseLtagTable(data, start) {
35672            var p = new parse.Parser(data, start);
35673            var tableVersion = p.parseULong();
35674            check.argument(tableVersion === 1, 'Unsupported ltag table version.'); // The 'ltag' specification does not define any flags; skip the field.
35675
35676            p.skip('uLong', 1);
35677            var numTags = p.parseULong();
35678            var tags = [];
35679
35680            for (var i = 0; i < numTags; i++) {
35681              var tag = '';
35682              var offset = start + p.parseUShort();
35683              var length = p.parseUShort();
35684
35685              for (var j = offset; j < offset + length; ++j) {
35686                tag += String.fromCharCode(data.getInt8(j));
35687              }
35688
35689              tags.push(tag);
35690            }
35691
35692            return tags;
35693          }
35694
35695          var ltag = {
35696            make: makeLtagTable,
35697            parse: parseLtagTable
35698          }; // The `maxp` table establishes the memory requirements for the font.
35699          // Parse the maximum profile `maxp` table.
35700
35701          function parseMaxpTable(data, start) {
35702            var maxp = {};
35703            var p = new parse.Parser(data, start);
35704            maxp.version = p.parseVersion();
35705            maxp.numGlyphs = p.parseUShort();
35706
35707            if (maxp.version === 1.0) {
35708              maxp.maxPoints = p.parseUShort();
35709              maxp.maxContours = p.parseUShort();
35710              maxp.maxCompositePoints = p.parseUShort();
35711              maxp.maxCompositeContours = p.parseUShort();
35712              maxp.maxZones = p.parseUShort();
35713              maxp.maxTwilightPoints = p.parseUShort();
35714              maxp.maxStorage = p.parseUShort();
35715              maxp.maxFunctionDefs = p.parseUShort();
35716              maxp.maxInstructionDefs = p.parseUShort();
35717              maxp.maxStackElements = p.parseUShort();
35718              maxp.maxSizeOfInstructions = p.parseUShort();
35719              maxp.maxComponentElements = p.parseUShort();
35720              maxp.maxComponentDepth = p.parseUShort();
35721            }
35722
35723            return maxp;
35724          }
35725
35726          function makeMaxpTable(numGlyphs) {
35727            return new table.Table('maxp', [{
35728              name: 'version',
35729              type: 'FIXED',
35730              value: 0x00005000
35731            }, {
35732              name: 'numGlyphs',
35733              type: 'USHORT',
35734              value: numGlyphs
35735            }]);
35736          }
35737
35738          var maxp = {
35739            parse: parseMaxpTable,
35740            make: makeMaxpTable
35741          }; // The `name` naming table.
35742          // NameIDs for the name table.
35743
35744          var nameTableNames = ['copyright', // 0
35745          'fontFamily', // 1
35746          'fontSubfamily', // 2
35747          'uniqueID', // 3
35748          'fullName', // 4
35749          'version', // 5
35750          'postScriptName', // 6
35751          'trademark', // 7
35752          'manufacturer', // 8
35753          'designer', // 9
35754          'description', // 10
35755          'manufacturerURL', // 11
35756          'designerURL', // 12
35757          'license', // 13
35758          'licenseURL', // 14
35759          'reserved', // 15
35760          'preferredFamily', // 16
35761          'preferredSubfamily', // 17
35762          'compatibleFullName', // 18
35763          'sampleText', // 19
35764          'postScriptFindFontName', // 20
35765          'wwsFamily', // 21
35766          'wwsSubfamily' // 22
35767          ];
35768          var macLanguages = {
35769            0: 'en',
35770            1: 'fr',
35771            2: 'de',
35772            3: 'it',
35773            4: 'nl',
35774            5: 'sv',
35775            6: 'es',
35776            7: 'da',
35777            8: 'pt',
35778            9: 'no',
35779            10: 'he',
35780            11: 'ja',
35781            12: 'ar',
35782            13: 'fi',
35783            14: 'el',
35784            15: 'is',
35785            16: 'mt',
35786            17: 'tr',
35787            18: 'hr',
35788            19: 'zh-Hant',
35789            20: 'ur',
35790            21: 'hi',
35791            22: 'th',
35792            23: 'ko',
35793            24: 'lt',
35794            25: 'pl',
35795            26: 'hu',
35796            27: 'es',
35797            28: 'lv',
35798            29: 'se',
35799            30: 'fo',
35800            31: 'fa',
35801            32: 'ru',
35802            33: 'zh',
35803            34: 'nl-BE',
35804            35: 'ga',
35805            36: 'sq',
35806            37: 'ro',
35807            38: 'cz',
35808            39: 'sk',
35809            40: 'si',
35810            41: 'yi',
35811            42: 'sr',
35812            43: 'mk',
35813            44: 'bg',
35814            45: 'uk',
35815            46: 'be',
35816            47: 'uz',
35817            48: 'kk',
35818            49: 'az-Cyrl',
35819            50: 'az-Arab',
35820            51: 'hy',
35821            52: 'ka',
35822            53: 'mo',
35823            54: 'ky',
35824            55: 'tg',
35825            56: 'tk',
35826            57: 'mn-CN',
35827            58: 'mn',
35828            59: 'ps',
35829            60: 'ks',
35830            61: 'ku',
35831            62: 'sd',
35832            63: 'bo',
35833            64: 'ne',
35834            65: 'sa',
35835            66: 'mr',
35836            67: 'bn',
35837            68: 'as',
35838            69: 'gu',
35839            70: 'pa',
35840            71: 'or',
35841            72: 'ml',
35842            73: 'kn',
35843            74: 'ta',
35844            75: 'te',
35845            76: 'si',
35846            77: 'my',
35847            78: 'km',
35848            79: 'lo',
35849            80: 'vi',
35850            81: 'id',
35851            82: 'tl',
35852            83: 'ms',
35853            84: 'ms-Arab',
35854            85: 'am',
35855            86: 'ti',
35856            87: 'om',
35857            88: 'so',
35858            89: 'sw',
35859            90: 'rw',
35860            91: 'rn',
35861            92: 'ny',
35862            93: 'mg',
35863            94: 'eo',
35864            128: 'cy',
35865            129: 'eu',
35866            130: 'ca',
35867            131: 'la',
35868            132: 'qu',
35869            133: 'gn',
35870            134: 'ay',
35871            135: 'tt',
35872            136: 'ug',
35873            137: 'dz',
35874            138: 'jv',
35875            139: 'su',
35876            140: 'gl',
35877            141: 'af',
35878            142: 'br',
35879            143: 'iu',
35880            144: 'gd',
35881            145: 'gv',
35882            146: 'ga',
35883            147: 'to',
35884            148: 'el-polyton',
35885            149: 'kl',
35886            150: 'az',
35887            151: 'nn'
35888          }; // MacOS language ID → MacOS script ID
35889          //
35890          // Note that the script ID is not sufficient to determine what encoding
35891          // to use in TrueType files. For some languages, MacOS used a modification
35892          // of a mainstream script. For example, an Icelandic name would be stored
35893          // with smRoman in the TrueType naming table, but the actual encoding
35894          // is a special Icelandic version of the normal Macintosh Roman encoding.
35895          // As another example, Inuktitut uses an 8-bit encoding for Canadian Aboriginal
35896          // Syllables but MacOS had run out of available script codes, so this was
35897          // done as a (pretty radical) "modification" of Ethiopic.
35898          //
35899          // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt
35900
35901          var macLanguageToScript = {
35902            0: 0,
35903            // langEnglish → smRoman
35904            1: 0,
35905            // langFrench → smRoman
35906            2: 0,
35907            // langGerman → smRoman
35908            3: 0,
35909            // langItalian → smRoman
35910            4: 0,
35911            // langDutch → smRoman
35912            5: 0,
35913            // langSwedish → smRoman
35914            6: 0,
35915            // langSpanish → smRoman
35916            7: 0,
35917            // langDanish → smRoman
35918            8: 0,
35919            // langPortuguese → smRoman
35920            9: 0,
35921            // langNorwegian → smRoman
35922            10: 5,
35923            // langHebrew → smHebrew
35924            11: 1,
35925            // langJapanese → smJapanese
35926            12: 4,
35927            // langArabic → smArabic
35928            13: 0,
35929            // langFinnish → smRoman
35930            14: 6,
35931            // langGreek → smGreek
35932            15: 0,
35933            // langIcelandic → smRoman (modified)
35934            16: 0,
35935            // langMaltese → smRoman
35936            17: 0,
35937            // langTurkish → smRoman (modified)
35938            18: 0,
35939            // langCroatian → smRoman (modified)
35940            19: 2,
35941            // langTradChinese → smTradChinese
35942            20: 4,
35943            // langUrdu → smArabic
35944            21: 9,
35945            // langHindi → smDevanagari
35946            22: 21,
35947            // langThai → smThai
35948            23: 3,
35949            // langKorean → smKorean
35950            24: 29,
35951            // langLithuanian → smCentralEuroRoman
35952            25: 29,
35953            // langPolish → smCentralEuroRoman
35954            26: 29,
35955            // langHungarian → smCentralEuroRoman
35956            27: 29,
35957            // langEstonian → smCentralEuroRoman
35958            28: 29,
35959            // langLatvian → smCentralEuroRoman
35960            29: 0,
35961            // langSami → smRoman
35962            30: 0,
35963            // langFaroese → smRoman (modified)
35964            31: 4,
35965            // langFarsi → smArabic (modified)
35966            32: 7,
35967            // langRussian → smCyrillic
35968            33: 25,
35969            // langSimpChinese → smSimpChinese
35970            34: 0,
35971            // langFlemish → smRoman
35972            35: 0,
35973            // langIrishGaelic → smRoman (modified)
35974            36: 0,
35975            // langAlbanian → smRoman
35976            37: 0,
35977            // langRomanian → smRoman (modified)
35978            38: 29,
35979            // langCzech → smCentralEuroRoman
35980            39: 29,
35981            // langSlovak → smCentralEuroRoman
35982            40: 0,
35983            // langSlovenian → smRoman (modified)
35984            41: 5,
35985            // langYiddish → smHebrew
35986            42: 7,
35987            // langSerbian → smCyrillic
35988            43: 7,
35989            // langMacedonian → smCyrillic
35990            44: 7,
35991            // langBulgarian → smCyrillic
35992            45: 7,
35993            // langUkrainian → smCyrillic (modified)
35994            46: 7,
35995            // langByelorussian → smCyrillic
35996            47: 7,
35997            // langUzbek → smCyrillic
35998            48: 7,
35999            // langKazakh → smCyrillic
36000            49: 7,
36001            // langAzerbaijani → smCyrillic
36002            50: 4,
36003            // langAzerbaijanAr → smArabic
36004            51: 24,
36005            // langArmenian → smArmenian
36006            52: 23,
36007            // langGeorgian → smGeorgian
36008            53: 7,
36009            // langMoldavian → smCyrillic
36010            54: 7,
36011            // langKirghiz → smCyrillic
36012            55: 7,
36013            // langTajiki → smCyrillic
36014            56: 7,
36015            // langTurkmen → smCyrillic
36016            57: 27,
36017            // langMongolian → smMongolian
36018            58: 7,
36019            // langMongolianCyr → smCyrillic
36020            59: 4,
36021            // langPashto → smArabic
36022            60: 4,
36023            // langKurdish → smArabic
36024            61: 4,
36025            // langKashmiri → smArabic
36026            62: 4,
36027            // langSindhi → smArabic
36028            63: 26,
36029            // langTibetan → smTibetan
36030            64: 9,
36031            // langNepali → smDevanagari
36032            65: 9,
36033            // langSanskrit → smDevanagari
36034            66: 9,
36035            // langMarathi → smDevanagari
36036            67: 13,
36037            // langBengali → smBengali
36038            68: 13,
36039            // langAssamese → smBengali
36040            69: 11,
36041            // langGujarati → smGujarati
36042            70: 10,
36043            // langPunjabi → smGurmukhi
36044            71: 12,
36045            // langOriya → smOriya
36046            72: 17,
36047            // langMalayalam → smMalayalam
36048            73: 16,
36049            // langKannada → smKannada
36050            74: 14,
36051            // langTamil → smTamil
36052            75: 15,
36053            // langTelugu → smTelugu
36054            76: 18,
36055            // langSinhalese → smSinhalese
36056            77: 19,
36057            // langBurmese → smBurmese
36058            78: 20,
36059            // langKhmer → smKhmer
36060            79: 22,
36061            // langLao → smLao
36062            80: 30,
36063            // langVietnamese → smVietnamese
36064            81: 0,
36065            // langIndonesian → smRoman
36066            82: 0,
36067            // langTagalog → smRoman
36068            83: 0,
36069            // langMalayRoman → smRoman
36070            84: 4,
36071            // langMalayArabic → smArabic
36072            85: 28,
36073            // langAmharic → smEthiopic
36074            86: 28,
36075            // langTigrinya → smEthiopic
36076            87: 28,
36077            // langOromo → smEthiopic
36078            88: 0,
36079            // langSomali → smRoman
36080            89: 0,
36081            // langSwahili → smRoman
36082            90: 0,
36083            // langKinyarwanda → smRoman
36084            91: 0,
36085            // langRundi → smRoman
36086            92: 0,
36087            // langNyanja → smRoman
36088            93: 0,
36089            // langMalagasy → smRoman
36090            94: 0,
36091            // langEsperanto → smRoman
36092            128: 0,
36093            // langWelsh → smRoman (modified)
36094            129: 0,
36095            // langBasque → smRoman
36096            130: 0,
36097            // langCatalan → smRoman
36098            131: 0,
36099            // langLatin → smRoman
36100            132: 0,
36101            // langQuechua → smRoman
36102            133: 0,
36103            // langGuarani → smRoman
36104            134: 0,
36105            // langAymara → smRoman
36106            135: 7,
36107            // langTatar → smCyrillic
36108            136: 4,
36109            // langUighur → smArabic
36110            137: 26,
36111            // langDzongkha → smTibetan
36112            138: 0,
36113            // langJavaneseRom → smRoman
36114            139: 0,
36115            // langSundaneseRom → smRoman
36116            140: 0,
36117            // langGalician → smRoman
36118            141: 0,
36119            // langAfrikaans → smRoman
36120            142: 0,
36121            // langBreton → smRoman (modified)
36122            143: 28,
36123            // langInuktitut → smEthiopic (modified)
36124            144: 0,
36125            // langScottishGaelic → smRoman (modified)
36126            145: 0,
36127            // langManxGaelic → smRoman (modified)
36128            146: 0,
36129            // langIrishGaelicScript → smRoman (modified)
36130            147: 0,
36131            // langTongan → smRoman
36132            148: 6,
36133            // langGreekAncient → smRoman
36134            149: 0,
36135            // langGreenlandic → smRoman
36136            150: 0,
36137            // langAzerbaijanRoman → smRoman
36138            151: 0 // langNynorsk → smRoman
36139
36140          }; // While Microsoft indicates a region/country for all its language
36141          // IDs, we omit the region code if it's equal to the "most likely
36142          // region subtag" according to Unicode CLDR. For scripts, we omit
36143          // the subtag if it is equal to the Suppress-Script entry in the
36144          // IANA language subtag registry for IETF BCP 47.
36145          //
36146          // For example, Microsoft states that its language code 0x041A is
36147          // Croatian in Croatia. We transform this to the BCP 47 language code 'hr'
36148          // and not 'hr-HR' because Croatia is the default country for Croatian,
36149          // according to Unicode CLDR. As another example, Microsoft states
36150          // that 0x101A is Croatian (Latin) in Bosnia-Herzegovina. We transform
36151          // this to 'hr-BA' and not 'hr-Latn-BA' because Latin is the default script
36152          // for the Croatian language, according to IANA.
36153          //
36154          // http://www.unicode.org/cldr/charts/latest/supplemental/likely_subtags.html
36155          // http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
36156
36157          var windowsLanguages = {
36158            0x0436: 'af',
36159            0x041C: 'sq',
36160            0x0484: 'gsw',
36161            0x045E: 'am',
36162            0x1401: 'ar-DZ',
36163            0x3C01: 'ar-BH',
36164            0x0C01: 'ar',
36165            0x0801: 'ar-IQ',
36166            0x2C01: 'ar-JO',
36167            0x3401: 'ar-KW',
36168            0x3001: 'ar-LB',
36169            0x1001: 'ar-LY',
36170            0x1801: 'ary',
36171            0x2001: 'ar-OM',
36172            0x4001: 'ar-QA',
36173            0x0401: 'ar-SA',
36174            0x2801: 'ar-SY',
36175            0x1C01: 'aeb',
36176            0x3801: 'ar-AE',
36177            0x2401: 'ar-YE',
36178            0x042B: 'hy',
36179            0x044D: 'as',
36180            0x082C: 'az-Cyrl',
36181            0x042C: 'az',
36182            0x046D: 'ba',
36183            0x042D: 'eu',
36184            0x0423: 'be',
36185            0x0845: 'bn',
36186            0x0445: 'bn-IN',
36187            0x201A: 'bs-Cyrl',
36188            0x141A: 'bs',
36189            0x047E: 'br',
36190            0x0402: 'bg',
36191            0x0403: 'ca',
36192            0x0C04: 'zh-HK',
36193            0x1404: 'zh-MO',
36194            0x0804: 'zh',
36195            0x1004: 'zh-SG',
36196            0x0404: 'zh-TW',
36197            0x0483: 'co',
36198            0x041A: 'hr',
36199            0x101A: 'hr-BA',
36200            0x0405: 'cs',
36201            0x0406: 'da',
36202            0x048C: 'prs',
36203            0x0465: 'dv',
36204            0x0813: 'nl-BE',
36205            0x0413: 'nl',
36206            0x0C09: 'en-AU',
36207            0x2809: 'en-BZ',
36208            0x1009: 'en-CA',
36209            0x2409: 'en-029',
36210            0x4009: 'en-IN',
36211            0x1809: 'en-IE',
36212            0x2009: 'en-JM',
36213            0x4409: 'en-MY',
36214            0x1409: 'en-NZ',
36215            0x3409: 'en-PH',
36216            0x4809: 'en-SG',
36217            0x1C09: 'en-ZA',
36218            0x2C09: 'en-TT',
36219            0x0809: 'en-GB',
36220            0x0409: 'en',
36221            0x3009: 'en-ZW',
36222            0x0425: 'et',
36223            0x0438: 'fo',
36224            0x0464: 'fil',
36225            0x040B: 'fi',
36226            0x080C: 'fr-BE',
36227            0x0C0C: 'fr-CA',
36228            0x040C: 'fr',
36229            0x140C: 'fr-LU',
36230            0x180C: 'fr-MC',
36231            0x100C: 'fr-CH',
36232            0x0462: 'fy',
36233            0x0456: 'gl',
36234            0x0437: 'ka',
36235            0x0C07: 'de-AT',
36236            0x0407: 'de',
36237            0x1407: 'de-LI',
36238            0x1007: 'de-LU',
36239            0x0807: 'de-CH',
36240            0x0408: 'el',
36241            0x046F: 'kl',
36242            0x0447: 'gu',
36243            0x0468: 'ha',
36244            0x040D: 'he',
36245            0x0439: 'hi',
36246            0x040E: 'hu',
36247            0x040F: 'is',
36248            0x0470: 'ig',
36249            0x0421: 'id',
36250            0x045D: 'iu',
36251            0x085D: 'iu-Latn',
36252            0x083C: 'ga',
36253            0x0434: 'xh',
36254            0x0435: 'zu',
36255            0x0410: 'it',
36256            0x0810: 'it-CH',
36257            0x0411: 'ja',
36258            0x044B: 'kn',
36259            0x043F: 'kk',
36260            0x0453: 'km',
36261            0x0486: 'quc',
36262            0x0487: 'rw',
36263            0x0441: 'sw',
36264            0x0457: 'kok',
36265            0x0412: 'ko',
36266            0x0440: 'ky',
36267            0x0454: 'lo',
36268            0x0426: 'lv',
36269            0x0427: 'lt',
36270            0x082E: 'dsb',
36271            0x046E: 'lb',
36272            0x042F: 'mk',
36273            0x083E: 'ms-BN',
36274            0x043E: 'ms',
36275            0x044C: 'ml',
36276            0x043A: 'mt',
36277            0x0481: 'mi',
36278            0x047A: 'arn',
36279            0x044E: 'mr',
36280            0x047C: 'moh',
36281            0x0450: 'mn',
36282            0x0850: 'mn-CN',
36283            0x0461: 'ne',
36284            0x0414: 'nb',
36285            0x0814: 'nn',
36286            0x0482: 'oc',
36287            0x0448: 'or',
36288            0x0463: 'ps',
36289            0x0415: 'pl',
36290            0x0416: 'pt',
36291            0x0816: 'pt-PT',
36292            0x0446: 'pa',
36293            0x046B: 'qu-BO',
36294            0x086B: 'qu-EC',
36295            0x0C6B: 'qu',
36296            0x0418: 'ro',
36297            0x0417: 'rm',
36298            0x0419: 'ru',
36299            0x243B: 'smn',
36300            0x103B: 'smj-NO',
36301            0x143B: 'smj',
36302            0x0C3B: 'se-FI',
36303            0x043B: 'se',
36304            0x083B: 'se-SE',
36305            0x203B: 'sms',
36306            0x183B: 'sma-NO',
36307            0x1C3B: 'sms',
36308            0x044F: 'sa',
36309            0x1C1A: 'sr-Cyrl-BA',
36310            0x0C1A: 'sr',
36311            0x181A: 'sr-Latn-BA',
36312            0x081A: 'sr-Latn',
36313            0x046C: 'nso',
36314            0x0432: 'tn',
36315            0x045B: 'si',
36316            0x041B: 'sk',
36317            0x0424: 'sl',
36318            0x2C0A: 'es-AR',
36319            0x400A: 'es-BO',
36320            0x340A: 'es-CL',
36321            0x240A: 'es-CO',
36322            0x140A: 'es-CR',
36323            0x1C0A: 'es-DO',
36324            0x300A: 'es-EC',
36325            0x440A: 'es-SV',
36326            0x100A: 'es-GT',
36327            0x480A: 'es-HN',
36328            0x080A: 'es-MX',
36329            0x4C0A: 'es-NI',
36330            0x180A: 'es-PA',
36331            0x3C0A: 'es-PY',
36332            0x280A: 'es-PE',
36333            0x500A: 'es-PR',
36334            // Microsoft has defined two different language codes for
36335            // “Spanish with modern sorting” and “Spanish with traditional
36336            // sorting”. This makes sense for collation APIs, and it would be
36337            // possible to express this in BCP 47 language tags via Unicode
36338            // extensions (eg., es-u-co-trad is Spanish with traditional
36339            // sorting). However, for storing names in fonts, the distinction
36340            // does not make sense, so we give “es” in both cases.
36341            0x0C0A: 'es',
36342            0x040A: 'es',
36343            0x540A: 'es-US',
36344            0x380A: 'es-UY',
36345            0x200A: 'es-VE',
36346            0x081D: 'sv-FI',
36347            0x041D: 'sv',
36348            0x045A: 'syr',
36349            0x0428: 'tg',
36350            0x085F: 'tzm',
36351            0x0449: 'ta',
36352            0x0444: 'tt',
36353            0x044A: 'te',
36354            0x041E: 'th',
36355            0x0451: 'bo',
36356            0x041F: 'tr',
36357            0x0442: 'tk',
36358            0x0480: 'ug',
36359            0x0422: 'uk',
36360            0x042E: 'hsb',
36361            0x0420: 'ur',
36362            0x0843: 'uz-Cyrl',
36363            0x0443: 'uz',
36364            0x042A: 'vi',
36365            0x0452: 'cy',
36366            0x0488: 'wo',
36367            0x0485: 'sah',
36368            0x0478: 'ii',
36369            0x046A: 'yo'
36370          }; // Returns a IETF BCP 47 language code, for example 'zh-Hant'
36371          // for 'Chinese in the traditional script'.
36372
36373          function getLanguageCode(platformID, languageID, ltag) {
36374            switch (platformID) {
36375              case 0:
36376                // Unicode
36377                if (languageID === 0xFFFF) {
36378                  return 'und';
36379                } else if (ltag) {
36380                  return ltag[languageID];
36381                }
36382
36383                break;
36384
36385              case 1:
36386                // Macintosh
36387                return macLanguages[languageID];
36388
36389              case 3:
36390                // Windows
36391                return windowsLanguages[languageID];
36392            }
36393
36394            return undefined;
36395          }
36396
36397          var utf16 = 'utf-16'; // MacOS script ID → encoding. This table stores the default case,
36398          // which can be overridden by macLanguageEncodings.
36399
36400          var macScriptEncodings = {
36401            0: 'macintosh',
36402            // smRoman
36403            1: 'x-mac-japanese',
36404            // smJapanese
36405            2: 'x-mac-chinesetrad',
36406            // smTradChinese
36407            3: 'x-mac-korean',
36408            // smKorean
36409            6: 'x-mac-greek',
36410            // smGreek
36411            7: 'x-mac-cyrillic',
36412            // smCyrillic
36413            9: 'x-mac-devanagai',
36414            // smDevanagari
36415            10: 'x-mac-gurmukhi',
36416            // smGurmukhi
36417            11: 'x-mac-gujarati',
36418            // smGujarati
36419            12: 'x-mac-oriya',
36420            // smOriya
36421            13: 'x-mac-bengali',
36422            // smBengali
36423            14: 'x-mac-tamil',
36424            // smTamil
36425            15: 'x-mac-telugu',
36426            // smTelugu
36427            16: 'x-mac-kannada',
36428            // smKannada
36429            17: 'x-mac-malayalam',
36430            // smMalayalam
36431            18: 'x-mac-sinhalese',
36432            // smSinhalese
36433            19: 'x-mac-burmese',
36434            // smBurmese
36435            20: 'x-mac-khmer',
36436            // smKhmer
36437            21: 'x-mac-thai',
36438            // smThai
36439            22: 'x-mac-lao',
36440            // smLao
36441            23: 'x-mac-georgian',
36442            // smGeorgian
36443            24: 'x-mac-armenian',
36444            // smArmenian
36445            25: 'x-mac-chinesesimp',
36446            // smSimpChinese
36447            26: 'x-mac-tibetan',
36448            // smTibetan
36449            27: 'x-mac-mongolian',
36450            // smMongolian
36451            28: 'x-mac-ethiopic',
36452            // smEthiopic
36453            29: 'x-mac-ce',
36454            // smCentralEuroRoman
36455            30: 'x-mac-vietnamese',
36456            // smVietnamese
36457            31: 'x-mac-extarabic' // smExtArabic
36458
36459          }; // MacOS language ID → encoding. This table stores the exceptional
36460          // cases, which override macScriptEncodings. For writing MacOS naming
36461          // tables, we need to emit a MacOS script ID. Therefore, we cannot
36462          // merge macScriptEncodings into macLanguageEncodings.
36463          //
36464          // http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt
36465
36466          var macLanguageEncodings = {
36467            15: 'x-mac-icelandic',
36468            // langIcelandic
36469            17: 'x-mac-turkish',
36470            // langTurkish
36471            18: 'x-mac-croatian',
36472            // langCroatian
36473            24: 'x-mac-ce',
36474            // langLithuanian
36475            25: 'x-mac-ce',
36476            // langPolish
36477            26: 'x-mac-ce',
36478            // langHungarian
36479            27: 'x-mac-ce',
36480            // langEstonian
36481            28: 'x-mac-ce',
36482            // langLatvian
36483            30: 'x-mac-icelandic',
36484            // langFaroese
36485            37: 'x-mac-romanian',
36486            // langRomanian
36487            38: 'x-mac-ce',
36488            // langCzech
36489            39: 'x-mac-ce',
36490            // langSlovak
36491            40: 'x-mac-ce',
36492            // langSlovenian
36493            143: 'x-mac-inuit',
36494            // langInuktitut
36495            146: 'x-mac-gaelic' // langIrishGaelicScript
36496
36497          };
36498
36499          function getEncoding(platformID, encodingID, languageID) {
36500            switch (platformID) {
36501              case 0:
36502                // Unicode
36503                return utf16;
36504
36505              case 1:
36506                // Apple Macintosh
36507                return macLanguageEncodings[languageID] || macScriptEncodings[encodingID];
36508
36509              case 3:
36510                // Microsoft Windows
36511                if (encodingID === 1 || encodingID === 10) {
36512                  return utf16;
36513                }
36514
36515                break;
36516            }
36517
36518            return undefined;
36519          } // Parse the naming `name` table.
36520          // FIXME: Format 1 additional fields are not supported yet.
36521          // ltag is the content of the `ltag' table, such as ['en', 'zh-Hans', 'de-CH-1904'].
36522
36523
36524          function parseNameTable(data, start, ltag) {
36525            var name = {};
36526            var p = new parse.Parser(data, start);
36527            var format = p.parseUShort();
36528            var count = p.parseUShort();
36529            var stringOffset = p.offset + p.parseUShort();
36530
36531            for (var i = 0; i < count; i++) {
36532              var platformID = p.parseUShort();
36533              var encodingID = p.parseUShort();
36534              var languageID = p.parseUShort();
36535              var nameID = p.parseUShort();
36536              var property = nameTableNames[nameID] || nameID;
36537              var byteLength = p.parseUShort();
36538              var offset = p.parseUShort();
36539              var language = getLanguageCode(platformID, languageID, ltag);
36540              var encoding = getEncoding(platformID, encodingID, languageID);
36541
36542              if (encoding !== undefined && language !== undefined) {
36543                var text = void 0;
36544
36545                if (encoding === utf16) {
36546                  text = decode.UTF16(data, stringOffset + offset, byteLength);
36547                } else {
36548                  text = decode.MACSTRING(data, stringOffset + offset, byteLength, encoding);
36549                }
36550
36551                if (text) {
36552                  var translations = name[property];
36553
36554                  if (translations === undefined) {
36555                    translations = name[property] = {};
36556                  }
36557
36558                  translations[language] = text;
36559                }
36560              }
36561            }
36562
36563            var langTagCount = 0;
36564
36565            if (format === 1) {
36566              // FIXME: Also handle Microsoft's 'name' table 1.
36567              langTagCount = p.parseUShort();
36568            }
36569
36570            return name;
36571          } // {23: 'foo'} → {'foo': 23}
36572          // ['bar', 'baz'] → {'bar': 0, 'baz': 1}
36573
36574
36575          function reverseDict(dict) {
36576            var result = {};
36577
36578            for (var key in dict) {
36579              result[dict[key]] = parseInt(key);
36580            }
36581
36582            return result;
36583          }
36584
36585          function makeNameRecord(platformID, encodingID, languageID, nameID, length, offset) {
36586            return new table.Record('NameRecord', [{
36587              name: 'platformID',
36588              type: 'USHORT',
36589              value: platformID
36590            }, {
36591              name: 'encodingID',
36592              type: 'USHORT',
36593              value: encodingID
36594            }, {
36595              name: 'languageID',
36596              type: 'USHORT',
36597              value: languageID
36598            }, {
36599              name: 'nameID',
36600              type: 'USHORT',
36601              value: nameID
36602            }, {
36603              name: 'length',
36604              type: 'USHORT',
36605              value: length
36606            }, {
36607              name: 'offset',
36608              type: 'USHORT',
36609              value: offset
36610            }]);
36611          } // Finds the position of needle in haystack, or -1 if not there.
36612          // Like String.indexOf(), but for arrays.
36613
36614
36615          function findSubArray(needle, haystack) {
36616            var needleLength = needle.length;
36617            var limit = haystack.length - needleLength + 1;
36618
36619            loop: for (var pos = 0; pos < limit; pos++) {
36620              for (; pos < limit; pos++) {
36621                for (var k = 0; k < needleLength; k++) {
36622                  if (haystack[pos + k] !== needle[k]) {
36623                    continue loop;
36624                  }
36625                }
36626
36627                return pos;
36628              }
36629            }
36630
36631            return -1;
36632          }
36633
36634          function addStringToPool(s, pool) {
36635            var offset = findSubArray(s, pool);
36636
36637            if (offset < 0) {
36638              offset = pool.length;
36639              var i = 0;
36640              var len = s.length;
36641
36642              for (; i < len; ++i) {
36643                pool.push(s[i]);
36644              }
36645            }
36646
36647            return offset;
36648          }
36649
36650          function makeNameTable(names, ltag) {
36651            var nameID;
36652            var nameIDs = [];
36653            var namesWithNumericKeys = {};
36654            var nameTableIds = reverseDict(nameTableNames);
36655
36656            for (var key in names) {
36657              var id = nameTableIds[key];
36658
36659              if (id === undefined) {
36660                id = key;
36661              }
36662
36663              nameID = parseInt(id);
36664
36665              if (isNaN(nameID)) {
36666                throw new Error('Name table entry "' + key + '" does not exist, see nameTableNames for complete list.');
36667              }
36668
36669              namesWithNumericKeys[nameID] = names[key];
36670              nameIDs.push(nameID);
36671            }
36672
36673            var macLanguageIds = reverseDict(macLanguages);
36674            var windowsLanguageIds = reverseDict(windowsLanguages);
36675            var nameRecords = [];
36676            var stringPool = [];
36677
36678            for (var i = 0; i < nameIDs.length; i++) {
36679              nameID = nameIDs[i];
36680              var translations = namesWithNumericKeys[nameID];
36681
36682              for (var lang in translations) {
36683                var text = translations[lang]; // For MacOS, we try to emit the name in the form that was introduced
36684                // in the initial version of the TrueType spec (in the late 1980s).
36685                // However, this can fail for various reasons: the requested BCP 47
36686                // language code might not have an old-style Mac equivalent;
36687                // we might not have a codec for the needed character encoding;
36688                // or the name might contain characters that cannot be expressed
36689                // in the old-style Macintosh encoding. In case of failure, we emit
36690                // the name in a more modern fashion (Unicode encoding with BCP 47
36691                // language tags) that is recognized by MacOS 10.5, released in 2009.
36692                // If fonts were only read by operating systems, we could simply
36693                // emit all names in the modern form; this would be much easier.
36694                // However, there are many applications and libraries that read
36695                // 'name' tables directly, and these will usually only recognize
36696                // the ancient form (silently skipping the unrecognized names).
36697
36698                var macPlatform = 1; // Macintosh
36699
36700                var macLanguage = macLanguageIds[lang];
36701                var macScript = macLanguageToScript[macLanguage];
36702                var macEncoding = getEncoding(macPlatform, macScript, macLanguage);
36703                var macName = encode.MACSTRING(text, macEncoding);
36704
36705                if (macName === undefined) {
36706                  macPlatform = 0; // Unicode
36707
36708                  macLanguage = ltag.indexOf(lang);
36709
36710                  if (macLanguage < 0) {
36711                    macLanguage = ltag.length;
36712                    ltag.push(lang);
36713                  }
36714
36715                  macScript = 4; // Unicode 2.0 and later
36716
36717                  macName = encode.UTF16(text);
36718                }
36719
36720                var macNameOffset = addStringToPool(macName, stringPool);
36721                nameRecords.push(makeNameRecord(macPlatform, macScript, macLanguage, nameID, macName.length, macNameOffset));
36722                var winLanguage = windowsLanguageIds[lang];
36723
36724                if (winLanguage !== undefined) {
36725                  var winName = encode.UTF16(text);
36726                  var winNameOffset = addStringToPool(winName, stringPool);
36727                  nameRecords.push(makeNameRecord(3, 1, winLanguage, nameID, winName.length, winNameOffset));
36728                }
36729              }
36730            }
36731
36732            nameRecords.sort(function (a, b) {
36733              return a.platformID - b.platformID || a.encodingID - b.encodingID || a.languageID - b.languageID || a.nameID - b.nameID;
36734            });
36735            var t = new table.Table('name', [{
36736              name: 'format',
36737              type: 'USHORT',
36738              value: 0
36739            }, {
36740              name: 'count',
36741              type: 'USHORT',
36742              value: nameRecords.length
36743            }, {
36744              name: 'stringOffset',
36745              type: 'USHORT',
36746              value: 6 + nameRecords.length * 12
36747            }]);
36748
36749            for (var r = 0; r < nameRecords.length; r++) {
36750              t.fields.push({
36751                name: 'record_' + r,
36752                type: 'RECORD',
36753                value: nameRecords[r]
36754              });
36755            }
36756
36757            t.fields.push({
36758              name: 'strings',
36759              type: 'LITERAL',
36760              value: stringPool
36761            });
36762            return t;
36763          }
36764
36765          var _name = {
36766            parse: parseNameTable,
36767            make: makeNameTable
36768          }; // The `OS/2` table contains metrics required in OpenType fonts.
36769
36770          var unicodeRanges = [{
36771            begin: 0x0000,
36772            end: 0x007F
36773          }, // Basic Latin
36774          {
36775            begin: 0x0080,
36776            end: 0x00FF
36777          }, // Latin-1 Supplement
36778          {
36779            begin: 0x0100,
36780            end: 0x017F
36781          }, // Latin Extended-A
36782          {
36783            begin: 0x0180,
36784            end: 0x024F
36785          }, // Latin Extended-B
36786          {
36787            begin: 0x0250,
36788            end: 0x02AF
36789          }, // IPA Extensions
36790          {
36791            begin: 0x02B0,
36792            end: 0x02FF
36793          }, // Spacing Modifier Letters
36794          {
36795            begin: 0x0300,
36796            end: 0x036F
36797          }, // Combining Diacritical Marks
36798          {
36799            begin: 0x0370,
36800            end: 0x03FF
36801          }, // Greek and Coptic
36802          {
36803            begin: 0x2C80,
36804            end: 0x2CFF
36805          }, // Coptic
36806          {
36807            begin: 0x0400,
36808            end: 0x04FF
36809          }, // Cyrillic
36810          {
36811            begin: 0x0530,
36812            end: 0x058F
36813          }, // Armenian
36814          {
36815            begin: 0x0590,
36816            end: 0x05FF
36817          }, // Hebrew
36818          {
36819            begin: 0xA500,
36820            end: 0xA63F
36821          }, // Vai
36822          {
36823            begin: 0x0600,
36824            end: 0x06FF
36825          }, // Arabic
36826          {
36827            begin: 0x07C0,
36828            end: 0x07FF
36829          }, // NKo
36830          {
36831            begin: 0x0900,
36832            end: 0x097F
36833          }, // Devanagari
36834          {
36835            begin: 0x0980,
36836            end: 0x09FF
36837          }, // Bengali
36838          {
36839            begin: 0x0A00,
36840            end: 0x0A7F
36841          }, // Gurmukhi
36842          {
36843            begin: 0x0A80,
36844            end: 0x0AFF
36845          }, // Gujarati
36846          {
36847            begin: 0x0B00,
36848            end: 0x0B7F
36849          }, // Oriya
36850          {
36851            begin: 0x0B80,
36852            end: 0x0BFF
36853          }, // Tamil
36854          {
36855            begin: 0x0C00,
36856            end: 0x0C7F
36857          }, // Telugu
36858          {
36859            begin: 0x0C80,
36860            end: 0x0CFF
36861          }, // Kannada
36862          {
36863            begin: 0x0D00,
36864            end: 0x0D7F
36865          }, // Malayalam
36866          {
36867            begin: 0x0E00,
36868            end: 0x0E7F
36869          }, // Thai
36870          {
36871            begin: 0x0E80,
36872            end: 0x0EFF
36873          }, // Lao
36874          {
36875            begin: 0x10A0,
36876            end: 0x10FF
36877          }, // Georgian
36878          {
36879            begin: 0x1B00,
36880            end: 0x1B7F
36881          }, // Balinese
36882          {
36883            begin: 0x1100,
36884            end: 0x11FF
36885          }, // Hangul Jamo
36886          {
36887            begin: 0x1E00,
36888            end: 0x1EFF
36889          }, // Latin Extended Additional
36890          {
36891            begin: 0x1F00,
36892            end: 0x1FFF
36893          }, // Greek Extended
36894          {
36895            begin: 0x2000,
36896            end: 0x206F
36897          }, // General Punctuation
36898          {
36899            begin: 0x2070,
36900            end: 0x209F
36901          }, // Superscripts And Subscripts
36902          {
36903            begin: 0x20A0,
36904            end: 0x20CF
36905          }, // Currency Symbol
36906          {
36907            begin: 0x20D0,
36908            end: 0x20FF
36909          }, // Combining Diacritical Marks For Symbols
36910          {
36911            begin: 0x2100,
36912            end: 0x214F
36913          }, // Letterlike Symbols
36914          {
36915            begin: 0x2150,
36916            end: 0x218F
36917          }, // Number Forms
36918          {
36919            begin: 0x2190,
36920            end: 0x21FF
36921          }, // Arrows
36922          {
36923            begin: 0x2200,
36924            end: 0x22FF
36925          }, // Mathematical Operators
36926          {
36927            begin: 0x2300,
36928            end: 0x23FF
36929          }, // Miscellaneous Technical
36930          {
36931            begin: 0x2400,
36932            end: 0x243F
36933          }, // Control Pictures
36934          {
36935            begin: 0x2440,
36936            end: 0x245F
36937          }, // Optical Character Recognition
36938          {
36939            begin: 0x2460,
36940            end: 0x24FF
36941          }, // Enclosed Alphanumerics
36942          {
36943            begin: 0x2500,
36944            end: 0x257F
36945          }, // Box Drawing
36946          {
36947            begin: 0x2580,
36948            end: 0x259F
36949          }, // Block Elements
36950          {
36951            begin: 0x25A0,
36952            end: 0x25FF
36953          }, // Geometric Shapes
36954          {
36955            begin: 0x2600,
36956            end: 0x26FF
36957          }, // Miscellaneous Symbols
36958          {
36959            begin: 0x2700,
36960            end: 0x27BF
36961          }, // Dingbats
36962          {
36963            begin: 0x3000,
36964            end: 0x303F
36965          }, // CJK Symbols And Punctuation
36966          {
36967            begin: 0x3040,
36968            end: 0x309F
36969          }, // Hiragana
36970          {
36971            begin: 0x30A0,
36972            end: 0x30FF
36973          }, // Katakana
36974          {
36975            begin: 0x3100,
36976            end: 0x312F
36977          }, // Bopomofo
36978          {
36979            begin: 0x3130,
36980            end: 0x318F
36981          }, // Hangul Compatibility Jamo
36982          {
36983            begin: 0xA840,
36984            end: 0xA87F
36985          }, // Phags-pa
36986          {
36987            begin: 0x3200,
36988            end: 0x32FF
36989          }, // Enclosed CJK Letters And Months
36990          {
36991            begin: 0x3300,
36992            end: 0x33FF
36993          }, // CJK Compatibility
36994          {
36995            begin: 0xAC00,
36996            end: 0xD7AF
36997          }, // Hangul Syllables
36998          {
36999            begin: 0xD800,
37000            end: 0xDFFF
37001          }, // Non-Plane 0 *
37002          {
37003            begin: 0x10900,
37004            end: 0x1091F
37005          }, // Phoenicia
37006          {
37007            begin: 0x4E00,
37008            end: 0x9FFF
37009          }, // CJK Unified Ideographs
37010          {
37011            begin: 0xE000,
37012            end: 0xF8FF
37013          }, // Private Use Area (plane 0)
37014          {
37015            begin: 0x31C0,
37016            end: 0x31EF
37017          }, // CJK Strokes
37018          {
37019            begin: 0xFB00,
37020            end: 0xFB4F
37021          }, // Alphabetic Presentation Forms
37022          {
37023            begin: 0xFB50,
37024            end: 0xFDFF
37025          }, // Arabic Presentation Forms-A
37026          {
37027            begin: 0xFE20,
37028            end: 0xFE2F
37029          }, // Combining Half Marks
37030          {
37031            begin: 0xFE10,
37032            end: 0xFE1F
37033          }, // Vertical Forms
37034          {
37035            begin: 0xFE50,
37036            end: 0xFE6F
37037          }, // Small Form Variants
37038          {
37039            begin: 0xFE70,
37040            end: 0xFEFF
37041          }, // Arabic Presentation Forms-B
37042          {
37043            begin: 0xFF00,
37044            end: 0xFFEF
37045          }, // Halfwidth And Fullwidth Forms
37046          {
37047            begin: 0xFFF0,
37048            end: 0xFFFF
37049          }, // Specials
37050          {
37051            begin: 0x0F00,
37052            end: 0x0FFF
37053          }, // Tibetan
37054          {
37055            begin: 0x0700,
37056            end: 0x074F
37057          }, // Syriac
37058          {
37059            begin: 0x0780,
37060            end: 0x07BF
37061          }, // Thaana
37062          {
37063            begin: 0x0D80,
37064            end: 0x0DFF
37065          }, // Sinhala
37066          {
37067            begin: 0x1000,
37068            end: 0x109F
37069          }, // Myanmar
37070          {
37071            begin: 0x1200,
37072            end: 0x137F
37073          }, // Ethiopic
37074          {
37075            begin: 0x13A0,
37076            end: 0x13FF
37077          }, // Cherokee
37078          {
37079            begin: 0x1400,
37080            end: 0x167F
37081          }, // Unified Canadian Aboriginal Syllabics
37082          {
37083            begin: 0x1680,
37084            end: 0x169F
37085          }, // Ogham
37086          {
37087            begin: 0x16A0,
37088            end: 0x16FF
37089          }, // Runic
37090          {
37091            begin: 0x1780,
37092            end: 0x17FF
37093          }, // Khmer
37094          {
37095            begin: 0x1800,
37096            end: 0x18AF
37097          }, // Mongolian
37098          {
37099            begin: 0x2800,
37100            end: 0x28FF
37101          }, // Braille Patterns
37102          {
37103            begin: 0xA000,
37104            end: 0xA48F
37105          }, // Yi Syllables
37106          {
37107            begin: 0x1700,
37108            end: 0x171F
37109          }, // Tagalog
37110          {
37111            begin: 0x10300,
37112            end: 0x1032F
37113          }, // Old Italic
37114          {
37115            begin: 0x10330,
37116            end: 0x1034F
37117          }, // Gothic
37118          {
37119            begin: 0x10400,
37120            end: 0x1044F
37121          }, // Deseret
37122          {
37123            begin: 0x1D000,
37124            end: 0x1D0FF
37125          }, // Byzantine Musical Symbols
37126          {
37127            begin: 0x1D400,
37128            end: 0x1D7FF
37129          }, // Mathematical Alphanumeric Symbols
37130          {
37131            begin: 0xFF000,
37132            end: 0xFFFFD
37133          }, // Private Use (plane 15)
37134          {
37135            begin: 0xFE00,
37136            end: 0xFE0F
37137          }, // Variation Selectors
37138          {
37139            begin: 0xE0000,
37140            end: 0xE007F
37141          }, // Tags
37142          {
37143            begin: 0x1900,
37144            end: 0x194F
37145          }, // Limbu
37146          {
37147            begin: 0x1950,
37148            end: 0x197F
37149          }, // Tai Le
37150          {
37151            begin: 0x1980,
37152            end: 0x19DF
37153          }, // New Tai Lue
37154          {
37155            begin: 0x1A00,
37156            end: 0x1A1F
37157          }, // Buginese
37158          {
37159            begin: 0x2C00,
37160            end: 0x2C5F
37161          }, // Glagolitic
37162          {
37163            begin: 0x2D30,
37164            end: 0x2D7F
37165          }, // Tifinagh
37166          {
37167            begin: 0x4DC0,
37168            end: 0x4DFF
37169          }, // Yijing Hexagram Symbols
37170          {
37171            begin: 0xA800,
37172            end: 0xA82F
37173          }, // Syloti Nagri
37174          {
37175            begin: 0x10000,
37176            end: 0x1007F
37177          }, // Linear B Syllabary
37178          {
37179            begin: 0x10140,
37180            end: 0x1018F
37181          }, // Ancient Greek Numbers
37182          {
37183            begin: 0x10380,
37184            end: 0x1039F
37185          }, // Ugaritic
37186          {
37187            begin: 0x103A0,
37188            end: 0x103DF
37189          }, // Old Persian
37190          {
37191            begin: 0x10450,
37192            end: 0x1047F
37193          }, // Shavian
37194          {
37195            begin: 0x10480,
37196            end: 0x104AF
37197          }, // Osmanya
37198          {
37199            begin: 0x10800,
37200            end: 0x1083F
37201          }, // Cypriot Syllabary
37202          {
37203            begin: 0x10A00,
37204            end: 0x10A5F
37205          }, // Kharoshthi
37206          {
37207            begin: 0x1D300,
37208            end: 0x1D35F
37209          }, // Tai Xuan Jing Symbols
37210          {
37211            begin: 0x12000,
37212            end: 0x123FF
37213          }, // Cuneiform
37214          {
37215            begin: 0x1D360,
37216            end: 0x1D37F
37217          }, // Counting Rod Numerals
37218          {
37219            begin: 0x1B80,
37220            end: 0x1BBF
37221          }, // Sundanese
37222          {
37223            begin: 0x1C00,
37224            end: 0x1C4F
37225          }, // Lepcha
37226          {
37227            begin: 0x1C50,
37228            end: 0x1C7F
37229          }, // Ol Chiki
37230          {
37231            begin: 0xA880,
37232            end: 0xA8DF
37233          }, // Saurashtra
37234          {
37235            begin: 0xA900,
37236            end: 0xA92F
37237          }, // Kayah Li
37238          {
37239            begin: 0xA930,
37240            end: 0xA95F
37241          }, // Rejang
37242          {
37243            begin: 0xAA00,
37244            end: 0xAA5F
37245          }, // Cham
37246          {
37247            begin: 0x10190,
37248            end: 0x101CF
37249          }, // Ancient Symbols
37250          {
37251            begin: 0x101D0,
37252            end: 0x101FF
37253          }, // Phaistos Disc
37254          {
37255            begin: 0x102A0,
37256            end: 0x102DF
37257          }, // Carian
37258          {
37259            begin: 0x1F030,
37260            end: 0x1F09F // Domino Tiles
37261
37262          }];
37263
37264          function getUnicodeRange(unicode) {
37265            for (var i = 0; i < unicodeRanges.length; i += 1) {
37266              var range = unicodeRanges[i];
37267
37268              if (unicode >= range.begin && unicode < range.end) {
37269                return i;
37270              }
37271            }
37272
37273            return -1;
37274          } // Parse the OS/2 and Windows metrics `OS/2` table
37275
37276
37277          function parseOS2Table(data, start) {
37278            var os2 = {};
37279            var p = new parse.Parser(data, start);
37280            os2.version = p.parseUShort();
37281            os2.xAvgCharWidth = p.parseShort();
37282            os2.usWeightClass = p.parseUShort();
37283            os2.usWidthClass = p.parseUShort();
37284            os2.fsType = p.parseUShort();
37285            os2.ySubscriptXSize = p.parseShort();
37286            os2.ySubscriptYSize = p.parseShort();
37287            os2.ySubscriptXOffset = p.parseShort();
37288            os2.ySubscriptYOffset = p.parseShort();
37289            os2.ySuperscriptXSize = p.parseShort();
37290            os2.ySuperscriptYSize = p.parseShort();
37291            os2.ySuperscriptXOffset = p.parseShort();
37292            os2.ySuperscriptYOffset = p.parseShort();
37293            os2.yStrikeoutSize = p.parseShort();
37294            os2.yStrikeoutPosition = p.parseShort();
37295            os2.sFamilyClass = p.parseShort();
37296            os2.panose = [];
37297
37298            for (var i = 0; i < 10; i++) {
37299              os2.panose[i] = p.parseByte();
37300            }
37301
37302            os2.ulUnicodeRange1 = p.parseULong();
37303            os2.ulUnicodeRange2 = p.parseULong();
37304            os2.ulUnicodeRange3 = p.parseULong();
37305            os2.ulUnicodeRange4 = p.parseULong();
37306            os2.achVendID = String.fromCharCode(p.parseByte(), p.parseByte(), p.parseByte(), p.parseByte());
37307            os2.fsSelection = p.parseUShort();
37308            os2.usFirstCharIndex = p.parseUShort();
37309            os2.usLastCharIndex = p.parseUShort();
37310            os2.sTypoAscender = p.parseShort();
37311            os2.sTypoDescender = p.parseShort();
37312            os2.sTypoLineGap = p.parseShort();
37313            os2.usWinAscent = p.parseUShort();
37314            os2.usWinDescent = p.parseUShort();
37315
37316            if (os2.version >= 1) {
37317              os2.ulCodePageRange1 = p.parseULong();
37318              os2.ulCodePageRange2 = p.parseULong();
37319            }
37320
37321            if (os2.version >= 2) {
37322              os2.sxHeight = p.parseShort();
37323              os2.sCapHeight = p.parseShort();
37324              os2.usDefaultChar = p.parseUShort();
37325              os2.usBreakChar = p.parseUShort();
37326              os2.usMaxContent = p.parseUShort();
37327            }
37328
37329            return os2;
37330          }
37331
37332          function makeOS2Table(options) {
37333            return new table.Table('OS/2', [{
37334              name: 'version',
37335              type: 'USHORT',
37336              value: 0x0003
37337            }, {
37338              name: 'xAvgCharWidth',
37339              type: 'SHORT',
37340              value: 0
37341            }, {
37342              name: 'usWeightClass',
37343              type: 'USHORT',
37344              value: 0
37345            }, {
37346              name: 'usWidthClass',
37347              type: 'USHORT',
37348              value: 0
37349            }, {
37350              name: 'fsType',
37351              type: 'USHORT',
37352              value: 0
37353            }, {
37354              name: 'ySubscriptXSize',
37355              type: 'SHORT',
37356              value: 650
37357            }, {
37358              name: 'ySubscriptYSize',
37359              type: 'SHORT',
37360              value: 699
37361            }, {
37362              name: 'ySubscriptXOffset',
37363              type: 'SHORT',
37364              value: 0
37365            }, {
37366              name: 'ySubscriptYOffset',
37367              type: 'SHORT',
37368              value: 140
37369            }, {
37370              name: 'ySuperscriptXSize',
37371              type: 'SHORT',
37372              value: 650
37373            }, {
37374              name: 'ySuperscriptYSize',
37375              type: 'SHORT',
37376              value: 699
37377            }, {
37378              name: 'ySuperscriptXOffset',
37379              type: 'SHORT',
37380              value: 0
37381            }, {
37382              name: 'ySuperscriptYOffset',
37383              type: 'SHORT',
37384              value: 479
37385            }, {
37386              name: 'yStrikeoutSize',
37387              type: 'SHORT',
37388              value: 49
37389            }, {
37390              name: 'yStrikeoutPosition',
37391              type: 'SHORT',
37392              value: 258
37393            }, {
37394              name: 'sFamilyClass',
37395              type: 'SHORT',
37396              value: 0
37397            }, {
37398              name: 'bFamilyType',
37399              type: 'BYTE',
37400              value: 0
37401            }, {
37402              name: 'bSerifStyle',
37403              type: 'BYTE',
37404              value: 0
37405            }, {
37406              name: 'bWeight',
37407              type: 'BYTE',
37408              value: 0
37409            }, {
37410              name: 'bProportion',
37411              type: 'BYTE',
37412              value: 0
37413            }, {
37414              name: 'bContrast',
37415              type: 'BYTE',
37416              value: 0
37417            }, {
37418              name: 'bStrokeVariation',
37419              type: 'BYTE',
37420              value: 0
37421            }, {
37422              name: 'bArmStyle',
37423              type: 'BYTE',
37424              value: 0
37425            }, {
37426              name: 'bLetterform',
37427              type: 'BYTE',
37428              value: 0
37429            }, {
37430              name: 'bMidline',
37431              type: 'BYTE',
37432              value: 0
37433            }, {
37434              name: 'bXHeight',
37435              type: 'BYTE',
37436              value: 0
37437            }, {
37438              name: 'ulUnicodeRange1',
37439              type: 'ULONG',
37440              value: 0
37441            }, {
37442              name: 'ulUnicodeRange2',
37443              type: 'ULONG',
37444              value: 0
37445            }, {
37446              name: 'ulUnicodeRange3',
37447              type: 'ULONG',
37448              value: 0
37449            }, {
37450              name: 'ulUnicodeRange4',
37451              type: 'ULONG',
37452              value: 0
37453            }, {
37454              name: 'achVendID',
37455              type: 'CHARARRAY',
37456              value: 'XXXX'
37457            }, {
37458              name: 'fsSelection',
37459              type: 'USHORT',
37460              value: 0
37461            }, {
37462              name: 'usFirstCharIndex',
37463              type: 'USHORT',
37464              value: 0
37465            }, {
37466              name: 'usLastCharIndex',
37467              type: 'USHORT',
37468              value: 0
37469            }, {
37470              name: 'sTypoAscender',
37471              type: 'SHORT',
37472              value: 0
37473            }, {
37474              name: 'sTypoDescender',
37475              type: 'SHORT',
37476              value: 0
37477            }, {
37478              name: 'sTypoLineGap',
37479              type: 'SHORT',
37480              value: 0
37481            }, {
37482              name: 'usWinAscent',
37483              type: 'USHORT',
37484              value: 0
37485            }, {
37486              name: 'usWinDescent',
37487              type: 'USHORT',
37488              value: 0
37489            }, {
37490              name: 'ulCodePageRange1',
37491              type: 'ULONG',
37492              value: 0
37493            }, {
37494              name: 'ulCodePageRange2',
37495              type: 'ULONG',
37496              value: 0
37497            }, {
37498              name: 'sxHeight',
37499              type: 'SHORT',
37500              value: 0
37501            }, {
37502              name: 'sCapHeight',
37503              type: 'SHORT',
37504              value: 0
37505            }, {
37506              name: 'usDefaultChar',
37507              type: 'USHORT',
37508              value: 0
37509            }, {
37510              name: 'usBreakChar',
37511              type: 'USHORT',
37512              value: 0
37513            }, {
37514              name: 'usMaxContext',
37515              type: 'USHORT',
37516              value: 0
37517            }], options);
37518          }
37519
37520          var os2 = {
37521            parse: parseOS2Table,
37522            make: makeOS2Table,
37523            unicodeRanges: unicodeRanges,
37524            getUnicodeRange: getUnicodeRange
37525          }; // The `post` table stores additional PostScript information, such as glyph names.
37526          // Parse the PostScript `post` table
37527
37528          function parsePostTable(data, start) {
37529            var post = {};
37530            var p = new parse.Parser(data, start);
37531            post.version = p.parseVersion();
37532            post.italicAngle = p.parseFixed();
37533            post.underlinePosition = p.parseShort();
37534            post.underlineThickness = p.parseShort();
37535            post.isFixedPitch = p.parseULong();
37536            post.minMemType42 = p.parseULong();
37537            post.maxMemType42 = p.parseULong();
37538            post.minMemType1 = p.parseULong();
37539            post.maxMemType1 = p.parseULong();
37540
37541            switch (post.version) {
37542              case 1:
37543                post.names = standardNames.slice();
37544                break;
37545
37546              case 2:
37547                post.numberOfGlyphs = p.parseUShort();
37548                post.glyphNameIndex = new Array(post.numberOfGlyphs);
37549
37550                for (var i = 0; i < post.numberOfGlyphs; i++) {
37551                  post.glyphNameIndex[i] = p.parseUShort();
37552                }
37553
37554                post.names = [];
37555
37556                for (var i$1 = 0; i$1 < post.numberOfGlyphs; i$1++) {
37557                  if (post.glyphNameIndex[i$1] >= standardNames.length) {
37558                    var nameLength = p.parseChar();
37559                    post.names.push(p.parseString(nameLength));
37560                  }
37561                }
37562
37563                break;
37564
37565              case 2.5:
37566                post.numberOfGlyphs = p.parseUShort();
37567                post.offset = new Array(post.numberOfGlyphs);
37568
37569                for (var i$2 = 0; i$2 < post.numberOfGlyphs; i$2++) {
37570                  post.offset[i$2] = p.parseChar();
37571                }
37572
37573                break;
37574            }
37575
37576            return post;
37577          }
37578
37579          function makePostTable() {
37580            return new table.Table('post', [{
37581              name: 'version',
37582              type: 'FIXED',
37583              value: 0x00030000
37584            }, {
37585              name: 'italicAngle',
37586              type: 'FIXED',
37587              value: 0
37588            }, {
37589              name: 'underlinePosition',
37590              type: 'FWORD',
37591              value: 0
37592            }, {
37593              name: 'underlineThickness',
37594              type: 'FWORD',
37595              value: 0
37596            }, {
37597              name: 'isFixedPitch',
37598              type: 'ULONG',
37599              value: 0
37600            }, {
37601              name: 'minMemType42',
37602              type: 'ULONG',
37603              value: 0
37604            }, {
37605              name: 'maxMemType42',
37606              type: 'ULONG',
37607              value: 0
37608            }, {
37609              name: 'minMemType1',
37610              type: 'ULONG',
37611              value: 0
37612            }, {
37613              name: 'maxMemType1',
37614              type: 'ULONG',
37615              value: 0
37616            }]);
37617          }
37618
37619          var post = {
37620            parse: parsePostTable,
37621            make: makePostTable
37622          }; // The `GSUB` table contains ligatures, among other things.
37623
37624          var subtableParsers = new Array(9); // subtableParsers[0] is unused
37625          // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#SS
37626
37627          subtableParsers[1] = function parseLookup1() {
37628            var start = this.offset + this.relativeOffset;
37629            var substFormat = this.parseUShort();
37630
37631            if (substFormat === 1) {
37632              return {
37633                substFormat: 1,
37634                coverage: this.parsePointer(Parser.coverage),
37635                deltaGlyphId: this.parseUShort()
37636              };
37637            } else if (substFormat === 2) {
37638              return {
37639                substFormat: 2,
37640                coverage: this.parsePointer(Parser.coverage),
37641                substitute: this.parseOffset16List()
37642              };
37643            }
37644
37645            check.assert(false, '0x' + start.toString(16) + ': lookup type 1 format must be 1 or 2.');
37646          }; // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#MS
37647
37648
37649          subtableParsers[2] = function parseLookup2() {
37650            var substFormat = this.parseUShort();
37651            check.argument(substFormat === 1, 'GSUB Multiple Substitution Subtable identifier-format must be 1');
37652            return {
37653              substFormat: substFormat,
37654              coverage: this.parsePointer(Parser.coverage),
37655              sequences: this.parseListOfLists()
37656            };
37657          }; // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#AS
37658
37659
37660          subtableParsers[3] = function parseLookup3() {
37661            var substFormat = this.parseUShort();
37662            check.argument(substFormat === 1, 'GSUB Alternate Substitution Subtable identifier-format must be 1');
37663            return {
37664              substFormat: substFormat,
37665              coverage: this.parsePointer(Parser.coverage),
37666              alternateSets: this.parseListOfLists()
37667            };
37668          }; // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#LS
37669
37670
37671          subtableParsers[4] = function parseLookup4() {
37672            var substFormat = this.parseUShort();
37673            check.argument(substFormat === 1, 'GSUB ligature table identifier-format must be 1');
37674            return {
37675              substFormat: substFormat,
37676              coverage: this.parsePointer(Parser.coverage),
37677              ligatureSets: this.parseListOfLists(function () {
37678                return {
37679                  ligGlyph: this.parseUShort(),
37680                  components: this.parseUShortList(this.parseUShort() - 1)
37681                };
37682              })
37683            };
37684          };
37685
37686          var lookupRecordDesc = {
37687            sequenceIndex: Parser.uShort,
37688            lookupListIndex: Parser.uShort
37689          }; // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CSF
37690
37691          subtableParsers[5] = function parseLookup5() {
37692            var start = this.offset + this.relativeOffset;
37693            var substFormat = this.parseUShort();
37694
37695            if (substFormat === 1) {
37696              return {
37697                substFormat: substFormat,
37698                coverage: this.parsePointer(Parser.coverage),
37699                ruleSets: this.parseListOfLists(function () {
37700                  var glyphCount = this.parseUShort();
37701                  var substCount = this.parseUShort();
37702                  return {
37703                    input: this.parseUShortList(glyphCount - 1),
37704                    lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)
37705                  };
37706                })
37707              };
37708            } else if (substFormat === 2) {
37709              return {
37710                substFormat: substFormat,
37711                coverage: this.parsePointer(Parser.coverage),
37712                classDef: this.parsePointer(Parser.classDef),
37713                classSets: this.parseListOfLists(function () {
37714                  var glyphCount = this.parseUShort();
37715                  var substCount = this.parseUShort();
37716                  return {
37717                    classes: this.parseUShortList(glyphCount - 1),
37718                    lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)
37719                  };
37720                })
37721              };
37722            } else if (substFormat === 3) {
37723              var glyphCount = this.parseUShort();
37724              var substCount = this.parseUShort();
37725              return {
37726                substFormat: substFormat,
37727                coverages: this.parseList(glyphCount, Parser.pointer(Parser.coverage)),
37728                lookupRecords: this.parseRecordList(substCount, lookupRecordDesc)
37729              };
37730            }
37731
37732            check.assert(false, '0x' + start.toString(16) + ': lookup type 5 format must be 1, 2 or 3.');
37733          }; // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#CC
37734
37735
37736          subtableParsers[6] = function parseLookup6() {
37737            var start = this.offset + this.relativeOffset;
37738            var substFormat = this.parseUShort();
37739
37740            if (substFormat === 1) {
37741              return {
37742                substFormat: 1,
37743                coverage: this.parsePointer(Parser.coverage),
37744                chainRuleSets: this.parseListOfLists(function () {
37745                  return {
37746                    backtrack: this.parseUShortList(),
37747                    input: this.parseUShortList(this.parseShort() - 1),
37748                    lookahead: this.parseUShortList(),
37749                    lookupRecords: this.parseRecordList(lookupRecordDesc)
37750                  };
37751                })
37752              };
37753            } else if (substFormat === 2) {
37754              return {
37755                substFormat: 2,
37756                coverage: this.parsePointer(Parser.coverage),
37757                backtrackClassDef: this.parsePointer(Parser.classDef),
37758                inputClassDef: this.parsePointer(Parser.classDef),
37759                lookaheadClassDef: this.parsePointer(Parser.classDef),
37760                chainClassSet: this.parseListOfLists(function () {
37761                  return {
37762                    backtrack: this.parseUShortList(),
37763                    input: this.parseUShortList(this.parseShort() - 1),
37764                    lookahead: this.parseUShortList(),
37765                    lookupRecords: this.parseRecordList(lookupRecordDesc)
37766                  };
37767                })
37768              };
37769            } else if (substFormat === 3) {
37770              return {
37771                substFormat: 3,
37772                backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)),
37773                inputCoverage: this.parseList(Parser.pointer(Parser.coverage)),
37774                lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)),
37775                lookupRecords: this.parseRecordList(lookupRecordDesc)
37776              };
37777            }
37778
37779            check.assert(false, '0x' + start.toString(16) + ': lookup type 6 format must be 1, 2 or 3.');
37780          }; // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#ES
37781
37782
37783          subtableParsers[7] = function parseLookup7() {
37784            // Extension Substitution subtable
37785            var substFormat = this.parseUShort();
37786            check.argument(substFormat === 1, 'GSUB Extension Substitution subtable identifier-format must be 1');
37787            var extensionLookupType = this.parseUShort();
37788            var extensionParser = new Parser(this.data, this.offset + this.parseULong());
37789            return {
37790              substFormat: 1,
37791              lookupType: extensionLookupType,
37792              extension: subtableParsers[extensionLookupType].call(extensionParser)
37793            };
37794          }; // https://www.microsoft.com/typography/OTSPEC/GSUB.htm#RCCS
37795
37796
37797          subtableParsers[8] = function parseLookup8() {
37798            var substFormat = this.parseUShort();
37799            check.argument(substFormat === 1, 'GSUB Reverse Chaining Contextual Single Substitution Subtable identifier-format must be 1');
37800            return {
37801              substFormat: substFormat,
37802              coverage: this.parsePointer(Parser.coverage),
37803              backtrackCoverage: this.parseList(Parser.pointer(Parser.coverage)),
37804              lookaheadCoverage: this.parseList(Parser.pointer(Parser.coverage)),
37805              substitutes: this.parseUShortList()
37806            };
37807          }; // https://www.microsoft.com/typography/OTSPEC/gsub.htm
37808
37809
37810          function parseGsubTable(data, start) {
37811            start = start || 0;
37812            var p = new Parser(data, start);
37813            var tableVersion = p.parseVersion(1);
37814            check.argument(tableVersion === 1 || tableVersion === 1.1, 'Unsupported GSUB table version.');
37815
37816            if (tableVersion === 1) {
37817              return {
37818                version: tableVersion,
37819                scripts: p.parseScriptList(),
37820                features: p.parseFeatureList(),
37821                lookups: p.parseLookupList(subtableParsers)
37822              };
37823            } else {
37824              return {
37825                version: tableVersion,
37826                scripts: p.parseScriptList(),
37827                features: p.parseFeatureList(),
37828                lookups: p.parseLookupList(subtableParsers),
37829                variations: p.parseFeatureVariationsList()
37830              };
37831            }
37832          } // GSUB Writing //////////////////////////////////////////////
37833
37834
37835          var subtableMakers = new Array(9);
37836
37837          subtableMakers[1] = function makeLookup1(subtable) {
37838            if (subtable.substFormat === 1) {
37839              return new table.Table('substitutionTable', [{
37840                name: 'substFormat',
37841                type: 'USHORT',
37842                value: 1
37843              }, {
37844                name: 'coverage',
37845                type: 'TABLE',
37846                value: new table.Coverage(subtable.coverage)
37847              }, {
37848                name: 'deltaGlyphID',
37849                type: 'USHORT',
37850                value: subtable.deltaGlyphId
37851              }]);
37852            } else {
37853              return new table.Table('substitutionTable', [{
37854                name: 'substFormat',
37855                type: 'USHORT',
37856                value: 2
37857              }, {
37858                name: 'coverage',
37859                type: 'TABLE',
37860                value: new table.Coverage(subtable.coverage)
37861              }].concat(table.ushortList('substitute', subtable.substitute)));
37862            }
37863
37864            check.fail('Lookup type 1 substFormat must be 1 or 2.');
37865          };
37866
37867          subtableMakers[3] = function makeLookup3(subtable) {
37868            check.assert(subtable.substFormat === 1, 'Lookup type 3 substFormat must be 1.');
37869            return new table.Table('substitutionTable', [{
37870              name: 'substFormat',
37871              type: 'USHORT',
37872              value: 1
37873            }, {
37874              name: 'coverage',
37875              type: 'TABLE',
37876              value: new table.Coverage(subtable.coverage)
37877            }].concat(table.tableList('altSet', subtable.alternateSets, function (alternateSet) {
37878              return new table.Table('alternateSetTable', table.ushortList('alternate', alternateSet));
37879            })));
37880          };
37881
37882          subtableMakers[4] = function makeLookup4(subtable) {
37883            check.assert(subtable.substFormat === 1, 'Lookup type 4 substFormat must be 1.');
37884            return new table.Table('substitutionTable', [{
37885              name: 'substFormat',
37886              type: 'USHORT',
37887              value: 1
37888            }, {
37889              name: 'coverage',
37890              type: 'TABLE',
37891              value: new table.Coverage(subtable.coverage)
37892            }].concat(table.tableList('ligSet', subtable.ligatureSets, function (ligatureSet) {
37893              return new table.Table('ligatureSetTable', table.tableList('ligature', ligatureSet, function (ligature) {
37894                return new table.Table('ligatureTable', [{
37895                  name: 'ligGlyph',
37896                  type: 'USHORT',
37897                  value: ligature.ligGlyph
37898                }
37898].concat(table.ushortList('component', ligature.components, ligature.components.length + 1)));
37899              }));
37900            })));
37901          };
37902
37903          function makeGsubTable(gsub) {
37904            return new table.Table('GSUB', [{
37905              name: 'version',
37906              type: 'ULONG',
37907              value: 0x10000
37908            }, {
37909              name: 'scripts',
37910              type: 'TABLE',
37911              value: new table.ScriptList(gsub.scripts)
37912            }, {
37913              name: 'features',
37914              type: 'TABLE',
37915              value: new table.FeatureList(gsub.features)
37916            }, {
37917              name: 'lookups',
37918              type: 'TABLE',
37919              value: new table.LookupList(gsub.lookups, subtableMakers)
37920            }]);
37921          }
37922
37923          var gsub = {
37924            parse: parseGsubTable,
37925            make: makeGsubTable
37926          }; // The `GPOS` table contains kerning pairs, among other things.
37927          // Parse the metadata `meta` table.
37928          // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6meta.html
37929
37930          function parseMetaTable(data, start) {
37931            var p = new parse.Parser(data, start);
37932            var tableVersion = p.parseULong();
37933            check.argument(tableVersion === 1, 'Unsupported META table version.');
37934            p.parseULong(); // flags - currently unused and set to 0
37935
37936            p.parseULong(); // tableOffset
37937
37938            var numDataMaps = p.parseULong();
37939            var tags = {};
37940
37941            for (var i = 0; i < numDataMaps; i++) {
37942              var tag = p.parseTag();
37943              var dataOffset = p.parseULong();
37944              var dataLength = p.parseULong();
37945              var text = decode.UTF8(data, start + dataOffset, dataLength);
37946              tags[tag] = text;
37947            }
37948
37949            return tags;
37950          }
37951
37952          function makeMetaTable(tags) {
37953            var numTags = Object.keys(tags).length;
37954            var stringPool = '';
37955            var stringPoolOffset = 16 + numTags * 12;
37956            var result = new table.Table('meta', [{
37957              name: 'version',
37958              type: 'ULONG',
37959              value: 1
37960            }, {
37961              name: 'flags',
37962              type: 'ULONG',
37963              value: 0
37964            }, {
37965              name: 'offset',
37966              type: 'ULONG',
37967              value: stringPoolOffset
37968            }, {
37969              name: 'numTags',
37970              type: 'ULONG',
37971              value: numTags
37972            }]);
37973
37974            for (var tag in tags) {
37975              var pos = stringPool.length;
37976              stringPool += tags[tag];
37977              result.fields.push({
37978                name: 'tag ' + tag,
37979                type: 'TAG',
37980                value: tag
37981              });
37982              result.fields.push({
37983                name: 'offset ' + tag,
37984                type: 'ULONG',
37985                value: stringPoolOffset + pos
37986              });
37987              result.fields.push({
37988                name: 'length ' + tag,
37989                type: 'ULONG',
37990                value: tags[tag].length
37991              });
37992            }
37993
37994            result.fields.push({
37995              name: 'stringPool',
37996              type: 'CHARARRAY',
37997              value: stringPool
37998            });
37999            return result;
38000          }
38001
38002          var meta = {
38003            parse: parseMetaTable,
38004            make: makeMetaTable
38005          }; // The `sfnt` wrapper provides organization for the tables in the font.
38006
38007          function log2(v) {
38008            return Math.log(v) / Math.log(2) | 0;
38009          }
38010
38011          function computeCheckSum(bytes) {
38012            while (bytes.length % 4 !== 0) {
38013              bytes.push(0);
38014            }
38015
38016            var sum = 0;
38017
38018            for (var i = 0; i < bytes.length; i += 4) {
38019              sum += (bytes[i] << 24) + (bytes[i + 1] << 16) + (bytes[i + 2] << 8) + bytes[i + 3];
38020            }
38021
38022            sum %= Math.pow(2, 32);
38023            return sum;
38024          }
38025
38026          function makeTableRecord(tag, checkSum, offset, length) {
38027            return new table.Record('Table Record', [{
38028              name: 'tag',
38029              type: 'TAG',
38030              value: tag !== undefined ? tag : ''
38031            }, {
38032              name: 'checkSum',
38033              type: 'ULONG',
38034              value: checkSum !== undefined ? checkSum : 0
38035            }, {
38036              name: 'offset',
38037              type: 'ULONG',
38038              value: offset !== undefined ? offset : 0
38039            }, {
38040              name: 'length',
38041              type: 'ULONG',
38042              value: length !== undefined ? length : 0
38043            }]);
38044          }
38045
38046          function makeSfntTable(tables) {
38047            var sfnt = new table.Table('sfnt', [{
38048              name: 'version',
38049              type: 'TAG',
38050              value: 'OTTO'
38051            }, {
38052              name: 'numTables',
38053              type: 'USHORT',
38054              value: 0
38055            }, {
38056              name: 'searchRange',
38057              type: 'USHORT',
38058              value: 0
38059            }, {
38060              name: 'entrySelector',
38061              type: 'USHORT',
38062              value: 0
38063            }, {
38064              name: 'rangeShift',
38065              type: 'USHORT',
38066              value: 0
38067            }]);
38068            sfnt.tables = tables;
38069            sfnt.numTables = tables.length;
38070            var highestPowerOf2 = Math.pow(2, log2(sfnt.numTables));
38071            sfnt.searchRange = 16 * highestPowerOf2;
38072            sfnt.entrySelector = log2(highestPowerOf2);
38073            sfnt.rangeShift = sfnt.numTables * 16 - sfnt.searchRange;
38074            var recordFields = [];
38075            var tableFields = [];
38076            var offset = sfnt.sizeOf() + makeTableRecord().sizeOf() * sfnt.numTables;
38077
38078            while (offset % 4 !== 0) {
38079              offset += 1;
38080              tableFields.push({
38081                name: 'padding',
38082                type: 'BYTE',
38083                value: 0
38084              });
38085            }
38086
38087            for (var i = 0; i < tables.length; i += 1) {
38088              var t = tables[i];
38089              check.argument(t.tableName.length === 4, 'Table name' + t.tableName + ' is invalid.');
38090              var tableLength = t.sizeOf();
38091              var tableRecord = makeTableRecord(t.tableName, computeCheckSum(t.encode()), offset, tableLength);
38092              recordFields.push({
38093                name: tableRecord.tag + ' Table Record',
38094                type: 'RECORD',
38095                value: tableRecord
38096              });
38097              tableFields.push({
38098                name: t.tableName + ' table',
38099                type: 'RECORD',
38100                value: t
38101              });
38102              offset += tableLength;
38103              check.argument(!isNaN(offset), 'Something went wrong calculating the offset.');
38104
38105              while (offset % 4 !== 0) {
38106                offset += 1;
38107                tableFields.push({
38108                  name: 'padding',
38109                  type: 'BYTE',
38110                  value: 0
38111                });
38112              }
38113            } // Table records need to be sorted alphabetically.
38114
38115
38116            recordFields.sort(function (r1, r2) {
38117              if (r1.value.tag > r2.value.tag) {
38118                return 1;
38119              } else {
38120                return -1;
38121              }
38122            });
38123            sfnt.fields = sfnt.fields.concat(recordFields);
38124            sfnt.fields = sfnt.fields.concat(tableFields);
38125            return sfnt;
38126          } // Get the metrics for a character. If the string has more than one character
38127          // this function returns metrics for the first available character.
38128          // You can provide optional fallback metrics if no characters are available.
38129
38130
38131          function metricsForChar(font, chars, notFoundMetrics) {
38132            for (var i = 0; i < chars.length; i += 1) {
38133              var glyphIndex = font.charToGlyphIndex(chars[i]);
38134
38135              if (glyphIndex > 0) {
38136                var glyph = font.glyphs.get(glyphIndex);
38137                return glyph.getMetrics();
38138              }
38139            }
38140
38141            return notFoundMetrics;
38142          }
38143
38144          function average(vs) {
38145            var sum = 0;
38146
38147            for (var i = 0; i < vs.length; i += 1) {
38148              sum += vs[i];
38149            }
38150
38151            return sum / vs.length;
38152          } // Convert the font object to a SFNT data structure.
38153          // This structure contains all the necessary tables and metadata to create a binary OTF file.
38154
38155
38156          function fontToSfntTable(font) {
38157            var xMins = [];
38158            var yMins = [];
38159            var xMaxs = [];
38160            var yMaxs = [];
38161            var advanceWidths = [];
38162            var leftSideBearings = [];
38163            var rightSideBearings = [];
38164            var firstCharIndex;
38165            var lastCharIndex = 0;
38166            var ulUnicodeRange1 = 0;
38167            var ulUnicodeRange2 = 0;
38168            var ulUnicodeRange3 = 0;
38169            var ulUnicodeRange4 = 0;
38170
38171            for (var i = 0; i < font.glyphs.length; i += 1) {
38172              var glyph = font.glyphs.get(i);
38173              var unicode = glyph.unicode | 0;
38174
38175              if (isNaN(glyph.advanceWidth)) {
38176                throw new Error('Glyph ' + glyph.name + ' (' + i + '): advanceWidth is not a number.');
38177              }
38178
38179              if (firstCharIndex > unicode || firstCharIndex === undefined) {
38180                // ignore .notdef char
38181                if (unicode > 0) {
38182                  firstCharIndex = unicode;
38183                }
38184              }
38185
38186              if (lastCharIndex < unicode) {
38187                lastCharIndex = unicode;
38188              }
38189
38190              var position = os2.getUnicodeRange(unicode);
38191
38192              if (position < 32) {
38193                ulUnicodeRange1 |= 1 << position;
38194              } else if (position < 64) {
38195                ulUnicodeRange2 |= 1 << position - 32;
38196              } else if (position < 96) {
38197                ulUnicodeRange3 |= 1 << position - 64;
38198              } else if (position < 123) {
38199                ulUnicodeRange4 |= 1 << position - 96;
38200              } else {
38201                throw new Error('Unicode ranges bits > 123 are reserved for internal usage');
38202              } // Skip non-important characters.
38203
38204
38205              if (glyph.name === '.notdef') {
38206                continue;
38207              }
38208
38209              var metrics = glyph.getMetrics();
38210              xMins.push(metrics.xMin);
38211              yMins.push(metrics.yMin);
38212              xMaxs.push(metrics.xMax);
38213              yMaxs.push(metrics.yMax);
38214              leftSideBearings.push(metrics.leftSideBearing);
38215              rightSideBearings.push(metrics.rightSideBearing);
38216              advanceWidths.push(glyph.advanceWidth);
38217            }
38218
38219            var globals = {
38220              xMin: Math.min.apply(null, xMins),
38221              yMin: Math.min.apply(null, yMins),
38222              xMax: Math.max.apply(null, xMaxs),
38223              yMax: Math.max.apply(null, yMaxs),
38224              advanceWidthMax: Math.max.apply(null, advanceWidths),
38225              advanceWidthAvg: average(advanceWidths),
38226              minLeftSideBearing: Math.min.apply(null, leftSideBearings),
38227              maxLeftSideBearing: Math.max.apply(null, leftSideBearings),
38228              minRightSideBearing: Math.min.apply(null, rightSideBearings)
38229            };
38230            globals.ascender = font.ascender;
38231            globals.descender = font.descender;
38232            var headTable = head.make({
38233              flags: 3,
38234              // 00000011 (baseline for font at y=0; left sidebearing point at x=0)
38235              unitsPerEm: font.unitsPerEm,
38236              xMin: globals.xMin,
38237              yMin: globals.yMin,
38238              xMax: globals.xMax,
38239              yMax: globals.yMax,
38240              lowestRecPPEM: 3,
38241              createdTimestamp: font.createdTimestamp
38242            });
38243            var hheaTable = hhea.make({
38244              ascender: globals.ascender,
38245              descender: globals.descender,
38246              advanceWidthMax: globals.advanceWidthMax,
38247              minLeftSideBearing: globals.minLeftSideBearing,
38248              minRightSideBearing: globals.minRightSideBearing,
38249              xMaxExtent: globals.maxLeftSideBearing + (globals.xMax - globals.xMin),
38250              numberOfHMetrics: font.glyphs.length
38251            });
38252            var maxpTable = maxp.make(font.glyphs.length);
38253            var os2Table = os2.make({
38254              xAvgCharWidth: Math.round(globals.advanceWidthAvg),
38255              usWeightClass: font.tables.os2.usWeightClass,
38256              usWidthClass: font.tables.os2.usWidthClass,
38257              usFirstCharIndex: firstCharIndex,
38258              usLastCharIndex: lastCharIndex,
38259              ulUnicodeRange1: ulUnicodeRange1,
38260              ulUnicodeRange2: ulUnicodeRange2,
38261              ulUnicodeRange3: ulUnicodeRange3,
38262              ulUnicodeRange4: ulUnicodeRange4,
38263              fsSelection: font.tables.os2.fsSelection,
38264              // REGULAR
38265              // See http://typophile.com/node/13081 for more info on vertical metrics.
38266              // We get metrics for typical characters (such as "x" for xHeight).
38267              // We provide some fallback characters if characters are unavailable: their
38268              // ordering was chosen experimentally.
38269              sTypoAscender: globals.ascender,
38270              sTypoDescender: globals.descender,
38271              sTypoLineGap: 0,
38272              usWinAscent: globals.yMax,
38273              usWinDescent: Math.abs(globals.yMin),
38274              ulCodePageRange1: 1,
38275              // FIXME: hard-code Latin 1 support for now
38276              sxHeight: metricsForChar(font, 'xyvw', {
38277                yMax: Math.round(globals.ascender / 2)
38278              }).yMax,
38279              sCapHeight: metricsForChar(font, 'HIKLEFJMNTZBDPRAGOQSUVWXY', globals).yMax,
38280              usDefaultChar: font.hasChar(' ') ? 32 : 0,
38281              // Use space as the default character, if available.
38282              usBreakChar: font.hasChar(' ') ? 32 : 0 // Use space as the break character, if available.
38283
38284            });
38285            var hmtxTable = hmtx.make(font.glyphs);
38286            var cmapTable = cmap.make(font.glyphs);
38287            var englishFamilyName = font.getEnglishName('fontFamily');
38288            var englishStyleName = font.getEnglishName('fontSubfamily');
38289            var englishFullName = englishFamilyName + ' ' + englishStyleName;
38290            var postScriptName = font.getEnglishName('postScriptName');
38291
38292            if (!postScriptName) {
38293              postScriptName = englishFamilyName.replace(/\s/g, '') + '-' + englishStyleName;
38294            }
38295
38296            var names = {};
38297
38298            for (var n in font.names) {
38299              names[n] = font.names[n];
38300            }
38301
38302            if (!names.uniqueID) {
38303              names.uniqueID = {
38304                en: font.getEnglishName('manufacturer') + ':' + englishFullName
38305              };
38306            }
38307
38308            if (!names.postScriptName) {
38309              names.postScriptName = {
38310                en: postScriptName
38311              };
38312            }
38313
38314            if (!names.preferredFamily) {
38315              names.preferredFamily = font.names.fontFamily;
38316            }
38317
38318            if (!names.preferredSubfamily) {
38319              names.preferredSubfamily = font.names.fontSubfamily;
38320            }
38321
38322            var languageTags = [];
38323
38324            var nameTable = _name.make(names, languageTags);
38325
38326            var ltagTable = languageTags.length > 0 ? ltag.make(languageTags) : undefined;
38327            var postTable = post.make();
38328            var cffTable = cff.make(font.glyphs, {
38329              version: font.getEnglishName('version'),
38330              fullName: englishFullName,
38331              familyName: englishFamilyName,
38332              weightName: englishStyleName,
38333              postScriptName: postScriptName,
38334              unitsPerEm: font.unitsPerEm,
38335              fontBBox: [0, globals.yMin, globals.ascender, globals.advanceWidthMax]
38336            });
38337            var metaTable = font.metas && Object.keys(font.metas).length > 0 ? meta.make(font.metas) : undefined; // The order does not matter because makeSfntTable() will sort them.
38338
38339            var tables = [headTable, hheaTable, maxpTable, os2Table, nameTable, cmapTable, postTable, cffTable, hmtxTable];
38340
38341            if (ltagTable) {
38342              tables.push(ltagTable);
38343            } // Optional tables
38344
38345
38346            if (font.tables.gsub) {
38347              tables.push(gsub.make(font.tables.gsub));
38348            }
38349
38350            if (metaTable) {
38351              tables.push(metaTable);
38352            }
38353
38354            var sfntTable = makeSfntTable(tables); // Compute the font's checkSum and store it in head.checkSumAdjustment.
38355
38356            var bytes = sfntTable.encode();
38357            var checkSum = computeCheckSum(bytes);
38358            var tableFields = sfntTable.fields;
38359            var checkSumAdjusted = false;
38360
38361            for (var i$1 = 0; i$1 < tableFields.length; i$1 += 1) {
38362              if (tableFields[i$1].name === 'head table') {
38363                tableFields[i$1].value.checkSumAdjustment = 0xB1B0AFBA - checkSum;
38364                checkSumAdjusted = true;
38365                break;
38366              }
38367            }
38368
38369            if (!checkSumAdjusted) {
38370              throw new Error('Could not find head table with checkSum to adjust.');
38371            }
38372
38373            return sfntTable;
38374          }
38375
38376          var sfnt = {
38377            make: makeSfntTable,
38378            fontToTable: fontToSfntTable,
38379            computeCheckSum: computeCheckSum
38380          }; // The Layout object is the prototype of Substitution objects, and provides
38381
38382          function searchTag(arr, tag) {
38383            /* jshint bitwise: false */
38384            var imin = 0;
38385            var imax = arr.length - 1;
38386
38387            while (imin <= imax) {
38388              var imid = imin + imax >>> 1;
38389              var val = arr[imid].tag;
38390
38391              if (val === tag) {
38392                return imid;
38393              } else if (val < tag) {
38394                imin = imid + 1;
38395              } else {
38396                imax = imid - 1;
38397              }
38398            } // Not found: return -1-insertion point
38399
38400
38401            return -imin - 1;
38402          }
38403
38404          function binSearch(arr, value) {
38405            /* jshint bitwise: false */
38406            var imin = 0;
38407            var imax = arr.length - 1;
38408
38409            while (imin <= imax) {
38410              var imid = imin + imax >>> 1;
38411              var val = arr[imid];
38412
38413              if (val === value) {
38414                return imid;
38415              } else if (val < value) {
38416                imin = imid + 1;
38417              } else {
38418                imax = imid - 1;
38419              }
38420            } // Not found: return -1-insertion point
38421
38422
38423            return -imin - 1;
38424          } // binary search in a list of ranges (coverage, class definition)
38425
38426
38427          function searchRange(ranges, value) {
38428            // jshint bitwise: false
38429            var range;
38430            var imin = 0;
38431            var imax = ranges.length - 1;
38432
38433            while (imin <= imax) {
38434              var imid = imin + imax >>> 1;
38435              range = ranges[imid];
38436              var start = range.start;
38437
38438              if (start === value) {
38439                return range;
38440              } else if (start < value) {
38441                imin = imid + 1;
38442              } else {
38443                imax = imid - 1;
38444              }
38445            }
38446
38447            if (imin > 0) {
38448              range = ranges[imin - 1];
38449
38450              if (value > range.end) {
38451                return 0;
38452              }
38453
38454              return range;
38455            }
38456          }
38457          /**
38458           * @exports opentype.Layout
38459           * @class
38460           */
38461
38462
38463          function Layout(font, tableName) {
38464            this.font = font;
38465            this.tableName = tableName;
38466          }
38467
38468          Layout.prototype = {
38469            /**
38470             * Binary search an object by "tag" property
38471             * @instance
38472             * @function searchTag
38473             * @memberof opentype.Layout
38474             * @param  {Array} arr
38475             * @param  {string} tag
38476             * @return {number}
38477             */
38478            searchTag: searchTag,
38479
38480            /**
38481             * Binary search in a list of numbers
38482             * @instance
38483             * @function binSearch
38484             * @memberof opentype.Layout
38485             * @param  {Array} arr
38486             * @param  {number} value
38487             * @return {number}
38488             */
38489            binSearch: binSearch,
38490
38491            /**
38492             * Get or create the Layout table (GSUB, GPOS etc).
38493             * @param  {boolean} create - Whether to create a new one.
38494             * @return {Object} The GSUB or GPOS table.
38495             */
38496            getTable: function (create) {
38497              var layout = this.font.tables[this.tableName];
38498
38499              if (!layout && create) {
38500                layout = this.font.tables[this.tableName] = this.createDefaultTable();
38501              }
38502
38503              return layout;
38504            },
38505
38506            /**
38507             * Returns all scripts in the substitution table.
38508             * @instance
38509             * @return {Array}
38510             */
38511            getScriptNames: function () {
38512              var layout = this.getTable();
38513
38514              if (!layout) {
38515                return [];
38516              }
38517
38518              return layout.scripts.map(function (script) {
38519                return script.tag;
38520              });
38521            },
38522
38523            /**
38524             * Returns the best bet for a script name.
38525             * Returns 'DFLT' if it exists.
38526             * If not, returns 'latn' if it exists.
38527             * If neither exist, returns undefined.
38528             */
38529            getDefaultScriptName: function () {
38530              var layout = this.getTable();
38531
38532              if (!layout) {
38533                return;
38534              }
38535
38536              var hasLatn = false;
38537
38538              for (var i = 0; i < layout.scripts.length; i++) {
38539                var name = layout.scripts[i].tag;
38540
38541                if (name === 'DFLT') {
38542                  return name;
38543                }
38544
38545                if (name === 'latn') {
38546                  hasLatn = true;
38547                }
38548              }
38549
38550              if (hasLatn) {
38551                return 'latn';
38552              }
38553            },
38554
38555            /**
38556             * Returns all LangSysRecords in the given script.
38557             * @instance
38558             * @param {string} [script='DFLT']
38559             * @param {boolean} create - forces the creation of this script table if it doesn't exist.
38560             * @return {Object} An object with tag and script properties.
38561             */
38562            getScriptTable: function (script, create) {
38563              var layout = this.getTable(create);
38564
38565              if (layout) {
38566                script = script || 'DFLT';
38567                var scripts = layout.scripts;
38568                var pos = searchTag(layout.scripts, script);
38569
38570                if (pos >= 0) {
38571                  return scripts[pos].script;
38572                } else if (create) {
38573                  var scr = {
38574                    tag: script,
38575                    script: {
38576                      defaultLangSys: {
38577                        reserved: 0,
38578                        reqFeatureIndex: 0xffff,
38579                        featureIndexes: []
38580                      },
38581                      langSysRecords: []
38582                    }
38583                  };
38584                  scripts.splice(-1 - pos, 0, scr);
38585                  return scr.script;
38586                }
38587              }
38588            },
38589
38590            /**
38591             * Returns a language system table
38592             * @instance
38593             * @param {string} [script='DFLT']
38594             * @param {string} [language='dlft']
38595             * @param {boolean} create - forces the creation of this langSysTable if it doesn't exist.
38596             * @return {Object}
38597             */
38598            getLangSysTable: function (script, language, create) {
vendor: 4,771 bytes, lines 38599-38714
38599              var scriptTable = this.getScriptTable(script, create);
38600
38601              if (scriptTable) {
38602                if (!language || language === 'dflt' || language === 'DFLT') {
38603                  return scriptTable.defaultLangSys;
38604                }
38605
38606                var pos = searchTag(scriptTable.langSysRecords, language);
38607
38608                if (pos >= 0) {
38609                  return scriptTable.langSysRecords[pos].langSys;
38610                } else if (create) {
38611                  var langSysRecord = {
38612                    tag: language,
38613                    langSys: {
38614                      reserved: 0,
38615                      reqFeatureIndex: 0xffff,
38616                      featureIndexes: []
38617                    }
38618                  };
38619                  scriptTable.langSysRecords.splice(-1 - pos, 0, langSysRecord);
38620                  return langSysRecord.langSys;
38621                }
38622              }
38623            },
38624
38625            /**
38626             * Get a specific feature table.
38627             * @instance
38628             * @param {string} [script='DFLT']
38629             * @param {string} [language='dlft']
38630             * @param {string} feature - One of the codes listed at https://www.microsoft.com/typography/OTSPEC/featurelist.htm
38631             * @param {boolean} create - forces the creation of the feature table if it doesn't exist.
38632             * @return {Object}
38633             */
38634            getFeatureTable: function (script, language, feature, create) {
38635              var langSysTable = this.getLangSysTable(script, language, create);
38636
38637              if (langSysTable) {
38638                var featureRecord;
38639                var featIndexes = langSysTable.featureIndexes;
38640                var allFeatures = this.font.tables[this.tableName].features; // The FeatureIndex array of indices is in arbitrary order,
38641                // even if allFeatures is sorted alphabetically by feature tag.
38642
38643                for (var i = 0; i < featIndexes.length; i++) {
38644                  featureRecord = allFeatures[featIndexes[i]];
38645
38646                  if (featureRecord.tag === feature) {
38647                    return featureRecord.feature;
38648                  }
38649                }
38650
38651                if (create) {
38652                  var index = allFeatures.length; // Automatic ordering of features would require to shift feature indexes in the script list.
38653
38654                  check.assert(index === 0 || feature >= allFeatures[index - 1].tag, 'Features must be added in alphabetical order.');
38655                  featureRecord = {
38656                    tag: feature,
38657                    feature: {
38658                      params: 0,
38659                      lookupListIndexes: []
38660                    }
38661                  };
38662                  allFeatures.push(featureRecord);
38663                  featIndexes.push(index);
38664                  return featureRecord.feature;
38665                }
38666              }
38667            },
38668
38669            /**
38670             * Get the lookup tables of a given type for a script/language/feature.
38671             * @instance
38672             * @param {string} [script='DFLT']
38673             * @param {string} [language='dlft']
38674             * @param {string} feature - 4-letter feature code
38675             * @param {number} lookupType - 1 to 9
38676             * @param {boolean} create - forces the creation of the lookup table if it doesn't exist, with no subtables.
38677             * @return {Object[]}
38678             */
38679            getLookupTables: function (script, language, feature, lookupType, create) {
38680              var featureTable = this.getFeatureTable(script, language, feature, create);
38681              var tables = [];
38682
38683              if (featureTable) {
38684                var lookupTable;
38685                var lookupListIndexes = featureTable.lookupListIndexes;
38686                var allLookups = this.font.tables[this.tableName].lookups; // lookupListIndexes are in no particular order, so use naive search.
38687
38688                for (var i = 0; i < lookupListIndexes.length; i++) {
38689                  lookupTable = allLookups[lookupListIndexes[i]];
38690
38691                  if (lookupTable.lookupType === lookupType) {
38692                    tables.push(lookupTable);
38693                  }
38694                }
38695
38696                if (tables.length === 0 && create) {
38697                  lookupTable = {
38698                    lookupType: lookupType,
38699                    lookupFlag: 0,
38700                    subtables: [],
38701                    markFilteringSet: undefined
38702                  };
38703                  var index = allLookups.length;
38704                  allLookups.push(lookupTable);
38705                  lookupListIndexes.push(index);
38706                  return [lookupTable];
38707                }
38708              }
38709
38710              return tables;
38711            },
38712
38713            /**
38714             * Find a glyph in a class definition table
38715             * https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table
38716             * @param {object} classDefTable - an OpenType Layout class definition table
38717             * @param {number} glyphIndex - the index of the glyph to find
38718             * @returns {number} -1 if not found
38719             */
38720            getGlyphClass: function (classDefTable, glyphIndex) {
38721              switch (classDefTable.format) {
38722                case 1:
38723                  if (classDefTable.startGlyph <= glyphIndex && glyphIndex < classDefTable.startGlyph + classDefTable.classes.length) {
38724                    return classDefTable.classes[glyphIndex - classDefTable.startGlyph];
38725                  }
38726
38727                  return 0;
38728
38729                case 2:
38730                  var range = searchRange(classDefTable.ranges, glyphIndex);
38731                  return range ? range.classId : 0;
38732              }
38733            },
38734
38735            /**
38736             * Find a glyph in a coverage table
38737             * https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-table
38738             * @param {object} coverageTable - an OpenType Layout coverage table
38739             * @param {number} glyphIndex - the index of the glyph to find
38740             * @returns {number} -1 if not found
38741             */
38742            getCoverageIndex: function (coverageTable, glyphIndex) {
38743              switch (coverageTable.format) {
38744                case 1:
38745                  var index = binSearch(coverageTable.glyphs, glyphIndex);
38746                  return index >= 0 ? index : -1;
38747
38748                case 2:
38749                  var range = searchRange(coverageTable.ranges, glyphIndex);
38750                  return range ? range.index + glyphIndex - range.start : -1;
38751              }
38752            },
38753
38754            /**
38755             * Returns the list of glyph indexes of a coverage table.
38756             * Format 1: the list is stored raw
38757             * Format 2: compact list as range records.
38758             * @instance
38759             * @param  {Object} coverageTable
38760             * @return {Array}
38761             */
38762            expandCoverage: function (coverageTable) {
38763              if (coverageTable.format === 1) {
38764                return coverageTable.glyphs;
38765              } else {
38766                var glyphs = [];
38767                var ranges = coverageTable.ranges;
38768
38769                for (var i = 0; i < ranges.length; i++) {
38770                  var range = ranges[i];
38771                  var start = range.start;
38772                  var end = range.end;
38773
38774                  for (var j = start; j <= end; j++) {
38775                    glyphs.push(j);
38776                  }
38777                }
38778
38779                return glyphs;
38780              }
38781            }
38782          }; // The Position object provides utility methods to manipulate
38783
38784          /**
38785           * @exports opentype.Position
38786           * @class
38787           * @extends opentype.Layout
38788           * @param {opentype.Font}
38789           * @constructor
38790           */
38791
38792          function Position(font) {
38793            Layout.call(this, font, 'gpos');
38794          }
38795
38796          Position.prototype = Layout.prototype;
38797          /**
38798           * Init some data for faster and easier access later.
38799           */
38800
38801          Position.prototype.init = function () {
38802            var script = this.getDefaultScriptName();
38803            this.defaultKerningTables = this.getKerningTables(script);
38804          };
38805          /**
38806           * Find a glyph pair in a list of lookup tables of type 2 and retrieve the xAdvance kerning value.
38807           *
38808           * @param {integer} leftIndex - left glyph index
38809           * @param {integer} rightIndex - right glyph index
38810           * @returns {integer}
38811           */
38812
38813
38814          Position.prototype.getKerningValue = function (kerningLookups, leftIndex, rightIndex) {
38815            var this$1 = this;
38816
38817            for (var i = 0; i < kerningLookups.length; i++) {
38818              var subtables = kerningLookups[i].subtables;
38819
38820              for (var j = 0; j < subtables.length; j++) {
38821                var subtable = subtables[j];
38822                var covIndex = this$1.getCoverageIndex(subtable.coverage, leftIndex);
38823
38824                if (covIndex < 0) {
38825                  continue;
38826                }
38827
38828                switch (subtable.posFormat) {
38829                  case 1:
38830                    // Search Pair Adjustment Positioning Format 1
38831                    var pairSet = subtable.pairSets[covIndex];
38832
38833                    for (var k = 0; k < pairSet.length; k++) {
38834                      var pair = pairSet[k];
38835
38836                      if (pair.secondGlyph === rightIndex) {
38837                        return pair.value1 && pair.value1.xAdvance || 0;
38838                      }
38839                    }
38840
38841                    break;
38842                  // left glyph found, not right glyph - try next subtable
38843
38844                  case 2:
38845                    // Search Pair Adjustment Positioning Format 2
38846                    var class1 = this$1.getGlyphClass(subtable.classDef1, leftIndex);
38847                    var class2 = this$1.getGlyphClass(subtable.classDef2, rightIndex);
38848                    var pair$1 = subtable.classRecords[class1][class2];
38849                    return pair$1.value1 && pair$1.value1.xAdvance || 0;
38850                }
38851              }
38852            }
38853
38854            return 0;
38855          };
38856          /**
38857           * List all kerning lookup tables.
38858           *
38859           * @param {string} [script='DFLT'] - use font.position.getDefaultScriptName() for a better default value
38860           * @param {string} [language='dflt']
38861           * @return {object[]} The list of kerning lookup tables (may be empty), or undefined if there is no GPOS table (and we should use the kern table)
38862           */
38863
38864
38865          Position.prototype.getKerningTables = function (script, language) {
38866            if (this.font.tables.gpos) {
38867              return this.getLookupTables(script, language, 'kern', 2);
38868            }
38869          }; // The Substitution object provides utility methods to manipulate
38870
38871          /**
38872           * @exports opentype.Substitution
38873           * @class
vendor: 26,662 bytes, lines 38874-39611
38874           * @extends opentype.Layout
38875           * @param {opentype.Font}
38876           * @constructor
38877           */
38878
38879
38880          function Substitution(font) {
38881            Layout.call(this, font, 'gsub');
38882          } // Check if 2 arrays of primitives are equal.
38883
38884
38885          function arraysEqual(ar1, ar2) {
38886            var n = ar1.length;
38887
38888            if (n !== ar2.length) {
38889              return false;
38890            }
38891
38892            for (var i = 0; i < n; i++) {
38893              if (ar1[i] !== ar2[i]) {
38894                return false;
38895              }
38896            }
38897
38898            return true;
38899          } // Find the first subtable of a lookup table in a particular format.
38900
38901
38902          function getSubstFormat(lookupTable, format, defaultSubtable) {
38903            var subtables = lookupTable.subtables;
38904
38905            for (var i = 0; i < subtables.length; i++) {
38906              var subtable = subtables[i];
38907
38908              if (subtable.substFormat === format) {
38909                return subtable;
38910              }
38911            }
38912
38913            if (defaultSubtable) {
38914              subtables.push(defaultSubtable);
38915              return defaultSubtable;
38916            }
38917
38918            return undefined;
38919          }
38920
38921          Substitution.prototype = Layout.prototype;
38922          /**
38923           * Create a default GSUB table.
38924           * @return {Object} gsub - The GSUB table.
38925           */
38926
38927          Substitution.prototype.createDefaultTable = function () {
38928            // Generate a default empty GSUB table with just a DFLT script and dflt lang sys.
38929            return {
38930              version: 1,
38931              scripts: [{
38932                tag: 'DFLT',
38933                script: {
38934                  defaultLangSys: {
38935                    reserved: 0,
38936                    reqFeatureIndex: 0xffff,
38937                    featureIndexes: []
38938                  },
38939                  langSysRecords: []
38940                }
38941              }],
38942              features: [],
38943              lookups: []
38944            };
38945          };
38946          /**
38947           * List all single substitutions (lookup type 1) for a given script, language, and feature.
38948           * @param {string} [script='DFLT']
38949           * @param {string} [language='dflt']
38950           * @param {string} feature - 4-character feature name ('aalt', 'salt', 'ss01'...)
38951           * @return {Array} substitutions - The list of substitutions.
38952           */
38953
38954
38955          Substitution.prototype.getSingle = function (feature, script, language) {
38956            var this$1 = this;
38957            var substitutions = [];
38958            var lookupTables = this.getLookupTables(script, language, feature, 1);
38959
38960            for (var idx = 0; idx < lookupTables.length; idx++) {
38961              var subtables = lookupTables[idx].subtables;
38962
38963              for (var i = 0; i < subtables.length; i++) {
38964                var subtable = subtables[i];
38965                var glyphs = this$1.expandCoverage(subtable.coverage);
38966                var j = void 0;
38967
38968                if (subtable.substFormat === 1) {
38969                  var delta = subtable.deltaGlyphId;
38970
38971                  for (j = 0; j < glyphs.length; j++) {
38972                    var glyph = glyphs[j];
38973                    substitutions.push({
38974                      sub: glyph,
38975                      by: glyph + delta
38976                    });
38977                  }
38978                } else {
38979                  var substitute = subtable.substitute;
38980
38981                  for (j = 0; j < glyphs.length; j++) {
38982                    substitutions.push({
38983                      sub: glyphs[j],
38984                      by: substitute[j]
38985                    });
38986                  }
38987                }
38988              }
38989            }
38990
38991            return substitutions;
38992          };
38993          /**
38994           * List all alternates (lookup type 3) for a given script, language, and feature.
38995           * @param {string} [script='DFLT']
38996           * @param {string} [language='dflt']
38997           * @param {string} feature - 4-character feature name ('aalt', 'salt'...)
38998           * @return {Array} alternates - The list of alternates
38999           */
39000
39001
39002          Substitution.prototype.getAlternates = function (feature, script, language) {
39003            var this$1 = this;
39004            var alternates = [];
39005            var lookupTables = this.getLookupTables(script, language, feature, 3);
39006
39007            for (var idx = 0; idx < lookupTables.length; idx++) {
39008              var subtables = lookupTables[idx].subtables;
39009
39010              for (var i = 0; i < subtables.length; i++) {
39011                var subtable = subtables[i];
39012                var glyphs = this$1.expandCoverage(subtable.coverage);
39013                var alternateSets = subtable.alternateSets;
39014
39015                for (var j = 0; j < glyphs.length; j++) {
39016                  alternates.push({
39017                    sub: glyphs[j],
39018                    by: alternateSets[j]
39019                  });
39020                }
39021              }
39022            }
39023
39024            return alternates;
39025          };
39026          /**
39027           * List all ligatures (lookup type 4) for a given script, language, and feature.
39028           * The result is an array of ligature objects like { sub: [ids], by: id }
39029           * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...)
39030           * @param {string} [script='DFLT']
39031           * @param {string} [language='dflt']
39032           * @return {Array} ligatures - The list of ligatures.
39033           */
39034
39035
39036          Substitution.prototype.getLigatures = function (feature, script, language) {
39037            var this$1 = this;
39038            var ligatures = [];
39039            var lookupTables = this.getLookupTables(script, language, feature, 4);
39040
39041            for (var idx = 0; idx < lookupTables.length; idx++) {
39042              var subtables = lookupTables[idx].subtables;
39043
39044              for (var i = 0; i < subtables.length; i++) {
39045                var subtable = subtables[i];
39046                var glyphs = this$1.expandCoverage(subtable.coverage);
39047                var ligatureSets = subtable.ligatureSets;
39048
39049                for (var j = 0; j < glyphs.length; j++) {
39050                  var startGlyph = glyphs[j];
39051                  var ligSet = ligatureSets[j];
39052
39053                  for (var k = 0; k < ligSet.length; k++) {
39054                    var lig = ligSet[k];
39055                    ligatures.push({
39056                      sub: [startGlyph].concat(lig.components),
39057                      by: lig.ligGlyph
39058                    });
39059                  }
39060                }
39061              }
39062            }
39063
39064            return ligatures;
39065          };
39066          /**
39067           * Add or modify a single substitution (lookup type 1)
39068           * Format 2, more flexible, is always used.
39069           * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...)
39070           * @param {Object} substitution - { sub: id, delta: number } for format 1 or { sub: id, by: id } for format 2.
39071           * @param {string} [script='DFLT']
39072           * @param {string} [language='dflt']
39073           */
39074
39075
39076          Substitution.prototype.addSingle = function (feature, substitution, script, language) {
39077            var lookupTable = this.getLookupTables(script, language, feature, 1, true)[0];
39078            var subtable = getSubstFormat(lookupTable, 2, {
39079              // lookup type 1 subtable, format 2, coverage format 1
39080              substFormat: 2,
39081              coverage: {
39082                format: 1,
39083                glyphs: []
39084              },
39085              substitute: []
39086            });
39087            check.assert(subtable.coverage.format === 1, 'Ligature: unable to modify coverage table format ' + subtable.coverage.format);
39088            var coverageGlyph = substitution.sub;
39089            var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph);
39090
39091            if (pos < 0) {
39092              pos = -1 - pos;
39093              subtable.coverage.glyphs.splice(pos, 0, coverageGlyph);
39094              subtable.substitute.splice(pos, 0, 0);
39095            }
39096
39097            subtable.substitute[pos] = substitution.by;
39098          };
39099          /**
39100           * Add or modify an alternate substitution (lookup type 1)
39101           * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...)
39102           * @param {Object} substitution - { sub: id, by: [ids] }
39103           * @param {string} [script='DFLT']
39104           * @param {string} [language='dflt']
39105           */
39106
39107
39108          Substitution.prototype.addAlternate = function (feature, substitution, script, language) {
39109            var lookupTable = this.getLookupTables(script, language, feature, 3, true)[0];
39110            var subtable = getSubstFormat(lookupTable, 1, {
39111              // lookup type 3 subtable, format 1, coverage format 1
39112              substFormat: 1,
39113              coverage: {
39114                format: 1,
39115                glyphs: []
39116              },
39117              alternateSets: []
39118            });
39119            check.assert(subtable.coverage.format === 1, 'Ligature: unable to modify coverage table format ' + subtable.coverage.format);
39120            var coverageGlyph = substitution.sub;
39121            var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph);
39122
39123            if (pos < 0) {
39124              pos = -1 - pos;
39125              subtable.coverage.glyphs.splice(pos, 0, coverageGlyph);
39126              subtable.alternateSets.splice(pos, 0, 0);
39127            }
39128
39129            subtable.alternateSets[pos] = substitution.by;
39130          };
39131          /**
39132           * Add a ligature (lookup type 4)
39133           * Ligatures with more components must be stored ahead of those with fewer components in order to be found
39134           * @param {string} feature - 4-letter feature name ('liga', 'rlig', 'dlig'...)
39135           * @param {Object} ligature - { sub: [ids], by: id }
39136           * @param {string} [script='DFLT']
39137           * @param {string} [language='dflt']
39138           */
39139
39140
39141          Substitution.prototype.addLigature = function (feature, ligature, script, language) {
39142            var lookupTable = this.getLookupTables(script, language, feature, 4, true)[0];
39143            var subtable = lookupTable.subtables[0];
39144
39145            if (!subtable) {
39146              subtable = {
39147                // lookup type 4 subtable, format 1, coverage format 1
39148                substFormat: 1,
39149                coverage: {
39150                  format: 1,
39151                  glyphs: []
39152                },
39153                ligatureSets: []
39154              };
39155              lookupTable.subtables[0] = subtable;
39156            }
39157
39158            check.assert(subtable.coverage.format === 1, 'Ligature: unable to modify coverage table format ' + subtable.coverage.format);
39159            var coverageGlyph = ligature.sub[0];
39160            var ligComponents = ligature.sub.slice(1);
39161            var ligatureTable = {
39162              ligGlyph: ligature.by,
39163              components: ligComponents
39164            };
39165            var pos = this.binSearch(subtable.coverage.glyphs, coverageGlyph);
39166
39167            if (pos >= 0) {
39168              // ligatureSet already exists
39169              var ligatureSet = subtable.ligatureSets[pos];
39170
39171              for (var i = 0; i < ligatureSet.length; i++) {
39172                // If ligature already exists, return.
39173                if (arraysEqual(ligatureSet[i].components, ligComponents)) {
39174                  return;
39175                }
39176              } // ligature does not exist: add it.
39177
39178
39179              ligatureSet.push(ligatureTable);
39180            } else {
39181              // Create a new ligatureSet and add coverage for the first glyph.
39182              pos = -1 - pos;
39183              subtable.coverage.glyphs.splice(pos, 0, coverageGlyph);
39184              subtable.ligatureSets.splice(pos, 0, [ligatureTable]);
39185            }
39186          };
39187          /**
39188           * List all feature data for a given script and language.
39189           * @param {string} feature - 4-letter feature name
39190           * @param {string} [script='DFLT']
39191           * @param {string} [language='dflt']
39192           * @return {Array} substitutions - The list of substitutions.
39193           */
39194
39195
39196          Substitution.prototype.getFeature = function (feature, script, language) {
39197            if (/ss\d\d/.test(feature)) {
39198              // ss01 - ss20
39199              return this.getSingle(feature, script, language);
39200            }
39201
39202            switch (feature) {
39203              case 'aalt':
39204              case 'salt':
39205                return this.getSingle(feature, script, language).concat(this.getAlternates(feature, script, language));
39206
39207              case 'dlig':
39208              case 'liga':
39209              case 'rlig':
39210                return this.getLigatures(feature, script, language);
39211            }
39212
39213            return undefined;
39214          };
39215          /**
39216           * Add a substitution to a feature for a given script and language.
39217           * @param {string} feature - 4-letter feature name
39218           * @param {Object} sub - the substitution to add (an object like { sub: id or [ids], by: id or [ids] })
39219           * @param {string} [script='DFLT']
39220           * @param {string} [language='dflt']
39221           */
39222
39223
39224          Substitution.prototype.add = function (feature, sub, script, language) {
39225            if (/ss\d\d/.test(feature)) {
39226              // ss01 - ss20
39227              return this.addSingle(feature, sub, script, language);
39228            }
39229
39230            switch (feature) {
39231              case 'aalt':
39232              case 'salt':
39233                if (typeof sub.by === 'number') {
39234                  return this.addSingle(feature, sub, script, language);
39235                }
39236
39237                return this.addAlternate(feature, sub, script, language);
39238
39239              case 'dlig':
39240              case 'liga':
39241              case 'rlig':
39242                return this.addLigature(feature, sub, script, language);
39243            }
39244
39245            return undefined;
39246          };
39247
39248          function isBrowser() {
39249            return typeof window !== 'undefined';
39250          }
39251
39252          function nodeBufferToArrayBuffer(buffer) {
39253            var ab = new ArrayBuffer(buffer.length);
39254            var view = new Uint8Array(ab);
39255
39256            for (var i = 0; i < buffer.length; ++i) {
39257              view[i] = buffer[i];
39258            }
39259
39260            return ab;
39261          }
39262
39263          function arrayBufferToNodeBuffer(ab) {
39264            var buffer = new Buffer(ab.byteLength);
39265            var view = new Uint8Array(ab);
39266
39267            for (var i = 0; i < buffer.length; ++i) {
39268              buffer[i] = view[i];
39269            }
39270
39271            return buffer;
39272          }
39273
39274          function checkArgument(expression, message) {
39275            if (!expression) {
39276              throw message;
39277            }
39278          } // The `glyf` table describes the glyphs in TrueType outline format.
39279          // Parse the coordinate data for a glyph.
39280
39281
39282          function parseGlyphCoordinate(p, flag, previousValue, shortVectorBitMask, sameBitMask) {
39283            var v;
39284
39285            if ((flag & shortVectorBitMask) > 0) {
39286              // The coordinate is 1 byte long.
39287              v = p.parseByte(); // The `same` bit is re-used for short values to signify the sign of the value.
39288
39289              if ((flag & sameBitMask) === 0) {
39290                v = -v;
39291              }
39292
39293              v = previousValue + v;
39294            } else {
39295              //  The coordinate is 2 bytes long.
39296              // If the `same` bit is set, the coordinate is the same as the previous coordinate.
39297              if ((flag & sameBitMask) > 0) {
39298                v = previousValue;
39299              } else {
39300                // Parse the coordinate as a signed 16-bit delta value.
39301                v = previousValue + p.parseShort();
39302              }
39303            }
39304
39305            return v;
39306          } // Parse a TrueType glyph.
39307
39308
39309          function parseGlyph(glyph, data, start) {
39310            var p = new parse.Parser(data, start);
39311            glyph.numberOfContours = p.parseShort();
39312            glyph._xMin = p.parseShort();
39313            glyph._yMin = p.parseShort();
39314            glyph._xMax = p.parseShort();
39315            glyph._yMax = p.parseShort();
39316            var flags;
39317            var flag;
39318
39319            if (glyph.numberOfContours > 0) {
39320              // This glyph is not a composite.
39321              var endPointIndices = glyph.endPointIndices = [];
39322
39323              for (var i = 0; i < glyph.numberOfContours; i += 1) {
39324                endPointIndices.push(p.parseUShort());
39325              }
39326
39327              glyph.instructionLength = p.parseUShort();
39328              glyph.instructions = [];
39329
39330              for (var i$1 = 0; i$1 < glyph.instructionLength; i$1 += 1) {
39331                glyph.instructions.push(p.parseByte());
39332              }
39333
39334              var numberOfCoordinates = endPointIndices[endPointIndices.length - 1] + 1;
39335              flags = [];
39336
39337              for (var i$2 = 0; i$2 < numberOfCoordinates; i$2 += 1) {
39338                flag = p.parseByte();
39339                flags.push(flag); // If bit 3 is set, we repeat this flag n times, where n is the next byte.
39340
39341                if ((flag & 8) > 0) {
39342                  var repeatCount = p.parseByte();
39343
39344                  for (var j = 0; j < repeatCount; j += 1) {
39345                    flags.push(flag);
39346                    i$2 += 1;
39347                  }
39348                }
39349              }
39350
39351              check.argument(flags.length === numberOfCoordinates, 'Bad flags.');
39352
39353              if (endPointIndices.length > 0) {
39354                var points = [];
39355                var point; // X/Y coordinates are relative to the previous point, except for the first point which is relative to 0,0.
39356
39357                if (numberOfCoordinates > 0) {
39358                  for (var i$3 = 0; i$3 < numberOfCoordinates; i$3 += 1) {
39359                    flag = flags[i$3];
39360                    point = {};
39361                    point.onCurve = !!(flag & 1);
39362                    point.lastPointOfContour = endPointIndices.indexOf(i$3) >= 0;
39363                    points.push(point);
39364                  }
39365
39366                  var px = 0;
39367
39368                  for (var i$4 = 0; i$4 < numberOfCoordinates; i$4 += 1) {
39369                    flag = flags[i$4];
39370                    point = points[i$4];
39371                    point.x = parseGlyphCoordinate(p, flag, px, 2, 16);
39372                    px = point.x;
39373                  }
39374
39375                  var py = 0;
39376
39377                  for (var i$5 = 0; i$5 < numberOfCoordinates; i$5 += 1) {
39378                    flag = flags[i$5];
39379                    point = points[i$5];
39380                    point.y = parseGlyphCoordinate(p, flag, py, 4, 32);
39381                    py = point.y;
39382                  }
39383                }
39384
39385                glyph.points = points;
39386              } else {
39387                glyph.points = [];
39388              }
39389            } else if (glyph.numberOfContours === 0) {
39390              glyph.points = [];
39391            } else {
39392              glyph.isComposite = true;
39393              glyph.points = [];
39394              glyph.components = [];
39395              var moreComponents = true;
39396
39397              while (moreComponents) {
39398                flags = p.parseUShort();
39399                var component = {
39400                  glyphIndex: p.parseUShort(),
39401                  xScale: 1,
39402                  scale01: 0,
39403                  scale10: 0,
39404                  yScale: 1,
39405                  dx: 0,
39406                  dy: 0
39407                };
39408
39409                if ((flags & 1) > 0) {
39410                  // The arguments are words
39411                  if ((flags & 2) > 0) {
39412                    // values are offset
39413                    component.dx = p.parseShort();
39414                    component.dy = p.parseShort();
39415                  } else {
39416                    // values are matched points
39417                    component.matchedPoints = [p.parseUShort(), p.parseUShort()];
39418                  }
39419                } else {
39420                  // The arguments are bytes
39421                  if ((flags & 2) > 0) {
39422                    // values are offset
39423                    component.dx = p.parseChar();
39424                    component.dy = p.parseChar();
39425                  } else {
39426                    // values are matched points
39427                    component.matchedPoints = [p.parseByte(), p.parseByte()];
39428                  }
39429                }
39430
39431                if ((flags & 8) > 0) {
39432                  // We have a scale
39433                  component.xScale = component.yScale = p.parseF2Dot14();
39434                } else if ((flags & 64) > 0) {
39435                  // We have an X / Y scale
39436                  component.xScale = p.parseF2Dot14();
39437                  component.yScale = p.parseF2Dot14();
39438                } else if ((flags & 128) > 0) {
39439                  // We have a 2x2 transformation
39440                  component.xScale = p.parseF2Dot14();
39441                  component.scale01 = p.parseF2Dot14();
39442                  component.scale10 = p.parseF2Dot14();
39443                  component.yScale = p.parseF2Dot14();
39444                }
39445
39446                glyph.components.push(component);
39447                moreComponents = !!(flags & 32);
39448              }
39449
39450              if (flags & 0x100) {
39451                // We have instructions
39452                glyph.instructionLength = p.parseUShort();
39453                glyph.instructions = [];
39454
39455                for (var i$6 = 0; i$6 < glyph.instructionLength; i$6 += 1) {
39456                  glyph.instructions.push(p.parseByte());
39457                }
39458              }
39459            }
39460          } // Transform an array of points and return a new array.
39461
39462
39463          function transformPoints(points, transform) {
39464            var newPoints = [];
39465
39466            for (var i = 0; i < points.length; i += 1) {
39467              var pt = points[i];
39468              var newPt = {
39469                x: transform.xScale * pt.x + transform.scale01 * pt.y + transform.dx,
39470                y: transform.scale10 * pt.x + transform.yScale * pt.y + transform.dy,
39471                onCurve: pt.onCurve,
39472                lastPointOfContour: pt.lastPointOfContour
39473              };
39474              newPoints.push(newPt);
39475            }
39476
39477            return newPoints;
39478          }
39479
39480          function getContours(points) {
39481            var contours = [];
39482            var currentContour = [];
39483
39484            for (var i = 0; i < points.length; i += 1) {
39485              var pt = points[i];
39486              currentContour.push(pt);
39487
39488              if (pt.lastPointOfContour) {
39489                contours.push(currentContour);
39490                currentContour = [];
39491              }
39492            }
39493
39494            check.argument(currentContour.length === 0, 'There are still points left in the current contour.');
39495            return contours;
39496          } // Convert the TrueType glyph outline to a Path.
39497
39498
39499          function getPath(points) {
39500            var p = new Path();
39501
39502            if (!points) {
39503              return p;
39504            }
39505
39506            var contours = getContours(points);
39507
39508            for (var contourIndex = 0; contourIndex < contours.length; ++contourIndex) {
39509              var contour = contours[contourIndex];
39510              var prev = null;
39511              var curr = contour[contour.length - 1];
39512              var next = contour[0];
39513
39514              if (curr.onCurve) {
39515                p.moveTo(curr.x, curr.y);
39516              } else {
39517                if (next.onCurve) {
39518                  p.moveTo(next.x, next.y);
39519                } else {
39520                  // If both first and last points are off-curve, start at their middle.
39521                  var start = {
39522                    x: (curr.x + next.x) * 0.5,
39523                    y: (curr.y + next.y) * 0.5
39524                  };
39525                  p.moveTo(start.x, start.y);
39526                }
39527              }
39528
39529              for (var i = 0; i < contour.length; ++i) {
39530                prev = curr;
39531                curr = next;
39532                next = contour[(i + 1) % contour.length];
39533
39534                if (curr.onCurve) {
39535                  // This is a straight line.
39536                  p.lineTo(curr.x, curr.y);
39537                } else {
39538                  var prev2 = prev;
39539                  var next2 = next;
39540
39541                  if (!prev.onCurve) {
39542                    prev2 = {
39543                      x: (curr.x + prev.x) * 0.5,
39544                      y: (curr.y + prev.y) * 0.5
39545                    };
39546                  }
39547
39548                  if (!next.onCurve) {
39549                    next2 = {
39550                      x: (curr.x + next.x) * 0.5,
39551                      y: (curr.y + next.y) * 0.5
39552                    };
39553                  }
39554
39555                  p.quadraticCurveTo(curr.x, curr.y, next2.x, next2.y);
39556                }
39557              }
39558
39559              p.closePath();
39560            }
39561
39562            return p;
39563          }
39564
39565          function buildPath(glyphs, glyph) {
39566            if (glyph.isComposite) {
39567              for (var j = 0; j < glyph.components.length; j += 1) {
39568                var component = glyph.components[j];
39569                var componentGlyph = glyphs.get(component.glyphIndex); // Force the ttfGlyphLoader to parse the glyph.
39570
39571                componentGlyph.getPath();
39572
39573                if (componentGlyph.points) {
39574                  var transformedPoints = void 0;
39575
39576                  if (component.matchedPoints === undefined) {
39577                    // component positioned by offset
39578                    transformedPoints = transformPoints(componentGlyph.points, component);
39579                  } else {
39580                    // component positioned by matched points
39581                    if (component.matchedPoints[0] > glyph.points.length - 1 || component.matchedPoints[1] > componentGlyph.points.length - 1) {
39582                      throw Error('Matched points out of range in ' + glyph.name);
39583                    }
39584
39585                    var firstPt = glyph.points[component.matchedPoints[0]];
39586                    var secondPt = componentGlyph.points[component.matchedPoints[1]];
39587                    var transform = {
39588                      xScale: component.xScale,
39589                      scale01: component.scale01,
39590                      scale10: component.scale10,
39591                      yScale: component.yScale,
39592                      dx: 0,
39593                      dy: 0
39594                    };
39595                    secondPt = transformPoints([secondPt], transform)[0];
39596                    transform.dx = firstPt.x - secondPt.x;
39597                    transform.dy = firstPt.y - secondPt.y;
39598                    transformedPoints = transformPoints(componentGlyph.points, transform);
39599                  }
39600
39601                  glyph.points = glyph.points.concat(transformedPoints);
39602                }
39603              }
39604            }
39605
39606            return getPath(glyph.points);
39607          } // Parse all the glyphs according to the offsets from the `loca` table.
39608
39609
39610          function parseGlyfTable(data, start, loca, font) {
39611            var glyphs = new glyphset.GlyphSet(font);
39611 // The last element of the loca table is invalid.
39612
39613            for (var i = 0; i < loca.length - 1; i += 1) {
39614              var offset = loca[i];
39615              var nextOffset = loca[i + 1];
39616
39617              if (offset !== nextOffset) {
39618                glyphs.push(i, glyphset.ttfGlyphLoader(font, i, parseGlyph, data, start + offset, buildPath));
39619              } else {
39620                glyphs.push(i, glyphset.glyphLoader(font, i));
39621              }
39622            }
39623
39624            return glyphs;
39625          }
39626
39627          var glyf = {
39628            getPath: getPath,
39629            parse: parseGlyfTable
39630          };
39631          /* A TrueType font hinting interpreter.
39632          *
39633          * (c) 2017 Axel Kittenberger
39634          *
39635          * This interpreter has been implemented according to this documentation:
39636          * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM05/Chap5.html
39637          *
39638          * According to the documentation F24DOT6 values are used for pixels.
39639          * That means calculation is 1/64 pixel accurate and uses integer operations.
39640          * However, Javascript has floating point operations by default and only
39641          * those are available. One could make a case to simulate the 1/64 accuracy
39642          * exactly by truncating after every division operation
39643          * (for example with << 0) to get pixel exactly results as other TrueType
39644          * implementations. It may make sense since some fonts are pixel optimized
39645          * by hand using DELTAP instructions. The current implementation doesn't
39646          * and rather uses full floating point precision.
39647          *
39648          * xScale, yScale and rotation is currently ignored.
39649          *
39650          * A few non-trivial instructions are missing as I didn't encounter yet
39651          * a font that used them to test a possible implementation.
39652          *
39653          * Some fonts seem to use undocumented features regarding the twilight zone.
39654          * Only some of them are implemented as they were encountered.
39655          *
39656          * The exports.DEBUG statements are removed on the minified distribution file.
39657          */
39658
39659          var instructionTable;
39660          var exec;
39661          var execGlyph;
39662          var execComponent;
39663          /*
39664          * Creates a hinting object.
39665          *
39666          * There ought to be exactly one
39667          * for each truetype font that is used for hinting.
39668          */
39669
39670          function Hinting(font) {
39671            // the font this hinting object is for
39672            this.font = font;
39673
39674            this.getCommands = function (hPoints) {
39675              return glyf.getPath(hPoints).commands;
39676            }; // cached states
39677
39678
39679            this._fpgmState = this._prepState = undefined; // errorState
39680            // 0 ... all okay
39681            // 1 ... had an error in a glyf,
39682            //       continue working but stop spamming
39683            //       the console
39684            // 2 ... error at prep, stop hinting at this ppem
39685            // 3 ... error at fpeg, stop hinting for this font at all
39686
39687            this._errorState = 0;
39688          }
39689          /*
39690          * Not rounding.
39691          */
39692
39693
39694          function roundOff(v) {
39695            return v;
39696          }
39697          /*
39698          * Rounding to grid.
39699          */
39700
39701
39702          function roundToGrid(v) {
39703            //Rounding in TT is supposed to "symmetrical around zero"
39704            return Math.sign(v) * Math.round(Math.abs(v));
39705          }
39706          /*
39707          * Rounding to double grid.
39708          */
39709
39710
39711          function roundToDoubleGrid(v) {
39712            return Math.sign(v) * Math.round(Math.abs(v * 2)) / 2;
39713          }
39714          /*
39715          * Rounding to half grid.
39716          */
39717
39718
39719          function roundToHalfGrid(v) {
39720            return Math.sign(v) * (Math.round(Math.abs(v) + 0.5) - 0.5);
39721          }
39722          /*
39723          * Rounding to up to grid.
39724          */
39725
39726
39727          function roundUpToGrid(v) {
39728            return Math.sign(v) * Math.ceil(Math.abs(v));
39729          }
39730          /*
39731          * Rounding to down to grid.
39732          */
39733
39734
39735          function roundDownToGrid(v) {
39736            return Math.sign(v) * Math.floor(Math.abs(v));
39737          }
39738          /*
39739          * Super rounding.
39740          */
39741
39742
39743          var roundSuper = function (v) {
vendor: 71,121 bytes, lines 39744-42332
39744            var period = this.srPeriod;
39745            var phase = this.srPhase;
39746            var threshold = this.srThreshold;
39747            var sign = 1;
39748
39749            if (v < 0) {
39750              v = -v;
39751              sign = -1;
39752            }
39753
39754            v += threshold - phase;
39755            v = Math.trunc(v / period) * period;
39756            v += phase; // according to http://xgridfit.sourceforge.net/round.html
39757
39758            if (v < 0) {
39759              return phase * sign;
39760            }
39761
39762            return v * sign;
39763          };
39764          /*
39765          * Unit vector of x-axis.
39766          */
39767
39768
39769          var xUnitVector = {
39770            x: 1,
39771            y: 0,
39772            axis: 'x',
39773            // Gets the projected distance between two points.
39774            // o1/o2 ... if true, respective original position is used.
39775            distance: function (p1, p2, o1, o2) {
39776              return (o1 ? p1.xo : p1.x) - (o2 ? p2.xo : p2.x);
39777            },
39778            // Moves point p so the moved position has the same relative
39779            // position to the moved positions of rp1 and rp2 than the
39780            // original positions had.
39781            //
39782            // See APPENDIX on INTERPOLATE at the bottom of this file.
39783            interpolate: function (p, rp1, rp2, pv) {
39784              var do1;
39785              var do2;
39786              var doa1;
39787              var doa2;
39788              var dm1;
39789              var dm2;
39790              var dt;
39791
39792              if (!pv || pv === this) {
39793                do1 = p.xo - rp1.xo;
39794                do2 = p.xo - rp2.xo;
39795                dm1 = rp1.x - rp1.xo;
39796                dm2 = rp2.x - rp2.xo;
39797                doa1 = Math.abs(do1);
39798                doa2 = Math.abs(do2);
39799                dt = doa1 + doa2;
39800
39801                if (dt === 0) {
39802                  p.x = p.xo + (dm1 + dm2) / 2;
39803                  return;
39804                }
39805
39806                p.x = p.xo + (dm1 * doa2 + dm2 * doa1) / dt;
39807                return;
39808              }
39809
39810              do1 = pv.distance(p, rp1, true, true);
39811              do2 = pv.distance(p, rp2, true, true);
39812              dm1 = pv.distance(rp1, rp1, false, true);
39813              dm2 = pv.distance(rp2, rp2, false, true);
39814              doa1 = Math.abs(do1);
39815              doa2 = Math.abs(do2);
39816              dt = doa1 + doa2;
39817
39818              if (dt === 0) {
39819                xUnitVector.setRelative(p, p, (dm1 + dm2) / 2, pv, true);
39820                return;
39821              }
39822
39823              xUnitVector.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true);
39824            },
39825            // Slope of line normal to this
39826            normalSlope: Number.NEGATIVE_INFINITY,
39827            // Sets the point 'p' relative to point 'rp'
39828            // by the distance 'd'.
39829            //
39830            // See APPENDIX on SETRELATIVE at the bottom of this file.
39831            //
39832            // p   ... point to set
39833            // rp  ... reference point
39834            // d   ... distance on projection vector
39835            // pv  ... projection vector (undefined = this)
39836            // org ... if true, uses the original position of rp as reference.
39837            setRelative: function (p, rp, d, pv, org) {
39838              if (!pv || pv === this) {
39839                p.x = (org ? rp.xo : rp.x) + d;
39840                return;
39841              }
39842
39843              var rpx = org ? rp.xo : rp.x;
39844              var rpy = org ? rp.yo : rp.y;
39845              var rpdx = rpx + d * pv.x;
39846              var rpdy = rpy + d * pv.y;
39847              p.x = rpdx + (p.y - rpdy) / pv.normalSlope;
39848            },
39849            // Slope of vector line.
39850            slope: 0,
39851            // Touches the point p.
39852            touch: function (p) {
39853              p.xTouched = true;
39854            },
39855            // Tests if a point p is touched.
39856            touched: function (p) {
39857              return p.xTouched;
39858            },
39859            // Untouches the point p.
39860            untouch: function (p) {
39861              p.xTouched = false;
39862            }
39863          };
39864          /*
39865          * Unit vector of y-axis.
39866          */
39867
39868          var yUnitVector = {
39869            x: 0,
39870            y: 1,
39871            axis: 'y',
39872            // Gets the projected distance between two points.
39873            // o1/o2 ... if true, respective original position is used.
39874            distance: function (p1, p2, o1, o2) {
39875              return (o1 ? p1.yo : p1.y) - (o2 ? p2.yo : p2.y);
39876            },
39877            // Moves point p so the moved position has the same relative
39878            // position to the moved positions of rp1 and rp2 than the
39879            // original positions had.
39880            //
39881            // See APPENDIX on INTERPOLATE at the bottom of this file.
39882            interpolate: function (p, rp1, rp2, pv) {
39883              var do1;
39884              var do2;
39885              var doa1;
39886              var doa2;
39887              var dm1;
39888              var dm2;
39889              var dt;
39890
39891              if (!pv || pv === this) {
39892                do1 = p.yo - rp1.yo;
39893                do2 = p.yo - rp2.yo;
39894                dm1 = rp1.y - rp1.yo;
39895                dm2 = rp2.y - rp2.yo;
39896                doa1 = Math.abs(do1);
39897                doa2 = Math.abs(do2);
39898                dt = doa1 + doa2;
39899
39900                if (dt === 0) {
39901                  p.y = p.yo + (dm1 + dm2) / 2;
39902                  return;
39903                }
39904
39905                p.y = p.yo + (dm1 * doa2 + dm2 * doa1) / dt;
39906                return;
39907              }
39908
39909              do1 = pv.distance(p, rp1, true, true);
39910              do2 = pv.distance(p, rp2, true, true);
39911              dm1 = pv.distance(rp1, rp1, false, true);
39912              dm2 = pv.distance(rp2, rp2, false, true);
39913              doa1 = Math.abs(do1);
39914              doa2 = Math.abs(do2);
39915              dt = doa1 + doa2;
39916
39917              if (dt === 0) {
39918                yUnitVector.setRelative(p, p, (dm1 + dm2) / 2, pv, true);
39919                return;
39920              }
39921
39922              yUnitVector.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true);
39923            },
39924            // Slope of line normal to this.
39925            normalSlope: 0,
39926            // Sets the point 'p' relative to point 'rp'
39927            // by the distance 'd'
39928            //
39929            // See APPENDIX on SETRELATIVE at the bottom of this file.
39930            //
39931            // p   ... point to set
39932            // rp  ... reference point
39933            // d   ... distance on projection vector
39934            // pv  ... projection vector (undefined = this)
39935            // org ... if true, uses the original position of rp as reference.
39936            setRelative: function (p, rp, d, pv, org) {
39937              if (!pv || pv === this) {
39938                p.y = (org ? rp.yo : rp.y) + d;
39939                return;
39940              }
39941
39942              var rpx = org ? rp.xo : rp.x;
39943              var rpy = org ? rp.yo : rp.y;
39944              var rpdx = rpx + d * pv.x;
39945              var rpdy = rpy + d * pv.y;
39946              p.y = rpdy + pv.normalSlope * (p.x - rpdx);
39947            },
39948            // Slope of vector line.
39949            slope: Number.POSITIVE_INFINITY,
39950            // Touches the point p.
39951            touch: function (p) {
39952              p.yTouched = true;
39953            },
39954            // Tests if a point p is touched.
39955            touched: function (p) {
39956              return p.yTouched;
39957            },
39958            // Untouches the point p.
39959            untouch: function (p) {
39960              p.yTouched = false;
39961            }
39962          };
39963          Object.freeze(xUnitVector);
39964          Object.freeze(yUnitVector);
39965          /*
39966          * Creates a unit vector that is not x- or y-axis.
39967          */
39968
39969          function UnitVector(x, y) {
39970            this.x = x;
39971            this.y = y;
39972            this.axis = undefined;
39973            this.slope = y / x;
39974            this.normalSlope = -x / y;
39975            Object.freeze(this);
39976          }
39977          /*
39978          * Gets the projected distance between two points.
39979          * o1/o2 ... if true, respective original position is used.
39980          */
39981
39982
39983          UnitVector.prototype.distance = function (p1, p2, o1, o2) {
39984            return this.x * xUnitVector.distance(p1, p2, o1, o2) + this.y * yUnitVector.distance(p1, p2, o1, o2);
39985          };
39986          /*
39987          * Moves point p so the moved position has the same relative
39988          * position to the moved positions of rp1 and rp2 than the
39989          * original positions had.
39990          *
39991          * See APPENDIX on INTERPOLATE at the bottom of this file.
39992          */
39993
39994
39995          UnitVector.prototype.interpolate = function (p, rp1, rp2, pv) {
39996            var dm1;
39997            var dm2;
39998            var do1;
39999            var do2;
40000            var doa1;
40001            var doa2;
40002            var dt;
40003            do1 = pv.distance(p, rp1, true, true);
40004            do2 = pv.distance(p, rp2, true, true);
40005            dm1 = pv.distance(rp1, rp1, false, true);
40006            dm2 = pv.distance(rp2, rp2, false, true);
40007            doa1 = Math.abs(do1);
40008            doa2 = Math.abs(do2);
40009            dt = doa1 + doa2;
40010
40011            if (dt === 0) {
40012              this.setRelative(p, p, (dm1 + dm2) / 2, pv, true);
40013              return;
40014            }
40015
40016            this.setRelative(p, p, (dm1 * doa2 + dm2 * doa1) / dt, pv, true);
40017          };
40018          /*
40019          * Sets the point 'p' relative to point 'rp'
40020          * by the distance 'd'
40021          *
40022          * See APPENDIX on SETRELATIVE at the bottom of this file.
40023          *
40024          * p   ...  point to set
40025          * rp  ... reference point
40026          * d   ... distance on projection vector
40027          * pv  ... projection vector (undefined = this)
40028          * org ... if true, uses the original position of rp as reference.
40029          */
40030
40031
40032          UnitVector.prototype.setRelative = function (p, rp, d, pv, org) {
40033            pv = pv || this;
40034            var rpx = org ? rp.xo : rp.x;
40035            var rpy = org ? rp.yo : rp.y;
40036            var rpdx = rpx + d * pv.x;
40037            var rpdy = rpy + d * pv.y;
40038            var pvns = pv.normalSlope;
40039            var fvs = this.slope;
40040            var px = p.x;
40041            var py = p.y;
40042            p.x = (fvs * px - pvns * rpdx + rpdy - py) / (fvs - pvns);
40043            p.y = fvs * (p.x - px) + py;
40044          };
40045          /*
40046          * Touches the point p.
40047          */
40048
40049
40050          UnitVector.prototype.touch = function (p) {
40051            p.xTouched = true;
40052            p.yTouched = true;
40053          };
40054          /*
40055          * Returns a unit vector with x/y coordinates.
40056          */
40057
40058
40059          function getUnitVector(x, y) {
40060            var d = Math.sqrt(x * x + y * y);
40061            x /= d;
40062            y /= d;
40063
40064            if (x === 1 && y === 0) {
40065              return xUnitVector;
40066            } else if (x === 0 && y === 1) {
40067              return yUnitVector;
40068            } else {
40069              return new UnitVector(x, y);
40070            }
40071          }
40072          /*
40073          * Creates a point in the hinting engine.
40074          */
40075
40076
40077          function HPoint(x, y, lastPointOfContour, onCurve) {
40078            this.x = this.xo = Math.round(x * 64) / 64; // hinted x value and original x-value
40079
40080            this.y = this.yo = Math.round(y * 64) / 64; // hinted y value and original y-value
40081
40082            this.lastPointOfContour = lastPointOfContour;
40083            this.onCurve = onCurve;
40084            this.prevPointOnContour = undefined;
40085            this.nextPointOnContour = undefined;
40086            this.xTouched = false;
40087            this.yTouched = false;
40088            Object.preventExtensions(this);
40089          }
40090          /*
40091          * Returns the next touched point on the contour.
40092          *
40093          * v  ... unit vector to test touch axis.
40094          */
40095
40096
40097          HPoint.prototype.nextTouched = function (v) {
40098            var p = this.nextPointOnContour;
40099
40100            while (!v.touched(p) && p !== this) {
40101              p = p.nextPointOnContour;
40102            }
40103
40104            return p;
40105          };
40106          /*
40107          * Returns the previous touched point on the contour
40108          *
40109          * v  ... unit vector to test touch axis.
40110          */
40111
40112
40113          HPoint.prototype.prevTouched = function (v) {
40114            var p = this.prevPointOnContour;
40115
40116            while (!v.touched(p) && p !== this) {
40117              p = p.prevPointOnContour;
40118            }
40119
40120            return p;
40121          };
40122          /*
40123          * The zero point.
40124          */
40125
40126
40127          var HPZero = Object.freeze(new HPoint(0, 0));
40128          /*
40129          * The default state of the interpreter.
40130          *
40131          * Note: Freezing the defaultState and then deriving from it
40132          * makes the V8 Javascript engine going awkward,
40133          * so this is avoided, albeit the defaultState shouldn't
40134          * ever change.
40135          */
40136
40137          var defaultState = {
40138            cvCutIn: 17 / 16,
40139            // control value cut in
40140            deltaBase: 9,
40141            deltaShift: 0.125,
40142            loop: 1,
40143            // loops some instructions
40144            minDis: 1,
40145            // minimum distance
40146            autoFlip: true
40147          };
40148          /*
40149          * The current state of the interpreter.
40150          *
40151          * env  ... 'fpgm' or 'prep' or 'glyf'
40152          * prog ... the program
40153          */
40154
40155          function State(env, prog) {
40156            this.env = env;
40157            this.stack = [];
40158            this.prog = prog;
40159
40160            switch (env) {
40161              case 'glyf':
40162                this.zp0 = this.zp1 = this.zp2 = 1;
40163                this.rp0 = this.rp1 = this.rp2 = 0;
40164
40165              /* fall through */
40166
40167              case 'prep':
40168                this.fv = this.pv = this.dpv = xUnitVector;
40169                this.round = roundToGrid;
40170            }
40171          }
40172          /*
40173          * Executes a glyph program.
40174          *
40175          * This does the hinting for each glyph.
40176          *
40177          * Returns an array of moved points.
40178          *
40179          * glyph: the glyph to hint
40180          * ppem: the size the glyph is rendered for
40181          */
40182
40183
40184          Hinting.prototype.exec = function (glyph, ppem) {
40185            if (typeof ppem !== 'number') {
40186              throw new Error('Point size is not a number!');
40187            } // Received a fatal error, don't do any hinting anymore.
40188
40189
40190            if (this._errorState > 2) {
40191              return;
40192            }
40193
40194            var font = this.font;
40195            var prepState = this._prepState;
40196
40197            if (!prepState || prepState.ppem !== ppem) {
40198              var fpgmState = this._fpgmState;
40199
40200              if (!fpgmState) {
40201                // Executes the fpgm state.
40202                // This is used by fonts to define functions.
40203                State.prototype = defaultState;
40204                fpgmState = this._fpgmState = new State('fpgm', font.tables.fpgm);
40205                fpgmState.funcs = [];
40206                fpgmState.font = font;
40207
40208                if (exports.DEBUG) {
40209                  console.log('---EXEC FPGM---');
40210                  fpgmState.step = -1;
40211                }
40212
40213                try {
40214                  exec(fpgmState);
40215                } catch (e) {
40216                  console.log('Hinting error in FPGM:' + e);
40217                  this._errorState = 3;
40218                  return;
40219                }
40220              } // Executes the prep program for this ppem setting.
40221              // This is used by fonts to set cvt values
40222              // depending on to be rendered font size.
40223
40224
40225              State.prototype = fpgmState;
40226              prepState = this._prepState = new State('prep', font.tables.prep);
40227              prepState.ppem = ppem; // Creates a copy of the cvt table
40228              // and scales it to the current ppem setting.
40229
40230              var oCvt = font.tables.cvt;
40231
40232              if (oCvt) {
40233                var cvt = prepState.cvt = new Array(oCvt.length);
40234                var scale = ppem / font.unitsPerEm;
40235
40236                for (var c = 0; c < oCvt.length; c++) {
40237                  cvt[c] = oCvt[c] * scale;
40238                }
40239              } else {
40240                prepState.cvt = [];
40241              }
40242
40243              if (exports.DEBUG) {
40244                console.log('---EXEC PREP---');
40245                prepState.step = -1;
40246              }
40247
40248              try {
40249                exec(prepState);
40250              } catch (e) {
40251                if (this._errorState < 2) {
40252                  console.log('Hinting error in PREP:' + e);
40253                }
40254
40255                this._errorState = 2;
40256              }
40257            }
40258
40259            if (this._errorState > 1) {
40260              return;
40261            }
40262
40263            try {
40264              return execGlyph(glyph, prepState);
40265            } catch (e) {
40266              if (this._errorState < 1) {
40267                console.log('Hinting error:' + e);
40268                console.log('Note: further hinting errors are silenced');
40269              }
40270
40271              this._errorState = 1;
40272              return undefined;
40273            }
40274          };
40275          /*
40276          * Executes the hinting program for a glyph.
40277          */
40278
40279
40280          execGlyph = function (glyph, prepState) {
40281            // original point positions
40282            var xScale = prepState.ppem / prepState.font.unitsPerEm;
40283            var yScale = xScale;
40284            var components = glyph.components;
40285            var contours;
40286            var gZone;
40287            var state;
40288            State.prototype = prepState;
40289
40290            if (!components) {
40291              state = new State('glyf', glyph.instructions);
40292
40293              if (exports.DEBUG) {
40294                console.log('---EXEC GLYPH---');
40295                state.step = -1;
40296              }
40297
40298              execComponent(glyph, state, xScale, yScale);
40299              gZone = state.gZone;
40300            } else {
40301              var font = prepState.font;
40302              gZone = [];
40303              contours = [];
40304
40305              for (var i = 0; i < components.length; i++) {
40306                var c = components[i];
40307                var cg = font.glyphs.get(c.glyphIndex);
40308                state = new State('glyf', cg.instructions);
40309
40310                if (exports.DEBUG) {
40311                  console.log('---EXEC COMP ' + i + '---');
40312                  state.step = -1;
40313                }
40314
40315                execComponent(cg, state, xScale, yScale); // appends the computed points to the result array
40316                // post processes the component points
40317
40318                var dx = Math.round(c.dx * xScale);
40319                var dy = Math.round(c.dy * yScale);
40320                var gz = state.gZone;
40321                var cc = state.contours;
40322
40323                for (var pi = 0; pi < gz.length; pi++) {
40324                  var p = gz[pi];
40325                  p.xTouched = p.yTouched = false;
40326                  p.xo = p.x = p.x + dx;
40327                  p.yo = p.y = p.y + dy;
40328                }
40329
40330                var gLen = gZone.length;
40331                gZone.push.apply(gZone, gz);
40332
40333                for (var j = 0; j < cc.length; j++) {
40334                  contours.push(cc[j] + gLen);
40335                }
40336              }
40337
40338              if (glyph.instructions && !state.inhibitGridFit) {
40339                // the composite has instructions on its own
40340                state = new State('glyf', glyph.instructions);
40341                state.gZone = state.z0 = state.z1 = state.z2 = gZone;
40342                state.contours = contours; // note: HPZero cannot be used here, since
40343                //       the point might be modified
40344
40345                gZone.push(new HPoint(0, 0), new HPoint(Math.round(glyph.advanceWidth * xScale), 0));
40346
40347                if (exports.DEBUG) {
40348                  console.log('---EXEC COMPOSITE---');
40349                  state.step = -1;
40350                }
40351
40352                exec(state);
40353                gZone.length -= 2;
40354              }
40355            }
40356
40357            return gZone;
40358          };
40359          /*
40360          * Executes the hinting program for a component of a multi-component glyph
40361          * or of the glyph itself for a non-component glyph.
40362          */
40363
40364
40365          execComponent = function (glyph, state, xScale, yScale) {
40366            var points = glyph.points || [];
40367            var pLen = points.length;
40368            var gZone = state.gZone = state.z0 = state.z1 = state.z2 = [];
40369            var contours = state.contours = []; // Scales the original points and
40370            // makes copies for the hinted points.
40371
40372            var cp; // current point
40373
40374            for (var i = 0; i < pLen; i++) {
40375              cp = points[i];
40376              gZone[i] = new HPoint(cp.x * xScale, cp.y * yScale, cp.lastPointOfContour, cp.onCurve);
40377            } // Chain links the contours.
40378
40379
40380            var sp; // start point
40381
40382            var np; // next point
40383
40384            for (var i$1 = 0; i$1 < pLen; i$1++) {
40385              cp = gZone[i$1];
40386
40387              if (!sp) {
40388                sp = cp;
40389                contours.push(i$1);
40390              }
40391
40392              if (cp.lastPointOfContour) {
40393                cp.nextPointOnContour = sp;
40394                sp.prevPointOnContour = cp;
40395                sp = undefined;
40396              } else {
40397                np = gZone[i$1 + 1];
40398                cp.nextPointOnContour = np;
40399                np.prevPointOnContour = cp;
40400              }
40401            }
40402
40403            if (state.inhibitGridFit) {
40404              return;
40405            }
40406
40407            if (exports.DEBUG) {
40408              console.log('PROCESSING GLYPH', state.stack);
40409
40410              for (var i$2 = 0; i$2 < pLen; i$2++) {
40411                console.log(i$2, gZone[i$2].x, gZone[i$2].y);
40412              }
40413            }
40414
40415            gZone.push(new HPoint(0, 0), new HPoint(Math.round(glyph.advanceWidth * xScale), 0));
40416            exec(state); // Removes the extra points.
40417
40418            gZone.length -= 2;
40419
40420            if (exports.DEBUG) {
40421              console.log('FINISHED GLYPH', state.stack);
40422
40423              for (var i$3 = 0; i$3 < pLen; i$3++) {
40424                console.log(i$3, gZone[i$3].x, gZone[i$3].y);
40425              }
40426            }
40427          };
40428          /*
40429          * Executes the program loaded in state.
40430          */
40431
40432
40433          exec = function (state) {
40434            var prog = state.prog;
40435
40436            if (!prog) {
40437              return;
40438            }
40439
40440            var pLen = prog.length;
40441            var ins;
40442
40443            for (state.ip = 0; state.ip < pLen; state.ip++) {
40444              if (exports.DEBUG) {
40445                state.step++;
40446              }
40447
40448              ins = instructionTable[prog[state.ip]];
40449
40450              if (!ins) {
40451                throw new Error('unknown instruction: 0x' + Number(prog[state.ip]).toString(16));
40452              }
40453
40454              ins(state); // very extensive debugging for each step
40455
40456              /*
40457              if (exports.DEBUG) {
40458                  var da;
40459                  if (state.gZone) {
40460                      da = [];
40461                      for (let i = 0; i < state.gZone.length; i++)
40462                      {
40463                          da.push(i + ' ' +
40464                              state.gZone[i].x * 64 + ' ' +
40465                              state.gZone[i].y * 64 + ' ' +
40466                              (state.gZone[i].xTouched ? 'x' : '') +
40467                              (state.gZone[i].yTouched ? 'y' : '')
40468                          );
40469                      }
40470                      console.log('GZ', da);
40471                  }
40472                   if (state.tZone) {
40473                      da = [];
40474                      for (let i = 0; i < state.tZone.length; i++) {
40475                          da.push(i + ' ' +
40476                              state.tZone[i].x * 64 + ' ' +
40477                              state.tZone[i].y * 64 + ' ' +
40478                              (state.tZone[i].xTouched ? 'x' : '') +
40479                              (state.tZone[i].yTouched ? 'y' : '')
40480                          );
40481                      }
40482                      console.log('TZ', da);
40483                  }
40484                   if (state.stack.length > 10) {
40485                      console.log(
40486                          state.stack.length,
40487                          '...', state.stack.slice(state.stack.length - 10)
40488                      );
40489                  } else {
40490                      console.log(state.stack.length, state.stack);
40491                  }
40492              }
40493              */
40494            }
40495          };
40496          /*
40497          * Initializes the twilight zone.
40498          *
40499          * This is only done if a SZPx instruction
40500          * refers to the twilight zone.
40501          */
40502
40503
40504          function initTZone(state) {
40505            var tZone = state.tZone = new Array(state.gZone.length); // no idea if this is actually correct...
40506
40507            for (var i = 0; i < tZone.length; i++) {
40508              tZone[i] = new HPoint(0, 0);
40509            }
40510          }
40511          /*
40512          * Skips the instruction pointer ahead over an IF/ELSE block.
40513          * handleElse .. if true breaks on matching ELSE
40514          */
40515
40516
40517          function skip(state, handleElse) {
40518            var prog = state.prog;
40519            var ip = state.ip;
40520            var nesting = 1;
40521            var ins;
40522
40523            do {
40524              ins = prog[++ip];
40525
40526              if (ins === 0x58) // IF
40527                {
40528                  nesting++;
40529                } else if (ins === 0x59) // EIF
40530                {
40531                  nesting--;
40532                } else if (ins === 0x40) // NPUSHB
40533                {
40534                  ip += prog[ip + 1] + 1;
40535                } else if (ins === 0x41) // NPUSHW
40536                {
40537                  ip += 2 * prog[ip + 1] + 1;
40538                } else if (ins >= 0xB0 && ins <= 0xB7) // PUSHB
40539                {
40540                  ip += ins - 0xB0 + 1;
40541                } else if (ins >= 0xB8 && ins <= 0xBF) // PUSHW
40542                {
40543                  ip += (ins - 0xB8 + 1) * 2;
40544                } else if (handleElse && nesting === 1 && ins === 0x1B) // ELSE
40545                {
40546                  break;
40547                }
40548            } while (nesting > 0);
40549
40550            state.ip = ip;
40551          }
40552          /*----------------------------------------------------------*
40553          *          And then a lot of instructions...                *
40554          *----------------------------------------------------------*/
40555          // SVTCA[a] Set freedom and projection Vectors To Coordinate Axis
40556          // 0x00-0x01
40557
40558
40559          function SVTCA(v, state) {
40560            if (exports.DEBUG) {
40561              console.log(state.step, 'SVTCA[' + v.axis + ']');
40562            }
40563
40564            state.fv = state.pv = state.dpv = v;
40565          } // SPVTCA[a] Set Projection Vector to Coordinate Axis
40566          // 0x02-0x03
40567
40568
40569          function SPVTCA(v, state) {
40570            if (exports.DEBUG) {
40571              console.log(state.step, 'SPVTCA[' + v.axis + ']');
40572            }
40573
40574            state.pv = state.dpv = v;
40575          } // SFVTCA[a] Set Freedom Vector to Coordinate Axis
40576          // 0x04-0x05
40577
40578
40579          function SFVTCA(v, state) {
40580            if (exports.DEBUG) {
40581              console.log(state.step, 'SFVTCA[' + v.axis + ']');
40582            }
40583
40584            state.fv = v;
40585          } // SPVTL[a] Set Projection Vector To Line
40586          // 0x06-0x07
40587
40588
40589          function SPVTL(a, state) {
40590            var stack = state.stack;
40591            var p2i = stack.pop();
40592            var p1i = stack.pop();
40593            var p2 = state.z2[p2i];
40594            var p1 = state.z1[p1i];
40595
40596            if (exports.DEBUG) {
40597              console.log('SPVTL[' + a + ']', p2i, p1i);
40598            }
40599
40600            var dx;
40601            var dy;
40602
40603            if (!a) {
40604              dx = p1.x - p2.x;
40605              dy = p1.y - p2.y;
40606            } else {
40607              dx = p2.y - p1.y;
40608              dy = p1.x - p2.x;
40609            }
40610
40611            state.pv = state.dpv = getUnitVector(dx, dy);
40612          } // SFVTL[a] Set Freedom Vector To Line
40613          // 0x08-0x09
40614
40615
40616          function SFVTL(a, state) {
40617            var stack = state.stack;
40618            var p2i = stack.pop();
40619            var p1i = stack.pop();
40620            var p2 = state.z2[p2i];
40621            var p1 = state.z1[p1i];
40622
40623            if (exports.DEBUG) {
40624              console.log('SFVTL[' + a + ']', p2i, p1i);
40625            }
40626
40627            var dx;
40628            var dy;
40629
40630            if (!a) {
40631              dx = p1.x - p2.x;
40632              dy = p1.y - p2.y;
40633            } else {
40634              dx = p2.y - p1.y;
40635              dy = p1.x - p2.x;
40636            }
40637
40638            state.fv = getUnitVector(dx, dy);
40639          } // SPVFS[] Set Projection Vector From Stack
40640          // 0x0A
40641
40642
40643          function SPVFS(state) {
40644            var stack = state.stack;
40645            var y = stack.pop();
40646            var x = stack.pop();
40647
40648            if (exports.DEBUG) {
40649              console.log(state.step, 'SPVFS[]', y, x);
40650            }
40651
40652            state.pv = state.dpv = getUnitVector(x, y);
40653          } // SFVFS[] Set Freedom Vector From Stack
40654          // 0x0B
40655
40656
40657          function SFVFS(state) {
40658            var stack = state.stack;
40659            var y = stack.pop();
40660            var x = stack.pop();
40661
40662            if (exports.DEBUG) {
40663              console.log(state.step, 'SPVFS[]', y, x);
40664            }
40665
40666            state.fv = getUnitVector(x, y);
40667          } // GPV[] Get Projection Vector
40668          // 0x0C
40669
40670
40671          function GPV(state) {
40672            var stack = state.stack;
40673            var pv = state.pv;
40674
40675            if (exports.DEBUG) {
40676              console.log(state.step, 'GPV[]');
40677            }
40678
40679            stack.push(pv.x * 0x4000);
40680            stack.push(pv.y * 0x4000);
40681          } // GFV[] Get Freedom Vector
40682          // 0x0C
40683
40684
40685          function GFV(state) {
40686            var stack = state.stack;
40687            var fv = state.fv;
40688
40689            if (exports.DEBUG) {
40690              console.log(state.step, 'GFV[]');
40691            }
40692
40693            stack.push(fv.x * 0x4000);
40694            stack.push(fv.y * 0x4000);
40695          } // SFVTPV[] Set Freedom Vector To Projection Vector
40696          // 0x0E
40697
40698
40699          function SFVTPV(state) {
40700            state.fv = state.pv;
40701
40702            if (exports.DEBUG) {
40703              console.log(state.step, 'SFVTPV[]');
40704            }
40705          } // ISECT[] moves point p to the InterSECTion of two lines
40706          // 0x0F
40707
40708
40709          function ISECT(state) {
40710            var stack = state.stack;
40711            var pa0i = stack.pop();
40712            var pa1i = stack.pop();
40713            var pb0i = stack.pop();
40714            var pb1i = stack.pop();
40715            var pi = stack.pop();
40716            var z0 = state.z0;
40717            var z1 = state.z1;
40718            var pa0 = z0[pa0i];
40719            var pa1 = z0[pa1i];
40720            var pb0 = z1[pb0i];
40721            var pb1 = z1[pb1i];
40722            var p = state.z2[pi];
40723
40724            if (exports.DEBUG) {
40725              console.log('ISECT[], ', pa0i, pa1i, pb0i, pb1i, pi);
40726            } // math from
40727            // en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
40728
40729
40730            var x1 = pa0.x;
40731            var y1 = pa0.y;
40732            var x2 = pa1.x;
40733            var y2 = pa1.y;
40734            var x3 = pb0.x;
40735            var y3 = pb0.y;
40736            var x4 = pb1.x;
40737            var y4 = pb1.y;
40738            var div = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
40739            var f1 = x1 * y2 - y1 * x2;
40740            var f2 = x3 * y4 - y3 * x4;
40741            p.x = (f1 * (x3 - x4) - f2 * (x1 - x2)) / div;
40742            p.y = (f1 * (y3 - y4) - f2 * (y1 - y2)) / div;
40743          } // SRP0[] Set Reference Point 0
40744          // 0x10
40745
40746
40747          function SRP0(state) {
40748            state.rp0 = state.stack.pop();
40749
40750            if (exports.DEBUG) {
40751              console.log(state.step, 'SRP0[]', state.rp0);
40752            }
40753          } // SRP1[] Set Reference Point 1
40754          // 0x11
40755
40756
40757          function SRP1(state) {
40758            state.rp1 = state.stack.pop();
40759
40760            if (exports.DEBUG) {
40761              console.log(state.step, 'SRP1[]', state.rp1);
40762            }
40763          } // SRP1[] Set Reference Point 2
40764          // 0x12
40765
40766
40767          function SRP2(state) {
40768            state.rp2 = state.stack.pop();
40769
40770            if (exports.DEBUG) {
40771              console.log(state.step, 'SRP2[]', state.rp2);
40772            }
40773          } // SZP0[] Set Zone Pointer 0
40774          // 0x13
40775
40776
40777          function SZP0(state) {
40778            var n = state.stack.pop();
40779
40780            if (exports.DEBUG) {
40781              console.log(state.step, 'SZP0[]', n);
40782            }
40783
40784            state.zp0 = n;
40785
40786            switch (n) {
40787              case 0:
40788                if (!state.tZone) {
40789                  initTZone(state);
40790                }
40791
40792                state.z0 = state.tZone;
40793                break;
40794
40795              case 1:
40796                state.z0 = state.gZone;
40797                break;
40798
40799              default:
40800                throw new Error('Invalid zone pointer');
40801            }
40802          } // SZP1[] Set Zone Pointer 1
40803          // 0x14
40804
40805
40806          function SZP1(state) {
40807            var n = state.stack.pop();
40808
40809            if (exports.DEBUG) {
40810              console.log(state.step, 'SZP1[]', n);
40811            }
40812
40813            state.zp1 = n;
40814
40815            switch (n) {
40816              case 0:
40817                if (!state.tZone) {
40818                  initTZone(state);
40819                }
40820
40821                state.z1 = state.tZone;
40822                break;
40823
40824              case 1:
40825                state.z1 = state.gZone;
40826                break;
40827
40828              default:
40829                throw new Error('Invalid zone pointer');
40830            }
40831          } // SZP2[] Set Zone Pointer 2
40832          // 0x15
40833
40834
40835          function SZP2(state) {
40836            var n = state.stack.pop();
40837
40838            if (exports.DEBUG) {
40839              console.log(state.step, 'SZP2[]', n);
40840            }
40841
40842            state.zp2 = n;
40843
40844            switch (n) {
40845              case 0:
40846                if (!state.tZone) {
40847                  initTZone(state);
40848                }
40849
40850                state.z2 = state.tZone;
40851                break;
40852
40853              case 1:
40854                state.z2 = state.gZone;
40855                break;
40856
40857              default:
40858                throw new Error('Invalid zone pointer');
40859            }
40860          } // SZPS[] Set Zone PointerS
40861          // 0x16
40862
40863
40864          function SZPS(state) {
40865            var n = state.stack.pop();
40866
40867            if (exports.DEBUG) {
40868              console.log(state.step, 'SZPS[]', n);
40869            }
40870
40871            state.zp0 = state.zp1 = state.zp2 = n;
40872
40873            switch (n) {
40874              case 0:
40875                if (!state.tZone) {
40876                  initTZone(state);
40877                }
40878
40879                state.z0 = state.z1 = state.z2 = state.tZone;
40880                break;
40881
40882              case 1:
40883                state.z0 = state.z1 = state.z2 = state.gZone;
40884                break;
40885
40886              default:
40887                throw new Error('Invalid zone pointer');
40888            }
40889          } // SLOOP[] Set LOOP variable
40890          // 0x17
40891
40892
40893          function SLOOP(state) {
40894            state.loop = state.stack.pop();
40895
40896            if (exports.DEBUG) {
40897              console.log(state.step, 'SLOOP[]', state.loop);
40898            }
40899          } // RTG[] Round To Grid
40900          // 0x18
40901
40902
40903          function RTG(state) {
40904            if (exports.DEBUG) {
40905              console.log(state.step, 'RTG[]');
40906            }
40907
40908            state.round = roundToGrid;
40909          } // RTHG[] Round To Half Grid
40910          // 0x19
40911
40912
40913          function RTHG(state) {
40914            if (exports.DEBUG) {
40915              console.log(state.step, 'RTHG[]');
40916            }
40917
40918            state.round = roundToHalfGrid;
40919          } // SMD[] Set Minimum Distance
40920          // 0x1A
40921
40922
40923          function SMD(state) {
40924            var d = state.stack.pop();
40925
40926            if (exports.DEBUG) {
40927              console.log(state.step, 'SMD[]', d);
40928            }
40929
40930            state.minDis = d / 0x40;
40931          } // ELSE[] ELSE clause
40932          // 0x1B
40933
40934
40935          function ELSE(state) {
40936            // This instruction has been reached by executing a then branch
40937            // so it just skips ahead until matching EIF.
40938            //
40939            // In case the IF was negative the IF[] instruction already
40940            // skipped forward over the ELSE[]
40941            if (exports.DEBUG) {
40942              console.log(state.step, 'ELSE[]');
40943            }
40944
40945            skip(state, false);
40946          } // JMPR[] JuMP Relative
40947          // 0x1C
40948
40949
40950          function JMPR(state) {
40951            var o = state.stack.pop();
40952
40953            if (exports.DEBUG) {
40954              console.log(state.step, 'JMPR[]', o);
40955            } // A jump by 1 would do nothing.
40956
40957
40958            state.ip += o - 1;
40959          } // SCVTCI[] Set Control Value Table Cut-In
40960          // 0x1D
40961
40962
40963          function SCVTCI(state) {
40964            var n = state.stack.pop();
40965
40966            if (exports.DEBUG) {
40967              console.log(state.step, 'SCVTCI[]', n);
40968            }
40969
40970            state.cvCutIn = n / 0x40;
40971          } // DUP[] DUPlicate top stack element
40972          // 0x20
40973
40974
40975          function DUP(state) {
40976            var stack = state.stack;
40977
40978            if (exports.DEBUG) {
40979              console.log(state.step, 'DUP[]');
40980            }
40981
40982            stack.push(stack[stack.length - 1]);
40983          } // POP[] POP top stack element
40984          // 0x21
40985
40986
40987          function POP(state) {
40988            if (exports.DEBUG) {
40989              console.log(state.step, 'POP[]');
40990            }
40991
40992            state.stack.pop();
40993          } // CLEAR[] CLEAR the stack
40994          // 0x22
40995
40996
40997          function CLEAR(state) {
40998            if (exports.DEBUG) {
40999              console.log(state.step, 'CLEAR[]');
41000            }
41001
41002            state.stack.length = 0;
41003          } // SWAP[] SWAP the top two elements on the stack
41004          // 0x23
41005
41006
41007          function SWAP(state) {
41008            var stack = state.stack;
41009            var a = stack.pop();
41010            var b = stack.pop();
41011
41012            if (exports.DEBUG) {
41013              console.log(state.step, 'SWAP[]');
41014            }
41015
41016            stack.push(a);
41017            stack.push(b);
41018          } // DEPTH[] DEPTH of the stack
41019          // 0x24
41020
41021
41022          function DEPTH(state) {
41023            var stack = state.stack;
41024
41025            if (exports.DEBUG) {
41026              console.log(state.step, 'DEPTH[]');
41027            }
41028
41029            stack.push(stack.length);
41030          } // LOOPCALL[] LOOPCALL function
41031          // 0x2A
41032
41033
41034          function LOOPCALL(state) {
41035            var stack = state.stack;
41036            var fn = stack.pop();
41037            var c = stack.pop();
41038
41039            if (exports.DEBUG) {
41040              console.log(state.step, 'LOOPCALL[]', fn, c);
41041            } // saves callers program
41042
41043
41044            var cip = state.ip;
41045            var cprog = state.prog;
41046            state.prog = state.funcs[fn]; // executes the function
41047
41048            for (var i = 0; i < c; i++) {
41049              exec(state);
41050
41051              if (exports.DEBUG) {
41052                console.log(++state.step, i + 1 < c ? 'next loopcall' : 'done loopcall', i);
41053              }
41054            } // restores the callers program
41055
41056
41057            state.ip = cip;
41058            state.prog = cprog;
41059          } // CALL[] CALL function
41060          // 0x2B
41061
41062
41063          function CALL(state) {
41064            var fn = state.stack.pop();
41065
41066            if (exports.DEBUG) {
41067              console.log(state.step, 'CALL[]', fn);
41068            } // saves callers program
41069
41070
41071            var cip = state.ip;
41072            var cprog = state.prog;
41073            state.prog = state.funcs[fn]; // executes the function
41074
41075            exec(state); // restores the callers program
41076
41077            state.ip = cip;
41078            state.prog = cprog;
41079
41080            if (exports.DEBUG) {
41081              console.log(++state.step, 'returning from', fn);
41082            }
41083          } // CINDEX[] Copy the INDEXed element to the top of the stack
41084          // 0x25
41085
41086
41087          function CINDEX(state) {
41088            var stack = state.stack;
41089            var k = stack.pop();
41090
41091            if (exports.DEBUG) {
41092              console.log(state.step, 'CINDEX[]', k);
41093            } // In case of k == 1, it copies the last element after popping
41094            // thus stack.length - k.
41095
41096
41097            stack.push(stack[stack.length - k]);
41098          } // MINDEX[] Move the INDEXed element to the top of the stack
41099          // 0x26
41100
41101
41102          function MINDEX(state) {
41103            var stack = state.stack;
41104            var k = stack.pop();
41105
41106            if (exports.DEBUG) {
41107              console.log(state.step, 'MINDEX[]', k);
41108            }
41109
41110            stack.push(stack.splice(stack.length - k, 1)[0]);
41111          } // FDEF[] Function DEFinition
41112          // 0x2C
41113
41114
41115          function FDEF(state) {
41116            if (state.env !== 'fpgm') {
41117              throw new Error('FDEF not allowed here');
41118            }
41119
41120            var stack = state.stack;
41121            var prog = state.prog;
41122            var ip = state.ip;
41123            var fn = stack.pop();
41124            var ipBegin = ip;
41125
41126            if (exports.DEBUG) {
41127              console.log(state.step, 'FDEF[]', fn);
41128            }
41129
41130            while (prog[++ip] !== 0x2D) {}
41131
41132            state.ip = ip;
41133            state.funcs[fn] = prog.slice(ipBegin + 1, ip);
41134          } // MDAP[a] Move Direct Absolute Point
41135          // 0x2E-0x2F
41136
41137
41138          function MDAP(round, state) {
41139            var pi = state.stack.pop();
41140            var p = state.z0[pi];
41141            var fv = state.fv;
41142            var pv = state.pv;
41143
41144            if (exports.DEBUG) {
41145              console.log(state.step, 'MDAP[' + round + ']', pi);
41146            }
41147
41148            var d = pv.distance(p, HPZero);
41149
41150            if (round) {
41151              d = state.round(d);
41152            }
41153
41154            fv.setRelative(p, HPZero, d, pv);
41155            fv.touch(p);
41156            state.rp0 = state.rp1 = pi;
41157          } // IUP[a] Interpolate Untouched Points through the outline
41158          // 0x30
41159
41160
41161          function IUP(v, state) {
41162            var z2 = state.z2;
41163            var pLen = z2.length - 2;
41164            var cp;
41165            var pp;
41166            var np;
41167
41168            if (exports.DEBUG) {
41169              console.log(state.step, 'IUP[' + v.axis + ']');
41170            }
41171
41172            for (var i = 0; i < pLen; i++) {
41173              cp = z2[i]; // current point
41174              // if this point has been touched go on
41175
41176              if (v.touched(cp)) {
41177                continue;
41178              }
41179
41180              pp = cp.prevTouched(v); // no point on the contour has been touched?
41181
41182              if (pp === cp) {
41183                continue;
41184              }
41185
41186              np = cp.nextTouched(v);
41187
41188              if (pp === np) {
41189                // only one point on the contour has been touched
41190                // so simply moves the point like that
41191                v.setRelative(cp, cp, v.distance(pp, pp, false, true), v, true);
41192              }
41193
41194              v.interpolate(cp, pp, np, v);
41195            }
41196          } // SHP[] SHift Point using reference point
41197          // 0x32-0x33
41198
41199
41200          function SHP(a, state) {
41201            var stack = state.stack;
41202            var rpi = a ? state.rp1 : state.rp2;
41203            var rp = (a ? state.z0 : state.z1)[rpi];
41204            var fv = state.fv;
41205            var pv = state.pv;
41206            var loop = state.loop;
41207            var z2 = state.z2;
41208
41209            while (loop--) {
41210              var pi = stack.pop();
41211              var p = z2[pi];
41212              var d = pv.distance(rp, rp, false, true);
41213              fv.setRelative(p, p, d, pv);
41214              fv.touch(p);
41215
41216              if (exports.DEBUG) {
41217                console.log(state.step, (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') + 'SHP[' + (a ? 'rp1' : 'rp2') + ']', pi);
41218              }
41219            }
41220
41221            state.loop = 1;
41222          } // SHC[] SHift Contour using reference point
41223          // 0x36-0x37
41224
41225
41226          function SHC(a, state) {
41227            var stack = state.stack;
41228            var rpi = a ? state.rp1 : state.rp2;
41229            var rp = (a ? state.z0 : state.z1)[rpi];
41230            var fv = state.fv;
41231            var pv = state.pv;
41232            var ci = stack.pop();
41233            var sp = state.z2[state.contours[ci]];
41234            var p = sp;
41235
41236            if (exports.DEBUG) {
41237              console.log(state.step, 'SHC[' + a + ']', ci);
41238            }
41239
41240            var d = pv.distance(rp, rp, false, true);
41241
41242            do {
41243              if (p !== rp) {
41244                fv.setRelative(p, p, d, pv);
41245              }
41246
41247              p = p.nextPointOnContour;
41248            } while (p !== sp);
41249          } // SHZ[] SHift Zone using reference point
41250          // 0x36-0x37
41251
41252
41253          function SHZ(a, state) {
41254            var stack = state.stack;
41255            var rpi = a ? state.rp1 : state.rp2;
41256            var rp = (a ? state.z0 : state.z1)[rpi];
41257            var fv = state.fv;
41258            var pv = state.pv;
41259            var e = stack.pop();
41260
41261            if (exports.DEBUG) {
41262              console.log(state.step, 'SHZ[' + a + ']', e);
41263            }
41264
41265            var z;
41266
41267            switch (e) {
41268              case 0:
41269                z = state.tZone;
41270                break;
41271
41272              case 1:
41273                z = state.gZone;
41274                break;
41275
41276              default:
41277                throw new Error('Invalid zone');
41278            }
41279
41280            var p;
41281            var d = pv.distance(rp, rp, false, true);
41282            var pLen = z.length - 2;
41283
41284            for (var i = 0; i < pLen; i++) {
41285              p = z[i];
41286              fv.setRelative(p, p, d, pv); //if (p !== rp) fv.setRelative(p, p, d, pv);
41287            }
41288          } // SHPIX[] SHift point by a PIXel amount
41289          // 0x38
41290
41291
41292          function SHPIX(state) {
41293            var stack = state.stack;
41294            var loop = state.loop;
41295            var fv = state.fv;
41296            var d = stack.pop() / 0x40;
41297            var z2 = state.z2;
41298
41299            while (loop--) {
41300              var pi = stack.pop();
41301              var p = z2[pi];
41302
41303              if (exports.DEBUG) {
41304                console.log(state.step, (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') + 'SHPIX[]', pi, d);
41305              }
41306
41307              fv.setRelative(p, p, d);
41308              fv.touch(p);
41309            }
41310
41311            state.loop = 1;
41312          } // IP[] Interpolate Point
41313          // 0x39
41314
41315
41316          function IP(state) {
41317            var stack = state.stack;
41318            var rp1i = state.rp1;
41319            var rp2i = state.rp2;
41320            var loop = state.loop;
41321            var rp1 = state.z0[rp1i];
41322            var rp2 = state.z1[rp2i];
41323            var fv = state.fv;
41324            var pv = state.dpv;
41325            var z2 = state.z2;
41326
41327            while (loop--) {
41328              var pi = stack.pop();
41329              var p = z2[pi];
41330
41331              if (exports.DEBUG) {
41332                console.log(state.step, (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') + 'IP[]', pi, rp1i, '<->', rp2i);
41333              }
41334
41335              fv.interpolate(p, rp1, rp2, pv);
41336              fv.touch(p);
41337            }
41338
41339            state.loop = 1;
41340          } // MSIRP[a] Move Stack Indirect Relative Point
41341          // 0x3A-0x3B
41342
41343
41344          function MSIRP(a, state) {
41345            var stack = state.stack;
41346            var d = stack.pop() / 64;
41347            var pi = stack.pop();
41348            var p = state.z1[pi];
41349            var rp0 = state.z0[state.rp0];
41350            var fv = state.fv;
41351            var pv = state.pv;
41352            fv.setRelative(p, rp0, d, pv);
41353            fv.touch(p);
41354
41355            if (exports.DEBUG) {
41356              console.log(state.step, 'MSIRP[' + a + ']', d, pi);
41357            }
41358
41359            state.rp1 = state.rp0;
41360            state.rp2 = pi;
41361
41362            if (a) {
41363              state.rp0 = pi;
41364            }
41365          } // ALIGNRP[] Align to reference point.
41366          // 0x3C
41367
41368
41369          function ALIGNRP(state) {
41370            var stack = state.stack;
41371            var rp0i = state.rp0;
41372            var rp0 = state.z0[rp0i];
41373            var loop = state.loop;
41374            var fv = state.fv;
41375            var pv = state.pv;
41376            var z1 = state.z1;
41377
41378            while (loop--) {
41379              var pi = stack.pop();
41380              var p = z1[pi];
41381
41382              if (exports.DEBUG) {
41383                console.log(state.step, (state.loop > 1 ? 'loop ' + (state.loop - loop) + ': ' : '') + 'ALIGNRP[]', pi);
41384              }
41385
41386              fv.setRelative(p, rp0, 0, pv);
41387              fv.touch(p);
41388            }
41389
41390            state.loop = 1;
41391          } // RTG[] Round To Double Grid
41392          // 0x3D
41393
41394
41395          function RTDG(state) {
41396            if (exports.DEBUG) {
41397              console.log(state.step, 'RTDG[]');
41398            }
41399
41400            state.round = roundToDoubleGrid;
41401          } // MIAP[a] Move Indirect Absolute Point
41402          // 0x3E-0x3F
41403
41404
41405          function MIAP(round, state) {
41406            var stack = state.stack;
41407            var n = stack.pop();
41408            var pi = stack.pop();
41409            var p = state.z0[pi];
41410            var fv = state.fv;
41411            var pv = state.pv;
41412            var cv = state.cvt[n];
41413
41414            if (exports.DEBUG) {
41415              console.log(state.step, 'MIAP[' + round + ']', n, '(', cv, ')', pi);
41416            }
41417
41418            var d = pv.distance(p, HPZero);
41419
41420            if (round) {
41421              if (Math.abs(d - cv) < state.cvCutIn) {
41422                d = cv;
41423              }
41424
41425              d = state.round(d);
41426            }
41427
41428            fv.setRelative(p, HPZero, d, pv);
41429
41430            if (state.zp0 === 0) {
41431              p.xo = p.x;
41432              p.yo = p.y;
41433            }
41434
41435            fv.touch(p);
41436            state.rp0 = state.rp1 = pi;
41437          } // NPUSB[] PUSH N Bytes
41438          // 0x40
41439
41440
41441          function NPUSHB(state) {
41442            var prog = state.prog;
41443            var ip = state.ip;
41444            var stack = state.stack;
41445            var n = prog[++ip];
41446
41447            if (exports.DEBUG) {
41448              console.log(state.step, 'NPUSHB[]', n);
41449            }
41450
41451            for (var i = 0; i < n; i++) {
41452              stack.push(prog[++ip]);
41453            }
41454
41455            state.ip = ip;
41456          } // NPUSHW[] PUSH N Words
41457          // 0x41
41458
41459
41460          function NPUSHW(state) {
41461            var ip = state.ip;
41462            var prog = state.prog;
41463            var stack = state.stack;
41464            var n = prog[++ip];
41465
41466            if (exports.DEBUG) {
41467              console.log(state.step, 'NPUSHW[]', n);
41468            }
41469
41470            for (var i = 0; i < n; i++) {
41471              var w = prog[++ip] << 8 | prog[++ip];
41472
41473              if (w & 0x8000) {
41474                w = -((w ^ 0xffff) + 1);
41475              }
41476
41477              stack.push(w);
41478            }
41479
41480            state.ip = ip;
41481          } // WS[] Write Store
41482          // 0x42
41483
41484
41485          function WS(state) {
41486            var stack = state.stack;
41487            var store = state.store;
41488
41489            if (!store) {
41490              store = state.store = [];
41491            }
41492
41493            var v = stack.pop();
41494            var l = stack.pop();
41495
41496            if (exports.DEBUG) {
41497              console.log(state.step, 'WS', v, l);
41498            }
41499
41500            store[l] = v;
41501          } // RS[] Read Store
41502          // 0x43
41503
41504
41505          function RS(state) {
41506            var stack = state.stack;
41507            var store = state.store;
41508            var l = stack.pop();
41509
41510            if (exports.DEBUG) {
41511              console.log(state.step, 'RS', l);
41512            }
41513
41514            var v = store && store[l] || 0;
41515            stack.push(v);
41516          } // WCVTP[] Write Control Value Table in Pixel units
41517          // 0x44
41518
41519
41520          function WCVTP(state) {
41521            var stack = state.stack;
41522            var v = stack.pop();
41523            var l = stack.pop();
41524
41525            if (exports.DEBUG) {
41526              console.log(state.step, 'WCVTP', v, l);
41527            }
41528
41529            state.cvt[l] = v / 0x40;
41530          } // RCVT[] Read Control Value Table entry
41531          // 0x45
41532
41533
41534          function RCVT(state) {
41535            var stack = state.stack;
41536            var cvte = stack.pop();
41537
41538            if (exports.DEBUG) {
41539              console.log(state.step, 'RCVT', cvte);
41540            }
41541
41542            stack.push(state.cvt[cvte] * 0x40);
41543          } // GC[] Get Coordinate projected onto the projection vector
41544          // 0x46-0x47
41545
41546
41547          function GC(a, state) {
41548            var stack = state.stack;
41549            var pi = stack.pop();
41550            var p = state.z2[pi];
41551
41552            if (exports.DEBUG) {
41553              console.log(state.step, 'GC[' + a + ']', pi);
41554            }
41555
41556            stack.push(state.dpv.distance(p, HPZero, a, false) * 0x40);
41557          } // MD[a] Measure Distance
41558          // 0x49-0x4A
41559
41560
41561          function MD(a, state) {
41562            var stack = state.stack;
41563            var pi2 = stack.pop();
41564            var pi1 = stack.pop();
41565            var p2 = state.z1[pi2];
41566            var p1 = state.z0[pi1];
41567            var d = state.dpv.distance(p1, p2, a, a);
41568
41569            if (exports.DEBUG) {
41570              console.log(state.step, 'MD[' + a + ']', pi2, pi1, '->', d);
41571            }
41572
41573            state.stack.push(Math.round(d * 64));
41574          } // MPPEM[] Measure Pixels Per EM
41575          // 0x4B
41576
41577
41578          function MPPEM(state) {
41579            if (exports.DEBUG) {
41580              console.log(state.step, 'MPPEM[]');
41581            }
41582
41583            state.stack.push(state.ppem);
41584          } // FLIPON[] set the auto FLIP Boolean to ON
41585          // 0x4D
41586
41587
41588          function FLIPON(state) {
41589            if (exports.DEBUG) {
41590              console.log(state.step, 'FLIPON[]');
41591            }
41592
41593            state.autoFlip = true;
41594          } // LT[] Less Than
41595          // 0x50
41596
41597
41598          function LT(state) {
41599            var stack = state.stack;
41600            var e2 = stack.pop();
41601            var e1 = stack.pop();
41602
41603            if (exports.DEBUG) {
41604              console.log(state.step, 'LT[]', e2, e1);
41605            }
41606
41607            stack.push(e1 < e2 ? 1 : 0);
41608          } // LTEQ[] Less Than or EQual
41609          // 0x53
41610
41611
41612          function LTEQ(state) {
41613            var stack = state.stack;
41614            var e2 = stack.pop();
41615            var e1 = stack.pop();
41616
41617            if (exports.DEBUG) {
41618              console.log(state.step, 'LTEQ[]', e2, e1);
41619            }
41620
41621            stack.push(e1 <= e2 ? 1 : 0);
41622          } // GTEQ[] Greater Than
41623          // 0x52
41624
41625
41626          function GT(state) {
41627            var stack = state.stack;
41628            var e2 = stack.pop();
41629            var e1 = stack.pop();
41630
41631            if (exports.DEBUG) {
41632              console.log(state.step, 'GT[]', e2, e1);
41633            }
41634
41635            stack.push(e1 > e2 ? 1 : 0);
41636          } // GTEQ[] Greater Than or EQual
41637          // 0x53
41638
41639
41640          function GTEQ(state) {
41641            var stack = state.stack;
41642            var e2 = stack.pop();
41643            var e1 = stack.pop();
41644
41645            if (exports.DEBUG) {
41646              console.log(state.step, 'GTEQ[]', e2, e1);
41647            }
41648
41649            stack.push(e1 >= e2 ? 1 : 0);
41650          } // EQ[] EQual
41651          // 0x54
41652
41653
41654          function EQ(state) {
41655            var stack = state.stack;
41656            var e2 = stack.pop();
41657            var e1 = stack.pop();
41658
41659            if (exports.DEBUG) {
41660              console.log(state.step, 'EQ[]', e2, e1);
41661            }
41662
41663            stack.push(e2 === e1 ? 1 : 0);
41664          } // NEQ[] Not EQual
41665          // 0x55
41666
41667
41668          function NEQ(state) {
41669            var stack = state.stack;
41670            var e2 = stack.pop();
41671            var e1 = stack.pop();
41672
41673            if (exports.DEBUG) {
41674              console.log(state.step, 'NEQ[]', e2, e1);
41675            }
41676
41677            stack.push(e2 !== e1 ? 1 : 0);
41678          } // ODD[] ODD
41679          // 0x56
41680
41681
41682          function ODD(state) {
41683            var stack = state.stack;
41684            var n = stack.pop();
41685
41686            if (exports.DEBUG) {
41687              console.log(state.step, 'ODD[]', n);
41688            }
41689
41690            stack.push(Math.trunc(n) % 2 ? 1 : 0);
41691          } // EVEN[] EVEN
41692          // 0x57
41693
41694
41695          function EVEN(state) {
41696            var stack = state.stack;
41697            var n = stack.pop();
41698
41699            if (exports.DEBUG) {
41700              console.log(state.step, 'EVEN[]', n);
41701            }
41702
41703            stack.push(Math.trunc(n) % 2 ? 0 : 1);
41704          } // IF[] IF test
41705          // 0x58
41706
41707
41708          function IF(state) {
41709            var test = state.stack.pop();
41710
41711            if (exports.DEBUG) {
41712              console.log(state.step, 'IF[]', test);
41713            } // if test is true it just continues
41714            // if not the ip is skipped until matching ELSE or EIF
41715
41716
41717            if (!test) {
41718              skip(state, true);
41719
41720              if (exports.DEBUG) {
41721                console.log(state.step, 'EIF[]');
41722              }
41723            }
41724          } // EIF[] End IF
41725          // 0x59
41726
41727
41728          function EIF(state) {
41729            // this can be reached normally when
41730            // executing an else branch.
41731            // -> just ignore it
41732            if (exports.DEBUG) {
41733              console.log(state.step, 'EIF[]');
41734            }
41735          } // AND[] logical AND
41736          // 0x5A
41737
41738
41739          function AND(state) {
41740            var stack = state.stack;
41741            var e2 = stack.pop();
41742            var e1 = stack.pop();
41743
41744            if (exports.DEBUG) {
41745              console.log(state.step, 'AND[]', e2, e1);
41746            }
41747
41748            stack.push(e2 && e1 ? 1 : 0);
41749          } // OR[] logical OR
41750          // 0x5B
41751
41752
41753          function OR(state) {
41754            var stack = state.stack;
41755            var e2 = stack.pop();
41756            var e1 = stack.pop();
41757
41758            if (exports.DEBUG) {
41759              console.log(state.step, 'OR[]', e2, e1);
41760            }
41761
41762            stack.push(e2 || e1 ? 1 : 0);
41763          } // NOT[] logical NOT
41764          // 0x5C
41765
41766
41767          function NOT(state) {
41768            var stack = state.stack;
41769            var e = stack.pop();
41770
41771            if (exports.DEBUG) {
41772              console.log(state.step, 'NOT[]', e);
41773            }
41774
41775            stack.push(e ? 0 : 1);
41776          } // DELTAP1[] DELTA exception P1
41777          // DELTAP2[] DELTA exception P2
41778          // DELTAP3[] DELTA exception P3
41779          // 0x5D, 0x71, 0x72
41780
41781
41782          function DELTAP123(b, state) {
41783            var stack = state.stack;
41784            var n = stack.pop();
41785            var fv = state.fv;
41786            var pv = state.pv;
41787            var ppem = state.ppem;
41788            var base = state.deltaBase + (b - 1) * 16;
41789            var ds = state.deltaShift;
41790            var z0 = state.z0;
41791
41792            if (exports.DEBUG) {
41793              console.log(state.step, 'DELTAP[' + b + ']', n, stack);
41794            }
41795
41796            for (var i = 0; i < n; i++) {
41797              var pi = stack.pop();
41798              var arg = stack.pop();
41799              var appem = base + ((arg & 0xF0) >> 4);
41800
41801              if (appem !== ppem) {
41802                continue;
41803              }
41804
41805              var mag = (arg & 0x0F) - 8;
41806
41807              if (mag >= 0) {
41808                mag++;
41809              }
41810
41811              if (exports.DEBUG) {
41812                console.log(state.step, 'DELTAPFIX', pi, 'by', mag * ds);
41813              }
41814
41815              var p = z0[pi];
41816              fv.setRelative(p, p, mag * ds, pv);
41817            }
41818          } // SDB[] Set Delta Base in the graphics state
41819          // 0x5E
41820
41821
41822          function SDB(state) {
41823            var stack = state.stack;
41824            var n = stack.pop();
41825
41826            if (exports.DEBUG) {
41827              console.log(state.step, 'SDB[]', n);
41828            }
41829
41830            state.deltaBase = n;
41831          } // SDS[] Set Delta Shift in the graphics state
41832          // 0x5F
41833
41834
41835          function SDS(state) {
41836            var stack = state.stack;
41837            var n = stack.pop();
41838
41839            if (exports.DEBUG) {
41840              console.log(state.step, 'SDS[]', n);
41841            }
41842
41843            state.deltaShift = Math.pow(0.5, n);
41844          } // ADD[] ADD
41845          // 0x60
41846
41847
41848          function ADD(state) {
41849            var stack = state.stack;
41850            var n2 = stack.pop();
41851            var n1 = stack.pop();
41852
41853            if (exports.DEBUG) {
41854              console.log(state.step, 'ADD[]', n2, n1);
41855            }
41856
41857            stack.push(n1 + n2);
41858          } // SUB[] SUB
41859          // 0x61
41860
41861
41862          function SUB(state) {
41863            var stack = state.stack;
41864            var n2 = stack.pop();
41865            var n1 = stack.pop();
41866
41867            if (exports.DEBUG) {
41868              console.log(state.step, 'SUB[]', n2, n1);
41869            }
41870
41871            stack.push(n1 - n2);
41872          } // DIV[] DIV
41873          // 0x62
41874
41875
41876          function DIV(state) {
41877            var stack = state.stack;
41878            var n2 = stack.pop();
41879            var n1 = stack.pop();
41880
41881            if (exports.DEBUG) {
41882              console.log(state.step, 'DIV[]', n2, n1);
41883            }
41884
41885            stack.push(n1 * 64 / n2);
41886          } // MUL[] MUL
41887          // 0x63
41888
41889
41890          function MUL(state) {
41891            var stack = state.stack;
41892            var n2 = stack.pop();
41893            var n1 = stack.pop();
41894
41895            if (exports.DEBUG) {
41896              console.log(state.step, 'MUL[]', n2, n1);
41897            }
41898
41899            stack.push(n1 * n2 / 64);
41900          } // ABS[] ABSolute value
41901          // 0x64
41902
41903
41904          function ABS(state) {
41905            var stack = state.stack;
41906            var n = stack.pop();
41907
41908            if (exports.DEBUG) {
41909              console.log(state.step, 'ABS[]', n);
41910            }
41911
41912            stack.push(Math.abs(n));
41913          } // NEG[] NEGate
41914          // 0x65
41915
41916
41917          function NEG(state) {
41918            var stack = state.stack;
41919            var n = stack.pop();
41920
41921            if (exports.DEBUG) {
41922              console.log(state.step, 'NEG[]', n);
41923            }
41924
41925            stack.push(-n);
41926          } // FLOOR[] FLOOR
41927          // 0x66
41928
41929
41930          function FLOOR(state) {
41931            var stack = state.stack;
41932            var n = stack.pop();
41933
41934            if (exports.DEBUG) {
41935              console.log(state.step, 'FLOOR[]', n);
41936            }
41937
41938            stack.push(Math.floor(n / 0x40) * 0x40);
41939          } // CEILING[] CEILING
41940          // 0x67
41941
41942
41943          function CEILING(state) {
41944            var stack = state.stack;
41945            var n = stack.pop();
41946
41947            if (exports.DEBUG) {
41948              console.log(state.step, 'CEILING[]', n);
41949            }
41950
41951            stack.push(Math.ceil(n / 0x40) * 0x40);
41952          } // ROUND[ab] ROUND value
41953          // 0x68-0x6B
41954
41955
41956          function ROUND(dt, state) {
41957            var stack = state.stack;
41958            var n = stack.pop();
41959
41960            if (exports.DEBUG) {
41961              console.log(state.step, 'ROUND[]');
41962            }
41963
41964            stack.push(state.round(n / 0x40) * 0x40);
41965          } // WCVTF[] Write Control Value Table in Funits
41966          // 0x70
41967
41968
41969          function WCVTF(state) {
41970            var stack = state.stack;
41971            var v = stack.pop();
41972            var l = stack.pop();
41973
41974            if (exports.DEBUG) {
41975              console.log(state.step, 'WCVTF[]', v, l);
41976            }
41977
41978            state.cvt[l] = v * state.ppem / state.font.unitsPerEm;
41979          } // DELTAC1[] DELTA exception C1
41980          // DELTAC2[] DELTA exception C2
41981          // DELTAC3[] DELTA exception C3
41982          // 0x73, 0x74, 0x75
41983
41984
41985          function DELTAC123(b, state) {
41986            var stack = state.stack;
41987            var n = stack.pop();
41988            var ppem = state.ppem;
41989            var base = state.deltaBase + (b - 1) * 16;
41990            var ds = state.deltaShift;
41991
41992            if (exports.DEBUG) {
41993              console.log(state.step, 'DELTAC[' + b + ']', n, stack);
41994            }
41995
41996            for (var i = 0; i < n; i++) {
41997              var c = stack.pop();
41998              var arg = stack.pop();
41999              var appem = base + ((arg & 0xF0) >> 4);
42000
42001              if (appem !== ppem) {
42002                continue;
42003              }
42004
42005              var mag = (arg & 0x0F) - 8;
42006
42007              if (mag >= 0) {
42008                mag++;
42009              }
42010
42011              var delta = mag * ds;
42012
42013              if (exports.DEBUG) {
42014                console.log(state.step, 'DELTACFIX', c, 'by', delta);
42015              }
42016
42017              state.cvt[c] += delta;
42018            }
42019          } // SROUND[] Super ROUND
42020          // 0x76
42021
42022
42023          function SROUND(state) {
42024            var n = state.stack.pop();
42025
42026            if (exports.DEBUG) {
42027              console.log(state.step, 'SROUND[]', n);
42028            }
42029
42030            state.round = roundSuper;
42031            var period;
42032
42033            switch (n & 0xC0) {
42034              case 0x00:
42035                period = 0.5;
42036                break;
42037
42038              case 0x40:
42039                period = 1;
42040                break;
42041
42042              case 0x80:
42043                period = 2;
42044                break;
42045
42046              default:
42047                throw new Error('invalid SROUND value');
42048            }
42049
42050            state.srPeriod = period;
42051
42052            switch (n & 0x30) {
42053              case 0x00:
42054                state.srPhase = 0;
42055                break;
42056
42057              case 0x10:
42058                state.srPhase = 0.25 * period;
42059                break;
42060
42061              case 0x20:
42062                state.srPhase = 0.5 * period;
42063                break;
42064
42065              case 0x30:
42066                state.srPhase = 0.75 * period;
42067                break;
42068
42069              default:
42070                throw new Error('invalid SROUND value');
42071            }
42072
42073            n &= 0x0F;
42074
42075            if (n === 0) {
42076              state.srThreshold = 0;
42077            } else {
42078              state.srThreshold = (n / 8 - 0.5) * period;
42079            }
42080          } // S45ROUND[] Super ROUND 45 degrees
42081          // 0x77
42082
42083
42084          function S45ROUND(state) {
42085            var n = state.stack.pop();
42086
42087            if (exports.DEBUG) {
42088              console.log(state.step, 'S45ROUND[]', n);
42089            }
42090
42091            state.round = roundSuper;
42092            var period;
42093
42094            switch (n & 0xC0) {
42095              case 0x00:
42096                period = Math.sqrt(2) / 2;
42097                break;
42098
42099              case 0x40:
42100                period = Math.sqrt(2);
42101                break;
42102
42103              case 0x80:
42104                period = 2 * Math.sqrt(2);
42105                break;
42106
42107              default:
42108                throw new Error('invalid S45ROUND value');
42109            }
42110
42111            state.srPeriod = period;
42112
42113            switch (n & 0x30) {
42114              case 0x00:
42115                state.srPhase = 0;
42116                break;
42117
42118              case 0x10:
42119                state.srPhase = 0.25 * period;
42120                break;
42121
42122              case 0x20:
42123                state.srPhase = 0.5 * period;
42124                break;
42125
42126              case 0x30:
42127                state.srPhase = 0.75 * period;
42128                break;
42129
42130              default:
42131                throw new Error('invalid S45ROUND value');
42132            }
42133
42134            n &= 0x0F;
42135
42136            if (n === 0) {
42137              state.srThreshold = 0;
42138            } else {
42139              state.srThreshold = (n / 8 - 0.5) * period;
42140            }
42141          } // ROFF[] Round Off
42142          // 0x7A
42143
42144
42145          function ROFF(state) {
42146            if (exports.DEBUG) {
42147              console.log(state.step, 'ROFF[]');
42148            }
42149
42150            state.round = roundOff;
42151          } // RUTG[] Round Up To Grid
42152          // 0x7C
42153
42154
42155          function RUTG(state) {
42156            if (exports.DEBUG) {
42157              console.log(state.step, 'RUTG[]');
42158            }
42159
42160            state.round = roundUpToGrid;
42161          } // RDTG[] Round Down To Grid
42162          // 0x7D
42163
42164
42165          function RDTG(state) {
42166            if (exports.DEBUG) {
42167              console.log(state.step, 'RDTG[]');
42168            }
42169
42170            state.round = roundDownToGrid;
42171          } // SCANCTRL[] SCAN conversion ConTRoL
42172          // 0x85
42173
42174
42175          function SCANCTRL(state) {
42176            var n = state.stack.pop(); // ignored by opentype.js
42177
42178            if (exports.DEBUG) {
42179              console.log(state.step, 'SCANCTRL[]', n);
42180            }
42181          } // SDPVTL[a] Set Dual Projection Vector To Line
42182          // 0x86-0x87
42183
42184
42185          function SDPVTL(a, state) {
42186            var stack = state.stack;
42187            var p2i = stack.pop();
42188            var p1i = stack.pop();
42189            var p2 = state.z2[p2i];
42190            var p1 = state.z1[p1i];
42191
42192            if (exports.DEBUG) {
42193              console.log(state.step, 'SDPVTL[' + a + ']', p2i, p1i);
42194            }
42195
42196            var dx;
42197            var dy;
42198
42199            if (!a) {
42200              dx = p1.x - p2.x;
42201              dy = p1.y - p2.y;
42202            } else {
42203              dx = p2.y - p1.y;
42204              dy = p1.x - p2.x;
42205            }
42206
42207            state.dpv = getUnitVector(dx, dy);
42208          } // GETINFO[] GET INFOrmation
42209          // 0x88
42210
42211
42212          function GETINFO(state) {
42213            var stack = state.stack;
42214            var sel = stack.pop();
42215            var r = 0;
42216
42217            if (exports.DEBUG) {
42218              console.log(state.step, 'GETINFO[]', sel);
42219            } // v35 as in no subpixel hinting
42220
42221
42222            if (sel & 0x01) {
42223              r = 35;
42224            } // TODO rotation and stretch currently not supported
42225            // and thus those GETINFO are always 0.
42226            // opentype.js is always gray scaling
42227
42228
42229            if (sel & 0x20) {
42230              r |= 0x1000;
42231            }
42232
42233            stack.push(r);
42234          } // ROLL[] ROLL the top three stack elements
42235          // 0x8A
42236
42237
42238          function ROLL(state) {
42239            var stack = state.stack;
42240            var a = stack.pop();
42241            var b = stack.pop();
42242            var c = stack.pop();
42243
42244            if (exports.DEBUG) {
42245              console.log(state.step, 'ROLL[]');
42246            }
42247
42248            stack.push(b);
42249            stack.push(a);
42250            stack.push(c);
42251          } // MAX[] MAXimum of top two stack elements
42252          // 0x8B
42253
42254
42255          function MAX(state) {
42256            var stack = state.stack;
42257            var e2 = stack.pop();
42258            var e1 = stack.pop();
42259
42260            if (exports.DEBUG) {
42261              console.log(state.step, 'MAX[]', e2, e1);
42262            }
42263
42264            stack.push(Math.max(e1, e2));
42265          } // MIN[] MINimum of top two stack elements
42266          // 0x8C
42267
42268
42269          function MIN(state) {
42270            var stack = state.stack;
42271            var e2 = stack.pop();
42272            var e1 = stack.pop();
42273
42274            if (exports.DEBUG) {
42275              console.log(state.step, 'MIN[]', e2, e1);
42276            }
42277
42278            stack.push(Math.min(e1, e2));
42279          } // SCANTYPE[] SCANTYPE
42280          // 0x8D
42281
42282
42283          function SCANTYPE(state) {
42284            var n = state.stack.pop(); // ignored by opentype.js
42285
42286            if (exports.DEBUG) {
42287              console.log(state.step, 'SCANTYPE[]', n);
42288            }
42289          } // INSTCTRL[] INSTCTRL
42290          // 0x8D
42291
42292
42293          function INSTCTRL(state) {
42294            var s = state.stack.pop();
42295            var v = state.stack.pop();
42296
42297            if (exports.DEBUG) {
42298              console.log(state.step, 'INSTCTRL[]', s, v);
42299            }
42300
42301            switch (s) {
42302              case 1:
42303                state.inhibitGridFit = !!v;
42304                return;
42305
42306              case 2:
42307                state.ignoreCvt = !!v;
42308                return;
42309
42310              default:
42311                throw new Error('invalid INSTCTRL[] selector');
42312            }
42313          } // PUSHB[abc] PUSH Bytes
42314          // 0xB0-0xB7
42315
42316
42317          function PUSHB(n, state) {
42318            var stack = state.stack;
42319            var prog = state.prog;
42320            var ip = state.ip;
42321
42322            if (exports.DEBUG) {
42323              console.log(state.step, 'PUSHB[' + n + ']');
42324            }
42325
42326            for (var i = 0; i < n; i++) {
42327              stack.push(prog[++ip]);
42328            }
42329
42330            state.ip = ip;
42331          } // PUSHW[abc] PUSH Words
42332         
42332 // 0xB8-0xBF
42333
42334
42335          function PUSHW(n, state) {
42336            var ip = state.ip;
42337            var prog = state.prog;
42338            var stack = state.stack;
42339
42340            if (exports.DEBUG) {
42341              console.log(state.ip, 'PUSHW[' + n + ']');
42342            }
42343
42344            for (var i = 0; i < n; i++) {
42345              var w = prog[++ip] << 8 | prog[++ip];
42346
42347              if (w & 0x8000) {
42348                w = -((w ^ 0xffff) + 1);
42349              }
42350
42351              stack.push(w);
42352            }
42353
42354            state.ip = ip;
42355          } // MDRP[abcde] Move Direct Relative Point
42356          // 0xD0-0xEF
42357          // (if indirect is 0)
42358          //
42359          // and
42360          //
42361          // MIRP[abcde] Move Indirect Relative Point
42362          // 0xE0-0xFF
42363          // (if indirect is 1)
42364
42365
42366          function MDRP_MIRP(indirect, setRp0, keepD, ro, dt, state) {
42367            var stack = state.stack;
42368            var cvte = indirect && stack.pop();
42369            var pi = stack.pop();
42370            var rp0i = state.rp0;
42371            var rp = state.z0[rp0i];
42372            var p = state.z1[pi];
42373            var md = state.minDis;
42374            var fv = state.fv;
42375            var pv = state.dpv;
42376            var od; // original distance
42377
42378            var d; // moving distance
42379
42380            var sign; // sign of distance
42381
42382            var cv;
42383            d = od = pv.distance(p, rp, true, true);
42384            sign = d >= 0 ? 1 : -1; // Math.sign would be 0 in case of 0
42385            // TODO consider autoFlip
42386
42387            d = Math.abs(d);
42388
42389            if (indirect) {
42390              cv = state.cvt[cvte];
42391
42392              if (ro && Math.abs(d - cv) < state.cvCutIn) {
42393                d = cv;
42394              }
42395            }
42396
42397            if (keepD && d < md) {
42398              d = md;
42399            }
42400
42401            if (ro) {
42402              d = state.round(d);
42403            }
42404
42405            fv.setRelative(p, rp, sign * d, pv);
42406            fv.touch(p);
42407
42408            if (exports.DEBUG) {
42409              console.log(state.step, (indirect ? 'MIRP[' : 'MDRP[') + (setRp0 ? 'M' : 'm') + (keepD ? '>' : '_') + (ro ? 'R' : '_') + (dt === 0 ? 'Gr' : dt === 1 ? 'Bl' : dt === 2 ? 'Wh' : '') + ']', indirect ? cvte + '(' + state.cvt[cvte] + ',' + cv + ')' : '', pi, '(d =', od, '->', sign * d, ')');
42410            }
42411
42412            state.rp1 = state.rp0;
42413            state.rp2 = pi;
42414
42415            if (setRp0) {
42416              state.rp0 = pi;
42417            }
42418          }
42419          /*
42420          * The instruction table.
42421          */
42422
42423
42424          instructionTable = [
42425          /* 0x00 */
42426          SVTCA.bind(undefined, yUnitVector),
42427          /* 0x01 */
42428          SVTCA.bind(undefined, xUnitVector),
42429          /* 0x02 */
42430          SPVTCA.bind(undefined, yUnitVector),
42431          /* 0x03 */
42432          SPVTCA.bind(undefined, xUnitVector),
42433          /* 0x04 */
42434          SFVTCA.bind(undefined, yUnitVector),
42435          /* 0x05 */
42436          SFVTCA.bind(undefined, xUnitVector),
42437          /* 0x06 */
42438          SPVTL.bind(undefined, 0),
42439          /* 0x07 */
42440          SPVTL.bind(undefined, 1),
42441          /* 0x08 */
42442          SFVTL.bind(undefined, 0),
42443          /* 0x09 */
42444          SFVTL.bind(undefined, 1),
42445          /* 0x0A */
42446          SPVFS,
42447          /* 0x0B */
42448          SFVFS,
42449          /* 0x0C */
42450          GPV,
42451          /* 0x0D */
42452          GFV,
42453          /* 0x0E */
42454          SFVTPV,
42455          /* 0x0F */
42456          ISECT,
42457          /* 0x10 */
42458          SRP0,
42459          /* 0x11 */
42460          SRP1,
42461          /* 0x12 */
42462          SRP2,
42463          /* 0x13 */
42464          SZP0,
42465          /* 0x14 */
42466          SZP1,
42467          /* 0x15 */
42468          SZP2,
42469          /* 0x16 */
42470          SZPS,
42471          /* 0x17 */
42472          SLOOP,
42473          /* 0x18 */
42474          RTG,
42475          /* 0x19 */
42476          RTHG,
42477          /* 0x1A */
42478          SMD,
42479          /* 0x1B */
42480          ELSE,
42481          /* 0x1C */
42482          JMPR,
42483          /* 0x1D */
42484          SCVTCI,
42485          /* 0x1E */
42486          undefined, // TODO SSWCI
42487
42488          /* 0x1F */
42489          undefined, // TODO SSW
42490
42491          /* 0x20 */
42492          DUP,
42493          /* 0x21 */
42494          POP,
42495          /* 0x22 */
42496          CLEAR,
42497          /* 0x23 */
42498          SWAP,
42499          /* 0x24 */
42500          DEPTH,
42501          /* 0x25 */
42502          CINDEX,
42503          /* 0x26 */
42504          MINDEX,
42505          /* 0x27 */
42506          undefined, // TODO ALIGNPTS
42507
42508          /* 0x28 */
42509          undefined,
42510          /* 0x29 */
42511          undefined, // TODO UTP
42512
42513          /* 0x2A */
42514          LOOPCALL,
42515          /* 0x2B */
42516          CALL,
42517          /* 0x2C */
42518          FDEF,
42519          /* 0x2D */
42520          undefined, // ENDF (eaten by FDEF)
42521
42522          /* 0x2E */
42523          MDAP.bind(undefined, 0),
42524          /* 0x2F */
42525          MDAP.bind(undefined, 1),
42526          /* 0x30 */
42527          IUP.bind(undefined, yUnitVector),
42528          /* 0x31 */
42529          IUP.bind(undefined, xUnitVector),
42530          /* 0x32 */
42531          SHP.bind(undefined, 0),
42532          /* 0x33 */
42533          SHP.bind(undefined, 1),
42534          /* 0x34 */
42535          SHC.bind(undefined, 0),
42536          /* 0x35 */
42537          SHC.bind(undefined, 1),
42538          /* 0x36 */
42539          SHZ.bind(undefined, 0),
42540          /* 0x37 */
42541          SHZ.bind(undefined, 1),
42542          /* 0x38 */
42543          SHPIX,
42544          /* 0x39 */
42545          IP,
42546          /* 0x3A */
42547          MSIRP.bind(undefined, 0),
42548          /* 0x3B */
42549          MSIRP.bind(undefined, 1),
42550          /* 0x3C */
42551          ALIGNRP,
42552          /* 0x3D */
42553          RTDG,
42554          /* 0x3E */
42555          MIAP.bind(undefined, 0),
42556          /* 0x3F */
42557          MIAP.bind(undefined, 1),
42558          /* 0x40 */
42559          NPUSHB,
42560          /* 0x41 */
42561          NPUSHW,
42562          /* 0x42 */
42563          WS,
42564          /* 0x43 */
42565          RS,
42566          /* 0x44 */
42567          WCVTP,
42568          /* 0x45 */
42569          RCVT,
42570          /* 0x46 */
42571          GC.bind(undefined, 0),
42572          /* 0x47 */
42573          GC.bind(undefined, 1),
42574          /* 0x48 */
42575          undefined, // TODO SCFS
42576
42577          /* 0x49 */
42578          MD.bind(undefined, 0),
42579          /* 0x4A */
42580          MD.bind(undefined, 1),
42581          /* 0x4B */
42582          MPPEM,
42583          /* 0x4C */
42584          undefined, // TODO MPS
42585
42586          /* 0x4D */
42587          FLIPON,
42588          /* 0x4E */
42589          undefined, // TODO FLIPOFF
42590
42591          /* 0x4F */
42592          undefined, // TODO DEBUG
42593
42594          /* 0x50 */
42595          LT,
42596          /* 0x51 */
42597          LTEQ,
42598          /* 0x52 */
42599          GT,
42600          /* 0x53 */
42601          GTEQ,
42602          /* 0x54 */
42603          EQ,
42604          /* 0x55 */
42605          NEQ,
42606          /* 0x56 */
42607          ODD,
42608          /* 0x57 */
42609          EVEN,
42610          /* 0x58 */
42611          IF,
42612          /* 0x59 */
42613          EIF,
42614          /* 0x5A */
42615          AND,
42616          /* 0x5B */
42617          OR,
42618          /* 0x5C */
42619          NOT,
42620          /* 0x5D */
42621          DELTAP123.bind(undefined, 1),
42622          /* 0x5E */
42623          SDB,
42624          /* 0x5F */
42625          SDS,
42626          /* 0x60 */
42627          ADD,
42628          /* 0x61 */
42629          SUB,
42630          /* 0x62 */
42631          DIV,
42632          /* 0x63 */
42633          MUL,
42634          /* 0x64 */
42635          ABS,
42636          /* 0x65 */
42637          NEG,
42638          /* 0x66 */
42639          FLOOR,
42640          /* 0x67 */
42641          CEILING,
42642          /* 0x68 */
42643          ROUND.bind(undefined, 0),
42644          /* 0x69 */
42645          ROUND.bind(undefined, 1),
42646          /* 0x6A */
42647          ROUND.bind(undefined, 2),
42648          /* 0x6B */
42649          ROUND.bind(undefined, 3),
42650          /* 0x6C */
42651          undefined, // TODO NROUND[ab]
42652
42653          /* 0x6D */
42654          undefined, // TODO NROUND[ab]
42655
42656          /* 0x6E */
42657          undefined, // TODO NROUND[ab]
42658
42659          /* 0x6F */
42660          undefined, // TODO NROUND[ab]
42661
42662          /* 0x70 */
42663          WCVTF,
42664          /* 0x71 */
42665          DELTAP123.bind(undefined, 2),
42666          /* 0x72 */
42667          DELTAP123.bind(undefined, 3),
42668          /* 0x73 */
42669          DELTAC123.bind(undefined, 1),
42670          /* 0x74 */
42671          DELTAC123.bind(undefined, 2),
42672          /* 0x75 */
42673          DELTAC123.bind(undefined, 3),
42674          /* 0x76 */
42675          SROUND,
42676          /* 0x77 */
42677          S45ROUND,
42678          /* 0x78 */
42679          undefined, // TODO JROT[]
42680
42681          /* 0x79 */
42682          undefined, // TODO JROF[]
42683
42684          /* 0x7A */
42685          ROFF,
42686          /* 0x7B */
42687          undefined,
42688          /* 0x7C */
42689          RUTG,
42690          /* 0x7D */
42691          RDTG,
42692          /* 0x7E */
42693          POP, // actually SANGW, supposed to do only a pop though
42694
42695          /* 0x7F */
42696          POP, // actually AA, supposed to do only a pop though
42697
42698          /* 0x80 */
42699          undefined, // TODO FLIPPT
42700
42701          /* 0x81 */
42702          undefined, // TODO FLIPRGON
42703
42704          /* 0x82 */
42705          undefined, // TODO FLIPRGOFF
42706
42707          /* 0x83 */
42708          undefined,
42709          /* 0x84 */
42710          undefined,
42711          /* 0x85 */
42712          SCANCTRL,
42713          /* 0x86 */
42714          SDPVTL.bind(undefined, 0),
42715          /* 0x87 */
42716          SDPVTL.bind(undefined, 1),
42717          /* 0x88 */
42718          GETINFO,
42719          /* 0x89 */
42720          undefined, // TODO IDEF
42721
42722          /* 0x8A */
42723          ROLL,
42724          /* 0x8B */
42725          MAX,
42726          /* 0x8C */
42727          MIN,
42728          /* 0x8D */
42729          SCANTYPE,
42730          /* 0x8E */
42731          INSTCTRL,
42732          /* 0x8F */
42733          undefined,
42734          /* 0x90 */
42735          undefined,
42736          /* 0x91 */
42737          undefined,
42738          /* 0x92 */
42739          undefined,
42740          /* 0x93 */
42741          undefined,
42742          /* 0x94 */
42743          undefined,
42744          /* 0x95 */
42745          undefined,
42746          /* 0x96 */
42747          undefined,
42748          /* 0x97 */
42749          undefined,
42750          /* 0x98 */
42751          undefined,
42752          /* 0x99 */
42753          undefined,
42754          /* 0x9A */
42755          undefined,
42756          /* 0x9B */
42757          undefined,
42758          /* 0x9C */
42759          undefined,
42760          /* 0x9D */
42761          undefined,
42762          /* 0x9E */
42763          undefined,
42764          /* 0x9F */
42765          undefined,
42766          /* 0xA0 */
42767          undefined,
42768          /* 0xA1 */
42769          undefined,
42770          /* 0xA2 */
42771          undefined,
42772          /* 0xA3 */
42773          undefined,
42774          /* 0xA4 */
42775          undefined,
42776          /* 0xA5 */
42777          undefined,
42778          /* 0xA6 */
42779          undefined,
42780          /* 0xA7 */
42781          undefined,
42782          /* 0xA8 */
42783          undefined,
42784          /* 0xA9 */
42785          undefined,
42786          /* 0xAA */
42787          undefined,
42788          /* 0xAB */
42789          undefined,
42790          /* 0xAC */
42791          undefined,
42792          /* 0xAD */
42793          undefined,
42794          /* 0xAE */
42795          undefined,
42796          /* 0xAF */
42797          undefined,
42798          /* 0xB0 */
42799          PUSHB.bind(undefined, 1),
42800          /* 0xB1 */
42801          PUSHB.bind(undefined, 2),
42802          /* 0xB2 */
42803          PUSHB.bind(undefined, 3),
42804          /* 0xB3 */
42805          PUSHB.bind(undefined, 4),
42806          /* 0xB4 */
42807          PUSHB.bind(undefined, 5),
42808          /* 0xB5 */
42809          PUSHB.bind(undefined, 6),
42810          /* 0xB6 */
42811          PUSHB.bind(undefined, 7),
42812          /* 0xB7 */
42813          PUSHB.bind(undefined, 8),
42814          /* 0xB8 */
42815          PUSHW.bind(undefined, 1),
42816          /* 0xB9 */
42817          PUSHW.bind(undefined, 2),
42818          /* 0xBA */
42819          PUSHW.bind(undefined, 3),
42820          /* 0xBB */
42821          PUSHW.bind(undefined, 4),
42822          /* 0xBC */
42823          PUSHW.bind(undefined, 5),
42824          /* 0xBD */
42825          PUSHW.bind(undefined, 6),
42826          /* 0xBE */
42827          PUSHW.bind(undefined, 7),
42828          /* 0xBF */
42829          PUSHW.bind(undefined, 8),
42830          /* 0xC0 */
42831          MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 0),
42832          /* 0xC1 */
42833          MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 1),
42834          /* 0xC2 */
42835          MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 2),
42836          /* 0xC3 */
42837          MDRP_MIRP.bind(undefined, 0, 0, 0, 0, 3),
42838          /* 0xC4 */
42839          MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 0),
42840          /* 0xC5 */
42841          MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 1),
42842          /* 0xC6 */
42843          MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 2),
42844          /* 0xC7 */
42845          MDRP_MIRP.bind(undefined, 0, 0, 0, 1, 3),
42846          /* 0xC8 */
42847          MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 0),
42848          /* 0xC9 */
42849          MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 1),
42850          /* 0xCA */
42851          MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 2),
42852          /* 0xCB */
42853          MDRP_MIRP.bind(undefined, 0, 0, 1, 0, 3),
42854          /* 0xCC */
42855          MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 0),
42856          /* 0xCD */
42857          MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 1),
42858          /* 0xCE */
42859          MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 2),
42860          /* 0xCF */
42861          MDRP_MIRP.bind(undefined, 0, 0, 1, 1, 3),
42862          /* 0xD0 */
42863          MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 0),
42864          /* 0xD1 */
42865          MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 1),
42866          /* 0xD2 */
42867          MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 2),
42868          /* 0xD3 */
42869          MDRP_MIRP.bind(undefined, 0, 1, 0, 0, 3),
42870          /* 0xD4 */
42871          MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 0),
42872          /* 0xD5 */
42873          MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 1),
42874          /* 0xD6 */
42875          MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 2),
42876          /* 0xD7 */
42877          MDRP_MIRP.bind(undefined, 0, 1, 0, 1, 3),
42878          /* 0xD8 */
42879          MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 0),
42880          /* 0xD9 */
42881          MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 1),
42882          /* 0xDA */
42883          MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 2),
42884          /* 0xDB */
42885          MDRP_MIRP.bind(undefined, 0, 1, 1, 0, 3),
42886          /* 0xDC */
42887          MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 0),
42888          /* 0xDD */
42889          MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 1),
42890          /* 0xDE */
42891          MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 2),
42892          /* 0xDF */
42893          MDRP_MIRP.bind(undefined, 0, 1, 1, 1, 3),
42894          /* 0xE0 */
42895          MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 0),
42896          /* 0xE1 */
42897          MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 1),
42898          /* 0xE2 */
42899          MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 2),
42900          /* 0xE3 */
42901          MDRP_MIRP.bind(undefined, 1, 0, 0, 0, 3),
42902          /* 0xE4 */
42903          MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 0),
42904          /* 0xE5 */
42905          MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 1),
42906          /* 0xE6 */
42907          MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 2),
42908          /* 0xE7 */
42909          MDRP_MIRP.bind(undefined, 1, 0, 0, 1, 3),
42910          /* 0xE8 */
42911          MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 0),
42912          /* 0xE9 */
42913          MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 1),
42914          /* 0xEA */
42915          MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 2),
42916          /* 0xEB */
42917          MDRP_MIRP.bind(undefined, 1, 0, 1, 0, 3),
42918          /* 0xEC */
42919          MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 0),
42920          /* 0xED */
42921          MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 1),
42922          /* 0xEE */
42923          MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 2),
42924          /* 0xEF */
42925          MDRP_MIRP.bind(undefined, 1, 0, 1, 1, 3),
42926          /* 0xF0 */
42927          MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 0),
42928          /* 0xF1 */
42929          MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 1),
42930          /* 0xF2 */
42931          MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 2),
42932          /* 0xF3 */
42933          MDRP_MIRP.bind(undefined, 1, 1, 0, 0, 3),
42934          /* 0xF4 */
42935          MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 0),
42936          /* 0xF5 */
42937          MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 1),
42938          /* 0xF6 */
42939          MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 2),
42940          /* 0xF7 */
42941          MDRP_MIRP.bind(undefined, 1, 1, 0, 1, 3),
42942          /* 0xF8 */
42943          MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 0),
42944          /* 0xF9 */
42945          MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 1),
42946          /* 0xFA */
42947          MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 2),
42948          /* 0xFB */
42949          MDRP_MIRP.bind(undefined, 1, 1, 1, 0, 3),
42950          /* 0xFC */
42951          MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 0),
42952          /* 0xFD */
42953          MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 1),
42954          /* 0xFE */
42955          MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 2),
42956          /* 0xFF */
42957          MDRP_MIRP.bind(undefined, 1, 1, 1, 1, 3)];
42958          /*****************************
42959            Mathematical Considerations
42960          ******************************
42961          	fv ... refers to freedom vector
42962          pv ... refe
42962rs to projection vector
42963          rp ... refers to reference point
42964          p  ... refers to to point being operated on
42965          d  ... refers to distance
42966          	SETRELATIVE:
42967          ============
42968          	case freedom vector == x-axis:
42969          ------------------------------
42970          	                        (pv)
42971                               .-'
42972                        rpd .-'
42973                         .-*
42974                    d .-'90°'
42975                   .-'       '
42976                .-'           '
42977             *-'               ' b
42978            rp                  '
42979                                 '
42980                                  '
42981                      p *----------*-------------- (fv)
42982                                    pm
42983          	  rpdx = rpx + d * pv.x
42984            rpdy = rpy + d * pv.y
42985          	  equation of line b
42986          	   y - rpdy = pvns * (x- rpdx)
42987          	   y = p.y
42988          	   x = rpdx + ( p.y - rpdy ) / pvns
42989          
42990          case freedom vector == y-axis:
42991          ------------------------------
42992          	    * pm
42993              |\
42994              | \
42995              |  \
42996              |   \
42997              |    \
42998              |     \
42999              |      \
43000              |       \
43001              |        \
43002              |         \ b
43003              |          \
43004              |           \
43005              |            \    .-' (pv)
43006              |         90° \.-'
43007              |           .-'* rpd
43008              |        .-'
43009              *     *-'  d
43010              p     rp
43011          	  rpdx = rpx + d * pv.x
43012            rpdy = rpy + d * pv.y
43013          	  equation of line b:
43014                     pvns ... normal slope to pv
43015          	   y - rpdy = pvns * (x - rpdx)
43016          	   x = p.x
43017          	   y = rpdy +  pvns * (p.x - rpdx)
43018          
43019          	generic case:
43020          -------------
43021          
43022                                        .'(fv)
43023                                      .'
43024                                    .* pm
43025                                  .' !
43026                                .'    .
43027                              .'      !
43028                            .'         . b
43029                          .'           !
43030                         *              .
43031                        p               !
43032                                   90°   .    ... (pv)
43033                                     ...-*-'''
43034                            ...---'''    rpd
43035                   ...---'''   d
43036             *--'''
43037            rp
43038          	    rpdx = rpx + d * pv.x
43039              rpdy = rpy + d * pv.y
43040          	 equation of line b:
43041              pvns... normal slope to pv
43042          	    y - rpdy = pvns * (x - rpdx)
43043          	 equation of freedom vector line:
43044              fvs ... slope of freedom vector (=fy/fx)
43045          	    y - py = fvs * (x - px)
43046          
43047            on pm both equations are true for same x/y
43048          	    y - rpdy = pvns * (x - rpdx)
43049          	    y - py = fvs * (x - px)
43050          	  form to y and set equal:
43051          	    pvns * (x - rpdx) + rpdy = fvs * (x - px) + py
43052          	  expand:
43053          	    pvns * x - pvns * rpdx + rpdy = fvs * x - fvs * px + py
43054          	  switch:
43055          	    fvs * x - fvs * px + py = pvns * x - pvns * rpdx + rpdy
43056          	  solve for x:
43057          	    fvs * x - pvns * x = fvs * px - pvns * rpdx - py + rpdy
43058          
43059          	          fvs * px - pvns * rpdx + rpdy - py
43060              x =  -----------------------------------
43061                           fvs - pvns
43062          	  and:
43063          	    y = fvs * (x - px) + py
43064          
43065          	INTERPOLATE:
43066          ============
43067          	Examples of point interpolation.
43068          	The weight of the movement of the reference point gets bigger
43069          the further the other reference point is away, thus the safest
43070          option (that is avoiding 0/0 divisions) is to weight the
43071          original distance of the other point by the sum of both distances.
43072          	If the sum of both distances is 0, then move the point by the
43073          arithmetic average of the movement of both reference points.
43074          
43075          
43076                     (+6)
43077              rp1o *---->*rp1
43078                   .     .                          (+12)
43079                   .     .                  rp2o *---------->* rp2
43080                   .     .                       .           .
43081                   .     .                       .           .
43082                   .    10          20           .           .
43083                   |.........|...................|           .
43084                         .   .                               .
43085                         .   . (+8)                          .
43086                          po *------>*p                      .
43087                         .           .                       .
43088                         .    12     .          24           .
43089                         |...........|.......................|
43090                                            36
43091          
43092          -------
43093          
43094          	           (+10)
43095              rp1o *-------->*rp1
43096                   .         .                      (-10)
43097                   .         .              rp2 *<---------* rpo2
43098                   .         .                   .         .
43099                   .         .                   .         .
43100                   .    10   .          30       .         .
43101                   |.........|.............................|
43102                             .                   .
43103                             . (+5)              .
43104                          po *--->* p            .
43105                             .    .              .
43106                             .    .   20         .
43107                             |....|..............|
43108                               5        15
43109          
43110          -------
43111          
43112                     (+10)
43113              rp1o *-------->*rp1
43114                   .         .
43115                   .         .
43116              rp2o *-------->*rp2
43117          
43118                                         (+10)
43119                                    po *-------->* p
43120          	-------
43121          
43122                     (+10)
43123              rp1o *-------->*rp1
43124                   .         .
43125                   .         .(+30)
43126              rp2o *---------------------------->*rp2
43127          
43128                                                  (+25)
43129                                    po *----------------------->* p
43130          
43131          	vim: set ts=4 sw=4 expandtab:
43132          *****/
43133          // The Font object
43134          // This code is based on Array.from implementation for strings in https://github.com/mathiasbynens/Array.from
43135
43136          var arrayFromString = Array.from || function (s) {
43137            return s.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]?|[^\uD800-\uDFFF]|./g) || [];
43138          };
43139          /**
43140           * @typedef FontOptions
43141           * @type Object
43142           * @property {Boolean} empty - whether to create a new empty font
43143           * @property {string} familyName
43144           * @property {string} styleName
43145           * @property {string=} fullName
43146           * @property {string=} postScriptName
43147           * @property {string=} designer
43148           * @property {string=}
43148 designerURL
43149           * @property {string=} manufacturer
43150           * @property {string=} manufacturerURL
43151           * @property {string=} license
43152           * @property {string=} licenseURL
43153           * @property {string=} version
43154           * @property {string=} description
43155           * @property {string=} copyright
43156           * @property {string=} trademark
43157           * @property {Number} unitsPerEm
43158           * @property {Number} ascender
43159           * @property {Number} descender
43160           * @property {Number} createdTimestamp
43161           * @property {string=} weightClass
43162           * @property {string=} widthClass
43163           * @property {string=} fsSelection
43164           */
43165
43166          /**
43167           * A Font represents a loaded OpenType font file.
43168           * It contains a set of glyphs and methods to draw text on a drawing context,
43169           * or to get a path representing the text.
43170           * @exports opentype.Font
43171           * @class
43172           * @param {FontOptions}
43173           * @constructor
43174           */
43175
43176
43177          function Font(options) {
43178            options = options || {};
43179
43180            if (!options.empty) {
43181              // Check that we've provided the minimum set of names.
43182              checkArgument(options.familyName, 'When creating a new Font object, familyName is required.');
43183              checkArgument(options.styleName, 'When creating a new Font object, styleName is required.');
43184              checkArgument(options.unitsPerEm, 'When creating a new Font object, unitsPerEm is required.');
43185              checkArgument(options.ascender, 'When creating a new Font object, ascender is required.');
43186              checkArgument(options.descender, 'When creating a new Font object, descender is required.');
43187              checkArgument(options.descender < 0, 'Descender should be negative (e.g. -512).'); // OS X will complain if the names are empty, so we put a single space everywhere by default.
43188
43189              this.names = {
43190                fontFamily: {
43191                  en: options.familyName || ' '
43192                },
43193                fontSubfamily: {
43194                  en: options.styleName || ' '
43195                },
43196                fullName: {
43197                  en: options.fullName || options.familyName + ' ' + options.styleName
43198                },
43199                // postScriptName may not contain any whitespace
43200                postScriptName: {
43201                  en: options.postScriptName || (options.familyName + options.styleName).replace(/\s/g, '')
43202                },
43203                designer: {
43204                  en: options.designer || ' '
43205                },
43206                designerURL: {
43207                  en: options.designerURL || ' '
43208                },
43209                manufacturer: {
43210                  en: options.manufacturer || ' '
43211                },
43212                manufacturerURL: {
43213                  en: options.manufacturerURL || ' '
43214                },
43215                license: {
43216                  en: options.license || ' '
43217                },
43218                licenseURL: {
43219                  en: options.licenseURL || ' '
43220                },
43221                version: {
43222                  en: options.version || 'Version 0.1'
43223                },
43224                description: {
43225                  en: options.description || ' '
43226                },
43227                copyright: {
43228                  en: options.copyright || ' '
43229                },
43230                trademark: {
43231                  en: options.trademark || ' '
43232                }
43233              };
43234              this.unitsPerEm = options.unitsPerEm || 1000;
43235              this.ascender = options.ascender;
43236              this.descender = options.descender;
43237              this.createdTimestamp = options.createdTimestamp;
43238              this.tables = {
43239                os2: {
43240                  usWeightClass: options.weightClass || this.usWeightClasses.MEDIUM,
43241                  usWidthClass: options.widthClass || this.usWidthClasses.MEDIUM,
43242                  fsSelection: options.fsSelection || this.fsSelectionValues.REGULAR
43243                }
43244              };
43245            }
43246
43247            this.supported = true; // Deprecated: parseBuffer will throw an error if font is not supported.
43248
43249            this.glyphs = new glyphset.GlyphSet(this, options.glyphs || []);
43250            this.encoding = new DefaultEncoding(this);
43251            this.position = new Position(this);
43252            this.substitution = new Substitution(this);
43253            this.tables = this.tables || {};
43254            Object.defineProperty(this, 'hinting', {
43255              get: function () {
43256                if (this._hinting) {
43257                  return this._hinting;
43258                }
43259
43260                if (this.outlinesFormat === 'truetype') {
43261                  return this._hinting = new Hinting(this);
43262                }
43263              }
43264            });
43265          }
43266          /**
43267           * Check if the font has a glyph for the given character.
43268           * @param  {string}
43269           * @return {Boolean}
43270           */
43271
43272
43273          Font.prototype.hasChar = function (c) {
43274            return this.encoding.charToGlyphIndex(c) !== null;
43275          };
43276          /**
43277           * Convert the given character to a single glyph index.
43278           * Note that this function assumes that there is a one-to-one mapping between
43279           * the given character and a glyph; for complex scripts this might not be the case.
43280           * @param  {string}
43281           * @return {Number}
43282           */
43283
43284
43285          Font.prototype.charToGlyphIndex = function (s) {
43286            return this.encoding.charToGlyphIndex(s);
43287          };
43288          /**
43289           * Convert the given character to a single Glyph object.
43290           * Note that this function assumes that there is a one-to-one mapping between
43291           * the given character and a glyph; for complex scripts this might not be the case.
43292           * @param  {string}
43293           * @return {opentype.Glyph}
43294           */
43295
43296
43297          Font.prototype.charToGlyph = function (c) {
43298            var glyphIndex = this.charToGlyphIndex(c);
43299            var glyph = this.glyphs.get(glyphIndex);
43300
43301            if (!glyph) {
43302              // .notdef
43303              glyph = this.glyphs.get(0);
43304            }
43305
43306            return glyph;
43307          };
43308          /**
43309           * Convert the given text to a list of Glyph objects.
43310           * Note that there is no strict one-to-one mapping between characters and
43311           * glyphs, so the list of returned glyphs can be larger or smaller than the
43312           * length of the given string.
43313           * @param  {string}
43314           * @param  {GlyphRenderOptions} [options]
43315           * @return {opentype.Glyph[]}
43316           */
43317
43318
43319          Font.prototype.stringToGlyphs = function (s, options) {
43320            var this$1 = this;
43321            options = options || this.defaultRenderOptions; // Get glyph indexes
43322
43323            var chars = arrayFromString(s);
43324            var indexes = [];
43325
43326            for (var i = 0; i < chars.length; i += 1) {
43327              var c = chars[i];
43328              indexes.push(this$1.charToGlyphIndex(c));
43329            }
43330
43331            var length = indexes.length; // Apply substitutions on glyph indexes
43332
43333            if (options.features) {
43334              var script = options.script || this.substitution.getDefaultScriptName();
43335              var manyToOne = [];
43336
43337              if (options.features.liga) {
43338                manyToOne = manyToOne.concat(this.substitution.getFeature('liga', script, options.language));
43339              }
43340
43341              if (options.features.rlig) {
43342                manyToOne = manyToOne.concat(this.substitution.getFeature('rlig', script, options.language));
43343              }
43344
43345              for (var i$1 = 0; i$1 < length; i$1 += 1) {
43346                for (var j = 0; j < manyToOne.length; j++) {
43347                  var ligature = manyToOne[j];
43348                  var components = ligature.sub;
43349                  var compCount = components.length;
43350                  var k = 0;
43351
43352                  while (k < compCount && components[k] === indexes[i$1 + k]) {
43353                    k++;
43354                  }
43355
43356                  if (k === compCount) {
43357                    indexes.splice(i$1, compCount, ligature.by);
43358                    length = length - compCount + 1;
43359                  }
43360                }
43361              }
43362            } // convert glyph indexes to glyph objects
43363
43364
43365            var glyphs = new Array(length);
43366            var notdef = this.glyphs.get(0);
43367
43368            for (var i$2 = 0; i$2 < length; i$2 += 1) {
43369              glyphs[i$2] = this$1.glyphs.get(indexes[i$2]) || notdef;
43370            }
43371
43372            return glyphs;
43373          };
43374          /**
43375           * @param  {string}
43376           * @return {Number}
43377           */
43378
43379
43380          Font.prototype.nameToGlyphIndex = function (name) {
43381            return this.glyphNames.nameToGlyphIndex(name);
43382          };
43383          /**
43384           * @param  {string}
43385           * @return {opentype.Glyph}
43386           */
43387
43388
43389          Font.prototype.nameToGlyph = function (name) {
43390            var glyphIndex = this.nameToGlyphIndex(name);
43391            var glyph = this.glyphs.get(glyphIndex);
43392
43393            if (!glyph) {
43394              // .notdef
43395              glyph = this.glyphs.get(0);
43396            }
43397
43398            return glyph;
43399          };
43400          /**
43401           * @param  {Number}
43402           * @return {String}
43403           */
43404
43405
43406          Font.prototype.glyphIndexToName = function (gid) {
43407            if (!this.glyphNames.glyphIndexToName) {
43408              return '';
43409            }
43410
43411            return this.glyphNames.glyphIndexToName(gid);
43412          };
43413          /**
43414           * Retrieve the value of the kerning pair between the left glyph (or its index)
43415           * and the right glyph (or its index). If no kerning pair is found, return 0.
43416           * The kerning value gets added to the advance width when calculating the spacing
43417           * between glyphs.
43418           * For GPOS kerning, this method uses the default script and language, which covers
43419           * most use cases. To have greater control, use font.position.getKerningValue .
43420           * @param  {opentype.Glyph} leftGlyph
43421           * @param  {opentype.Glyph} rightGlyph
43422           * @return {Number}
43423           */
43424
43425
43426          Font.prototype.getKerningValue = function (leftGlyph, rightGlyph) {
43427            leftGlyph = leftGlyph.index || leftGlyph;
43428            rightGlyph = rightGlyph.index || rightGlyph;
43429            var gposKerning = this.position.defaultKerningTables;
43430
43431            if (gposKerning) {
43432              return this.position.getKerningValue(gposKerning, leftGlyph, rightGlyph);
43433            } // "kern" table
43434
43435
43436            return this.kerningPairs[leftGlyph + ',' + rightGlyph] || 0;
43437          };
43438          /**
43439           * @typedef GlyphRenderOptions
43440           * @type Object
43441           * @property {string} [script] - script used to determine which features to apply. By default, 'DFLT' or 'latn' is used.
43442           *                               See https://www.microsoft.com/typography/otspec/scripttags.htm
43443           * @property {string} [language='dflt'] - language system used to determine which features to apply.
43444           *                                        See https://www.microsoft.com/typography/developers/opentype/languagetags.aspx
43445           * @property {boolean} [kerning=true] - whether to include kerning values
43446           * @property {object} [features] - OpenType Layout feature tags. Used to enable or disable the features of the given script/language system.
43447           *                                 See https://www.microsoft.com/typography/otspec/featuretags.htm
43448           */
43449
43450
43451          Font.prototype.defaultRenderOptions = {
43452            kerning: true,
43453            features: {
43454              liga: true,
43455              rlig: true
43456            }
43457          };
43458          /**
43459           * Helper function that invokes the given callback for each glyph in the given text.
43460           * The callback gets `(glyph, x, y, fontSize, options)`.* @param  {string} text
43461           * @param {string} text - The text to apply.
43462           * @param  {number} [x=0] - Horizontal position of the beginning of the text.
43463           * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
43464           * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
43465           * @param  {GlyphRenderOptions=} options
43466           * @param  {Function} callback
43467           */
43468
43469          Font.prototype.forEachGlyph = function (text, x, y, fontSize, options, callback) {
43470            var this$1 = this;
43471            x = x !== undefined ? x : 0;
43472            y = y !== undefined ? y : 0;
43473            fontSize = fontSize !== undefined ? fontSize : 72;
43474            options = options || this.defaultRenderOptions;
43475            var fontScale = 1 / this.unitsPerEm * fontSize;
43476            var glyphs = this.stringToGlyphs(text, options);
43477            var kerningLookups;
43478
43479            if (options.kerning) {
43480              var script = options.script || this.position.getDefaultScriptName();
43481              kerningLookups = this.position.getKerningTables(script, options.language);
43482            }
43483
43484            for (var i = 0; i < glyphs.length; i += 1) {
43485              var glyph = glyphs[i];
43486              callback.call(this$1, glyph, x, y, fontSize, options);
43487
43488              if (glyph.advanceWidth) {
43489                x += glyph.advanceWidth * fontScale;
43490              }
43491
43492              if (options.kerning && i < glyphs.length - 1) {
43493                // We should apply position adjustment lookups in a more generic way.
43494                // Here we only use the xAdvance value.
43495                var kerningValue = kerningLookups ? this$1.position.getKerningValue(kerningLookups, glyph.index, glyphs[i + 1].index) : this$1.getKerningValue(glyph, glyphs[i + 1]);
43496                x += kerningValue * fontScale;
43497              }
43498
43499              if (options.letterSpacing) {
43500                x += options.letterSpacing * fontSize;
43501              } else if (options.tracking) {
43502                x += options.tracking / 1000 * fontSize;
43503              }
43504            }
43505
43506            return x;
43507          };
43508          /**
43509           * Create a Path object that represents the given text.
43510           * @param  {string} text - The text to create.
43511           * @param  {number} [x=0] - Horizontal position of the beginning of the text.
43512           * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
43513           * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
43514           * @param  {GlyphRenderOptions=} options
43515           * @return {opentype.Path}
43516           */
43517
43518
43519          Font.prototype.getPath = function (text, x, y, fontSize, options) {
43520            var fullPath = new Path();
43521            this.forEachGlyph(text, x, y, fontSize, options, function (glyph, gX, gY, gFontSize) {
43522              var glyphPath = glyph.getPath(gX, gY, gFontSize, options, this);
43523              fullPath.extend(glyphPath);
43524            });
43525            return fullPath;
43526          };
43527          /**
43528           * Create an array of Path objects that represent the glyphs of a given text.
43529           * @param  {string} text - The text to create.
43530           * @param  {number} [x=0] - Horizontal position of the beginning of the text.
43531           * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
43532           * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
43533           * @param  {GlyphRenderOptions=} options
43534           * @return {opentype.Path[]}
43535           */
43536
43537
43538          Font.prototype.getPaths = function (text, x, y, fontSize, options) {
43539            var glyphPaths = [];
43540            this.forEachGlyph(text, x, y, fontSize, options, function (glyph, gX, gY, gFontSize) {
43541              var glyphPath = glyph.getPath(gX, gY, gFontSize, options, this);
43542              glyphPaths.push(glyphPath);
43543            });
43544            return glyphPaths;
43545          };
43546          /**
43547           * Returns the advance width of a text.
43548           *
43549           * This is something different than Path.getBoundingBox() as for example a
43550           * suffixed whitespace increases the advanceWidth but not the bounding box
43551           * or an overhanging letter like a calligraphic 'f' mi
43551ght have a quite larger
43552           * bounding box than its advance width.
43553           *
43554           * This corresponds to canvas2dContext.measureText(text).width
43555           *
43556           * @param  {string} text - The text to create.
43557           * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
43558           * @param  {GlyphRenderOptions=} options
43559           * @return advance width
43560           */
43561
43562
43563          Font.prototype.getAdvanceWidth = function (text, fontSize, options) {
43564            return this.forEachGlyph(text, 0, 0, fontSize, options, function () {});
43565          };
43566          /**
43567           * Draw the text on the given drawing context.
43568           * @param  {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
43569           * @param  {string} text - The text to create.
43570           * @param  {number} [x=0] - Horizontal position of the beginning of the text.
43571           * @param  {number} [y=0] - Vertical position of the *baseline* of the text.
43572           * @param  {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
43573           * @param  {GlyphRenderOptions=} options
43574           */
43575
43576
43577          Font.prototype.draw = function (ctx, text, x, y, fontSize, options) {
43578            this.getPath(text, x, y, fontSize, options).draw(ctx);
43579          };
43580          /**
43581           * Draw the points of all glyphs in the text.
43582           * On-curve points will be drawn in blue, off-curve points will be drawn in red.
43583           * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
43584           * @param {string} text - The text to create.
43585           * @param {number} [x=0] - Horizontal position of the beginning of the text.
43586           * @param {number} [y=0] - Vertical position of the *baseline* of the text.
43587           * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
43588           * @param {GlyphRenderOptions=} options
43589           */
43590
43591
43592          Font.prototype.drawPoints = function (ctx, text, x, y, fontSize, options) {
43593            this.forEachGlyph(text, x, y, fontSize, options, function (glyph, gX, gY, gFontSize) {
43594              glyph.drawPoints(ctx, gX, gY, gFontSize);
43595            });
43596          };
43597          /**
43598           * Draw lines indicating important font measurements for all glyphs in the text.
43599           * Black lines indicate the origin of the coordinate system (point 0,0).
43600           * Blue lines indicate the glyph bounding box.
43601           * Green line indicates the advance width of the glyph.
43602           * @param {CanvasRenderingContext2D} ctx - A 2D drawing context, like Canvas.
43603           * @param {string} text - The text to create.
43604           * @param {number} [x=0] - Horizontal position of the beginning of the text.
43605           * @param {number} [y=0] - Vertical position of the *baseline* of the text.
43606           * @param {number} [fontSize=72] - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`.
43607           * @param {GlyphRenderOptions=} options
43608           */
43609
43610
43611          Font.prototype.drawMetrics = function (ctx, text, x, y, fontSize, options) {
43612            this.forEachGlyph(text, x, y, fontSize, options, function (glyph, gX, gY, gFontSize) {
43613              glyph.drawMetrics(ctx, gX, gY, gFontSize);
43614            });
43615          };
43616          /**
43617           * @param  {string}
43618           * @return {string}
43619           */
43620
43621
43622          Font.prototype.getEnglishName = function (name) {
43623            var translations = this.names[name];
43624
43625            if (translations) {
43626              return translations.en;
43627            }
43628          };
43629          /**
43630           * Validate
43631           */
43632
43633
43634          Font.prototype.validate = function () {
43635            var _this = this;
43636
43637            function assert(predicate, message) {}
43638
43639            function assertNamePresent(name) {
43640              var englishName = _this.getEnglishName(name);
43641
43642              assert(englishName && englishName.trim().length > 0, 'No English ' + name + ' specified.');
43643            } // Identification information
43644
43645
43646            assertNamePresent('fontFamily');
43647            assertNamePresent('weightName');
43648            assertNamePresent('manufacturer');
43649            assertNamePresent('copyright');
43650            assertNamePresent('version'); // Dimension information
43651
43652            assert(this.unitsPerEm > 0, 'No unitsPerEm specified.');
43653          };
43654          /**
43655           * Convert the font object to a SFNT data structure.
43656           * This structure contains all the necessary tables and metadata to create a binary OTF file.
43657           * @return {opentype.Table}
43658           */
43659
43660
43661          Font.prototype.toTables = function () {
43662            return sfnt.fontToTable(this);
43663          };
43664          /**
43665           * @deprecated Font.toBuffer is deprecated. Use Font.toArrayBuffer instead.
43666           */
43667
43668
43669          Font.prototype.toBuffer = function () {
43670            console.warn('Font.toBuffer is deprecated. Use Font.toArrayBuffer instead.');
43671            return this.toArrayBuffer();
43672          };
43673          /**
43674           * Converts a `opentype.Font` into an `ArrayBuffer`
43675           * @return {ArrayBuffer}
43676           */
43677
43678
43679          Font.prototype.toArrayBuffer = function () {
43680            var sfntTable = this.toTables();
43681            var bytes = sfntTable.encode();
43682            var buffer = new ArrayBuffer(bytes.length);
43683            var intArray = new Uint8Array(buffer);
43684
43685            for (var i = 0; i < bytes.length; i++) {
43686              intArray[i] = bytes[i];
43687            }
43688
43689            return buffer;
43690          };
43691          /**
43692           * Initiate a download of the OpenType font.
43693           */
43694
43695
43696          Font.prototype.download = function (fileName) {
43697            var familyName = this.getEnglishName('fontFamily');
43698            var styleName = this.getEnglishName('fontSubfamily');
43699            fileName = fileName || familyName.replace(/\s/g, '') + '-' + styleName + '.otf';
43700            var arrayBuffer = this.toArrayBuffer();
43701
43702            if (isBrowser()) {
43703              window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
43704              window.requestFileSystem(window.TEMPORARY, arrayBuffer.byteLength, function (fs) {
43705                fs.root.getFile(fileName, {
43706                  create: true
43707                }, function (fileEntry) {
43708                  fileEntry.createWriter(function (writer) {
43709                    var dataView = new DataView(arrayBuffer);
43710                    var blob = new Blob([dataView], {
43711                      type: 'font/opentype'
43712                    });
43713                    writer.write(blob);
43714                    writer.addEventListener('writeend', function () {
43715                      // Navigating to the file will download it.
43716                      location.href = fileEntry.toURL();
43717                    }, false);
43718                  });
43719                });
43720              }, function (err) {
43721                throw new Error(err.name + ': ' + err.message);
43722              });
43723            } else {
43724              var fs = _dereq_('fs');
43725
43726              var buffer = arrayBufferToNodeBuffer(arrayBuffer);
43727              fs.writeFileSync(fileName, buffer);
43728            }
43729          };
43730          /**
43731           * @private
43732           */
43733
43734
43735          Font.prototype.fsSelectionValues = {
43736            ITALIC: 0x001,
43737            //1
43738            UNDERSCORE: 0x002,
43739            //2
43740            NEGATIVE: 0x004,
43741            //4
43742            OUTLINED: 0x008,
43743            //8
43744            STRIKEOUT: 0x010,
43745            //16
43746            BOLD: 0x020,
43747            //32
43748            REGULAR: 0x040,
43749            //64
43750            USER_TYPO_METRICS: 0x080,
43751            //128
43752            WWS: 0x100,
43753            //256
43754            OBLIQUE: 0x200 //512
43755
43756          };
43757          /**
43758           * @private
43759           */
43760
43761          Font.prototype.usWidthClasses = {
43762            ULTRA_CONDENSED: 1,
43763            EXTRA_CONDENSED: 2,
43764            CONDENSED: 3,
43765            SEMI_CONDENSED: 4,
43766            MEDIUM: 5,
43767            SEMI_EXPANDED: 6,
43768            EXPANDED: 7,
43769            EXTRA_EXPANDED: 8,
43770            ULTRA_EXPANDED: 9
43771          };
43772          /**
43773           * @private
43774           */
43775
43776          Font.prototype.usWeightClasses = {
43777            THIN: 100,
43778            EXTRA_LIGHT: 200,
43779            LIGHT: 300,
43780            NORMAL: 400,
43781            MEDIUM: 500,
43782            SEMI_BOLD: 600,
43783            BOLD: 700,
43784            EXTRA_BOLD: 800,
43785            BLACK: 900
43786          }; // The `fvar` table stores font variation axes and instances.
43787
43788          function addName(name, names) {
43789            var nameString = JSON.stringify(name);
43790            var nameID = 256;
43791
43792            for (var nameKey in names) {
43793              var n = parseInt(nameKey);
43794
43795              if (!n || n < 256) {
43796                continue;
43797              }
43798
43799              if (JSON.stringify(names[nameKey]) === nameString) {
43800                return n;
43801              }
43802
43803              if (nameID <= n) {
43804                nameID = n + 1;
43805              }
43806            }
43807
43808            names[nameID] = name;
43809            return nameID;
43810          }
43811
43812          function makeFvarAxis(n, axis, names) {
43813            var nameID = addName(axis.name, names);
43814            return [{
43815              name: 'tag_' + n,
43816              type: 'TAG',
43817              value: axis.tag
43818            }, {
43819              name: 'minValue_' + n,
43820              type: 'FIXED',
43821              value: axis.minValue << 16
43822            }, {
43823              name: 'defaultValue_' + n,
43824              type: 'FIXED',
43825              value: axis.defaultValue << 16
43826            }, {
43827              name: 'maxValue_' + n,
43828              type: 'FIXED',
43829              value: axis.maxValue << 16
43830            }, {
43831              name: 'flags_' + n,
43832              type: 'USHORT',
43833              value: 0
43834            }, {
43835              name: 'nameID_' + n,
43836              type: 'USHORT',
43837              value: nameID
43838            }];
43839          }
43840
43841          function parseFvarAxis(data, start, names) {
43842            var axis = {};
43843            var p = new parse.Parser(data, start);
43844            axis.tag = p.parseTag();
43845            axis.minValue = p.parseFixed();
43846            axis.defaultValue = p.parseFixed();
43847            axis.maxValue = p.parseFixed();
43848            p.skip('uShort', 1); // reserved for flags; no values defined
43849
43850            axis.name = names[p.parseUShort()] || {};
43851            return axis;
43852          }
43853
43854          function makeFvarInstance(n, inst, axes, names) {
43855            var nameID = addName(inst.name, names);
43856            var fields = [{
43857              name: 'nameID_' + n,
43858              type: 'USHORT',
43859              value: nameID
43860            }, {
43861              name: 'flags_' + n,
43862              type: 'USHORT',
43863              value: 0
43864            }];
43865
43866            for (var i = 0; i < axes.length; ++i) {
43867              var axisTag = axes[i].tag;
43868              fields.push({
43869                name: 'axis_' + n + ' ' + axisTag,
43870                type: 'FIXED',
43871                value: inst.coordinates[axisTag] << 16
43872              });
43873            }
43874
43875            return fields;
43876          }
43877
43878          function parseFvarInstance(data, start, axes, names) {
43879            var inst = {};
43880            var p = new parse.Parser(data, start);
43881            inst.name = names[p.parseUShort()] || {};
43882            p.skip('uShort', 1); // reserved for flags; no values defined
43883
43884            inst.coordinates = {};
43885
43886            for (var i = 0; i < axes.length; ++i) {
43887              inst.coordinates[axes[i].tag] = p.parseFixed();
43888            }
43889
43890            return inst;
43891          }
43892
43893          function makeFvarTable(fvar, names) {
43894            var result = new table.Table('fvar', [{
43895              name: 'version',
43896              type: 'ULONG',
43897              value: 0x10000
43898            }, {
43899              name: 'offsetToData',
43900              type: 'USHORT',
43901              value: 0
43902            }, {
43903              name: 'countSizePairs',
43904              type: 'USHORT',
43905              value: 2
43906            }, {
43907              name: 'axisCount',
43908              type: 'USHORT',
43909              value: fvar.axes.length
43910            }, {
43911              name: 'axisSize',
43912              type: 'USHORT',
43913              value: 20
43914            }, {
43915              name: 'instanceCount',
43916              type: 'USHORT',
43917              value: fvar.instances.length
43918            }, {
43919              name: 'instanceSize',
43920              type: 'USHORT',
43921              value: 4 + fvar.axes.length * 4
43922            }]);
43923            result.offsetToData = result.sizeOf();
43924
43925            for (var i = 0; i < fvar.axes.length; i++) {
43926              result.fields = result.fields.concat(makeFvarAxis(i, fvar.axes[i], names));
43927            }
43928
43929            for (var j = 0; j < fvar.instances.length; j++) {
43930              result.fields = result.fields.concat(makeFvarInstance(j, fvar.instances[j], fvar.axes, names));
43931            }
43932
43933            return result;
43934          }
43935
43936          function parseFvarTable(data, start, names) {
43937            var p = new parse.Parser(data, start);
43938            var tableVersion = p.parseULong();
43939            check.argument(tableVersion === 0x00010000, 'Unsupported fvar table version.');
43940            var offsetToData = p.parseOffset16(); // Skip countSizePairs.
43941
vendor: 4,756 bytes, lines 43942-44065
43942            p.skip('uShort', 1);
43943            var axisCount = p.parseUShort();
43944            var axisSize = p.parseUShort();
43945            var instanceCount = p.parseUShort();
43946            var instanceSize = p.parseUShort();
43947            var axes = [];
43948
43949            for (var i = 0; i < axisCount; i++) {
43950              axes.push(parseFvarAxis(data, start + offsetToData + i * axisSize, names));
43951            }
43952
43953            var instances = [];
43954            var instanceStart = start + offsetToData + axisCount * axisSize;
43955
43956            for (var j = 0; j < instanceCount; j++) {
43957              instances.push(parseFvarInstance(data, instanceStart + j * instanceSize, axes, names));
43958            }
43959
43960            return {
43961              axes: axes,
43962              instances: instances
43963            };
43964          }
43965
43966          var fvar = {
43967            make: makeFvarTable,
43968            parse: parseFvarTable
43969          }; // The `GPOS` table contains kerning pairs, among other things.
43970
43971          var subtableParsers$1 = new Array(10); // subtableParsers[0] is unused
43972          // https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#lookup-type-1-single-adjustment-positioning-subtable
43973          // this = Parser instance
43974
43975          subtableParsers$1[1] = function parseLookup1() {
43976            var start = this.offset + this.relativeOffset;
43977            var posformat = this.parseUShort();
43978
43979            if (posformat === 1) {
43980              return {
43981                posFormat: 1,
43982                coverage: this.parsePointer(Parser.coverage),
43983                value: this.parseValueRecord()
43984              };
43985            } else if (posformat === 2) {
43986              return {
43987                posFormat: 2,
43988                coverage: this.parsePointer(Parser.coverage),
43989                values: this.parseValueRecordList()
43990              };
43991            }
43992
43993            check.assert(false, '0x' + start.toString(16) + ': GPOS lookup type 1 format must be 1 or 2.');
43994          }; // https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#lookup-type-2-pair-adjustment-positioning-subtable
43995
43996
43997          subtableParsers$1[2] = function parseLookup2() {
43998            var start = this.offset + this.relativeOffset;
43999            var posFormat = this.parseUShort();
44000            check.assert(posFormat === 1 || posFormat === 2, '0x' + start.toString(16) + ': GPOS lookup type 2 format must be 1 or 2.');
44001            var coverage = this.parsePointer(Parser.coverage);
44002            var valueFormat1 = this.parseUShort();
44003            var valueFormat2 = this.parseUShort();
44004
44005            if (posFormat === 1) {
44006              // Adjustments for Glyph Pairs
44007              return {
44008                posFormat: posFormat,
44009                coverage: coverage,
44010                valueFormat1: valueFormat1,
44011                valueFormat2: valueFormat2,
44012                pairSets: this.parseList(Parser.pointer(Parser.list(function () {
44013                  return {
44014                    // pairValueRecord
44015                    secondGlyph: this.parseUShort(),
44016                    value1: this.parseValueRecord(valueFormat1),
44017                    value2: this.parseValueRecord(valueFormat2)
44018                  };
44019                })))
44020              };
44021            } else if (posFormat === 2) {
44022              var classDef1 = this.parsePointer(Parser.classDef);
44023              var classDef2 = this.parsePointer(Parser.classDef);
44024              var class1Count = this.parseUShort();
44025              var class2Count = this.parseUShort();
44026              return {
44027                // Class Pair Adjustment
44028                posFormat: posFormat,
44029                coverage: coverage,
44030                valueFormat1: valueFormat1,
44031                valueFormat2: valueFormat2,
44032                classDef1: classDef1,
44033                classDef2: classDef2,
44034                class1Count: class1Count,
44035                class2Count: class2Count,
44036                classRecords: this.parseList(class1Count, Parser.list(class2Count, function () {
44037                  return {
44038                    value1: this.parseValueRecord(valueFormat1),
44039                    value2: this.parseValueRecord(valueFormat2)
44040                  };
44041                }))
44042              };
44043            }
44044          };
44045
44046          subtableParsers$1[3] = function parseLookup3() {
44047            return {
44048              error: 'GPOS Lookup 3 not supported'
44049            };
44050          };
44051
44052          subtableParsers$1[4] = function parseLookup4() {
44053            return {
44054              error: 'GPOS Lookup 4 not supported'
44055            };
44056          };
44057
44058          subtableParsers$1[5] = function parseLookup5() {
44059            return {
44060              error: 'GPOS Lookup 5 not supported'
44061            };
44062          };
44063
44064          subtableParsers$1[6] = function parseLookup6() {
44065            return {
44066              error: 'GPOS Lookup 6 not supported'
44067            };
44068          };
44069
44070          subtableParsers$1[7] = function parseLookup7() {
44071            return {
44072              error: 'GPOS Lookup 7 not supported'
44073            };
44074          };
44075
44076          subtableParsers$1[8] = function parseLookup8() {
44077            return {
44078              error: 'GPOS Lookup 8 not supported'
44079            };
44080          };
44081
44082          subtableParsers$1[9] = function parseLookup9() {
44083            return {
44084              error: 'GPOS Lookup 9 not supported'
44085            };
44086          }; // https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
44087
44088
44089          function parseGposTable(data, start) {
44090            start = start || 0;
44091            var p = new Parser(data, start);
44092            var tableVersion = p.parseVersion(1);
44093            check.argument(tableVersion === 1 || tableVersion === 1.1, 'Unsupported GPOS table version ' + tableVersion);
44094
44095            if (tableVersion === 1) {
44096              return {
44097                version: tableVersion,
44098                scripts: p.parseScriptList(),
44099                features: p.parseFeatureList(),
44100                lookups: p.parseLookupList(subtableParsers$1)
44101              };
44102            } else {
44103              return {
44104                version: tableVersion,
44105                scripts: p.parseScriptList(),
44106                features: p.parseFeatureList(),
44107                lookups: p.parseLookupList(subtableParsers$1),
44108                variations: p.parseFeatureVariationsList()
44109              };
44110            }
44111          } // GPOS Writing //////////////////////////////////////////////
44112          // NOT SUPPORTED
44113
44114
44115          var subtableMakers$1 = new Array(10);
44116
44117          function makeGposTable(gpos) {
44118            return new table.Table('GPOS', [{
44119              name: 'version',
44120              type: 'ULONG',
44121              value: 0x10000
44122            }, {
44123              name: 'scripts',
44124              type: 'TABLE',
44125              value: new table.ScriptList(gpos.scripts)
44126            }, {
44127              name: 'features',
44128              type: 'TABLE',
44129              value: new table.FeatureList(gpos.features)
44130            }, {
44131              name: 'lookups',
44132              type: 'TABLE',
44133              value: new table.LookupList(gpos.lookups, subtableMakers$1)
44134            }]);
44135          }
44136
44137          var gpos = {
44138            parse: parseGposTable,
44139            make: makeGposTable
44140          }; // The `kern` table contains kerning pairs.
44141
44142          function parseWindowsKernTable(p) {
44143            var pairs = {}; // Skip nTables.
44144
44145            p.skip('uShort');
44146            var subtableVersion = p.parseUShort();
44147            check.argument(subtableVersion === 0, 'Unsupported kern sub-table version.'); // Skip subtableLength, subtableCoverage
44148
44149            p.skip('uShort', 2);
44150            var nPairs = p.parseUShort(); // Skip searchRange, entrySelector, rangeShift.
44151
44152            p.skip('uShort', 3);
44153
44154            for (var i = 0; i < nPairs; i += 1) {
44155              var leftIndex = p.parseUShort();
44156              var rightIndex = p.parseUShort();
44157              var value = p.parseShort();
44158              pairs[leftIndex + ',' + rightIndex] = value;
44159            }
44160
44161            return pairs;
44162          }
44163
44164          function parseMacKernTable(p) {
44165            var pairs = {}; // The Mac kern table stores the version as a fixed (32 bits) but we only loaded the first 16 bits.
44166            // Skip the rest.
44167
44168            p.skip('uShort');
44169            var nTables = p.parseULong(); //check.argument(nTables === 1, 'Only 1 subtable is supported (got ' + nTables + ').');
44170
44171            if (nTables > 1) {
44172              console.warn('Only the first kern subtable is supported.');
44173            }
44174
44175            p.skip('uLong');
44176            var coverage = p.parseUShort();
44177            var subtableVersion = coverage & 0xFF;
44178            p.skip('uShort');
44179
44180            if (subtableVersion === 0) {
44181              var nPairs = p.parseUShort(); // Skip searchRange, entrySelector, rangeShift.
44182
44183              p.skip('uShort', 3);
44184
44185              for (var i = 0; i < nPairs; i += 1) {
44186                var leftIndex = p.parseUShort();
44187                var rightIndex = p.parseUShort();
44188                var value = p.parseShort();
44189                pairs[leftIndex + ',' + rightIndex] = value;
44190              }
44191            }
44192
44193            return pairs;
44194          } // Parse the `kern` table which contains kerning pairs.
44195
44196
44197          function parseKernTable(data, start) {
44198            var p = new parse.Parser(data, start);
44199            var tableVersion = p.parseUShort();
44200
44201            if (tableVersion === 0) {
44202              return parseWindowsKernTable(p);
44203            } else if (tableVersion === 1) {
44204              return parseMacKernTable(p);
44205            } else {
44206              throw new Error('Unsupported kern table version (' + tableVersion + ').');
44207            }
44208          }
44209
44210          var kern = {
44211            parse: parseKernTable
44212          }; // The `loca` table stores the offsets to the locations of the glyphs in the font.
44213          // Parse the `loca` table. This table stores the offsets to the locations of the glyphs in the font,
44214          // relative to the beginning of the glyphData table.
44215          // The number of glyphs stored in the `loca` table is specified in the `maxp` table (under numGlyphs)
44216          // The loca table has two versions: a short version where offsets are stored as uShorts, and a long
44217          // version where offsets are stored as uLongs. The `head` table specifies which version to use
44218          // (under indexToLocFormat).
44219
44220          function parseLocaTable(data, start, numGlyphs, shortVersion) {
44221            var p = new parse.Parser(data, start);
44222            var parseFn = shortVersion ? p.parseUShort : p.parseULong; // There is an extra entry after the last index element to compute the length of the last glyph.
44223            // That's why we use numGlyphs + 1.
44224
44225            var glyphOffsets = [];
44226
44227            for (var i = 0; i < numGlyphs + 1; i += 1) {
44228              var glyphOffset = parseFn.call(p);
44229
44230              if (shortVersion) {
44231                // The short table version stores the actual offset divided by 2.
44232                glyphOffset *= 2;
44233              }
44234
44235              glyphOffsets.push(glyphOffset);
44236            }
44237
44238            return glyphOffsets;
44239          }
44240
44241          var loca = {
44242            parse: parseLocaTable
44243          }; // opentype.js
44244
44245          /**
44246           * The opentype library.
44247           * @namespace opentype
44248           */
44249          // File loaders /////////////////////////////////////////////////////////
44250
44251          /**
44252           * Loads a font from a file. The callback throws an error message as the first parameter if it fails
44253           * and the font as an ArrayBuffer in the second parameter if it succeeds.
44254           * @param  {string} path - The path of the file
44255           * @param  {Function} callback - The function to call when the font load completes
44256           */
44257
44258          function loadFromFile(path, callback) {
44259            var fs = _dereq_('fs');
44260
44261            fs.readFile(path, function (err, buffer) {
44262              if (err) {
44263                return callback(err.message);
44264              }
44265
44266              callback(null, nodeBufferToArrayBuffer(buffer));
44267            });
44268          }
44269          /**
44270           * Loads a font from a URL. The callback throws an error message as the first parameter if it fails
44271           * and the font as an ArrayBuffer in the second parameter if it succeeds.
44272           * @param  {string} url - The URL of the font file.
44273           * @param  {Function} callback - The function to call when the font load completes
44274           */
44275
44276
44277          function loadFromUrl(url, callback) {
44278            var request = new XMLHttpRequest();
44279            request.open('get', url, true);
44280            request.responseType = 'arraybuffer';
44281
44282            request.onload = function () {
44283              if (request.response) {
44284                return callback(null, request.response);
44285              } else {
44286                return callback('Font could not be loaded: ' + request.statusText);
44287              }
44288            };
44289
44290            request.onerror = function () {
44291              callback('Font could not be loaded');
44292            };
44293
44294            request.send();
44295          } // Table Directory Entries //////////////////////////////////////////////
44296
44297          /**
44298           * Parses OpenType table entries.
44299           * @param  {DataView}
44300           * @param  {Number}
44301           * @return {Object[]}
44302           */
44303
44304
44305          function parseOpenTypeTableEntries(data, numTables) {
44306            var tableEntries = [];
44307            var p = 12;
44308
44309            for (var i = 0; i < numTables; i += 1) {
44310              var tag = parse.getTag(data, p);
44311              var checksum = parse.getULong(data, p + 4);
44312              var offset = parse.getULong(data, p + 8);
44313              var length = parse.getULong(data, p + 12);
44314              tableEntries.push({
44315                tag: tag,
44316                checksum: checksum,
44317                offset: offset,
44318                length: length,
44319                compression: false
44320              });
44321              p += 16;
44322            }
44323
44324            return tableEntries;
44325          }
44326          /**
44327           * Parses WOFF table entries.
44328           * @param  {DataView}
44329           * @param  {Number}
44330           * @return {Object[]}
44331           */
44332
44333
44334          function parseWOFFTableEntries(data, numTables) {
44335            var tableEntries = [];
44336            var p = 44; // offset to the first table directory entry.
44337
44338            for (var i = 0; i < numTables; i += 1) {
44339              var tag = parse.getTag(data, p);
44340              var offset = parse.getULong(data, p + 4);
44341              var compLength = parse.getULong(data, p + 8);
44342              var origLength = parse.getULong(data, p + 12);
44343              var compression = void 0;
44344
44345              if (compLength < origLength) {
44346                compression = 'WOFF';
44347              } else {
44348                compression = false;
vendor: 8,505 bytes, lines 44349-44577
44349              }
44350
44351              tableEntries.push({
44352                tag: tag,
44353                offset: offset,
44354                compression: compression,
44355                compressedLength: compLength,
44356                length: origLength
44357              });
44358              p += 20;
44359            }
44360
44361            return tableEntries;
44362          }
44363          /**
44364           * @typedef TableData
44365           * @type Object
44366           * @property {DataView} data - The DataView
44367           * @property {number} offset - The data offset.
44368           */
44369
44370          /**
44371           * @param  {DataView}
44372           * @param  {Object}
44373           * @return {TableData}
44374           */
44375
44376
44377          function uncompressTable(data, tableEntry) {
44378            if (tableEntry.compression === 'WOFF') {
44379              var inBuffer = new Uint8Array(data.buffer, tableEntry.offset + 2, tableEntry.compressedLength - 2);
44380              var outBuffer = new Uint8Array(tableEntry.length);
44381              tinyInflate(inBuffer, outBuffer);
44382
44383              if (outBuffer.byteLength !== tableEntry.length) {
44384                throw new Error('Decompression error: ' + tableEntry.tag + ' decompressed length doesn\'t match recorded length');
44385              }
44386
44387              var view = new DataView(outBuffer.buffer, 0);
44388              return {
44389                data: view,
44390                offset: 0
44391              };
44392            } else {
44393              return {
44394                data: data,
44395                offset: tableEntry.offset
44396              };
44397            }
44398          } // Public API ///////////////////////////////////////////////////////////
44399
44400          /**
44401           * Parse the OpenType file data (as an ArrayBuffer) and return a Font object.
44402           * Throws an error if the font could not be parsed.
44403           * @param  {ArrayBuffer}
44404           * @return {opentype.Font}
44405           */
44406
44407
44408          function parseBuffer(buffer) {
44409            var indexToLocFormat;
44410            var ltagTable; // Since the constructor can also be called to create new fonts from scratch, we indicate this
44411            // should be an empty font that we'll fill with our own data.
44412
44413            var font = new Font({
44414              empty: true
44415            }); // OpenType fonts use big endian byte ordering.
44416            // We can't rely on typed array view types, because they operate with the endianness of the host computer.
44417            // Instead we use DataViews where we can specify endianness.
44418
44419            var data = new DataView(buffer, 0);
44420            var numTables;
44421            var tableEntries = [];
44422            var signature = parse.getTag(data, 0);
44423
44424            if (signature === String.fromCharCode(0, 1, 0, 0) || signature === 'true' || signature === 'typ1') {
44425              font.outlinesFormat = 'truetype';
44426              numTables = parse.getUShort(data, 4);
44427              tableEntries = parseOpenTypeTableEntries(data, numTables);
44428            } else if (signature === 'OTTO') {
44429              font.outlinesFormat = 'cff';
44430              numTables = parse.getUShort(data, 4);
44431              tableEntries = parseOpenTypeTableEntries(data, numTables);
44432            } else if (signature === 'wOFF') {
44433              var flavor = parse.getTag(data, 4);
44434
44435              if (flavor === String.fromCharCode(0, 1, 0, 0)) {
44436                font.outlinesFormat = 'truetype';
44437              } else if (flavor === 'OTTO') {
44438                font.outlinesFormat = 'cff';
44439              } else {
44440                throw new Error('Unsupported OpenType flavor ' + signature);
44441              }
44442
44443              numTables = parse.getUShort(data, 12);
44444              tableEntries = parseWOFFTableEntries(data, numTables);
44445            } else {
44446              throw new Error('Unsupported OpenType signature ' + signature);
44447            }
44448
44449            var cffTableEntry;
44450            var fvarTableEntry;
44451            var glyfTableEntry;
44452            var gposTableEntry;
44453            var gsubTableEntry;
44454            var hmtxTableEntry;
44455            var kernTableEntry;
44456            var locaTableEntry;
44457            var nameTableEntry;
44458            var metaTableEntry;
44459            var p;
44460
44461            for (var i = 0; i < numTables; i += 1) {
44462              var tableEntry = tableEntries[i];
44463              var table = void 0;
44464
44465              switch (tableEntry.tag) {
44466                case 'cmap':
44467                  table = uncompressTable(data, tableEntry);
44468                  font.tables.cmap = cmap.parse(table.data, table.offset);
44469                  font.encoding = new CmapEncoding(font.tables.cmap);
44470                  break;
44471
44472                case 'cvt ':
44473                  table = uncompressTable(data, tableEntry);
44474                  p = new parse.Parser(table.data, table.offset);
44475                  font.tables.cvt = p.parseShortList(tableEntry.length / 2);
44476                  break;
44477
44478                case 'fvar':
44479                  fvarTableEntry = tableEntry;
44480                  break;
44481
44482                case 'fpgm':
44483                  table = uncompressTable(data, tableEntry);
44484                  p = new parse.Parser(table.data, table.offset);
44485                  font.tables.fpgm = p.parseByteList(tableEntry.length);
44486                  break;
44487
44488                case 'head':
44489                  table = uncompressTable(data, tableEntry);
44490                  font.tables.head = head.parse(table.data, table.offset);
44491                  font.unitsPerEm = font.tables.head.unitsPerEm;
44492                  indexToLocFormat = font.tables.head.indexToLocFormat;
44493                  break;
44494
44495                case 'hhea':
44496                  table = uncompressTable(data, tableEntry);
44497                  font.tables.hhea = hhea.parse(table.data, table.offset);
44498                  font.ascender = font.tables.hhea.ascender;
44499                  font.descender = font.tables.hhea.descender;
44500                  font.numberOfHMetrics = font.tables.hhea.numberOfHMetrics;
44501                  break;
44502
44503                case 'hmtx':
44504                  hmtxTableEntry = tableEntry;
44505                  break;
44506
44507                case 'ltag':
44508                  table = uncompressTable(data, tableEntry);
44509                  ltagTable = ltag.parse(table.data, table.offset);
44510                  break;
44511
44512                case 'maxp':
44513                  table = uncompressTable(data, tableEntry);
44514                  font.tables.maxp = maxp.parse(table.data, table.offset);
44515                  font.numGlyphs = font.tables.maxp.numGlyphs;
44516                  break;
44517
44518                case 'name':
44519                  nameTableEntry = tableEntry;
44520                  break;
44521
44522                case 'OS/2':
44523                  table = uncompressTable(data, tableEntry);
44524                  font.tables.os2 = os2.parse(table.data, table.offset);
44525                  break;
44526
44527                case 'post':
44528                  table = uncompressTable(data, tableEntry);
44529                  font.tables.post = post.parse(table.data, table.offset);
44530                  font.glyphNames = new GlyphNames(font.tables.post);
44531                  break;
44532
44533                case 'prep':
44534                  table = uncompressTable(data, tableEntry);
44535                  p = new parse.Parser(table.data, table.offset);
44536                  font.tables.prep = p.parseByteList(tableEntry.length);
44537                  break;
44538
44539                case 'glyf':
44540                  glyfTableEntry = tableEntry;
44541                  break;
44542
44543                case 'loca':
44544                  locaTableEntry = tableEntry;
44545                  break;
44546
44547                case 'CFF ':
44548                  cffTableEntry = tableEntry;
44549                  break;
44550
44551                case 'kern':
44552                  kernTableEntry = tableEntry;
44553                  break;
44554
44555                case 'GPOS':
44556                  gposTableEntry = tableEntry;
44557                  break;
44558
44559                case 'GSUB':
44560                  gsubTableEntry = tableEntry;
44561                  break;
44562
44563                case 'meta':
44564                  metaTableEntry = tableEntry;
44565                  break;
44566              }
44567            }
44568
44569            var nameTable = uncompressTable(data, nameTableEntry);
44570            font.tables.name = _name.parse(nameTable.data, nameTable.offset, ltagTable);
44571            font.names = font.tables.name;
44572
44573            if (glyfTableEntry && locaTableEntry) {
44574              var shortVersion = indexToLocFormat === 0;
44575              var locaTable = uncompressTable(data, locaTableEntry);
44576              var locaOffsets = loca.parse(locaTable.data, locaTable.offset, font.numGlyphs, shortVersion);
44577              var glyfTable = uncompressTable(data, glyfTableEntry
44577);
44578              font.glyphs = glyf.parse(glyfTable.data, glyfTable.offset, locaOffsets, font);
44579            } else if (cffTableEntry) {
44580              var cffTable = uncompressTable(data, cffTableEntry);
44581              cff.parse(cffTable.data, cffTable.offset, font);
44582            } else {
44583              throw new Error('Font doesn\'t contain TrueType or CFF outlines.');
44584            }
44585
44586            var hmtxTable = uncompressTable(data, hmtxTableEntry);
44587            hmtx.parse(hmtxTable.data, hmtxTable.offset, font.numberOfHMetrics, font.numGlyphs, font.glyphs);
44588            addGlyphNames(font);
44589
44590            if (kernTableEntry) {
44591              var kernTable = uncompressTable(data, kernTableEntry);
44592              font.kerningPairs = kern.parse(kernTable.data, kernTable.offset);
44593            } else {
44594              font.kerningPairs = {};
44595            }
44596
44597            if (gposTableEntry) {
44598              var gposTable = uncompressTable(data, gposTableEntry);
44599              font.tables.gpos = gpos.parse(gposTable.data, gposTable.offset);
44600              font.position.init();
44601            }
44602
44603            if (gsubTableEntry) {
44604              var gsubTable = uncompressTable(data, gsubTableEntry);
44605              font.tables.gsub = gsub.parse(gsubTable.data, gsubTable.offset);
44606            }
44607
44608            if (fvarTableEntry) {
44609              var fvarTable = uncompressTable(data, fvarTableEntry);
44610              font.tables.fvar = fvar.parse(fvarTable.data, fvarTable.offset, font.names);
44611            }
44612
44613            if (metaTableEntry) {
44614              var metaTable = uncompressTable(data, metaTableEntry);
44615              font.tables.meta = meta.parse(metaTable.data, metaTable.offset);
44616              font.metas = font.tables.meta;
44617            }
44618
44619            return font;
44620          }
44621          /**
44622           * Asynchronously load the font from a URL or a filesystem. When done, call the callback
44623           * with two arguments `(err, font)`. The `err` will be null on success,
44624           * the `font` is a Font object.
44625           * We use the node.js callback convention so that
44626           * opentype.js can integrate with frameworks like async.js.
44627           * @alias opentype.load
44628           * @param  {string} url - The URL of the font to load.
44629           * @param  {Function} callback - The callback.
44630           */
44631
44632
44633          function load(url, callback) {
44634            var isNode$$1 = typeof window === 'undefined';
44635            var loadFn = isNode$$1 ? loadFromFile : loadFromUrl;
44636            loadFn(url, function (err, arrayBuffer) {
44637              if (err) {
44638                return callback(err);
44639              }
44640
44641              var font;
44642
44643              try {
44644                font = parseBuffer(arrayBuffer);
44645              } catch (e) {
44646                return callback(e, null);
44647              }
44648
44649              return callback(null, font);
44650            });
44651          }
44652          /**
44653           * Synchronously load the font from a URL or file.
44654           * When done, returns the font object or throws an error.
44655           * @alias opentype.loadSync
44656           * @param  {string} url - The URL of the font to load.
44657           * @return {opentype.Font}
44658           */
44659
44660
44661          function loadSync(url) {
44662            var fs = _dereq_('fs');
44663
44664            var buffer = fs.readFileSync(url);
44665            return parseBuffer(nodeBufferToArrayBuffer(buffer));
44666          }
44667
44668          exports.Font = Font;
44669          exports.Glyph = Glyph;
44670          exports.Path = Path;
44671          exports.BoundingBox = BoundingBox;
44672          exports._parse = parse;
44673          exports.parse = parseBuffer;
44674          exports.load = load;
44675          exports.loadSync = loadSync;
44676          Object.defineProperty(exports, '__esModule', {
44677            value: true
44678          });
44679        });
44680      }).call(this, _dereq_("buffer").Buffer);
44681    }, {
44682      "buffer": 4,
44683      "fs": 3
44684    }],
44685    11: [function (_dereq_, module, exports) {
44686      // shim for using process in browser
44687      var process = module.exports = {}; // cached from whatever global is present so that test runners that stub it
44688      // don't break things.  But we need to wrap it in a try catch in case it is
vendor: 4,237 bytes, lines 44689-44825
44689      // wrapped in strict mode code which doesn't define any globals.  It's inside a
44690      // function because try/catches deoptimize in certain engines.
44691
44692      var cachedSetTimeout;
44693      var cachedClearTimeout;
44694
44695      function defaultSetTimout() {
44696        throw new Error('setTimeout has not been defined');
44697      }
44698
44699      function defaultClearTimeout() {
44700        throw new Error('clearTimeout has not been defined');
44701      }
44702
44703      (function () {
44704        try {
44705          if (typeof setTimeout === 'function') {
44706            cachedSetTimeout = setTimeout;
44707          } else {
44708            cachedSetTimeout = defaultSetTimout;
44709          }
44710        } catch (e) {
44711          cachedSetTimeout = defaultSetTimout;
44712        }
44713
44714        try {
44715          if (typeof clearTimeout === 'function') {
44716            cachedClearTimeout = clearTimeout;
44717          } else {
44718            cachedClearTimeout = defaultClearTimeout;
44719          }
44720        } catch (e) {
44721          cachedClearTimeout = defaultClearTimeout;
44722        }
44723      })();
44724
44725      function runTimeout(fun) {
44726        if (cachedSetTimeout === setTimeout) {
44727          //normal enviroments in sane situations
44728          return setTimeout(fun, 0);
44729        } // if setTimeout wasn't available but was latter defined
44730
44731
44732        if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
44733          cachedSetTimeout = setTimeout;
44734          return setTimeout(fun, 0);
44735        }
44736
44737        try {
44738          // when when somebody has screwed with setTimeout but no I.E. maddness
44739          return cachedSetTimeout(fun, 0);
44740        } catch (e) {
44741          try {
44742            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
44743            return cachedSetTimeout.call(null, fun, 0);
44744          } catch (e) {
44745            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
44746            return cachedSetTimeout.call(this, fun, 0);
44747          }
44748        }
44749      }
44750
44751      function runClearTimeout(marker) {
44752        if (cachedClearTimeout === clearTimeout) {
44753          //normal enviroments in sane situations
44754          return clearTimeout(marker);
44755        } // if clearTimeout wasn't available but was latter defined
44756
44757
44758        if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
44759          cachedClearTimeout = clearTimeout;
44760          return clearTimeout(marker);
44761        }
44762
44763        try {
44764          // when when somebody has screwed with setTimeout but no I.E. maddness
44765          return cachedClearTimeout(marker);
44766        } catch (e) {
44767          try {
44768            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
44769            return cachedClearTimeout.call(null, marker);
44770          } catch (e) {
44771            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
44772            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
44773            return cachedClearTimeout.call(this, marker);
44774          }
44775        }
44776      }
44777
44778      var queue = [];
44779      var draining = false;
44780      var currentQueue;
44781      var queueIndex = -1;
44782
44783      function cleanUpNextTick() {
44784        if (!draining || !currentQueue) {
44785          return;
44786        }
44787
44788        draining = false;
44789
44790        if (currentQueue.length) {
44791          queue = currentQueue.concat(queue);
44792        } else {
44793          queueIndex = -1;
44794        }
44795
44796        if (queue.length) {
44797          drainQueue();
44798        }
44799      }
44800
44801      function drainQueue() {
44802        if (draining) {
44803          return;
44804        }
44805
44806        var timeout = runTimeout(cleanUpNextTick);
44807        draining = true;
44808        var len = queue.length;
44809
44810        while (len) {
44811          currentQueue = queue;
44812          queue = [];
44813
44814          while (++queueIndex < len) {
44815            if (currentQueue) {
44816              currentQueue[queueIndex].run();
44817            }
44818          }
44819
44820          queueIndex = -1;
44821          len = queue.length;
44822        }
44823
44824        currentQueue = null;
44825        draining = false;
44826        runClearTimeout(timeout);
44827      }
44828
44829      process.nextTick = function (fun) {
44830        var args = new Array(arguments.length - 1);
44831
44832        if (arguments.length > 1) {
44833          for (var i = 1; i < arguments.length; i++) {
44834            args[i - 1] = arguments[i];
44835          }
44836        }
44837
44838        queue.push(new Item(fun, args));
44839
44840        if (queue.length === 1 && !draining) {
44841          runTimeout(drainQueue);
44842        }
44843      }; // v8 likes predictible objects
44844
44845
44846      function Item(fun, array) {
44847        this.fun = fun;
44848        this.array = array;
44849      }
44850
44851      Item.prototype.run = function () {
44852        this.fun.apply(null, this.array);
44853      };
44854
44855      process.title = 'browser';
44856      process.env = {};
44857      process.argv = [];
44858      process.version = ''; // empty string to avoid regexp issues
44859
44860      process.versions = {};
44861
44862      function noop() {}
44863
44864      process.on = noop;
44865      process.addListener = noop;
44866      process.once = noop;
44867      process.off = noop;
44868      process.removeListener = noop;
44869      process.removeAllListeners = noop;
44870      process.emit = noop;
44871      process.prependListener = noop;
44872      process.prependOnceListener = noop;
44873
44874      process.listeners = function (name) {
44875        return [];
44876      };
44877
44878      process.binding = function (name) {
44879        throw new Error('process.binding is not supported');
44880      };
44881
44882      process.cwd = function () {
44883        return '/';
44884      };
44885
44886      process.chdir = function (dir) {
44887        throw new Error('process.chdir is not supported');
44888      };
44889
44890      process.umask = function () {
44891        return 0;
44892      };
44893    }, {}],
44894    12: [function (_dereq_, module, exports) {
44895      (function (self) {
44896        'use strict';
44897
44898        if (self.fetch) {
44899          return;
44900        }
44901
44902        var support = {
44903          searchParams: 'URLSearchParams' in self,
44904          iterable: 'Symbol' in self && 'iterator' in Symbol,
44905          blob: 'FileReader' in self && 'Blob' in self && function () {
44906            try {
44907              new Blob();
44908              return true;
44909            } catch (e) {
44910              return false;
44911            }
44912          }(),
44913          formData: 'FormData' in self,
44914          arrayBuffer: 'ArrayBuffer' in self
44915        };
44916
44917        if (support.arrayBuffer) {
44918          var viewClasses = ['[object Int8Array]', '[object Uint8Array]', '[object Uint8ClampedArray]', '[object Int16Array]', '[object Uint16Array]', '[object Int32Array]', '[object Uint32Array]', '[object Float32Array]', '[object Float64Array]'];
44919
44920          var isDataView = function (obj) {
44921            return obj && DataView.prototype.isPrototypeOf(obj);
44922          };
44923
44924          var isArrayBufferView = ArrayBuffer.isView || function (obj) {
44925            return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1;
44926          };
44927        }
44928
44929        function normalizeName(name) {
44930          if (typeof name !== 'string') {
44931            name = String(name);
44932          }
44933
44934          if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
44935            throw new TypeError('Invalid character in header field name');
44936          }
44937
44938          return name.toLowerCase();
44939        }
44940
44941        function normalizeValue(value) {
44942          if (typeof value !== 'string') {
44943            value = String(value);
44944          }
44945
44946          return value;
44947        } // Build a destructive iterator for the value list
44948
44949
44950        function iteratorFor(items) {
44951          var iterator = {
44952            next: function () {
44953              var value = items.shift();
44954              return {
44955                done: value === undefined,
44956                value: value
44957              };
44958            }
44959          };
44960
44961          if (support.iterable) {
44962            iterator[Symbol.iterator] = function () {
44963              return iterator;
44964            };
44965          }
44966
44967          return iterator;
44968        }
44969
44970        function Headers(headers) {
44971          this.map = {};
44972
44973          if (headers instanceof Headers) {
44974            headers.forEach(function (value, name) {
44975              this.append(name, value);
44976            }, this);
44977          } else if (Array.isArray(headers)) {
44978            headers.forEach(function (header) {
44979              this.append(header[0], header[1]);
44980            }, this);
44981          } else if (headers) {
vendor: 7,195 bytes, lines 44982-45201
44982            Object.getOwnPropertyNames(headers).forEach(function (name) {
44983              this.append(name, headers[name]);
44984            }, this);
44985          }
44986        }
44987
44988        Headers.prototype.append = function (name, value) {
44989          name = normalizeName(name);
44990          value = normalizeValue(value);
44991          var oldValue = this.map[name];
44992          this.map[name] = oldValue ? oldValue + ',' + value : value;
44993        };
44994
44995        Headers.prototype['delete'] = function (name) {
44996          delete this.map[normalizeName(name)];
44997        };
44998
44999        Headers.prototype.get = function (name) {
45000          name = normalizeName(name);
45001          return this.has(name) ? this.map[name] : null;
45002        };
45003
45004        Headers.prototype.has = function (name) {
45005          return this.map.hasOwnProperty(normalizeName(name));
45006        };
45007
45008        Headers.prototype.set = function (name, value) {
45009          this.map[normalizeName(name)] = normalizeValue(value);
45010        };
45011
45012        Headers.prototype.forEach = function (callback, thisArg) {
45013          for (var name in this.map) {
45014            if (this.map.hasOwnProperty(name)) {
45015              callback.call(thisArg, this.map[name], name, this);
45016            }
45017          }
45018        };
45019
45020        Headers.prototype.keys = function () {
45021          var items = [];
45022          this.forEach(function (value, name) {
45023            items.push(name);
45024          });
45025          return iteratorFor(items);
45026        };
45027
45028        Headers.prototype.values = function () {
45029          var items = [];
45030          this.forEach(function (value) {
45031            items.push(value);
45032          });
45033          return iteratorFor(items);
45034        };
45035
45036        Headers.prototype.entries = function () {
45037          var items = [];
45038          this.forEach(function (value, name) {
45039            items.push([name, value]);
45040          });
45041          return iteratorFor(items);
45042        };
45043
45044        if (support.iterable) {
45045          Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
45046        }
45047
45048        function consumed(body) {
45049          if (body.bodyUsed) {
45050            return Promise.reject(new TypeError('Already read'));
45051          }
45052
45053          body.bodyUsed = true;
45054        }
45055
45056        function fileReaderReady(reader) {
45057          return new Promise(function (resolve, reject) {
45058            reader.onload = function () {
45059              resolve(reader.result);
45060            };
45061
45062            reader.onerror = function () {
45063              reject(reader.error);
45064            };
45065          });
45066        }
45067
45068        function readBlobAsArrayBuffer(blob) {
45069          var reader = new FileReader();
45070          var promise = fileReaderReady(reader);
45071          reader.readAsArrayBuffer(blob);
45072          return promise;
45073        }
45074
45075        function readBlobAsText(blob) {
45076          var reader = new FileReader();
45077          var promise = fileReaderReady(reader);
45078          reader.readAsText(blob);
45079          return promise;
45080        }
45081
45082        function readArrayBufferAsText(buf) {
45083          var view = new Uint8Array(buf);
45084          var chars = new Array(view.length);
45085
45086          for (var i = 0; i < view.length; i++) {
45087            chars[i] = String.fromCharCode(view[i]);
45088          }
45089
45090          return chars.join('');
45091        }
45092
45093        function bufferClone(buf) {
45094          if (buf.slice) {
45095            return buf.slice(0);
45096          } else {
45097            var view = new Uint8Array(buf.byteLength);
45098            view.set(new Uint8Array(buf));
45099            return view.buffer;
45100          }
45101        }
45102
45103        function Body() {
45104          this.bodyUsed = false;
45105
45106          this._initBody = function (body) {
45107            this._bodyInit = body;
45108
45109            if (!body) {
45110              this._bodyText = '';
45111            } else if (typeof body === 'string') {
45112              this._bodyText = body;
45113            } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
45114              this._bodyBlob = body;
45115            } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
45116              this._bodyFormData = body;
45117            } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
45118              this._bodyText = body.toString();
45119            } else if (support.arrayBuffer && support.blob && isDataView(body)) {
45120              this._bodyArrayBuffer = bufferClone(body.buffer); // IE 10-11 can't handle a DataView body.
45121
45122              this._bodyInit = new Blob([this._bodyArrayBuffer]);
45123            } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
45124              this._bodyArrayBuffer = bufferClone(body);
45125            } else {
45126              throw new Error('unsupported BodyInit type');
45127            }
45128
45129            if (!this.headers.get('content-type')) {
45130              if (typeof body === 'string') {
45131                this.headers.set('content-type', 'text/plain;charset=UTF-8');
45132              } else if (this._bodyBlob && this._bodyBlob.type) {
45133                this.headers.set('content-type', this._bodyBlob.type);
45134              } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
45135                this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
45136              }
45137            }
45138          };
45139
45140          if (support.blob) {
45141            this.blob = function () {
45142              var rejected = consumed(this);
45143
45144              if (rejected) {
45145                return rejected;
45146              }
45147
45148              if (this._bodyBlob) {
45149                return Promise.resolve(this._bodyBlob);
45150              } else if (this._bodyArrayBuffer) {
45151                return Promise.resolve(new Blob([this._bodyArrayBuffer]));
45152              } else if (this._bodyFormData) {
45153                throw new Error('could not read FormData body as blob');
45154              } else {
45155                return Promise.resolve(new Blob([this._bodyText]));
45156              }
45157            };
45158
45159            this.arrayBuffer = function () {
45160              if (this._bodyArrayBuffer) {
45161                return consumed(this) || Promise.resolve(this._bodyArrayBuffer);
45162              } else {
45163                return this.blob().then(readBlobAsArrayBuffer);
45164              }
45165            };
45166          }
45167
45168          this.text = function () {
45169            var rejected = consumed(this);
45170
45171            if (rejected) {
45172              return rejected;
45173            }
45174
45175            if (this._bodyBlob) {
45176              return readBlobAsText(this._bodyBlob);
45177            } else if (this._bodyArrayBuffer) {
45178              return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer));
45179            } else if (this._bodyFormData) {
45180              throw new Error('could not read FormData body as text');
45181            } else {
45182              return Promise.resolve(this._bodyText);
45183            }
45184          };
45185
45186          if (support.formData) {
45187            this.formData = function () {
45188              return this.text().then(decode);
45189            };
45190          }
45191
45192          this.json = function () {
45193            return this.text().then(JSON.parse);
45194          };
45195
45196          return this;
45197        } // HTTP methods whose capitalization should be normalized
45198
45199
45200        var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'];
45201
45202        function normalizeMethod(method) {
45203          var upcased = method.toUpperCase();
45204          return methods.indexOf(upcased) > -1 ? upcased : method;
45205        }
45206
45207        function Request(input, options) {
45208          options = options || {};
45209          var body = options.body;
45210
45211          if (input instanceof Request) {
45212            if (input.bodyUsed) {
45213              throw new TypeError('Already read');
45214            }
45215
45216            this.url = input.url;
45217            this.credentials = input.credentials;
45218
45219            if (!options.headers) {
45220              this.headers = new Headers(input.headers);
45221            }
45222
45223            this.method = input.method;
45224            this.mode = input.mode;
45225
45226            if (!body && input._bodyInit != null) {
45227              body = input._bodyInit;
45228              input.bodyUsed = true;
45229            }
45230          } else {
45231            this.url = String(input);
45232          }
45233
45234          this.credentials = options.credentials || this.credentials || 'omit';
45235
45236          if (options.headers || !this.headers) {
45237            this.headers = new Headers(options.headers);
45238          }
45239
45240          this.method = normalizeMethod(options.method || this.method || 'GET');
45241          this.mode = options.mode || this.mode || null;
45242          this.referrer = null;
45243
45244          if ((this.method === 'GET' || this.method === 'HEAD') && body) {
45245            throw new TypeError('Body not allowed for GET or HEAD requests');
45246          }
45247
45248          this._initBody(body);
45249        }
45250
45251        Request.prototype.clone = function () {
45252          return new Request(this, {
45253            body: this._bodyInit
45254          });
45255        };
45256
45257        function decode(body) {
45258          var form = new FormData();
45259          body.trim().split('&').forEach(function (bytes) {
45260            if (bytes) {
45261              var split = bytes.split('=');
45262              var name = split.shift().replace(/\+/g, ' ');
45263              var value = split.join('=').replace(/\+/g, ' ');
45264              form.append(decodeURIComponent(name), decodeURIComponent(value));
45265            }
45266          });
45267          return form;
45268        }
45269
45270        function parseHeaders(rawHeaders) {
45271          var headers = new Headers();
45272          rawHeaders.split(/\r?\n/).forEach(function (line) {
45273            var parts = line.split(':');
45274            var key = parts.shift().trim();
45275
45276            if (key) {
45277              var value = parts.join(':').trim();
45278              headers.append(key, value);
45279            }
45280          });
45281          return headers;
45282        }
45283
45284        Body.call(Request.prototype);
45285
45286        function Response(bodyInit, options) {
45287          if (!options) {
45288            options = {};
45289          }
45290
45291          this.type = 'default';
45292          this.status = 'status' in options ? options.status : 200;
45293          this.ok = this.status >= 200 && this.status < 300;
45294          this.statusText = 'statusText' in options ? options.statusText : 'OK';
45295          this.headers = new Headers(options.headers);
45296          this.url = options.url || '';
45297
45298          this._initBody(bodyInit);
45299        }
45300
45301        Body.call(Response.prototype);
45302
45303        Response.prototype.clone = function () {
45304          return new Response(this._bodyInit, {
45305            status: this.status,
45306            statusText: this.statusText,
45307            headers: new Headers(this.headers),
45308            url: this.url
45309          });
45310        };
45311
45312        Response.error = function () {
45313          var response = new Response(null, {
45314            status: 0,
45315            statusText: ''
45316          });
45317          response.type = 'error';
45318          return response;
45319        };
45320
45321        var redirectStatuses = [301, 302, 303, 307, 308];
45322
45323        Response.redirect = function (url, status) {
45324          if (redirectStatuses.indexOf(status) === -1) {
45325            throw new RangeError('Invalid status code');
45326          }
45327
45328          return new Response(null, {
45329            status: status,
45330            headers: {
45331              location: url
45332            }
45333          });
45334        };
45335
45336        self.Headers = Headers;
45337        self.Request = Request;
45338        self.Response = Response;
45339
45340        self.fetch = function (input, init) {
45341          return new Promise(function (resolve, reject) {
45342            var request = new Request(input, init);
45343            var xhr = new XMLHttpRequest();
45344
45345            xhr.onload = function () {
45346              var options = {
45347                status: xhr.status,
45348                statusText: xhr.statusText,
45349                headers: parseHeaders(xhr.getAllResponseHeaders() || '')
45350              };
45351              options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL');
45352              var body = 'response' in xhr ? xhr.response : xhr.responseText;
45353              resolve(new Response(body, options));
45354            };
45355
45356            xhr.onerror = function () {
45357              reject(new TypeError('Network request failed'));
45358            };
45359
45360            xhr.ontimeout = function () {
45361              reject(new TypeError('Network request failed'));
45362            };
45363
45364            xhr.open(request.method, request.url, true);
45365
45366            if (request.credentials === 'include') {
45367              xhr.withCredentials = true;
45368            }
45369
45370            if ('responseType' in xhr && support.blob) {
45371              xhr.responseType = 'blob';
45372            }
45373
45374            request.headers.forEach(function (value, name) {
45375              xhr.setRequestHeader(name, value);
45376            });
45377            xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit);
45378          });
45379        };
45380
45381        self.fetch.polyfill = true;
45382      })(typeof self !== 'undefined' ? self : this);
45383    }, {}],
45384    13: [function (_dereq_, module, exports) {
45385      'use strict'; // core
45386
45387      var p5 = _dereq_('./core/main');
45388
45389      _dereq_('./core/constants');
45390
45391      _dereq_('./core/environment');
45392
45393      _dereq_('./core/error_helpers');
45394
45395      _dereq_('./core/helpers');
45396
45397      _dereq_('./core/legacy');
45398
45399      _dereq_('./core/p5.Element');
45400
45401      _dereq_('./core/p5.Graphics');
45402
45403      _dereq_('./core/p5.Renderer');
45404
45405      _dereq_('./core/p5.Renderer2D');
45406
45407      _dereq_('./core/rendering');
45408
45409      _dereq_('./core/shim');
45410
45411      _dereq_('./core/structure');
45412
45413      _dereq_('./core/transform');
45414
45415      _dereq_('./core/shape/2d_primitives');
45416
45417      _dereq_('./core/shape/attributes');
45418
45419      _dereq_('./core/shape/curves');
45420
45421      _dereq_('./core/shape/vertex'); // color
45422
45423
45424      _dereq_('./color/color_conversion');
45425
45426      _dereq_('./color/creating_reading');
45427
45428      _dereq_('./color/p5.Color');
45429
45430      _dereq_('./color/setting'); // data
45431
45432
45433      _dereq_('./data/p5.TypedDict'); // events
45434
45435
45436      _dereq_('./events/acceleration');
45437
45438      _dereq_('./events/keyboard');
45439
45440      _dereq_('./events/mouse');
45441
45442      _dereq_('./events/touch'); // image
45443
45444
45445      _dereq_('./image/filters');
45446
45447      _dereq_('./image/image');
45448
45449      _dereq_('./image/loading_displaying');
45450
45451      _dereq_('./image/p5.Image');
45452
45453      _dereq_('./image/pixels'); // io
45454
45455
45456      _dereq_('./io/files');
45457
45458      _dereq_('./io/p5.Table');
45459
45460      _dereq_('./io/p5.TableRow');
45461
45462      _dereq_('./io/p5.XML'); // math
45463
45464
45465      _dereq_('./math/calculation');
45466
45467      _dereq_('./math/math');
45468
45469      _dereq_('./math/noise');
45470
45471      _dereq_('./math/p5.Vector');
45472
45473      _dereq_('./math/random');
45474
45475      _dereq_('./math/trigonometry'); // typography
45476
45477
45478      _dereq_('./typography/attributes');
45479
45480      _dereq_('./typography/loading_displaying');
45481
45482      _dereq_('./typography/p5.Font'); // utilities
45483
45484
45485      _dereq_('./utilities/array_functions');
45486
45487      _dereq_('./utilities/conversion');
45488
45489      _dereq_('./utilities/string_functions');
45490
45491      _dereq_('./utilities/time_date'); // webgl
45492
45493
45494      _dereq_('./webgl/3d_primitives');
45495
45496      _dereq_('./webgl/interaction');
45497
45498      _dereq_('./webgl/light');
45499
45500      _dereq_('./webgl/loading');
45501
45502      _dereq_('./webgl/material');
45503
45504      _dereq_('./webgl/p5.Camera');
45505
45506      _dereq_('./webgl/p5.Geometry');
45507
45508      _dereq_('./webgl/p5.Matrix');
45509
45510      _dereq_('./webgl/p5.RendererGL.Immediate');
45511
45512      _dereq_('./webgl/p5.RendererGL');
45513
45514      _dereq_('./webgl/p5.RendererGL.Retained');
45515
45516      _dereq_('./webgl/p5.Shader');
45517
45518      _dereq_('./webgl/p5.Texture');
45519
45520      _dereq_('./webgl/text');
45521
45522      _dereq_('./core/init');
45523
45524      module.exports = p5;
45525    }, {
45526      "./color/color_conversion": 14,
45527      "./color/creating_reading": 15,
45528      "./color/p5.Color": 16,
45529      "./color/setting": 17,
45530      "./core/constants": 18,
45531      "./core/environment": 19,
45532      "./core/error_helpers": 20,
45533      "./core/helpers": 21,
45534      "./core/init": 22,
45535      "./core/legacy": 23,
45536      "./core/main": 24,
45537      "./core/p5.Element": 25,
45538      "./core/p5.Graphics": 26,
45539      "./core/p5.Renderer": 27,
45540      "./core/p5.Renderer2D": 28,
45541      "./core/rendering": 29,
45542      "./core/shape/2d_primitives": 30,
45543      "./core/shape/attributes": 31,
45544      "./core/shape/curves": 32,
45545      "./core/shape/vertex": 33,
45546      "./core/shim": 34,
45547      "./core/structure": 35,
45548      "./core/transform": 36,
45549      "./data/p5.TypedDict": 37,
45550      "./events/acceleration": 38,
45551      "./events/keyboard": 39,
45552      "./events/mouse": 40,
45553      "./events/touch": 41,
45554      "./image/filters": 42,
45555      "./image/image": 43,
45556      "./image/loading_displaying": 44,
45557      "./image/p5.Image": 45,
45558      "./image/pixels": 46,
45559      "./io/files": 47,
45560      "./io/p5.Table": 48,
45561      "./io/p5.TableRow": 49,
45562      "./io/p5.XML": 50,
45563      "./math/calculation": 51,
45564      "./math/math": 52,
45565      "./math/noise": 53,
45566      "./math/p5.Vector": 54,
45567      "./math/random": 55,
45568      "./math/trigonometry": 56,
45569      "./typography/attributes": 57,
45570      "./typography/loading_displaying": 58,
45571      "./typography/p5.Font": 59,
45572      "./utilities/array_functions": 60,
45573      "./utilities/conversion": 61,
45574      "./utilities/string_functions": 62,
45575      "./utilities/time_date": 63,
45576      "./webgl/3d_primitives": 64,
45577      "./webgl/interaction": 65,
45578      "./webgl/light": 66,
45579      "./webgl/loading": 67,
45580      "./webgl/material": 68,
45581      "./webgl/p5.Camera": 69,
45582      "./webgl/p5.Geometry": 70,
45583      "./webgl/p5.Matrix": 71,
45584      "./webgl/p5.RendererGL": 74,
45585      "./webgl/p5.RendererGL.Immediate": 72,
45586      "./webgl/p5.RendererGL.Retained": 73,
45587      "./webgl/p5.Shader": 75,
45588      "./webgl/p5.Texture": 76,
45589      "./webgl/text": 77
45590    }],
45591    14: [function (_dereq_, module, exports) {
45592      /**
45593       * @module Color
45594       * @submodule Color Conversion
45595       * @for p5
45596       * @requires core
45597       */
45598      'use strict';
45599      /**
45600       * Conversions adapted from <http://www.easyrgb.com/en/math.php>.
45601       *
45602       * In these functions, hue is always in the range [0, 1], just like all other
45603       * components are in the range [0, 1]. 'Brightness' and 'value' are used
45604       * interchangeably.
45605       */
45606
45607      var p5 = _dereq_('../core/main');
45608
45609      p5.ColorConversion = {};
45610      /**
45611       * Convert an HSBA array to HSLA.
45612       */
45613
45614      p5.ColorConversion._hsbaToHSLA = function (hsba) {
45615        var hue = hsba[0];
45616        var sat = hsba[1];
45617        var val = hsba[2]; // Calculate lightness.
45618
45619        var li = (2 - sat) * val / 2; // Convert saturation.
45620
45621        if (li !== 0) {
45622          if (li === 1) {
45623            sat = 0;
45624          } else if (li < 0.5) {
45625            sat = sat / (2 - sat);
45626          } else {
45627            sat = sat * val / (2 - li * 2);
45628          }
45629        } // Hue and alpha stay the same.
45630
45631
45632        return [hue, sat, li, hsba[3]];
45633      };
45634      /**
45635       * Convert an HSBA array to RGBA.
45636       */
45637
45638
45639      p5.ColorConversion._hsbaToRGBA = function (hsba) {
45640        var hue = hsba[0] * 6; // We will split hue into 6 sectors.
45641
45642        var sat = hsba[1];
45643        var val = hsba[2];
45644        var RGBA = [];
45645
45646        if (sat === 0) {
45647          RGBA = [val, val, val, hsba[3]]; // Return early if grayscale.
45648        } else {
45649          var sector = Math.floor(hue);
45650          var tint1 = val * (1 - sat);
45651          var tint2 = val * (1 - sat * (hue - sector));
45652          var tint3 = val * (1 - sat * (1 + sector - hue));
45653          var red, green, blue;
45654
45655          if (sector === 1) {
45656            // Yellow to green.
45657            red = tint2;
45658            green = val;
45659            blue = tint1;
45660          } else if (sector === 2) {
45661            // Green to cyan.
45662            red = tint1;
45663            green = val;
45664            blue = tint3;
45665          } else if (sector === 3) {
45666            // Cyan to blue.
45667            red = tint1;
45668            green = tint2;
45669            blue = val;
45670          } else if (sector === 4) {
45671            // Blue to magenta.
45672            red = tint3;
45673            green = tint1;
45674            blue = val;
45675          } else if (sector === 5) {
45676            // Magenta to red.
45677            red = val;
45678            green = tint1;
45679            blue = tint2;
45680          } else {
45681            // Red to yellow (sector could be 0 or 6).
45682            red = val;
45683            green = tint3;
45684            blue = tint1;
45685          }
45686
45687          RGBA = [red, green, blue, hsba[3]];
45688        }
45689
45690        return RGBA;
45691      };
45692      /**
45693       * Convert an HSLA array to HSBA.
45694       */
45695
45696
45697      p5.ColorConversion._hslaToHSBA = function (hsla) {
45698        var hue = hsla[0];
45699        var sat = hsla[1];
45700        var li = hsla[2]; // Calculate brightness.
45701
45702        var val;
45703
45704        if (li < 0.5) {
45705          val = (1 + sat) * li;
45706        } else {
45707          val = li + sat - li * sat;
45708        } // Convert saturation.
45709
45710
45711        sat = 2 * (val - li) / val; // Hue and alpha stay the same.
45712
45713        return [hue, sat, val, hsla[3]];
45714      };
45715      /**
45716       * Convert an HSLA array to RGBA.
45717       *
45718       * We need to change basis from HSLA to something that can be more easily be
45719       * projected onto RGBA. We will choose hue and brightness as our first two
45720       * components, and pick a convenient third one ('zest') so that we don't need
45721       * to calculate formal HSBA saturation.
45722       */
45723
45724
45725      p5.ColorConversion._hslaToRGBA = function (hsla) {
45726        var hue = hsla[0] * 6; // We will split hue into 6 sectors.
45727
45728        var sat = hsla[1];
45729        var li = hsla[2];
45730        var RGBA = [];
45731
45732        if (sat === 0) {
45733          RGBA = [li, li, li, hsla[3]]; // Return early if grayscale.
45734        } else {
45735          // Calculate brightness.
45736          var val;
45737
45738          if (li < 0.5) {
45739            val = (1 + sat) * li;
45740          } else {
45741            val = li + sat - li * sat;
45742          } // Define zest.
45743
45744
45745          var zest = 2 * li - val; // Implement projection (project onto green by default).
45746
45747          var hzvToRGB = function (hue, zest, val) {
45748            if (hue < 0) {
45749              // Hue must wrap to allow projection onto red and blue.
45750              hue += 6;
45751            } else if (hue >= 6) {
45752              hue -= 6;
45753            }
45754
45755            if (hue < 1) {
45756              // Red to yellow (increasing green).
45757              return zest + (val - zest) * hue;
45758            } else if (hue < 3) {
45759              // Yellow to cyan (greatest green).
45760              return val;
45761            } else if (hue < 4) {
45762              // Cyan to blue (decreasing green).
45763              return zest + (val - zest) * (4 - hue);
45764            } else {
45765              // Blue to red (least green).
45766              return zest;
45767            }
45768          }; // Perform projections, offsetting hue as necessary.
45769
45770
45771          RGBA = [hzvToRGB(hue + 2, zest, val), hzvToRGB(hue, zest, val), hzvToRGB(hue - 2, zest, val), hsla[3]];
45772        }
45773
45774        return RGBA;
45775      };
45776      /**
45777       * Convert an RGBA array to HSBA.
45778       */
45779
45780
45781      p5.ColorConversion._rgbaToHSBA = function (rgba) {
45782        var red = rgba[0];
45783        var green = rgba[1];
45784        var blue = rgba[2];
45785        var val = Math.max(red, green, blue);
45786        var chroma = val - Math.min(red, green, blue);
45787        var hue, sat;
45788
45789        if (chroma === 0) {
45790          // Return early if grayscale.
45791          hue = 0;
45792          sat = 0;
45793        } else {
45794          sat = chroma / val;
45795
45796          if (red === val) {
45797            // Magenta to yellow.
45798            hue = (green - blue) / chroma;
45799          } else if (green === val) {
45800            // Yellow to cyan.
45801            hue = 2 + (blue - red) / chroma;
45802          } else if (blue === val) {
45803            // Cyan to magenta.
45804            hue = 4 + (red - green) / chroma;
45805          }
45806
45807          if (hue < 0) {
45808            // Confine hue to the interval [0, 1).
45809            hue += 6;
45810          } else if (hue >= 6) {
45811            hue -= 6;
45812          }
45813        }
45814
45815        return [hue / 6, sat, val, rgba[3]];
45816      };
45817      /**
45818       * Convert an RGBA array to HSLA.
45819       */
45820
45821
45822      p5.ColorConversion._rgbaToHSLA = function (rgba) {
45823        var red = rgba[0];
45824        var green = rgba[1];
45825        var blue = rgba[2];
45826        var val = Math.max(red, green, blue);
45827        var min = Math.min(red, green, blue);
45828        var li = val + min; // We will halve this later.
45829
45830        var chroma = val - min;
45831        var hue, sat;
45832
45833        if (chroma === 0) {
45834          // Return early if grayscale.
45835          hue = 0;
45836          sat = 0;
45837        } else {
45838          if (li < 1) {
45839            sat = chroma / li;
45840          } else {
45841            sat = chroma / (2 - li);
45842          }
45843
45844          if (red === val) {
45845            // Magenta to yellow.
45846            hue = (green - blue) / chroma;
45847          } else if (green === val) {
45848            // Yellow to cyan.
45849            hue = 2 + (blue - red) / chroma;
45850          } else if (blue === val) {
45851            // Cyan to magenta.
45852            hue = 4 + (red - green) / chroma;
45853          }
45854
45855          if (hue < 0) {
45856            // Confine hue to the interval [0, 1).
45857            hue += 6;
45858          } else if (hue >= 6) {
45859            hue -= 6;
45860          }
45861        }
45862
45863        return [hue / 6, sat, li / 2, rgba[3]];
45864      };
45865
45866      module.exports = p5.ColorConversion;
45867    }, {
45868      "../core/main": 24
45869    }],
45870    15: [function (_dereq_, module, exports) {
45871      /**
45872       * @module Color
45873       * @submodule Creating & Reading
45874       * @for p5
45875       * @requires core
45876       * @requires constants
45877       */
45878      'use strict';
45879
45880      var p5 = _dereq_('../core/main');
45881
45882      var constants = _dereq_('../core/constants');
45883
45884      _dereq_('./p5.Color');
45885
45886      _dereq_('../core/error_helpers');
45887      /**
45888       * Extracts the alpha value from a color or pixel array.
45889       *
45890       * @method alpha
45891       * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
45892       *                                         or CSS color
45893       * @return {Number} the alpha value
45894       * @example
45895       * <div>
45896       * <code>
45897       * noStroke();
45898       * let c = color(0, 126, 255, 102);
45899       * fill(c);
45900       * rect(15, 15, 35, 70);
45901       * let value = alpha(c); // Sets 'value' to 102
45902       * fill(value);
45903       * rect(50, 15, 35, 70);
45904       * </code>
45905       * </div>
45906       *
45907       * @alt
45908       * Left half of canvas light blue and right half light charcoal grey.
45909       * Left half of canvas light purple and right half a royal blue.
45910       * Left half of canvas salmon pink and the right half white.
45911       * Yellow rect in middle right of canvas, with 55 pixel width and height.
45912       * Yellow ellipse in top left canvas, black ellipse in bottom right,both 80x80.
45913       * Bright fuschia rect in middle of canvas, 60 pixel width and height.
45914       * Two bright green rects on opposite sides of the canvas, both 45x80.
45915       * Four blue rects in each corner of the canvas, each are 35x35.
45916       * Bright sea green rect on left and darker rect on right of canvas, both 45x80.
45917       * Dark green rect on left and light green rect on right of canvas, both 45x80.
45918       * Dark blue rect on left and light teal rect on right of canvas, both 45x80.
45919       * blue rect on left and green on right, both with black outlines & 35x60.
45920       * salmon pink rect on left and black on right, both 35x60.
45921       * 4 rects, tan, brown, brownish purple and purple, with white outlines & 20x60.
45922       * light pastel green rect on left and dark grey rect on right, both 35x60.
45923       * yellow rect on left and red rect on right, both with black outlines & 35x60.
45924       * grey canvas
45925       * deep pink rect on left and grey rect on right, both 35x60.
45926       */
45927
45928
45929      p5.prototype.alpha = function (c) {
45930        p5._validateParameters('alpha', arguments);
45931
45932        return this.color(c)._getAlpha();
45933      };
45934      /**
45935       * Extracts the blue value from a color or pixel array.
45936       *
45937       * @method blue
45938       * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
45939       *                                         or CSS color
45940       * @return {Number} the blue value
45941       * @example
45942       * <div>
45943       * <code>
45944       * let c = color(175, 100, 220); // Define color 'c'
45945       * fill(c); // Use color variable 'c' as fill color
45946       * rect(15, 20, 35, 60); // Draw left rectangle
45947       *
45948       * let blueValue = blue(c); // Get blue in 'c'
45949       * print(blueValue); // Prints "220.0"
45950       * fill(0, 0, blueValue); // Use 'blueValue' in new fill
45951       * rect(50, 20, 35, 60); // Draw right rectangle
45952       * </code>
45953       * </div>
45954       *
45955       * @alt
45956       * Left half of canvas light purple and right half a royal blue.
45957       *
45958       */
45959
45960
45961      p5.prototype.blue = function (c) {
45962        p5._validateParameters('blue', arguments);
45963
45964        return this.color(c)._getBlue();
45965      };
45966      /**
45967       * Extracts the HSB brightness value from a color or pixel array.
45968       *
45969       * @method brightness
45970       * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
45971       *                                         or CSS color
45972       * @return {Number} the brightness value
45973       * @example
45974       * <div>
45975       * <code>
45976       * noStroke();
45977       * colorMode(HSB, 255);
45978       * let c = color(0, 126, 255);
45979       * fill(c);
45980       * rect(15, 20, 35, 60);
45981       * let value = brightness(c); // Sets 'value' to 255
45982       * fill(value);
45983       * rect(50, 20, 35, 60);
45984       * </code>
45985       * </div>
45986       *
45987       * @alt
45988       * Left half of canvas salmon pink and the right half white.
45989       *
45990       */
45991
45992
45993      p5.prototype.brightness = function (c) {
45994        p5._validateParameters('brightness', arguments);
45995
45996        return this.color(c)._getBrightness();
45997      };
45998      /**
45999       * Creates colors for storing in variables of the color datatype. The
46000       * parameters are interpreted as RGB or HSB values depending on the
46001       * current <a href="#/p5/colorMode">colorMode()</a>. The default mode is RGB values from 0 to 255
46002       * and, therefore, the function call color(255, 204, 0) will return a
46003       * bright yellow color.
46004       * <br><br>
46005       * Note that if only one value is provided to <a href="#/p5/color">color()</a>, it will be interpreted
46006       * as a grayscale value. Add a second value, and it will be used for alpha
46007       * transparency. When three values are specified, they are interpreted as
46008       * either RGB or HSB values. Adding a fourth value applies alpha
46009       * transparency.
46010       * <br><br>
46011       * If a single string argument is provided, RGB, RGBA and Hex CSS color
46012       * strings and all named color strings are supported. In this case, an alpha
46013       * number value as a second argument is not supported, the RGBA form should be
46014       * used.
46015       *
46016       * @method color
46017       * @param  {Number}        gray    number specifying value between white
46018       *                                 and black.
46019       * @param  {Number}        [alpha] alpha value relative to current color range
46020       *                                 (default is 0-255)
46021       * @return {p5.Color}              resulting color
46022       *
46023       * @example
46024       * <div>
46025       * <code>
46026       * let c = color(255, 204, 0); // Define color 'c'
46027       * fill(c); // Use color variable 'c' as fill color
46028       * noStroke(); // Don't draw a stroke around shapes
46029       * rect(30, 20, 55, 55); // Draw rectangle
46030       * </code>
46031       * </div>
46032       *
46033       * <div>
46034       * <code>
46035       * let c = color(255, 204, 0); // Define color 'c'
46036       * fill(c); // Use color variable 'c' as fill color
46037       * noStroke(); // Don't draw a stroke around shapes
46038       * ellipse(25, 25, 80, 80); // Draw left circle
46039       *
46040       * // Using only one value with color()
46041       * // generates a grayscale value.
46042       * c = color(65); // Update 'c' with grayscale value
46043       * fill(c); // Use updated 'c' as fill color
46044       * ellipse(75, 75, 80, 80); // Draw right circle
46045       * </code>
46046       * </div>
46047       *
46048       * <div>
46049       * <code>
46050       * // Named SVG & CSS colors may be used,
46051       * let c = color('magenta');
46052       * fill(c); // Use 'c' as fill color
46053       * noStroke(); // Don't draw a stroke around shapes
46054       * rect(20, 20, 60, 60); // Draw rectangle
46055       * </code>
46056       * </div>
46057       *
46058       * <div>
46059       * <code>
46060       * // as can hex color codes:
46061       * noStroke(); // Don't draw a stroke around shapes
46062       * let c = color('#0f0');
46063       * fill(c); // Use 'c' as fill color
46064       * rect(0, 10, 45, 80); // Draw rectangle
46065       *
46066       * c = color('#00ff00');
46067       * fill(c); // Use updated 'c' as fill color
46068       * rect(55, 10, 45, 80); // Draw rectangle
46069       * </code>
46070       * </div>
46071       *
46072       * <div>
46073       * <code>
46074       * // RGB and RGBA color strings are also supported:
46075       * // these all set to the same color (solid blue)
46076       * let c;
46077       * noStroke(); // Don't draw a stroke around shapes
46078       * c = color('rgb(0,0,255)');
46079       * fill(c); // Use 'c' as fill color
46080       * rect(10, 10, 35, 35); // Draw rectangle
46081       *
46082       * c = color('rgb(0%, 0%, 100%)');
46083       * fill(c); // Use updated 'c' as fill color
46084       * rect(55, 10, 35, 35); // Draw rectangle
46085       *
46086       * c = color('rgba(0, 0, 255, 1)');
46087       * fill(c); // Use updated 'c' as fill color
46088       * rect(10, 55, 35, 35); // Draw rectangle
46089       *
46090       * c = color('rgba(0%, 0%, 100%, 1)');
46091       * fill(c); // Use updated 'c' as fill color
46092       * rect(55, 55, 35, 35); // Draw rectangle
46093       * </code>
46094       * </div>
46095       *
46096       * <div>
46097       * <code>
46098       * // HSL color is also supported and can be specified
46099       * // by value
46100       * let c;
46101       * noStroke(); // Don't draw a stroke around shapes
46102       * c = color('hsl(160, 100%, 50%)');
46103       * fill(c); // Use 'c' as fill color
46104       * rect(0, 10, 45, 80); // Draw rectangle
46105       *
46106       * c = color('hsla(160, 100%, 50%, 0.5)');
46107       * fill(c); // Use updated 'c' as fill color
46108       * rect(55, 10, 45, 80); // Draw rectangle
46109       * </code>
46110       * </div>
46111       *
46112       * <div>
46113       * <code>
46114       * // HSB color is also supported and can be specified
46115       * // by value
46116       * let c;
46117       * noStroke(); // Don't draw a stroke around shapes
46118       * c = color('hsb(160, 100%, 50%)');
46119       * fill(c); // Use 'c' as fill color
46120       * rect(0, 10, 45, 80); // Draw rectangle
46121       *
46122       * c = color('hsba(160, 100%, 50%, 0.5)');
46123       * fill(c); // Use updated 'c' as fill color
46124       * rect(55, 10, 45, 80); // Draw rectangle
46125       * </code>
46126       * </div>
46127       *
46128       * <div>
46129       * <code>
46130       * let c; // Declare color 'c'
46131       * noStroke(); // Don't draw a stroke around shapes
46132       *
46133       * // If no colorMode is specified, then the
46134       * // default of RGB with scale of 0-255 is used.
46135       * c = color(50, 55, 100); // Create a color for 'c'
46136       * fill(c); // Use color variable 'c' as fill color
46137       * rect(0, 10, 45, 80); // Draw left rect
46138       *
46139       * colorMode(HSB, 100); // Use HSB with scale of 0-100
46140       * c = color(50, 55, 100); // Update 'c' with new color
46141       * fill(c); // Use updated 'c' as fill color
46142       * rect(55, 10, 45, 80); // Draw right rect
46143       * </code>
46144       * </div>
46145       *
46146       * @alt
46147       * Yellow rect in middle right of canvas, with 55 pixel width and height.
46148       * Yellow ellipse in top left of canvas, black ellipse in bottom right,both 80x80.
46149       * Bright fuschia rect in middle of canvas, 60 pixel width and height.
46150       * Two bright green rects on opposite sides of the canvas, both 45x80.
46151       * Four blue rects in each corner of the canvas, each are 35x35.
46152       * Bright sea green rect on left and darker rect on right of canvas, both 45x80.
46153       * Dark green rect on left and lighter green rect on right of canvas, both 45x80.
46154       * Dark blue rect on left and light teal rect on right of canvas, both 45x80.
46155       *
46156       */
46157
46158      /**
46159       * @method color
46160       * @param  {Number}        v1      red or hue value relative to
46161       *                                 the current color range
46162       * @param  {Number}        v2      green or saturation value
46163       *                                 relative to the current color range
46164       * @param  {Number}        v3      blue or brightness value
46165       *                                 relative to the current color range
46166       * @param  {Number}        [alpha]
46167       * @return {p5.Color}
46168       */
46169
46170      /**
46171       * @method color
46172       * @param  {String}        value   a color string
46173       * @return {p5.Color}
46174       */
46175
46176      /**
46177       * @method color
46178       * @param  {Number[]}      values  an array containing the red,green,blue &
46179       *                                 and alpha components of the color
46180       * @return {p5.Color}
46181       */
46182
46183      /**
46184       * @method color
46185       * @param  {p5.Color}     color
46186       * @return {p5.Color}
46187       */
46188
46189
46190      p5.prototype.color = function () {
46191        p5._validateParameters('color', arguments);
46192
46193        if (arguments[0] instanceof p5.Color) {
46194          return arguments[0]; // Do nothing if argument is already a color object.
46195        }
46196
46197        var args = arguments[0] instanceof Array ? arguments[0] : arguments;
46198        return new p5.Color(this, args);
46199      };
46200      /**
46201       * Extracts the green value from a color or pixel array.
46202       *
46203       * @method green
46204       * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
46205       *                                         or CSS color
46206       * @return {Number} the green value
46207       * @example
46208       * <div>
46209       * <code>
46210       * let c = color(20, 75, 200); // Define color 'c'
46211       * fill(c); // Use color variable 'c' as fill color
46212       * rect(15, 20, 35, 60); // Draw left rectangle
46213       *
46214       * let greenValue = green(c); // Get green in 'c'
46215       * print(greenValue); // Print "75.0"
46216       * fill(0, greenValue, 0); // Use 'greenValue' in new fill
46217       * rect(50, 20, 35, 60); // Draw right rectangle
46218       * </code>
46219       * </div>
46220       *
46221       * @alt
46222       * blue rect on left and green on right, both with black outlines & 35x60.
46223       *
46224       */
46225
46226
46227      p5.prototype.green = function (c) {
46228        p5._validateParameters('green', arguments);
46229
46230        return this.color(c)._getGreen();
46231      };
46232      /**
46233       * Extracts the hue value from a color or pixel array.
46234       *
46235       * Hue exists in both HSB and HSL. This function will return the
46236       * HSB-normalized hue when supplied with an HSB color object (or when supplied
46237       * with a pixel array while the color mode is HSB), but will default to the
46238       * HSL-normalized hue otherwise. (The values will only be different if the
46239       * maximum hue setting for each system is different.)
46240       *
46241       * @method hue
46242       * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
46243       *                                         or CSS color
46244       * @return {Number} the hue
46245       * @example
46246       * <div>
46247       * <code>
46248       * noStroke();
46249       * colorMode(HSB, 255);
46250       * let c = color(0, 126, 255);
46251       * fill(c);
46252       * rect(15, 20, 35, 60);
46253       * let value = hue(c); // Sets 'value' to "0"
46254       * fill(value);
46255       * rect(50, 20, 35, 60);
46256       * </code>
46257       * </div>
46258       *
46259       * @alt
46260       * salmon pink rect on left and black on right, both 35x60.
46261       *
46262       */
46263
46264
46265      p5.prototype.hue = function (c) {
46266        p5._validateParameters('hue', arguments);
46267
46268        return this.color(c)._getHue();
46269      };
46270      /**
46271       * Blends two colors to find a third color somewhere between them. The amt
46272       * parameter is the amount to interpolate between the two values where 0.0
46273       * equal to the first color, 0.1 is very near the first color, 0.5 is halfway
46274       * in between, etc. An amount below 0 will be treated as 0. Likewise, amounts
46275       * above 1 will be capped at 1. This is different from the behavior of <a href="#/p5/lerp">lerp()</a>,
46276       * but necessary because otherwise numbers outside the range will produce
46277       * strange and unexpected colors.
46278       * <br><br>
46279       * The way that colours are interpolated depends on the current color mode.
46280       *
46281       * @method lerpColor
46282       * @param  {p5.Color} c1  interpolate from this color
46283       * @param  {p5.Color} c2  interpolate to this color
46284       * @param  {Number}       amt number between 0 and 1
46285       * @return {p5.Color}     interpolated color
46286       * @example
46287       * <div>
46288       * <code>
46289       * colorMode(RGB);
46290       * stroke(255);
46291       * background(51);
46292       * let from = color(218, 165, 32);
46293       * let to = color(72, 61, 139);
46294       * colorMode(RGB); // Try changing to HSB.
46295       * let interA = lerpColor(from, to, 0.33);
46296       * let interB = lerpColor(from, to, 0.66);
46297       * fill(from);
46298       * rect(10, 20, 20, 60);
46299       * fill(interA);
46300       * rect(30, 20, 20, 60);
46301       * fill(interB);
46302       * rect(50, 20, 20, 60);
46303       * fill(to);
46304       * rect(70, 20, 20, 60);
46305       * </code>
46306       * </div>
46307       *
46308       * @alt
46309       * 4 rects one tan, brown, brownish purple, purple, with white outlines & 20x60
46310       *
46311       */
46312
46313
46314      p5.prototype.lerpColor = function (c1, c2, amt) {
46315        p5._validateParameters('lerpColor', arguments);
46316
46317        var mode = this._colorMode;
46318        var maxes = this._colorMaxes;
46319        var l0, l1, l2, l3;
46320        var fromArray, toArray;
46321
46322        if (mode === constants.RGB) {
46323          fromArray = c1.levels.map(function (level) {
46324            return level / 255;
46325          });
46326          toArray = c2.levels.map(function (level) {
46327            return level / 255;
46328          });
46329        } else if (mode === constants.HSB) {
46330          c1._getBrightness(); // Cache hsba so it definitely exists.
46331
46332
46333          c2._getBrightness();
46334
46335          fromArray = c1.hsba;
46336          toArray = c2.hsba;
46337        } else if (mode === constants.HSL) {
46338          c1._getLightness(); // Cache hsla so it definitely exists.
46339
46340
46341          c2._getLightness();
46342
46343          fromArray = c1.hsla;
46344          toArray = c2.hsla;
46345        } else {
46346          throw new Error(mode + 'cannot be used for interpolation.');
46347        } // Prevent extrapolation.
46348
46349
46350        amt = Math.max(Math.min(amt, 1), 0); // Define lerp here itself if user isn't using math module.
46351        // Maintains the definition as found in math/calculation.js
46352
46353        if (typeof this.lerp === 'undefined') {
46354          this.lerp = function (start, stop, amt) {
46355            return amt * (stop - start) + start;
46356          };
46357        } // Perform interpolation.
46358
46359
46360        l0 = this.lerp(fromArray[0], toArray[0], amt);
46361        l1 = this.lerp(fromArray[1], toArray[1], amt);
46362        l2 = this.lerp(fromArray[2], toArray[2], amt);
46363        l3 = this.lerp(fromArray[3], toArray[3], amt); // Scale components.
46364
46365        l0 *= maxes[mode][0];
46366        l1 *= maxes[mode][1];
46367        l2 *= maxes[mode][2];
46368        l3 *= maxes[mode][3];
46369        return this.color(l0, l1, l2, l3);
46370      };
46371      /**
46372       * Extracts the HSL lightness value from a color or pixel array.
46373       *
46374       * @method lightness
46375       * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
46376       *                                         or CSS color
46377       * @return {Number} the lightness
46378       * @example
46379       * <div>
46380       * <code>
46381       * noStroke();
46382       * colorMode(HSL);
46383       * let c = color(156, 100, 50, 1);
46384       * fill(c);
46385       * rect(15, 20, 35, 60);
46386       * let value = lightness(c); // Sets 'value' to 50
46387       * fill(value);
46388       * rect(50, 20, 35, 60);
46389       * </code>
46390       * </div>
46391       *
46392       * @alt
46393       * light pastel green rect on left and dark grey rect on right, both 35x60.
46394       *
46395       */
46396
46397
46398      p5.prototype.lightness = function (c) {
46399        p5._validateParameters('lightness', arguments);
46400
46401        return this.color(c)._getLightness();
46402      };
46403      /**
46404       * Extracts the red value from a color or pixel array.
46405       *
46406       * @method red
46407       * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
46408       *                                         or CSS color
46409       * @return {Number} the red value
46410       * @example
46411       * <div>
46412       * <code>
46413       * let c = color(255, 204, 0); // Define color 'c'
46414       * fill(c); // Use color variable 'c' as fill color
46415       * rect(15, 20, 35, 60); // Draw left rectangle
46416       *
46417       * let redValue = red(c); // Get red in 'c'
46418       * print(redValue); // Print "255.0"
46419       * fill(redValue, 0, 0); // Use 'redValue' in new fill
46420       * rect(50, 20, 35, 60); // Draw right rectangle
46421       * </code>
46422       * </div>
46423       *
46424       * <div>
46425       * <code>
46426       * colorMode(RGB, 255);
46427       * let c = color(127, 255, 0);
46428       * colorMode(RGB, 1);
46429       * let myColor = red(c);
46430       * print(myColor);
46431       * </code>
46432       * </div>
46433       *
46434       * @alt
46435       * yellow rect on left and red rect on right, both with black outlines and 35x60.
46436       * grey canvas
46437       */
46438
46439
46440      p5.prototype.red = function (c) {
46441        p5._validateParameters('red', arguments);
46442
46443        return this.color(c)._getRed();
46444      };
46445      /**
46446       * Extracts the saturation value from a color or pixel array.
46447       *
46448       * Saturation is scaled differently in HSB and HSL. This function will return
46449       * the HSB saturation when supplied with an HSB color object (or when supplied
46450       * with a pixel array while the color mode is HSB), but will default to the
46451       * HSL saturation otherwise.
46452       *
46453       * @method saturation
46454       * @param {p5.Color|Number[]|String} color <a href="#/p5.Color">p5.Color</a> object, color components,
46455       *                                         or CSS color
46456       * @return {Number} the saturation value
46457       * @example
46458       * <div>
46459       * <code>
46460       * noStroke();
46461       * colorMode(HSB, 255);
46462       * let c = color(0, 126, 255);
46463       * fill(c);
46464       * rect(15, 20, 35, 60);
46465       * let value = saturation(c); // Sets 'value' to 126
46466       * fill(value);
46467       * rect(50, 20, 35, 60);
46468       * </code>
46469       * </div>
46470       *
46471       * @alt
46472       *deep pink rect on left and grey rect on right, both 35x60.
46473       *
46474       */
46475
46476
46477      p5.prototype.saturation = function (c) {
46478        p5._validateParameters('saturation', arguments);
46479
46480        return this.color(c)._getSaturation();
46481      };
46482
46483      module.exports = p5;
46484    }, {
46485      "../core/constants": 18,
46486      "../core/error_helpers": 20,
46487      "../core/main": 24,
46488      "./p5.Color": 16
46489    }],
46490    16: [function (_dereq_, module, exports) {
46491      /**
46492       * @module Color
46493       * @submodule Creating & Reading
46494       * @for p5
46495       * @requires core
46496       * @requires constants
46497       * @requires color_conversion
46498       */
46499      'use strict';
46500
46501      var p5 = _dereq_('../core/main');
46502
46503      var constants = _dereq_('../core/constants');
46504
46505      var color_conversion = _dereq_('./color_conversion');
46506      /**
46507       * Each color stores the color mode and level maxes that applied at the
46508       * time of its construction. These are used to interpret the input arguments
46509       * (at construction and later for that instance of color) and to format the
46510       * output e.g. when <a href="#/p5/saturation">saturation()</a> is requested.
46511       *
46512       * Internally we store an array representing the ideal RGBA values in floating
46513       * point form, normalized from 0 to 1. From this we calculate the closest
46514       * screen color (RGBA levels from 0 to 255) and expose this to the renderer.
46515       *
46516       * We also cache normalized, floating point components of the color in various
46517       * representations as they are calculated. This is done to prevent repeating a
46518       * conversion that has already been performed.
46519       *
46520       * @class p5.Color
46521       */
46522
46523
46524      p5.Color = function (pInst, vals) {
46525        // Record color mode and maxes at time of construction.
46526        this._storeModeAndMaxes(pInst._colorMode, pInst._colorMaxes); // Calculate normalized RGBA values.
46527
46528
46529        if (this.mode !== constants.RGB && this.mode !== constants.HSL && this.mode !== constants.HSB) {
46530          throw new Error(this.mode + ' is an invalid colorMode.');
46531        } else {
46532          this._array = p5.Color._parseInputs.apply(this, vals);
46533        } // Expose closest screen color.
46534
46535
46536        this._calculateLevels();
46537
46538        return this;
46539      };
46540      /**
46541       * This function returns the color formatted as a string. This can be useful
46542       * for debugging, or for using p5.js with other libraries.
46543       * @method toString
46544       * @param {String} [format] How the color string will be formatted.
46545       * Leaving this empty formats the string as rgba(r, g, b, a).
46546       * '#rgb' '#rgba' '#rrggbb' and '#rrggbbaa' format as hexadecimal color codes.
46547       * 'rgb' 'hsb' and 'hsl' return the color formatted in the specified color mode.
46548       * 'rgba' 'hsba' and 'hsla' are the same as above but with alpha channels.
46549       * 'rgb%' 'hsb%' 'hsl%' 'rgba%' 'hsba%' and 'hsla%' format as percentages.
46550       * @return {String} the formatted string
46551       * @example
46552       * <div>
46553       * <code>
46554       * let myColor;
46555       * function setup() {
46556       *   createCanvas(200, 200);
46557       *   stroke(255);
46558       *   myColor = color(100, 100, 250);
46559       *   fill(myColor);
46560       * }
46561       *
46562       * function draw() {
46563       *   rotate(HALF_PI);
46564       *   text(myColor.toString(), 0, -5);
46565       *   text(myColor.toString('#rrggbb'), 0, -30);
46566       *   text(myColor.toString('rgba%'), 0, -55);
46567       * }
46568       * </code>
46569       * </div>
46570       *
46571       * @alt
46572       * canvas with text representation of color
46573       */
46574
46575
46576      p5.Color.prototype.toString = function (format) {
46577        if (!this.hsba) this.hsba = color_conversion._rgbaToHSBA(this._array);
46578        if (!this.hsla) this.hsla = color_conversion._rgbaToHSLA(this._array);
46579        var a = this.levels;
46580        var f = this._array;
46581        var alpha = f[3]; // String representation uses normalized alpha
46582
46583        switch (format) {
46584          case '#rrggbb':
46585            return '#'.concat(a[0] < 16 ? '0'.concat(a[0].toString(16)) : a[0].toString(16), a[1] < 16 ? '0'.concat(a[1].toString(16)) : a[1].toString(16), a[2] < 16 ? '0'.concat(a[2].toString(16)) : a[2].toString(16));
46586
46587          case '#rrggbbaa':
46588            return '#'.concat(a[0] < 16 ? '0'.concat(a[0].toString(16)) : a[0].toString(16), a[1] < 16 ? '0'.concat(a[1].toString(16)) : a[1].toString(16), a[2] < 16 ? '0'.concat(a[2].toString(16)) : a[2].toString(16), a[3] < 16 ? '0'.concat(a[2].toString(16)) : a[3].toString(16));
46589
46590          case '#rgb':
46591            return '#'.concat(Math.round(f[0] * 15).toString(16), Math.round(f[1] * 15).toString(16), Math.round(f[2] * 15).toString(16));
46592
46593          case '#rgba':
46594            return '#'.concat(Math.round(f[0] * 15).toString(16), Math.round(f[1] * 15).toString(16), Math.round(f[2] * 15).toString(16), Math.round(f[3] * 15).toString(16));
46595
46596          case 'rgb':
46597            return 'rgb('.concat(a[0], ', ', a[1], ', ', a[2], ')');
46598
46599          case 'rgb%':
46600            return 'rgb('.concat((100 * f[0]).toPrecision(3), '%, ', (100 * f[1]).toPrecision(3), '%, ', (100 * f[2]).toPrecision(3), '%)');
46601
46602          case 'rgba%':
46603            return 'rgba('.concat((100 * f[0]).toPrecision(3), '%, ', (100 * f[1]).toPrecision(3), '%, ', (100 * f[2]).toPrecision(3), '%, ', (100 * f[3]).toPrecision(3), '%)');
46604
46605          case 'hsb':
46606          case 'hsv':
46607            return 'hsb('.concat(this.hsba[0] * this.maxes[constants.HSB][0], ', ', this.hsba[1] * this.maxes[constants.HSB][1], ', ', this.hsba[2] * this.maxes[constants.HSB][2], ')');
46608
46609          case 'hsb%':
46610          case 'hsv%':
46611            return 'hsb('.concat((100 * this.hsba[0]).toPrecision(3), '%, ', (100 * this.hsba[1]).toPrecision(3), '%, ', (100 * this.hsba[2]).toPrecision(3), '%)');
46612
46613          case 'hsba':
46614          case 'hsva':
46615            return 'hsba('.concat(this.hsba[0] * this.maxes[constants.HSB][0], ', ', this.hsba[1] * this.maxes[constants.HSB][1], ', ', this.hsba[2] * this.maxes[constants.HSB][2], ', ', alpha, ')');
46616
46617          case 'hsba%':
46618          case 'hsva%':
46619            return 'hsba('.concat((100 * this.hsba[0]).toPrecision(3), '%, ', (100 * this.hsba[1]).toPrecision(3), '%, ', (100 * this.hsba[2]).toPrecision(3), '%, ', (100 * alpha).toPrecision(3), '%)');
46620
46621          case 'hsl':
46622            return 'hsl('.concat(this.hsla[0] * this.maxes[constants.HSL][0], ', ', this.hsla[1] * this.maxes[constants.HSL][1], ', ', this.hsla[2] * this.maxes[constants.HSL][2], ')');
46623
46624          case 'hsl%':
46625            return 'hsl('.concat((100 * this.hsla[0]).toPrecision(3), '%, ', (100 * this.hsla[1]).toPrecision(3), '%, ', (100 * this.hsla[2]).toPrecision(3), '%)');
46626
46627          case 'hsla':
46628            return 'hsla('.concat(this.hsla[0] * this.maxes[constants.HSL][0], ', ', this.hsla[1] * this.maxes[constants.HSL][1], ', ', this.hsla[2] * this.maxes[constants.HSL][2], ', ', alpha, ')');
46629
46630          case 'hsla%':
46631            return 'hsl('.concat((100 * this.hsla[0]).toPrecision(3), '%, ', (100 * this.hsla[1]).toPrecision(3), '%, ', (100 * this.hsla[2]).toPrecision(3), '%, ', (100 * alpha).toPrecision(3), '%)');
46632
46633          case 'rgba':
46634          default:
46635            return 'rgba(' + a[0] + ',' + a[1] + ',' + a[2] + ',' + alpha + ')';
46636        }
46637      };
46638      /**
46639       * @method setRed
46640       * @param {Number} red the new red value
46641       * @example
46642       * <div>
46643       * <code>
46644       * let backgroundColor;
46645       *
46646       * function setup() {
46647       *   backgroundColor = color(100, 50, 150);
46648       * }
46649       *
46650       * function draw() {
46651       *   backgroundColor.setRed(128 + 128 * sin(millis() / 1000));
46652       *   background(backgroundColor);
46653       * }
46654       * </code>
46655       * </div>
46656       *
46657       * @alt
46658       * canvas with gradually changing background color
46659       */
46660
46661
46662      p5.Color.prototype.setRed = function (new_red) {
46663        this._array[0] = new_red / this.maxes[constants.RGB][0];
46664
46665        this._calculateLevels();
46666      };
46667      /**
46668       * @method setGreen
46669       * @param {Number} green the new green value
46670       * @example
46671       * <div>
46672       * <code>
46673       * let backgroundColor;
46674       *
46675       * function setup() {
46676       *   backgroundColor = color(100, 50, 150);
46677       * }
46678       *
46679       * function draw() {
46680       *   backgroundColor.setGreen(128 + 128 * sin(millis() / 1000));
46681       *   background(backgroundColor);
46682       * }
46683       * </code>
46684       * </div>
46685       *
46686       * @alt
46687       * canvas with gradually changing background color
46688       **/
46689
46690
46691      p5.Color.prototype.setGreen = function (new_green) {
46692        this._array[1] = new_green / this.maxes[constants.RGB][1];
46693
46694        this._calculateLevels();
46695      };
46696      /**
46697       * @method setBlue
46698       * @param {Number} blue the new blue value
46699       * @example
46700       * <div>
46701       * <code>
46702       * let backgroundColor;
46703       *
46704       * function setup() {
46705       *   backgroundColor = color(100, 50, 150);
46706       * }
46707       *
46708       * function draw() {
46709       *   backgroundColor.setBlue(128 + 128 * sin(millis() / 1000));
46710       *   background(backgroundColor);
46711       * }
46712       * </code>
46713       * </div>
46714       *
46715       * @alt
46716       * canvas with gradually changing background color
46717       **/
46718
46719
46720      p5.Color.prototype.setBlue = function (new_blue) {
46721        this._array[2] = new_blue / this.maxes[constants.RGB][2];
46722
46723        this._calculateLevels();
46724      };
46725      /**
46726       * @method setAlpha
46727       * @param {Number} alpha the new alpha value
46728       * @example
46729       * <div>
46730       * <code>
46731       * let squareColor;
46732       *
46733       * function setup() {
46734       *   ellipseMode(CORNERS);
46735       *   strokeWeight(4);
46736       *   squareColor = color(100, 50, 150);
46737       * }
46738       *
46739       * function draw() {
46740       *   background(255);
46741       *
46742       *   noFill();
46743       *   stroke(0);
46744       *   ellipse(10, 10, width - 10, height - 10);
46745       *
46746       *   squareColor.setAlpha(128 + 128 * sin(millis() / 1000));
46747       *   fill(squareColor);
46748       *   noStroke();
46749       *   rect(13, 13, width - 26, height - 26);
46750       * }
46751       * </code>
46752       * </div>
46753       *
46754       * @alt
46755       * circle behind a square with gradually changing opacity
46756       **/
46757
46758
46759      p5.Color.prototype.setAlpha = function (new_alpha) {
46760        this._array[3] = new_alpha / this.maxes[this.mode][3];
46761
46762        this._calculateLevels();
46763      }; // calculates and stores the closest screen levels
46764
46765
46766      p5.Color.prototype._calculateLevels = function () {
46767        var array = this._array; // (loop backwards for performance)
46768
46769        var levels = this.levels = new Array(array.length);
46770
46771        for (var i = array.length - 1; i >= 0; --i) {
46772          levels[i] = Math.round(array[i] * 255);
46773        }
46774      };
46775
46776      p5.Color.prototype._getAlpha = function () {
46777        return this._array[3] * this.maxes[this.mode][3];
46778      }; // stores the color mode and maxes in this instance of Color
46779      // for later use (by _parseInputs())
46780
46781
46782      p5.Color.prototype._storeModeAndMaxes = function (new_mode, new_maxes) {
46783        this.mode = new_mode;
46784        this.maxes = new_maxes;
46785      };
46786
46787      p5.Color.prototype._getMode = function () {
46788        return this.mode;
46789      };
46790
46791      p5.Color.prototype._getMaxes = function () {
46792        return this.maxes;
46793      };
46794
46795      p5.Color.prototype._getBlue = function () {
46796        return this._array[2] * this.maxes[constants.RGB][2];
46797      };
46798
46799      p5.Color.prototype._getBrightness = function () {
46800        if (!this.hsba) {
46801          this.hsba = color_conversion._rgbaToHSBA(this._array);
46802        }
46803
46804        return this.hsba[2] * this.maxes[constants.HSB][2];
46805      };
46806
46807      p5.Color.prototype._getGreen = function () {
46808        return this._array[1] * this.maxes[constants.RGB][1];
46809      };
46810      /**
46811       * Hue is the same in HSB and HSL, but the maximum value may be different.
46812       * This function will return the HSB-normalized saturation when supplied with
46813       * an HSB color object, but will default to the HSL-normalized saturation
46814       * otherwise.
46815       */
46816
46817
46818      p5.Color.prototype._getHue = function () {
46819        if (this.mode === constants.HSB) {
46820          if (!this.hsba) {
46821            this.hsba = color_conversion._rgbaToHSBA(this._array);
46822          }
46823
46824          return this.hsba[0] * this.maxes[constants.HSB][0];
46825        } else {
46826          if (!this.hsla) {
46827            this.hsla = color_conversion._rgbaToHSLA(this._array);
46828          }
46829
46830          return this.hsla[0] * this.maxes[constants.HSL][0];
46831        }
46832      };
46833
46834      p5.Color.prototype._getLightness = function () {
46835        if (!this.hsla) {
46836          this.hsla = color_conversion._rgbaToHSLA(this._array);
46837        }
46838
46839        return this.hsla[2] * this.maxes[constants.HSL][2];
46840      };
46841
46842      p5.Color.prototype._getRed = function () {
46843        return this._array[0] * this.maxes[constants.RGB][0];
46844      };
46845      /**
46846       * Saturation is scaled differently in HSB and HSL. This function will return
46847       * the HSB saturation when supplied with an HSB color object, but will default
46848       * to the HSL saturation otherwise.
46849       */
46850
46851
46852      p5.Color.prototype._getSaturation = function () {
46853        if (this.mode === constants.HSB) {
46854          if (!this.hsba) {
46855            this.hsba = color_conversion._rgbaToHSBA(this._array);
46856          }
46857
46858          return this.hsba[1] * this.maxes[constants.HSB][1];
46859        } else {
46860          if (!this.hsla) {
46861            this.hsla = color_conversion._rgbaToHSLA(this._array);
46862          }
46863
46864          return this.hsla[1] * this.maxes[constants.HSL][1];
46865        }
46866      };
46867      /**
46868       * CSS named colors.
46869       */
46870
46871
46872      var namedColors = {
46873        aliceblue: '#f0f8ff',
46874        antiquewhite: '#faebd7',
46875        aqua: '#00ffff',
46876        aquamarine: '#7fffd4',
46877        azure: '#f0ffff',
46878        beige: '#f5f5dc',
46879        bisque: '#ffe4c4',
46880        black: '#000000',
46881        blanchedalmond: '#ffebcd',
46882        blue: '#0000ff',
46883        blueviolet: '#8a2be2',
46884        brown: '#a52a2a',
46885        burlywood: '#deb887',
46886        cadetblue: '#5f9ea0',
46887        chartreuse: '#7fff00',
46888        chocolate: '#d2691e',
46889        coral: '#ff7f50',
46890        cornflowerblue: '#6495ed',
46891        cornsilk: '#fff8dc',
46892        crimson: '#dc143c',
46893        cyan: '#00ffff',
46894        darkblue: '#00008b',
46895        darkcyan: '#008b8b',
46896        darkgoldenrod: '#b8860b',
46897        darkgray: '#a9a9a9',
46898        darkgreen: '#006400',
46899        darkgrey: '#a9a9a9',
46900        darkkhaki: '#bdb76b',
46901        darkmagenta: '#8b008b',
46902        darkolivegreen: '#556b2f',
46903        darkorange: '#ff8c00',
46904        darkorchid: '#9932cc',
46905        darkred: '#8b0000',
46906        darksalmon: '#e9967a',
46907        darkseagreen: '#8fbc8f',
46908        darkslateblue: '#483d8b',
46909        darkslategray: '#2f4f4f',
46910        darkslategrey: '#2f4f4f',
46911        darkturquoise: '#00ced1',
46912        darkviolet: '#9400d3',
46913        deeppink: '#ff1493',
46914        deepskyblue: '#00bfff',
46915        dimgray: '#696969',
46916        dimgrey: '#696969',
46917        dodgerblue: '#1e90ff',
46918        firebrick: '#b22222',
46919        floralwhite: '#fffaf0',
46920        forestgreen: '#228b22',
46921        fuchsia: '#ff00ff',
46922        gainsboro: '#dcdcdc',
46923        ghostwhite: '#f8f8ff',
46924        gold: '#ffd700',
46925        goldenrod: '#daa520',
46926        gray: '#808080',
46927        green: '#008000',
46928        greenyellow: '#adff2f',
46929        grey: '#808080',
46930        honeydew: '#f0fff0',
46931        hotpink: '#ff69b4',
46932        indianred: '#cd5c5c',
46933        indigo: '#4b0082',
46934        ivory: '#fffff0',
46935        khaki: '#f0e68c',
46936        lavender: '#e6e6fa',
46937        lavenderblush: '#fff0f5',
46938        lawngreen: '#7cfc00',
46939        lemonchiffon: '#fffacd',
46940        lightblue: '#add8e6',
46941        lightcoral: '#f08080',
46942        lightcyan: '#e0ffff',
46943        lightgoldenrodyellow: '#fafad2',
46944        lightgray: '#d3d3d3',
46945        lightgreen: '#90ee90',
46946        lightgrey: '#d3d3d3',
46947        lightpink: '#ffb6c1',
46948        lightsalmon: '#ffa07a',
46949        lightseagreen: '#20b2aa',
46950        lightskyblue: '#87cefa',
46951        lightslategray: '#778899',
46952        lightslategrey: '#778899',
46953        lightsteelblue: '#b0c4de',
46954        lightyellow: '#ffffe0',
46955        lime: '#00ff00',
46956        limegreen: '#32cd32',
46957        linen: '#faf0e6',
46958        magenta: '#ff00ff',
46959        maroon: '#800000',
46960        mediumaquamarine: '#66cdaa',
46961        mediumblue: '#0000cd',
46962        mediumorchid: '#ba55d3',
46963        mediumpurple: '#9370db',
46964        mediumseagreen: '#3cb371',
46965        mediumslateblue: '#7b68ee',
46966        mediumspringgreen: '#00fa9a',
46967        mediumturquoise: '#48d1cc',
46968        mediumvioletred: '#c71585',
46969        midnightblue: '#191970',
46970        mintcream: '#f5fffa',
46971        mistyrose: '#ffe4e1',
46972        moccasin: '#ffe4b5',
46973        navajowhite: '#ffdead',
46974        navy: '#000080',
46975        oldlace: '#fdf5e6',
46976        olive: '#808000',
46977        olivedrab: '#6b8e23',
46978        orange: '#ffa500',
46979        orangered: '#ff4500',
46980        orchid: '#da70d6',
46981        palegoldenrod: '#eee8aa',
46982        palegreen: '#98fb98',
46983        paleturquoise: '#afeeee',
46984        palevioletred: '#db7093',
46985        papayawhip: '#ffefd5',
46986        peachpuff: '#ffdab9',
46987        peru: '#cd853f',
46988        pink: '#ffc0cb',
46989        plum: '#dda0dd',
46990        powderblue: '#b0e0e6',
46991        purple: '#800080',
46992        red: '#ff0000',
46993        rosybrown: '#bc8f8f',
46994        royalblue: '#4169e1',
46995        saddlebrown: '#8b4513',
46996        salmon: '#fa8072',
46997        sandybrown: '#f4a460',
46998        seagreen: '#2e8b57',
46999        seashell: '#fff5ee',
47000        sienna: '#a0522d',
47001        silver: '#c0c0c0',
47002        skyblue: '#87ceeb',
47003        slateblue: '#6a5acd',
47004        slategray: '#708090',
47005        slategrey: '#708090',
47006        snow: '#fffafa',
47007        springgreen: '#00ff7f',
47008        steelblue: '#4682b4',
47009        tan: '#d2b48c',
47010        teal: '#008080',
47011        thistle: '#d8bfd8',
47012        tomato: '#ff6347',
47013        turquoise: '#40e0d0',
47014        violet: '#ee82ee',
47015        wheat: '#f5deb3',
47016        white: '#ffffff',
47017        whitesmoke: '#f5f5f5',
47018        yellow: '#ffff00',
47019        yellowgreen: '#9acd32'
47020      };
47021      /**
47022       * These regular expressions are used to build up the patterns for matching
47023       * viable CSS color strings: fragmenting the regexes in this way increases the
47024       * legibility and comprehensibility of the code.
47025       *
47026       * Note that RGB values of .9 are not parsed by IE, but are supported here for
47027       * color string consistency.
47028       */
47029
47030      var WHITESPACE = /\s*/; // Match zero or more whitespace characters.
47031
47032      var INTEGER = /(\d{1,3})/; // Match integers: 79, 255, etc.
47033
47034      var DECIMAL = /((?:\d+(?:\.\d+)?)|(?:\.\d+))/; // Match 129.6, 79, .9, etc.
47035
47036      var PERCENT = new RegExp(DECIMAL.source + '%'); // Match 12.9%, 79%, .9%, etc.
47037
47038      /**
47039       * Full color string patterns. The capture groups are necessary.
47040       */
47041
47042      var colorPatterns = {
47043        // Match colors in format #XXX, e.g. #416.
47044        HEX3: /^#([a-f0-9])([a-f0-9])([a-f0-9])$/i,
47045        // Match colors in format #XXXX, e.g. #5123.
47046        HEX4: /^#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])$/i,
47047        // Match colors in format #XXXXXX, e.g. #b4d455.
47048        HEX6: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i,
47049        // Match colors in format #XXXXXXXX, e.g. #b4d45535.
47050        HEX8: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i,
47051        // Match colors in format rgb(R, G, B), e.g. rgb(255, 0, 128).
47052        RGB: new RegExp(['^rgb\\(', INTEGER.source, ',', INTEGER.source, ',', INTEGER.source, '\\)$'].join(WHITESPACE.source), 'i'),
47053        // Match colors in format rgb(R%, G%, B%), e.g. rgb(100%, 0%, 28.9%).
47054        RGB_PERCENT: new RegExp(['^rgb\\(', PERCENT.source, ',', PERCENT.source, ',', PERCENT.source, '\\)$'].join(WHITESPACE.source), 'i'),
47055        // Match colors in format rgb(R, G, B, A), e.g. rgb(255, 0, 128, 0.25).
47056        RGBA: new RegExp(['^rgba\\(', INTEGER.source, ',', INTEGER.source, ',', INTEGER.source, ',', DECIMAL.source, '\\)$'].join(WHITESPACE.source), 'i'),
47057        // Match colors in format rgb(R%, G%, B%, A), e.g. rgb(100%, 0%, 28.9%, 0.5).
47058        RGBA_PERCENT: new RegExp(['^rgba\\(', PERCENT.source, ',', PERCENT.source, ',', PERCENT.source, ',', DECIMAL.source, '\\)$'].join(WHITESPACE.source), 'i'),
47059        // Match colors in format hsla(H, S%, L%), e.g. hsl(100, 40%, 28.9%).
47060        HSL: new RegExp(['^hsl\\(', INTEGER.source, ',', PERCENT.source, ',', PERCENT.source, '\\)$'].join(WHITESPACE.source), 'i'),
47061        // Match colors in format hsla(H, S%, L%, A), e.g. hsla(100, 40%, 28.9%, 0.5).
47062        HSLA: new RegExp(['^hsla\\(', INTEGER.source, ',', PERCENT.source, ',', PERCENT.source, ',', DECIMAL.source, '\\)$'].join(WHITESPACE.source), 'i'),
47063        // Match colors in format hsb(H, S%, B%), e.g. hsb(100, 40%, 28.9%).
47064        HSB: new RegExp(['^hsb\\(', INTEGER.source, ',', PERCENT.source, ',', PERCENT.source, '\\)$'].join(WHITESPACE.source), 'i'),
47065        // Match colors in format hsba(H, S%, B%, A), e.g. hsba(100, 40%, 28.9%, 0.5).
47066        HSBA: new RegExp(['^hsba\\(', INTEGER.source, ',', PERCENT.source, ',', PERCENT.source, ',', DECIMAL.source, '\\)$'].join(WHITESPACE.source), 'i')
47067      };
47068      /**
47069       * For a number of different inputs, returns a color formatted as [r, g, b, a]
47070       * arrays, with each component normalized between 0 and 1.
47071       *
47072       * @private
47073       * @param {Array} [...args] An 'array-like' object that represents a list of
47074       *                          arguments
47075       * @return {Number[]}       a color formatted as [r, g, b, a]
47076       *                          Example:
47077       *                          input        ==> output
47078       *                          g            ==> [g, g, g, 255]
47079       *                          g,a          ==> [g, g, g, a]
47080       *                          r, g, b      ==> [r, g, b, 255]
47081       *                          r, g, b, a   ==> [r, g, b, a]
47082       *                          [g]          ==> [g, g, g, 255]
47083       *                          [g, a]       ==> [g, g, g, a]
47084       *                          [r, g, b]    ==> [r, g, b, 255]
47085       *                          [r, g, b, a] ==> [r, g, b, a]
47086       * @example
47087       * <div>
47088       * <code>
47089       * // todo
47090       * </code>
47091       * </div>
47092       *
47093       * @alt
47094       * //todo
47095       *
47096       */
47097
47098      p5.Color._parseInputs = function (r, g, b, a) {
47099        var numArgs = arguments.length;
47100        var mode = this.mode;
47101        var maxes = this.maxes[mode];
47102        var results = [];
47103        var i;
47104
47105        if (numArgs >= 3) {
47106          // Argument is a list of component values.
47107          results[0] = r / maxes[0];
47108          results[1] = g / maxes[1];
47109          results[2] = b / maxes[2]; // Alpha may be undefined, so default it to 100%.
47110
47111          if (typeof a === 'number') {
47112            results[3] = a / maxes[3];
47113          } else {
47114            results[3] = 1;
47115          } // Constrain components to the range [0,1].
47116          // (loop backwards for performance)
47117
47118
47119          for (i = results.length - 1; i >= 0; --i) {
47120            var result = results[i];
47121
47122            if (result < 0) {
47123              results[i] = 0;
47124            } else if (result > 1) {
47125              results[i] = 1;
47126            }
47127          } // Convert to RGBA and return.
47128
47129
47130          if (mode === constants.HSL) {
47131            return color_conversion._hslaToRGBA(results);
47132          } else if (mode === constants.HSB) {
47133            return color_conversion._hsbaToRGBA(results);
47134          } else {
47135            return results;
47136          }
47137        } else if (numArgs === 1 && typeof r === 'string') {
47138          var str = r.trim().toLowerCase(); // Return if string is a named colour.
47139
47140          if (namedColors[str]) {
47141            return p5.Color._parseInputs.call(this, namedColors[str]);
47142          } // Try RGBA pattern matching.
47143
47144
47145          if (colorPatterns.HEX3.test(str)) {
47146            // #rgb
47147            results = colorPatterns.HEX3.exec(str).slice(1).map(function (color) {
47148              return parseInt(color + color, 16) / 255;
47149            });
47150            results[3] = 1;
47151            return results;
47152          } else if (colorPatterns.HEX6.test(str)) {
47153            // #rrggbb
47154            results = colorPatterns.HEX6.exec(str).slice(1).map(function (color) {
47155              return parseInt(color, 16) / 255;
47156            });
47157            results[3] = 1;
47158            return results;
47159          } else if (colorPatterns.HEX4.test(str)) {
47160            // #rgba
47161            results = colorPatterns.HEX4.exec(str).slice(1).map(function (color) {
47162              return parseInt(color + color, 16) / 255;
47163            });
47164            return results;
47165          } else if (colorPatterns.HEX8.test(str)) {
47166            // #rrggbbaa
47167            results = colorPatterns.HEX8.exec(str).slice(1).map(function (color) {
47168              return parseInt(color, 16) / 255;
47169            });
47170            return results;
47171          } else if (colorPatterns.RGB.test(str)) {
47172            // rgb(R,G,B)
47173            results = colorPatterns.RGB.exec(str).slice(1).map(function (color) {
47174              return color / 255;
47175            });
47176            results[3] = 1;
47177            return results;
47178          } else if (colorPatterns.RGB_PERCENT.test(str)) {
47179            // rgb(R%,G%,B%)
47180            results = colorPatterns.RGB_PERCENT.exec(str).slice(1).map(function (color) {
47181              return parseFloat(color) / 100;
47182            });
47183            results[3] = 1;
47184            return results;
47185          } else if (colorPatterns.RGBA.test(str)) {
47186            // rgba(R,G,B,A)
47187            results = colorPatterns.RGBA.exec(str).slice(1).map(function (color, idx) {
47188              if (idx === 3) {
47189                return parseFloat(color);
47190              }
47191
47192              return color / 255;
47193            });
47194            return results;
47195          } else if (colorPatterns.RGBA_PERCENT.test(str)) {
47196            // rgba(R%,G%,B%,A%)
47197            results = colorPatterns.RGBA_PERCENT.exec(str).slice(1).map(function (color, idx) {
47198              if (idx === 3) {
47199                return parseFloat(color);
47200              }
47201
47202              return parseFloat(color) / 100;
47203            });
47204            return results;
47205          } // Try HSLA pattern matching.
47206
47207
47208          if (colorPatterns.HSL.test(str)) {
47209            // hsl(H,S,L)
47210            results = colorPatterns.HSL.exec(str).slice(1).map(function (color, idx) {
47211              if (idx === 0) {
47212                return parseInt(color, 10) / 360;
47213              }
47214
47215              return parseInt(color, 10) / 100;
47216            });
47217            results[3] = 1;
47218          } else if (colorPatterns.HSLA.test(str)) {
47219            // hsla(H,S,L,A)
47220            results = colorPatterns.HSLA.exec(str).slice(1).map(function (color, idx) {
47221              if (idx === 0) {
47222                return parseInt(color, 10) / 360;
47223              } else if (idx === 3) {
47224                return parseFloat(color);
47225              }
47226
47227              return parseInt(color, 10) / 100;
47228            });
47229          }
47230
47231          results = results.map(function (value) {
47232            return Math.max(Math.min(value, 1), 0);
47233          });
47234
47235          if (results.length) {
47236            return color_conversion._hslaToRGBA(results);
47237          } // Try HSBA pattern matching.
47238
47239
47240          if (colorPatterns.HSB.test(str)) {
47241            // hsb(H,S,B)
47242            results = colorPatterns.HSB.exec(str).slice(1).map(function (color, idx) {
47243              if (idx === 0) {
47244                return parseInt(color, 10) / 360;
47245              }
47246
47247              return parseInt(color, 10) / 100;
47248            });
47249            results[3] = 1;
47250          } else if (colorPatterns.HSBA.test(str)) {
47251            // hsba(H,S,B,A)
47252            results = colorPatterns.HSBA.exec(str).slice(1).map(function (color, idx) {
47253              if (idx === 0) {
47254                return parseInt(color, 10) / 360;
47255              } else if (idx === 3) {
47256                return parseFloat(color);
47257              }
47258
47259              return parseInt(color, 10) / 100;
47260            });
47261          }
47262
47263          if (results.length) {
47264            // (loop backwards for performance)
47265            for (i = results.length - 1; i >= 0; --i) {
47266              results[i] = Math.max(Math.min(results[i], 1), 0);
47267            }
47268
47269            return color_conversion._hsbaToRGBA(results);
47270          } // Input did not match any CSS color pattern: default to white.
47271
47272
47273          results = [1, 1, 1, 1];
47274        } else if ((numArgs === 1 || numArgs === 2) && typeof r === 'number') {
47275          // 'Grayscale' mode.
47276
47277          /**
47278           * For HSB and HSL, interpret the gray level as a brightness/lightness
47279           * value (they are equivalent when chroma is zero). For RGB, normalize the
47280           * gray level according to the blue maximum.
47281           */
47282          results[0] = r / maxes[2];
47283          results[1] = r / maxes[2];
47284          results[2] = r / maxes[2]; // Alpha may be undefined, so default it to 100%.
47285
47286          if (typeof g === 'number') {
47287            results[3] = g / maxes[3];
47288          } else {
47289            results[3] = 1;
47290          } // Constrain components to the range [0,1].
47291
47292
47293          results = results.map(function (value) {
47294            return Math.max(Math.min(value, 1), 0);
47295          });
47296        } else {
47297          throw new Error(arguments + 'is not a valid color representation.');
47298        }
47299
47300        return results;
47301      };
47302
47303      module.exports = p5.Color;
47304    }, {
47305      "../core/constants": 18,
47306      "../core/main": 24,
47307      "./color_conversion": 14
47308    }],
47309    17: [function (_dereq_, module, exports) {
47310      /**
47311       * @module Color
47312       * @submodule Setting
47313       * @for p5
47314       * @requires core
47315       * @requires constants
47316       */
47317      'use strict';
47318
47319      var p5 = _dereq_('../core/main');
47320
47321      var constants = _dereq_('../core/constants');
47322
47323      _dereq_('./p5.Color');
47324      /**
47325       * The <a href="#/p5/background">background()</a> function sets the color used for the background of the
47326       * p5.js canvas. The default background is transparent. This function is
47327       * typically used within <a href="#/p5/draw">draw()</a> to clear the display window at the beginning
47328       * of each frame, but it can be used inside <a href="#/p5/setup">setup()</a> to set the background on
47329       * the first frame of animation or if the background need only be set once.
47330       * <br><br>
47331       * The color is either specified in terms of the RGB, HSB, or HSL color
47332       * depending on the current <a href="#/p5/colorMode">colorMode</a>. (The default color space is RGB, with
47333       * each value in the range from 0 to 255). The alpha range by default is also 0 to 255.
47334       * <br><br>
47335       * If a single string argument is provided, RGB, RGBA and Hex CSS color strings
47336       * and all named color strings are supported. In this case, an alpha number
47337       * value as a second argument is not supported, the RGBA form should be used.
47338       * <br><br>
47339       * A <a href="#/p5.Color">p5.Color</a> object can also be provided to set the background color.
47340       * <br><br>
47341       * A <a href="#/p5.Image">p5.Image</a> can also be provided to set the background image.
47342       *
47343       * @method background
47344       * @param {p5.Color} color     any value created by the <a href="#/p5/color">color()</a> function
47345       * @chainable
47346       *
47347       * @example
47348       * <div>
47349       * <code>
47350       * // Grayscale integer value
47351       * background(51);
47352       * </code>
47353       * </div>
47354       *
47355       * <div>
47356       * <code>
47357       * // R, G & B integer values
47358       * background(255, 204, 0);
47359       * </code>
47360       * </div>
47361       *
47362       * <div>
47363       * <code>
47364       * // H, S & B integer values
47365       * colorMode(HSB);
47366       * background(255, 204, 100);
47367       * </code>
47368       * </div>
47369       *
47370       * <div>
47371       * <code>
47372       * // Named SVG/CSS color string
47373       * background('red');
47374       * </code>
47375       * </div>
47376       *
47377       * <div>
47378       * <code>
47379       * // three-digit hexadecimal RGB notation
47380       * background('#fae');
47381       * </code>
47382       * </div>
47383       *
47384       * <div>
47385       * <code>
47386       * // six-digit hexadecimal RGB notation
47387       * background('#222222');
47388       * </code>
47389       * </div>
47390       *
47391       * <div>
47392       * <code>
47393       * // integer RGB notation
47394       * background('rgb(0,255,0)');
47395       * </code>
47396       * </div>
47397       *
47398       * <div>
47399       * <code>
47400       * // integer RGBA notation
47401       * background('rgba(0,255,0, 0.25)');
47402       * </code>
47403       * </div>
47404       *
47405       * <div>
47406       * <code>
47407       * // percentage RGB notation
47408       * background('rgb(100%,0%,10%)');
47409       * </code>
47410       * </div>
47411       *
47412       * <div>
47413       * <code>
47414       * // percentage RGBA notation
47415       * background('rgba(100%,0%,100%,0.5)');
47416       * </code>
47417       * </div>
47418       *
47419       * <div>
47420       * <code>
47421       * // p5 Color object
47422       * background(color(0, 0, 255));
47423       * </code>
47424       * </div>
47425       *
47426       * @alt
47427       * canvas with darkest charcoal grey background.
47428       * canvas with yellow background.
47429       * canvas with royal blue background.
47430       * canvas with red background.
47431       * canvas with pink background.
47432       * canvas with black background.
47433       * canvas with bright green background.
47434       * canvas with soft green background.
47435       * canvas with red background.
47436       * canvas with light purple background.
47437       * canvas with blue background.
47438       */
47439
47440      /**
47441       * @method background
47442       * @param {String} colorstring color string, possible formats include: integer
47443       *                         rgb() or rgba(), percentage rgb() or rgba(),
47444       *                         3-digit hex, 6-digit hex
47445       * @param {Number} [a]         opacity of the background relative to current
47446       *                             color range (default is 0-255)
47447       * @chainable
47448       */
47449
47450      /**
47451       * @method background
47452       * @param {Number} gray   specifies a value between white and black
47453       * @param {Number} [a]
47454       * @chainable
47455       */
47456
47457      /**
47458       * @method background
47459       * @param {Number} v1     red or hue value (depending on the current color
47460       *                        mode)
47461       * @param {Number} v2     green or saturation value (depending on the current
47462       *                        color mode)
47463       * @param {Number} v3     blue or brightness value (depending on the current
47464       *                        color mode)
47465       * @param  {Number} [a]
47466       * @chainable
47467       */
47468
47469      /**
47470       * @method background
47471       * @param  {Number[]}      values  an array containing the red,green,blue &
47472       *                                 and alpha components of the color
47473       * @chainable
47474       */
47475
47476      /**
47477       * @method background
47478       * @param {p5.Image} image     image created with <a href="#/p5/loadImage">loadImage()</a> or <a href="#/p5/createImage">createImage()</a>,
47479       *                             to set as background
47480       *                             (must be same size as the sketch window)
47481       * @param  {Number}  [a]
47482       * @chainable
47483       */
47484
47485
47486      p5.prototype.background = function () {
47487        if (arguments[0] instanceof p5.Image) {
47488          this.image(arguments[0], 0, 0, this.width, this.height);
47489        } else {
47490          this._renderer.background.apply(this._renderer, arguments);
47491        }
47492
47493        return this;
47494      };
47495      /**
47496       * Clears the pixels within a buffer. This function only works on p5.Canvas
47497       * objects created with the <a href="#/p5/createCanvas">createCanvas()</a> function; it won't work with the
47498       * main display window. Unlike the main graphics context, pixels in
47499       * additional graphics areas created with <a href="#/p5/createGraphics">createGraphics()</a> can be entirely
47500       * or partially transparent. This function clears everything to make all of
47501       * the pixels 100% transparent.
47502       *
47503       * @method clear
47504       * @chainable
47505       * @example
47506       * <div>
47507       * <code>
47508       * // Clear the screen on mouse press.
47509       * function setup() {
47510       *   createCanvas(100, 100);
47511       * }
47512       *
47513       * function draw() {
47514       *   ellipse(mouseX, mouseY, 20, 20);
47515       * }
47516       *
47517       * function mousePressed() {
47518       *   clear();
47519       * }
47520       * </code>
47521       * </div>
47522       *
47523       * @alt
47524       * 20x20 white ellipses are continually drawn at mouse x and y coordinates.
47525       *
47526       */
47527
47528
47529      p5.prototype.clear = function () {
47530        this._renderer.clear();
47531
47532        return this;
47533      };
47534      /**
47535       * <a href="#/p5/colorMode">colorMode()</a> changes the way p5.js interprets color data. By default, the
47536       * parameters for <a href="#/p5/fill">fill()</a>, <a href="#/p5/stroke">stroke()</a>, <a href="#/p5/background">background()</a>, and <a href="#/p5/color">color()</a> are defined by
47537       * values between 0 and 255 using the RGB color model. This is equivalent to
47538       * setting colorMode(RGB, 255). Setting colorMode(HSB) lets you use the HSB
47539       * system instead. By default, this is colorMode(HSB, 360, 100, 100, 1). You
47540       * can also use HSL.
47541       * <br><br>
47542       * Note: existing color objects remember the mode that they were created in,
47543       * so you can change modes as you like without affecting their appearance.
47544       *
47545       *
47546       * @method colorMode
47547       * @param {Constant} mode   either RGB, HSB or HSL, corresponding to
47548       *                          Red/Green/Blue and Hue/Saturation/Brightness
47549       *                          (or Lightness)
47550       * @param {Number}  [max]  range for all values
47551       * @chainable
47552       *
47553       * @example
47554       * <div>
47555       * <code>
47556       * noStroke();
47557       * colorMode(RGB, 100);
47558       * for (let i = 0; i < 100; i++) {
47559       *   for (let j = 0; j < 100; j++) {
47560       *     stroke(i, j, 0);
47561       *     point(i, j);
47562       *   }
47563       * }
47564       * </code>
47565       * </div>
47566       *
47567       * <div>
47568       * <code>
47569       * noStroke();
47570       * colorMode(HSB, 100);
47571       * for (let i = 0; i < 100; i++) {
47572       *   for (let j = 0; j < 100; j++) {
47573       *     stroke(i, j, 100);
47574       *     point(i, j);
47575       *   }
47576       * }
47577       * </code>
47578       * </div>
47579       *
47580       * <div>
47581       * <code>
47582       * colorMode(RGB, 255);
47583       * let c = color(127, 255, 0);
47584       *
47585       * colorMode(RGB, 1);
47586       * let myColor = c._getRed();
47587       * text(myColor, 10, 10, 80, 80);
47588       * </code>
47589       * </div>
47590       *
47591       * <div>
47592       * <code>
47593       * noFill();
47594       * colorMode(RGB, 255, 255, 255, 1);
47595       * background(255);
47596       *
47597       * strokeWeight(4);
47598       * stroke(255, 0, 10, 0.3);
47599       * ellipse(40, 40, 50, 50);
47600       * ellipse(50, 50, 40, 40);
47601       * </code>
47602       * </div>
47603       *
47604       * @alt
47605       *Green to red gradient from bottom L to top R. shading originates from top left.
47606       *Rainbow gradient from left to right. Brightness increasing to white at top.
47607       *unknown image.
47608       *50x50 ellipse at middle L & 40x40 ellipse at center. Transluscent pink outlines.
47609       *
47610       */
47611
47612      /**
47613       * @method colorMode
47614       * @param {Constant} mode
47615       * @param {Number} max1     range for the red or hue depending on the
47616       *                              current color mode
47617       * @param {Number} max2     range for the green or saturation depending
47618       *                              on the current color mode
47619       * @param {Number} max3     range for the blue or brightness/lighntess
47620       *                              depending on the current color mode
47621       * @param {Number} [maxA]   range for the alpha
47622       * @chainable
47623       */
47624
47625
47626      p5.prototype.colorMode = function (mode, max1, max2, max3, maxA) {
47627        p5._validateParameters('colorMode', arguments);
47628
47629        if (mode === constants.RGB || mode === constants.HSB || mode === constants.HSL) {
47630          // Set color mode.
47631          this._colorMode = mode; // Set color maxes.
47632
47633          var maxes = this._colorMaxes[mode];
47634
47635          if (arguments.length === 2) {
47636            maxes[0] = max1; // Red
47637
47638            maxes[1] = max1; // Green
47639
47640            maxes[2] = max1; // Blue
47641
47642            maxes[3] = max1; // Alpha
47643          } else if (arguments.length === 4) {
47644            maxes[0] = max1; // Red
47645
47646            maxes[1] = max2; // Green
47647
47648            maxes[2] = max3; // Blue
47649          } else if (arguments.length === 5) {
47650            maxes[0] = max1; // Red
47651
47652            maxes[1] = max2; // Green
47653
47654            maxes[2] = max3; // Blue
47655
47656            maxes[3] = maxA; // Alpha
47657          }
47658        }
47659
47660        return this;
47661      };
47662      /**
47663       * Sets the color used to fill shapes. For example, if you run
47664       * fill(204, 102, 0), all subsequent shapes will be filled with orange. This
47665       * color is either specified in terms of the RGB or HSB color depending on
47666       * the current <a href="#/p5/colorMode">colorMode()</a>. (The default color space is RGB, with each value
47667       * in the range from 0 to 255). The alpha range by default is also 0 to 255.
47668       * <br><br>
47669       * If a single string argument is provided, RGB, RGBA and Hex CSS color strings
47670       * and all named color strings are supported. In this case, an alpha number
47671       * value as a second argument is not supported, the RGBA form should be used.
47672       * <br><br>
47673       * A p5 <a href="#/p5.Color">Color</a> object can also be provided to set the fill color.
47674       *
47675       * @method fill
47676       * @param  {Number}        v1      red or hue value relative to
47677       *                                 the current color range
47678       * @param  {Number}        v2      green or saturation value
47679       *                                 relative to the current color range
47680       * @param  {Number}        v3      blue or brightness value
47681       *                                 relative to the current color range
47682       * @param  {Number}        [alpha]
47683       * @chainable
47684       * @example
47685       * <div>
47686       * <code>
47687       * // Grayscale integer value
47688       * fill(51);
47689       * rect(20, 20, 60, 60);
47690       * </code>
47691       * </div>
47692       *
47693       * <div>
47694       * <code>
47695       * // R, G & B integer values
47696       * fill(255, 204, 0);
47697       * rect(20, 20, 60, 60);
47698       * </code>
47699       * </div>
47700       *
47701       * <div>
47702       * <code>
47703       * // H, S & B integer values
47704       * colorMode(HSB);
47705       * fill(255, 204, 100);
47706       * rect(20, 20, 60, 60);
47707       * </code>
47708       * </div>
47709       *
47710       * <div>
47711       * <code>
47712       * // Named SVG/CSS color string
47713       * fill('red');
47714       * rect(20, 20, 60, 60);
47715       * </code>
47716       * </div>
47717       *
47718       * <div>
47719       * <code>
47720       * // three-digit hexadecimal RGB notation
47721       * fill('#fae');
47722       * rect(20, 20, 60, 60);
47723       * </code>
47724       * </div>
47725       *
47726       * <div>
47727       * <code>
47728       * // six-digit hexadecimal RGB notation
47729       * fill('#222222');
47730       * rect(20, 20, 60, 60);
47731       * </code>
47732       * </div>
47733       *
47734       * <div>
47735       * <code>
47736       * // integer RGB notation
47737       * fill('rgb(0,255,0)');
47738       * rect(20, 20, 60, 60);
47739       * </code>
47740       * </div>
47741       *
47742       * <div>
47743       * <code>
47744       * // integer RGBA notation
47745       * fill('rgba(0,255,0, 0.25)');
47746       * rect(20, 20, 60, 60);
47747       * </code>
47748       * </div>
47749       *
47750       * <div>
47751       * <code>
47752       * // percentage RGB notation
47753       * fill('rgb(100%,0%,10%)');
47754       * rect(20, 20, 60, 60);
47755       * </code>
47756       * </div>
47757       *
47758       * <div>
47759       * <code>
47760       * // percentage RGBA notation
47761       * fill('rgba(100%,0%,100%,0.5)');
47762       * rect(20, 20, 60, 60);
47763       * </code>
47764       * </div>
47765       *
47766       * <div>
47767       * <code>
47768       * // p5 Color object
47769       * fill(color(0, 0, 255));
47770       * rect(20, 20, 60, 60);
47771       * </code>
47772       * </div>
47773       * @alt
47774       * 60x60 dark charcoal grey rect with black outline in center of canvas.
47775       * 60x60 yellow rect with black outline in center of canvas.
47776       * 60x60 royal blue rect with black outline in center of canvas.
47777       * 60x60 red rect with black outline in center of canvas.
47778       * 60x60 pink rect with black outline in center of canvas.
47779       * 60x60 black rect with black outline in center of canvas.
47780       * 60x60 light green rect with black outline in center of canvas.
47781       * 60x60 soft green rect with black outline in center of canvas.
47782       * 60x60 red rect with black outline in center of canvas.
47783       * 60x60 dark fushcia rect with black outline in center of canvas.
47784       * 60x60 blue rect with black outline in center of canvas.
47785       */
47786
47787      /**
47788       * @method fill
47789       * @param  {String}        value   a color string
47790       * @chainable
47791       */
47792
47793      /**
47794       * @method fill
47795       * @param  {Number}        gray   a gray value
47796       * @param  {Number}        [alpha]
47797       * @chainable
47798       */
47799
47800      /**
47801       * @method fill
47802       * @param  {Number[]}      values  an array containing the red,green,blue &
47803       *                                 and alpha components of the color
47804       * @chainable
47805       */
47806
47807      /**
47808       * @method fill
47809       * @param  {p5.Color}      color   the fill color
47810       * @chainable
47811       */
47812
47813
47814      p5.prototype.fill = function () {
47815        this._renderer._setProperty('_fillSet', true);
47816
47817        this._renderer._setProperty('_doFill', true);
47818
47819        this._renderer.fill.apply(this._renderer, arguments);
47820
47821        return this;
47822      };
47823      /**
47824       * Disables filling geometry. If both <a href="#/p5/noStroke">noStroke()</a> and <a href="#/p5/noFill">noFill()</a> are called,
47825       * nothing will be drawn to the screen.
47826       *
47827       * @method noFill
47828       * @chainable
47829       * @example
47830       * <div>
47831       * <code>
47832       * rect(15, 10, 55, 55);
47833       * noFill();
47834       * rect(20, 20, 60, 60);
47835       * </code>
47836       * </div>
47837       *
47838       * <div modernizr='webgl'>
47839       * <code>
47840       * function setup() {
47841       *   createCanvas(100, 100, WEBGL);
47842       * }
47843       *
47844       * function draw() {
47845       *   background(0);
47846       *   noFill();
47847       *   stroke(100, 100, 240);
47848       *   rotateX(frameCount * 0.01);
47849       *   rotateY(frameCount * 0.01);
47850       *   box(45, 45, 45);
47851       * }
47852       * </code>
47853       * </div>
47854       *
47855       * @alt
47856       * white rect top middle and noFill rect center. Both 60x60 with black outlines.
47857       * black canvas with purple cube wireframe spinning
47858       */
47859
47860
47861      p5.prototype.noFill = function () {
47862        this._renderer._setProperty('_doFill', false);
47863
47864        return this;
47865      };
47866      /**
47867       * Disables drawing the stroke (outline). If both <a href="#/p5/noStroke">noStroke()</a> and <a href="#/p5/noFill">noFill()</a>
47868       * are called, nothing will be drawn to the screen.
47869       *
47870       * @method noStroke
47871       * @chainable
47872       * @example
47873       * <div>
47874       * <code>
47875       * noStroke();
47876       * rect(20, 20, 60, 60);
47877       * </code>
47878       * </div>
47879       *
47880       * <div modernizr='webgl'>
47881       * <code>
47882       * function setup() {
47883       *   createCanvas(100, 100, WEBGL);
47884       * }
47885       *
47886       * function draw() {
47887       *   background(0);
47888       *   noStroke();
47889       *   fill(240, 150, 150);
47890       *   rotateX(frameCount * 0.01);
47891       *   rotateY(frameCount * 0.01);
47892       *   box(45, 45, 45);
47893       * }
47894       * </code>
47895       * </div>
47896       *
47897       * @alt
47898       * 60x60 white rect at center. no outline.
47899       * black canvas with pink cube spinning
47900       */
47901
47902
47903      p5.prototype.noStroke = function () {
47904        this._renderer._setProperty('_doStroke', false);
47905
47906        return this;
47907      };
47908      /**
47909       * Sets the color used to draw lines and borders around shapes. This color
47910       * is either specified in terms of the RGB or HSB color depending on the
47911       * current <a href="#/p5/colorMode">colorMode()</a> (the default color space is RGB, with each value in
47912       * the range from 0 to 255). The alpha range by default is also 0 to 255.
47913       * <br><br>
47914       * If a single string argument is provided, RGB, RGBA and Hex CSS color
47915       * strings and all named color strings are supported. In this case, an alpha
47916       * number value as a second argument is not supported, the RGBA form should be
47917       * used.
47918       * <br><br>
47919       * A p5 <a href="#/p5.Color">Color</a> object can also be provided to set the stroke color.
47920       *
47921       *
47922       * @method stroke
47923       * @param  {Number}        v1      red or hue value relative to
47924       *                                 the current color range
47925       * @param  {Number}        v2      green or saturation value
47926       *                                 relative to the current color range
47927       * @param  {Number}        v3      blue or brightness value
47928       *                                 relative to the current color range
47929       * @param  {Number}        [alpha]
47930       * @chainable
47931       *
47932       * @example
47933       * <div>
47934       * <code>
47935       * // Grayscale integer value
47936       * strokeWeight(4);
47937       * stroke(51);
47938       * rect(20, 20, 60, 60);
47939       * </code>
47940       * </div>
47941       *
47942       * <div>
47943       * <code>
47944       * // R, G & B integer values
47945       * stroke(255, 204, 0);
47946       * strokeWeight(4);
47947       * rect(20, 20, 60, 60);
47948       * </code>
47949       * </div>
47950       *
47951       * <div>
47952       * <code>
47953       * // H, S & B integer values
47954       * colorMode(HSB);
47955       * strokeWeight(4);
47956       * stroke(255, 204, 100);
47957       * rect(20, 20, 60, 60);
47958       * </code>
47959       * </div>
47960       *
47961       * <div>
47962       * <code>
47963       * // Named SVG/CSS color string
47964       * stroke('red');
47965       * strokeWeight(4);
47966       * rect(20, 20, 60, 60);
47967       * </code>
47968       * </div>
47969       *
47970       * <div>
47971       * <code>
47972       * // three-digit hexadecimal RGB notation
47973       * stroke('#fae');
47974       * strokeWeight(4);
47975       * rect(20, 20, 60, 60);
47976       * </code>
47977       * </div>
47978       *
47979       * <div>
47980       * <code>
47981       * // six-digit hexadecimal RGB notation
47982       * stroke('#222222');
47983       * strokeWeight(4);
47984       * rect(20, 20, 60, 60);
47985       * </code>
47986       * </div>
47987       *
47988       * <div>
47989       * <code>
47990       * // integer RGB notation
47991       * stroke('rgb(0,255,0)');
47992       * strokeWeight(4);
47993       * rect(20, 20, 60, 60);
47994       * </code>
47995       * </div>
47996       *
47997       * <div>
47998       * <code>
47999       * // integer RGBA notation
48000       * stroke('rgba(0,255,0,0.25)');
48001       * strokeWeight(4);
48002       * rect(20, 20, 60, 60);
48003       * </code>
48004       * </div>
48005       *
48006       * <div>
48007       * <code>
48008       * // percentage RGB notation
48009       * stroke('rgb(100%,0%,10%)');
48010       * strokeWeight(4);
48011       * rect(20, 20, 60, 60);
48012       * </code>
48013       * </div>
48014       *
48015       * <div>
48016       * <code>
48017       * // percentage RGBA notation
48018       * stroke('rgba(100%,0%,100%,0.5)');
48019       * strokeWeight(4);
48020       * rect(20, 20, 60, 60);
48021       * </code>
48022       * </div>
48023       *
48024       * <div>
48025       * <code>
48026       * // p5 Color object
48027       * stroke(color(0, 0, 255));
48028       * strokeWeight(4);
48029       * rect(20, 20, 60, 60);
48030       * </code>
48031       * </div>
48032       *
48033       * @alt
48034       * 60x60 white rect at center. Dark charcoal grey outline.
48035       * 60x60 white rect at center. Yellow outline.
48036       * 60x60 white rect at center. Royal blue outline.
48037       * 60x60 white rect at center. Red outline.
48038       * 60x60 white rect at center. Pink outline.
48039       * 60x60 white rect at center. Black outline.
48040       * 60x60 white rect at center. Bright green outline.
48041       * 60x60 white rect at center. Soft green outline.
48042       * 60x60 white rect at center. Red outline.
48043       * 60x60 white rect at center. Dark fushcia outline.
48044       * 60x60 white rect at center. Blue outline.
48045       */
48046
48047      /**
48048       * @method stroke
48049       * @param  {String}        value   a color string
48050       * @chainable
48051       */
48052
48053      /**
48054       * @method stroke
48055       * @param  {Number}        gray   a gray value
48056       * @param  {Number}        [alpha]
48057       * @chainable
48058       */
48059
48060      /**
48061       * @method stroke
48062       * @param  {Number[]}      values  an array containing the red,green,blue &
48063       *                                 and alpha components of the color
48064       * @chainable
48065       */
48066
48067      /**
48068       * @method stroke
48069       * @param  {p5.Color}      color   the stroke color
48070       * @chainable
48071       */
48072
48073
48074      p5.prototype.stroke = function () {
48075        this._renderer._setProperty('_strokeSet', true);
48076
48077        this._renderer._setProperty('_doStroke', true);
48078
48079        this._renderer.stroke.apply(this._renderer, arguments);
48080
48081        return this;
48082      };
48083
48084      module.exports = p5;
48085    }, {
48086      "../core/constants": 18,
48087      "../core/main": 24,
48088      "./p5.Color": 16
48089    }],
48090    18: [function (_dereq_, module, exports) {
48091      /**
48092       * @module Constants
48093       * @submodule Constants
48094       * @for p5
48095       */
48096      'use strict';
48097
48098      var PI = Math.PI;
48099      module.exports = {
48100        // GRAPHICS RENDERER
48101
48102        /**
48103         * @property {String} P2D
48104         * @final
48105         */
48106        P2D: 'p2d',
48107
48108        /**
48109         * @property {String} WEBGL
48110         * @final
48111         */
48112        WEBGL: 'webgl',
48113        // ENVIRONMENT
48114
48115        /**
48116         * @property {String} ARROW
48117         * @final
48118         */
48119        ARROW: 'default',
48120
48121        /**
48122         * @property {String} CROSS
48123         * @final
48124         */
48125        CROSS: 'crosshair',
48126
48127        /**
48128         * @property {String} HAND
48129         * @final
48130         */
48131        HAND: 'pointer',
48132
48133        /**
48134         * @property {String} MOVE
48135         * @final
48136         */
48137        MOVE: 'move',
48138
48139        /**
48140         * @property {String} TEXT
48141         * @final
48142         */
48143        TEXT: 'text',
48144
48145        /**
48146         * @property {String} WAIT
48147         * @final
48148         */
48149        WAIT: 'wait',
48150        // TRIGONOMETRY
48151
48152        /**
48153         * HALF_PI is a mathematical constant with the value
48154         * 1.57079632679489661923. It is half the ratio of the
48155         * circumference of a circle to its diameter. It is useful in
48156         * combination with the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
48157         *
48158         * @property {Number} HALF_PI
48159         * @final
48160         *
48161         * @example
48162         * <div><code>
48163         * arc(50, 50, 80, 80, 0, HALF_PI);
48164         * </code></div>
48165         *
48166         * @alt
48167         * 80x80 white quarter-circle with curve toward bottom right of canvas.
48168         *
48169         */
48170        HALF_PI: PI / 2,
48171
48172        /**
48173         * PI is a mathematical constant with the value
48174         * 3.14159265358979323846. It is the ratio of the circumference
48175         * of a circle to its diameter. It is useful in combination with
48176         * the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
48177         *
48178         * @property {Number} PI
48179         * @final
48180         *
48181         * @example
48182         * <div><code>
48183         * arc(50, 50, 80, 80, 0, PI);
48184         * </code></div>
48185         *
48186         * @alt
48187         * white half-circle with curve toward bottom of canvas.
48188         *
48189         */
48190        PI: PI,
48191
48192        /**
48193         * QUARTER_PI is a mathematical constant with the value 0.7853982.
48194         * It is one quarter the ratio of the circumference of a circle to
48195         * its diameter. It is useful in combination with the trigonometric
48196         * functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
48197         *
48198         * @property {Number} QUARTER_PI
48199         * @final
48200         *
48201         * @example
48202         * <div><code>
48203         * arc(50, 50, 80, 80, 0, QUARTER_PI);
48204         * </code></div>
48205         *
48206         * @alt
48207         * white eighth-circle rotated about 40 degrees with curve bottom right canvas.
48208         *
48209         */
48210        QUARTER_PI: PI / 4,
48211
48212        /**
48213         * TAU is an alias for TWO_PI, a mathematical constant with the
48214         * value 6.28318530717958647693. It is twice the ratio of the
48215         * circumference of a circle to its diameter. It is useful in
48216         * combination with the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
48217         *
48218         * @property {Number} TAU
48219         * @final
48220         *
48221         * @example
48222         * <div><code>
48223         * arc(50, 50, 80, 80, 0, TAU);
48224         * </code></div>
48225         *
48226         * @alt
48227         * 80x80 white ellipse shape in center of canvas.
48228         *
48229         */
48230        TAU: PI * 2,
48231
48232        /**
48233         * TWO_PI is a mathematical constant with the value
48234         * 6.28318530717958647693. It is twice the ratio of the
48235         * circumference of a circle to its diameter. It is useful in
48236         * combination with the trigonometric functions <a href="#/p5/sin">sin()</a> and <a href="#/p5/cos">cos()</a>.
48237         *
48238         * @property {Number} TWO_PI
48239         * @final
48240         *
48241         * @example
48242         * <div><code>
48243         * arc(50, 50, 80, 80, 0, TWO_PI);
48244         * </code></div>
48245         *
48246         * @alt
48247         * 80x80 white ellipse shape in center of canvas.
48248         *
48249         */
48250        TWO_PI: PI * 2,
48251
48252        /**
48253         * Constant to be used with <a href="#/p5/angleMode">angleMode()</a> function, to set the mode which
48254         * p5.js interprates and calculates angles (either DEGREES or RADIANS).
48255         * @property {String} DEGREES
48256         * @final
48257         *
48258         * @example
48259         * <div class='norender'><code>
48260         * function setup() {
48261         *   angleMode(DEGREES);
48262         * }
48263         * </code></div>
48264         */
48265        DEGREES: 'degrees',
48266
48267        /**
48268         * Constant to be used with <a href="#/p5/angleMode">angleMode()</a> function, to set the mode which
48269         * p5.js interprates and calculates angles (either RADIANS or DEGREES).
48270         * @property {String} RADIANS
48271         * @final
48272         *
48273         * @example
48274         * <div class='norender'><code>
48275         * function setup() {
48276         *   angleMode(RADIANS);
48277         * }
48278         * </code></div>
48279         */
48280        RADIANS: 'radians',
48281        DEG_TO_RAD: PI / 180.0,
48282        RAD_TO_DEG: 180.0 / PI,
48283        // SHAPE
48284
48285        /**
48286         * @property {String} CORNER
48287         * @final
48288         */
48289        CORNER: 'corner',
48290
48291        /**
48292         * @property {String} CORNERS
48293         * @final
48294         */
48295        CORNERS: 'corners',
48296
48297        /**
48298         * @property {String} RADIUS
48299         * @final
48300         */
48301        RADIUS: 'radius',
48302
48303        /**
48304         * @property {String} RIGHT
48305         * @final
48306         */
48307        RIGHT: 'right',
48308
48309        /**
48310         * @property {String} LEFT
48311         * @final
48312         */
48313        LEFT: 'left',
48314
48315        /**
48316         * @property {String} CENTER
48317         * @final
48318         */
48319        CENTER: 'center',
48320
48321        /**
48322         * @property {String} TOP
48323         * @final
48324         */
48325        TOP: 'top',
48326
48327        /**
48328         * @property {String} BOTTOM
48329         * @final
48330         */
48331        BOTTOM: 'bottom',
48332
48333        /**
48334         * @property {String} BASELINE
48335         * @final
48336         * @default alphabetic
48337         */
48338        BASELINE: 'alphabetic',
48339
48340        /**
48341         * @property {Number} POINTS
48342         * @final
48343         * @default 0x0000
48344         */
48345        POINTS: 0x0000,
48346
48347        /**
48348         * @property {Number} LINES
48349         * @final
48350         * @default 0x0001
48351         */
48352        LINES: 0x0001,
48353
48354        /**
48355         * @property {Number} LINE_STRIP
48356         * @final
48357         * @default 0x0003
48358         */
48359        LINE_STRIP: 0x0003,
48360
48361        /**
48362         * @property {Number} LINE_LOOP
48363         * @final
48364         * @default 0x0002
48365         */
48366        LINE_LOOP: 0x0002,
48367
48368        /**
48369         * @property {Number} TRIANGLES
48370         * @final
48371         * @default 0x0004
48372         */
48373        TRIANGLES: 0x0004,
48374
48375        /**
48376         * @property {Number} TRIANGLE_FAN
48377         * @final
48378         * @default 0x0006
48379         */
48380        TRIANGLE_FAN: 0x0006,
48381
48382        /**
48383         * @property {Number} TRIANGLE_STRIP
48384         * @final
48385         * @default 0x0005
48386         */
48387        TRIANGLE_STRIP: 0x0005,
48388
48389        /**
48390         * @property {String} QUADS
48391         * @final
48392         */
48393        QUADS: 'quads',
48394
48395        /**
48396         * @property {String} QUAD_STRIP
48397         * @final
48398         * @default quad_strip
48399         */
48400        QUAD_STRIP: 'quad_strip',
48401
48402        /**
48403         * @property {String} CLOSE
48404         * @final
48405         */
48406        CLOSE: 'close',
48407
48408        /**
48409         * @property {String} OPEN
48410         * @final
48411         */
48412        OPEN: 'open',
48413
48414        /**
48415         * @property {String} CHORD
48416         * @final
48417         */
48418        CHORD: 'chord',
48419
48420        /**
48421         * @property {String} PIE
48422         * @final
48423         */
48424        PIE: 'pie',
48425
48426        /**
48427         * @property {String} PROJECT
48428         * @final
48429         * @default square
48430         */
48431        PROJECT: 'square',
48432        // PEND: careful this is counterintuitive
48433
48434        /**
48435         * @property {String} SQUARE
48436         * @final
48437         * @default butt
48438         */
48439        SQUARE: 'butt',
48440
48441        /**
48442         * @property {String} ROUND
48443         * @final
48444         */
48445        ROUND: 'round',
48446
48447        /**
48448         * @property {String} BEVEL
48449         * @final
48450         */
48451        BEVEL: 'bevel',
48452
48453        /**
48454         * @property {String} MITER
48455         * @final
48456         */
48457        MITER: 'miter',
48458        // COLOR
48459
48460        /**
48461         * @property {String} RGB
48462         * @final
48463         */
48464        RGB: 'rgb',
48465
48466        /**
48467         * @property {String} HSB
48468         * @final
48469         */
48470        HSB: 'hsb',
48471
48472        /**
48473         * @property {String} HSL
48474         * @final
48475         */
48476        HSL: 'hsl',
48477        // DOM EXTENSION
48478
48479        /**
48480         * @property {String} AUTO
48481         * @final
48482         */
48483        AUTO: 'auto',
48484        // INPUT
48485        ALT: 18,
48486        BACKSPACE: 8,
48487        CONTROL: 17,
48488        DELETE: 46,
48489        DOWN_ARROW: 40,
48490        ENTER: 13,
48491        ESCAPE: 27,
48492        LEFT_ARROW: 37,
48493        OPTION: 18,
48494        RETURN: 13,
48495        RIGHT_ARROW: 39,
48496        SHIFT: 16,
48497        TAB: 9,
48498        UP_ARROW: 38,
48499        // RENDERING
48500
48501        /**
48502         * @property {String} BLEND
48503         * @final
48504         * @default source-over
48505         */
48506        BLEND: 'source-over',
48507
48508        /**
48509         * @property {String} ADD
48510         * @final
48511         * @default lighter
48512         */
48513        ADD: 'lighter',
48514        //ADD: 'add', //
48515        //SUBTRACT: 'subtract', //
48516
48517        /**
48518         * @property {String} DARKEST
48519         * @final
48520         */
48521        DARKEST: 'darken',
48522
48523        /**
48524         * @property {String} LIGHTEST
48525         * @final
48526         * @default lighten
48527         */
48528        LIGHTEST: 'lighten',
48529
48530        /**
48531         * @property {String} DIFFERENCE
48532         * @final
48533         */
48534        DIFFERENCE: 'difference',
48535
48536        /**
48537         * @property {String} EXCLUSION
48538         * @final
48539         */
48540        EXCLUSION: 'exclusion',
48541
48542        /**
48543         * @property {String} MULTIPLY
48544         * @final
48545         */
48546        MULTIPLY: 'multiply',
48547
48548        /**
48549         * @property {String} SCREEN
48550         * @final
48551         */
48552        SCREEN: 'screen',
48553
48554        /**
48555         * @property {String} REPLACE
48556         * @final
48557         * @default copy
48558         */
48559        REPLACE: 'copy',
48560
48561        /**
48562         * @property {String} OVERLAY
48563         * @final
48564         */
48565        OVERLAY: 'overlay',
48566
48567        /**
48568         * @property {String} HARD_LIGHT
48569         * @final
48570         */
48571        HARD_LIGHT: 'hard-light',
48572
48573        /**
48574         * @property {String} SOFT_LIGHT
48575         * @final
48576         */
48577        SOFT_LIGHT: 'soft-light',
48578
48579        /**
48580         * @property {String} DODGE
48581         * @final
48582         * @default color-dodge
48583         */
48584        DODGE: 'color-dodge',
48585
48586        /**
48587         * @property {String} BURN
48588         * @final
48589         * @default color-burn
48590         */
48591        BURN: 'color-burn',
48592        // FILTERS
48593
48594        /**
48595         * @property {String} THRESHOLD
48596         * @final
48597         */
48598        THRESHOLD: 'threshold',
48599
48600        /**
48601         * @property {String} GRAY
48602         * @final
48603         */
48604        GRAY: 'gray',
48605
48606        /**
48607         * @property {String} OPAQUE
48608         * @final
48609         */
48610        OPAQUE: 'opaque',
48611
48612        /**
48613         * @property {String} INVERT
48614         * @final
48615         */
48616        INVERT: 'invert',
48617
48618        /**
48619         * @property {String} POSTERIZE
48620         * @final
48621         */
48622        POSTERIZE: 'posterize',
48623
48624        /**
48625         * @property {String} DILATE
48626         * @final
48627         */
48628        DILATE: 'dilate',
48629
48630        /**
48631         * @property {String} ERODE
48632         * @final
48633         */
48634        ERODE: 'erode',
48635
48636        /**
48637         * @property {String} BLUR
48638         * @final
48639         */
48640        BLUR: 'blur',
48641        // TYPOGRAPHY
48642
48643        /**
48644         * @property {String} NORMAL
48645         * @final
48646         */
48647        NORMAL: 'normal',
48648
48649        /**
48650         * @property {String} ITALIC
48651         * @final
48652         */
48653        ITALIC: 'italic',
48654
48655        /**
48656         * @property {String} BOLD
48657         * @final
48658         */
48659        BOLD: 'bold',
48660
48661        /**
48662         * @property {String} BOLDITALIC
48663         * @final
48664         */
48665        BOLDITALIC: 'bold italic',
48666        // TYPOGRAPHY-INTERNAL
48667        _DEFAULT_TEXT_FILL: '#000000',
48668        _DEFAULT_LEADMULT: 1.25,
48669        _CTX_MIDDLE: 'middle',
48670        // VERTICES
48671        LINEAR: 'linear',
48672        QUADRATIC: 'quadratic',
48673        BEZIER: 'bezier',
48674        CURVE: 'curve',
48675        // WEBGL DRAWMODES
48676        STROKE: 'stroke',
48677        FILL: 'fill',
48678        TEXTURE: 'texture',
48679        IMMEDIATE: 'immediate',
48680        // WEBGL TEXTURE MODE
48681        // NORMAL already exists for typography
48682        IMAGE: 'image',
48683        // WEBGL TEXTURE WRAP AND FILTERING
48684        // LINEAR already exists above
48685        NEAREST: 'nearest',
48686        REPEAT: 'repeat',
48687        CLAMP: 'clamp',
48688        MIRROR: 'mirror',
48689        // DEVICE-ORIENTATION
48690
48691        /**
48692         * @property {String} LANDSCAPE
48693         * @final
48694         */
48695        LANDSCAPE: 'landscape',
48696
48697        /**
48698         * @property {String} PORTRAIT
48699         * @final
48700         */
48701        PORTRAIT: 'portrait',
48702        // DEFAULTS
48703        _DEFAULT_STROKE: '#000000',
48704        _DEFAULT_FILL: '#FFFFFF',
48705
48706        /**
48707         * @property {String} GRID
48708         * @final
48709         */
48710        GRID: 'grid',
48711
48712        /**
48713         * @property {String} AXES
48714         * @final
48715         */
48716        AXES: 'axes'
48717      };
48718    }, {}],
48719    19: [function (_dereq_, module, exports) {
48720      /**
48721       * @module Environment
48722       * @submodule Environment
48723       * @for p5
48724       * @requires core
48725       * @requires constants
48726       */
48727      'use strict';
48728
48729      var p5 = _dereq_('./main');
48730
48731      var C = _dereq_('./constants');
48732
48733      var standardCursors = [C.ARROW, C.CROSS, C.HAND, C.MOVE, C.TEXT, C.WAIT];
48734      p5.prototype._frameRate = 0;
48735      p5.prototype._lastFrameTime = window.performance.now();
48736      p5.prototype._targetFrameRate = 60;
48737      var _windowPrint = window.print;
48738      /**
48739       * The <a href="#/p5/print">print()</a> function writes to the console area of your browser.
48740       * This function is often helpful for looking at the data a program is
48741       * producing. This function creates a new line of text for each call to
48742       * the function. Individual elements can be
48743       * separated with quotes ("") and joined with the addition operator (+).
48744       *
48745       * Note that calling print() without any arguments invokes the window.print()
48746       * function which opens the browser's print dialog. To print a blank line
48747       * to console you can write print('\n').
48748       *
48749       * @method print
48750       * @param {Any} contents any combination of Number, String, Object, Boolean,
48751       *                       Array to print
48752       * @example
48753       * <div><code class='norender'>
48754       * let x = 10;
48755       * print('The value of x is ' + x);
48756       * // prints "The value of x is 10"
48757       * </code></div>
48758       * @alt
48759       * default grey canvas
48760       */
48761
48762      p5.prototype.print = function () {
48763        if (!arguments.length) {
48764          _windowPrint();
48765        } else {
48766          console.log.apply(console, arguments);
48767        }
48768      };
48769      /**
48770       * The system variable <a href="#/p5/frameCount">frameCount</a> contains the number of frames that have
48771       * been displayed since the program started. Inside <a href="#/p5/setup">setup()</a> the value is 0,
48772       * after the first iteration of draw it is 1, etc.
48773       *
48774       * @property {Integer} frameCount
48775       * @readOnly
48776       * @example
48777       *   <div><code>
48778       * function setup() {
48779       *   frameRate(30);
48780       *   textSize(30);
48781       *   textAlign(CENTER);
48782       * }
48783       *
48784       * function draw() {
48785       *   background(200);
48786       *   text(frameCount, width / 2, height / 2);
48787       * }
48788      </code></div>
48789       *
48790       * @alt
48791       * numbers rapidly counting upward with frame count set to 30.
48792       *
48793       */
48794
48795
48796      p5.prototype.frameCount = 0;
48797      /**
48798       * Confirms if the window a p5.js program is in is "focused," meaning that
48799       * the sketch will accept mouse or keyboard input. This variable is
48800       * "true" if the window is focused and "false" if not.
48801       *
48802       * @property {Boolean}
48802 focused
48803       * @readOnly
48804       * @example
48805       * <div><code>
48806       * // To demonstrate, put two windows side by side.
48807       * // Click on the window that the p5 sketch isn't in!
48808       * function draw() {
48809       *   background(200);
48810       *   noStroke();
48811       *   fill(0, 200, 0);
48812       *   ellipse(25, 25, 50, 50);
48813       *
48814       *   if (!focused) {
48815          // or "if (focused === false)"
48816       *     stroke(200, 0, 0);
48817       *     line(0, 0, 100, 100);
48818       *     line(100, 0, 0, 100);
48819       *   }
48820       * }
48821       * </code></div>
48822       *
48823       * @alt
48824       * green 50x50 ellipse at top left. Red X covers canvas when page focus changes
48825       *
48826       */
48827
48828      p5.prototype.focused = document.hasFocus();
48829      /**
48830       * Sets the cursor to a predefined symbol or an image, or makes it visible
48831       * if already hidden. If you are trying to set an image as the cursor, the
48832       * recommended size is 16x16 or 32x32 pixels. The values for parameters x and y
48833       * must be less than the dimensions of the image.
48834       *
48835       * @method cursor
48836       * @param {String|Constant} type Built-In: either ARROW, CROSS, HAND, MOVE, TEXT and WAIT
48837       *                               Native CSS properties: 'grab', 'progress', 'cell' etc.
48838       *                               External: path for cursor's images
48839       *                               (Allowed File extensions: .cur, .gif, .jpg, .jpeg, .png)
48840       *                               For more information on Native CSS cursors and url visit:
48841       *                               https://developer.mozilla.org/en-US/docs/Web/CSS/cursor
48842       * @param {Number}          [x]  the horizontal active spot of the cursor (must be less than 32)
48843       * @param {Number}          [y]  the vertical active spot of the cursor (must be less than 32)
48844       * @example
48845       * <div><code>
48846       * // Move the mouse across the quadrants
48847       * // to see the cursor change
48848       * function draw() {
48849       *   line(width / 2, 0, width / 2, height);
48850       *   line(0, height / 2, width, height / 2);
48851       *   if (mouseX < 50 && mouseY < 50) {
48852       *     cursor(CROSS);
48853       *   } else if (mouseX > 50 && mouseY < 50) {
48854       *     cursor('progress');
48855       *   } else if (mouseX > 50 && mouseY > 50) {
48856       *     cursor('https://s3.amazonaws.com/mupublicdata/cursor.cur');
48857       *   } else {
48858       *     cursor('grab');
48859       *   }
48860       * }
48861       * </code></div>
48862       *
48863       * @alt
48864       * canvas is divided into four quadrants. cursor on first is a cross, second is a progress,
48865       * third is a custom cursor using path to the cursor and fourth is a grab.
48866       *
48867       */
48868
48869      p5.prototype.cursor = function (type, x, y) {
48870        var cursor = 'auto';
48871        var canvas = this._curElement.elt;
48872
48873        if (standardCursors.indexOf(type) > -1) {
48874          // Standard css cursor
48875          cursor = type;
48876        } else if (typeof type === 'string') {
48877          var coords = '';
48878
48879          if (x && y && typeof x === 'number' && typeof y === 'number') {
48880            // Note that x and y values must be unit-less positive integers < 32
48881            // https://developer.mozilla.org/en-US/docs/Web/CSS/cursor
48882            coords = x + ' ' + y;
48883          }
48884
48885          if (type.substring(0, 7) === 'http://' || type.substring(0, 8) === 'https://') {
48886            // Image (absolute url)
48887            cursor = 'url(' + type + ') ' + coords + ', auto';
48888          } else if (/\.(cur|jpg|jpeg|gif|png|CUR|JPG|JPEG|GIF|PNG)$/.test(type)) {
48889            // Image file (relative path) - Separated for performance reasons
48890            cursor = 'url(' + type + ') ' + coords + ', auto';
48891          } else {
48892            // Any valid string for the css cursor property
48893            cursor = type;
48894          }
48895        }
48896
48897        canvas.style.cursor = cursor;
48898      };
48899      /**
48900       * Specifies the number of frames to be displayed every second. For example,
48901       * the function call frameRate(30) will attempt to refresh 30 times a second.
48902       * If the processor is not fast enough to maintain the specified rate, the
48903       * frame rate will not be achieved. Setting the frame rate within <a href="#/p5/setup">setup()</a> is
48904       * recommended. The default frame rate is based on the frame rate of the display
48905       * (here also called "refresh rate"), which is set to 60 frames per second on most
48906       * computers. A frame rate of 24 frames per second (usual for movies) or above
48907       * will be enough for smooth animations
48908       * This is the same as setFrameRate(val).
48909       * <br><br>
48910       * Calling <a href="#/p5/frameRate">frameRate()</a> with no arguments returns the current framerate. The
48911       * draw function must run at least once before it will return a value. This
48912       * is the same as <a href="#/p5/getFrameRate">getFrameRate()</a>.
48913       * <br><br>
48914       * Calling <a href="#/p5/frameRate">frameRate()</a> with arguments that are not of the type numbers
48915       * or are non positive also returns current framerate.
48916       *
48917       * @method frameRate
48918       * @param  {Number} fps number of frames to be displayed every second
48919       * @chainable
48920       *
48921       * @example
48922       *
48923       * <div><code>
48924       * let rectX = 0;
48925       * let fr = 30; //starting FPS
48926       * let clr;
48927       *
48928       * function setup() {
48929       *   background(200);
48930       *   frameRate(fr); // Attempt to refresh at starting FPS
48931       *   clr = color(255, 0, 0);
48932       * }
48933       *
48934       * function draw() {
48935       *   background(200);
48936       *   rectX = rectX += 1; // Move Rectangle
48937       *
48938       *   if (rectX >= width) {
48939          // If you go off screen.
48940       *     if (fr === 30) {
48941       *       clr = color(0, 0, 255);
48942       *       fr = 10;
48943       *       frameRate(fr); // make frameRate 10 FPS
48944       *     } else {
48945       *       clr = color(255, 0, 0);
48946       *       fr = 30;
48947       *       frameRate(fr); // make frameRate 30 FPS
48948       *     }
48949       *     rectX = 0;
48950       *   }
48951       *   fill(clr);
48952       *   rect(rectX, 40, 20, 20);
48953       * }
48954       * </code></div>
48955       *
48956       * @alt
48957       * blue rect moves left to right, followed by red rect moving faster. Loops.
48958       *
48959       */
48960
48961      /**
48962       * @method frameRate
48963       * @return {Number}       current frameRate
48964       */
48965
48966
48967      p5.prototype.frameRate = function (fps) {
48968        p5._validateParameters('frameRate', arguments);
48969
48970        if (typeof fps !== 'number' || fps < 0) {
48971          return this._frameRate;
48972        } else {
48973          this._setProperty('_targetFrameRate', fps);
48974
48975          return this;
48976        }
48977      };
48978      /**
48979       * Returns the current framerate.
48980       *
48981       * @private
48982       * @return {Number} current frameRate
48983       */
48984
48985
48986      p5.prototype.getFrameRate = function () {
48987        return this.frameRate();
48988      };
48989      /**
48990       * Specifies the number of frames to be displayed every second. For example,
48991       * the function call frameRate(30) will attempt to refresh 30 times a second.
48992       * If the processor is not fast enough to maintain the specified rate, the
48993       * frame rate will not be achieved. Setting the frame rate within <a href="#/p5/setup">setup()</a> is
48994       * recommended. The default rate is 60 frames per second.
48995       *
48996       * Calling <a href="#/p5/frameRate">frameRate()</a> with no arguments returns the current framerate.
48997       *
48998       * @private
48999       * @param {Number} [fps] number of frames to be displayed every second
49000       */
49001
49002
49003      p5.prototype.setFrameRate = function (fps) {
49004        return this.frameRate(fps);
49005      };
49006      /**
49007       * Hides the cursor from view.
49008       *
49009       * @method noCursor
49010       * @example
49011       * <div><code>
49012       * function setup() {
49013       *   noCursor();
49014       * }
49015       *
49016       * function draw() {
49017       *   background(200);
49018       *   ellipse(mouseX, mouseY, 10, 10);
49019       * }
49020       * </code></div>
49021       *
49022       *
49023       * @alt
49024       * cursor becomes 10x 10 white ellipse the moves with mouse x and y.
49025       *
49026       */
49027
49028
49029      p5.prototype.noCursor = function () {
49030        this._curElement.elt.style.cursor = 'none';
49031      };
49032      /**
49033       * System variable that stores the width of the screen display according to The
49034       * default <a href="#/p5/pixelDensity">pixelDensity</a>. This is used to run a
49035       * full-screen program on any display size. To return actual screen size,
49036       * multiply this by pixelDensity.
49037       *
49038       * @property {Number} displayWidth
49039       * @readOnly
49040       * @example
49041       * <div class="norender"><code>
49042       * createCanvas(displayWidth, displayHeight);
49043       * </code></div>
49044       *
49045       * @alt
49046       * cursor becomes 10x 10 white ellipse the moves with mouse x and y.
49047       *
49048       */
49049
49050
49051      p5.prototype.displayWidth = screen.width;
49052      /**
49053       * System variable that stores the height of the screen display according to The
49054       * default <a href="#/p5/pixelDensity">pixelDensity</a>. This is used to run a
49055       * full-screen program on any display size. To return actual screen size,
49056       * multiply this by pixelDensity.
49057       *
49058       * @property {Number} displayHeight
49059       * @readOnly
49060       * @example
49061       * <div class="norender"><code>
49062       * createCanvas(displayWidth, displayHeight);
49063       * </code></div>
49064       *
49065       * @alt
49066       * no display.
49067       *
49068       */
49069
49070      p5.prototype.displayHeight = screen.height;
49071      /**
49072       * System variable that stores the width of the inner window, it maps to
49073       * window.innerWidth.
49074       *
49075       * @property {Number} windowWidth
49076       * @readOnly
49077       * @example
49078       * <div class="norender"><code>
49079       * createCanvas(windowWidth, windowHeight);
49080       * </code></div>
49081       *
49082       * @alt
49083       * no display.
49084       *
49085       */
49086
49087      p5.prototype.windowWidth = getWindowWidth();
49088      /**
49089       * System variable that stores the height of the inner window, it maps to
49090       * window.innerHeight.
49091       *
49092       * @property {Number} windowHeight
49093       * @readOnly
49094       * @example
49095       * <div class="norender"><code>
49096       * createCanvas(windowWidth, windowHeight);
49097       * </code></div>
49098       *@alt
49099       * no display.
49100       *
49101       */
49102
49103      p5.prototype.windowHeight = getWindowHeight();
49104      /**
49105       * The <a href="#/p5/windowResized">windowResized()</a> function is called once every time the browser window
49106       * is resized. This is a good place to resize the canvas or do any other
49107       * adjustments to accommodate the new window size.
49108       *
49109       * @method windowResized
49110       * @example
49111       * <div class="norender"><code>
49112       * function setup() {
49113       *   createCanvas(windowWidth, windowHeight);
49114       * }
49115       *
49116       * function draw() {
49117       *   background(0, 100, 200);
49118       * }
49119       *
49120       * function windowResized() {
49121       *   resizeCanvas(windowWidth, windowHeight);
49122       * }
49123       * </code></div>
49124       * @alt
49125       * no display.
49126       */
49127
49128      p5.prototype._onresize = function (e) {
49129        this._setProperty('windowWidth', getWindowWidth());
49130
49131        this._setProperty('windowHeight', getWindowHeight());
49132
49133        var context = this._isGlobal ? window : this;
49134        var executeDefault;
49135
49136        if (typeof context.windowResized === 'function') {
49137          executeDefault = context.windowResized(e);
49138
49139          if (executeDefault !== undefined && !executeDefault) {
49140            e.preventDefault();
49141          }
49142        }
49143      };
49144
49145      function getWindowWidth() {
49146        return window.innerWidth || document.documentElement && document.documentElement.clientWidth || document.body && document.body.clientWidth || 0;
49147      }
49148
49149      function getWindowHeight() {
49150        return window.innerHeight || document.documentElement && document.documentElement.clientHeight || document.body && document.body.clientHeight || 0;
49151      }
49152      /**
49153       * System variable that stores the width of the drawing canvas. This value
49154       * is set by the first parameter of the <a href="#/p5/createCanvas">createCanvas()</a> function.
49155       * For example, the function call createCanvas(320, 240) sets the width
49156       * variable to the value 320. The value of width defaults to 100 if
49157       * <a href="#/p5/createCanvas">createCanvas()</a> is not used in a program.
49158       *
49159       * @property {Number} width
49160       * @readOnly
49161       */
49162
49163
49164      p5.prototype.width = 0;
49165      /**
49166       * System variable that stores the height of the drawing canvas. This value
49167       * is set by the second parameter of the <a href="#/p5/createCanvas">createCanvas()</a> function. For
49168       * example, the function call createCanvas(320, 240) sets the height
49169       * variable to the value 240. The value of height defaults to 100 if
49170       * <a href="#/p5/createCanvas">createCanvas()</a> is not used in a program.
49171       *
49172       * @property {Number} height
49173       * @readOnly
49174       */
49175
49176      p5.prototype.height = 0;
49177      /**
49178       * If argument is given, sets the sketch to fullscreen or not based on the
49179       * value of the argument. If no argument is given, returns the current
49180       * fullscreen state. Note that due to browser restrictions this can only
49181       * be called on user input, for example, on mouse press like the example
49182       * below.
49183       *
49184       * @method fullscreen
49185       * @param  {Boolean} [val] whether the sketch should be in fullscreen mode
49186       * or not
49187       * @return {Boolean} current fullscreen state
49188       * @example
49189       * <div>
49190       * <code>
49191       * // Clicking in the box toggles fullscreen on and off.
49192       * function setup() {
49193       *   background(200);
49194       * }
49195       * function mousePressed() {
49196       *   if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {
49197       *     let fs = fullscreen();
49198       *     fullscreen(!fs);
49199       *   }
49200       * }
49201       * </code>
49202       * </div>
49203       *
49204       * @alt
49205       * no display.
49206       *
49207       */
49208
49209      p5.prototype.fullscreen = function (val) {
49210        p5._validateParameters('fullscreen', arguments); // no arguments, return fullscreen or not
49211
49212
49213        if (typeof val === 'undefined') {
49214          return document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;
49215        } else {
49216          // otherwise set to fullscreen or not
49217          if (val) {
49218            launchFullscreen(document.documentElement);
49219          } else {
49220            exitFullscreen();
49221          }
49222        }
49223      };
49224      /**
49225       * Sets the pixel scaling for high pixel density displays. By default
49226       * pixel density is set to match display density, call pixelDensity(1)
49227       * to turn this off. Calling <a href="#/p5/pixelDensity">pixelDensity()</a> with no arguments returns
49228       * the current pixel density of the sketch.
49229       *
49230       * @method pixelDensity
49231       * @param  {Number} val whether or how much the sketch should scale
49232       * @chainable
49233       * @example
49234       * <div>
49235       * <code>
49236       * function setup() {
49237       *   pixelDensity(1);
49238       *   createCanvas(100, 100);
49239       *   background(200);
49240       *   ellipse(width / 2, height / 2, 50, 50);
49241       * }
49242       * </code>
49243       * </div>
49244       * <div>
49245       * <code>
49246       * function setup() {
49247       *   pixelDensity(3.0);
49248       *   createCanvas(100, 100);
49249       *   background(200);
49250       *   ellipse(width / 2, height / 2, 50, 50);
49251       * }
49252       * </code>
49253       * </div>
49254       *
49255       * @alt
49256       * fuzzy 50x50 white ellipse with black outline in center of canvas.
49257       * sharp 50x50 white ellipse with black outline in center of canvas.
49258       */
49259
49260      /**
49261       * @method pixelDensity
49262       * @returns {Number} current pixel density of the sketch
49263       */
49264
49265
49266      p5.prototype.pixelDensity = function (val) {
49267        p5._validateParameters('pixelDensity', arguments);
49268
49269        var returnValue;
49270
49271        if (typeof val === 'number') {
49272          if (val !== this._pixelDensity) {
49273            this._pixelDensity = val;
49274            this._pixelsDirty = true;
49275          }
49276
49277          returnValue = this;
49278          this.resizeCanvas(this.width, this.height, true); // as a side effect, it will clear the canvas
49279        } else {
49280          returnValue = this._pixelDensity;
49281        }
49282
49283        return returnValue;
49284      };
49285      /**
49286       * Returns the pixel density of the current display the sketch is running on.
49287       *
49288       * @method displayDensity
49289       * @returns {Number} current pixel density of the display
49290       * @example
49291       * <div>
49292       * <code>
49293       * function setup() {
49294       *   let density = displayDensity();
49295       *   pixelDensity(density);
49296       *   createCanvas(100, 100);
49297       *   background(200);
49298       *   ellipse(width / 2, height / 2, 50, 50);
49299       * }
49300       * </code>
49301       * </div>
49302       *
49303       * @alt
49304       * 50x50 white ellipse with black outline in center of canvas.
49305       */
49306
49307
49308      p5.prototype.displayDensity = function () {
49309        return window.devicePixelRatio;
49310      };
49311
49312      function launchFullscreen(element) {
49313        var enabled = document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled;
49314
49315        if (!enabled) {
49316          throw new Error('Fullscreen not enabled in this browser.');
49317        }
49318
49319        if (element.requestFullscreen) {
49320          element.requestFullscreen();
49321        } else if (element.mozRequestFullScreen) {
49322          element.mozRequestFullScreen();
49323        } else if (element.webkitRequestFullscreen) {
49324          element.webkitRequestFullscreen();
49325        } else if (element.msRequestFullscreen) {
49326          element.msRequestFullscreen();
49327        }
49328      }
49329
49330      function exitFullscreen() {
49331        if (document.exitFullscreen) {
49332          document.exitFullscreen();
49333        } else if (document.mozCancelFullScreen) {
49334          document.mozCancelFullScreen();
49335        } else if (document.webkitExitFullscreen) {
49336          document.webkitExitFullscreen();
49337        } else if (document.msExitFullscreen) {
49338          document.msExitFullscreen();
49339        }
49340      }
49341      /**
49342       * Gets the current URL.
49343       * @method getURL
49344       * @return {String} url
49345       * @example
49346       * <div>
49347       * <code>
49348       * let url;
49349       * let x = 100;
49350       *
49351       * function setup() {
49352       *   fill(0);
49353       *   noStroke();
49354       *   url = getURL();
49355       * }
49356       *
49357       * function draw() {
49358       *   background(200);
49359       *   text(url, x, height / 2);
49360       *   x--;
49361       * }
49362       * </code>
49363       * </div>
49364       *
49365       * @alt
49366       * current url (http://p5js.org/reference/#/p5/getURL) moves right to left.
49367       *
49368       */
49369
49370
49371      p5.prototype.getURL = function () {
49372        return location.href;
49373      };
49374      /**
49375       * Gets the current URL path as an array.
49376       * @method getURLPath
49377       * @return {String[]} path components
49378       * @example
49379       * <div class='norender'><code>
49380       * function setup() {
49381       *   let urlPath = getURLPath();
49382       *   for (let i = 0; i < urlPath.length; i++) {
49383       *     text(urlPath[i], 10, i * 20 + 20);
49384       *   }
49385       * }
49386       * </code></div>
49387       *
49388       * @alt
49389       *no display
49390       *
49391       */
49392
49393
49394      p5.prototype.getURLPath = function () {
49395        return location.pathname.split('/').filter(function (v) {
49396          return v !== '';
49397        });
49398      };
49399      /**
49400       * Gets the current URL params as an Object.
49401       * @method getURLParams
49402       * @return {Object} URL params
49403       * @example
49404       * <div class='norender notest'>
49405       * <code>
49406       * // Example: http://p5js.org?year=2014&month=May&day=15
49407       *
49408       * function setup() {
49409       *   let params = getURLParams();
49410       *   text(params.day, 10, 20);
49411       *   text(params.month, 10, 40);
49412       *   text(params.year, 10, 60);
49413       * }
49414       * </code>
49415       * </div>
49416       * @alt
49417       * no display.
49418       *
49419       */
49420
49421
49422      p5.prototype.getURLParams = function () {
49423        var re = /[?&]([^&=]+)(?:[&=])([^&=]+)/gim;
49424        var m;
49425        var v = {};
49426
49427        while ((m = re.exec(location.search)) != null) {
49428          if (m.index === re.lastIndex) {
49429            re.lastIndex++;
49430          }
49431
49432          v[m[1]] = m[2];
49433        }
49434
49435        return v;
49436      };
49437
49438      module.exports = p5;
49439    }, {
49440      "./constants": 18,
49441      "./main": 24
49442    }],
49443    20: [function (_dereq_, module, exports) {
49444      /**
49445       * @for p5
49446       * @requires core
49447       */
49448      'use strict';
49449
49450      var p5 = _dereq_('./main');
49451
49452      var constants = _dereq_('./constants'); // p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta
49453      // See testColors below for all the color codes and names
49454
49455
49456      var typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00'];
49457
49458      if (typeof IS_MINIFIED !== 'undefined') {
49459        p5._validateParameters = p5._friendlyFileLoadError = p5._friendlyError = function () {};
49460      } else {
49461        var doFriendlyWelcome = false; // TEMP until we get it all working LM
49462        // for parameter validation
49463
49464        var dataDoc = _dereq_('../../docs/reference/data.json');
49465
49466        var arrDoc = JSON.parse(JSON.stringify(dataDoc)); // -- Borrowed from jQuery 1.11.3 --
49467
49468        var class2type = {};
49469        var toString = class2type.toString;
49470        var names = ['Boolean', 'Number', 'String', 'Function', 'Array', 'Date', 'RegExp', 'Object', 'Error'];
49471
49472        for (var n = 0; n < names.length; n++) {
49473          class2type['[object ' + names[n] + ']'] = names[n].toLowerCase();
49474        }
49475
49476        var getType = function (obj) {
49477          if (obj == null) {
49478            return obj + '';
49479          }
49480
49481          return typeof obj === 'object' || typeof obj === 'function' ? class2type[toString.call(obj)] || 'object' : typeof obj;
49482        }; // -- End borrow --
49483
49484
49485        var friendlyWelcome = function () {
49486          // p5.js brand - magenta: #ED225D
49487          //var astrixBgColor = 'transparent';
49488          //var astrixTxtColor = '#ED225D';
49489          //var welcomeBgColor = '#ED225D';
49490          //var welcomeTextColor = 'white';
49491          console.log('    _ \n' + ' /\\| |/\\ \n' + " \\ ` ' /  \n" + ' / , . \\  \n' + ' \\/|_|\\/ ' + '\n\n> p5.js says: Welcome! ' + 'This is your friendly debugger. ' + 'To turn me off switch to using “p5.min.js”.');
49492        };
49493        /**
49494         * Prints out a fancy, colorful message to the console log
49495         *
49496         * @method report
49497         * @private
49498         * @param  {String}               message the words to be said
49499         * @param  {String}               func    the name of the function to link
49500         * @param  {Number|String} color   CSS color string or error type
49501         *
49502         * @return console logs
49503         */
49504
49505
49506        var report = function (message, func, color) {
49507          if (doFriendlyWelcome) {
49508            friendlyWelcome();
49509            doFriendlyWelcome = false;
49510          }
49511
49512          if ('undefined' === getType(color)) {
49513            color = '#B40033'; // dark magenta
49514          } else if (getType(color) === 'number') {
49515            // Type to color
49516            color = typeColors[color];
49517          }
49518
49519          if (func === 'loadX') {
49520            console.log('> p5.js says: ' + message);
49521          } else if (func.substring(0, 4) === 'load') {
49522            console.log('> p5.js says: ' + message + '[https://github.com/processing/p5.js/wiki/Local-server]');
49523          } else {
49524            console.log('> p5.js says: ' + message + ' [http://p5js.org/reference/#p5/' + func + ']');
49525          }
49526        };
49527
49528        var errorCases = {
49529          '0': {
49530            fileType: 'image',
49531            method: 'loadImage',
49532            message: ' hosting the image online,'
49533          },
49534          '1': {
49535            fileType: 'XML file',
49536            method: 'loadXML'
49537          },
49538          '2': {
49539            fileType: 'table file',
49540            method: 'loadTable'
49541          },
49542          '3': {
49543            fileType: 'text file',
49544            method: 'loadStrings'
49545          },
49546          '4': {
49547            fileType: 'font',
49548            method: 'loadFont',
49549            message: ' hosting the font online,'
49550          },
49551          '5': {
49552            fileType: 'json',
49553            method: 'loadJSON'
49554          },
49555          '6': {
49556            fileType: 'file',
49557            method: 'loadBytes'
49558          },
49559          '7': {
49560            method: 'loadX',
49561            message: "In case your large file isn't fetched successfully," + 'we recommend splitting the file into smaller segments and fetching those.'
49562          }
49563        };
49564        /**
49565         * This is called internally if there is a error during file loading.
49566         *
49567         * @method _friendlyFileLoadError
49568         * @private
49569         * @param  {Number} errorType
49570         * @param  {String} filePath
49571         */
49572
49573        p5._friendlyFileLoadError = function (errorType, filePath) {
49574          var errorInfo = errorCases[errorType];
49575          var message;
49576
49577          if (errorType === 7) {
49578            message = errorInfo.message;
49579          } else {
49580            message = 'It looks like there was a problem' + ' loading your ' + errorInfo.fileType + '.' + ' Try checking if the file path [' + filePath + '] is correct,' + (errorInfo.message || '') + ' or running a local server.';
49581          }
49582
49583          report(message, errorInfo.method, 3);
49584        };
49585        /**
49586         * This is a generic method that can be called from anywhere in the p5
49587         * library to alert users to a common error.
49588         *
49589         * @method _friendlyError
49590         * @private
49591         * @param  {Number} message message to be printed
49592         * @param  {String} method name of method
49593         */
49594
49595
49596        p5._friendlyError = function (message, method) {
49597          report(message, method);
49598        };
49599
49600        var docCache = {};
49601        var builtinTypes = ['null', 'number', 'string', 'boolean', 'constant', 'function', 'any', 'integer']; // validateParameters() helper functions:
49602        // lookupParamDoc() for querying data.json
49603
49604        var lookupParamDoc = function (func) {
49605          // look for the docs in the `data.json` datastructure
49606          var ichDot = func.lastIndexOf('.');
49607          var funcName = func.substr(ichDot + 1);
49608          var funcClass = func.substr(0, ichDot) || 'p5';
49609          var queryResult;
49610          var classitems = arrDoc.classitems;
49611
49612          for (var ici = 0; ici < classitems.length; ici++) {
49613            var x = classitems[ici];
49614
49615            if (x.name === funcName && x.class === funcClass) {
49616              queryResult = x;
49617              break;
49618            }
49619          } // different JSON structure for funct with multi-format
49620
49621
49622          var overloads = [];
49623
49624          if (queryResult.hasOwnProperty('overloads')) {
49625            // add all the overloads
49626            for (var i = 0; i < queryResult.overloads.length; i++) {
49627              overloads.push({
49628                formats: queryResult.overloads[i].params
49629              });
49630            }
49631          } else {
49632            // no overloads, just add the main method definition
49633            overloads.push({
49634              formats: queryResult.params || []
49635            });
49636          } // parse the parameter types for each overload
49637
49638
49639          var mapConstants = {};
49640          var maxParams = 0;
49641          overloads.forEach(function (overload) {
49642            var formats = overload.formats; // keep a record of the maximum number of arguments
49643            // this method requires.
49644
49645            if (maxParams < formats.length) {
49646              maxParams = formats.length;
49647            } // calculate the minimum number of arguments
49648            // this overload requires.
49649
49650
49651            var minParams = formats.length;
49652
49653            while (minParams > 0 && formats[minParams - 1].optional) {
49654              minParams--;
49655            }
49656
49657            overload.minParams = minParams; // loop through each parameter position, and parse its types
49658
49659            formats.forEach(function (format) {
49660              // split this parameter's types
49661              format.types = format.type.split('|').map(function ct(type) {
49662                // array
49663                if (type.substr(type.length - 2, 2) === '[]') {
49664                  return {
49665                    name: type,
49666                    array: ct(type.substr(0, type.length - 2))
49667                  };
49668                }
49669
49670                var lowerType = type.toLowerCase(); // contant
49671
49672                if (lowerType === 'constant') {
49673                  var constant;
49674
49675                  if (mapConstants.hasOwnProperty(format.name)) {
49676                    constant = mapConstants[format.name];
49677                  } else {
49678                    // parse possible constant values from description
49679                    var myRe = /either\s+(?:[A-Z0-9_]+\s*,?\s*(?:or)?\s*)+/g;
49680                    var values = {};
49681                    var names = [];
49682                    constant = mapConstants[format.name] = {
49683                      values: values,
49684                      names: names
49685                    };
49686                    var myArray = myRe.exec(format.description);
49687
49688                    if (func === 'endShape' && format.name === 'mode') {
49689                      values[constants.CLOSE] = true;
49690                      names.push('CLOSE');
49691                    } else {
49692                      var match = myArray[0];
49693                      var reConst = /[A-Z0-9_]+/g;
49694                      var matchConst;
49695
49696                      while ((matchConst = reConst.exec(match)) !== null) {
49697                        var name = matchConst[0];
49698
49699                        if (constants.hasOwnProperty(name)) {
49700                          values[constants[name]] = true;
49701                          names.push(name);
49702                        }
49703                      }
49704                    }
49705                  }
49706
49707                  return {
49708                    name: type,
49709                    builtin: lowerType,
49710                    names: constant.names,
49711                    values: constant.values
49712                  };
49713                } // function
49714
49715
49716                if (lowerType.substr(0, 'function'.length) === 'function') {
49717                  lowerType = 'function';
49718                } // builtin
49719
49720
49721                if (builtinTypes.indexOf(lowerType) >= 0) {
49722                  return {
49723                    name: type,
49724                    builtin: lowerType
49725                  };
49726                } // find type's prototype
49727
49728
49729                var t = window;
49730                var typeParts = type.split('.'); // special-case 'p5' since it may be non-global
49731
49732                if (typeParts[0] === 'p5') {
49733                  t = p5;
49734                  typeParts.shift();
49735                }
49736
49737                typeParts.forEach(function (p) {
49738                  t = t && t[p];
49739                });
49740
49741                if (t) {
49742                  return {
49743                    name: type,
49744                    prototype: t
49745                  };
49746                }
49747
49748                return {
49749                  name: type,
49750                  type: lowerType
49751                };
49752              });
49753            });
49754          });
49755          return {
49756            overloads: overloads,
49757            maxParams: maxParams
49758          };
49759        };
49760
49761        var isNumber = function (param) {
49762          switch (typeof param) {
49763            case 'number':
49764              return true;
49765
49766            case 'string':
49767              return !isNaN(param);
49768
49769            default:
49770              return false;
49771          }
49772        };
49773
49774        var testParamType = function (param, type) {
49775          var isArray = param instanceof Array;
49776          var matches = true;
49777
49778          if (type.array && isArray) {
49779            for (var i = 0; i < param.length; i++) {
49780              var error = testParamType(param[i], type.array);
49781              if (error) return error / 2; // half error for elements
49782            }
49783          } else if (type.prototype) {
49784            matches = param instanceof type.prototype;
49785          } else if (type.builtin) {
49786            switch (type.builtin) {
49787              case 'number':
49788                matches = isNumber(param);
49789                break;
49790
49791              case 'integer':
49792                matches = isNumber(param) && Number(param) === Math.floor(param);
49793                break;
49794
49795              case 'boolean':
49796              case 'any':
49797                matches = true;
49798                break;
49799
49800              case 'array':
49801                matches = isArray;
49802                break;
49803
49804              case 'string':
49805                matches =
49806                /*typeof param === 'number' ||*/
49807                typeof param === 'string';
49808                break;
49809
49810              case 'constant':
49811                matches = type.values.hasOwnProperty(param);
49812                break;
49813
49814              case 'function':
49815                matches = param instanceof Function;
49816                break;
49817
49818              case 'null':
49819                matches = param === null;
49820                break;
49821            }
49822          } else {
49823            matches = typeof param === type.t;
49824          }
49825
49826          return matches ? 0 : 1;
49827        }; // testType() for non-object type parameter validation
49828
49829
49830        var testParamTypes = function (param, types) {
49831          var minScore = 9999;
49832
49833          for (var i = 0; minScore > 0 && i < types.length; i++) {
49834            var score = testParamType(param, types[i]);
49835            if (minScore > score) minScore = score;
49836          }
49837
49838          return minScore;
49839        }; // generate a score (higher is worse) for applying these args to
49840        // this overload.
49841
49842
49843        var scoreOverload = function (args, argCount, overload, minScore) {
49844          var score = 0;
49845          var formats = overload.formats;
49846          var minParams = overload.minParams; // check for too few/many args
49847          // the score is double number of extra/missing args
49848
49849          if (argCount < minParams) {
49850            score = (minParams - argCount) * 2;
49851          } else if (argCount > formats.length) {
49852            score = (argCount - formats.length) * 2;
49853          } // loop through the formats, adding up the error score for each arg.
49854          // quit early if the score gets higher than the previous best overload.
49855
49856
49857          for (var p = 0; score <= minScore && p < formats.length; p++) {
49858            var arg = args[p];
49859            var format = formats[p]; // '== null' checks for 'null' and typeof 'undefined'
49860
49861            if (arg == null) {
49862              // handle non-optional and non-trailing undefined args
49863              if (!format.optional || p < minParams || p < argCount) {
49864                score += 1;
49865              }
49866            } else {
49867              score += testParamTypes(arg, format.types);
49868            }
49869          }
49870
49871          return score;
49872        }; // gets a list of errors for this overload
49873
49874
49875        var getOverloadErrors = function (args, argCount, overload) {
49876          var formats = overload.formats;
49877          var minParams = overload.minParams; // check for too few/many args
49878
49879          if (argCount < minParams) {
49880            return [{
49881              type: 'TOO_FEW_ARGUMENTS',
49882              argCount: argCount,
49883              minParams: minParams
49884            }];
49885          } else if (argCount > formats.length) {
49886            return [{
49887              type: 'TOO_MANY_ARGUMENTS',
49888              argCount: argCount,
49889              maxParams: formats.length
49890            }];
49891          }
49892
49893          var errorArray = [];
49894
49895          for (var p = 0; p < formats.length; p++) {
49896            var arg = args[p];
49897            var format = formats[p]; // '== null' checks for 'null' and typeof 'undefined'
49898
49899            if (arg == null) {
49900              // handle non-optional and non-trailing undefined args
49901              if (!format.optional || p < minParams || p < argCount) {
49902                errorArray.push({
49903                  type: 'EMPTY_VAR',
49904                  position: p,
49905                  format: format
49906                });
49907              }
49908            } else if (testParamTypes(arg, format.types) > 0) {
49909              errorArray.push({
49910                type: 'WRONG_TYPE',
49911                position: p,
49912                format: format,
49913                arg: arg
49914              });
49915            }
49916          }
49917
49918          return errorArray;
49919        }; // a custom error type, used by the mocha
49920        // tests when expecting validation errors
49921
49922
49923        p5.ValidationError = function (name) {
49924          var err = function (message, func) {
49925            this.message = message;
49926            this.func = func;
49927            if ('captureStackTrace' in Error) Error.captureStackTrace(this, err);else this.stack = new Error().stack;
49928          };
49929
49930          err.prototype = Object.create(Error.prototype);
49931          err.prototype.name = name;
49932          err.prototype.constructor = err;
49933          return err;
49934        }('ValidationError'); // function for generating console.log() msg
49935
49936
49937        p5._friendlyParamError = function (errorObj, func) {
49938          var message;
49939
49940          function formatType() {
49941            var format = errorObj.format;
49942            return format.types.map(function (type) {
49943              return type.names ? type.names.join('|') : type.name;
49944            }).join('|');
49945          }
49946
49947          switch (errorObj.type) {
49948            case 'EMPTY_VAR':
49949              message = func + '() was expecting ' + formatType() + ' for parameter #' + errorObj.position + ' (zero-based index), received an empty variable instead.' + ' If not intentional, this is often a problem with scope:' + ' [https://p5js.org/examples/data-variable-scope.html]';
49950              break;
49951
49952            case 'WRONG_TYPE':
49953              var arg = errorObj.arg;
49954              var argType = arg instanceof Array ? 'array' : arg === null ? 'null' : arg.name || typeof arg;
49955              message = func + '() was expecting ' + formatType() + ' for parameter #' + errorObj.position + ' (zero-based index), received ' + argType + ' instead';
49956              break;
49957
49958            case 'TOO_FEW_ARGUMENTS':
49959              message = func + '() was expecting at least ' + errorObj.minParams + ' arguments, but received only ' + errorObj.argCount;
49960              break;
49961
49962            case 'TOO_MANY_ARGUMENTS':
49963              message = func + '() was expecting no more than ' + errorObj.maxParams + ' arguments, but received ' + errorObj.argCount;
49964              break;
49965          }
49966
49967          if (message) {
49968            if (p5._throwValidationErrors) {
49969              throw new p5.ValidationError(message);
49970            }
49971
49972            try {
49973              var re = /Function\.validateParameters.*[\r\n].*[\r\n].*\(([^)]*)/;
49974              var location = re.exec(new Error().stack)[1];
49975
49976              if (location) {
49977                message += ' at ' + location;
49978              }
49979            } catch (err) {}
49980
49981            report(message + '.', func, 3);
49982          }
49983        };
49984        /**
49985         * Validates parameters
49986         * param  {String}               func    the name of the function
49987         * param  {Array}                args    user input arguments
49988         *
49989         * example:
49990         *  var a;
49991         *  ellipse(10,10,a,5);
49992         * console ouput:
49993         *  "It looks like ellipse received an empty variable in spot #2."
49994         *
49995         * example:
49996         *  ellipse(10,"foo",5,5);
49997         * console output:
49998         *  "ellipse was expecting a number for parameter #1,
49999         *           received "foo" instead."
50000         */
50001
50002
50003        p5._validateParameters = function validateParameters(func, args) {
50004          if (p5.disableFriendlyErrors) {
50005            return; // skip FES
50006          } // lookup the docs in the 'data.json' file
50007
50008
50009          var docs = docCache[func] || (docCache[func] = lookupParamDoc(func));
50010          var overloads = docs.overloads; // ignore any trailing `undefined` arguments
50011
50012          var argCount = args.length; // '== null' checks for 'null' and typeof 'undefined'
50013
50014          while (argCount > 0 && args[argCount - 1] == null) argCount--; // find the overload with the best score
50015
50016
50017          var minScore = 99999;
50018          var minOverload;
50019
50020          for (var i = 0; i < overloads.length; i++) {
50021            var score = scoreOverload(args, argCount, overloads[i], minScore);
50022
50023            if (score === 0) {
50024              return; // done!
50025            } else if (minScore > score) {
50026              // this score is better that what we have so far...
50027              minScore = score;
50028              minOverload = i;
50029            }
50030          } // this should _always_ be true here...
50031
50032
50033          if (minScore > 0) {
50034            // get the errors for the best overload
50035            var errorArray = getOverloadErrors(args, argCount, overloads[minOverload]); // generate err msg
50036
50037            for (var n = 0; n < errorArray.length; n++) {
50038              p5._friendlyParamError(errorArray[n], func);
50039            }
50040          }
50041        };
50042        /**
50043         * Prints out all the colors in the color pallete with white text.
50044         * For color blindness testing.
50045         */
50046
50047        /* function testColors() {
50048          var str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer';
50049          report(str, 'print', '#ED225D'); // p5.js magenta
50050          report(str, 'print', '#2D7BB6'); // p5.js blue
50051          report(str, 'print', '#EE9900'); // p5.js orange
50052          report(str, 'print', '#A67F59'); // p5.js light brown
50053          report(str, 'print', '#704F21'); // p5.js gold
50054          report(str, 'print', '#1CC581'); // auto cyan
50055          report(str, 'print', '#FF6625'); // auto orange
50056          report(str, 'print', '#79EB22'); // auto green
50057          report(str, 'print', '#B40033'); // p5.js darkened magenta
50058          report(str, 'print', '#084B7F'); // p5.js darkened blue
50059          report(str, 'print', '#945F00'); // p5.js darkened orange
50060          report(str, 'print', '#6B441D'); // p5.js darkened brown
50061          report(str, 'print', '#2E1B00'); // p5.js darkened gold
50062          report(str, 'print', '#008851'); // auto dark cyan
50063          report(str, 'print', '#C83C00'); // auto dark orange
50064          report(str, 'print', '#4DB200'); // auto dark green
50065        } */
50066
50067
50068        p5.prototype._validateParameters = p5.validateParameters;
50069      } // This is a lazily-defined list of p5 symbols that may be
50070      // misused by beginners at top-level code, outside of setup/draw. We'd like
50071      // to detect these errors and help the user by suggesting they move them
50072      // into setup/draw.
50073      //
50074      // For more details, see https://github.com/processing/p5.js/issues/1121.
50075
50076
50077      var misusedAtTopLevelCode = null;
50078      var FAQ_URL = 'https://github.com/processing/p5.js/wiki/p5.js-overview' + '#why-cant-i-assign-variables-using-p5-functions-and-' + 'variables-before-setup';
50079
50080      var defineMisusedAtTopLevelCode = function () {
50081        var uniqueNamesFound = {};
50082
50083        var getSymbols = function (obj) {
50084          return Object.getOwnPropertyNames(obj).filter(function (name) {
50085            if (name[0] === '_') {
50086              return false;
50087            }
50088
50089            if (name in uniqueNamesFound) {
50090              return false;
50091            }
50092
50093            uniqueNamesFound[name] = true;
50094            return true;
50095          }).map(function (name) {
50096            var type;
50097
50098            if (typeof obj[name] === 'function') {
50099              type = 'function';
50100            } else if (name === name.toUpperCase()) {
50101              type = 'constant';
50102            } else {
50103              type = 'variable';
50104            }
50105
50106            return {
50107              name: name,
50108              type: type
50109            };
50110          });
50111        };
50112
50113        misusedAtTopLevelCode = [].concat(getSymbols(p5.prototype), // At present, p5 only adds its constants to p5.prototype during
50114        // construction, which may not have happened at the time a
50115        // ReferenceError is thrown, so we'll manually add them to our list.
50116        getSymbols(_dereq_('./constants'))); // This will ultimately ensure that we report the most specific error
50117        // possible to the user, e.g. advising them about HALF_PI instead of PI
50118        // when their code misuses the former.
50119
50120        misusedAtTopLevelCode.sort(function (a, b) {
50121          return b.name.length - a.name.length;
50122        });
50123      };
50124
50125      var helpForMisusedAtTopLevelCode = function (e, log) {
50126        if (!log) {
50127          log = console.log.bind(console);
50128        }
50129
50130        if (!misusedAtTopLevelCode) {
50131          defineMisusedAtTopLevelCode();
50132        } // If we find that we're logging lots of false positives, we can
50133        // uncomment the following code to avoid displaying anything if the
50134        // user's code isn't likely to be using p5's global mode. (Note that
50135        // setup/draw are more likely to be defined due to JS function hoisting.)
50136        //
50137        //if (!('setup' in window || 'draw' in window)) {
50138        //  return;
50139        //}
50140
50141
50142        misusedAtTopLevelCode.some(function (symbol) {
50143          // Note that while just checking for the occurrence of the
50144          // symbol name in the error message could result in false positives,
50145          // a more rigorous test is difficult because different browsers
50146          // log different messages, and the format of those messages may
50147          // change over time.
50148          //
50149          // For example, if the user uses 'PI' in their code, it may result
50150          // in any one of the following messages:
50151          //
50152          //   * 'PI' is undefined                           (Microsoft Edge)
50153          //   * ReferenceError: PI is undefined             (Firefox)
50154          //   * Uncaught ReferenceError: PI is not defined  (Chrome)
50155          if (e.message && e.message.match('\\W?' + symbol.name + '\\W') !== null) {
50156            log("Did you just try to use p5.js's " + symbol.name + (symbol.type === 'function' ? '() ' : ' ') + symbol.type + '? If so, you may want to ' + "move it into your sketch's setup() function.\n\n" + 'For more details, see: ' + FAQ_URL);
50157            return true;
50158          }
50159        });
50160      }; // Exposing this primarily for unit testing.
50161
50162
50163      p5.prototype._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode;
50164
50165      if (document.readyState !== 'complete') {
50166        window.addEventListener('error', helpForMisusedAtTopLevelCode, false); // Our job is only to catch ReferenceErrors that are thrown when
50167        // global (non-instance mode) p5 APIs are used at the top-level
50168        // scope of a file, so we'll unbind our error listener now to make
50169        // sure we don't log false positives later.
50170
50171        window.addEventListener('load', function () {
50172          window.removeEventListener('error', helpForMisusedAtTopLevelCode, false);
50173        });
50174      }
50175
50176      module.exports = p5;
50177    }, {
50178      "../../docs/reference/data.json": 1,
50179      "./constants": 18,
50180      "./main": 24
50181    }],
50182    21: [function (_dereq_, module, exports) {
50183      /**
50184       * @requires constants
50185       */
50186      'use strict';
50187
50188      var constants = _dereq_('./constants');
50189
50190      module.exports = {
50191        modeAdjust: function (a, b, c, d, mode) {
50192          if (mode === constants.CORNER) {
50193            return {
50194              x: a,
50195              y: b,
50196              w: c,
50197              h: d
50198            };
50199          } else if (mode === constants.CORNERS) {
50200            return {
50201              x: a,
50202              y: b,
50203              w: c - a,
50204              h: d - b
50205            };
50206          } else if (mode === constants.RADIUS) {
50207            return {
50208              x: a - c,
50209              y: b - d,
50210              w: 2 * c,
50211              h: 2 * d
50212            };
50213          } else if (mode === constants.CENTER) {
50214            return {
50215              x: a - c * 0.5,
50216              y: b - d * 0.5,
50217              w: c,
50218              h: d
50219            };
50220          }
50221        }
50222      };
50223    }, {
50224      "./constants": 18
50225    }],
50226    22: [function (_dereq_, module, exports) {
50227      'use strict';
50228
50229      var p5 = _dereq_('../core/main');
50230      /**
50231       * _globalInit
50232       *
50233       * TODO: ???
50234       * if sketch is on window
50235       * assume "global" mode
50236       * and instantiate p5 automatically
50237       * otherwise do nothing
50238       *
50239       * @private
50240       * @return {Undefined}
50241       */
50242
50243
50244      var _globalInit = function () {
50245        if (!window.mocha) {
50246          // If there is a setup or draw function on the window
50247          // then instantiate p5 in "global" mode
50248          if ((window.setup && typeof window.setup === 'function' || window.draw && typeof window.draw === 'function') && !p5.instance) {
50249            new p5();
50250          }
50251        }
50252      }; // TODO: ???
50253      // if the page is ready, initialize p5 immediately
50254
50255
50256      if (document.readyState === 'complete') {
50257        _globalInit(); // if the page is still loading, add an event listener
50258        // and initialize p5 as soon as it finishes loading
50259
50260      } else {
50261        window.addEventListener('load', _globalInit, false);
50262      }
50263    }, {
50264      "../core/main": 24
50265    }],
50266    23: [function (_dereq_, module, exports) {
50267      /**
50268       * @for p5
50269       * @requires core
50270       * These are functions that are part of the Processing API but are not part of
50271       * the p5.js API. In some cases they have a new name, in others, they are
50272       * removed completely. Not all unsupported Processing functions are listed here
50273       * but we try to include ones that a user coming from Processing might likely
50274       * call.
50275       */
50276      'use strict';
50277
50278      var p5 = _dereq_('./main');
50279
50280      p5.prototype.pushStyle = function () {
50281        throw new Error('pushStyle() not used, see push()');
50282      };
50283
50284      p5.prototype.popStyle = function () {
50285        throw new Error('popStyle() not used, see pop()');
50286      };
50287
50288      module.exports = p5;
50289    }, {
50290      "./main": 24
50291    }],
50292    24: [function (_dereq_, module, exports) {
50293      /**
50294       * @module Structure
50295       * @submodule Structure
50296       * @for p5
50297       * @requires constants
50298       */
50299      'use strict';
50300
50301      _dereq_('./shim'); // Core needs the PVariables object
50302
50303
50304      var constants = _dereq_('./constants');
50305      /**
50306       * This is the p5 instance constructor.
50307       *
50308       * A p5 instance holds all the properties and methods related to
50309       * a p5 sketch.  It expects an incoming sketch closure and it can also
50310       * take an optional node parameter for attaching the generated p5 canvas
50311       * to a node.  The sketch closure takes the newly created p5 instance as
50312       * its sole argument and may optionally set <a href="#/p5/preload">preload()</a>, <a href="#/p5/setup">setup()</a>, and/or
50313       * <a href="#/p5/draw">draw()</a> properties on it for running a sketch.
50314       *
50315       * A p5 sketch can run in "global" or "instance" mode:
50316       * "global"   - all properties and methods are attached to the window
50317       * "instance" - all properties and methods are bound to this p5 object
50318       *
50319       * @class p5
50320       * @constructor
50321       * @param  {function}    sketch a closure that can set optional <a href="#/p5/preload">preload()</a>,
50322       *                              <a href="#/p5/setup">setup()</a>, and/or <a href="#/p5/draw">draw()</a> properties on the
50323       *                              given p5 instance
50324       * @param  {HTMLElement|Boolean} [node] element to attach canvas to, if a
50325       *                                      boolean is passed in use it as sync
50326       * @param  {Boolean}     [sync] start synchronously (optional)
50327       * @return {p5}                 a p5 instance
50328       */
50329
50330
50331      var p5 = function (sketch, node, sync) {
50332        if (typeof node === 'boolean' && typeof sync === 'undefined') {
50333          sync = node;
50334          node = undefined;
50335        } //////////////////////////////////////////////
50336        // PUBLIC p5 PROPERTIES AND METHODS
50337        //////////////////////////////////////////////
50338
50339        /**
50340         * Called directly before <a href="#/p5/setup">setup()</a>, the <a href="#/p5/preload">preload()</a> function is used to handle
50341         * asynchronous loading of external files in a blocking way. If a preload
50342         * function is defined, <a href="#/p5/setup">setup()</a> will wait until any load calls within have
50343         * finished. Nothing besides load calls (<a href="#/p5/loadImage">loadImage</a>, <a href="#/p5/loadJSON">loadJSON</a>, <a href="#/p5/loadFont">loadFont</a>,
50344         * <a href="#/p5/loadStrings">loadStrings</a>, etc.) should be inside the preload function. If asynchronous
50345         * loading is preferred, the load methods can instead be called in <a href="#/p5/setup">setup()</a>
50346         * or anywhere else with the use of a callback parameter.
50347         * <br><br>
50348         * By default the text "loading..." will be displayed. To make your own
50349         * loading page, include an HTML element with id "p5_loading" in your
50350         * page. More information <a href="http://bit.ly/2kQ6Nio">here</a>.
50351         *
50352         * @method preload
50353         * @example
50354         * <div><code>
50355         * let img;
50356         * let c;
50357         * function preload() {
50358         *   // preload() runs once
50359         *   img = loadImage('assets/laDefense.jpg');
50360         * }
50361         *
50362         * function setup() {
50363         *   // setup() waits until preload() is done
50364         *   img.loadPixels();
50365         *   // get color of middle pixel
50366         *   c = img.get(img.width / 2, img.height / 2);
50367         * }
50368         *
50369         * function draw() {
50370         *   background(c);
50371         *   image(img, 25, 25, 50, 50);
50372         * }
50373         * </code></div>
50374         *
50375         * @alt
50376         * nothing displayed
50377         *
50378         */
50379
50380        /**
50381         * The <a href="#/p5/setup">setup()</a> function is called once when the program starts. It's used to
50382         * define initial environment properties such as screen size and background
50383         * color and to load media such as images and fonts as the program starts.
50384         * There can only be one <a href="#/p5/setup">setup()</a> function for each program and it shouldn't
50385         * be called again after its initial execution.
50386         * <br><br>
50387         * Note: Variables declared within <a href="#/p5/setup">setup()</a> are not accessible within other
50388         * functions, including <a href="#/p5/draw">draw()</a>.
50389         *
50390         * @method setup
50391         * @example
50392         * <div><code>
50393         * let a = 0;
50394         *
50395         * function setup() {
50396         *   background(0);
50397         *   noStroke();
50398         *   fill(102);
50399         * }
50400         *
50401         * function draw() {
50402         *   rect(a++ % width, 10, 2, 80);
50403         * }
50404         * </code></div>
50405         *
50406         * @alt
50407         * nothing displayed
50408         *
50409         */
50410
50411        /**
50412         * Called directly after <a href="#/p5/setup">setup()</a>, the <a href="#/p5/draw">draw()</a> function continuously executes
50413         * the lines of code contained inside its block until the program is stopped
50414         * or <a href="#/p5/noLoop">noLoop()</a> is called. Note if <a href="#/p5/noLoop">noLoop()</a> is called in <a href="#/p5/setup">setup()</a>, <a href="#/p5/draw">draw()</a> will
50415         * still be executed once before stopping. <a href="#/p5/draw">draw()</a> is called automatically and
50416         * should never be called explicitly.
50417         * <br><br>
50418         * It should always be controlled with <a href="#/p5/noLoop">noLoop()</a>, <a href="#/p5/redraw">redraw()</a> and <a href="#/p5/loop">loop()</a>. After
50419         * <a href="#/p5/noLoop">noLoop()</a> stops the code in <a href="#/p5/draw">draw()</a> from executing, <a href="#/p5/redraw">redraw()</a> causes the
50420         * code inside <a href="#/p5/draw">draw()</a> to execute once, and <a href="#/p5/loop">loop()</a> will cause the code
50421         * inside <a href="#/p5/draw">draw()</a> to resume executing continuously.
50422         * <br><br>
50423         * The number of times <a href="#/p5/draw">draw()</a> executes in each second may be controlled with
50424         * the <a href="#/p5/frameRate">frameRate()</a> function.
50425         * <br><br>
50426         * There can only be one <a href="#/p5/draw">draw()</a> function for each sketch, and <a href="#/p5/draw">draw()</a> must
50427         * exist if you want the code to run continuously, or to process events such
50428         * as <a href="#/p5/mousePressed">mousePressed()</a>. Sometimes, you might have an empty call to <a href="#/p5/draw">draw()</a> in
50429         * your program, as shown in the above example.
50430         * <br><br>
50431         * It is important to note that the drawing coordinate system will be reset
50432         * at the beginning of each <a href="#/p5/draw">draw()</a> call. If any transformations are performed
50433         * within <a href="#/p5/draw">draw()</a> (ex: scale, rotate, translate), their effects will be
50434         * undone at the beginning of <a href="#/p5/draw">draw()</a>, so transformations will not accumulate
50435         * over time. On the other hand, styling applied (ex: fill, stroke, etc) will
50436         * remain in effect.
50437         *
50438         * @method draw
50439         * @example
50440         * <div><code>
50441         * let yPos = 0;
50442         * function setup() {
50443         *   // setup() runs once
50444         *   frameRate(30);
50445         * }
50446         * function draw() {
50447         *   // draw() loops forever, until stopped
50448         *   background(204);
50449         *   yPos = yPos - 1;
50450         *   if (yPos < 0) {
50451         *     yPos = height;
50452         *   }
50453         *   line(0, yPos, width, yPos);
50454         * }
50455         * </code></div>
50456         *
50457         * @alt
50458         * nothing displayed
50459         *
50460         */
50461        //////////////////////////////////////////////
50462        // PRIVATE p5 PROPERTIES AND METHODS
50463        //////////////////////////////////////////////
50464
50465
50466        this._setupDone = false; // for handling hidpi
50467
50468        this._pixelDensity = Math.ceil(window.devicePixelRatio) || 1;
50469        this._userNode = node;
50470        this._curElement = null;
50471        this._elements = [];
50472        this._requestAnimId = 0;
50473        this._preloadCount = 0;
50474        this._isGlobal = false;
50475        this._loop = true;
50476
50477        this._initializeInstanceVariables();
50478
50479        this._defaultCanvasSize = {
50480          width: 100,
50481          height: 100
50482        };
50483        this._events = {
50484          // keep track of user-events for unregistering later
50485          mousemove: null,
50486          mousedown: null,
50487          mouseup: null,
50488          dragend: null,
50489          dragover: null,
50490          click: null,
50491          dblclick: null,
50492          mouseover: null,
50493          mouseout: null,
50494          keydown: null,
50495          keyup: null,
50496          keypress: null,
50497          touchstart: null,
50498          touchmove: null,
50499          touchend: null,
50500          resize: null,
50501          blur: null
50502        };
50503        this._events.wheel = null;
50504        this._loadingScreenId = 'p5_loading'; // Allows methods to be registered on an instance that
50505        // are instance-specific.
50506
50507        this._registeredMethods = {};
50508        var methods = Object.getOwnPropertyNames(p5.prototype._registeredMethods);
50509
50510        for (var i = 0; i < methods.length; i++) {
50511          var prop = methods[i];
50512          this._registeredMethods[prop] = p5.prototype._registeredMethods[prop].slice();
50513        }
50514
50515        if (window.DeviceOrientationEvent) {
50516          this._events.deviceorientation = null;
50517        }
50518
50519        if (window.DeviceMotionEvent && !window._isNodeWebkit) {
50520          this._events.devicemotion = null;
50521        }
50522
50523        this._start = function () {
50524          // Find node if id given
50525          if (this._userNode) {
50526            if (typeof this._userNode === 'string') {
50527              this._userNode = document.getElementById(this._userNode);
50528            }
50529          }
50530
50531          var context = this._isGlobal ? window : this;
50532          var userPreload = context.preload;
50533
50534          if (userPreload) {
50535            // Setup loading screen
50536            // Set loading screen into dom if not present
50537            // Otherwise displays and removes user provided loading screen
50538            var loadingScreen = document.getElementById(this._loadingScreenId);
50539
50540            if (!loadingScreen) {
50541              loadingScreen = document.createElement('div');
50542              loadingScreen.innerHTML = 'Loading...';
50543              loadingScreen.style.position = 'absolute';
50544              loadingScreen.id = this._loadingScreenId;
50545              var node = this._userNode || document.body;
50546              node.appendChild(loadingScreen);
50547            }
50548
50549            var methods = this._preloadMethods;
50550
50551            for (var method in methods) {
50552              // default to p5 if no object defined
50553              methods[method] = methods[method] || p5;
50554              var obj = methods[method]; //it's p5, check if it's global or instance
50555
50556              if (obj === p5.prototype || obj === p5) {
50557                if (this._isGlobal) {
50558                  window[method] = this._wrapPreload(this, method);
50559                }
50560
50561                obj = this;
50562              }
50563
50564              this._registeredPreloadMethods[method] = obj[method];
50565              obj[method] = this._wrapPreload(obj, method);
50566            }
50567
50568            userPreload();
50569
50570            this._runIfPreloadsAreDone();
50571          } else {
50572            this._setup();
50573
50574            this._draw();
50575          }
50576        }.bind(this);
50577
50578        this._runIfPreloadsAreDone = function () {
50579          var context = this._isGlobal ? window : this;
50580
50581          if (context._preloadCount === 0) {
50582            var loadingScreen = document.getElementById(context._loadingScreenId);
50583
50584            if (loadingScreen) {
50585              loadingScreen.parentNode.removeChild(loadingScreen);
50586            }
50587
50588            context._setup();
50589
50590            context._draw();
50591          }
50592        };
50593
50594        this._decrementPreload = function () {
50595          var context = this._isGlobal ? window : this;
50596
50597          if (typeof context.preload === 'function') {
50598            context._setProperty('_preloadCount', context._preloadCount - 1);
50599
50600            context._runIfPreloadsAreDone();
50601          }
50602        };
50603
50604        this._wrapPreload = function (obj, fnName) {
50605          return function () {
50606            //increment counter
50607            this._incrementPreload(); //call original function
50608
50609
50610            return this._registeredPreloadMethods[fnName].apply(obj, arguments);
50611          }.bind(this);
50612        };
50613
50614        this._incrementPreload = function () {
50615          var context = this._isGlobal ? window : this;
50616
50617          context._setProperty('_preloadCount', context._preloadCount + 1);
50618        };
50619
50620        this._setup = function () {
50621          // Always create a default canvas.
50622          // Later on if the user calls createCanvas, this default one
50623          // will be replaced
50624          this.createCanvas(this._defaultCanvasSize.width, this._defaultCanvasSize.height, 'p2d'); // return preload functions to their normal vals if switched by preload
50625
50626          var context = this._isGlobal ? window : this;
50627
50628          if (typeof context.preload === 'function') {
50629            for (var f in this._preloadMethods) {
50630              context[f] = this._preloadMethods[f][f];
50631
50632              if (context[f] && this) {
50633                context[f] = context[f].bind(this);
50634              }
50635            }
50636          } // Short-circuit on this, in case someone used the library in "global"
50637          // mode earlier
50638
50639
50640          if (typeof context.setup === 'function') {
50641            context.setup();
50642          } // unhide any hidden canvases that were created
50643
50644
50645          var canvases = document.getElementsByTagName('canvas');
50646
50647          for (var i = 0; i < canvases.length; i++) {
50648            var k = canvases[i];
50649
50650            if (k.dataset.hidden === 'true') {
50651              k.style.visibility = '';
50652              delete k.dataset.hidden;
50653            }
50654          }
50655
50656          this._setupDone = true;
50657        }.bind(this);
50658
50659        this._draw = function () {
50660          var now = window.performance.now();
50661          var time_since_last = now - this._lastFrameTime;
50662          var target_time_between_frames = 1000 / this._targetFrameRate; // only draw if we really need to; don't overextend the browser.
50663          // draw if we're within 5ms of when our next frame should paint
50664          // (this will prevent us from giving up opportunities to draw
50665          // again when it's really about time for us to do so). fixes an
50666          // issue where the frameRate is too low if our refresh loop isn't
50667          // in sync with the browser. note that we have to draw once even
50668          // if looping is off, so we bypass the time delay if that
50669          // is the case.
50670
50671          var epsilon = 5;
50672
50673          if (!this._loop || time_since_last >= target_time_between_frames - epsilon) {
50674            //mandatory update values(matrixs and stack)
50675            this.redraw();
50676            this._frameRate = 1000.0 / (now - this._lastFrameTime);
50677            this._lastFrameTime = now; // If the user is actually using mouse module, then update
50678            // coordinates, otherwise skip. We can test this by simply
50679            // checking if any of the mouse functions are available or not.
50680            // NOTE : This reflects only in complete build or modular build.
50681
50682            if (typeof this._updateMouseCoords !== 'undefined') {
50683              this._updateMouseCoords();
50684            }
50685          } // get notified the next time the browser gives us
50686          // an opportunity to draw.
50687
50688
50689          if (this._loop) {
50690            this._requestAnimId = window.requestAnimationFrame(this._draw);
50691          }
50692        }.bind(this);
50693
50694        this._setProperty = function (prop, value) {
50695          this[prop] = value;
50696
50697          if (this._isGlobal) {
50698            window[prop] = value;
50699          }
50700        }.bind(this);
50701        /**
50702         * Removes the entire p5 sketch. This will remove the canvas and any
50703         * elements created by p5.js. It will also stop the draw loop and unbind
50704         * any properties or methods from the window global scope. It will
50705         * leave a variable p5 in case you wanted to create a new p5 sketch.
50706         * If you like, you can set p5 = null to erase it. While all functions and
50707         * variables and objects created by the p5 library will be removed, any
50708         * other global variables created by your code will remain.
50709         *
50710         * @method remove
50711         * @example
50712         * <div class='norender'><code>
50713         * function draw() {
50714         *   ellipse(50, 50, 10, 10);
50715         * }
50716         *
50717         * function mousePressed() {
50718         *   remove(); // remove whole sketch on mouse press
50719         * }
50720         * </code></div>
50721         *
50722         * @alt
50723         * nothing displayed
50724         *
50725         */
50726
50727
50728        this.remove = function () {
50729          var loadingScreen = document.getElementById(this._loadingScreenId);
50730
50731          if (loadingScreen) {
50732            loadingScreen.parentNode.removeChild(loadingScreen); // Add 1 to preload counter to prevent the sketch ever executing setup()
50733
50734            this._incrementPreload();
50735          }
50736
50737          if (this._curElement) {
50738            // stop draw
50739            this._loop = false;
50740
50741            if (this._requestAnimId) {
50742              window.cancelAnimationFrame(this._requestAnimId);
50743            } // unregister events sketch-wide
50744
50745
50746            for (var ev in this._events) {
50747              window.removeEventListener(ev, this._events[ev]);
50748            } // remove DOM elements created by p5, and listeners
50749
50750
50751            for (var i = 0; i < this._elements.length; i++) {
50752              var e = this._elements[i];
50753
50754              if (e.elt.parentNode) {
50755                e.elt.parentNode.removeChild(e.elt);
50756              }
50757
50758              for (var elt_ev in e._events) {
50759                e.elt.removeEventListener(elt_ev, e._events[elt_ev]);
50760              }
50761            } // call any registered remove functions
50762
50763
50764            var self = this;
50765
50766            this._registeredMethods.remove.forEach(function (f) {
50767              if (typeof f !== 'undefined') {
50768                f.call(self);
50769              }
50770            });
50771          } // remove window bound properties and methods
50772
50773
50774          if (this._isGlobal) {
50775            for (var p in p5.prototype) {
50776              try {
50777                delete window[p];
50778              } catch (x) {
50779                window[p] = undefined;
50780              }
50781            }
50782
50783            for (var p2 in this) {
50784              if (this.hasOwnProperty(p2)) {
50785                try {
50786                  delete window[p2];
50787                } catch (x) {
50788                  window[p2] = undefined;
50789                }
50790              }
50791            }
50792
50793            p5.instance = null;
50794          }
50795        }.bind(this); // call any registered init functions
50796
50797
50798        this._registeredMethods.init.forEach(function (f) {
50799          if (typeof f !== 'undefined') {
50800            f.call(this);
50801          }
50802        }, this);
50803
50804        var friendlyBindGlobal = this._createFriendlyGlobalFunctionBinder(); // If the user has created a global setup or draw function,
50805        // assume "global" mode and make everything global (i.e. on the window)
50806
50807
50808        if (!sketch) {
50809          this._isGlobal = true;
50810          p5.instance = this; // Loop through methods on the prototype and attach them to the window
50811
50812          for (var p in p5.prototype) {
50813            if (typeof p5.prototype[p] === 'function') {
50814              var ev = p.substring(2);
50815
50816              if (!this._events.hasOwnProperty(ev)) {
50817                if (Math.hasOwnProperty(p) && Math[p] === p5.prototype[p]) {
50818                  // Multiple p5 methods are just native Math functions. These can be
50819                  // called without any binding.
50820                  friendlyBindGlobal(p, p5.prototype[p]);
50821                } else {
50822                  friendlyBindGlobal(p, p5.prototype[p].bind(this));
50823                }
50824              }
50825            } else {
50826              friendlyBindGlobal(p, p5.prototype[p]);
50827            }
50828          } // Attach its properties to the window
50829
50830
50831          for (var p2 in this) {
50832            if (this.hasOwnProperty(p2)) {
50833              friendlyBindGlobal(p2, this[p2]);
50834            }
50835          }
50836        } else {
50837          // Else, the user has passed in a sketch closure that may set
50838          // user-provided 'setup', 'draw', etc. properties on this instance of p5
50839          sketch(this);
50840        } // Bind events to window (not using container div bc key events don't work)
50841
50842
50843        for (var e in this._events) {
50844          var f = this['_on' + e];
50845
50846          if (f) {
50847            var m = f.bind(this);
50848            window.addEventListener(e, m, {
50849              passive: false
50850            });
50851            this._events[e] = m;
50852          }
50853        }
50854
50855        var focusHandler = function () {
50856          this._setProperty('focused', true);
50857        }.bind(this);
50858
50859        var blurHandler = function () {
50860          this._setProperty('focused', false);
50861        }.bind(this);
50862
50863        window.addEventListener('focus', focusHandler);
50864        window.addEventListener('blur', blurHandler);
50865        this.registerMethod('remove', function () {
50866          window.removeEventListener('focus', focusHandler);
50867          window.removeEventListener('blur', blurHandler);
50868        });
50869
50870        if (sync) {
50871          this._start();
50872        } else {
50873          if (document.readyState === 'complete') {
50874            this._start();
50875          } else {
50876            window.addEventListener('load', this._start.bind(this), false);
50877          }
50878        }
50879      };
50880
50881      p5.prototype._initializeInstanceVariables = function () {
50882        this._styles = [];
50883        this._bezierDetail = 20;
50884        this._curveDetail = 20;
50885        this._colorMode = constants.RGB;
50886        this._colorMaxes = {
50887          rgb: [255, 255, 255, 255],
50888          hsb: [360, 100, 100, 1],
50889          hsl: [360, 100, 100, 1]
50890        };
50891        this._pixelsDirty = true;
50892      }; // This is a pointer to our global mode p5 instance, if we're in
50893      // global mode.
50894
50895
50896      p5.instance = null; // Allows for the friendly error system to be turned off when creating a sketch,
50897      // which can give a significant boost to performance when needed.
50898
50899      p5.disableFriendlyErrors = false; // attach constants to p5 prototype
50900
50901      for (var k in constants) {
50902        p5.prototype[k] = constants[k];
50903      } // functions that cause preload to wait
50904      // more can be added by using registerPreloadMethod(func)
50905
50906
50907      p5.prototype._preloadMethods = {
50908        loadJSON: p5.prototype,
50909        loadImage: p5.prototype,
50910        loadStrings: p5.prototype,
50911        loadXML: p5.prototype,
50912        loadBytes: p5.prototype,
50913        loadTable: p5.prototype,
50914        loadFont: p5.prototype,
50915        loadModel: p5.prototype,
50916        loadShader: p5.prototype
50917      };
50918      p5.prototype._registeredMethods = {
50919        init: [],
50920        pre: [],
50921        post: [],
50922        remove: []
50923      };
50924      p5.prototype._registeredPreloadMethods = {};
50925
50926      p5.prototype.registerPreloadMethod = function (fnString, obj) {
50927        // obj = obj || p5.prototype;
50928        if (!p5.prototype._preloadMethods.hasOwnProperty(fnString)) {
50929          p5.prototype._preloadMethods[fnString] = obj;
50930        }
50931      };
50932
50933      p5.prototype.registerMethod = function (name, m) {
50934        var target = this || p5.prototype;
50935
50936        if (!target._registeredMethods.hasOwnProperty(name)) {
50937          target._registeredMethods[name] = [];
50938        }
50939
50940        target._registeredMethods[name].push(m);
50941      }; // create a function which provides a standardized process for binding
50942      // globals; this is implemented as a factory primarily so that there's a
50943      // way to redefine what "global" means for the binding function so it
50944      // can be used in scenarios like unit testing where the window object
50945      // might not exist
50946
50947
50948      p5.prototype._createFriendlyGlobalFunctionBinder = function (options) {
50949        options = options || {};
50950        var globalObject = options.globalObject || window;
50951        var log = options.log || console.log.bind(console);
50952        var propsToForciblyOverwrite = {
50953          // p5.print actually always overwrites an existing global function,
50954          // albeit one that is very unlikely to be used:
50955          //
50956          //   https://developer.mozilla.org/en-US/docs/Web/API/Window/print
50957          print: true
50958        };
50959        return function (prop, value) {
50960          if (!p5.disableFriendlyErrors && typeof IS_MINIFIED === 'undefined' && typeof value === 'function' && !(prop in p5.prototype._preloadMethods)) {
50961            try {
50962              // Because p5 has so many common function names, it's likely
50963              // that users may accidentally overwrite global p5 functions with
50964              // their own variables. Let's allow this but log a warning to
50965              // help users who may be doing this unintentionally.
50966              //
50967              // For more information, see:
50968              //
50969              //   https://github.com/processing/p5.js/issues/1317
50970              if (prop in globalObject && !(prop in propsToForciblyOverwrite)) {
50971                throw new Error('global "' + prop + '" already exists');
50972              } // It's possible that this might throw an error because there
50973              // are a lot of edge-cases in which `Object.defineProperty` might
50974              // not succeed; since this functionality is only intended to
50975              // help beginners anyways, we'll just catch such an exception
50976              // if it occurs, and fall back to legacy behavior.
50977
50978
50979              Object.defineProperty(globalObject, prop, {
50980                configurable: true,
50981                enumerable: true,
50982                get: function () {
50983                  return value;
50984                },
50985                set: function (newValue) {
50986                  Object.defineProperty(globalObject, prop, {
50987                    configurable: true,
50988                    enumerable: true,
50989                    value: newValue,
50990                    writable: true
50991                  });
50992                  log('You just changed the value of "' + prop + '", which was ' + "a p5 function. This could cause problems later if you're " + 'not careful.');
50993                }
50994              });
50995            } catch (e) {
50996              log('p5 had problems creating the global function "' + prop + '", ' + 'possibly because your co
50996de is already using that name as ' + 'a variable. You may want to rename your variable to something ' + 'else.');
50997              globalObject[prop] = value;
50998            }
50999          } else {
51000            globalObject[prop] = value;
51001          }
51002        };
51003      };
51004
51005      module.exports = p5;
51006    }, {
51007      "./constants": 18,
51008      "./shim": 34
51009    }],
51010    25: [function (_dereq_, module, exports) {
51011      /**
51012       * @module DOM
51013       * @submodule DOM
51014       * @for p5.Element
51015       */
51016      'use strict';
51017
51018      var p5 = _dereq_('./main');
51019      /**
51020       * Base class for all elements added to a sketch, including canvas,
51021       * graphics buffers, and other HTML elements. Methods in blue are
51022       * included in the core functionality, methods in brown are added
51023       * with the <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom
51024       * library</a>.
51025       * It is not called directly, but <a href="#/p5.Element">p5.Element</a>
51026       * objects are created by calling <a href="#/p5/createCanvas">createCanvas</a>, <a href="#/p5/createGraphics">createGraphics</a>,
51027       * or in the p5.dom library, <a href="#/p5/createDiv">createDiv</a>, <a href="#/p5/createImg">createImg</a>, <a href="#/p5/createInput">createInput</a>, etc.
51028       *
51029       * @class p5.Element
51030       * @param {String} elt DOM node that is wrapped
51031       * @param {p5} [pInst] pointer to p5 instance
51032       */
51033
51034
51035      p5.Element = function (elt, pInst) {
51036        /**
51037         * Underlying HTML element. All normal HTML methods can be called on this.
51038         * @example
51039         * <div>
51040         * <code>
51041         * function setup() {
51042         *   var c = createCanvas(50, 50);
51043         *   c.elt.style.border = '5px solid red';
51044         * }
51045         *
51046         * function draw() {
51047         *   background(220);
51048         * }
51049         * </code>
51050         * </div>
51051         *
51052         * @property elt
51053         * @readOnly
51054         */
51055        this.elt = elt;
51056        this._pInst = pInst;
51057        this._events = {};
51058        this.width = this.elt.offsetWidth;
51059        this.height = this.elt.offsetHeight;
51060      };
51061      /**
51062       *
51063       * Attaches the element to the parent specified. A way of setting
51064       * the container for the element. Accepts either a string ID, DOM
51065       * node, or <a href="#/p5.Element">p5.Element</a>. If no arguments given, parent node is returned.
51066       * For more ways to position the canvas, see the
51067       * <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>
51068       * positioning the canvas</a> wiki page.
51069       *
51070       * All above examples except for the first one require the inclusion of
51071       * the p5.dom library in your index.html. See the
51072       * <a href='http://p5js.org/libraries/#using-a-library'>using a library</a>
51073       * section for information on how to include this library.
51074       *
51075       * @method parent
51076       * @param  {String|p5.Element|Object} parent the ID, DOM node, or <a href="#/p5.Element">p5.Element</a>
51077       *                         of desired parent element
51078       * @chainable
51079       *
51080       * @example
51081       * <div class="norender notest"><code>
51082       * // in the html file:
51083       * // &lt;div id="myContainer">&lt;/div>
51084       *
51085       * // in the js file:
51086       * var cnv = createCanvas(100, 100);
51087       * cnv.parent('myContainer');
51088       * </code></div>
51089       * <div class='norender'><code>
51090       * var div0 = createDiv('this is the parent');
51091       * var div1 = createDiv('this is the child');
51092       * div1.parent(div0); // use p5.Element
51093       * </code></div>
51094       * <div class='norender'><code>
51095       * var div0 = createDiv('this is the parent');
51096       * div0.id('apples');
51097       * var div1 = createDiv('this is the child');
51098       * div1.parent('apples'); // use id
51099       * </code></div>
51100       * <div class='norender notest'><code>
51101       * var elt = document.getElementById('myParentDiv');
51102       * var div1 = createDiv('this is the child');
51103       * div1.parent(elt); // use element from page
51104       * </code></div>
51105       *
51106       * @alt
51107       * no display.
51108       */
51109
51110      /**
51111       * @method parent
51112       * @return {p5.Element}
51113       *
51114       */
51115
51116
51117      p5.Element.prototype.parent = function (p) {
51118        if (typeof p === 'undefined') {
51119          return this.elt.parentNode;
51120        }
51121
51122        if (typeof p === 'string') {
51123          if (p[0] === '#') {
51124            p = p.substring(1);
51125          }
51126
51127          p = document.getElementById(p);
51128        } else if (p instanceof p5.Element) {
51129          p = p.elt;
51130        }
51131
51132        p.appendChild(this.elt);
51133        return this;
51134      };
51135      /**
51136       *
51137       * Sets the ID of the element. If no ID argument is passed in, it instead
51138       * returns the current ID of the element.
51139       *
51140       * @method id
51141       * @param  {String} id ID of the element
51142       * @chainable
51143       *
51144       * @example
51145       * <div class='norender'><code>
51146       * function setup() {
51147       *   var cnv = createCanvas(100, 100);
51148       *   // Assigns a CSS selector ID to
51149       *   // the canvas element.
51150       *   cnv.id('mycanvas');
51151       * }
51152       * </code></div>
51153       *
51154       * @alt
51155       * no display.
51156       */
51157
51158      /**
51159       * @method id
51160       * @return {String} the id of the element
51161       */
51162
51163
51164      p5.Element.prototype.id = function (id) {
51165        if (typeof id === 'undefined') {
51166          return this.elt.id;
51167        }
51168
51169        this.elt.id = id;
51170        this.width = this.elt.offsetWidth;
51171        this.height = this.elt.offsetHeight;
51172        return this;
51173      };
51174      /**
51175       *
51176       * Adds given class to the element. If no class argument is passed in, it
51177       * instead returns a string containing the current class(es) of the element.
51178       *
51179       * @method class
51180       * @param  {String} class class to add
51181       * @chainable
51182       *
51183       * @example
51184       * <div class='norender'><code>
51185       * function setup() {
51186       *   var cnv = createCanvas(100, 100);
51187       *   // Assigns a CSS selector class 'small'
51188       *   // to the canvas element.
51189       *   cnv.class('small');
51190       * }
51191       * </code></div>
51192       *
51193       * @alt
51194       * no display.
51195       */
51196
51197      /**
51198       * @method class
51199       * @return {String} the class of the element
51200       */
51201
51202
51203      p5.Element.prototype.class = function (c) {
51204        if (typeof c === 'undefined') {
51205          return this.elt.className;
51206        }
51207
51208        this.elt.className = c;
51209        return this;
51210      };
51211      /**
51212       * The .<a href="#/p5.Element/mousePressed">mousePressed()</a> function is called once after every time a
51213       * mouse button is pressed over the element.
51214       * Some mobile browsers may also trigger this event on a touch screen,
51215       * if the user performs a quick tap.
51216       * This can be used to attach element specific event listeners.
51217       *
51218       * @method mousePressed
51219       * @param  {Function|Boolean} fxn function to be fired when mouse is
51220       *                                pressed over the element.
51221       *                                if `false` is passed instead, the previously
51222       *                                firing function will no longer fire.
51223       * @chainable
51224       * @example
51225       * <div class='norender'><code>
51226       * var cnv;
51227       * var d;
51228       * var g;
51229       * function setup() {
51230       *   cnv = createCanvas(100, 100);
51231       *   cnv.mousePressed(changeGray); // attach listener for
51232       *   // canvas click only
51233       *   d = 10;
51234       *   g = 100;
51235       * }
51236       *
51237       * function draw() {
51238       *   background(g);
51239       *   ellipse(width / 2, height / 2, d, d);
51240       * }
51241       *
51242       * // this function fires with any click anywhere
51243       * function mousePressed() {
51244       *   d = d + 10;
51245       * }
51246       *
51247       * // this function fires only when cnv is clicked
51248       * function changeGray() {
51249       *   g = random(0, 255);
51250       * }
51251       * </code></div>
51252       *
51253       * @alt
51254       * no display.
51255       *
51256       */
51257
51258
51259      p5.Element.prototype.mousePressed = function (fxn) {
51260        // Prepend the mouse property setters to the event-listener.
51261        // This is required so that mouseButton is set correctly prior to calling the callback (fxn).
51262        // For details, see https://github.com/processing/p5.js/issues/3087.
51263        var eventPrependedFxn = function (event) {
51264          this._pInst._setProperty('mouseIsPressed', true);
51265
51266          this._pInst._setMouseButton(event); // Pass along the return-value of the callback:
51267
51268
51269          return fxn.call(this);
51270        }; // Pass along the event-prepended form of the callback.
51271
51272
51273        p5.Element._adjustListener('mousedown', eventPrependedFxn, this);
51274
51275        return this;
51276      };
51277      /**
51278       * The .<a href="#/p5.Element/doubleClicked">doubleClicked()</a> function is called once after every time a
51279       * mouse button is pressed twice over the element. This can be used to
51280       * attach element and action specific event listeners.
51281       *
51282       * @method doubleClicked
51283       * @param  {Function|Boolean} fxn function to be fired when mouse is
51284       *                                double clicked over the element.
51285       *                                if `false` is passed instead, the previously
51286       *                                firing function will no longer fire.
51287       * @return {p5.Element}
51288       * @example
51289       * <div class='norender'><code>
51290       * var cnv;
51291       * var d;
51292       * var g;
51293       * function setup() {
51294       *   cnv = createCanvas(100, 100);
51295       *   cnv.doubleClicked(changeGray); // attach listener for
51296       *   // canvas double click only
51297       *   d = 10;
51298       *   g = 100;
51299       * }
51300       *
51301       * function draw() {
51302       *   background(g);
51303       *   ellipse(width / 2, height / 2, d, d);
51304       * }
51305       *
51306       * // this function fires with any double click anywhere
51307       * function doubleClicked() {
51308       *   d = d + 10;
51309       * }
51310       *
51311       * // this function fires only when cnv is double clicked
51312       * function changeGray() {
51313       *   g = random(0, 255);
51314       * }
51315       * </code></div>
51316       *
51317       * @alt
51318       * no display.
51319       *
51320       */
51321
51322
51323      p5.Element.prototype.doubleClicked = function (fxn) {
51324        p5.Element._adjustListener('dblclick', fxn, this);
51325
51326        return this;
51327      };
51328      /**
51329       * The .<a href="#/p5.Element/mouseWheel">mouseWheel()</a> function is called once after every time a
51330       * mouse wheel is scrolled over the element. This can be used to
51331       * attach element specific event listeners.
51332       * <br><br>
51333       * The function accepts a callback function as argument which will be executed
51334       * when the `wheel` event is triggered on the element, the callback function is
51335       * passed one argument `event`. The `event.deltaY` property returns negative
51336       * values if the mouse wheel is rotated up or away from the user and positive
51337       * in the other direction. The `event.deltaX` does the same as `event.deltaY`
51338       * except it reads the horizontal wheel scroll of the mouse wheel.
51339       * <br><br>
51340       * On OS X with "natural" scrolling enabled, the `event.deltaY` values are
51341       * reversed.
51342       *
51343       * @method mouseWheel
51344       * @param  {Function|Boolean} fxn function to be fired when mouse is
51345       *                                scrolled over the element.
51346       *                                if `false` is passed instead, the previously
51347       *                                firing function will no longer fire.
51348       * @chainable
51349       * @example
51350       * <div class='norender'><code>
51351       * var cnv;
51352       * var d;
51353       * var g;
51354       * function setup() {
51355       *   cnv = createCanvas(100, 100);
51356       *   cnv.mouseWheel(changeSize); // attach listener for
51357       *   // activity on canvas only
51358       *   d = 10;
51359       *   g = 100;
51360       * }
51361       *
51362       * function draw() {
51363       *   background(g);
51364       *   ellipse(width / 2, height / 2, d, d);
51365       * }
51366       *
51367       * // this function fires with mousewheel movement
51368       * // anywhere on screen
51369       * function mouseWheel() {
51370       *   g = g + 10;
51371       * }
51372       *
51373       * // this function fires with mousewheel movement
51374       * // over canvas only
51375       * function changeSize(event) {
51376       *   if (event.deltaY > 0) {
51377       *     d = d + 10;
51378       *   } else {
51379       *     d = d - 10;
51380       *   }
51381       * }
51382       * </code></div>
51383       *
51384       *
51385       * @alt
51386       * no display.
51387       *
51388       */
51389
51390
51391      p5.Element.prototype.mouseWheel = function (fxn) {
51392        p5.Element._adjustListener('wheel', fxn, this);
51393
51394        return this;
51395      };
51396      /**
51397       * The .<a href="#/p5.Element/mouseReleased">mouseReleased()</a> function is called once after every time a
51398       * mouse button is released over the element.
51399       * Some mobile browsers may also trigger this event on a touch screen,
51400       * if the user performs a quick tap.
51401       * This can be used to attach element specific event listeners.
51402       *
51403       * @method mouseReleased
51404       * @param  {Function|Boolean} fxn function to be fired when mouse is
51405       *                                released over the element.
51406       *                                if `false` is passed instead, the previously
51407       *                                firing function will no longer fire.
51408       * @chainable
51409       * @example
51410       * <div class='norender'><code>
51411       * var cnv;
51412       * var d;
51413       * var g;
51414       * function setup() {
51415       *   cnv = createCanvas(100, 100);
51416       *   cnv.mouseReleased(changeGray); // attach listener for
51417       *   // activity on canvas only
51418       *   d = 10;
51419       *   g = 100;
51420       * }
51421       *
51422       * function draw() {
51423       *   background(g);
51424       *   ellipse(width / 2, height / 2, d, d);
51425       * }
51426       *
51427       * // this function fires after the mouse has been
51428       * // released
51429       * function mouseReleased() {
51430       *   d = d + 10;
51431       * }
51432       *
51433       * // this function fires after the mouse has been
51434       * // released while on canvas
51435       * function changeGray() {
51436       *   g = random(0, 255);
51437       * }
51438       * </code></div>
51439       *
51440       *
51441       * @alt
51442       * no display.
51443       *
51444       */
51445
51446
51447      p5.Element.prototype.mouseReleased = function (fxn) {
51448        p5.Element._adjustListener('mouseup', fxn, this);
51449
51450        return this;
51451      };
51452      /**
51453       * The .<a href="#/p5.Element/mouseClicked">mouseClicked()</a> function is called once after a mouse button is
51454       * pressed and released over the element.
51455       * Some mobile browsers may also trigger this event on a touch screen,
51456       * if the user performs a quick tap.
51457       * This can be used to attach element specific event listeners.
51458       *
51459       * @method mouseClicked
51460       * @param  {Function|Boolean} fxn function to be fired when mouse is
51461       *                                clicked over the element.
51462       *                                if `false` is passed instead, the previously
51463       *                                firing function will no longer fire.
51464       * @chainable
51465       * @example
51466       * <div class="norender">
51467       * <code>
51468       * var cnv;
51469       * var d;
51470       * var g;
51471       *
51472       * function setup() {
51473       *   cnv = createCanvas(100, 100);
51474       *   cnv.mouseClicked(changeGray); // attach listener for
51475       *   // activity on canvas only
51476       *   d = 10;
51477       *   g = 100;
51478       * }
51479       *
51480       * function draw() {
51481       *   background(g);
51482       *   ellipse(width / 2, height / 2, d, d);
51483       * }
51484       *
51485       * // this function fires after the mouse has been
51486       * // clicked anywhere
51487       * function mouseClicked() {
51488       *   d = d + 10;
51489       * }
51490       *
51491       * // this function fires after the mouse has been
51492       * // clicked on canvas
51493       * function changeGray() {
51494       *   g = random(0, 255);
51495       * }
51496       * </code>
51497       * </div>
51498       *
51499       * @alt
51500       * no display.
51501       *
51502       */
51503
51504
51505      p5.Element.prototype.mouseClicked = function (fxn) {
51506        p5.Element._adjustListener('click', fxn, this);
51507
51508        return this;
51509      };
51510      /**
51511       * The .<a href="#/p5.Element/mouseMoved">mouseMoved()</a> function is called once every time a
51512       * mouse moves over the element. This can be used to attach an
51513       * element specific event listener.
51514       *
51515       * @method mouseMoved
51516       * @param  {Function|Boolean} fxn function to be fired when a mouse moves
51517       *                                over the element.
51518       *                                if `false` is passed instead, the previously
51519       *                                firing function will no longer fire.
51520       * @chainable
51521       * @example
51522       * <div class='norender'><code>
51523       * var cnv;
51524       * var d = 30;
51525       * var g;
51526       * function setup() {
51527       *   cnv = createCanvas(100, 100);
51528       *   cnv.mouseMoved(changeSize); // attach listener for
51529       *   // activity on canvas only
51530       *   d = 10;
51531       *   g = 100;
51532       * }
51533       *
51534       * function draw() {
51535       *   background(g);
51536       *   fill(200);
51537       *   ellipse(width / 2, height / 2, d, d);
51538       * }
51539       *
51540       * // this function fires when mouse moves anywhere on
51541       * // page
51542       * function mouseMoved() {
51543       *   g = g + 5;
51544       *   if (g > 255) {
51545       *     g = 0;
51546       *   }
51547       * }
51548       *
51549       * // this function fires when mouse moves over canvas
51550       * function changeSize() {
51551       *   d = d + 2;
51552       *   if (d > 100) {
51553       *     d = 0;
51554       *   }
51555       * }
51556       * </code></div>
51557       *
51558       *
51559       * @alt
51560       * no display.
51561       *
51562       */
51563
51564
51565      p5.Element.prototype.mouseMoved = function (fxn) {
51566        p5.Element._adjustListener('mousemove', fxn, this);
51567
51568        return this;
51569      };
51570      /**
51571       * The .<a href="#/p5.Element/mouseOver">mouseOver()</a> function is called once after every time a
51572       * mouse moves onto the element. This can be used to attach an
51573       * element specific event listener.
51574       *
51575       * @method mouseOver
51576       * @param  {Function|Boolean} fxn function to be fired when a mouse moves
51577       *                                onto the element.
51578       *                                if `false` is passed instead, the previously
51579       *                                firing function will no longer fire.
51580       * @chainable
51581       * @example
51582       * <div class='norender'><code>
51583       * var cnv;
51584       * var d;
51585       * function setup() {
51586       *   cnv = createCanvas(100, 100);
51587       *   cnv.mouseOver(changeGray);
51588       *   d = 10;
51589       * }
51590       *
51591       * function draw() {
51592       *   ellipse(width / 2, height / 2, d, d);
51593       * }
51594       *
51595       * function changeGray() {
51596       *   d = d + 10;
51597       *   if (d > 100) {
51598       *     d = 0;
51599       *   }
51600       * }
51601       * </code></div>
51602       *
51603       *
51604       * @alt
51605       * no display.
51606       *
51607       */
51608
51609
51610      p5.Element.prototype.mouseOver = function (fxn) {
51611        p5.Element._adjustListener('mouseover', fxn, this);
51612
51613        return this;
51614      };
51615      /**
51616       * The .<a href="#/p5.Element/mouseOut">mouseOut()</a> function is called once after every time a
51617       * mouse moves off the element. This can be used to attach an
51618       * element specific event listener.
51619       *
51620       * @method mouseOut
51621       * @param  {Function|Boolean} fxn function to be fired when a mouse
51622       *                                moves off of an element.
51623       *                                if `false` is passed instead, the previously
51624       *                                firing function will no longer fire.
51625       * @chainable
51626       * @example
51627       * <div class='norender'><code>
51628       * var cnv;
51629       * var d;
51630       * function setup() {
51631       *   cnv = createCanvas(100, 100);
51632       *   cnv.mouseOut(changeGray);
51633       *   d = 10;
51634       * }
51635       *
51636       * function draw() {
51637       *   ellipse(width / 2, height / 2, d, d);
51638       * }
51639       *
51640       * function changeGray() {
51641       *   d = d + 10;
51642       *   if (d > 100) {
51643       *     d = 0;
51644       *   }
51645       * }
51646       * </code></div>
51647       *
51648       * @alt
51649       * no display.
51650       *
51651       */
51652
51653
51654      p5.Element.prototype.mouseOut = function (fxn) {
51655        p5.Element._adjustListener('mouseout', fxn, this);
51656
51657        return this;
51658      };
51659      /**
51660       * The .<a href="#/p5.Element/touchStarted">touchStarted()</a> function is called once after every time a touch is
51661       * registered. This can be used to attach element specific event listeners.
51662       *
51663       * @method touchStarted
51664       * @param  {Function|Boolean} fxn function to be fired when a touch
51665       *                                starts over the element.
51666       *                                if `false` is passed instead, the previously
51667       *                                firing function will no longer fire.
51668       * @chainable
51669       * @example
51670       * <div class='norender'><code>
51671       * var cnv;
51672       * var d;
51673       * var g;
51674       * function setup() {
51675       *   cnv = createCanvas(100, 100);
51676       *   cnv.touchStarted(changeGray); // attach listener for
51677       *   // canvas click only
51678       *   d = 10;
51679       *   g = 100;
51680       * }
51681       *
51682       * function draw() {
51683       *   background(g);
51684       *   ellipse(width / 2, height / 2, d, d);
51685       * }
51686       *
51687       * // this function fires with any touch anywhere
51688       * function touchStarted() {
51689       *   d = d + 10;
51690       * }
51691       *
51692       * // this function fires only when cnv is clicked
51693       * function changeGray() {
51694       *   g = random(0, 255);
51695       * }
51696       * </code></div>
51697       *
51698       * @alt
51699       * no display.
51700       *
51701       */
51702
51703
51704      p5.Element.prototype.touchStarted = function (fxn) {
51705        p5.Element._adjustListener('touchstart', fxn, this);
51706
51707        return this;
51708      };
51709      /**
51710       * The .<a href="#/p5.Element/touchMoved">touchMoved()</a> function is called once after every time a touch move is
51711       * registered. This can be used to attach element specific event listeners.
51712       *
51713       * @method touchMoved
51714       * @param  {Function|Boolean} fxn function to be fired when a touch moves over
51715       *                                the element.
51716       *                                if `false` is passed instead, the previously
51717       *                                firing function will no longer fire.
51718       * @chainable
51719       * @example
51720       * <div class='norender'><code>
51721       * var cnv;
51722       * var g;
51723       * function setup() {
51724       *   cnv = createCanvas(100, 100);
51725       *   cnv.touchMoved(changeGray); // attach listener for
51726       *   // canvas click only
51727       *   g = 100;
51728       * }
51729       *
51730       * function draw() {
51731       *   background(g);
51732       * }
51733       *
51734       * // this function fires only when cnv is clicked
51735       * function changeGray() {
51736       *   g = random(0, 255);
51737       * }
51738       * </code></div>
51739       *
51740       * @alt
51741       * no display.
51742       *
51743       */
51744
51745
51746      p5.Element.prototype.touchMoved = function (fxn) {
51747        p5.Element._adjustListener('touchmove', fxn, this);
51748
51749        return this;
51750      };
51751      /**
51752       * The .<a href="#/p5.Element/touchEnded">touchEnded()</a> function is called once after every time a touch is
51753       * registered. This can be used to attach element specific event listeners.
51754       *
51755       * @method touchEnded
51756       * @param  {Function|Boolean} fxn function to be fired when a touch ends
51757       *                                over the element.
51758       *                                if `false` is passed instead, the previously
51759       *                                firing function will no longer fire.
51760       * @chainable
51761       * @example
51762       * <div class='norender'><code>
51763       * var cnv;
51764       * var d;
51765       * var g;
51766       * function setup() {
51767       *   cnv = createCanvas(100, 100);
51768       *   cnv.touchEnded(changeGray); // attach listener for
51769       *   // canvas click only
51770       *   d = 10;
51771       *   g = 100;
51772       * }
51773       *
51774       * function draw() {
51775       *   background(g);
51776       *   ellipse(width / 2, height / 2, d, d);
51777       * }
51778       *
51779       * // this function fires with any touch anywhere
51780       * function touchEnded() {
51781       *   d = d + 10;
51782       * }
51783       *
51784       * // this function fires only when cnv is clicked
51785       * function changeGray() {
51786       *   g = random(0, 255);
51787       * }
51788       * </code></div>
51789       *
51790       *
51791       * @alt
51792       * no display.
51793       *
51794       */
51795
51796
51797      p5.Element.prototype.touchEnded = function (fxn) {
51798        p5.Element._adjustListener('touchend', fxn, this);
51799
51800        return this;
51801      };
51802      /**
51803       * The .<a href="#/p5.Element/dragOver">dragOver()</a> function is called once after every time a
51804       * file is dragged over the element. This can be used to attach an
51805       * element specific event listener.
51806       *
51807       * @method dragOver
51808       * @param  {Function|Boolean} fxn function to be fired when a file is
51809       *                                dragged over the element.
51810       *                                if `false` is passed instead, the previously
51811       *                                firing function will no longer fire.
51812       * @chainable
51813       * @example
51814       * <div><code>
51815       * // To test this sketch, simply drag a
51816       * // file over the canvas
51817       * function setup() {
51818       *   var c = createCanvas(100, 100);
51819       *   background(200);
51820       *   textAlign(CENTER);
51821       *   text('Drag file', width / 2, height / 2);
51822       *   c.dragOver(dragOverCallback);
51823       * }
51824       *
51825       * // This function will be called whenever
51826       * // a file is dragged over the canvas
51827       * function dragOverCallback() {
51828       *   background(240);
51829       *   text('Dragged over', width / 2, height / 2);
51830       * }
51831       * </code></div>
51832       * @alt
51833       * nothing displayed
51834       */
51835
51836
51837      p5.Element.prototype.dragOver = function (fxn) {
51838        p5.Element._adjustListener('dragover', fxn, this);
51839
51840        return this;
51841      };
51842      /**
51843       * The .dragLeave() function is called once after every time a
51844       * dragged file leaves the element area. This can be used to attach an
51845       * element specific event listener.
51846       *
51847       * @method dragLeave
51848       * @param  {Function|Boolean} fxn function to be fired when a file is
51849       *                                dragged off the element.
51850       *                                if `false` is passed instead, the previously
51851       *                                firing function will no longer fire.
51852       * @chainable
51853       * @example
51854       * <div><code>
51855       * // To test this sketch, simply drag a file
51856       * // over and then out of the canvas area
51857       * function setup() {
51858       *   var c = createCanvas(100, 100);
51859       *   background(200);
51860       *   textAlign(CENTER);
51861       *   text('Drag file', width / 2, height / 2);
51862       *   c.dragLeave(dragLeaveCallback);
51863       * }
51864       *
51865       * // This function will be called whenever
51866       * // a file is dragged out of the canvas
51867       * function dragLeaveCallback() {
51868       *   background(240);
51869       *   text('Dragged off', width / 2, height / 2);
51870       * }
51871       * </code></div>
51872       * @alt
51873       * nothing displayed
51874       */
51875
51876
51877      p5.Element.prototype.dragLeave = function (fxn) {
51878        p5.Element._adjustListener('dragleave', fxn, this);
51879
51880        return this;
51881      };
51882      /**
51883       * Registers a callback that gets called every time a file that is
51884       * dropped on the element has been loaded.
51885       * p5 will load every dropped file into memory and pass it as a p5.File object to the callback.
51886       * Multiple files dropped at the same time will result in multiple calls to the callback.
51887       *
51888       * You can optionally pass a second callback which will be registered to the raw
51889       * <a href="https://developer.mozilla.org/en-US/docs/Web/Events/drop">drop</a> event.
51890       * The callback will thus be provided the original
51891       * <a href="https://developer.mozilla.org/en-US/docs/Web/API/DragEvent">DragEvent</a>.
51892       * Dropping multiple files at the same time will trigger the second callback once per drop,
51893       * whereas the first callback will trigger for each loaded file.
51894       *
51895       * @method drop
51896       * @param  {Function} callback  callback to receive loaded file.
51897       * @param  {Function}
51897 [fxn]     callback triggered when files are dropped.
51898       * @chainable
51899       * @example
51900       * <div><code>
51901       * function setup() {
51902       *   var c = createCanvas(100, 100);
51903       *   background(200);
51904       *   textAlign(CENTER);
51905       *   text('drop file', width / 2, height / 2);
51906       *   c.drop(gotFile);
51907       * }
51908       *
51909       * function gotFile(file) {
51910       *   background(200);
51911       *   text('received file:', width / 2, height / 2);
51912       *   text(file.name, width / 2, height / 2 + 50);
51913       * }
51914       * </code></div>
51915       *
51916       * <div><code>
51917       * var img;
51918       *
51919       * function setup() {
51920       *   var c = createCanvas(100, 100);
51921       *   background(200);
51922       *   textAlign(CENTER);
51923       *   text('drop image', width / 2, height / 2);
51924       *   c.drop(gotFile);
51925       * }
51926       *
51927       * function draw() {
51928       *   if (img) {
51929       *     image(img, 0, 0, width, height);
51930       *   }
51931       * }
51932       *
51933       * function gotFile(file) {
51934       *   img = createImg(file.data).hide();
51935       * }
51936       * </code></div>
51937       *
51938       * @alt
51939       * Canvas turns into whatever image is dragged/dropped onto it.
51940       */
51941
51942
51943      p5.Element.prototype.drop = function (callback, fxn) {
51944        // Is the file stuff supported?
51945        if (window.File && window.FileReader && window.FileList && window.Blob) {
51946          if (!this._dragDisabled) {
51947            this._dragDisabled = true;
51948
51949            var preventDefault = function (evt) {
51950              evt.preventDefault();
51951            }; // If you want to be able to drop you've got to turn off
51952            // a lot of default behavior.
51953            // avoid `attachListener` here, since it overrides other handlers.
51954
51955
51956            this.elt.addEventListener('dragover', preventDefault); // If this is a drag area we need to turn off the default behavior
51957
51958            this.elt.addEventListener('dragleave', preventDefault);
51959          } // Attach the second argument as a callback that receives the raw drop event
51960
51961
51962          if (typeof fxn !== 'undefined') {
51963            p5.Element._attachListener('drop', fxn, this);
51964          } // Deal with the files
51965
51966
51967          p5.Element._attachListener('drop', function (evt) {
51968            evt.preventDefault(); // A FileList
51969
51970            var files = evt.dataTransfer.files; // Load each one and trigger the callback
51971
51972            for (var i = 0; i < files.length; i++) {
51973              var f = files[i];
51974
51975              p5.File._load(f, callback);
51976            }
51977          }, this);
51978        } else {
51979          console.log('The File APIs are not fully supported in this browser.');
51980        }
51981
51982        return this;
51983      }; // General handler for event attaching and detaching
51984
51985
51986      p5.Element._adjustListener = function (ev, fxn, ctx) {
51987        if (fxn === false) {
51988          p5.Element._detachListener(ev, ctx);
51989        } else {
51990          p5.Element._attachListener(ev, fxn, ctx);
51991        }
51992
51993        return this;
51994      };
51995
51996      p5.Element._attachListener = function (ev, fxn, ctx) {
51997        // detach the old listener if there was one
51998        if (ctx._events[ev]) {
51999          p5.Element._detachListener(ev, ctx);
52000        }
52001
52002        var f = fxn.bind(ctx);
52003        ctx.elt.addEventListener(ev, f, false);
52004        ctx._events[ev] = f;
52005      };
52006
52007      p5.Element._detachListener = function (ev, ctx) {
52008        var f = ctx._events[ev];
52009        ctx.elt.removeEventListener(ev, f, false);
52010        ctx._events[ev] = null;
52011      };
52012      /**
52013       * Helper fxn for sharing pixel methods
52014       *
52015       */
52016
52017
52018      p5.Element.prototype._setProperty = function (prop, value) {
52019        this[prop] = value;
52020      };
52021
52022      module.exports = p5.Element;
52023    }, {
52024      "./main": 24
52025    }],
52026    26: [function (_dereq_, module, exports) {
52027      /**
52028       * @module Rendering
52029       * @submodule Rendering
52030       * @for p5
52031       */
52032      'use strict';
52033
52034      var p5 = _dereq_('./main');
52035
52036      var constants = _dereq_('./constants');
52037      /**
52038       * Thin wrapper around a renderer, to be used for creating a
52039       * graphics buffer object. Use this class if you need
52040       * to draw into an off-screen graphics buffer. The two parameters define the
52041       * width and height in pixels. The fields and methods for this class are
52042       * extensive, but mirror the normal drawing API for p5.
52043       *
52044       * @class p5.Graphics
52045       * @extends p5.Element
52046       * @param {Number} w            width
52047       * @param {Number} h            height
52048       * @param {Constant} renderer   the renderer to use, either P2D or WEBGL
52049       * @param {p5} [pInst]          pointer to p5 instance
52050       */
52051
52052
52053      p5.Graphics = function (w, h, renderer, pInst) {
52054        var r = renderer || constants.P2D;
52055        this.canvas = document.createElement('canvas');
52056        var node = pInst._userNode || document.body;
52057        node.appendChild(this.canvas);
52058        p5.Element.call(this, this.canvas, pInst, false); // bind methods and props of p5 to the new object
52059
52060        for (var p in p5.prototype) {
52061          if (!this[p]) {
52062            if (typeof p5.prototype[p] === 'function') {
52063              this[p] = p5.prototype[p].bind(this);
52064            } else {
52065              this[p] = p5.prototype[p];
52066            }
52067          }
52068        }
52069
52070        p5.prototype._initializeInstanceVariables.apply(this);
52071
52072        this.width = w;
52073        this.height = h;
52074        this._pixelDensity = pInst._pixelDensity;
52075
52076        if (r === constants.WEBGL) {
52077          this._renderer = new p5.RendererGL(this.canvas, this, false);
52078        } else {
52079          this._renderer = new p5.Renderer2D(this.canvas, this, false);
52080        }
52081
52082        pInst._elements.push(this);
52083
52084        this._renderer.resize(w, h);
52085
52086        this._renderer._applyDefaults();
52087
52088        return this;
52089      };
52090
52091      p5.Graphics.prototype = Object.create(p5.Element.prototype);
52092      /**
52093       * Removes a Graphics object from the page and frees any resources
52094       * associated with it.
52095       *
52096       * @method remove
52097       *
52098       * @example
52099       * <div class='norender'><code>
52100       * let bg;
52101       * function setup() {
52102       *   bg = createCanvas(100, 100);
52103       *   bg.background(0);
52104       *   image(bg, 0, 0);
52105       *   bg.remove();
52106       * }
52107       * </code></div>
52108       *
52109       * <div><code>
52110       * let bg;
52111       * function setup() {
52112       *   pixelDensity(1);
52113       *   createCanvas(100, 100);
52114       *   stroke(255);
52115       *   fill(0);
52116       *
52117       *   // create and draw the background image
52118       *   bg = createGraphics(100, 100);
52119       *   bg.background(200);
52120       *   bg.ellipse(50, 50, 80, 80);
52121       * }
52122       * function draw() {
52123       *   let t = millis() / 1000;
52124       *   // draw the background
52125       *   if (bg) {
52126       *     image(bg, frameCount % 100, 0);
52127       *     image(bg, frameCount % 100 - 100, 0);
52128       *   }
52129       *   // draw the foreground
52130       *   let p = p5.Vector.fromAngle(t, 35).add(50, 50);
52131       *   ellipse(p.x, p.y, 30);
52132       * }
52133       * function mouseClicked() {
52134       *   // remove the background
52135       *   if (bg) {
52136       *     bg.remove();
52137       *     bg = null;
52138       *   }
52139       * }
52140       * </code></div>
52141       *
52142       * @alt
52143       * no image
52144       * a multi-colored circle moving back and forth over a scrolling background.
52145       *
52146       */
52147
52148      p5.Graphics.prototype.remove = function () {
52149        if (this.elt.parentNode) {
52150          this.elt.parentNode.removeChild(this.elt);
52151        }
52152
52153        var idx = this._pInst._elements.indexOf(this);
52154
52155        if (idx !== -1) {
52156          this._pInst._elements.splice(idx, 1);
52157        }
52158
52159        for (var elt_ev in this._events) {
52160          this.elt.removeEventListener(elt_ev, this._events[elt_ev]);
52161        }
52162      };
52163
52164      module.exports = p5.Graphics;
52165    }, {
52166      "./constants": 18,
52167      "./main": 24
52168    }],
52169    27: [function (_dereq_, module, exports) {
52170      /**
52171       * @module Rendering
52172       * @submodule Rendering
52173       * @for p5
52174       */
52175      'use strict';
52176
52177      var p5 = _dereq_('./main');
52178
52179      var constants = _dereq_('../core/constants');
52180      /**
52181       * Main graphics and rendering context, as well as the base API
52182       * implementation for p5.js "core". To be used as the superclass for
52183       * Renderer2D and Renderer3D classes, respecitvely.
52184       *
52185       * @class p5.Renderer
52186       * @constructor
52187       * @extends p5.Element
52188       * @param {String} elt DOM node that is wrapped
52189       * @param {p5} [pInst] pointer to p5 instance
52190       * @param {Boolean} [isMainCanvas] whether we're using it as main canvas
52191       */
52192
52193
52194      p5.Renderer = function (elt, pInst, isMainCanvas) {
52195        p5.Element.call(this, elt, pInst);
52196        this.canvas = elt;
52197
52198        if (isMainCanvas) {
52199          this._isMainCanvas = true; // for pixel method sharing with pimage
52200
52201          this._pInst._setProperty('_curElement', this);
52202
52203          this._pInst._setProperty('canvas', this.canvas);
52204
52205          this._pInst._setProperty('width', this.width);
52206
52207          this._pInst._setProperty('height', this.height);
52208        } else {
52209          // hide if offscreen buffer by default
52210          this.canvas.style.display = 'none';
52211          this._styles = []; // non-main elt styles stored in p5.Renderer
52212        }
52213
52214        this._textSize = 12;
52215        this._textLeading = 15;
52216        this._textFont = 'sans-serif';
52217        this._textStyle = constants.NORMAL;
52218        this._textAscent = null;
52219        this._textDescent = null;
52220        this._textAlign = constants.LEFT;
52221        this._textBaseline = constants.BASELINE;
52222        this._rectMode = constants.CORNER;
52223        this._ellipseMode = constants.CENTER;
52224        this._curveTightness = 0;
52225        this._imageMode = constants.CORNER;
52226        this._tint = null;
52227        this._doStroke = true;
52228        this._doFill = true;
52229        this._strokeSet = false;
52230        this._fillSet = false;
52231      };
52232
52233      p5.Renderer.prototype = Object.create(p5.Element.prototype); // the renderer should return a 'style' object that it wishes to
52234      // store on the push stack.
52235
52236      p5.Renderer.prototype.push = function () {
52237        return {
52238          properties: {
52239            _doStroke: this._doStroke,
52240            _strokeSet: this._strokeSet,
52241            _doFill: this._doFill,
52242            _fillSet: this._fillSet,
52243            _tint: this._tint,
52244            _imageMode: this._imageMode,
52245            _rectMode: this._rectMode,
52246            _ellipseMode: this._ellipseMode,
52247            _textFont: this._textFont,
52248            _textLeading: this._textLeading,
52249            _textSize: this._textSize,
52250            _textAlign: this._textAlign,
52251            _textBaseline: this._textBaseline,
52252            _textStyle: this._textStyle
52253          }
52254        };
52255      }; // a pop() operation is in progress
52256      // the renderer is passed the 'style' object that it returned
52257      // from its push() method.
52258
52259
52260      p5.Renderer.prototype.pop = function (style) {
52261        if (style.properties) {
52262          // copy the style properties back into the renderer
52263          Object.assign(this, style.properties);
52264        }
52265      };
52266      /**
52267       * Resize our canvas element.
52268       */
52269
52270
52271      p5.Renderer.prototype.resize = function (w, h) {
52272        this.width = w;
52273        this.height = h;
52274        this.elt.width = w * this._pInst._pixelDensity;
52275        this.elt.height = h * this._pInst._pixelDensity;
52276        this.elt.style.width = w + 'px';
52277        this.elt.style.height = h + 'px';
52278
52279        if (this._isMainCanvas) {
52280          this._pInst._setProperty('width', this.width);
52281
52282          this._pInst._setProperty('height', this.height);
52283        }
52284      };
52285
52286      p5.Renderer.prototype.textLeading = function (l) {
52287        if (typeof l === 'number') {
52288          this._setProperty('_textLeading', l);
52289
52290          return this._pInst;
52291        }
52292
52293        return this._textLeading;
52294      };
52295
52296      p5.Renderer.prototype.textSize = function (s) {
52297        if (typeof s === 'number') {
52298          this._setProperty('_textSize', s);
52299
52300          this._setProperty('_textLeading', s * constants._DEFAULT_LEADMULT);
52301
52302          return this._applyTextProperties();
52303        }
52304
52305        return this._textSize;
52306      };
52307
52308      p5.Renderer.prototype.textStyle = function (s) {
52309        if (s) {
52310          if (s === constants.NORMAL || s === constants.ITALIC || s === constants.BOLD || s === constants.BOLDITALIC) {
52311            this._setProperty('_textStyle', s);
52312          }
52313
52314          return this._applyTextProperties();
52315        }
52316
52317        return this._textStyle;
52318      };
52319
52320      p5.Renderer.prototype.textAscent = function () {
52321        if (this._textAscent === null) {
52322          this._updateTextMetrics();
52323        }
52324
52325        return this._textAscent;
52326      };
52327
52328      p5.Renderer.prototype.textDescent = function () {
52329        if (this._textDescent === null) {
52330          this._updateTextMetrics();
52331        }
52332
52333        return this._textDescent;
52334      };
52335
52336      p5.Renderer.prototype.textAlign = function (h, v) {
52337        if (typeof h !== 'undefined') {
52338          this._setProperty('_textAlign', h);
52339
52340          if (typeof v !== 'undefined') {
52341            this._setProperty('_textBaseline', v);
52342          }
52343
52344          return this._applyTextProperties();
52345        } else {
52346          return {
52347            horizontal: this._textAlign,
52348            vertical: this._textBaseline
52349          };
52350        }
52351      };
52352
52353      p5.Renderer.prototype.text = function (str, x, y, maxWidth, maxHeight) {
52354        var p = this._pInst,
52355            cars,
52356            n,
52357            ii,
52358            jj,
52359            line,
52360            testLine,
52361            testWidth,
52362            words,
52363            totalHeight,
52364            finalMaxHeight = Number.MAX_VALUE;
52365
52366        if (!(this._doFill || this._doStroke)) {
52367          return;
52368        }
52369
52370        if (typeof str === 'undefined') {
52371          return;
52372        } else if (typeof str !== 'string') {
52373          str = str.toString();
52374        }
52375
52376        str = str.replace(/(\t)/g, '  ');
52377        cars = str.split('\n');
52378
52379        if (typeof maxWidth !== 'undefined') {
52380          totalHeight = 0;
52381
52382          for (ii = 0; ii < cars.length; ii++) {
52383            line = '';
52384            words = cars[ii].split(' ');
52385
52386            for (n = 0; n < words.length; n++) {
52387              testLine = line + words[n] + ' ';
52388              testWidth = this.textWidth(testLine);
52389
52390              if (testWidth > maxWidth) {
52391                line = words[n] + ' ';
52392                totalHeight += p.textLeading();
52393              } else {
52394                line = testLine;
52395              }
52396            }
52397          }
52398
52399          if (this._rectMode === constants.CENTER) {
52400            x -= maxWidth / 2;
52401            y -= maxHeight / 2;
52402          }
52403
52404          switch (this._textAlign) {
52405            case constants.CENTER:
52406              x += maxWidth / 2;
52407              break;
52408
52409            case constants.RIGHT:
52410              x += maxWidth;
52411              break;
52412          }
52413
52414          var baselineHacked = false;
52415
52416          if (typeof maxHeight !== 'undefined') {
52417            switch (this._textBaseline) {
52418              case constants.BOTTOM:
52419                y += maxHeight - totalHeight;
52420                break;
52421
52422              case constants.CENTER:
52423                y += (maxHeight - totalHeight) / 2;
52424                break;
52425
52426              case constants.BASELINE:
52427                baselineHacked = true;
52428                this._textBaseline = constants.TOP;
52429                break;
52430            } // remember the max-allowed y-position for any line (fix to #928)
52431
52432
52433            finalMaxHeight = y + maxHeight - p.textAscent();
52434          }
52435
52436          for (ii = 0; ii < cars.length; ii++) {
52437            line = '';
52438            words = cars[ii].split(' ');
52439
52440            for (n = 0; n < words.length; n++) {
52441              testLine = line + words[n] + ' ';
52442              testWidth = this.textWidth(testLine);
52443
52444              if (testWidth > maxWidth && line.length > 0) {
52445                this._renderText(p, line, x, y, finalMaxHeight);
52446
52447                line = words[n] + ' ';
52448                y += p.textLeading();
52449              } else {
52450                line = testLine;
52451              }
52452            }
52453
52454            this._renderText(p, line, x, y, finalMaxHeight);
52455
52456            y += p.textLeading();
52457
52458            if (baselineHacked) {
52459              this._textBaseline = constants.BASELINE;
52460            }
52461          }
52462        } else {
52463          // Offset to account for vertically centering multiple lines of text - no
52464          // need to adjust anything for vertical align top or baseline
52465          var offset = 0,
52466              vAlign = p.textAlign().vertical;
52467
52468          if (vAlign === constants.CENTER) {
52469            offset = (cars.length - 1) * p.textLeading() / 2;
52470          } else if (vAlign === constants.BOTTOM) {
52471            offset = (cars.length - 1) * p.textLeading();
52472          }
52473
52474          for (jj = 0; jj < cars.length; jj++) {
52475            this._renderText(p, cars[jj], x, y - offset, finalMaxHeight);
52476
52477            y += p.textLeading();
52478          }
52479        }
52480
52481        return p;
52482      };
52483
52484      p5.Renderer.prototype._applyDefaults = function () {
52485        return this;
52486      };
52487      /**
52488       * Helper fxn to check font type (system or otf)
52489       */
52490
52491
52492      p5.Renderer.prototype._isOpenType = function (f) {
52493        f = f || this._textFont;
52494        return typeof f === 'object' && f.font && f.font.supported;
52495      };
52496
52497      p5.Renderer.prototype._updateTextMetrics = function () {
52498        if (this._isOpenType()) {
52499          this._setProperty('_textAscent', this._textFont._textAscent());
52500
52501          this._setProperty('_textDescent', this._textFont._textDescent());
52502
52503          return this;
52504        } // Adapted from http://stackoverflow.com/a/25355178
52505
52506
52507        var text = document.createElement('span');
52508        text.style.fontFamily = this._textFont;
52509        text.style.fontSize = this._textSize + 'px';
52510        text.innerHTML = 'ABCjgq|';
52511        var block = document.createElement('div');
52512        block.style.display = 'inline-block';
52513        block.style.width = '1px';
52514        block.style.height = '0px';
52515        var container = document.createElement('div');
52516        container.appendChild(text);
52517        container.appendChild(block);
52518        container.style.height = '0px';
52519        container.style.overflow = 'hidden';
52520        document.body.appendChild(container);
52521        block.style.verticalAlign = 'baseline';
52522        var blockOffset = calculateOffset(block);
52523        var textOffset = calculateOffset(text);
52524        var ascent = blockOffset[1] - textOffset[1];
52525        block.style.verticalAlign = 'bottom';
52526        blockOffset = calculateOffset(block);
52527        textOffset = calculateOffset(text);
52528        var height = blockOffset[1] - textOffset[1];
52529        var descent = height - ascent;
52530        document.body.removeChild(container);
52531
52532        this._setProperty('_textAscent', ascent);
52533
52534        this._setProperty('_textDescent', descent);
52535
52536        return this;
52537      };
52538      /**
52539       * Helper fxn to measure ascent and descent.
52540       * Adapted from http://stackoverflow.com/a/25355178
52541       */
52542
52543
52544      function calculateOffset(object) {
52545        var currentLeft = 0,
52546            currentTop = 0;
52547
52548        if (object.offsetParent) {
52549          do {
52550            currentLeft += object.offsetLeft;
52551            currentTop += object.offsetTop;
52552          } while (object = object.offsetParent);
52553        } else {
52554          currentLeft += object.offsetLeft;
52555          currentTop += object.offsetTop;
52556        }
52557
52558        return [currentLeft, currentTop];
52559      }
52560
52561      module.exports = p5.Renderer;
52562    }, {
52563      "../core/constants": 18,
52564      "./main": 24
52565    }],
52566    28: [function (_dereq_, module, exports) {
52567      'use strict';
52568
52569      var p5 = _dereq_('./main');
52570
52571      var constants = _dereq_('./constants');
52572
52573      var filters = _dereq_('../image/filters');
52574
52575      _dereq_('./p5.Renderer');
52576      /**
52577       * p5.Renderer2D
52578       * The 2D graphics canvas renderer class.
52579       * extends p5.Renderer
52580       */
52581
52582
52583      var styleEmpty = 'rgba(0,0,0,0)'; // var alphaThreshold = 0.00125; // minimum visible
52584
52585      p5.Renderer2D = function (elt, pInst, isMainCanvas) {
52586        p5.Renderer.call(this, elt, pInst, isMainCanvas);
52587        this.drawingContext = this.canvas.getContext('2d');
52588
52589        this._pInst._setProperty('drawingContext', this.drawingContext);
52590
52591        return this;
52592      };
52593
52594      p5.Renderer2D.prototype = Object.create(p5.Renderer.prototype);
52595
52596      p5.Renderer2D.prototype._applyDefaults = function () {
52597        this._cachedFillStyle = this._cachedStrokeStyle = undefined;
52598
52599        this._setFill(constants._DEFAULT_FILL);
52600
52601        this._setStroke(constants._DEFAULT_STROKE);
52602
52603        this.drawingContext.lineCap = constants.ROUND;
52604        this.drawingContext.font = 'normal 12px sans-serif';
52605      };
52606
52607      p5.Renderer2D.prototype.resize = function (w, h) {
52608        p5.Renderer.prototype.resize.call(this, w, h);
52609        this.drawingContext.scale(this._pInst._pixelDensity, this._pInst._pixelDensity);
52610      }; //////////////////////////////////////////////
52611      // COLOR | Setting
52612      //////////////////////////////////////////////
52613
52614
52615      p5.Renderer2D.prototype.background = function () {
52616        this.drawingContext.save();
52617        this.resetMatrix();
52618
52619        if (arguments[0] instanceof p5.Image) {
52620          this._pInst.image(arguments[0], 0, 0, this.width, this.height);
52621        } else {
52622          var curFill = this._getFill(); // create background rect
52623
52624
52625          var color = this._pInst.color.apply(this._pInst, arguments);
52626
52627          var newFill = color.toString();
52628
52629          this._setFill(newFill);
52630
52631          this.drawingContext.fillRect(0, 0, this.width, this.height); // reset fill
52632
52633          this._setFill(curFill);
52634        }
52635
52636        this.drawingContext.restore();
52637        this._pInst._pixelsDirty = true;
52638      };
52639
52640      p5.Renderer2D.prototype.clear = function () {
52641        this.drawingContext.save();
52642        this.resetMatrix();
52643        this.drawingContext.clearRect(0, 0, this.width, this.height);
52644        this.drawingContext.restore();
52645        this._pInst._pixelsDirty = true;
52646      };
52647
52648      p5.Renderer2D.prototype.fill = function () {
52649        var color = this._pInst.color.apply(this._pInst, arguments);
52650
52651        this._setFill(color.toString());
52652      };
52653
52654      p5.Renderer2D.prototype.stroke = function () {
52655        var color = this._pInst.color.apply(this._pInst, arguments);
52656
52657        this._setStroke(color.toString());
52658      }; //////////////////////////////////////////////
52659      // IMAGE | Loading & Displaying
52660      //////////////////////////////////////////////
52661
52662
52663      p5.Renderer2D.prototype.image = function (img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) {
52664        var cnv;
52665
52666        try {
52667          if (this._tint) {
52668            if (p5.MediaElement && img instanceof p5.MediaElement) {
52669              img.loadPixels();
52670            }
52671
52672            if (img.canvas) {
52673              cnv = this._getTintedImageCanvas(img);
52674            }
52675          }
52676
52677          if (!cnv) {
52678            cnv = img.canvas || img.elt;
52679          }
52680
52681          var s = 1;
52682
52683          if (img.width && img.width > 0) {
52684            s = cnv.width / img.width;
52685          }
52686
52687          this.drawingContext.drawImage(cnv, s * sx, s * sy, s * sWidth, s * sHeight, dx, dy, dWidth, dHeight);
52688        } catch (e) {
52689          if (e.name !== 'NS_ERROR_NOT_AVAILABLE') {
52690            throw e;
52691          }
52692        }
52693
52694        this._pInst._pixelsDirty = true;
52695      };
52696
52697      p5.Renderer2D.prototype._getTintedImageCanvas = function (img) {
52698        if (!img.canvas) {
52699          return img;
52700        }
52701
52702        var pixels = filters._toPixels(img.canvas);
52703
52704        var tmpCanvas = document.createElement('canvas');
52705        tmpCanvas.width = img.canvas.width;
52706        tmpCanvas.height = img.canvas.height;
52707        var tmpCtx = tmpCanvas.getContext('2d');
52708        var id = tmpCtx.createImageData(img.canvas.width, img.canvas.height);
52709        var newPixels = id.data;
52710
52711        for (var i = 0; i < pixels.length; i += 4) {
52712          var r = pixels[i];
52713          var g = pixels[i + 1];
52714          var b = pixels[i + 2];
52715          var a = pixels[i + 3];
52716          newPixels[i] = r * this._tint[0] / 255;
52717          newPixels[i + 1] = g * this._tint[1] / 255;
52718          newPixels[i + 2] = b * this._tint[2] / 255;
52719          newPixels[i + 3] = a * this._tint[3] / 255;
52720        }
52721
52722        tmpCtx.putImageData(id, 0, 0);
52723        return tmpCanvas;
52724      }; //////////////////////////////////////////////
52725      // IMAGE | Pixels
52726      //////////////////////////////////////////////
52727
52728
52729      p5.Renderer2D.prototype.blendMode = function (mode) {
52730        this.drawingContext.globalCompositeOperation = mode;
52731      };
52732
52733      p5.Renderer2D.prototype.blend = function () {
52734        var currBlend = this.drawingContext.globalCompositeOperation;
52735        var blendMode = arguments[arguments.length - 1];
52736        var copyArgs = Array.prototype.slice.call(arguments, 0, arguments.length - 1);
52737        this.drawingContext.globalCompositeOperation = blendMode;
52738
52739        if (this._pInst) {
52740          this._pInst.copy.apply(this._pInst, copyArgs);
52741        } else {
52742          this.copy.apply(this, copyArgs);
52743        }
52744
52745        this.drawingContext.globalCompositeOperation = currBlend;
52746      };
52747
52748      p5.Renderer2D.prototype.copy = function () {
52749        var srcImage, sx, sy, sw, sh, dx, dy, dw, dh;
52750
52751        if (arguments.length === 9) {
52752          srcImage = arguments[0];
52753          sx = arguments[1];
52754          sy = arguments[2];
52755          sw = arguments[3];
52756          sh = arguments[4];
52757          dx = arguments[5];
52758          dy = arguments[6];
52759          dw = arguments[7];
52760          dh = arguments[8];
52761        } else if (arguments.length === 8) {
52762          srcImage = this._pInst;
52763          sx = arguments[0];
52764          sy = arguments[1];
52765          sw = arguments[2];
52766          sh = arguments[3];
52767          dx = arguments[4];
52768          dy = arguments[5];
52769          dw = arguments[6];
52770          dh = arguments[7];
52771        } else {
52772          throw new Error('Signature not supported');
52773        }
52774
52775        p5.Renderer2D._copyHelper(this, srcImage, sx, sy, sw, sh, dx, dy, dw, dh);
52776
52777        this._pInst._pixelsDirty = true;
52778      };
52779
52780      p5.Renderer2D._copyHelper = function (dstImage, srcImage, sx, sy, sw, sh, dx, dy, dw, dh) {
52781        srcImage.loadPixels();
52782        var s = srcImage.canvas.width / srcImage.width;
52783        dstImage.drawingContext.drawImage(srcImage.canvas, s * sx, s * sy, s * sw, s * sh, dx, dy, dw, dh);
52784      };
52785
52786      p5.Renderer2D.prototype.get = function (x, y, w, h) {
52787        var ctx = this._pInst || this;
52788        var pd = ctx._pixelDensity;
52789        var sx = x * pd;
52790        var sy = y * pd;
52791
52792        if (w === 1 && h === 1) {
52793          var imageData, index;
52794
52795          if (ctx._pixelsDirty) {
52796            imageData = this.drawingContext.getImageData(sx, sy, 1, 1).data;
52797            index = 0;
52798          } else {
52799            imageData = ctx.pixels;
52800            index = (sx + sy * this.width * pd) * 4;
52801          }
52802
52803          return [imageData[index + 0], imageData[index + 1], imageData[index + 2], imageData[index + 3]];
52804        } else {
52805          //auto constrain the width and height to
52806          //dimensions of the source image
52807          var dw = Math.min(w, ctx.width);
52808          var dh = Math.min(h, ctx.height);
52809          var sw = dw * pd;
52810          var sh = dh * pd;
52811          var region = new p5.Image(dw, dh);
52812          region.canvas.getContext('2d').drawImage(this.canvas, sx, sy, sw, sh, 0, 0, dw, dh);
52813          return region;
52814        }
52815      };
52816
52817      p5.Renderer2D.prototype.loadPixels = function () {
52818        var ctx = this._pInst || this; // if called by p5.Image
52819
52820        if (!ctx._pixelsDirty) return;
52821        ctx._pixelsDirty = false;
52822        var pd = ctx._pixelDensity;
52823        var w = this.width * pd;
52824        var h = this.height * pd;
52825        var imageData = this.drawingContext.getImageData(0, 0, w, h); // @todo this should actually set pixels per object, so diff buffers can
52826        // have diff pixel arrays.
52827
52828        ctx._setProperty('imageData', imageData);
52829
52830        ctx._setProperty('pixels', imageData.data);
52831      };
52832
52833      p5.Renderer2D.prototype.set = function (x, y, imgOrCol) {
52834        // round down to get integer numbers
52835        x = Math.floor(x);
52836        y = Math.floor(y);
52837        var ctx = this._pInst || this;
52838
52839        if (imgOrCol instanceof p5.Image) {
52840          this.drawingContext.save();
52841          this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
52842          this.drawingContext.scale(ctx._pixelDensity, ctx._pixelDensity);
52843          this.drawingContext.drawImage(imgOrCol.canvas, x, y);
52844          this.drawingContext.restore();
52845          ctx._pixelsDirty = true;
52846        } else {
52847          var r = 0,
52848              g = 0,
52849              b = 0,
52850              a = 0;
52851          var idx = 4 * (y * ctx._pixelDensity * (this.width * ctx._pixelDensity) + x * ctx._pixelDensity);
52852
52853          if (!ctx.imageData || ctx._pixelsDirty) {
52854            ctx.loadPixels.call(ctx);
52855          }
52856
52857          if (typeof imgOrCol === 'number') {
52858            if (idx < ctx.pixels.length) {
52859              r = imgOrCol;
52860              g = imgOrCol;
52861              b = imgOrCol;
52862              a = 255; //this.updatePixels.call(this);
52863            }
52864          } else if (imgOrCol instanceof Array) {
52865            if (imgOrCol.length < 4) {
52866              throw new Error('pixel array must be of the form [R, G, B, A]');
52867            }
52868
52869            if (idx < ctx.pixels.length) {
52870              r = imgOrCol[0];
52871              g = imgOrCol[1];
52872              b = imgOrCol[2];
52873              a = imgOrCol[3]; //this.updatePixels.call(this);
52874            }
52875          } else if (imgOrCol instanceof p5.Color) {
52876            if (idx < ctx.pixels.length) {
52877              r = imgOrCol.levels[0];
52878              g = imgOrCol.levels[1];
52879              b = imgOrCol.levels[2];
52880              a = imgOrCol.levels[3]; //this.updatePixels.call(this);
52881            }
52882          } // loop over pixelDensity * pixelDensity
52883
52884
52885          for (var i = 0; i < ctx._pixelDensity; i++) {
52886            for (var j = 0; j < ctx._pixelDensity; j++) {
52887              // loop over
52888              idx = 4 * ((y * ctx._pixelDensity + j) * this.width * ctx._pixelDensity + (x * ctx._pixelDensity + i));
52889              ctx.pixels[idx] = r;
52890              ctx.pixels[idx + 1] = g;
52891              ctx.pixels[idx + 2] = b;
52892              ctx.pixels[idx + 3] = a;
52893            }
52894          }
52895        }
52896      };
52897
52898      p5.Renderer2D.prototype.updatePixels = function (x, y, w, h) {
52899        var ctx = this._pInst || this;
52900        var pd = ctx._pixelDensity;
52901
52902        if (x === undefined && y === undefined && w === undefined && h === undefined) {
52903          x = 0;
52904          y = 0;
52905          w = this.width;
52906          h = this.height;
52907        }
52908
52909        w *= pd;
52910        h *= pd;
52911        this.drawingContext.putImageData(ctx.imageData, x, y, 0, 0, w, h);
52912
52913        if (x !== 0 || y !== 0 || w !== this.width || h !== this.height) {
52914          ctx._pixelsDirty = true;
52915        }
52916      }; //////////////////////////////////////////////
52917      // SHAPE | 2D Primitives
52918      //////////////////////////////////////////////
52919
52920      /**
52921       * Generate a cubic Bezier representing an arc on the unit circle of total
52922       * angle `size` radians, beginning `start` radians above the x-axis. Up to
52923       * four of these curves are combined to make a full arc.
52924       *
52925       * See www.joecridge.me/bezier.pdf for an explanation of the method.
52926       */
52927
52928
52929      p5.Renderer2D.prototype._acuteArcToBezier = function _acuteArcToBezier(start, size) {
52930        // Evauate constants.
52931        var alpha = size / 2.0,
52932            cos_alpha = Math.cos(alpha),
52933            sin_alpha = Math.sin(alpha),
52934            cot_alpha = 1.0 / Math.tan(alpha),
52935            phi = start + alpha,
52936            // This is how far the arc needs to be rotated.
52937        cos_phi = Math.cos(phi),
52938            sin_phi = Math.sin(phi),
52939            lambda = (4.0 - cos_alpha) / 3.0,
52940            mu = sin_alpha + (cos_alpha - lambda) * cot_alpha; // Return rotated waypoints.
52941
52942        return {
52943          ax: Math.cos(start),
52944          ay: Math.sin(start),
52945          bx: lambda * cos_phi + mu * sin_phi,
52946          by: lambda * sin_phi - mu * cos_phi,
52947          cx: lambda * cos_phi - mu * sin_phi,
52948          cy: lambda * sin_phi + mu * cos_phi,
52949          dx: Math.cos(start + size),
52950          dy: Math.sin(start + size)
52951        };
52952      };
52953
52954      p5.Renderer2D.prototype.arc = function (x, y, w, h, start, stop, mode) {
52955        var ctx = this.drawingContext;
52956        var rx = w / 2.0;
52957        var ry = h / 2.0;
52958        var epsilon = 0.00001; // Smallest visible angle on displays up to 4K.
52959
52960        var arcToDraw = 0;
52961        var curves = [];
52962        x += rx;
52963        y += ry; // Create curves
52964
52965        while (stop - start > epsilon) {
52966          arcToDraw = Math.min(stop - start, constants.HALF_PI);
52967          curves.push(this._acuteArcToBezier(start, arcToDraw));
52968          start += arcToDraw;
52969        } // Fill curves
52970
52971
52972        if (this._doFill) {
52973          ctx.beginPath();
52974          curves.forEach(function (curve, index) {
52975            if (index === 0) {
52976              ctx.moveTo(x + curve.ax * rx, y + curve.ay * ry);
52977            } // prettier-ignore
52978
52979
52980            ctx.bezierCurveTo(x + curve.bx * rx, y + curve.by * ry, x + curve.cx * rx, y + curve.cy * ry, x + curve.dx * rx, y + curve.dy * ry);
52981          });
52982
52983          if (mode === constants.PIE || mode == null) {
52984            ctx.lineTo(x, y);
52985          }
52986
52987          ctx.closePath();
52988          ctx.fill();
52989        } // Stroke curves
52990
52991
52992        if (this._doStroke) {
52993          ctx.beginPath();
52994          curves.forEach(function (curve, index) {
52995            if (index === 0) {
52996              ctx.moveTo(x + curve.ax * rx, y + curve.ay * ry);
52997            } // prettier-ignore
52998
52999
53000            ctx.bezierCurveTo(x + curve.bx * rx, y + curve.by * ry, x + curve.cx * rx, y + curve.cy * ry, x + curve.dx * rx, y + curve.dy * ry);
53001          });
53002
53003          if (mode === constants.PIE) {
53004            ctx.lineTo(x, y);
53005            ctx.closePath();
53006          } else if (mode === constants.CHORD) {
53007            ctx.closePath();
53008          }
53009
53010          ctx.stroke();
53011        }
53012
53013        return this;
53014      };
53015
53016      p5.Renderer2D.prototype.ellipse = function (args) {
53017        var ctx = this.drawingContext;
53018        var doFill = this._doFill,
53019            doStroke = this._doStroke;
53020        var x = args[0],
53021            y = args[1],
53022            w = args[2],
53023            h = args[3];
53024
53025        if (doFill && !doStroke) {
53026          if (this._getFill() === styleEmpty) {
53027            return this;
53028          }
53029        } else if (!doFill && doStroke) {
53030          if (this._getStroke() === styleEmpty) {
53031            return this;
53032          }
53033        }
53034
53035        var kappa = 0.5522847498,
53036            ox = w / 2 * kappa,
53037            // control point offset horizontal
53038        oy = h / 2 * kappa,
53039            // control point offset vertical
53040        xe = x + w,
53041            // x-end
53042        ye = y + h,
53043            // y-end
53044        xm = x + w / 2,
53045            // x-middle
53046        ym = y + h / 2; // y-middle
53047
53048        ctx.beginPath();
53049        ctx.moveTo(x, ym);
53050        ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
53051        ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
53052        ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
53053        ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
53054        ctx.closePath();
53055
53056        if (doFill) {
53057          ctx.fill();
53058        }
53059
53060        if (doStroke) {
53061          ctx.stroke();
53062        }
53063      };
53064
53065      p5.Renderer2D.prototype.line = function (x1, y1, x2, y2) {
53066        var ctx = this.drawingContext;
53067
53068        if (!this._doStroke) {
53069          return this;
53070        } else if (this._getStroke() === styleEmpty) {
53071          return this;
53072        } // Translate the line by (0.5, 0.5) to draw it crisp
53073
53074
53075        if (ctx.lineWidth % 2 === 1) {
53076          ctx.translate(0.5, 0.5);
53077        }
53078
53079        ctx.beginPath();
53080        ctx.moveTo(x1, y1);
53081        ctx.lineTo(x2, y2);
53082        ctx.stroke();
53083
53084        if (ctx.lineWidth % 2 === 1) {
53085          ctx.translate(-0.5, -0.5);
53086        }
53087
53088        return this;
53089      };
53090
53091      p5.Renderer2D.prototype.point = function (x, y) {
53092        var ctx = this.drawingContext;
53093
53094        if (!this._doStroke) {
53095          return this;
53096        } else if (this._getStroke() === styleEmpty) {
53097          return this;
53098        }
53099
53100        var s = this._getStroke();
53101
53102        var f = this._getFill();
53103
53104        x = Math.round(x);
53105        y = Math.round(y); // swapping fill color to stroke and back after for correct point rendering
53106
53107        this._setFill(s);
53108
53109        if (ctx.lineWidth > 1) {
53110          ctx.beginPath();
53111          ctx.arc(x, y, ctx.lineWidth / 2, 0, constants.TWO_PI, false);
53112          ctx.fill();
53113        } else {
53114          ctx.fillRect(x, y, 1, 1);
53115        }
53116
53117        this._setFill(f);
53118      };
53119
53120      p5.Renderer2D.prototype.quad = function (x1, y1, x2, y2, x3, y3, x4, y4) {
53121        var ctx = this.drawingContext;
53122        var doFill = this._doFill,
53123            doStroke = this._doStroke;
53124
53125        if (doFill && !doStroke) {
53126          if (this._getFill() === styleEmpty) {
53127            return this;
53128          }
53129        } else if (!doFill && doStroke) {
53130          if (this._getStroke() === styleEmpty) {
53131            return this;
53132          }
53133        }
53134
53135        ctx.beginPath();
53136        ctx.moveTo(x1, y1);
53137        ctx.lineTo(x2, y2);
53138        ctx.lineTo(x3, y3);
53139        ctx.lineTo(x4, y4);
53140        ctx.closePath();
53141
53142        if (doFill) {
53143          ctx.fill();
53144        }
53145
53146        if (doStroke) {
53147          ctx.stroke();
53148        }
53149
53150        return this;
53151      };
53152
53153      p5.Renderer2D.prototype.rect = function (args) {
53154        var x = args[0],
53155            y = args[1],
53156            w = args[2],
53157            h = args[3],
53158            tl = args[4],
53159            tr = args[5],
53160            br = args[6],
53161            bl = args[7];
53162        var ctx = this.drawingContext;
53163        var doFill = this._doFill,
53164            doStroke = this._doStroke;
53165
53166        if (doFill && !doStroke) {
53167          if (this._getFill() === styleEmpty) {
53168            return this;
53169          }
53170        } else if (!doFill && doStroke) {
53171          if (this._getStroke() === styleEmpty) {
53172            return this;
53173          }
53174        } // Translate the line by (0.5, 0.5) to draw a crisp rectangle border
53175
53176
53177        if (this._doStroke && ctx.lineWidth % 2 === 1) {
53178          ctx.translate(0.5, 0.5);
53179        }
53180
53181        ctx.beginPath();
53182
53183        if (typeof tl === 'undefined') {
53184          // No rounded corners
53185          ctx.rect(x, y, w, h);
53186        } else {
53187          // At least one rounded corner
53188          // Set defaults when not specified
53189          if (typeof tr === 'undefined') {
53190            tr = tl;
53191          }
53192
53193          if (typeof br === 'undefined') {
53194            br = tr;
53195          }
53196
53197          if (typeof bl === 'undefined') {
53198            bl = br;
53199          }
53200
53201          var hw = w / 2;
53202          var hh = h / 2; // Clip radii
53203
53204          if (w < 2 * tl) {
53205            tl = hw;
53206          }
53207
53208          if (h < 2 * tl) {
53209            tl = hh;
53210          }
53211
53212          if (w < 2 * tr) {
53213            tr = hw;
53214          }
53215
53216          if (h < 2 * tr) {
53217            tr = hh;
53218          }
53219
53220          if (w < 2 * br) {
53221            br = hw;
53222          }
53223
53224          if (h < 2 * br) {
53225            br = hh;
53226          }
53227
53228          if (w < 2 * bl) {
53229            bl = hw;
53230          }
53231
53232          if (h < 2 * bl) {
53233            bl = hh;
53234          } // Draw shape
53235
53236
53237          ctx.beginPath();
53238          ctx.moveTo(x + tl, y);
53239          ctx.arcTo(x + w, y, x + w, y + h, tr);
53240          ctx.arcTo(x + w, y + h, x, y + h, br);
53241          ctx.arcTo(x, y + h, x, y, bl);
53242          ctx.arcTo(x, y, x + w, y, tl);
53243          ctx.closePath();
53244        }
53245
53246        if (this._doFill) {
53247          ctx.fill();
53248        }
53249
53250        if (this._doStroke) {
53251          ctx.stroke();
53252        }
53253
53254        if (this._doStroke && ctx.lineWidth % 2 === 1) {
53255          ctx.translate(-0.5, -0.5);
53256        }
53257
53258        return this;
53259      };
53260
53261      p5.Renderer2D.prototype.triangle = function (args) {
53262        var ctx = this.drawingContext;
53263        var doFill = this._doFill,
53264            doStroke = this._doStroke;
53265        var x1 = args[0],
53266            y1 = args[1];
53267        var x2 = args[2],
53268            y2 = args[3];
53269        var x3 = args[4],
53270            y3 = args[5];
53271
53272        if (doFill && !doStroke) {
53273          if (this._getFill() === styleEmpty) {
53274            return this;
53275          }
53276        } else if (!doFill && doStroke) {
53277          if (this._getStroke() === styleEmpty) {
53278            return this;
53279          }
53280        }
53281
53282        ctx.beginPath();
53283        ctx.moveTo(x1, y1);
53284        ctx.lineTo(x2, y2);
53285        ctx.lineTo(x3, y3);
53286        ctx.closePath();
53287
53288        if (doFill) {
53289          ctx.fill();
53290        }
53291
53292        if (doStroke) {
53293          ctx.stroke();
53294        }
53295      };
53296
53297      p5.Renderer2D.prototype.endShape = function (mode, vertices, isCurve, isBezier, isQuadratic, isContour, shapeKind) {
53298        if (vertices.length === 0) {
53299          return this;
53300        }
53301
53302        if (!this._doStroke && !this._doFill) {
53303          return this;
53304        }
53305
53306        var closeShape = mode === constants.CLOSE;
53307        var v;
53308
53309        if (closeShape && !isContour) {
53310          vertices.push(vertices[0]);
53311        }
53312
53313        var i, j;
53314        var numVerts = vertices.length;
53315
53316        if (isCurve && (shapeKind === constants.POLYGON || shapeKind === null)) {
53317          if (numVerts > 3) {
53318            var b = [],
53319                s = 1 - this._curveTightness;
53320            this.drawingContext.beginPath();
53321            this.drawingContext.moveTo(vertices[1][0], vertices[1][1]);
53322
53323            for (i = 1; i + 2 < numVerts; i++) {
53324              v = vertices[i];
53325              b[0] = [v[0], v[1]];
53326              b[1] = [v[0] + (s * vertices[i + 1][0] - s * vertices[i - 1][0]) / 6, v[1] + (s * vertices[i + 1][1] - s * vertices[i - 1][1]) / 6];
53327              b[2] = [vertices[i + 1][0] + (s * vertices[i][0] - s * vertices[i + 2][0]) / 6, vertices[i + 1][1] + (s * vertices[i][1] - s * vertices[i + 2][1]) / 6];
53328              b[3] = [vertices[i + 1][0], vertices[i + 1][1]];
53329              this.drawingContext.bezierCurveTo(b[1][0], b[1][1], b[2][0], b[2][1], b[3][0], b[3][1]);
53330            }
53331
53332            if (closeShape) {
53333              this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
53334            }
53335
53336            this._doFillStrokeClose(closeShape);
53337          }
53338        } else if (isBezier && (shapeKind === constants.POLYGON || shapeKind === null)) {
53339          this.drawingContext.beginPath();
53340
53341          for (i = 0; i < numVerts; i++) {
53342            if (vertices[i].isVert) {
53343              if (vertices[i].moveTo) {
53344                this.drawingContext.moveTo(vertices[i][0], vertices[i][1]);
53345              } else {
53346                this.drawingContext.lineTo(vertices[i][0], vertices[i][1]);
53347              }
53348            } else {
53349              this.drawingContext.bezierCurveTo(vertices[i][0], vertices[i][1], vertices[i][2], vertices[i][3], vertices[i][4], vertices[i][5]);
53350            }
53351          }
53352
53353          this._doFillStrokeClose(closeShape);
53354        } else if (isQuadratic && (shapeKind === constants.POLYGON || shapeKind === null)) {
53355          this.drawingContext.beginPath();
53356
53357          for (i = 0; i < numVerts; i++) {
53358            if (vertices[i].isVert) {
53359              if (vertices[i].moveTo) {
53360                this.drawingContext.moveTo([0], vertices[i][1]);
53361              } else {
53362                this.drawingContext.lineTo(vertices[i][0], vertices[i][1]);
53363              }
53364            } else {
53365              this.drawingContext.quadraticCurveTo(vertices[i][0], vertices[i][1], vertices[i][2], vertices[i][3]);
53366            }
53367          }
53368
53369          this._doFillStrokeClose(closeShape);
53370        } else {
53371          if (shapeKind === constants.POINTS) {
53372            for (i = 0; i < numVerts; i++) {
53373              v = vertices[i];
53374
53375              if (this._doStroke) {
53376                this._pInst.stroke(v[6]);
53377              }
53378
53379              this._pInst.point(v[0], v[1]);
53380            }
53381          } else if (shapeKind === constants.LINES) {
53382            for (i = 0; i + 1 < numVerts; i += 2) {
53383              v = vertices[i];
53384
53385              if (this._doStroke) {
53386                this._pInst.stroke(vertices[i + 1][6]);
53387              }
53388
53389              this._pInst.line(v[0], v[1], vertices[i + 1][0], vertices[i + 1][1]);
53390            }
53391          } else if (shapeKind === constants.TRIANGLES) {
53392            for (i = 0; i + 2 < numVerts; i += 3) {
53393              v = vertices[i];
53394              this.drawingContext.beginPath();
53395              this.drawingContext.moveTo(v[0], v[1]);
53396              this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
53397              this.drawingContext.lineTo(vertices[i + 2][0], vertices[i + 2][1]);
53398              this.drawingContext.closePath();
53399
53400              if (this._doFill) {
53401                this._pInst.fill(vertices[i + 2][5]);
53402
53403                this.drawingContext.fill();
53404              }
53405
53406              if (this._doStroke) {
53407                this._pInst.stroke(vertices[i + 2][6]);
53408
53409                this.drawingContext.stroke();
53410              }
53411            }
53412          } else if (shapeKind === constants.TRIANGLE_STRIP) {
53413            for (i = 0; i + 1 < numVerts; i++) {
53414              v = vertices[i];
53415              this.drawingContext.beginPath();
53416              this.drawingContext.moveTo(vertices[i + 1][0], vertices[i + 1][1]);
53417              this.drawingContext.lineTo(v[0], v[1]);
53418
53419              if (this._doStroke) {
53420                this._pInst.stroke(vertices[i + 1][6]);
53421              }
53422
53423              if (this._doFill) {
53424                this._pInst.fill(vertices[i + 1][5]);
53425              }
53426
53427              if (i + 2 < numVerts) {
53428                this.drawingContext.lineTo(vertices[i + 2][0], vertices[i + 2][1]);
53429
53430                if (this._doStroke) {
53431                  this._pInst.stroke(vertices[i + 2][6]);
53432                }
53433
53434                if (this._doFill) {
53435                  this._pInst.fill(vertices[i + 2][5]);
53436                }
53437              }
53438
53439              this._doFillStrokeClose(closeShape);
53440            }
53441          } else if (shapeKind === constants.TRIANGLE_FAN) {
53442            if (numVerts > 2) {
53443              // For performance reasons, try to batch as many of the
53444              // fill and stroke calls as possible.
53445              this.drawingContext.beginPath();
53446
53447              for (i = 2; i < numVerts; i++) {
53448                v = vertices[i];
53449                this.drawingContext.moveTo(vertices[0][0], vertices[0][1]);
53450                this.drawingContext.lineTo(vertices[i - 1][0], vertices[i - 1][1]);
53451                this.drawingContext.lineTo(v[0], v[1]);
53452                this.drawingContext.lineTo(vertices[0][0], vertices[0][1]); // If the next colour is going to be different, stroke / fill now
53453
53454                if (i < numVerts - 1) {
53455                  if (this._doFill && v[5] !== vertices[i + 1][5] || this._doStroke && v[6] !== vertices[i + 1][6]) {
53456                    if (this._doFill) {
53457                      this._pInst.fill(v[5]);
53458
53459                      this.drawingContext.fill();
53460
53461                      this._pInst.fill(vertices[i + 1][5]);
53462                    }
53463
53464                    if (this._doStroke) {
53465                      this._pInst.stroke(v[6]);
53466
53467                      this.drawingContext.stroke();
53468
53469                      this._pInst.stroke(vertices[i + 1][6]);
53470                    }
53471
53472                    this.drawingContext.closePath();
53473                    this.drawingContext.beginPath(); // Begin the next one
53474                  }
53475                }
53476              }
53477
53478              this._doFillStrokeClose(closeShape);
53479            }
53480          } else if (shapeKind === constants.QUADS) {
53481            for (i = 0; i + 3 < numVerts; i += 4) {
53482              v = vertices[i];
53483              this.drawingContext.beginPath();
53484              this.drawingContext.moveTo(v[0], v[1]);
53485
53486              for (j = 1; j < 4; j++) {
53487                this.drawingContext.lineTo(vertices[i + j][0], vertices[i + j][1]);
53488              }
53489
53490              this.drawingContext.lineTo(v[0], v[1]);
53491
53492              if (this._doFill) {
53493                this._pInst.fill(vertices[i + 3][5]);
53494              }
53495
53496              if (this._doStroke) {
53497                this._pInst.stroke(vertices[i + 3][6]);
53498              }
53499
53500              this._doFillStrokeClose(closeShape);
53501            }
53502          } else if (shapeKind === constants.QUAD_STRIP) {
53503            if (numVerts > 3) {
53504              for (i = 0; i + 1 < numVerts; i += 2) {
53505                v = vertices[i];
53506                this.drawingContext.beginPath();
53507
53508                if (i + 3 < numVerts) {
53509                  this.drawingContext.moveTo(vertices[i + 2][0], vertices[i + 2][1]);
53510                  this.drawingContext.lineTo(v[0], v[1]);
53511                  this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
53512                  this.drawingContext.lineTo(vertices[i + 3][0], vertices[i + 3][1]);
53513
53514                  if (this._doFill) {
53515                    this._pInst.fill(vertices[i + 3][5]);
53516                  }
53517
53518                  if (this._doStroke) {
53519                    this._pInst.stroke(vertices[i + 3][6]);
53520                  }
53521                } else {
53522                  this.drawingContext.moveTo(v[0], v[1]);
53523                  this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
53524                }
53525
53526                this._doFillStrokeClose(closeShape);
53527              }
53528            }
53529          } else {
53530            this.drawingContext.beginPath();
53531            this.drawingContext.moveTo(vertices[0][0], vertices[0][1]);
53532
53533            for (i = 1; i < numVerts; i++) {
53534              v = vertices[i];
53535
53536              if (v.isVert) {
53537                if (v.moveTo) {
53538                  this.drawingContext.moveTo(v[0], v[1]);
53539                } else {
53540                  this.drawingContext.lineTo(v[0], v[1]);
53541                }
53542              }
53543            }
53544
53545            this._doFillStrokeClose(closeShape);
53546          }
53547        }
53548
53549        isCurve = false;
53550        isBezier = false;
53551        isQuadratic = false;
53552        isContour = false;
53553
53554        if (closeShape) {
53555          vertices.pop();
53556        }
53557
53558        this._pInst._pixelsDirty = true;
53559        return this;
53560      }; //////////////////////////////////////////////
53561      // SHAPE | Attributes
53562      //////////////////////////////////////////////
53563
53564
53565      p5.Renderer2D.prototype.noSmooth = function () {
53566        if ('imageSmoothingEnabled' in this.drawingContext) {
53567          this.drawingContext.imageSmoothingEnabled = false;
53568        }
53569
53570        return this;
53571      };
53572
53573      p5.Renderer2D.prototype.smooth = function () {
53574        if ('imageSmoothingEnabled' in this.drawingContext) {
53575          this.drawingContext.imageSmoothingEnabled = true;
53576        }
53577
53578        return this;
53579      };
53580
53581      p5.Renderer2D.prototype.strokeCap = function (cap) {
53582        if (cap === constants.ROUND || cap === constants.SQUARE || cap === constants.PROJECT) {
53583          this.drawingContext.lineCap = cap;
53584        }
53585
53586        return this;
53587      };
53588
53589      p5.Renderer2D.prototype.strokeJoin = function (join) {
53590        if (join === constants.ROUND || join === constants.BEVEL || join === constants.MITER) {
53591          this.drawingContext.lineJoin = join;
53592        }
53593
53594        return this;
53595      };
53596
53597      p5.Renderer2D.prototype.strokeWeight = function (w) {
53598        if (typeof w === 'undefined' || w === 0) {
53599          // hack because lineWidth 0 doesn't work
53600          this.drawingContext.lineWidth = 0.0001;
53601        } else {
53602          this.drawingContext.lineWidth = w;
53603        }
53604
53605        return this;
53606      };
53607
53608      p5.Renderer2D.prototype._getFill = function () {
53609        if (!this._cachedFillStyle) {
53610          this._cachedFillStyle = this.drawingContext.fillStyle;
53611        }
53612
53613        return this._cachedFillStyle;
53614      };
53615
53616      p5.Renderer2D.prototype._setFill = function (fillStyle) {
53617        if (fillStyle !== this._cachedFillStyle) {
53618          this.drawingContext.fillStyle = fillStyle;
53619          this._cachedFillStyle = fillStyle;
53620        }
53621      };
53622
53623      p5.Renderer2D.prototype._getStroke = function () {
53624        if (!this._cachedStrokeStyle) {
53625          this._cachedStrokeStyle = this.drawingContext.strokeStyle;
53626        }
53627
53628        return this._cachedStrokeStyle;
53629      };
53630
53631      p5.Renderer2D.prototype._setStroke = function (strokeStyle) {
53632        if (strokeStyle !== this._cachedStrokeStyle) {
53633          this.drawingContext.strokeStyle = strokeStyle;
53634          this._cachedStrokeStyle = strokeStyle;
53635        }
53636      }; //////////////////////////////////////////////
53637      // SHAPE | Curves
53638      //////////////////////////////////////////////
53639
53640
53641      p5.Renderer2D.prototype.bezier = function (x1, y1, x2, y2, x3, y3, x4, y4) {
53642        this._pInst.beginShape();
53643
53644        this._pInst.vertex(x1, y1);
53645
53646        this._pInst.bezierVertex(x2, y2, x3, y3, x4, y4);
53647
53648        this._pInst.endShape();
53649
53650        return this;
53651      };
53652
53653      p5.Renderer2D.prototype.curve = function (x1, y1, x2, y2, x3, y3, x4, y4) {
53654        this._pInst.beginShape();
53655
53656        this._pInst.curveVertex(x1, y1);
53657
53658        this._pInst.curveVertex(x2, y2);
53659
53660        this._pInst.curveVertex(x3, y3);
53661
53662        this._pInst.curveVertex(x4, y4);
53663
53664        this._pInst.endShape();
53665
53666        return this;
53667      }; //////////////////////////////////////////////
53668      // SHAPE | Vertex
53669      //////////////////////////////////////////////
53670
53671
53672      p5.Renderer2D.prototype._doFillStrokeClose = function (closeShape) {
53673        if (closeShape) {
53674          this.drawingContext.closePath();
53675        }
53676
53677        if (this._doFill) {
53678          this.drawingContext.fill();
53679        }
53680
53681        if (this._doStroke) {
53682          this.drawingContext.stroke();
53683        }
53684
53685        this._pInst._pixelsDirty = true;
53686      }; //////////////////////////////////////////////
53687      // TRANSFORM
53688      //////////////////////////////////////////////
53689
53690
53691      p5.Renderer2D.prototype.applyMatrix = function (a, b, c, d, e, f) {
53692        this.drawingContext.transform(a, b, c, d, e, f);
53693      };
53694
53695      p5.Renderer2D.prototype.resetMatrix = function () {
53696        this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
53697        this.drawingContext.scale(this._pInst._pixelDensity, this._pInst._pixelDensity);
53698        return this;
53699      };
53700
53701      p5.Renderer2D.prototype.rotate = function (rad) {
53702        this.drawingContext.rotate(rad);
53703      };
53704
53705      p5.Renderer2D.prototype.scale = function (x, y) {
53706        this.drawingContext.scale(x, y);
53707        return this;
53708      };
53709
53710      p5.Renderer2D.prototype.shearX = function (rad) {
53711        this.drawingContext.transform(1, 0, Math.tan(rad), 1, 0, 0);
53712        return this;
53713      };
53714
53715      p5.Renderer2D.prototype.shearY = function (rad) {
53716        this.drawingContext.transform(1, Math.tan(rad), 0, 1, 0, 0);
53717        return this;
53718      };
53719
53720      p5.Renderer2D.prototype.translate = function (x, y) {
53721        // support passing a vector as the 1st parameter
53722        if (x instanceof p5.Vector) {
53723          y = x.y;
53724          x = x.x;
53725        }
53726
53727        this.drawingContext.translate(x, y);
53728        return this;
53729      }; //////////////////////////////////////////////
53730      // TYPOGRAPHY
53731      //
53732      //////////////////////////////////////////////
53733
53734
53735      p5.Renderer2D.prototype.text = function (str, x, y, maxWidth, maxHeight) {
53736        var baselineHacked; // baselineHacked: (HACK)
53737        // A temporary fix to conform to Processing's implementation
53738        // of BASELINE vertical alignment in a bounding box
53739
53740        if (typeof maxWidth !== 'undefined' && typeof maxHeight !== 'undefined') {
53741          if (this.drawingContext.textBaseline === constants.BASELINE) {
53742            baselineHacked = true;
53743            this.drawingContext.textBaseline = constants.TOP;
53744          }
53745        }
53746
53747        var p = p5.Renderer.prototype.text.apply(this, arguments);
53748
53749        if (baselineHacked) {
53750          this.drawingContext.textBaseline = constants.BASELINE;
53751        }
53752
53753        return p;
53754      };
53755
53756      p5.Renderer2D.prototype._renderText = function (p, line, x, y, maxY) {
53757        if (y >= maxY) {
53758          return; // don't render lines beyond our maxY position
53759        }
53760
53761        p.push(); // fix to #803
53762
53763        if (!this._isOpenType()) {
53764          // a system/browser font
53765          // no stroke unless specified by user
53766          if (this._doStroke && this._strokeSet) {
53767            this.drawingContext.strokeText(line, x, y);
53768          }
53769
53770          if (this._doFill) {
53771            // if fill hasn't been set by user, use default text fill
53772            if (!this._fillSet) {
53773              this._setFill(constants._DEFAULT_TEXT_FILL);
53774            }
53775
53776            this.drawingContext.fillText(line, x, y);
53777          }
53778        } else {
53779          // an opentype font, let it handle the rendering
53780          this._textFont._renderPath(line, x, y, {
53781            renderer: this
53782          });
53783        }
53784
53785        p.pop();
53786        this._pInst._pixelsDirty = true;
53787        return p;
53788      };
53789
53790      p5.Renderer2D.prototype.textWidth = function (s) {
53791        if (this._isOpenType()) {
53792          return this._textFont._textWidth(s, this._textSize);
53793        }
53794
53795        return this.drawingContext.measureText(s).width;
53796      };
53797
53798      p5.Renderer2D.prototype._applyTextProperties = function () {
53799        var font,
53800            p = this._pInst;
53801
53802        this._setProperty('_textAscent', null);
53803
53804        this._setProperty('_textDescent', null);
53805
53806        font = this._textFont;
53807
53808        if (this._isOpenType()) {
53809          font = this._textFont.font.familyName;
53810
53811          this._setProperty('_textStyle', this._textFont.font.styleName);
53812        }
53813
53814        this.drawingContext.font = (this._textStyle || 'normal') + ' ' + (this._textSize || 12) + 'px ' + (font || 'sans-serif');
53815        this.drawingContext.textAlign = this._textAlign;
53816
53817        if (this._textBaseline === constants.CENTER) {
53818          this.drawingContext.textBaseline = constants._CTX_MIDDLE;
53819        } else {
53820          this.drawingContext.textBaseline = this._textBaseline;
53821        }
53822
53823        return p;
53824      }; //////////////////////////////////////////////
53825      // STRUCTURE
53826      //////////////////////////////////////////////
53827      // a push() operation is in progress.
53828      // the renderer should return a 'style' object that it wishes to
53829      // store on the push stack.
53830      // derived renderers should call the base class' push() method
53831      // to fetch the base style object.
53832
53833
53834      p5.Renderer2D.prototype.push = function () {
53835        this.drawingContext.save(); // get the base renderer style
53836
53837        return p5.Renderer.prototype.push.apply(this);
53838      }; // a pop() operation is in progress
53839      // the renderer is passed the 'style' object that it returned
53840      // from its push() method.
53841      // derived renderers should pass this object to their base
53842      // class' pop method
53843
53844
53845      p5.Renderer2D.prototype.pop = function (style) {
53846        this.drawingContext.restore(); // Re-cache the fill / stroke state
53847
53848        this._cachedFillStyle = this.drawingContext.fillStyle;
53849        this._cachedStrokeStyle = this.drawingContext.strokeStyle;
53850        p5.Renderer.prototype.pop.call(this, style);
53851      };
53852
53853      module.exports = p5.Renderer2D;
53854    }, {
53855      "../image/filters": 42,
53856      "./constants": 18,
53857      "./main": 24,
53858      "./p5.Renderer": 27
53859    }],
53860    29: [function (_dereq_, module, exports) {
53861      /**
53862       * @module Rendering
53863       * @submodule Rendering
53864       * @for p5
53865       */
53866      'use strict';
53867
53868      var p5 = _dereq_('./main');
53869
53870      var constants = _dereq_('./constants');
53871
53872      _dereq_('./p5.Graphics');
53873
53874      _dereq_('./p5.Renderer2D');
53875
53876      _dereq_('../webgl/p5.RendererGL');
53877
53878      var defaultId = 'defaultCanvas0'; // this gets set again in createCanvas
53879
53880      var defaultClass = 'p5Canvas';
53881      /**
53882       * Creates a canvas element in the document, and sets the dimensions of it
53883       * in pixels. This method should be called only once at the start of setup.
53884       * Calling <a href="#/p5/createCanvas">createCanvas</a> more than once in a sketch will result in very
53885       * unpredictable behavior. If you want more than one drawing canvas
53886       * you could use <a href="#/p5/createGraphics">createGraphics</a> (hidden by default but it can be shown).
53887       * <br><br>
53888       * The system variables width and height are set by the parameters passed
53889       * to this function. If <a href="#/p5/createCanvas">createCanvas()</a> is not used, the window will be
53890       * given a default size of 100x100 pixels.
53891       * <br><br>
53892       * For more ways to position the canvas, see the
53893       * <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>
53894       * positioning the canvas</a> wiki page.
53895       *
53896       * @method createCanvas
53897       * @param  {Number} w width of the canvas
53898       * @param  {Number} h height of the canvas
53899       * @param  {Constant} [renderer] either P2D or WEBGL
53900       * @return {p5.Renderer}
53901       * @example
53902       * <div>
53903       * <code>
53904       * function setup() {
53905       *   createCanvas(100, 50);
53906       *   background(153);
53907       *   line(0, 0, width, height);
53908       * }
53909       * </code>
53910       * </div>
53911       *
53912       * @alt
53913       * Black line extending from top-left of canvas to bottom right.
53914       *
53915       */
53916
53917      p5.prototype.createCanvas = function (w, h, renderer) {
53918        p5._validateParameters('createCanvas', arguments); //optional: renderer, otherwise defaults to p2d
53919
53920
53921        var r = renderer || constants.P2D;
53922        var c;
53923
53924        if (r === constants.WEBGL) {
53925          c = document.getElementById(defaultId);
53926
53927          if (c) {
53928            //if defaultCanvas already exists
53929            c.parentNode.removeChild(c); //replace the existing defaultCanvas
53930
53931            var thisRenderer = this._renderer;
53932            this._elements = this._elements.filter(function (e) {
53933              return e !== thisRenderer;
53934            });
53935          }
53936
53937          c = document.createElement('canvas');
53938          c.id = defaultId;
53939          c.classList.add(defaultClass);
53940        } else {
53941          if (!this._defaultGraphicsCreated) {
53942            c = document.createElement('canvas');
53943            var i = 0;
53944
53945            while (document.getElementById('defaultCanvas' + i)) {
53946              i++;
53947            }
53948
53949            defaultId = 'defaultCanvas' + i;
53950            c.id = defaultId;
53951            c.classList.add(defaultClass);
53952          } else {
53953            // resize the default canvas if new one is created
53954            c = this.canvas;
53955          }
53956        } // set to invisible if still in setup (to prevent flashing with manipulate)
53957
53958
53959        if (!this._setupDone) {
53960          c.dataset.hidden = true; // tag to show later
53961
53962          c.style.visibility = 'hidden';
53963        }
53964
53965        if (this._userNode) {
53966          // user input node case
53967          this._userNode.appendChild(c);
53968        } else {
53969          document.body.appendChild(c);
53970        } // Init our graphics renderer
53971        //webgl mode
53972
53973
53974        if (r === constants.WEBGL) {
53975          this._setProperty('_renderer', new p5.RendererGL(c, this, true));
53976
53977          this._elements.push(this._renderer);
53978        } else {
53979          //P2D mode
53980          if (!this._defaultGraphicsCreated) {
53981            this._setProperty('_renderer', new p5.Renderer2D(c, this, true));
53982
53983            this._defaultGraphicsCreated = true;
53984
53985            this._elements.push(this._renderer);
53986          }
53987        }
53988
53989        this._renderer.resize(w, h);
53990
53991        this._renderer._applyDefaults();
53992
53993        return this._renderer;
53994      };
53995      /**
53996       * Resizes the canvas to given width and height. The canvas will be cleared
53997       * and draw will be called immediately, allowing the sketch to re-render itself
53998       * in the resized canvas.
53999       * @method resizeCanvas
54000       * @param  {Number} w width of the canvas
54001       * @param  {Number} h height of the canvas
54002       * @param  {Boolean} [noRedraw] don't redraw the canvas immediately
54003       * @example
54004       * <div class="norender"><code>
54005       * function setup() {
54006       *   createCanvas(windowWidth, windowHeight);
54007       * }
54008       *
54009       * function draw() {
54010       *   background(0, 100, 200);
54011       * }
54012       *
54013       * function windowResized() {
54014       *   resizeCanvas(windowWidth, windowHeight);
54015       * }
54016       * </code></div>
54017       *
54018       * @alt
54019       * No image displayed.
54020       *
54021       */
54022
54023
54024      p5.prototype.resizeCanvas = function (w, h, noRedraw) {
54025        p5._validateParameters('resizeCanvas', arguments);
54026
54027        if (this._renderer) {
54028          // save canvas properties
54029          var props = {};
54030
54031          for (var key in this.drawingContext) {
54032            var val = this.drawingContext[key];
54033
54034            if (typeof val !== 'object' && typeof val !== 'function') {
54035              props[key] = val;
54036            }
54037          }
54038
54039          this._renderer.resize(w, h);
54040
54041          this.width = w;
54042          this.height = h; // reset canvas properties
54043
54044          for (var savedKey in props) {
54045            try {
54046              this.drawingContext[savedKey] = props[savedKey];
54047            } catch (err) {// ignore read-only property errors
54048            }
54049          }
54050
54051          if (!noRedraw) {
54052            this.redraw();
54053          }
54054        }
54055      };
54056      /**
54057       * Removes the default canvas for a p5 sketch that doesn't
54058       * require a canvas
54059       * @method noCanvas
54060       * @example
54061       * <div>
54062       * <code>
54063       * function setup() {
54064       *   noCanvas();
54065       * }
54066       * </code>
54067       * </div>
54068       *
54069       * @alt
54070       * no image displayed
54071       *
54072       */
54073
54074
54075      p5.prototype.noCanvas = function () {
54076        if (this.canvas) {
54077          this.canvas.parentNode.removeChild(this.canvas);
54078        }
54079      };
54080      /**
54081       * Creates and returns a new p5.Renderer object. Use this class if you need
54082       * to draw into an off-screen graphics buffer. The two parameters define the
54083       * width and height in pixels.
54084       *
54085       * @method createGraphics
54086       * @param  {Number} w width of the offscreen graphics buffer
54087       * @param  {Number} h height of the offscreen graphics buffer
54088       * @param  {Constant} [renderer] either P2D or WEBGL
54089       * undefined defaults to p2d
54090       * @return {p5.Graphics} offscreen graphics buffer
54091       * @example
54092       * <div>
54093       * <code>
54094       * let pg;
54095       * function setup() {
54096       *   createCanvas(100, 100);
54097       *   pg = createGraphics(100, 100);
54098       * }
54099       * function draw() {
54100       *   background(200);
54101       *   pg.background(100);
54102       *   pg.noStroke();
54103       *   pg.ellipse(pg.width / 2, pg.height / 2, 50, 50);
54104       *   image(pg, 50, 50);
54105       *   image(pg, 0, 0, 50, 50);
54106       * }
54107       * </code>
54108       * </div>
54109       *
54110       * @alt
54111       * 4 grey squares alternating light and dark grey. White quarter circle mid-left.
54112       *
54113       */
54114
54115
54116      p5.prototype.createGraphics = function (w, h, renderer) {
54117        p5._validateParameters('createGraphics', arguments);
54118
54119        return new p5.Graphics(w, h, renderer, this);
54120      };
54121      /**
54122       * Blends the pixels in the display window according to the defined mode.
54123       * There is a choice of the following modes to blend the source pixels (A)
54124       * with the ones of pixels already in the display window (B):
54125       * <ul>
54126       * <li><code>BLEND</code> - linear interpolation of colours: C =
54127       * A\*factor + B. This is the default blending mode.</li>
54128       * <li><code>ADD</code> - sum of A and B</li>
54129       * <li><code>DARKEST</code> - only the darkest colour succeeds: C =
54130       * min(A\*factor, B).</li>
54131       * <li><code>LIGHTEST</code> - only the lightest colour succeeds: C =
54132       * max(A\*factor, B).</li>
54133       * <li><code>DIFFERENCE</code> - subtract colors from underlying image.</li>
54134       * <li><code>EXCLUSION</code> - similar to <code>DIFFERENCE</code>, but less
54135       * extreme.</li>
54136       * <li><code>MULTIPLY</code> - multiply the colors, result will always be
54137       * darker.</li>
54138       * <li><code>SCREEN</code> - opposite multiply, uses inverse values of the
54139       * colors.</li>
54140       * <li><code>REPLACE</code> - the pixels entirely replace the others and
54141       * don't utilize alpha (transparency) values.</li>
54142       * <li><code>OVERLAY</code> - mix of <code>MULTIPLY</code> and <code>SCREEN
54143       * </code>. Multiplies dark values, and screens light values.</li>
54144       * <li><code>HARD_LIGHT</code> - <code>SCREEN</code> when greater than 50%
54145       * gray, <code>MULTIPLY</code> when lower.</li>
54146       * <li><code>SOFT_LIGHT</code> - mix of <code>DARKEST</code> and
54147       * <code>LIGHTEST</code>. Works like <code>OVERLAY</code>, but not as harsh.
54148       * </li>
54149       * <li><code>DODGE</code> - lightens light tones and increases contrast,
54150       * ignores darks.</li>
54151       * <li><code>BURN</code> - darker areas are applied, increasing contrast,
54152       * ignores lights.</li>
54153       * </ul>
54154       *
54155       * @method blendMode
54156       * @param  {Constant} mode blend mode to set for canvas.
54157       *                either BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY,
54158       *                EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,
54159       *                SOFT_LIGHT, DODGE, BURN, ADD or NORMAL
54160       * @example
54161       * <div>
54162       * <code>
54163       * blendMode(LIGHTEST);
54164       * strokeWeight(30);
54165       * stroke(80, 150, 255);
54166       * line(25, 25, 75, 75);
54167       * stroke(255, 50, 50);
54168       * line(75, 25, 25, 75);
54169       * </code>
54170       * </div>
54171       * <div>
54172       * <code>
54173       * blendMode(MULTIPLY);
54174       * strokeWeight(30);
54175       * stroke(80, 150, 255);
54176       * line(25, 25, 75, 75);
54177       * stroke(255, 50, 50);
54178       * line(75, 25, 25, 75);
54179       * </code>
54180       * </div>
54181       * @alt
54182       * translucent image thick red & blue diagonal rounded lines intersecting center
54183       * Thick red & blue diagonal rounded lines intersecting center. dark at overlap
54184       *
54185       */
54186
54187
54188      p5.prototype.blendMode = function (mode) {
54189        p5._validateParameters('blendMode', arguments);
54190
54191        if (mode === constants.BLEND || mode === constants.DARKEST || mode === constants.LIGHTEST || mode === constants.DIFFERENCE || mode === constants.MULTIPLY || mode === constants.EXCLUSION || mode === constants.SCREEN || mode === constants.REPLACE || mode === constants.OVERLAY || mode === constants.HARD_LIGHT || mode === constants.SOFT_LIGHT || mode === constants.DODGE || mode === constants.BURN || mode === constants.ADD || mode === constants.NORMAL) {
54192          this._renderer.blendMode(mode);
54193        } else {
54194          throw new Error('Mode ' + mode + ' not recognized.');
54195        }
54196      };
54197
54198      module.exports = p5;
54199    }, {
54200      "../webgl/p5.RendererGL": 74,
54201      "./constants": 18,
54202      "./main": 24,
54203      "./p5.Graphics": 26,
54204      "./p5.Renderer2D": 28
54205    }],
54206    30: [function (_dereq_, module, exports) {
54207      /**
54208       * @module Shape
54209       * @submodule 2D Primitives
54210       * @for p5
54211       * @requires core
54212       * @requires constants
54213       */
54214      'use strict';
54215
54216      var p5 = _dereq_('../main');
54217
54218      var constants = _dereq_('../constants');
54219
54220      var canvas = _dereq_('../helpers');
54221
54222      _dereq_('../error_helpers');
54223      /**
54224       * Draw an arc to the screen. If called with only x, y, w, h, start, and
54225       * stop, the arc will be drawn and filled as an open pie segment. If a mode parameter is provided, the arc
54226       * will be filled like an open semi-circle (OPEN) , a closed semi-circle (CHORD), or as a closed pie segment (PIE). The
54227       * origin may be changed with the <a href="#/p5/ellipseMode">ellipseMode()</a> function.<br><br>
54228       * Note that drawing a full circle (ex: 0 to TWO_PI) will appear blank
54229       * because 0 and TWO_PI are the same position on the unit circle. The
54230       * best way to handle this is by using the <a href="#/p5/ellipse">ellipse()</a> function instead
54231       * to create a closed ellipse, and to use the <a href="#/p5/arc">arc()</a> function
54232       * only to draw parts of an ellipse.
54233       *
54234       * @method arc
54235       * @param  {Number} x      x-coordinate of the arc's ellipse
54236       * @param  {Number} y      y-coordinate of the arc's ellipse
54237       * @param  {Number} w      width of the arc's ellipse by default
54238       * @param  {Number} h      height of the arc's ellipse by default
54239       * @param  {Number} start  angle to start the arc, specified in radians
54240       * @param  {Number} stop   angle to stop the arc, specified in radians
54241       * @param  {Constant} [mode] optional parameter to determine the way of drawing
54242       *                         the arc. either CHORD, PIE or OPEN
54243       * @param  {Number} [detail] optional parameter for WebGL mode only. This is to
54244       *                         specify the number of vertices that makes up the
54245       *                         perimeter of the arc. Default value is 25.
54246       *
54247       * @chainable
54248       * @example
54249       * <div>
54250       * <code>
54251       * arc(50, 55, 50, 50, 0, HALF_PI);
54252       * noFill();
54253       * arc(50, 55, 60, 60, HALF_PI, PI);
54254       * arc(50, 55, 70, 70, PI, PI + QUARTER_PI);
54255       * arc(50, 55, 80, 80, PI + QUARTER_PI, TWO_PI);
54256       * </code>
54257       * </div>
54258       *
54259       * <div>
54260       * <code>
54261       * arc(50, 50, 80, 80, 0, PI + QUARTER_PI);
54262       * </code>
54263       * </div>
54264       *
54265       * <div>
54266       * <code>
54267       * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, OPEN);
54268       * </code>
54269       * </div>
54270       *
54271       * <div>
54272       * <code>
54273       * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, CHORD);
54274       * </code>
54275       * </div>
54276       *
54277       * <div>
54278       * <code>
54279       * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, PIE);
54280       * </code>
54281       * </div>
54282       *
54283       * @alt
54284       *shattered outline of an ellipse with a quarter of a white circle bottom-right.
54285       *white ellipse with top right quarter missing.
54286       *white ellipse with black outline with top right missing.
54287       *white ellipse with top right missing with black outline around shape.
54288       *white ellipse with top right quarter missing with black outline around the shape.
54289       *
54290       */
54291
54292
54293      p5.prototype.arc = function (x, y, w, h, start, stop, mode, detail) {
54294        p5._validateParameters('arc', arguments); // if the current stroke and fill settings wouldn't result in something
54295        // visible, exit immediately
54296
54297
54298        if (!this._renderer._doStroke && !this._renderer._doFill) {
54299          return this;
54300        }
54301
54302        start = this._toRadians(start);
54303        stop = this._toRadians(stop); // Make all angles positive...
54304
54305        while (start < 0) {
54306          start += constants.TWO_PI;
54307        }
54308
54309        while (stop < 0) {
54310          stop += constants.TWO_PI;
54311        }
54312
54313        if (typeof start !== 'undefined' && typeof stop !== 'undefined') {
54314          // don't display anything if the angles are same or they have a difference of 0 - TWO_PI
54315          if (stop.toFixed(10) === start.toFixed(10) || Math.abs(stop - start) === constants.TWO_PI) {
54316            start %= constants.TWO_PI;
54317            stop %= constants.TWO_PI;
54318            start += constants.TWO_PI;
54319          } else if (Math.abs(stop - start) > constants.TWO_PI) {
54320            // display a full circle if the difference between them is greater than 0 - TWO_PI
54321            start %= constants.TWO_PI;
54322            stop %= constants.TWO_PI;
54323            stop += constants.TWO_PI;
54324          }
54325        } //Adjust angles to counter linear scaling.
54326
54327
54328        if (start <= constants.HALF_PI) {
54329          start = Math.atan(w / h * Math.tan(start));
54330        } else if (start > constants.HALF_PI && start <= 3 * constants.HALF_PI) {
54331          start = Math.atan(w / h * Math.tan(start)) + constants.PI;
54332        }
54333
54334        if (stop <= constants.HALF_PI) {
54335          stop = Math.atan(w / h * Math.tan(stop));
54336        } else if (stop > constants.HALF_PI && stop <= 3 * constants.HALF_PI) {
54337          stop = Math.atan(w / h * Math.tan(stop)) + constants.PI;
54338        } // Exceed the interval if necessary in order to preserve the size and
54339        // orientation of the arc.
54340
54341
54342        if (start > stop) {
54343          stop += constants.TWO_PI;
54344        } // p5 supports negative width and heights for ellipses
54345
54346
54347        w = Math.abs(w);
54348        h = Math.abs(h);
54349        var vals = canvas.modeAdjust(x, y, w, h, this._renderer._ellipseMode);
54350
54351        this._renderer.arc(vals.x, vals.y, vals.w, vals.h, start, stop, mode, detail);
54352
54353        return this;
54354      };
54355      /**
54356       * Draws an ellipse (oval) to the screen. An ellipse with equal width and
54357       * height is a circle. By default, the first two parameters set the location,
54358       * and the third and fourth parameters set the shape's width and height. If
54359       * no height is specified, the value of width is used for both the width and
54360       * height. If a negative height or width is specified, the absolute value is taken.
54361       * The origin may be changed with the <a href="#/p5/ellipseMode">ellipseMode()</a> function.
54362       *
54363       * @method ellipse
54364       * @param  {Number} x x-coordinate of the ellipse.
54365       * @param  {Number} y y-coordinate of the ellipse.
54366       * @param  {Number} w width of the ellipse.
54367       * @param  {Number} [h] height of the ellipse.
54368       * @chainable
54369       * @example
54370       * <div>
54371       * <code>
54372       * ellipse(56, 46, 55, 55);
54373       * </code>
54374       * </div>
54375       *
54376       * @alt
54377       *white ellipse with black outline in middle-right of canvas that is 55x55.
54378       *
54379       */
54380
54381      /**
54382       * @method ellipse
54383       * @param  {Number} x
54384       * @param  {Number} y
54385       * @param  {Number} w
54386       * @param  {Number} h
54387       * @param  {Integer} detail number of radial sectors to draw (for WebGL mode)
54388       */
54389
54390
54391      p5.prototype.ellipse = function (x, y, w, h, detailX) {
54392        p5._validateParameters('ellipse', arguments); // if the current stroke and fill settings wouldn't result in something
54393        // visible, exit immediately
54394
54395
54396        if (!this._renderer._doStroke && !this._renderer._doFill) {
54397          return this;
54398        } // p5 supports negative width and heights for rects
54399
54400
54401        if (w < 0) {
54402          w = Math.abs(w);
54403        }
54404
54405        if (typeof h === 'undefined') {
54406          // Duplicate 3rd argument if only 3 given.
54407          h = w;
54408        } else if (h < 0) {
54409          h = Math.abs(h);
54410        }
54411
54412        var vals = canvas.modeAdjust(x, y, w, h, this._renderer._ellipseMode);
54413
54414        this._renderer.ellipse([vals.x, vals.y, vals.w, vals.h, detailX]);
54415
54416        return this;
54417      };
54418      /**
54419       * Draws a circle to the screen. A circle is a simple closed shape.
54420       * It is the set of all points in a plane that are at a given distance from a given point, the centre.
54421       * This function is a special case of the ellipse() function, where the width and height of the ellipse are the same.
54422       * Height and width of the ellipse is equal to twice the radius of the circle..
54423       * By default, the first two parameters set the location of the centre of the circle, the third sets the radius of the circle.
54424       *
54425       * @method circle
54426       * @param  {Number} x  x-coordinate of the centre of the circle.
54427       * @param  {Number} y  y-coordinate of the centre of the circle.
54428       * @param  {Number} r  radius of the circle.
54429       * @chainable
54430       * @example
54431       * <div>
54432       * <code>
54433       * // Draw a circle at location (30, 30) with a radius of 20.
54434       * circle(30, 30, 20);
54435       * </code>
54436       * </div>
54437       *
54438       * @alt
54439       * white circle with black outline in mid of canvas that is 55x55.
54440       */
54441
54442
54443      p5.prototype.circle = function () {
54444        var args = Array.prototype.slice.call(arguments, 0, 2);
54445        args.push(2 * arguments[2]);
54446        args.push(2 * arguments[2]);
54447        this.ellipse.apply(this, args);
54448      };
54449      /**
54450       * Draws a line (a direct path between two points) to the screen. The version
54451       * of <a href="#/p5/line">line()</a> with four parameters draws the line in 2D. To color a line, use
54452       * the <a href="#/p5/stroke">stroke()</a> function. A line cannot be filled, therefore the <a href="#/p5/fill">fill()</a>
54453       * function will not affect the color of a line. 2D lines are drawn with a
54454       * width of one pixel by default, but this can be changed with the
54455       * <a href="#/p5/strokeWeight">
54455strokeWeight()</a> function.
54456       *
54457       * @method line
54458       * @param  {Number} x1 the x-coordinate of the first point
54459       * @param  {Number} y1 the y-coordinate of the first point
54460       * @param  {Number} x2 the x-coordinate of the second point
54461       * @param  {Number} y2 the y-coordinate of the second point
54462       * @chainable
54463       * @example
54464       * <div>
54465       * <code>
54466       * line(30, 20, 85, 75);
54467       * </code>
54468       * </div>
54469       *
54470       * <div>
54471       * <code>
54472       * line(30, 20, 85, 20);
54473       * stroke(126);
54474       * line(85, 20, 85, 75);
54475       * stroke(255);
54476       * line(85, 75, 30, 75);
54477       * </code>
54478       * </div>
54479       *
54480       * @alt
54481       *line 78 pixels long running from mid-top to bottom-right of canvas.
54482       *3 lines of various stroke sizes. Form top, bottom and right sides of a square.
54483       *
54484       */
54485
54486      /**
54487       * @method line
54488       * @param  {Number} x1
54489       * @param  {Number} y1
54490       * @param  {Number} z1 the z-coordinate of the first point
54491       * @param  {Number} x2
54492       * @param  {Number} y2
54493       * @param  {Number} z2 the z-coordinate of the second point
54494       * @chainable
54495       */
54496
54497
54498      p5.prototype.line = function () {
54499        p5._validateParameters('line', arguments);
54500
54501        if (this._renderer._doStroke) {
54502          this._renderer.line.apply(this._renderer, arguments);
54503        }
54504
54505        return this;
54506      };
54507      /**
54508       * Draws a point, a coordinate in space at the dimension of one pixel.
54509       * The first parameter is the horizontal value for the point, the second
54510       * value is the vertical value for the point. The color of the point is
54511       * determined by the current stroke.
54512       *
54513       * @method point
54514       * @param  {Number} x the x-coordinate
54515       * @param  {Number} y the y-coordinate
54516       * @param  {Number} [z] the z-coordinate (for WebGL mode)
54517       * @chainable
54518       * @example
54519       * <div>
54520       * <code>
54521       * point(30, 20);
54522       * point(85, 20);
54523       * point(85, 75);
54524       * point(30, 75);
54525       * </code>
54526       * </div>
54527       *
54528       * @alt
54529       *4 points centered in the middle-right of the canvas.
54530       *
54531       */
54532
54533
54534      p5.prototype.point = function () {
54535        p5._validateParameters('point', arguments);
54536
54537        if (this._renderer._doStroke) {
54538          this._renderer.point.apply(this._renderer, arguments);
54539        }
54540
54541        return this;
54542      };
54543      /**
54544       * Draw a quad. A quad is a quadrilateral, a four sided polygon. It is
54545       * similar to a rectangle, but the angles between its edges are not
54546       * constrained to ninety degrees. The first pair of parameters (x1,y1)
54547       * sets the first vertex and the subsequent pairs should proceed
54548       * clockwise or counter-clockwise around the defined shape.
54549       *
54550       * @method quad
54551       * @param {Number} x1 the x-coordinate of the first point
54552       * @param {Number} y1 the y-coordinate of the first point
54553       * @param {Number} x2 the x-coordinate of the second point
54554       * @param {Number} y2 the y-coordinate of the second point
54555       * @param {Number} x3 the x-coordinate of the third point
54556       * @param {Number} y3 the y-coordinate of the third point
54557       * @param {Number} x4 the x-coordinate of the fourth point
54558       * @param {Number} y4 the y-coordinate of the fourth point
54559       * @chainable
54560       * @example
54561       * <div>
54562       * <code>
54563       * quad(38, 31, 86, 20, 69, 63, 30, 76);
54564       * </code>
54565       * </div>
54566       *
54567       * @alt
54568       *irregular white quadrilateral shape with black outline mid-right of canvas.
54569       *
54570       */
54571
54572      /**
54573       * @method quad
54574       * @param {Number} x1
54575       * @param {Number} y1
54576       * @param {Number} z1 the z-coordinate of the first point
54577       * @param {Number} x2
54578       * @param {Number} y2
54579       * @param {Number} z2 the z-coordinate of the second point
54580       * @param {Number} x3
54581       * @param {Number} y3
54582       * @param {Number} z3 the z-coordinate of the third point
54583       * @param {Number} x4
54584       * @param {Number} y4
54585       * @param {Number} z4 the z-coordinate of the fourth point
54586       * @chainable
54587       */
54588
54589
54590      p5.prototype.quad = function () {
54591        p5._validateParameters('quad', arguments);
54592
54593        if (this._renderer._doStroke || this._renderer._doFill) {
54594          this._renderer.quad.apply(this._renderer, arguments);
54595        }
54596
54597        return this;
54598      };
54599      /**
54600       * Draws a rectangle to the screen. A rectangle is a four-sided shape with
54601       * every angle at ninety degrees. By default, the first two parameters set
54602       * the location of the upper-left corner, the third sets the width, and the
54603       * fourth sets the height. The way these parameters are interpreted, however,
54604       * may be changed with the <a href="#/p5/rectMode">rectMode()</a> function.
54605       * <br><br>
54606       * The fifth, sixth, seventh and eighth parameters, if specified,
54607       * determine corner radius for the top-left, top-right, lower-right and
54608       * lower-left corners, respectively. An omitted corner radius parameter is set
54609       * to the value of the previously specified radius value in the parameter list.
54610       *
54611       * @method rect
54612       * @param  {Number} x  x-coordinate of the rectangle.
54613       * @param  {Number} y  y-coordinate of the rectangle.
54614       * @param  {Number} w  width of the rectangle.
54615       * @param  {Number} h  height of the rectangle.
54616       * @param  {Number} [tl] optional radius of top-left corner.
54617       * @param  {Number} [tr] optional radius of top-right corner.
54618       * @param  {Number} [br] optional radius of bottom-right corner.
54619       * @param  {Number} [bl] optional radius of bottom-left corner.
54620       * @chainable
54621       * @example
54622       * <div>
54623       * <code>
54624       * // Draw a rectangle at location (30, 20) with a width and height of 55.
54625       * rect(30, 20, 55, 55);
54626       * </code>
54627       * </div>
54628       *
54629       * <div>
54630       * <code>
54631       * // Draw a rectangle with rounded corners, each having a radius of 20.
54632       * rect(30, 20, 55, 55, 20);
54633       * </code>
54634       * </div>
54635       *
54636       * <div>
54637       * <code>
54638       * // Draw a rectangle with rounded corners having the following radii:
54639       * // top-left = 20, top-right = 15, bottom-right = 10, bottom-left = 5.
54640       * rect(30, 20, 55, 55, 20, 15, 10, 5);
54641       * </code>
54642       * </div>
54643       *
54644       * @alt
54645       * 55x55 white rect with black outline in mid-right of canvas.
54646       * 55x55 white rect with black outline and rounded edges in mid-right of canvas.
54647       * 55x55 white rect with black outline and rounded edges of different radii.
54648       */
54649
54650      /**
54651       * @method rect
54652       * @param  {Number} x
54653       * @param  {Number} y
54654       * @param  {Number} w
54655       * @param  {Number} h
54656       * @param  {Integer} [detailX] number of segments in the x-direction (for WebGL mode)
54657       * @param  {Integer} [detailY] number of segments in the y-direction (for WebGL mode)
54658       * @chainable
54659       */
54660
54661
54662      p5.prototype.rect = function () {
54663        p5._validateParameters('rect', arguments);
54664
54665        if (this._renderer._doStroke || this._renderer._doFill) {
54666          var vals = canvas.modeAdjust(arguments[0], arguments[1], arguments[2], arguments[3], this._renderer._rectMode);
54667          var args = [vals.x, vals.y, vals.w, vals.h]; // append the additional arguments (either cornder radii, or
54668          // segment details) to the argument list
54669
54670          for (var i = 4; i < arguments.length; i++) {
54671            args[i] = arguments[i];
54672          }
54673
54674          this._renderer.rect(args);
54675        }
54676
54677        return this;
54678      };
54679      /**
54680       * Draws a square to the screen. A square is a four-sided shape with
54681       * every angle at ninety degrees, and equal side size.
54682       * This function is a special case of the rect() function, where the width and height are the same, and the parameter is called "s" for side size.
54683       * By default, the first two parameters set the location of the upper-left corner, the third sets the side size of the square.
54684       * The way these parameters are interpreted, however,
54685       * may be changed with the <a href="#/p5/rectMode">rectMode()</a> function.
54686       * <br><br>
54687       * The fourth, fifth, sixth and seventh parameters, if specified,
54688       * determine corner radius for the top-left, top-right, lower-right and
54689       * lower-left corners, respectively. An omitted corner radius parameter is set
54690       * to the value of the previously specified radius value in the parameter list.
54691       *
54692       * @method square
54693       * @param  {Number} x  x-coordinate of the square.
54694       * @param  {Number} y  y-coordinate of the square.
54695       * @param  {Number} s  side size of the square.
54696       * @param  {Number} [tl] optional radius of top-left corner.
54697       * @param  {Number} [tr] optional radius of top-right corner.
54698       * @param  {Number} [br] optional radius of bottom-right corner.
54699       * @param  {Number} [bl] optional radius of bottom-left corner.
54700       * @chainable
54701       * @example
54702       * <div>
54703       * <code>
54704       * // Draw a square at location (30, 20) with a side size of 55.
54705       * square(30, 20, 55);
54706       * </code>
54707       * </div>
54708       *
54709       * <div>
54710       * <code>
54711       * // Draw a square with rounded corners, each having a radius of 20.
54712       * square(30, 20, 55, 20);
54713       * </code>
54714       * </div>
54715       *
54716       * <div>
54717       * <code>
54718       * // Draw a square with rounded corners having the following radii:
54719       * // top-left = 20, top-right = 15, bottom-right = 10, bottom-left = 5.
54720       * square(30, 20, 55, 20, 15, 10, 5);
54721       * </code>
54722       * </div>
54723       *
54724       * @alt
54725       * 55x55 white square with black outline in mid-right of canvas.
54726       * 55x55 white square with black outline and rounded edges in mid-right of canvas.
54727       * 55x55 white square with black outline and rounded edges of different radii.
54728       */
54729
54730
54731      p5.prototype.square = function () {
54732        var args = Array.prototype.slice.call(arguments, 0, 3);
54733        args.push(arguments[2]);
54734        args = args.concat(Array.prototype.slice.call(arguments, 4));
54735        this.rect.apply(this, args);
54736      };
54737      /**
54738       * A triangle is a plane created by connecting three points. The first two
54739       * arguments specify the first point, the middle two arguments specify the
54740       * second point, and the last two arguments specify the third point.
54741       *
54742       * @method triangle
54743       * @param  {Number} x1 x-coordinate of the first point
54744       * @param  {Number} y1 y-coordinate of the first point
54745       * @param  {Number} x2 x-coordinate of the second point
54746       * @param  {Number} y2 y-coordinate of the second point
54747       * @param  {Number} x3 x-coordinate of the third point
54748       * @param  {Number} y3 y-coordinate of the third point
54749       * @chainable
54750       * @example
54751       * <div>
54752       * <code>
54753       * triangle(30, 75, 58, 20, 86, 75);
54754       * </code>
54755       * </div>
54756       *
54757       *@alt
54758       * white triangle with black outline in mid-right of canvas.
54759       *
54760       */
54761
54762
54763      p5.prototype.triangle = function () {
54764        p5._validateParameters('triangle', arguments);
54765
54766        if (this._renderer._doStroke || this._renderer._doFill) {
54767          this._renderer.triangle(arguments);
54768        }
54769
54770        return this;
54771      };
54772
54773      module.exports = p5;
54774    }, {
54775      "../constants": 18,
54776      "../error_helpers": 20,
54777      "../helpers": 21,
54778      "../main": 24
54779    }],
54780    31: [function (_dereq_, module, exports) {
54781      /**
54782       * @module Shape
54783       * @submodule Attributes
54784       * @for p5
54785       * @requires core
54786       * @requires constants
54787       */
54788      'use strict';
54789
54790      var p5 = _dereq_('../main');
54791
54792      var constants = _dereq_('../constants');
54793      /**
54794       * Modifies the location from which ellipses are drawn by changing the way
54795       * in which parameters given to <a href="#/p5/ellipse">ellipse()</a> are interpreted.
54796       * <br><br>
54797       * The default mode is ellipseMode(CENTER), which interprets the first two
54798       * parameters of <a href="#/p5/ellipse">ellipse()</a> as the shape's center point, while the third and
54799       * fourth parameters are its width and height.
54800       * <br><br>
54801       * ellipseMode(RADIUS) also uses the first two parameters of <a href="#/p5/ellipse">ellipse()</a> as
54802       * the shape's center point, but uses the third and fourth parameters to
54803       * specify half of the shapes's width and height.
54804       * <br><br>
54805       * ellipseMode(CORNER) interprets the first two parameters of <a href="#/p5/ellipse">ellipse()</a> as
54806       * the upper-left corner of the shape, while the third and fourth parameters
54807       * are its width and height.
54808       * <br><br>
54809       * ellipseMode(CORNERS) interprets the first two parameters of <a href="#/p5/ellipse">ellipse()</a> as
54810       * the location of one corner of the ellipse's bounding box, and the third
54811       * and fourth parameters as the location of the opposite corner.
54812       * <br><br>
54813       * The parameter must be written in ALL CAPS because Javascript is a
54814       * case-sensitive language.
54815       *
54816       * @method ellipseMode
54817       * @param  {Constant} mode either CENTER, RADIUS, CORNER, or CORNERS
54818       * @chainable
54819       * @example
54820       * <div>
54821       * <code>
54822       * ellipseMode(RADIUS); // Set ellipseMode to RADIUS
54823       * fill(255); // Set fill to white
54824       * ellipse(50, 50, 30, 30); // Draw white ellipse using RADIUS mode
54825       *
54826       * ellipseMode(CENTER); // Set ellipseMode to CENTER
54827       * fill(100); // Set fill to gray
54828       * ellipse(50, 50, 30, 30); // Draw gray ellipse using CENTER mode
54829       * </code>
54830       * </div>
54831       *
54832       * <div>
54833       * <code>
54834       * ellipseMode(CORNER); // Set ellipseMode is CORNER
54835       * fill(255); // Set fill to white
54836       * ellipse(25, 25, 50, 50); // Draw white ellipse using CORNER mode
54837       *
54838       * ellipseMode(CORNERS); // Set ellipseMode to CORNERS
54839       * fill(100); // Set fill to gray
54840       * ellipse(25, 25, 50, 50); // Draw gray ellipse using CORNERS mode
54841       * </code>
54842       * </div>
54843       *
54844       * @alt
54845       * 60x60 white ellipse and 30x30 grey ellipse with black outlines at center.
54846       * 60x60 white ellipse @center and 30x30 grey ellipse top-right, black outlines.
54847       *
54848       */
54849
54850
54851      p5.prototype.ellipseMode = function (m) {
54852        p5._validateParameters('ellipseMode', arguments);
54853
54854        if (m === constants.CORNER || m === constants.CORNERS || m === constants.RADIUS || m === constants.CENTER) {
54855          this._renderer._ellipseMode = m;
54856        }
54857
54858        return this;
54859      };
54860      /**
54861       * Draws all geometry with jagged (aliased) edges. Note that <a href="#/p5/smooth">smooth()</a> is
54862       * active by default in 2D mode, so it is necessary to call <a href="#/p5/noSmooth">noSmooth()</a> to disable
54863       * smoothing of geometry, images, and fonts. In 3D mode, <a href="#/p5/noSmooth">noSmooth()</a> is enabled
54864       * by default, so it is necessary to call <a href="#/p5/smooth">smooth()</a> if you would like
54865       * smooth (antialiased) edges on your geometry.
54866       *
54867       * @method noSmooth
54868       * @chainable
54869       * @example
54870       * <div>
54871       * <code>
54872       * background(0);
54873       * noStroke();
54874       * smooth();
54875       * ellipse(30, 48, 36, 36);
54876       * noSmooth();
54877       * ellipse(70, 48, 36, 36);
54878       * </code>
54879       * </div>
54880       *
54881       * @alt
54882       * 2 pixelated 36x36 white ellipses to left & right of center, black background
54883       *
54884       */
54885
54886
54887      p5.prototype.noSmooth = function () {
54888        this._renderer.noSmooth();
54889
54890        return this;
54891      };
54892      /**
54893       * Modifies the location from which rectangles are drawn by changing the way
54894       * in which parameters given to <a href="#/p5/rect">rect()</a> are interpreted.
54895       * <br><br>
54896       * The default mode is rectMode(CORNER), which interprets the first two
54897       * parameters of <a href="#/p5/rect">rect()</a> as the upper-left corner of the shape, while the
54898       * third and fourth parameters are its width and height.
54899       * <br><br>
54900       * rectMode(CORNERS) interprets the first two parameters of <a href="#/p5/rect">rect()</a> as the
54901       * location of one corner, and the third and fourth parameters as the
54902       * location of the opposite corner.
54903       * <br><br>
54904       * rectMode(CENTER) interprets the first two parameters of <a href="#/p5/rect">rect()</a> as the
54905       * shape's center point, while the third and fourth parameters are its
54906       * width and height.
54907       * <br><br>
54908       * rectMode(RADIUS) also uses the first two parameters of <a href="#/p5/rect">rect()</a> as the
54909       * shape's center point, but uses the third and fourth parameters to 
54909specify
54910       * half of the shapes's width and height.
54911       * <br><br>
54912       * The parameter must be written in ALL CAPS because Javascript is a
54913       * case-sensitive language.
54914       *
54915       * @method rectMode
54916       * @param  {Constant} mode either CORNER, CORNERS, CENTER, or RADIUS
54917       * @chainable
54918       * @example
54919       * <div>
54920       * <code>
54921       * rectMode(CORNER); // Default rectMode is CORNER
54922       * fill(255); // Set fill to white
54923       * rect(25, 25, 50, 50); // Draw white rect using CORNER mode
54924       *
54925       * rectMode(CORNERS); // Set rectMode to CORNERS
54926       * fill(100); // Set fill to gray
54927       * rect(25, 25, 50, 50); // Draw gray rect using CORNERS mode
54928       * </code>
54929       * </div>
54930       *
54931       * <div>
54932       * <code>
54933       * rectMode(RADIUS); // Set rectMode to RADIUS
54934       * fill(255); // Set fill to white
54935       * rect(50, 50, 30, 30); // Draw white rect using RADIUS mode
54936       *
54937       * rectMode(CENTER); // Set rectMode to CENTER
54938       * fill(100); // Set fill to gray
54939       * rect(50, 50, 30, 30); // Draw gray rect using CENTER mode
54940       * </code>
54941       * </div>
54942       *
54943       * @alt
54944       * 50x50 white rect at center and 25x25 grey rect in the top left of the other.
54945       * 50x50 white rect at center and 25x25 grey rect in the center of the other.
54946       *
54947       */
54948
54949
54950      p5.prototype.rectMode = function (m) {
54951        p5._validateParameters('rectMode', arguments);
54952
54953        if (m === constants.CORNER || m === constants.CORNERS || m === constants.RADIUS || m === constants.CENTER) {
54954          this._renderer._rectMode = m;
54955        }
54956
54957        return this;
54958      };
54959      /**
54960       * Draws all geometry with smooth (anti-aliased) edges. <a href="#/p5/smooth">smooth()</a> will also
54961       * improve image quality of resized images. Note that <a href="#/p5/smooth">smooth()</a> is active by
54962       * default in 2D mode; <a href="#/p5/noSmooth">noSmooth()</a> can be used to disable smoothing of geometry,
54963       * images, and fonts. In 3D mode, <a href="#/p5/noSmooth">noSmooth()</a> is enabled
54964       * by default, so it is necessary to call <a href="#/p5/smooth">smooth()</a> if you would like
54965       * smooth (antialiased) edges on your geometry.
54966       *
54967       * @method smooth
54968       * @chainable
54969       * @example
54970       * <div>
54971       * <code>
54972       * background(0);
54973       * noStroke();
54974       * smooth();
54975       * ellipse(30, 48, 36, 36);
54976       * noSmooth();
54977       * ellipse(70, 48, 36, 36);
54978       * </code>
54979       * </div>
54980       *
54981       * @alt
54982       * 2 pixelated 36x36 white ellipses one left one right of center. On black.
54983       *
54984       */
54985
54986
54987      p5.prototype.smooth = function () {
54988        this._renderer.smooth();
54989
54990        return this;
54991      };
54992      /**
54993       * Sets the style for rendering line endings. These ends are either squared,
54994       * extended, or rounded, each of which specified with the corresponding
54995       * parameters: SQUARE, PROJECT, and ROUND. The default cap is ROUND.
54996       *
54997       * @method strokeCap
54998       * @param  {Constant} cap either SQUARE, PROJECT, or ROUND
54999       * @chainable
55000       * @example
55001       * <div>
55002       * <code>
55003       * strokeWeight(12.0);
55004       * strokeCap(ROUND);
55005       * line(20, 30, 80, 30);
55006       * strokeCap(SQUARE);
55007       * line(20, 50, 80, 50);
55008       * strokeCap(PROJECT);
55009       * line(20, 70, 80, 70);
55010       * </code>
55011       * </div>
55012       *
55013       * @alt
55014       * 3 lines. Top line: rounded ends, mid: squared, bottom:longer squared ends.
55015       *
55016       */
55017
55018
55019      p5.prototype.strokeCap = function (cap) {
55020        p5._validateParameters('strokeCap', arguments);
55021
55022        if (cap === constants.ROUND || cap === constants.SQUARE || cap === constants.PROJECT) {
55023          this._renderer.strokeCap(cap);
55024        }
55025
55026        return this;
55027      };
55028      /**
55029       * Sets the style of the joints which connect line segments. These joints
55030       * are either mitered, beveled, or rounded and specified with the
55031       * corresponding parameters MITER, BEVEL, and ROUND. The default joint is
55032       * MITER.
55033       *
55034       * @method strokeJoin
55035       * @param  {Constant} join either MITER, BEVEL, ROUND
55036       * @chainable
55037       * @example
55038       * <div>
55039       * <code>
55040       * noFill();
55041       * strokeWeight(10.0);
55042       * strokeJoin(MITER);
55043       * beginShape();
55044       * vertex(35, 20);
55045       * vertex(65, 50);
55046       * vertex(35, 80);
55047       * endShape();
55048       * </code>
55049       * </div>
55050       *
55051       * <div>
55052       * <code>
55053       * noFill();
55054       * strokeWeight(10.0);
55055       * strokeJoin(BEVEL);
55056       * beginShape();
55057       * vertex(35, 20);
55058       * vertex(65, 50);
55059       * vertex(35, 80);
55060       * endShape();
55061       * </code>
55062       * </div>
55063       *
55064       * <div>
55065       * <code>
55066       * noFill();
55067       * strokeWeight(10.0);
55068       * strokeJoin(ROUND);
55069       * beginShape();
55070       * vertex(35, 20);
55071       * vertex(65, 50);
55072       * vertex(35, 80);
55073       * endShape();
55074       * </code>
55075       * </div>
55076       *
55077       * @alt
55078       * Right-facing arrowhead shape with pointed tip in center of canvas.
55079       * Right-facing arrowhead shape with flat tip in center of canvas.
55080       * Right-facing arrowhead shape with rounded tip in center of canvas.
55081       *
55082       */
55083
55084
55085      p5.prototype.strokeJoin = function (join) {
55086        p5._validateParameters('strokeJoin', arguments);
55087
55088        if (join === constants.ROUND || join === constants.BEVEL || join === constants.MITER) {
55089          this._renderer.strokeJoin(join);
55090        }
55091
55092        return this;
55093      };
55094      /**
55095       * Sets the width of the stroke used for lines, points, and the border
55096       * around shapes. All widths are set in units of pixels.
55097       *
55098       * @method strokeWeight
55099       * @param  {Number} weight the weight (in pixels) of the stroke
55100       * @chainable
55101       * @example
55102       * <div>
55103       * <code>
55104       * strokeWeight(1); // Default
55105       * line(20, 20, 80, 20);
55106       * strokeWeight(4); // Thicker
55107       * line(20, 40, 80, 40);
55108       * strokeWeight(10); // Beastly
55109       * line(20, 70, 80, 70);
55110       * </code>
55111       * </div>
55112       *
55113       * @alt
55114       * 3 horizontal black lines. Top line: thin, mid: medium, bottom:thick.
55115       *
55116       */
55117
55118
55119      p5.prototype.strokeWeight = function (w) {
55120        p5._validateParameters('strokeWeight', arguments);
55121
55122        this._renderer.strokeWeight(w);
55123
55124        return this;
55125      };
55126
55127      module.exports = p5;
55128    }, {
55129      "../constants": 18,
55130      "../main": 24
55131    }],
55132    32: [function (_dereq_, module, exports) {
55133      /**
55134       * @module Shape
55135       * @submodule Curves
55136       * @for p5
55137       * @requires core
55138       */
55139      'use strict';
55140
55141      var p5 = _dereq_('../main');
55142
55143      _dereq_('../error_helpers');
55144      /**
55145       * Draws a cubic Bezier curve on the screen. These curves are defined by a
55146       * series of anchor and control points. The first two parameters specify
55147       * the first anchor point and the last two parameters specify the other
55148       * anchor point, which become the first and last points on the curve. The
55149       * middle parameters specify the two control points which define the shape
55150       * of the curve. Approximately speaking, control points "pull" the curve
55151       * towards them.<br /><br />Bezier curves were developed by French
55152       * automotive engineer Pierre Bezier, and are commonly used in computer
55153       * graphics to define gently sloping curves. See also <a href="#/p5/curve">curve()</a>.
55154       *
55155       * @method bezier
55156       * @param  {Number} x1 x-coordinate for the first anchor point
55157       * @param  {Number} y1 y-coordinate for the first anchor point
55158       * @param  {Number} x2 x-coordinate for the first control point
55159       * @param  {Number} y2 y-coordinate for the first control point
55160       * @param  {Number} x3 x-coordinate for the second control point
55161       * @param  {Number} y3 y-coordinate for the second control point
55162       * @param  {Number} x4 x-coordinate for the second anchor point
55163       * @param  {Number} y4 y-coordinate for the second anchor point
55164       * @chainable
55165       * @example
55166       * <div>
55167       * <code>
55168       * noFill();
55169       * stroke(255, 102, 0);
55170       * line(85, 20, 10, 10);
55171       * line(90, 90, 15, 80);
55172       * stroke(0, 0, 0);
55173       * bezier(85, 20, 10, 10, 90, 90, 15, 80);
55174       * </code>
55175       * </div>
55176       *
55177       * <div>
55178       * <code>
55179       * background(0, 0, 0);
55180       * noFill();
55181       * stroke(255);
55182       * bezier(250, 250, 0, 100, 100, 0, 100, 0, 0, 0, 100, 0);
55183       * </code>
55184       * </div>
55185       *
55186       * @alt
55187       * stretched black s-shape in center with orange lines extending from end points.
55188       * stretched black s-shape with 10 5x5 white ellipses along the shape.
55189       * stretched black s-shape with 7 5x5 ellipses and orange lines along the shape.
55190       * stretched black s-shape with 17 small orange lines extending from under shape.
55191       * horseshoe shape with orange ends facing left and black curved center.
55192       * horseshoe shape with orange ends facing left and black curved center.
55193       * Line shaped like right-facing arrow,points move with mouse-x and warp shape.
55194       * horizontal line that hooks downward on the right and 13 5x5 ellipses along it.
55195       * right curving line mid-right of canvas with 7 short lines radiating from it.
55196       */
55197
55198      /**
55199       * @method bezier
55200       * @param  {Number} x1
55201       * @param  {Number} y1
55202       * @param  {Number} z1 z-coordinate for the first anchor point
55203       * @param  {Number} x2
55204       * @param  {Number} y2
55205       * @param  {Number} z2 z-coordinate for the first control point
55206       * @param  {Number} x3
55207       * @param  {Number} y3
55208       * @param  {Number} z3 z-coordinate for the second control point
55209       * @param  {Number} x4
55210       * @param  {Number} y4
55211       * @param  {Number} z4 z-coordinate for the second anchor point
55212       * @chainable
55213       */
55214
55215
55216      p5.prototype.bezier = function () {
55217        p5._validateParameters('bezier', arguments); // if the current stroke and fill settings wouldn't result in something
55218        // visible, exit immediately
55219
55220
55221        if (!this._renderer._doStroke && !this._renderer._doFill) {
55222          return this;
55223        }
55224
55225        this._renderer.bezier.apply(this._renderer, arguments);
55226
55227        return this;
55228      };
55229      /**
55230       * Sets the resolution at which Beziers display.
55231       *
55232       * The default value is 20.
55233       *
55234       * This function is only useful when using the WEBGL renderer
55235       * as the default canvas renderer does not use this information.
55236       *
55237       * @method bezierDetail
55238       * @param {Number} detail resolution of the curves
55239       * @chainable
55240       * @example
55241       * <div modernizr='webgl'>
55242       * <code>
55243       * function setup() {
55244       *   createCanvas(100, 100, WEBGL);
55245       *   noFill();
55246       *
55247       *   bezierDetail(5);
55248       * }
55249       *
55250       * function draw() {
55251       *   background(200);
55252       *
55253       *   // prettier-ignore
55254       *   bezier(-40, -40, 0,
55255       *           90, -40, 0,
55256       *          -90,  40, 0,
55257       *           40,  40, 0);
55258       * }
55259       * </code>
55260       * </div>
55261       *
55262       * @alt
55263       * stretched black s-shape with a low level of bezier detail
55264       *
55265       */
55266
55267
55268      p5.prototype.bezierDetail = function (d) {
55269        p5._validateParameters('bezierDetail', arguments);
55270
55271        this._bezierDetail = d;
55272        return this;
55273      };
55274      /**
55275       * Evaluates the Bezier at position t for points a, b, c, d.
55276       * The parameters a and d are the first and last points
55277       * on the curve, and b and c are the control points.
55278       * The final parameter t varies between 0 and 1.
55279       * This can be done once with the x coordinates and a second time
55280       * with the y coordinates to get the location of a bezier curve at t.
55281       *
55282       * @method bezierPoint
55283       * @param {Number} a coordinate of first point on the curve
55284       * @param {Number} b coordinate of first control point
55285       * @param {Number} c coordinate of second control point
55286       * @param {Number} d coordinate of second point on the curve
55287       * @param {Number} t value between 0 and 1
55288       * @return {Number} the value of the Bezier at position t
55289       * @example
55290       * <div>
55291       * <code>
55292       * noFill();
55293       * let x1 = 85,
55294        x2 = 10,
55295        x3 = 90,
55296        x4 = 15;
55297       * let y1 = 20,
55298        y2 = 10,
55299        y3 = 90,
55300        y4 = 80;
55301       * bezier(x1, y1, x2, y2, x3, y3, x4, y4);
55302       * fill(255);
55303       * let steps = 10;
55304       * for (let i = 0; i <= steps; i++) {
55305       *   let t = i / steps;
55306       *   let x = bezierPoint(x1, x2, x3, x4, t);
55307       *   let y = bezierPoint(y1, y2, y3, y4, t);
55308       *   ellipse(x, y, 5, 5);
55309       * }
55310       * </code>
55311       * </div>
55312       *
55313       * @alt
55314       * stretched black s-shape with 17 small orange lines extending from under shape.
55315       *
55316       */
55317
55318
55319      p5.prototype.bezierPoint = function (a, b, c, d, t) {
55320        p5._validateParameters('bezierPoint', arguments);
55321
55322        var adjustedT = 1 - t;
55323        return Math.pow(adjustedT, 3) * a + 3 * Math.pow(adjustedT, 2) * t * b + 3 * adjustedT * Math.pow(t, 2) * c + Math.pow(t, 3) * d;
55324      };
55325      /**
55326       * Evaluates the tangent to the Bezier at position t for points a, b, c, d.
55327       * The parameters a and d are the first and last points
55328       * on the curve, and b and c are the control points.
55329       * The final parameter t varies between 0 and 1.
55330       *
55331       * @method bezierTangent
55332       * @param {Number} a coordinate of first point on the curve
55333       * @param {Number} b coordinate of first control point
55334       * @param {Number} c coordinate of second control point
55335       * @param {Number} d coordinate of second point on the curve
55336       * @param {Number} t value between 0 and 1
55337       * @return {Number} the tangent at position t
55338       * @example
55339       * <div>
55340       * <code>
55341       * noFill();
55342       * bezier(85, 20, 10, 10, 90, 90, 15, 80);
55343       * let steps = 6;
55344       * fill(255);
55345       * for (let i = 0; i <= steps; i++) {
55346       *   let t = i / steps;
55347       *   // Get the location of the point
55348       *   let x = bezierPoint(85, 10, 90, 15, t);
55349       *   let y = bezierPoint(20, 10, 90, 80, t);
55350       *   // Get the tangent points
55351       *   let tx = bezierTangent(85, 10, 90, 15, t);
55352       *   let ty = bezierTangent(20, 10, 90, 80, t);
55353       *   // Calculate an angle from the tangent points
55354       *   let a = atan2(ty, tx);
55355       *   a += PI;
55356       *   stroke(255, 102, 0);
55357       *   line(x, y, cos(a) * 30 + x, sin(a) * 30 + y);
55358       *   // The following line of code makes a line
55359       *   // inverse of the above line
55360       *   //line(x, y, cos(a)*-30 + x, sin(a)*-30 + y);
55361       *   stroke(0);
55362       *   ellipse(x, y, 5, 5);
55363       * }
55364       * </code>
55365       * </div>
55366       *
55367       * <div>
55368       * <code>
55369       * noFill();
55370       * bezier(85, 20, 10, 10, 90, 90, 15, 80);
55371       * stroke(255, 102, 0);
55372       * let steps = 16;
55373       * for (let i = 0; i <= steps; i++) {
55374       *   let t = i / steps;
55375       *   let x = bezierPoint(85, 10, 90, 15, t);
55376       *   let y = bezierPoint(20, 10, 90, 80, t);
55377       *   let tx = bezierTangent(85, 10, 90, 15, t);
55378       *   let ty = bezierTangent(20, 10, 90, 80, t);
55379       *   let a = atan2(ty, tx);
55380       *   a -= HALF_PI;
55381       *   line(x, y, cos(a) * 8 + x, sin(a) * 8 + y);
55382       * }
55383       * </code>
55384       * </div>
55385       *
55386       * @alt
55387       * s-shaped line with 17 short orange lines extending from underside of shape
55388       *
55389       */
55390
55391
55392      p5.prototype.bezierTangent = function (a, b, c, d, t) {
55393        p5._validateParameters('bezierTangent', arguments);
55394
55395        var adjustedT = 1 - t;
55396        return 3 * d * Math.pow(t, 2) - 3 * c * Math.pow(t, 2) + 6 * c * adjustedT * t - 6 * b * adjustedT * t + 3 * b * Math.pow(adjustedT, 2) - 3 * a * Math.pow(adjustedT, 2);
55397      };
55398      /**
55399       * Draws a curved line on the screen between two points, given as the
55400       * middle four parameters. The first two parameters are a control point, as
55401       * if the curve came from this point even though it's not drawn. The last
55402       * two parameters similarly describe the other control point. <br /><br />
55403       * Longer curves can be created by putting a series of <a href="#/p5/curve">curve()</a> functions
55404       * together or using <a href="#/p5/curveVertex">curveVertex()</a>. An additional function called
55405       * <a href="#/p5/curveTightness">curveTightness()</a> provides control for the visual quality of the curve.
55406       * The <a href="#/p5/curve">curve()</a> function is an implementation of Catmull-Rom splines.
55407       *
55408       * @method curve
55409       * @param  {Number} x1 x-coordinate for the beginning control point
55410       * @param  {Number} y1 y-coordinate for the beginning control point
55411       * @param  {Number} x2 x-coordinate for the first point
55412       * @param  {Number} y2 y-coordinate for the first point
55413       * @param  {Number} x3 x-coordinate for the second point
55414       * @param  {Number} y3 y-coordinate for the second point
55415       * @param  {Number} x4 x-coordinate for the ending control point
55416       * @param  {Number} y4 y-coordinate for the ending control point
55417       * @chainable
55418       * @example
55419       * <div>
55420       * <code>
55421       * noFill();
55422       * stroke(255, 102, 0);
55423       * curve(5, 26, 5, 26, 73, 24, 73, 61);
55424       * stroke(0);
55425       * curve(5, 26, 73, 24, 73, 61, 15, 65);
55426       * stroke(255, 102, 0);
55427       * curve(73, 24, 73, 61, 15, 65, 15, 65);
55428       * </code>
55429       * </div>
55430       * <div>
55431       * <code>
55432       * // Define the curve points as JavaScript objects
55433       * let p1 = { x: 5, y: 26 },
55434        p2 = { x: 73, y: 24 };
55435       * let p3 = { x: 73, y: 61 },
55436        p4 = { x: 15, y: 65 };
55437       * noFill();
55438       * stroke(255, 102, 0);
55439       * curve(p1.x, p1.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
55440       * stroke(0);
55441       * curve(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);
55442       * stroke(255, 102, 0);
55443       * curve(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, p4.x, p4.y);
55444       * </code>
55445       * </div>
55446       * <div>
55447       * <code>
55448       * noFill();
55449       * stroke(255, 102, 0);
55450       * curve(5, 26, 0, 5, 26, 0, 73, 24, 0, 73, 61, 0);
55451       * stroke(0);
55452       * curve(5, 26, 0, 73, 24, 0, 73, 61, 0, 15, 65, 0);
55453       * stroke(255, 102, 0);
55454       * curve(73, 24, 0, 73, 61, 0, 15, 65, 0, 15, 65, 0);
55455       * </code>
55456       * </div>
55457       *
55458       * @alt
55459       * horseshoe shape with orange ends facing left and black curved center.
55460       * horseshoe shape with orange ends facing left and black curved center.
55461       * curving black and orange lines.
55462       */
55463
55464      /**
55465       * @method curve
55466       * @param  {Number} x1
55467       * @param  {Number} y1
55468       * @param  {Number} z1 z-coordinate for the beginning control point
55469       * @param  {Number} x2
55470       * @param  {Number} y2
55471       * @param  {Number} z2 z-coordinate for the first point
55472       * @param  {Number} x3
55473       * @param  {Number} y3
55474       * @param  {Number} z3 z-coordinate for the second point
55475       * @param  {Number} x4
55476       * @param  {Number} y4
55477       * @param  {Number} z4 z-coordinate for the ending control point
55478       * @chainable
55479       */
55480
55481
55482      p5.prototype.curve = function () {
55483        p5._validateParameters('curve', arguments);
55484
55485        if (this._renderer._doStroke) {
55486          this._renderer.curve.apply(this._renderer, arguments);
55487        }
55488
55489        return this;
55490      };
55491      /**
55492       * Sets the resolution at which curves display.
55493       *
55494       * The default value is 20 while the minimum value is 3.
55495       *
55496       * This function is only useful when using the WEBGL renderer
55497       * as the default canvas renderer does not use this
55498       * information.
55499       *
55500       * @method curveDetail
55501       * @param {Number} resolution resolution of the curves
55502       * @chainable
55503       * @example
55504       * <div modernizr='webgl'>
55505       * <code>
55506       * function setup() {
55507       *   createCanvas(100, 100, WEBGL);
55508       *
55509       *   curveDetail(5);
55510       * }
55511       * function draw() {
55512       *   background(200);
55513       *
55514       *   curve(250, 600, 0, -30, 40, 0, 30, 30, 0, -250, 600, 0);
55515       * }
55516       * </code>
55517       * </div>
55518       *
55519       * @alt
55520       * white arch shape with a low level of curve detail.
55521       *
55522       */
55523
55524
55525      p5.prototype.curveDetail = function (d) {
55526        p5._validateParameters('curveDetail', arguments);
55527
55528        if (d < 3) {
55529          this._curveDetail = 3;
55530        } else {
55531          this._curveDetail = d;
55532        }
55533
55534        return this;
55535      };
55536      /**
55537       * Modifies the quality of forms created with <a href="#/p5/curve">curve()</a> and <a href="#/p5/curveVertex">curveVertex()</a>.
55538       * The parameter tightness determines how the curve fits to the vertex
55539       * points. The value 0.0 is the default value for tightness (this value
55540       * defines the curves to be Catmull-Rom splines) and the value 1.0 connects
55541       * all the points with straight lines. Values within the range -5.0 and 5.0
55542       * will deform the curves but will leave them recognizable and as values
55543       * increase in magnitude, they will continue to deform.
55544       *
55545       * @method curveTightness
55546       * @param {Number} amount amount of deformation from the original vertices
55547       * @chainable
55548       * @example
55549       * <div>
55550       * <code>
55551       * // Move the mouse left and right to see the curve change
55552       *
55553       * function setup() {
55554       *   createCanvas(100, 100);
55555       *   noFill();
55556       * }
55557       *
55558       * function draw() {
55559       *   background(204);
55560       *   let t = map(mouseX, 0, width, -5, 5);
55561       *   curveTightness(t);
55562       *   beginShape();
55563       *   curveVertex(10, 26);
55564       *   curveVertex(10, 26);
55565       *   curveVertex(83, 24);
55566       *   curveVertex(83, 61);
55567       *   curveVertex(25, 65);
55568       *   curveVertex(25, 65);
55569       *   endShape();
55570       * }
55571       * </code>
55572       * </div>
55573       *
55574       * @alt
55575       * Line shaped like right-facing arrow,points move with mouse-x and warp shape.
55576       */
55577
55578
55579      p5.prototype.curveTightness = function (t) {
55580        p5._validateParameters('curveTightness', arguments);
55581
55582        this._renderer._curveTightness = t;
55583        return this;
55584      };
55585      /**
55586       * Evaluates the curve at position t for points a, b, c, d.
55587       * The parameter t varies between 0 and 1, a and d are control points
55588       * of the curve, and b and c are the start and end points of the curve.
55589       * This can be done once with the x coordinates and a second time
55590       * with the y coordinates to get the location of a curve at t.
55591       *
55592       * @method curvePoint
55593       * @param {Number} a coordinate of first control point of the curve
55594       * @param {Number} b coordinate of first point
55595       * @param {Number} c coordinate of second point
55596       * @param {Number} d coordinate of second control point
55597       * @param {Number} t value between 0 and 1
55598       * @return {Number} bezier value at position t
55599       * @example
55600       * <div>
55601       * <code>
55602       * noFill();
55603       * curve(5, 26, 5, 26, 73, 24, 73, 61);
55604       * curve(5, 26, 73, 24, 73, 61, 15, 65);
55605       * fill(255);
55606       * ellipseMode(CENTER);
55607       * let steps = 6;
55608       * for (let i = 0; i <= steps; i++) {
55609       *   let t = i / steps;
55610       *   let x = curvePoint(5, 5, 73, 73, t);
55611       *   let y = curvePoint(26, 26, 24, 61, t);
55612       *   ellipse(x, y, 5, 5);
55613       *   x = curvePoint(5, 73, 73, 15, t);
55614       *   y = curvePoint(26, 24, 61, 65, t);
55615       *   ellipse(x, y, 5, 5);
55616       * }
55617       * </code>
55618       * </div>
55619       *
55620       *line hooking down to right-bottom with 13 5x5 white ellipse points
55621       */
55622
55623
55624      p5.prototype.curvePoint = function (a, b, c, d, t) {
55625        p5._validateParameters('curvePoint', arguments);
55626
55627        var t3 = t * t * t,
55628            t2 = t * t,
55629            f1 = -0.5 * t3 + t2 - 0.5 * t,
55630            f2 = 1.5 * t3 - 2.5 * t2 + 1.0,
55631            f3 = -1.5 * t3 + 2.0 * t2 + 0.5 * t,
55632            f4 = 0.5 * t3 - 0.5 * t2;
55633        return a * f1 + b * f2 + c * f3 + d * f4;
55634      };
55635      /**
55636       * Evaluates the tangent to the curve at position t for points a, b, c, d.
55637       * The parameter t varies between 0 and 1, a and d are points on the curve,
55638       * and b and c are the control points.
55639       *
55640       * @method curveTangent
55641       * @param {Number} a coordinate of first point on the curve
55642       * @param {Number} b coordinate of first control point
55643       * @param {Number} c coordinate of second control point
55644       * @param {Number} d coordinate of second point on the curve
55645       * @param {Number} t value between 0 and 1
55646       * @return {Number} the tangent at position t
55647       * @example
55648       * <div>
55649       * <code>
55650       * noFill();
55651       * curve(5, 26, 73, 24, 73, 61, 15, 65);
55652       * let steps = 6;
55653       * for (let i = 0; i <= steps; i++) {
55654       *   let t = i / steps;
55655       *   let x = curvePoint(5, 73, 73, 15, t);
55656       *   let y = curvePoint(26, 24, 61, 65, t);
55657       *   //ellipse(x, y, 5, 5);
55658       *   let tx = curveTangent(5, 73, 73, 15, t);
55659       *   let ty = curveTangent(26, 24, 61, 65, t);
55660       *   let a = atan2(ty, tx);
55661       *   a -= PI / 2.0;
55662       *   line(x, y, cos(a) * 8 + x, sin(a) * 8 + y);
55663       * }
55664       * </code>
55665       * </div>
55666       *
55667       * @alt
55668       *right curving line mid-right of canvas with 7 short lines radiating from it.
55669       */
55670
55671
55672      p5.prototype.curveTangent = function (a, b, c, d, t) {
55673        p5._validateParameters('curveTangent', arguments);
55674
55675        var t2 = t * t,
55676            f1 = -3 * t2 / 2 + 2 * t - 0.5,
55677            f2 = 9 * t2 / 2 - 5 * t,
55678            f3 = -9 * t2 / 2 + 4 * t + 0.5,
55679            f4 = 3 * t2 / 2 - t;
55680        return a * f1 + b * f2 + c * f3 + d * f4;
55681      };
55682
55683      module.exports = p5;
55684    }, {
55685      "../error_helpers": 20,
55686      "../main": 24
55687    }],
55688    33: [function (_dereq_, module, exports) {
55689      /**
55690       * @module Shape
55691       * @submodule Vertex
55692       * @for p5
55693       * @requires core
55694       * @requires constants
55695       */
55696      'use strict';
55697
55698      var p5 = _dereq_('../main');
55699
55700      var constants = _dereq_('../constants');
55701
55702      var shapeKind = null;
55703      var vertices = [];
55704      var contourVertices = [];
55705      var isBezier = false;
55706      var isCurve = false;
55707      var isQuadratic = false;
55708      var isContour = false;
55709      var isFirstContour = true;
55710      /**
55711       * Use the <a href="#/p5/beginContour">beginContour()</a> and <a href="#/p5/endContour">endContour()</a> functions to create negative
55712       * shapes within shapes such as the center of the letter 'O'. <a href="#/p5/beginContour">beginContour()</a>
55713       * begins recording vertices for the shape and <a href="#/p5/endContour">endContour()</a> stops recording.
55714       * The vertices that define a negative shape must "wind" in the opposite
55715       * direction from the exterior shape. First draw vertices for the exterior
55716       * clockwise order, then for internal shapes, draw vertices
55717       * shape in counter-clockwise.
55718       * <br><br>
55719       * These functions can only be used within a <a href="#/p5/beginShape">beginShape()</a>/<a href="#/p5/endShape">endShape()</a> pair and
55720       * transformations such as <a href="#/p5/translate">translate()</a>, <a href="#/p5/rotate">rotate()</a>, and <a href="#/p5/scale">scale()</a> do not work
55721       * within a <a href="#/p5/beginContour">beginContour()</a>/<a href="#/p5/endContour">endContour()</a> pair. It is also not possible to use
55722       * other shapes, such as <a href="#/p5/ellipse">ellipse()</a> or <a href="#/p5/rect">rect()</a> within.
55723       *
55724       * @method beginContour
55725       * @chainable
55726       * @example
55727       * <div>
55728       * <code>
55729       * translate(50, 50);
55730       * stroke(255, 0, 0);
55731       * beginShape();
55732       * // Exterior part of shape, clockwise winding
55733       * vertex(-40, -40);
55734       * vertex(40, -40);
55735       * vertex(40, 40);
55736       * vertex(-40, 40);
55737       * // Interior part of shape, counter-clockwise winding
55738       * beginContour();
55739       * vertex(-20, -20);
55740       * vertex(-20, 20);
55741       * vertex(20, 20);
55742       * vertex(20, -20);
55743       * endContour();
55744       * endShape(CLOSE);
55745       * </code>
55746       * </div>
55747       *
55748       * @alt
55749       * white rect and smaller grey rect with red outlines in center of canvas.
55750       *
55751       */
55752
55753      p5.prototype.beginContour = function () {
55754        contourVertices = [];
55755        isContour = true;
55756        return this;
55757      };
55758      /**
55759       * Using the <a href="#/p5/beginShape">beginShape()</a> and <a href="#/p5/endShape">endShape()</a> functions allow creating more
55760       * complex forms. <a href="#/p5/beginShape">beginShape()</a> begins recording vertices for a shape and
55761       * <a href="#/p5/endShape">endShape()</a> stops recording. The value of the kind parameter tells it which
55762       * types of shapes to create from the provided vertices. With no mode
55763       * specified, the shape can be any irregular polygon.
55764       * <br><br>
55765       * The parameters available for <a href="#/p5/beginShape">beginShape()</a> are POINTS, LINES, TRIANGLES,
55766       * TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, and QUAD_STRIP. After calling the
55767       * <a href="#/p5/beginShape">beginShape()</a> function, a series of <a href="#/p5/vertex">vertex()</a> commands must follow. To stop
55768       * drawing the shape, call <a href="#/p5/endShape">endShape()</a>. Each shape will be outlined with the
55769       * current stroke color and filled with the fill color.
55770       * <br><br>
55771       * Transformations such as <a href="#/p5/translate">translate()</a>, <a href="#/p5/rotate">rotate()</a>, and <a href="#/p5/scale">scale()</a> do not work
55772       * within <a href="#/p5/beginShape">beginShape()</a>. It is also not possible to use other shapes, such as
55773       * <a href="#/p5/ellipse">ellipse()</a> or <a href="#/p5/rect">rect()</a> within <a href="#/p5/beginShape">beginShape()</a>.
55774       *
55775       * @method beginShape
55776       * @param  {Constant} [kind] either POINTS, LINES, TRIANGLES, TRIANGLE_FAN
55777       *                                TRIANGLE_STRIP, QUADS, or QUAD_STRIP
55778       * @chainable
55779       * @example
55780       * <div>
55781       * <code>
55782       * beginShape();
55783       * vertex(30, 20);
55784       * vertex(85, 20);
55785       * vertex(85, 75);
55786       * vertex(30, 75);
55787       * endShape(CLOSE);
55788       * </code>
55789       * </div>
55790       *
55791       * <div>
55792       * <code>
55793       * beginShape(POINTS);
55794       * vertex(30, 20);
55795       * vertex(85, 20);
55796       * vertex(85, 75);
55797       * vertex(30, 75);
55798       * endShape();
55799       * </code>
55800       * </div>
55801       *
55802       * <div>
55803       * <code>
55804       * beginShape(LINES);
55805       * vertex(30, 20);
55806       * vertex(85, 20);
55807       * vertex(85, 75);
55808       * vertex(30, 75);
55809       * endShape();
55810       * </code>
55811       * </div>
55812       *
55813       * <div>
55814       * <code>
55815       * noFill();
55816       * beginShape();
55817       * vertex(30, 20);
55818       * vertex(85, 20);
55819       * vertex(85, 75);
55820       * vertex(30, 75);
55821       * endShape();
55822       * </code>
55823       * </div>
55824       *
55825       * <div>
55826       * <code>
55827       * noFill();
55828       * beginShape();
55829       * vertex(30, 20);
55830       * vertex(85, 20);
55831       * vertex(85, 75);
55832       * vertex(30, 75);
55833       * endShape(CLOSE);
55834       * </code>
55835       * </div>
55836       *
55837       * <div>
55838       * <code>
55839       * beginShape(TRIANGLES);
55840       * vertex(30, 75);
55841       * vertex(40, 20);
55842       * vertex(50, 75);
55843       * vertex(60, 20);
55844       * vertex(70, 75);
55845       * vertex(80, 20);
55846       * endShape();
55847       * </code>
55848       * </div>
55849       *
55850       * <div>
55851       * <code>
55852       * beginShape(TRIANGLE_STRIP);
55853       * vertex(30, 75);
55854       * vertex(40, 20);
55855       * vertex(50, 75);
55856       * vertex(60, 20);
55857       * vertex(70, 75);
55858       * vertex(80, 20);
55859       * vertex(90, 75);
55860       * endShape();
55861       * </code>
55862       * </div>
55863       *
55864       * <div>
55865       * <code>
55866       * beginShape(TRIANGLE_FAN);
55867       * vertex(57.5, 50);
55868       * vertex(57.5, 15);
55869       * vertex(92, 50);
55870       * vertex(57.5, 85);
55871       * vertex(22, 50);
55872       * vertex(57.5, 15);
55873       * endShape();
55874       * </code>
55875       * </div>
55876       *
55877       * <div>
55878       * <code>
55879       * beginShape(QUADS);
55880       * vertex(30, 20);
55881       * vertex(30, 75);
55882       * vertex(50, 75);
55883       * vertex(50, 20);
55884       * vertex(65, 20);
55885       * vertex(65, 75);
55886       * vertex(85, 75);
55887       * vertex(85, 20);
55888       * endShape();
55889       * </code>
55890       * </div>
55891       *
55892       * <div>
55893       * <code>
55894       * beginShape(QUAD_STRIP);
55895       * vertex(30, 20);
55896       * vertex(30, 75);
55897       * vertex(50, 20);
55898       * vertex(50, 75);
55899       * vertex(65, 20);
55900       * vertex(65, 75);
55901       * vertex(85, 20);
55902       * vertex(85, 75);
55903       * endShape();
55904       * </code>
55905       * </div>
55906       *
55907       * <div>
55908       * <code>
55909       * beginShape();
55910       * vertex(20, 20);
55911       * vertex(40, 20);
55912       * vertex(40, 40);
55913       * vertex(60, 40);
55914       * vertex(60, 60);
55915       * vertex(20, 60);
55916       * endShape(CLOSE);
55917       * </code>
55918       * </div>
55919       * @alt
55920       * white square-shape with black outline in middle-right of canvas.
55921       * 4 black points in a square shape in middle-right of canvas.
55922       * 2 horizontal black lines. In the top-right and bottom-right of canvas.
55923       * 3 line shape with horizontal on top, vertical in middle and horizontal bottom.
55924       * square line shape in middle-right of canvas.
55925       * 2 white triangle shapes mid-right canvas. left one pointing up and right down.
55926       * 5 horizontal interlocking and alternating white triangles in mid-right canvas.
55927       * 4 interlocking white triangles in 45 degree rotated square-shape.
55928       * 2 white rectangle shapes in mid-right canvas. Both 20x55.
55929       * 3 side-by-side white rectangles center rect is smaller in mid-right canvas.
55930       * Thick white l-shape with black outline mid-top-left of canvas.
55931       *
55932       */
55933
55934
55935      p5.prototype.beginShape = function (kind) {
55936        p5._validateParameters('beginShape', arguments);
55937
55938        if (this._renderer.isP3D) {
55939          this._renderer.beginShape.apply(this._renderer, arguments);
55940        } else {
55941          if (kind === constants.POINTS || kind === constants.LINES || kind === constants.TRIANGLES || kind === constants.TRIANGLE_FAN || kind === constants.TRIANGLE_STRIP || kind === constants.QUADS || kind === constants.QUAD_STRIP) {
55942            shapeKind = kind;
55943          } else {
55944            shapeKind = null;
55945          }
55946
55947          vertices = [];
55948          contourVertices = [];
55949        }
55950
55951        return this;
55952      };
55953      /**
55954       * Specifies vertex coordinates for Bezier curves. Each call to
55955       * bezierVertex() defines the position of two control points and
55956       * one anchor point of a Bezier curve, adding a new segment to a
55957       * line or shape. For WebGL mode bezierVertex() can be used in 2D
55958       * as well as 3D mode. 2D mode expects 6 parameters, while 3D mode
55959       * expects 9 parameters (including z coordinates).
55960       * <br><br>
55961       * The first time bezierVertex() is used within a <a href="#/p5/beginShape">beginShape()</a>
55962       * call, it must be prefaced with a call to <a href="#/p5/vertex">vertex()</a> to set the first anchor
55963       * point. This function must be used between <a href="#/p5/beginShape">beginShape()</a> and <a href="#/p5/endShape">endShape()</a>
55964       * and only when there is no MODE or POINTS parameter specified to
55965       * <a href="#/p5/beginShape">beginShape()</a>.
55966       *
55967       * @method bezierVertex
55968       * @param  {Number} x2 x-coordinate for the first control point
55969       * @param  {Number} y2 y-coordinate for the first control point
55970       * @param  {Number} x3 x-coordinate for the second control point
55971       * @param  {Number} y3 y-coordinate for the second control point
55972       * @param  {Number}
55972 x4 x-coordinate for the anchor point
55973       * @param  {Number} y4 y-coordinate for the anchor point
55974       * @chainable
55975       *
55976       * @example
55977       * <div>
55978       * <code>
55979       * noFill();
55980       * beginShape();
55981       * vertex(30, 20);
55982       * bezierVertex(80, 0, 80, 75, 30, 75);
55983       * endShape();
55984       * </code>
55985       * </div>
55986       *
55987       * @alt
55988       * crescent-shaped line in middle of canvas. Points facing left.
55989       *
55990       * @example
55991       * <div>
55992       * <code>
55993       * beginShape();
55994       * vertex(30, 20);
55995       * bezierVertex(80, 0, 80, 75, 30, 75);
55996       * bezierVertex(50, 80, 60, 25, 30, 20);
55997       * endShape();
55998       * </code>
55999       * </div>
56000       *
56001       * @alt
56002       * white crescent shape in middle of canvas. Points facing left.
56003       *
56004       * @example
56005       * <div>
56006       * <code>
56007       * function setup() {
56008       *   createCanvas(100, 100, WEBGL);
56009       *   setAttributes('antialias', true);
56010       * }
56011       * function draw() {
56012       *   orbitControl();
56013       *   background(50);
56014       *   strokeWeight(4);
56015       *   stroke(255);
56016       *   point(-25, 30);
56017       *   point(25, 30);
56018       *   point(25, -30);
56019       *   point(-25, -30);
56020       *
56021       *   strokeWeight(1);
56022       *   noFill();
56023       *
56024       *   beginShape();
56025       *   vertex(-25, 30);
56026       *   bezierVertex(25, 30, 25, -30, -25, -30);
56027       *   endShape();
56028       *
56029       *   beginShape();
56030       *   vertex(-25, 30, 20);
56031       *   bezierVertex(25, 30, 20, 25, -30, 20, -25, -30, 20);
56032       *   endShape();
56033       * }
56034       * </code>
56035       * </div>
56036       *
56037       * @alt
56038       * crescent shape in middle of canvas with another crescent shape on positive z-axis.
56039       */
56040
56041      /**
56042       * @method bezierVertex
56043       * @param  {Number} x2
56044       * @param  {Number} y2
56045       * @param  {Number} z2 z-coordinate for the first control point (for WebGL mode)
56046       * @param  {Number} x3
56047       * @param  {Number} y3
56048       * @param  {Number} z3 z-coordinate for the second control point (for WebGL mode)
56049       * @param  {Number} x4
56050       * @param  {Number} y4
56051       * @param  {Number} z4 z-coordinate for the anchor point (for WebGL mode)
56052       * @chainable
56053       */
56054
56055
56056      p5.prototype.bezierVertex = function () {
56057        p5._validateParameters('bezierVertex', arguments);
56058
56059        if (this._renderer.isP3D) {
56060          this._renderer.bezierVertex.apply(this._renderer, arguments);
56061        } else {
56062          if (vertices.length === 0) {
56063            p5._friendlyError('vertex() must be used once before calling bezierVertex()', 'bezierVertex');
56064          } else {
56065            isBezier = true;
56066            var vert = [];
56067
56068            for (var i = 0; i < arguments.length; i++) {
56069              vert[i] = arguments[i];
56070            }
56071
56072            vert.isVert = false;
56073
56074            if (isContour) {
56075              contourVertices.push(vert);
56076            } else {
56077              vertices.push(vert);
56078            }
56079          }
56080        }
56081
56082        return this;
56083      };
56084      /**
56085       * Specifies vertex coordinates for curves. This function may only
56086       * be used between <a href="#/p5/beginShape">beginShape()</a> and <a href="#/p5/endShape">endShape()</a> and only when there
56087       * is no MODE parameter specified to <a href="#/p5/beginShape">beginShape()</a>.
56088       * For WebGL mode curveVertex() can be used in 2D as well as 3D mode.
56089       * 2D mode expects 2 parameters, while 3D mode expects 3 parameters.
56090       * <br><br>
56091       * The first and last points in a series of curveVertex() lines will be used to
56092       * guide the beginning and end of a the curve. A minimum of four
56093       * points is required to draw a tiny curve between the second and
56094       * third points. Adding a fifth point with curveVertex() will draw
56095       * the curve between the second, third, and fourth points. The
56096       * curveVertex() function is an implementation of Catmull-Rom
56097       * splines.
56098       *
56099       * @method curveVertex
56100       * @param {Number} x x-coordinate of the vertex
56101       * @param {Number} y y-coordinate of the vertex
56102       * @chainable
56103       * @example
56104       * <div>
56105       * <code>
56106       * strokeWeight(5);
56107       * point(84, 91);
56108       * point(68, 19);
56109       * point(21, 17);
56110       * point(32, 91);
56111       * strokeWeight(1);
56112       *
56113       * noFill();
56114       * beginShape();
56115       * curveVertex(84, 91);
56116       * curveVertex(84, 91);
56117       * curveVertex(68, 19);
56118       * curveVertex(21, 17);
56119       * curveVertex(32, 91);
56120       * curveVertex(32, 91);
56121       * endShape();
56122       * </code>
56123       * </div>
56124       *
56125       *
56126       * @alt
56127       * Upside-down u-shape line, mid canvas. left point extends beyond canvas view.
56128       */
56129
56130      /**
56131       * @method curveVertex
56132       * @param {Number} x
56133       * @param {Number} y
56134       * @param {Number} [z] z-coordinate of the vertex (for WebGL mode)
56135       * @chainable
56136       * @example
56137       * <div>
56138       * <code>
56139       * function setup() {
56140       *   createCanvas(100, 100, WEBGL);
56141       *   setAttributes('antialias', true);
56142       * }
56143       * function draw() {
56144       *   orbitControl();
56145       *   background(50);
56146       *   strokeWeight(4);
56147       *   stroke(255);
56148       *
56149       *   point(-25, 25);
56150       *   point(-25, 25);
56151       *   point(-25, -25);
56152       *   point(25, -25);
56153       *   point(25, 25);
56154       *   point(25, 25);
56155       *
56156       *   strokeWeight(1);
56157       *   noFill();
56158       *
56159       *   beginShape();
56160       *   curveVertex(-25, 25);
56161       *   curveVertex(-25, 25);
56162       *   curveVertex(-25, -25);
56163       *   curveVertex(25, -25);
56164       *   curveVertex(25, 25);
56165       *   curveVertex(25, 25);
56166       *   endShape();
56167       *
56168       *   beginShape();
56169       *   curveVertex(-25, 25, 20);
56170       *   curveVertex(-25, 25, 20);
56171       *   curveVertex(-25, -25, 20);
56172       *   curveVertex(25, -25, 20);
56173       *   curveVertex(25, 25, 20);
56174       *   curveVertex(25, 25, 20);
56175       *   endShape();
56176       * }
56177       * </code>
56178       * </div>
56179       *
56180       * @alt
56181       * Upside-down u-shape line, mid canvas with the same shape in positive z-axis.
56182       *
56183       */
56184
56185
56186      p5.prototype.curveVertex = function () {
56187        p5._validateParameters('curveVertex', arguments);
56188
56189        if (this._renderer.isP3D) {
56190          this._renderer.curveVertex.apply(this._renderer, arguments);
56191        } else {
56192          isCurve = true;
56193          this.vertex(arguments[0], arguments[1]);
56194        }
56195
56196        return this;
56197      };
56198      /**
56199       * Use the <a href="#/p5/beginContour">beginContour()</a> and <a href="#/p5/endContour">endContour()</a> functions to create negative
56200       * shapes within shapes such as the center of the letter 'O'. <a href="#/p5/beginContour">beginContour()</a>
56201       * begins recording vertices for the shape and <a href="#/p5/endContour">endContour()</a> stops recording.
56202       * The vertices that define a negative shape must "wind" in the opposite
56203       * direction from the exterior shape. First draw vertices for the exterior
56204       * clockwise order, then for internal shapes, draw vertices
56205       * shape in counter-clockwise.
56206       * <br><br>
56207       * These functions can only be used within a <a href="#/p5/beginShape">beginShape()</a>/<a href="#/p5/endShape">endShape()</a> pair and
56208       * transformations such as <a href="#/p5/translate">translate()</a>, <a href="#/p5/rotate">rotate()</a>, and <a href="#/p5/scale">scale()</a> do not work
56209       * within a <a href="#/p5/beginContour">beginContour()</a>/<a href="#/p5/endContour">endContour()</a> pair. It is also not possible to use
56210       * other shapes, such as <a href="#/p5/ellipse">ellipse()</a> or <a href="#/p5/rect">rect()</a> within.
56211       *
56212       * @method endContour
56213       * @chainable
56214       * @example
56215       * <div>
56216       * <code>
56217       * translate(50, 50);
56218       * stroke(255, 0, 0);
56219       * beginShape();
56220       * // Exterior part of shape, clockwise winding
56221       * vertex(-40, -40);
56222       * vertex(40, -40);
56223       * vertex(40, 40);
56224       * vertex(-40, 40);
56225       * // Interior part of shape, counter-clockwise winding
56226       * beginContour();
56227       * vertex(-20, -20);
56228       * vertex(-20, 20);
56229       * vertex(20, 20);
56230       * vertex(20, -20);
56231       * endContour();
56232       * endShape(CLOSE);
56233       * </code>
56234       * </div>
56235       *
56236       * @alt
56237       * white rect and smaller grey rect with red outlines in center of canvas.
56238       *
56239       */
56240
56241
56242      p5.prototype.endContour = function () {
56243        var vert = contourVertices[0].slice(); // copy all data
56244
56245        vert.isVert = contourVertices[0].isVert;
56246        vert.moveTo = false;
56247        contourVertices.push(vert); // prevent stray lines with multiple contours
56248
56249        if (isFirstContour) {
56250          vertices.push(vertices[0]);
56251          isFirstContour = false;
56252        }
56253
56254        for (var i = 0; i < contourVertices.length; i++) {
56255          vertices.push(contourVertices[i]);
56256        }
56257
56258        return this;
56259      };
56260      /**
56261       * The <a href="#/p5/endShape">endShape()</a> function is the companion to <a href="#/p5/beginShape">beginShape()</a> and may only be
56262       * called after <a href="#/p5/beginShape">beginShape()</a>. When <a href="#/p5/endshape">endshape()</a> is called, all of image data
56263       * defined since the previous call to <a href="#/p5/beginShape">beginShape()</a> is written into the image
56264       * buffer. The constant CLOSE as the value for the MODE parameter to close
56265       * the shape (to connect the beginning and the end).
56266       *
56267       * @method endShape
56268       * @param  {Constant} [mode] use CLOSE to close the shape
56269       * @chainable
56270       * @example
56271       * <div>
56272       * <code>
56273       * noFill();
56274       *
56275       * beginShape();
56276       * vertex(20, 20);
56277       * vertex(45, 20);
56278       * vertex(45, 80);
56279       * endShape(CLOSE);
56280       *
56281       * beginShape();
56282       * vertex(50, 20);
56283       * vertex(75, 20);
56284       * vertex(75, 80);
56285       * endShape();
56286       * </code>
56287       * </div>
56288       *
56289       * @alt
56290       * Triangle line shape with smallest interior angle on bottom and upside-down L.
56291       *
56292       */
56293
56294
56295      p5.prototype.endShape = function (mode) {
56296        p5._validateParameters('endShape', arguments);
56297
56298        if (this._renderer.isP3D) {
56299          this._renderer.endShape(mode, isCurve, isBezier, isQuadratic, isContour, shapeKind);
56300        } else {
56301          if (vertices.length === 0) {
56302            return this;
56303          }
56304
56305          if (!this._renderer._doStroke && !this._renderer._doFill) {
56306            return this;
56307          }
56308
56309          var closeShape = mode === constants.CLOSE; // if the shape is closed, the first element is also the last element
56310
56311          if (closeShape && !isContour) {
56312            vertices.push(vertices[0]);
56313          }
56314
56315          this._renderer.endShape(mode, vertices, isCurve, isBezier, isQuadratic, isContour, shapeKind); // Reset some settings
56316
56317
56318          isCurve = false;
56319          isBezier = false;
56320          isQuadratic = false;
56321          isContour = false;
56322          isFirstContour = true; // If the shape is closed, the first element was added as last element.
56323          // We must remove it again to prevent the list of vertices from growing
56324          // over successive calls to endShape(CLOSE)
56325
56326          if (closeShape) {
56327            vertices.pop();
56328          }
56329        }
56330
56331        return this;
56332      };
56333      /**
56334       * Specifies vertex coordinates for quadratic Bezier curves. Each call to
56335       * quadraticVertex() defines the position of one control points and one
56336       * anchor point of a Bezier curve, adding a new segment to a line or shape.
56337       * The first time quadraticVertex() is used within a <a href="#/p5/beginShape">beginShape()</a> call, it
56338       * must be prefaced with a call to <a href="#/p5/vertex">vertex()</a> to set the first anchor point.
56339       * For WebGL mode quadraticVertex() can be used in 2D as well as 3D mode.
56340       * 2D mode expects 4 parameters, while 3D mode expects 6 parameters
56341       * (including z coordinates).
56342       * <br><br>
56343       * This function must be used between <a href="#/p5/beginShape">beginShape()</a> and <a href="#/p5/endShape">endShape()</a>
56344       * and only when there is no MODE or POINTS parameter specified to
56345       * <a href="#/p5/beginShape">beginShape()</a>.
56346       *
56347       * @method quadraticVertex
56348       * @param  {Number} cx x-coordinate for the control point
56349       * @param  {Number} cy y-coordinate for the control point
56350       * @param  {Number} x3 x-coordinate for the anchor point
56351       * @param  {Number} y3 y-coordinate for the anchor point
56352       * @chainable
56353       *
56354       * @example
56355       * <div>
56356       * <code>
56357       * strokeWeight(5);
56358       * point(20, 20);
56359       * point(80, 20);
56360       * point(50, 50);
56361       *
56362       * noFill();
56363       * strokeWeight(1);
56364       * beginShape();
56365       * vertex(20, 20);
56366       * quadraticVertex(80, 20, 50, 50);
56367       * endShape();
56368       * </code>
56369       * </div>
56370       *
56371       * <div>
56372       * <code>
56373       * strokeWeight(5);
56374       * point(20, 20);
56375       * point(80, 20);
56376       * point(50, 50);
56377       *
56378       * point(20, 80);
56379       * point(80, 80);
56380       * point(80, 60);
56381       *
56382       * noFill();
56383       * strokeWeight(1);
56384       * beginShape();
56385       * vertex(20, 20);
56386       * quadraticVertex(80, 20, 50, 50);
56387       * quadraticVertex(20, 80, 80, 80);
56388       * vertex(80, 60);
56389       * endShape();
56390       * </code>
56391       * </div>
56392       *
56393       * @alt
56394       * arched-shaped black line with 4 pixel thick stroke weight.
56395       * backwards s-shaped black line with 4 pixel thick stroke weight.
56396       *
56397       */
56398
56399      /**
56400       * @method quadraticVertex
56401       * @param  {Number} cx
56402       * @param  {Number} cy
56403       * @param  {Number} cz z-coordinate for the control point (for WebGL mode)
56404       * @param  {Number} x3
56405       * @param  {Number} y3
56406       * @param  {Number} z3 z-coordinate for the anchor point (for WebGL mode)
56407       * @chainable
56408       *
56409       * @example
56410       * <div>
56411       * <code>
56412       * function setup() {
56413       *   createCanvas(100, 100, WEBGL);
56414       *   setAttributes('antialias', true);
56415       * }
56416       * function draw() {
56417       *   orbitControl();
56418       *   background(50);
56419       *   strokeWeight(4);
56420       *   stroke(255);
56421       *
56422       *   point(-35, -35);
56423       *   point(35, -35);
56424       *   point(0, 0);
56425       *   point(-35, 35);
56426       *   point(35, 35);
56427       *   point(35, 10);
56428       *
56429       *   strokeWeight(1);
56430       *   noFill();
56431       *
56432       *   beginShape();
56433       *   vertex(-35, -35);
56434       *   quadraticVertex(35, -35, 0, 0);
56435       *   quadraticVertex(-35, 35, 35, 35);
56436       *   vertex(35, 10);
56437       *   endShape();
56438       *
56439       *   beginShape();
56440       *   vertex(-35, -35, 20);
56441       *   quadraticVertex(35, -35, 20, 0, 0, 20);
56442       *   quadraticVertex(-35, 35, 20, 35, 35, 20);
56443       *   vertex(35, 10, 20);
56444       *   endShape();
56445       * }
56446       * </code>
56447       * </div>
56448       *
56449       * @alt
56450       * backwards s-shaped black line with the same s-shaped line in postive z-axis.
56451       */
56452
56453
56454      p5.prototype.quadraticVertex = function () {
56455        p5._validateParameters('quadraticVertex', arguments);
56456
56457        if (this._renderer.isP3D) {
56458          this._renderer.quadraticVertex.apply(this._renderer, arguments);
56459        } else {
56460          //if we're drawing a contour, put the points into an
56461          // array for inside drawing
56462          if (this._contourInited) {
56463            var pt = {};
56464            pt.x = arguments[0];
56465            pt.y = arguments[1];
56466            pt.x3 = arguments[2];
56467            pt.y3 = arguments[3];
56468            pt.type = constants.QUADRATIC;
56469
56470            this._contourVertices.push(pt);
56471
56472            return this;
56473          }
56474
56475          if (vertices.length > 0) {
56476            isQuadratic = true;
56477            var vert = [];
56478
56479            for (var i = 0; i < arguments.length; i++) {
56480              vert[i] = arguments[i];
56481            }
56482
56483            vert.isVert = false;
56484
56485            if (isContour) {
56486              contourVertices.push(vert);
56487            } else {
56488              vertices.push(vert);
56489            }
56490          } else {
56491            p5._friendlyError('vertex() must be used once before calling quadraticVertex()', 'quadraticVertex');
56492          }
56493        }
56494
56495        return this;
56496      };
56497      /**
56498       * All shapes are constructed by connecting a series of vertices. <a href="#/p5/vertex">vertex()</a>
56499       * is used to specify the vertex coordinates for points, lines, triangles,
56500       * quads, and polygons. It is used exclusively within the <a href="#/p5/beginShape">beginShape()</a> and
56501       * <a href="#/p5/endShape">endShape()</a> functions.
56502       *
56503       * @method vertex
56504       * @param  {Number} x x-coordinate of the vertex
56505       * @param  {Number} y y-coordinate of the vertex
56506       * @chainable
56507       * @example
56508       * <div>
56509       * <code>
56510       * strokeWeight(3);
56511       * beginShape(POINTS);
56512       * vertex(30, 20);
56513       * vertex(85, 20);
56514       * vertex(85, 75);
56515       * vertex(30, 75);
56516       * endShape();
56517       * </code>
56518       * </div>
56519       *
56520       * @alt
56521       * 4 black points in a square shape in middle-right of canvas.
56522       *
56523       * <div>
56524       * <code>
56525       * createCanvas(100, 100, WEBGL);
56526       * background(240, 240, 240);
56527       * fill(237, 34, 93);
56528       * noStroke();
56529       * beginShape();
56530       * vertex(0, 35);
56531       * vertex(35, 0);
56532       * vertex(0, -35);
56533       * vertex(-35, 0);
56534       * endShape();
56535       * </code>
56536       * </div>
56537       *
56538       * @alt
56539       * 4 points making a diamond shape
56540       *
56541       * <div>
56542       * <code>
56543       * createCanvas(100, 100, WEBGL);
56544       * background(240, 240, 240);
56545       * fill(237, 34, 93);
56546       * noStroke();
56547       * beginShape();
56548       * vertex(-10, 10);
56549       * vertex(0, 35);
56550       * vertex(10, 10);
56551       * vertex(35, 0);
56552       * vertex(10, -8);
56553       * vertex(0, -35);
56554       * vertex(-10, -8);
56555       * vertex(-35, 0);
56556       * endShape();
56557       * </code>
56558       * </div>
56559       *
56560       * @alt
56561       * 8 points making a star
56562       *
56563       * <div>
56564       * <code>
56565       * strokeWeight(3);
56566       * stroke(237, 34, 93);
56567       * beginShape(LINES);
56568       * vertex(10, 35);
56569       * vertex(90, 35);
56570       * vertex(10, 65);
56571       * vertex(90, 65);
56572       * vertex(35, 10);
56573       * vertex(35, 90);
56574       * vertex(65, 10);
56575       * vertex(65, 90);
56576       * endShape();
56577       * </code>
56578       * </div>
56579       *
56580       * @alt
56581       * 8 points making 4 lines
56582       *
56583       */
56584
56585      /**
56586       * @method vertex
56587       * @param  {Number} x
56588       * @param  {Number} y
56589       * @param  {Number} z   z-coordinate of the vertex
56590       * @param  {Number} [u] the vertex's texture u-coordinate
56591       * @param  {Number} [v] the vertex's texture v-coordinate
56592       * @chainable
56593       */
56594
56595
56596      p5.prototype.vertex = function (x, y, moveTo, u, v) {
56597        if (this._renderer.isP3D) {
56598          this._renderer.vertex.apply(this._renderer, arguments);
56599        } else {
56600          var vert = [];
56601          vert.isVert = true;
56602          vert[0] = x;
56603          vert[1] = y;
56604          vert[2] = 0;
56605          vert[3] = 0;
56606          vert[4] = 0;
56607          vert[5] = this._renderer._getFill();
56608          vert[6] = this._renderer._getStroke();
56609
56610          if (moveTo) {
56611            vert.moveTo = moveTo;
56612          }
56613
56614          if (isContour) {
56615            if (contourVertices.length === 0) {
56616              vert.moveTo = true;
56617            }
56618
56619            contourVertices.push(vert);
56620          } else {
56621            vertices.push(vert);
56622          }
56623        }
56624
56625        return this;
56626      };
56627
56628      module.exports = p5;
56629    }, {
56630      "../constants": 18,
56631      "../main": 24
56632    }],
56633    34: [function (_dereq_, module, exports) {
56634      'use strict'; // requestAnim shim layer by Paul Irish
56635      // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
56636      // http://my.opera.com/emoller/blog/2011/12/20/
56637      // requestanimationframe-for-smart-er-animating
56638      // requestAnimationFrame polyfill by Erik Möller
56639      // fixes from Paul Irish and Tino Zijdel
56640
56641      window.requestAnimationFrame = function () {
56642        return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback, element) {
56643          // should '60' here be framerate?
56644          window.setTimeout(callback, 1000 / 60);
56645        };
56646      }();
56647      /**
56648       * shim for Uint8ClampedArray.slice
56649       * (allows arrayCopy to work with pixels[])
56650       * with thanks to http://halfpapstudios.com/blog/tag/html5-canvas/
56651       * Enumerable set to false to protect for...in from
56652       * Uint8ClampedArray.prototype pollution.
56653       */
56654
56655
56656      (function () {
56657        'use strict';
56658
56659        if (typeof Uint8ClampedArray !== 'undefined' && !Uint8ClampedArray.prototype.slice) {
56660          Object.defineProperty(Uint8ClampedArray.prototype, 'slice', {
56661            value: Array.prototype.slice,
56662            writable: true,
56663            configurable: true,
56664            enumerable: false
56665          });
56666        }
56667      })();
56668      /**
56669       * this is implementation of Object.assign() which is unavailable in
56670       * IE11 and (non-Chrome) Android browsers.
56671       * The assign() method is used to copy the values of all enumerable
56672       * own properties from one or more source objects to a target object.
56673       * It will return the target object.
56674       * Modified from https://github.com/ljharb/object.assign
56675       */
56676
56677
56678      (function () {
56679        'use strict';
56680
56681        if (!Object.assign) {
56682          var keys = Object.keys;
56683          var defineProperty = Object.defineProperty;
56684
56685          var canBeObject = function (obj) {
56686            return typeof obj !== 'undefined' && obj !== null;
56687          };
56688
56689          var hasSymbols = typeof Symbol === 'function' && typeof Symbol() === 'symbol';
56690          var propIsEnumerable = Object.prototype.propertyIsEnumerable;
56691
56692          var isEnumerableOn = function (obj) {
56693            return function isEnumerable(prop) {
56694              return propIsEnumerable.call(obj, prop);
56695            };
56696          }; // per ES6 spec, this function has to have a length of 2
56697
56698
56699          var assignShim = function assign(target, source1) {
56700            if (!canBeObject(target)) {
56701              throw new TypeError('target must be an object');
56702            }
56703
56704            var objTarget = Object(target);
56705            var s, source, i, props;
56706
56707            for (s = 1; s < arguments.length; ++s) {
56708              source = Object(arguments[s]);
56709              props = keys(source);
56710
56711              if (hasSymbols && Object.getOwnPropertySymbols) {
56712                props.push.apply(props, Object.getOwnPropertySymbols(source).filter(isEnumerableOn(source)));
56713              }
56714
56715              for (i = 0; i < props.length; ++i) {
56716                objTarget[props[i]] = source[props[i]];
56717              }
56718            }
56719
56720            return objTarget;
56721          };
56722
56723          defineProperty(Object, 'assign', {
56724            value: assignShim,
56725            configurable: true,
56726            enumerable: false,
56727            writable: true
56728          });
56729        }
56730      })();
56731    }, {}],
56732    35: [function (_dereq_, module, exports) {
56733      /**
56734       * @module Structure
56735       * @submodule Structure
56736       * @for p5
56737       * @requires core
56738       */
56739      'use strict';
56740
56741      var p5 = _dereq_('./main');
56742      /**
56743       * Stops p5.js from continuously executing the code within <a href="#/p5/draw">draw()</a>.
56744       * If <a href="#/p5/loop">loop()</a> is called, the code in <a href="#/p5/draw">draw()</a> begins to run continuously again.
56745       * If using <a href="#/p5/noLoop">noLoop()</a> in <a href="#/p5/setup">setup()</a>, it should be the last line inside the block.
56746       * <br><br>
56747       * When <a href="#/p5/noLoop">noLoop()</a> is used, it's not possible to manipulate or access the
56748       * screen inside event handling functions such as <a href="#/p5/mousePressed">mousePressed()</a> or
56749       * <a href="#/p5/keyPressed">keyPressed()</a>. Instead, use those functions to call <a href="#/p5/redraw">redraw()</a> or <a href="#/p5/loop">loop()</a>,
56750       * which will run <a href="#/p5/draw">draw()</a>, which can update the screen properly. This means
56751       * that when <a href="#/p5/noLoop">noLoop()</a> has been called, no drawing can happen, and functions
56752       * like <a href="#/p5/saveFrame">saveFrame()</a> or <a href="#/p5/loadPixels">loadPixels()</a> may not be used.
56753       * <br><br>
56754       * Note that if the sketch is resized, <a href="#/p5/redraw">redraw()</a> will be called to update
56755       * the sketch, even after <a href="#/p5/noLoop">noLoop()</a> has been specified. Otherwise, the sketch
56756       * would enter an odd state until <a href="#/p5/loop">loop()</a> was called.
56757       *
56758       * @method noLoop
56759       * @example
56760       * <div><code>
56761       * function setup() {
56762       *   createCanvas(100, 100);
56763       *   background(200);
56764       *   noLoop();
56765       * }
56766      
56767       * function draw() {
56768       *   line(10, 10, 90, 90);
56769       * }
56770       * </code></div>
56771       *
56772       * <div><code>
56773       * let x = 0;
56774       * function setup() {
56775       *   createCanvas(100, 100);
56776       * }
56777       *
56778       * function draw() {
56779       *   background(204);
56780       *   x = x + 0.1;
56781       *   if (x > width) {
56782       *     x = 0;
56783       *   }
56784       *   line(x, 0, x, height);
56785       * }
56786       *
56787       * function mousePressed() {
56788       *   noLoop();
56789       * }
56790       *
56791       * function mouseReleased() {
56792       *   loop();
56793       * }
56794       * </code></div>
56795       *
56796       * @alt
56797       * 113 pixel long line extending from top-left to bottom right of canvas.
56798       * horizontal line moves slowly from left. Loops but stops on mouse press.
56799       *
56800       */
56801
56802
56803      p5.prototype.noLoop = function () {
56804        this._loop = false;
56805      };
56806      /**
56807       * By default, p5.js loops through draw() continuously, executing the code
56808       * within it. However, the <a href="#/p5/draw">draw()</a> loop may be stopped by calling <a href="#/p5/noLoop">noLoop()</a>.
56809       * In that case, the <a href="#/p5/draw">draw()</a> loop can be resumed with loop().
56810       *
56811       * @method loop
56812       * @example
56813       * <div><code>
56814       * let x = 0;
56815       * function setup() {
56816       *   createCanvas(100, 100);
56817       *   noLoop();
56818       * }
56819       *
56820       * function draw() {
56821       *   background(204);
56822       *   x = x + 0.1;
56823       *   if (x > width) {
56824       *     x = 0;
56825       *   }
56826       *   line(x, 0, x, height);
56827       * }
56828       *
56829       * function mousePressed() {
56830       *   loop();
56831       * }
56832       *
56833       * function mouseReleased() {
56834       *   noLoop();
56835       * }
56836       * </code></div>
56837       *
56838       * @alt
56839       * horizontal line moves slowly from left. Loops but stops on mouse press.
56840       *
56841       */
56842
56843
56844      p5.prototype.loop = function () {
56845        this._loop = true;
56846
56847        this._draw();
56848      };
56849      /**
56850       * The <a href="#/p5/push">push()</a> function saves the current drawing style settings and
56851       * transformations, while <a href="#/p5/pop">pop()</a> restores these settings. Note that these
56852       * functions are always used together. They allow you to change the style
56853       * and transformation settings and later return to what you had. When a new
56854       * state is started with <a href="#/p5/push">push()</a>, it builds on the current style and transform
56855       * information. The <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a> functions can be embedded to provide
56856       * more control. (See the second example for a demonstration.)
56857       * <br><br>
56858       * <a href="#/p5/push">push()</a> stores information related to the current transformation state
56859       * and style settings controlled by the following functions: <a href="#/p5/fill">fill()</a>,
56860       * <a href="#/p5/stroke">stroke()</a>, <a href="#/p5/tint">tint()</a>, <a href="#/p5/strokeWeight">
56860strokeWeight()</a>, <a href="#/p5/strokeCap">strokeCap()</a>, <a href="#/p5/strokeJoin">strokeJoin()</a>,
56861       * <a href="#/p5/imageMode">imageMode()</a>, <a href="#/p5/rectMode">rectMode()</a>, <a href="#/p5/ellipseMode">ellipseMode()</a>, <a href="#/p5/colorMode">colorMode()</a>, <a href="#/p5/textAlign">textAlign()</a>,
56862       * <a href="#/p5/textFont">textFont()</a>, <a href="#/p5/textMode">textMode()</a>, <a href="#/p5/textSize">textSize()</a>, <a href="#/p5/textLeading">textLeading()</a>.
56863       *
56864       * @method push
56865       * @example
56866       * <div>
56867       * <code>
56868       * ellipse(0, 50, 33, 33); // Left circle
56869       *
56870       * push(); // Start a new drawing state
56871       * strokeWeight(10);
56872       * fill(204, 153, 0);
56873       * translate(50, 0);
56874       * ellipse(0, 50, 33, 33); // Middle circle
56875       * pop(); // Restore original state
56876       *
56877       * ellipse(100, 50, 33, 33); // Right circle
56878       * </code>
56879       * </div>
56880       * <div>
56881       * <code>
56882       * ellipse(0, 50, 33, 33); // Left circle
56883       *
56884       * push(); // Start a new drawing state
56885       * strokeWeight(10);
56886       * fill(204, 153, 0);
56887       * ellipse(33, 50, 33, 33); // Left-middle circle
56888       *
56889       * push(); // Start another new drawing state
56890       * stroke(0, 102, 153);
56891       * ellipse(66, 50, 33, 33); // Right-middle circle
56892       * pop(); // Restore previous state
56893       *
56894       * pop(); // Restore original state
56895       *
56896       * ellipse(100, 50, 33, 33); // Right circle
56897       * </code>
56898       * </div>
56899       *
56900       * @alt
56901       * Gold ellipse + thick black outline @center 2 white ellipses on left and right.
56902       * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right.
56903       *
56904       */
56905
56906
56907      p5.prototype.push = function () {
56908        this._styles.push({
56909          props: {
56910            _colorMode: this._colorMode
56911          },
56912          renderer: this._renderer.push()
56913        });
56914      };
56915      /**
56916       * The <a href="#/p5/push">push()</a> function saves the current drawing style settings and
56917       * transformations, while <a href="#/p5/pop">pop()</a> restores these settings. Note that these
56918       * functions are always used together. They allow you to change the style
56919       * and transformation settings and later return to what you had. When a new
56920       * state is started with <a href="#/p5/push">push()</a>, it builds on the current style and transform
56921       * information. The <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a> functions can be embedded to provide
56922       * more control. (See the second example for a demonstration.)
56923       * <br><br>
56924       * <a href="#/p5/push">push()</a> stores information related to the current transformation state
56925       * and style settings controlled by the following functions: <a href="#/p5/fill">fill()</a>,
56926       * <a href="#/p5/stroke">stroke()</a>, <a href="#/p5/tint">tint()</a>, <a href="#/p5/strokeWeight">
56926strokeWeight()</a>, <a href="#/p5/strokeCap">strokeCap()</a>, <a href="#/p5/strokeJoin">strokeJoin()</a>,
56927       * <a href="#/p5/imageMode">imageMode()</a>, <a href="#/p5/rectMode">rectMode()</a>, <a href="#/p5/ellipseMode">ellipseMode()</a>, <a href="#/p5/colorMode">colorMode()</a>, <a href="#/p5/textAlign">textAlign()</a>,
56928       * <a href="#/p5/textFont">textFont()</a>, <a href="#/p5/textMode">textMode()</a>, <a href="#/p5/textSize">textSize()</a>, <a href="#/p5/textLeading">textLeading()</a>.
56929       *
56930       * @method pop
56931       * @example
56932       * <div>
56933       * <code>
56934       * ellipse(0, 50, 33, 33); // Left circle
56935       *
56936       * push(); // Start a new drawing state
56937       * translate(50, 0);
56938       * strokeWeight(10);
56939       * fill(204, 153, 0);
56940       * ellipse(0, 50, 33, 33); // Middle circle
56941       * pop(); // Restore original state
56942       *
56943       * ellipse(100, 50, 33, 33); // Right circle
56944       * </code>
56945       * </div>
56946       * <div>
56947       * <code>
56948       * ellipse(0, 50, 33, 33); // Left circle
56949       *
56950       * push(); // Start a new drawing state
56951       * strokeWeight(10);
56952       * fill(204, 153, 0);
56953       * ellipse(33, 50, 33, 33); // Left-middle circle
56954       *
56955       * push(); // Start another new drawing state
56956       * stroke(0, 102, 153);
56957       * ellipse(66, 50, 33, 33); // Right-middle circle
56958       * pop(); // Restore previous state
56959       *
56960       * pop(); // Restore original state
56961       *
56962       * ellipse(100, 50, 33, 33); // Right circle
56963       * </code>
56964       * </div>
56965       *
56966       * @alt
56967       * Gold ellipse + thick black outline @center 2 white ellipses on left and right.
56968       * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right.
56969       *
56970       */
56971
56972
56973      p5.prototype.pop = function () {
56974        var style = this._styles.pop();
56975
56976        if (style) {
56977          this._renderer.pop(style.renderer);
56978
56979          Object.assign(this, style.props);
56980        } else {
56981          console.warn('pop() was called without matching push()');
56982        }
56983      };
56984      /**
56985       *
56986       * Executes the code within <a href="#/p5/draw">draw()</a> one time. This functions allows the
56987       * program to update the display window only when necessary, for example
56988       * when an event registered by <a href="#/p5/mousePressed">mousePressed()</a> or <a href="#/p5/keyPressed">keyPressed()</a> occurs.
56989       * <br><br>
56990       * In structuring a program, it only makes sense to call <a href="#/p5/redraw">redraw()</a> within
56991       * events such as <a href="#/p5/mousePressed">mousePressed()</a>. This is because <a href="#/p5/redraw">redraw()</a> does not run
56992       * <a href="#/p5/draw">draw()</a> immediately (it only sets a flag that indicates an update is
56993       * needed).
56994       * <br><br>
56995       * The <a href="#/p5/redraw">redraw()</a> function does not work properly when called inside <a href="#/p5/draw">draw()</a>.
56996       * To enable/disable animations, use <a href="#/p5/loop">loop()</a> and <a href="#/p5/noLoop">noLoop()</a>.
56997       * <br><br>
56998       * In addition you can set the number of redraws per method call. Just
56999       * add an integer as single parameter for the number of redraws.
57000       *
57001       * @method redraw
57002       * @param  {Integer} [n] Redraw for n-times. The default value is 1.
57003       * @example
57004       * <div><code>
57005       * let x = 0;
57006       *
57007       * function setup() {
57008       *   createCanvas(100, 100);
57009       *   noLoop();
57010       * }
57011       *
57012       * function draw() {
57013       *   background(204);
57014       *   line(x, 0, x, height);
57015       * }
57016       *
57017       * function mousePressed() {
57018       *   x += 1;
57019       *   redraw();
57020       * }
57021       * </code></div>
57022       *
57023       * <div class='norender'><code>
57024       * let x = 0;
57025       *
57026       * function setup() {
57027       *   createCanvas(100, 100);
57028       *   noLoop();
57029       * }
57030       *
57031       * function draw() {
57032       *   background(204);
57033       *   x += 1;
57034       *   line(x, 0, x, height);
57035       * }
57036       *
57037       * function mousePressed() {
57038       *   redraw(5);
57039       * }
57040       * </code></div>
57041       *
57042       * @alt
57043       * black line on far left of canvas
57044       * black line on far left of canvas
57045       *
57046       */
57047
57048
57049      p5.prototype.redraw = function (n) {
57050        var numberOfRedraws = parseInt(n);
57051
57052        if (isNaN(numberOfRedraws) || numberOfRedraws < 1) {
57053          numberOfRedraws = 1;
57054        }
57055
57056        var context = this._isGlobal ? window : this;
57057        var userSetup = context.setup;
57058        var userDraw = context.draw;
57059
57060        if (typeof userDraw === 'function') {
57061          if (typeof userSetup === 'undefined') {
57062            context.scale(context._pixelDensity, context._pixelDensity);
57063          }
57064
57065          var callMethod = function (f) {
57066            f.call(context);
57067          };
57068
57069          for (var idxRedraw = 0; idxRedraw < numberOfRedraws; idxRedraw++) {
57070            context.resetMatrix();
57071
57072            if (context._renderer.isP3D) {
57073              context._renderer._update();
57074            }
57075
57076            context._setProperty('frameCount', context.frameCount + 1);
57077
57078            context._registeredMethods.pre.forEach(callMethod);
57079
57080            userDraw();
57081
57082            context._registeredMethods.post.forEach(callMethod);
57083          }
57084        }
57085      };
57086
57087      module.exports = p5;
57088    }, {
57089      "./main": 24
57090    }],
57091    36: [function (_dereq_, module, exports) {
57092      /**
57093       * @module Transform
57094       * @submodule Transform
57095       * @for p5
57096       * @requires core
57097       * @requires constants
57098       */
57099      'use strict';
57100
57101      var p5 = _dereq_('./main');
57102      /**
57103       * Multiplies the current matrix by the one specified through the parameters.
57104       * This is a powerful operation that can perform the equivalent of translate,
57105       * scale, shear and rotate all at once. You can learn more about transformation
57106       * matrices on <a href="https://en.wikipedia.org/wiki/Transformation_matrix">
57107       * Wikipedia</a>.
57108       *
57109       * The naming of the arguments here follows the naming of the <a href=
57110       * "https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform">
57111       * WHATWG specification</a> and corresponds to a
57112       * transformation matrix of the
57113       * form:
57114       *
57115       * > <img style="max-width: 150px" src="assets/transformation-matrix.png"
57116       * alt="The transformation matrix used when applyMatrix is called"/>
57117       *
57118       * @method applyMatrix
57119       * @param  {Number} a numbers which define the 2x3 matrix to be multiplied
57120       * @param  {Number} b numbers which define the 2x3 matrix to be multiplied
57121       * @param  {Number} c numbers which define the 2x3 matrix to be multiplied
57122       * @param  {Number} d numbers which define the 2x3 matrix to be multiplied
57123       * @param  {Number} e numbers which define the 2x3 matrix to be multiplied
57124       * @param  {Number} f numbers which define the 2x3 matrix to be multiplied
57125       * @chainable
57126       * @example
57127       * <div>
57128       * <code>
57129       * function setup() {
57130       *   frameRate(10);
57131       *   rectMode(CENTER);
57132       * }
57133       *
57134       * function draw() {
57135       *   var step = frameCount % 20;
57136       *   background(200);
57137       *   // Equivalent to translate(x, y);
57138       *   applyMatrix(1, 0, 0, 1, 40 + step, 50);
57139       *   rect(0, 0, 50, 50);
57140       * }
57141       * </code>
57142       * </div>
57143       * <div>
57144       * <code>
57145       * function setup() {
57146       *   frameRate(10);
57147       *   rectMode(CENTER);
57148       * }
57149       *
57150       * function draw() {
57151       *   var step = frameCount % 20;
57152       *   background(200);
57153       *   translate(50, 50);
57154       *   // Equivalent to scale(x, y);
57155       *   applyMatrix(1 / step, 0, 0, 1 / step, 0, 0);
57156       *   rect(0, 0, 50, 50);
57157       * }
57158       * </code>
57159       * </div>
57160       * <div>
57161       * <code>
57162       * function setup() {
57163       *   frameRate(10);
57164       *   rectMode(CENTER);
57165       * }
57166       *
57167       * function draw() {
57168       *   var step = frameCount % 20;
57169       *   var angle = map(step, 0, 20, 0, TWO_PI);
57170       *   var cos_a = cos(angle);
57171       *   var sin_a = sin(angle);
57172       *   background(200);
57173       *   translate(50, 50);
57174       *   // Equivalent to rotate(angle);
57175       *   applyMatrix(cos_a, sin_a, -sin_a, cos_a, 0, 0);
57176       *   rect(0, 0, 50, 50);
57177       * }
57178       * </code>
57179       * </div>
57180       * <div>
57181       * <code>
57182       * function setup() {
57183       *   frameRate(10);
57184       *   rectMode(CENTER);
57185       * }
57186       *
57187       * function draw() {
57188       *   var step = frameCount % 20;
57189       *   var angle = map(step, 0, 20, -PI / 4, PI / 4);
57190       *   background(200);
57191       *   translate(50, 50);
57192       *   // equivalent to shearX(angle);
57193       *   var shear_factor = 1 / tan(PI / 2 - angle);
57194       *   applyMatrix(1, 0, shear_factor, 1, 0, 0);
57195       *   rect(0, 0, 50, 50);
57196       * }
57197       * </code>
57198       * </div>
57199       *
57200       * @alt
57201       * A rectangle translating to the right
57202       * A rectangle shrinking to the center
57203       * A rectangle rotating clockwise about the center
57204       * A rectangle shearing
57205       *
57206       */
57207
57208
57209      p5.prototype.applyMatrix = function (a, b, c, d, e, f) {
57210        this._renderer.applyMatrix(a, b, c, d, e, f);
57211
57212        return this;
57213      };
57214
57215      p5.prototype.popMatrix = function () {
57216        throw new Error('popMatrix() not used, see pop()');
57217      };
57218
57219      p5.prototype.printMatrix = function () {
57220        throw new Error('printMatrix() not implemented');
57221      };
57222
57223      p5.prototype.pushMatrix = function () {
57224        throw new Error('pushMatrix() not used, see push()');
57225      };
57226      /**
57227       * Replaces the current matrix with the identity matrix.
57228       *
57229       * @method resetMatrix
57230       * @chainable
57231       * @example
57232       * <div>
57233       * <code>
57234       * translate(50, 50);
57235       * applyMatrix(0.5, 0.5, -0.5, 0.5, 0, 0);
57236       * rect(0, 0, 20, 20);
57237       * // Note that the translate is also reset.
57238       * resetMatrix();
57239       * rect(0, 0, 20, 20);
57240       * </code>
57241       * </div>
57242       *
57243       * @alt
57244       * A rotated retangle in the center with another at the top left corner
57245       *
57246       */
57247
57248
57249      p5.prototype.resetMatrix = function () {
57250        this._renderer.resetMatrix();
57251
57252        return this;
57253      };
57254      /**
57255       * Rotates a shape the amount specified by the angle parameter. This
57256       * function accounts for <a href="#/p5/angleMode">angleMode</a>, so angles can be entered in either
57257       * RADIANS or DEGREES.
57258       * <br><br>
57259       * Objects are always rotated around their relative position to the
57260       * origin and positive numbers rotate objects in a clockwise direction.
57261       * Transformations apply to everything that happens after and subsequent
57262       * calls to the function accumulates the effect. For example, calling
57263       * rotate(HALF_PI) and then rotate(HALF_PI) is the same as rotate(PI).
57264       * All tranformations are reset when <a href="#/p5/draw">draw()</a> begins again.
57265       * <br><br>
57266       * Technically, <a href="#/p5/rotate">rotate()</a> multiplies the current transformation matrix
57267       * by a rotation matrix. This function can be further controlled by
57268       * the <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a>.
57269       *
57270       * @method rotate
57271       * @param  {Number} angle the angle of rotation, specified in radians
57272       *                        or degrees, depending on current angleMode
57273       * @param  {p5.Vector|Number[]} [axis] (in 3d) the axis to rotate around
57274       * @chainable
57275       * @example
57276       * <div>
57277       * <code>
57278       * translate(width / 2, height / 2);
57279       * rotate(PI / 3.0);
57280       * rect(-26, -26, 52, 52);
57281       * </code>
57282       * </div>
57283       *
57284       * @alt
57285       * white 52x52 rect with black outline at center rotated counter 45 degrees
57286       *
57287       */
57288
57289
57290      p5.prototype.rotate = function (angle, axis) {
57291        p5._validateParameters('rotate', arguments);
57292
57293        this._renderer.rotate(this._toRadians(angle), axis);
57294
57295        return this;
57296      };
57297      /**
57298       * Rotates around X axis.
57299       * @method  rotateX
57300       * @param  {Number} angle the angle of rotation, specified in radians
57301       *                        or degrees, depending on current angleMode
57302       * @chainable
57303       * @example
57304       * <div modernizr='webgl'>
57305       * <code>
57306       * function setup() {
57307       *   createCanvas(100, 100, WEBGL);
57308       * }
57309       * function draw() {
57310       *   background(255);
57311       *   rotateX(millis() / 1000);
57312       *   box();
57313       * }
57314       * </code>
57315       * </div>
57316       *
57317       * @alt
57318       * 3d box rotating around the x axis.
57319       */
57320
57321
57322      p5.prototype.rotateX = function (angle) {
57323        this._assert3d('rotateX');
57324
57325        p5._validateParameters('rotateX', arguments);
57326
57327        this._renderer.rotateX(this._toRadians(angle));
57328
57329        return this;
57330      };
57331      /**
57332       * Rotates around Y axis.
57333       * @method rotateY
57334       * @param  {Number} angle the angle of rotation, specified in radians
57335       *                        or degrees, depending on current angleMode
57336       * @chainable
57337       * @example
57338       * <div modernizr='webgl'>
57339       * <code>
57340       * function setup() {
57341       *   createCanvas(100, 100, WEBGL);
57342       * }
57343       * function draw() {
57344       *   background(255);
57345       *   rotateY(millis() / 1000);
57346       *   box();
57347       * }
57348       * </code>
57349       * </div>
57350       *
57351       * @alt
57352       * 3d box rotating around the y axis.
57353       */
57354
57355
57356      p5.prototype.rotateY = function (angle) {
57357        this._assert3d('rotateY');
57358
57359        p5._validateParameters('rotateY', arguments);
57360
57361        this._renderer.rotateY(this._toRadians(angle));
57362
57363        return this;
57364      };
57365      /**
57366       * Rotates around Z axis. Webgl mode only.
57367       * @method rotateZ
57368       * @param  {Number} angle the angle of rotation, specified in radians
57369       *                        or degrees, depending on current angleMode
57370       * @chainable
57371       * @example
57372       * <div modernizr='webgl'>
57373       * <code>
57374       * function setup() {
57375       *   createCanvas(100, 100, WEBGL);
57376       * }
57377       * function draw() {
57378       *   background(255);
57379       *   rotateZ(millis() / 1000);
57380       *   box();
57381       * }
57382       * </code>
57383       * </div>
57384       *
57385       * @alt
57386       * 3d box rotating around the z axis.
57387       */
57388
57389
57390      p5.prototype.rotateZ = function (angle) {
57391        this._assert3d('rotateZ');
57392
57393        p5._validateParameters('rotateZ', arguments);
57394
57395        this._renderer.rotateZ(this._toRadians(angle));
57396
57397        return this;
57398      };
57399      /**
57400       * Increases or decreases the size of a shape by expanding and contracting
57401       * vertices. Objects always scale from their relative origin to the
57402       * coordinate system. Scale values are specified as decimal percentages.
57403       * For example, the function call scale(2.0) increases the dimension of a
57404       * shape by 200%.
57405       * <br><br>
57406       * Transformations apply to everything that happens after and subsequent
57407       * calls to the function multiply the effect. For example, calling scale(2.0)
57408       * and then scale(1.5) is the same as scale(3.0). If <a href="#/p5/scale">scale()</a> is called
57409       * within <a href="#/p5/draw">draw()</a>, the transformation is reset when the loop begins again.
57410       * <br><br>
57411       * Using this function with the z parameter is only available in WEBGL mode.
57412       * This function can be further controlled with <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a>.
57413       *
57414       * @method scale
57415       * @param  {Number|p5.Vector|Number[]} s
57416       *                      percent to scale the object, or percentage to
57417       *                      scale the object in the x-axis if multiple arguments
57418       *                      are given
57419       * @param  {Number} [y] percent to scale the object in the y-axis
57420       * @param  {Number} [z] percent to scale the object in the z-axis (webgl only)
57421       * @chainable
57422       * @example
57423       * <div>
57424       * <code>
57425       * rect(30, 20, 50, 50);
57426       * scale(0.5);
57427       * rect(30, 20, 50, 50);
57428       * </code>
57429       * </div>
57430       *
57431       * <div>
57432       * <code>
57433       * rect(30, 20, 50, 50);
57434       * scale(0.5, 1.3);
57435       * rect(30, 20, 50, 50);
57436       * </code>
57437       * </div>
57438       *
57439       * @alt
57440       * white 52x52 rect with black outline at center rotated counter 45 degrees
57441       * 2 white rects with black outline- 1 50x50 at center. other 25x65 bottom left
57442       *
57443       */
57444
57445      /**
57446       * @method scale
57447       * @param  {p5.Vector|Number[]} scales per-axis percents to scale the object
57448       * @chainable
57449       */
57450
57451
57452      p5.prototype.scale = function (x, y, z) {
57453        p5._validateParameters('scale', arguments); // Only check for Vector argument type if Vector is available
57454
57455
57456        if (x instanceof p5.Vector) {
57457          var v = x;
57458          x = v.x;
57459          y = v.y;
57460          z = v.z;
57461        } else if (x instanceof Array) {
57462          var rg = x;
57463          x = rg[0];
57464          y = rg[1];
57465          z = rg[2] || 1;
57466        }
57467
57468        if (isNaN(y)) {
57469          y = z = x;
57470        } else if (isNaN(z)) {
57471          z = 1;
57472        }
57473
57474        this._renderer.scale.call(this._renderer, x, y, z);
57475
57476        return this;
57477      };
57478      /**
57479       * Shears a shape around the x-axis the amount specified by the angle
57480       * parameter. Angles should be specified in the current angleMode.
57481       * Objects are always sheared around their relative position to the origin
57482       * and positive numbers shear objects in a clockwise direction.
57483       * <br><br>
57484       * Transformations apply to everything that happens after and subsequent
57485       * calls to the function accumulates the effect. For example, calling
57486       * shearX(PI/2) and then shearX(PI/2) is the same as shearX(PI).
57487       * If <a href="#/p5/shearX">shearX()</a> is called within the <a href="#/p5/draw">draw()</a>, the transformation is reset when
57488       * the loop begins again.
57489       * <br><br>
57490       * Technically, <a href="#/p5/shearX">shearX()</a> multiplies the current transformation matrix by a
57491       * rotation matrix. This function can be further controlled by the
57492       * <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a> functions.
57493       *
57494       * @method shearX
57495       * @param  {Number} angle angle of shear specified in radians or degrees,
57496       *                        depending on current angleMode
57497       * @chainable
57498       * @example
57499       * <div>
57500       * <code>
57501       * translate(width / 4, height / 4);
57502       * shearX(PI / 4.0);
57503       * rect(0, 0, 30, 30);
57504       * </code>
57505       * </div>
57506       *
57507       * @alt
57508       * white irregular quadrilateral with black outline at top middle.
57509       *
57510       */
57511
57512
57513      p5.prototype.shearX = function (angle) {
57514        p5._validateParameters('shearX', arguments);
57515
57516        this._renderer.shearX(this._toRadians(angle));
57517
57518        return this;
57519      };
57520      /**
57521       * Shears a shape around the y-axis the amount specified by the angle
57522       * parameter. Angles should be specified in the current angleMode. Objects
57523       * are always sheared around their relative position to the origin and
57524       * positive numbers shear objects in a clockwise direction.
57525       * <br><br>
57526       * Transformations apply to everything that happens after and subsequent
57527       * calls to the function accumulates the effect. For example, calling
57528       * shearY(PI/2) and then shearY(PI/2) is the same as shearY(PI). If
57529       * <a href="#/p5/shearY">shearY()</a> is called within the <a href="#/p5/draw">draw()</a>, the transformation is reset when
57530       * the loop begins again.
57531       * <br><br>
57532       * Technically, <a href="#/p5/shearY">shearY()</a> multiplies the current transformation matrix by a
57533       * rotation matrix. This function can be further controlled by the
57534       * <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a> functions.
57535       *
57536       * @method shearY
57537       * @param  {Number} angle angle of shear specified in radians or degrees,
57538       *                        depending on current angleMode
57539       * @chainable
57540       * @example
57541       * <div>
57542       * <code>
57543       * translate(width / 4, height / 4);
57544       * shearY(PI / 4.0);
57545       * rect(0, 0, 30, 30);
57546       * </code>
57547       * </div>
57548       *
57549       * @alt
57550       * white irregular quadrilateral with black outline at middle bottom.
57551       *
57552       */
57553
57554
57555      p5.prototype.shearY = function (angle) {
57556        p5._validateParameters('shearY', arguments);
57557
57558        this._renderer.shearY(this._toRadians(angle));
57559
57560        return this;
57561      };
57562      /**
57563       * Specifies an amount to displace objects within the display window.
57564       * The x parameter specifies left/right translation, the y parameter
57565       * specifies up/down translation.
57566       * <br><br>
57567       * Transformations are cumulative and apply to everything that happens after
57568       * and subsequent calls to the function accumulates the effect. For example,
57569       * calling translate(50, 0) and then translate(20, 0) is the same as
57570       * translate(70, 0). If <a href="#/p5/translate">translate()</a> is called within <a href="#/p5/draw">draw()</a>, the
57571       * transformation is reset when the loop begins again. This function can be
57572       * further controlled by using <a href="#/p5/push">push()</a> and <a href="#/p5/pop">pop()</a>.
57573       *
57574       * @method translate
57575       * @param  {Number} x left/right translation
57576       * @param  {Number} y up/down translation
57577       * @param  {Number} [z] forward/backward translation (webgl only)
57578       * @chainable
57579       * @example
57580       * <div>
57581       * <code>
57582       * translate(30, 20);
57583       * rect(0, 0, 55, 55);
57584       * </code>
57585       * </div>
57586       *
57587       * <div>
57588       * <code>
57589       * rect(0, 0, 55, 55); // Draw rect at original 0,0
57590       * translate(30, 20);
57591       * rect(0, 0, 55, 55); // Draw rect at new 0,0
57592       * translate(14, 14);
57593       * rect(0, 0, 55, 55); // Draw rect at new 0,0
57594       * </code>
57595       * </div>
57596       *
57597      
57598       * <div>
57599       * <code>
57600       * function draw() {
57601       *   background(200);
57602       *   rectMode(CENTER);
57603       *   translate(width / 2, height / 2);
57604       *   translate(p5.Vector.fromAngle(millis() / 1000, 40));
57605       *   rect(0, 0, 20, 20);
57606       * }
57607       * </code>
57608       * </div>
57609       *
57610       * @alt
57611       * white 55x55 rect with black outline at center right.
57612       * 3 white 55x55 rects with black outlines at top-l, center-r and bottom-r.
57613       * a 20x20 white rect moving in a circle around the canvas
57614       *
57615       */
57616
57617      /**
57618       * @method translate
57619       * @param  {p5.Vector} vector the vector to translate by
57620       * @chainable
57621       */
57622
57623
57624      p5.prototype.translate = function (x, y, z) {
57625        p5._validateParameters('translate', arguments);
57626
57627        if (this._renderer.isP3D) {
57628          this._renderer.translate(x, y, z);
57629        } else {
57630          this._renderer.translate(x, y);
57631        }
57632
57633        return this;
57634      };
57635
57636      module.exports = p5;
57637    }, {
57638      "./main": 24
57639    }],
57640    37: [function (_dereq_, module, exports) {
57641      /**
57642       * @module Data
57643       * @submodule Dictionary
57644       * @for p5.TypedDict
57645       * @requires core
57646       *
57647       * This module defines the p5 methods for the p5 Dictionary classes.
57648       * The classes StringDict and NumberDict are for storing and working
57649       * with key-value pairs.
57650       */
57651      'use strict';
57652
57653      var p5 = _dereq_('../core/main');
57654      /**
57655       *
57656       * Creates a new instance of p5.StringDict using the key-value pair
57657       * or the object you provide.
57658       *
57659       * @method createStringDict
57660       * @for p5
57661       * @param {String} key
57662       * @param {String} value
57663       * @return {p5.StringDict}
57664       *
57665       * @example
57666       * <div class="norender">
57667       * <code>
57668       * function setup() {
57669       *   var myDictionary = createStringDict('p5', 'js');
57670       *   print(myDictionary.hasKey('p5')); // logs true to console
57671       *
57672       *   var anotherDictionary = createStringDict({ happy: 'coding' });
57673       *   print(anotherDictionary.hasKey('happy')); // logs true to console
57674       * }
57675       * </code></div>
57676       */
57677
57678      /**
57679       * @method createStringDict
57680       * @param {Object} object object
57681       * @return {p5.StringDict}
57682       */
57683
57684
57685      p5.prototype.createStringDict = function (key, value) {
57686        p5._validateParameters('createStringDict', arguments);
57687
57688        return new p5.StringDict(key, value);
57689      };
57690      /**
57691       *
57692       * Creates a new instance of <a href="#/p5.NumberDict">p5.NumberDict</a> using the key-value pair
57693       * or object you provide.
57694       *
57695       * @method createNumberDict
57696       * @for p5
57697       * @param {Number} key
57698       * @param {Number} value
57699       * @return {p5.NumberDict}
57700       *
57701       * @example
57702       * <div class="norender">
57703       * <code>
57704       * function setup() {
57705       *   var myDictionary = createNumberDict(100, 42);
57706       *   print(myDictionary.hasKey(100)); // logs true to console
57707       *
57708       *   var anotherDictionary = createNumberDict({ 200: 84 });
57709       *   print(anotherDictionary.hasKey(200)); // logs true to console
57710       * }
57711       * </code></div>
57712       */
57713
57714      /**
57715       * @method createNumberDict
57716       * @param {Object} object object
57717       * @return {p5.NumberDict}
57718       */
57719
57720
57721      p5.prototype.createNumberDict = function (key, value) {
57722        p5._validateParameters('createNumberDict', arguments);
57723
57724        return new p5.NumberDict(key, value);
57725      };
57726      /**
57727       *
57728       * Base class for all p5.Dictionary types. Specifically
57729       * typed Dictionary classes inherit from this class.
57730       *
57731       * @class p5.TypedDict
57732       *
57733       */
57734
57735
57736      p5.TypedDict = function (key, value) {
57737        if (key instanceof Object) {
57738          this.data = key;
57739        } else {
57740          this.data = {};
57741          this.data[key] = value;
57742        }
57743
57744        return this;
57745      };
57746      /**
57747       * Returns the number of key-value pairs currently stored in the Dictionary.
57748       *
57749       * @method size
57750       * @return {Integer} the number of key-value pairs in the Dictionary
57751       *
57752       * @example
57753       * <div class="norender">
57754       * <code>
57755       * function setup() {
57756       *   var myDictionary = createNumberDict(1, 10);
57757       *   myDictionary.create(2, 20);
57758       *   myDictionary.create(3, 30);
57759       *   print(myDictionary.size()); // logs 3 to the console
57760       * }
57761       * </code></div>
57762       *
57763       */
57764
57765
57766      p5.TypedDict.prototype.size = function () {
57767        return Object.keys(this.data).length;
57768      };
57769      /**
57770       * Returns true if the given key exists in the Dictionary,
57771       * otherwise returns false.
57772       *
57773       * @method hasKey
57774       * @param {Number|String} key that you want to look up
57775       * @return {Boolean} whether that key exists in Dictionary
57776       *
57777       * @example
57778       * <div class="norender">
57779       * <code>
57780       * function setup() {
57781       *   var myDictionary = createStringDict('p5', 'js');
57782       *   print(myDictionary.hasKey('p5')); // logs true to console
57783       * }
57784       * </code></div>
57785       *
57786       */
57787
57788
57789      p5.TypedDict.prototype.hasKey = function (key) {
57790        return this.data.hasOwnProperty(key);
57791      };
57792      /**
57793       * Returns the value stored at the given key.
57794       *
57795       * @method get
57796       * @param {Number|String} the key you want to access
57797       * @return {Number|String} the value stored at that key
57798       *
57799       * @example
57800       * <div class="norender">
57801       * <code>
57802       * function setup() {
57803       *   var myDictionary = createStringDict('p5', 'js');
57804       *   var myValue = myDictionary.get('p5');
57805       *   print(myValue === 'js'); // logs true to console
57806       * }
57807       * </code></div>
57808       *
57809       */
57810
57811
57812      p5.TypedDict.prototype.get = function (key) {
57813        if (this.data.hasOwnProperty(key)) {
57814          return this.data[key];
57815        } else {
57816          console.log(key + ' does not exist in this Dictionary');
57817        }
57818      };
57819      /**
57820       * Updates the value associated with the given key in case it already exists
57821       * in the Dictionary. Otherwise a new key-value pair is added.
57822       *
57823       * @method set
57824       * @param {Number|String} key
57825       * @param {Number|String} value
57826       *
57827       * @example
57828       * <div class="norender">
57829       * <code>
57830       * function setup() {
57831       *   var myDictionary = createStringDict('p5', 'js');
57832       *   myDictionary.set('p5', 'JS');
57833       *   myDictionary.print(); // logs "key: p5 - value: JS" to console
57834       * }
57835       * </code></div>
57836       *
57837       */
57838
57839
57840      p5.TypedDict.prototype.set = function (key, value) {
57841        if (this._validate(value)) {
57842          this.data[key] = value;
57843        } else {
57844          console.log('Those values dont work for this dictionary type.');
57845        }
57846      };
57847      /**
57848       * private helper function to handle the user passing in objects
57849       * during construction or calls to create()
57850       */
57851
57852
57853      p5.TypedDict.prototype._addObj = function (obj) {
57854        for (var key in obj) {
57855          this.set(key, obj[key]);
57856        }
57857      };
57858      /**
57859       * Creates a new key-value pair in the Dictionary.
57860       *
57861       * @method create
57862       * @param {Number|String} key
57863       * @param {Number|String} value
57864       *
57865       * @example
57866       * <div class="norender">
57867       * <code>
57868       * function setup() {
57869       *   var myDictionary = createStringDict('p5', 'js');
57870       *   myDictionary.create('happy', 'coding');
57871       *   myDictionary.print();
57872       *   // above logs "key: p5 - value: js, key: happy - value: coding" to console
57873       * }
57874       * </code></div>
57875       */
57876
57877      /**
57878       * @method create
57879       * @param {Object} obj key/value pair
57880       */
57881
57882
57883      p5.TypedDict.prototype.create = function (key, value) {
57884        if (key instanceof Object && typeof value === 'undefined') {
57885          this._addObj(key);
57886        } else if (typeof key !== 'undefined') {
57887          this.set(key, value);
57888        } else {
57889          console.log('In order to create a new Dictionary entry you must pass ' + 'an object or a key, value pair');
57890        }
57891      };
57892      /**
57893       * Removes all previously stored key-value pairs from the Dictionary.
57894       *
57895       * @method clear
57896       * @example
57897       * <div class="norender">
57898       * <code>
57899       * function setup() {
57900       *   var myDictionary = createStringDict('p5', 'js');
57901       *   print(myDictionary.hasKey('p5')); // prints 'true'
57902       *   myDictionary.clear();
57903       *   print(myDictionary.hasKey('p5')); // prints 'false'
57904       * }
57905       * </code>
57906       * </div>
57907       */
57908
57909
57910      p5.TypedDict.prototype.clear = function () {
57911        this.data = {};
57912      };
57913      /**
57914       * Removes the key-value pair stored at the given key from the Dictionary.
57915       *
57916       * @method remove
57917       * @param {Number|String} key for the pair to remove
57918       *
57919       * @example
57920       * <div class="norender">
57921       * <code>
57922       * function setup() {
57923       *   var myDictionary = createStringDict('p5', 'js');
57924       *   myDictionary.create('happy', 'coding');
57925       *   myDictionary.print();
57926       *   // above logs "key: p5 - value: js, key: happy - value: coding" to console
57927       *   myDictionary.remove('p5');
57928       *   myDictionary.print();
57929       *   // above logs "key: happy value: coding" to console
57930       * }
57931       * </code></div>
57932       *
57933       */
57934
57935
57936      p5.TypedDict.prototype.remove = function (key) {
57937        if (this.data.hasOwnProperty(key)) {
57938          delete this.data[key];
57939        } else {
57940          throw new Error(key + ' does not exist in this Dictionary');
57941        }
57942      };
57943      /**
57944       * Logs the set of items currently stored in the Dictionary to the console.
57945       *
57946       * @method print
57947       *
57948       * @example
57949       * <div class="norender">
57950       * <code>
57951       * function setup() {
57952       *   var myDictionary = createStringDict('p5', 'js');
57953       *   myDictionary.create('happy', 'coding');
57954       *   myDictionary.print();
57955       *   // above logs "key: p5 - value: js, key: happy - value: coding" to console
57956       * }
57957       * </code>
57958       * </div>
57959       */
57960
57961
57962      p5.TypedDict.prototype.print = function () {
57963        for (var item in this.data) {
57964          console.log('key:' + item + ' value:' + this.data[item]);
57965        }
57966      };
57967      /**
57968       * Converts the Dictionary into a CSV file for local download.
57969       *
57970       * @method saveTable
57971       * @example
57972       * <div>
57973       * <code>
57974       * function setup() {
57975       *   createCanvas(100, 100);
57976       *   background(200);
57977       *   text('click here to save', 10, 10, 70, 80);
57978       * }
57979       *
57980       * function mousePressed() {
57981       *   if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
57982       *     createStringDict({
57983       *       john: 1940,
57984       *       paul: 1942,
57985       *       george: 1943,
57986       *       ringo: 1940
57987       *     }).saveTable('beatles');
57988       *   }
57989       * }
57990       * </code>
57991       * </div>
57992       */
57993
57994
57995      p5.TypedDict.prototype.saveTable = function (filename) {
57996        var output = '';
57997
57998        for (var key in this.data) {
57999          output += key + ',' + this.data[key] + '\n';
58000        }
58001
58002        var blob = new Blob([output], {
58003          type: 'text/csv'
58004        });
58005        p5.prototype.downloadFile(blob, filename || 'mycsv', 'csv');
58006      };
58007      /**
58008       * Converts the Dictionary into a JSON file for local download.
58009       *
58010       * @method saveJSON
58011       * @example
58012       * <div>
58013       * <code>
58014       * function setup() {
58015       *   createCanvas(100, 100);
58016       *   background(200);
58017       *   text('click here to save', 10, 10, 70, 80);
58018       * }
58019       *
58020       * function mousePressed() {
58021       *   if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
58022       *     createStringDict({
58023       *       john: 1940,
58024       *       paul: 1942,
58025       *       george: 1943,
58026       *       ringo: 1940
58027       *     }).saveJSON('beatles');
58028       *   }
58029       * }
58030       * </code>
58031       * </div>
58032       */
58033
58034
58035      p5.TypedDict.prototype.saveJSON = function (filename, opt) {
58036        p5.prototype.saveJSON(this.data, filename, opt);
58037      };
58038      /**
58039       * private helper function to ensure that the user passed in valid
58040       * values for the Dictionary type
58041       */
58042
58043
58044      p5.TypedDict.prototype._validate = function (value) {
58045        return true;
58046      };
58047      /**
58048       *
58049       * A simple Dictionary class for Strings.
58050       *
58051       * @class p5.StringDict
58052       * @extends p5.TypedDict
58053       *
58054       */
58055
58056
58057      p5.StringDict = function () {
58058        p5.TypedDict.apply(this, arguments);
58059      };
58060
58061      p5.StringDict.prototype = Object.create(p5.TypedDict.prototype);
58062
58063      p5.StringDict.prototype._validate = function (value) {
58064        return typeof value === 'string';
58065      };
58066      /**
58067       *
58068       * A simple Dictionary class for Numbers.
58069       *
58070       * @class p5.NumberDict
58071       * @extends p5.TypedDict
58072       *
58073       */
58074
58075
58076      p5.NumberDict = function () {
58077        p5.TypedDict.apply(this, arguments);
58078      };
58079
58080      p5.NumberDict.prototype = Object.create(p5.TypedDict.prototype);
58081      /**
58082       * private helper function to ensure that the user passed in valid
58083       * values for the Dictionary type
58084       */
58085
58086      p5.NumberDict.prototype._validate = function (value) {
58087        return typeof value === 'number';
58088      };
58089      /**
58090       * Add the given number to the value currently stored at the given key.
58091       * The sum then replaces the value previously stored in the Dictionary.
58092       *
58093       * @method add
58094       * @param {Number} Key for the value you wish to add to
58095       * @param {Number} Number to add to the value
58096       * @example
58097       * <div class='norender'>
58098       * <code>
58099       * function setup() {
58100       *   var myDictionary = createNumberDict(2, 5);
58101       *   myDictionary.add(2, 2);
58102       *   print(myDictionary.get(2)); // logs 7 to console.
58103       * }
58104       * </code></div>
58105       *
58106       *
58107       */
58108
58109
58110      p5.NumberDict.prototype.add = function (key, amount) {
58111        if (this.data.hasOwnProperty(key)) {
58112          this.data[key] += amount;
58113        } else {
58114          console.log('The key - ' + key + ' does not exist in this dictionary.');
58115        }
58116      };
58117      /**
58118       * Subtract the given number from the value currently stored at the given key.
58119       * The difference then replaces the value previously stored in the Dictionary.
58120       *
58121       * @method sub
58122       * @param {Number}
58122 Key for the value you wish to subtract from
58123       * @param {Number} Number to subtract from the value
58124       * @example
58125       * <div class='norender'>
58126       * <code>
58127       * function setup() {
58128       *   var myDictionary = createNumberDict(2, 5);
58129       *   myDictionary.sub(2, 2);
58130       *   print(myDictionary.get(2)); // logs 3 to console.
58131       * }
58132       * </code></div>
58133       *
58134       *
58135       */
58136
58137
58138      p5.NumberDict.prototype.sub = function (key, amount) {
58139        this.add(key, -amount);
58140      };
58141      /**
58142       * Multiply the given number with the value currently stored at the given key.
58143       * The product then replaces the value previously stored in the Dictionary.
58144       *
58145       * @method mult
58146       * @param {Number} Key for value you wish to multiply
58147       * @param {Number} Amount to multiply the value by
58148       * @example
58149       * <div class='norender'>
58150       * <code>
58151       * function setup() {
58152       *   var myDictionary = createNumberDict(2, 4);
58153       *   myDictionary.mult(2, 2);
58154       *   print(myDictionary.get(2)); // logs 8 to console.
58155       * }
58156       * </code></div>
58157       *
58158       *
58159       */
58160
58161
58162      p5.NumberDict.prototype.mult = function (key, amount) {
58163        if (this.data.hasOwnProperty(key)) {
58164          this.data[key] *= amount;
58165        } else {
58166          console.log('The key - ' + key + ' does not exist in this dictionary.');
58167        }
58168      };
58169      /**
58170       * Divide the given number with the value currently stored at the given key.
58171       * The quotient then replaces the value previously stored in the Dictionary.
58172       *
58173       * @method div
58174       * @param {Number} Key for value you wish to divide
58175       * @param {Number} Amount to divide the value by
58176       * @example
58177       * <div class='norender'>
58178       * <code>
58179       * function setup() {
58180       *   var myDictionary = createNumberDict(2, 8);
58181       *   myDictionary.div(2, 2);
58182       *   print(myDictionary.get(2)); // logs 4 to console.
58183       * }
58184       * </code></div>
58185       *
58186       *
58187       */
58188
58189
58190      p5.NumberDict.prototype.div = function (key, amount) {
58191        if (this.data.hasOwnProperty(key)) {
58192          this.data[key] /= amount;
58193        } else {
58194          console.log('The key - ' + key + ' does not exist in this dictionary.');
58195        }
58196      };
58197      /**
58198       * private helper function for finding lowest or highest value
58199       * the argument 'flip' is used to flip the comparison arrow
58200       * from 'less than' to 'greater than'
58201       *
58202       */
58203
58204
58205      p5.NumberDict.prototype._valueTest = function (flip) {
58206        if (Object.keys(this.data).length === 0) {
58207          throw new Error('Unable to search for a minimum or maximum value on an empty NumberDict');
58208        } else if (Object.keys(this.data).length === 1) {
58209          return this.data[Object.keys(this.data)[0]];
58210        } else {
58211          var result = this.data[Object.keys(this.data)[0]];
58212
58213          for (var key in this.data) {
58214            if (this.data[key] * flip < result * flip) {
58215              result = this.data[key];
58216            }
58217          }
58218
58219          return result;
58220        }
58221      };
58222      /**
58223       * Return the lowest number currently stored in the Dictionary.
58224       *
58225       * @method minValue
58226       * @return {Number}
58227       * @example
58228       * <div class='norender'>
58229       * <code>
58230       * function setup() {
58231       *   var myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 });
58232       *   var lowestValue = myDictionary.minValue(); // value is -10
58233       *   print(lowestValue);
58234       * }
58235       * </code></div>
58236       *
58237       */
58238
58239
58240      p5.NumberDict.prototype.minValue = function () {
58241        return this._valueTest(1);
58242      };
58243      /**
58244       * Return the highest number currently stored in the Dictionary.
58245       *
58246       * @method maxValue
58247       * @return {Number}
58248       * @example
58249       * <div class='norender'>
58250       * <code>
58251       * function setup() {
58252       *   var myDictionary = createNumberDict({ 2: -10, 4: 0.65, 1.2: 3 });
58253       *   var highestValue = myDictionary.maxValue(); // value is 3
58254       *   print(highestValue);
58255       * }
58256       * </code></div>
58257       *
58258       */
58259
58260
58261      p5.NumberDict.prototype.maxValue = function () {
58262        return this._valueTest(-1);
58263      };
58264      /**
58265       * private helper function for finding lowest or highest key
58266       * the argument 'flip' is used to flip the comparison arrow
58267       * from 'less than' to 'greater than'
58268       *
58269       */
58270
58271
58272      p5.NumberDict.prototype._keyTest = function (flip) {
58273        if (Object.keys(this.data).length === 0) {
58274          throw new Error('Unable to use minValue on an empty NumberDict');
58275        } else if (Object.keys(this.data).length === 1) {
58276          return Object.keys(this.data)[0];
58277        } else {
58278          var result = Object.keys(this.data)[0];
58279
58280          for (var i = 1; i < Object.keys(this.data).length; i++) {
58281            if (Object.keys(this.data)[i] * flip < result * flip) {
58282              result = Object.keys(this.data)[i];
58283            }
58284          }
58285
58286          return result;
58287        }
58288      };
58289      /**
58290       * Return the lowest key currently used in the Dictionary.
58291       *
58292       * @method minKey
58293       * @return {Number}
58294       * @example
58295       * <div class='norender'>
58296       * <code>
58297       * function setup() {
58298       *   var myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 });
58299       *   var lowestKey = myDictionary.minKey(); // value is 1.2
58300       *   print(lowestKey);
58301       * }
58302       * </code></div>
58303       *
58304       */
58305
58306
58307      p5.NumberDict.prototype.minKey = function () {
58308        return this._keyTest(1);
58309      };
58310      /**
58311       * Return the highest key currently used in the Dictionary.
58312       *
58313       * @method maxKey
58314       * @return {Number}
58315       * @example
58316       * <div class='norender'>
58317       * <code>
58318       * function setup() {
58319       *   var myDictionary = createNumberDict({ 2: 4, 4: 6, 1.2: 3 });
58320       *   var highestKey = myDictionary.maxKey(); // value is 4
58321       *   print(highestKey);
58322       * }
58323       * </code></div>
58324       *
58325       */
58326
58327
58328      p5.NumberDict.prototype.maxKey = function () {
58329        return this._keyTest(-1);
58330      };
58331
58332      module.exports = p5.TypedDict;
58333    }, {
58334      "../core/main": 24
58335    }],
58336    38: [function (_dereq_, module, exports) {
58337      /**
58338       * @module Events
58339       * @submodule Acceleration
58340       * @for p5
58341       * @requires core
58342       */
58343      'use strict';
58344
58345      var p5 = _dereq_('../core/main');
58346      /**
58347       * The system variable deviceOrientation always contains the orientation of
58348       * the device. The value of this variable will either be set 'landscape'
58349       * or 'portrait'. If no data is available it will be set to 'undefined'.
58350       * either LANDSCAPE or PORTRAIT.
58351       *
58352       * @property {Constant} deviceOrientation
58353       * @readOnly
58354       */
58355
58356
58357      p5.prototype.deviceOrientation = undefined;
58358      /**
58359       * The system variable accelerationX always contains the acceleration of the
58360       * device along the x axis. Value is represented as meters per second squared.
58361       *
58362       * @property {Number} accelerationX
58363       * @readOnly
58364       * @example
58365       * <div>
58366       * <code>
58367       * // Move a touchscreen device to register
58368       * // acceleration changes.
58369       * function draw() {
58370       *   background(220, 50);
58371       *   fill('magenta');
58372       *   ellipse(width / 2, height / 2, accelerationX);
58373       * }
58374       * </code>
58375       * </div>
58376       * @alt
58377       * Magnitude of device acceleration is displayed as ellipse size
58378       */
58379
58380      p5.prototype.accelerationX = 0;
58381      /**
58382       * The system variable accelerationY always contains the acceleration of the
58383       * device along the y axis. Value is represented as meters per second squared.
58384       *
58385       * @property {Number} accelerationY
58386       * @readOnly
58387       * @example
58388       * <div>
58389       * <code>
58390       * // Move a touchscreen device to register
58391       * // acceleration changes.
58392       * function draw() {
58393       *   background(220, 50);
58394       *   fill('magenta');
58395       *   ellipse(width / 2, height / 2, accelerationY);
58396       * }
58397       * </code>
58398       * </div>
58399       * @alt
58400       * Magnitude of device acceleration is displayed as ellipse size
58401       */
58402
58403      p5.prototype.accelerationY = 0;
58404      /**
58405       * The system variable accelerationZ always contains the acceleration of the
58406       * device along the z axis. Value is represented as meters per second squared.
58407       *
58408       * @property {Number} accelerationZ
58409       * @readOnly
58410       *
58411       * @example
58412       * <div>
58413       * <code>
58414       * // Move a touchscreen device to register
58415       * // acceleration changes.
58416       * function draw() {
58417       *   background(220, 50);
58418       *   fill('magenta');
58419       *   ellipse(width / 2, height / 2, accelerationZ);
58420       * }
58421       * </code>
58422       * </div>
58423       *
58424       * @alt
58425       * Magnitude of device acceleration is displayed as ellipse size
58426       */
58427
58428      p5.prototype.accelerationZ = 0;
58429      /**
58430       * The system variable pAccelerationX always contains the acceleration of the
58431       * device along the x axis in the frame previous to the current frame. Value
58432       * is represented as meters per second squared.
58433       *
58434       * @property {Number} pAccelerationX
58435       * @readOnly
58436       */
58437
58438      p5.prototype.pAccelerationX = 0;
58439      /**
58440       * The system variable pAccelerationY always contains the acceleration of the
58441       * device along the y axis in the frame previous to the current frame. Value
58442       * is represented as meters per second squared.
58443       *
58444       * @property {Number} pAccelerationY
58445       * @readOnly
58446       */
58447
58448      p5.prototype.pAccelerationY = 0;
58449      /**
58450       * The system variable pAccelerationZ always contains the acceleration of the
58451       * device along the z axis in the frame previous to the current frame. Value
58452       * is represented as meters per second squared.
58453       *
58454       * @property {Number} pAccelerationZ
58455       * @readOnly
58456       */
58457
58458      p5.prototype.pAccelerationZ = 0;
58459      /**
58460       * _updatePAccelerations updates the pAcceleration values
58461       *
58462       * @private
58463       */
58464
58465      p5.prototype._updatePAccelerations = function () {
58466        this._setProperty('pAccelerationX', this.accelerationX);
58467
58468        this._setProperty('pAccelerationY', this.accelerationY);
58469
58470        this._setProperty('pAccelerationZ', this.accelerationZ);
58471      };
58472      /**
58473       * The system variable rotationX always contains the rotation of the
58474       * device along the x axis. Value is represented as 0 to +/-180 degrees.
58475       * <br><br>
58476       * Note: The order the rotations are called is important, ie. if used
58477       * together, it must be called in the order Z-X-Y or there might be
58478       * unexpected behaviour.
58479       *
58480       * @property {Number} rotationX
58481       * @readOnly
58482       * @example
58483       * <div>
58484       * <code>
58485       * function setup() {
58486       *   createCanvas(100, 100, WEBGL);
58487       * }
58488       *
58489       * function draw() {
58490       *   background(200);
58491       *   //rotateZ(radians(rotationZ));
58492       *   rotateX(radians(rotationX));
58493       *   //rotateY(radians(rotationY));
58494       *   box(200, 200, 200);
58495       * }
58496       * </code>
58497       * </div>
58498       * @alt
58499       * red horizontal line right, green vertical line bottom. black background.
58500       */
58501
58502
58503      p5.prototype.rotationX = 0;
58504      /**
58505       * The system variable rotationY always contains the rotation of the
58506       * device along the y axis. Value is represented as 0 to +/-90 degrees.
58507       * <br><br>
58508       * Note: The order the rotations are called is important, ie. if used
58509       * together, it must be called in the order Z-X-Y or there might be
58510       * unexpected behaviour.
58511       *
58512       * @property {Number} rotationY
58513       * @readOnly
58514       * @example
58515       * <div>
58516       * <code>
58517       * function setup() {
58518       *   createCanvas(100, 100, WEBGL);
58519       * }
58520       *
58521       * function draw() {
58522       *   background(200);
58523       *   //rotateZ(radians(rotationZ));
58524       *   //rotateX(radians(rotationX));
58525       *   rotateY(radians(rotationY));
58526       *   box(200, 200, 200);
58527       * }
58528       * </code>
58529       * </div>
58530       * @alt
58531       * red horizontal line right, green vertical line bottom. black background.
58532       */
58533
58534      p5.prototype.rotationY = 0;
58535      /**
58536       * The system variable rotationZ always contains the rotation of the
58537       * device along the z axis. Value is represented as 0 to 359 degrees.
58538       * <br><br>
58539       * Unlike rotationX and rotationY, this variable is available for devices
58540       * with a built-in compass only.
58541       * <br><br>
58542       * Note: The order the rotations are called is important, ie. if used
58543       * together, it must be called in the order Z-X-Y or there might be
58544       * unexpected behaviour.
58545       *
58546       * @example
58547       * <div>
58548       * <code>
58549       * function setup() {
58550       *   createCanvas(100, 100, WEBGL);
58551       * }
58552       *
58553       * function draw() {
58554       *   background(200);
58555       *   rotateZ(radians(rotationZ));
58556       *   //rotateX(radians(rotationX));
58557       *   //rotateY(radians(rotationY));
58558       *   box(200, 200, 200);
58559       * }
58560       * </code>
58561       * </div>
58562       *
58563       * @property {Number} rotationZ
58564       * @readOnly
58565       *
58566       * @alt
58567       * red horizontal line right, green vertical line bottom. black background.
58568       */
58569
58570      p5.prototype.rotationZ = 0;
58571      /**
58572       * The system variable pRotationX always contains the rotation of the
58573       * device along the x axis in the frame previous to the current frame. Value
58574       * is represented as 0 to +/-180 degrees.
58575       * <br><br>
58576       * pRotationX can also be used with rotationX to determine the rotate
58577       * direction of the device along the X-axis.
58578       * @example
58579       * <div class='norender'>
58580       * <code>
58581       * // A simple if statement looking at whether
58582       * // rotationX - pRotationX < 0 is true or not will be
58583       * // sufficient for determining the rotate direction
58584       * // in most cases.
58585       *
58586       * // Some extra logic is needed to account for cases where
58587       * // the angles wrap around.
58588       * let rotateDirection = 'clockwise';
58589       *
58590       * // Simple range conversion to make things simpler.
58591       * // This is not absolutely necessary but the logic
58592       * // will be different in that case.
58593       *
58594       * let rX = rotationX + 180;
58595       * let pRX = pRotationX + 180;
58596       *
58597       * if ((rX - pRX > 0 && rX - pRX < 270) || rX - pRX < -270) {
58598       *   rotateDirection = 'clockwise';
58599       * } else if (rX - pRX < 0 || rX - pRX > 270) {
58600       *   rotateDirection = 'counter-clockwise';
58601       * }
58602       *
58603       * print(rotateDirection);
58604       * </code>
58605       * </div>
58606       *
58607       * @alt
58608       * no image to display.
58609       *
58610       *
58611       * @property {Number} pRotationX
58612       * @readOnly
58613       */
58614
58615      p5.prototype.pRotationX = 0;
58616      /**
58617       * The system variable pRotationY always contains the rotation of the
58618       * device along the y axis in the frame previous to the current frame. Value
58619       * is represented as 0 to +/-90 degrees.
58620       * <br><br>
58621       * pRotationY can also be used with rotationY to determine the rotate
58622       * direction of the device along the Y-axis.
58623       * @example
58624       * <div class='norender'>
58625       * <code>
58626       * // A simple if statement looking at whether
58627       * // rotationY - pRotationY < 0 is true or not will be
58628       * // sufficient for determining the rotate direction
58629       * // in most cases.
58630       *
58631       * // Some extra logic is needed to account for cases where
58632       * // the angles wrap around.
58633       * let rotateDirection = 'clockwise';
58634       *
58635       * // Simple range conversion to make things simpler.
58636       * // This is not absolutely necessary but the logic
58637       * // will be different in that case.
58638       *
58639       * let rY = rotationY + 180;
58640       * let pRY = pRotationY + 180;
58641       *
58642       * if ((rY - pRY > 0 && rY - pRY < 270) || rY - pRY < -270) {
58643       *   rotateDirection = 'clockwise';
58644       * } else if (rY - pRY < 0 || rY - pRY > 270) {
58645       *   rotateDirection = 'counter-clockwise';
58646       * }
58647       * print(rotateDirection);
58648       * </code>
58649       * </div>
58650       *
58651       * @alt
58652       * no image to display.
58653       *
58654       *
58655       * @property {Number} pRotationY
58656       * @readOnly
58657       */
58658
58659      p5.prototype.pRotationY = 0;
58660      /**
58661       * The system variable pRotationZ always contains the rotation of the
58662       * device along the z axis in the frame previous to the current frame. Value
58663       * is represented as 0 to 359 degrees.
58664       * <br><br>
58665       * pRotationZ can also be used with rotationZ to determine the rotate
58666       * direction of the device along the Z-axis.
58667       * @example
58668       * <div class='norender'>
58669       * <code>
58670       * // A simple if statement looking at whether
58671       * // rotationZ - pRotationZ < 0 is true or not will be
58672       * // sufficient for determining the rotate direction
58673       * // in most cases.
58674       *
58675       * // Some extra logic is needed to account for cases where
58676       * // the angles wrap around.
58677       * let rotateDirection = 'clockwise';
58678       *
58679       * if (
58680       *   (rotationZ - pRotationZ > 0 && rotationZ - pRotationZ < 270) ||
58681       *   rotationZ - pRotationZ < -270
58682       * ) {
58683       *   rotateDirection = 'clockwise';
58684       * } else if (rotationZ - pRotationZ < 0 || rotationZ - pRotationZ > 270) {
58685       *   rotateDirection = 'counter-clockwise';
58686       * }
58687       * print(rotateDirection);
58688       * </code>
58689       * </div>
58690       *
58691       * @alt
58692       * no image to display.
58693       *
58694       *
58695       * @property {Number} pRotationZ
58696       * @readOnly
58697       */
58698
58699      p5.prototype.pRotationZ = 0;
58700      var startAngleX = 0;
58701      var startAngleY = 0;
58702      var startAngleZ = 0;
58703      var rotateDirectionX = 'clockwise';
58704      var rotateDirectionY = 'clockwise';
58705      var rotateDirectionZ = 'clockwise';
58706      var pRotateDirectionX;
58707      var pRotateDirectionY;
58708      var pRotateDirectionZ;
58709
58710      p5.prototype._updatePRotations = function () {
58711        this._setProperty('pRotationX', this.rotationX);
58712
58713        this._setProperty('pRotationY', this.rotationY);
58714
58715        this._setProperty('pRotationZ', this.rotationZ);
58716      };
58717      /**
58718       * When a device is rotated, the axis that triggers the <a href="#/p5/deviceTurned">deviceTurned()</a>
58719       * method is stored in the turnAxis variable. The turnAxis variable is only defined within
58720       * the scope of deviceTurned().
58721       * @property {String} turnAxis
58722       * @readOnly
58723       * @example
58724       * <div>
58725       * <code>
58726       * // Run this example on a mobile device
58727       * // Rotate the device by 90 degrees in the
58728       * // X-axis to change the value.
58729       *
58730       * var value = 0;
58731       * function draw() {
58732       *   fill(value);
58733       *   rect(25, 25, 50, 50);
58734       * }
58735       * function deviceTurned() {
58736       *   if (turnAxis === 'X') {
58737       *     if (value === 0) {
58738       *       value = 255;
58739       *     }
58739 else if (value === 255) {
58740       *       value = 0;
58741       *     }
58742       *   }
58743       * }
58744       * </code>
58745       * </div>
58746       *
58747       * @alt
58748       * 50x50 black rect in center of canvas. turns white on mobile when device turns
58749       * 50x50 black rect in center of canvas. turns white on mobile when x-axis turns
58750       */
58751
58752
58753      p5.prototype.turnAxis = undefined;
58754      var move_threshold = 0.5;
58755      var shake_threshold = 30;
58756      /**
58757       * The <a href="#/p5/setMoveThreshold">setMoveThreshold()</a> function is used to set the movement threshold for
58758       * the <a href="#/p5/deviceMoved">deviceMoved()</a> function. The default threshold is set to 0.5.
58759       *
58760       * @method setMoveThreshold
58761       * @param {number} value The threshold value
58762       * @example
58763       * <div class="norender">
58764       * <code>
58765       * // Run this example on a mobile device
58766       * // You will need to move the device incrementally further
58767       * // the closer the square's color gets to white in order to change the value.
58768       *
58769       * let value = 0;
58770       * let threshold = 0.5;
58771       * function setup() {
58772       *   setMoveThreshold(threshold);
58773       * }
58774       * function draw() {
58775       *   fill(value);
58776       *   rect(25, 25, 50, 50);
58777       * }
58778       * function deviceMoved() {
58779       *   value = value + 5;
58780       *   threshold = threshold + 0.1;
58781       *   if (value > 255) {
58782       *     value = 0;
58783       *     threshold = 30;
58784       *   }
58785       *   setMoveThreshold(threshold);
58786       * }
58787       * </code>
58788       * </div>
58789       *
58790       * @alt
58791       * 50x50 black rect in center of canvas. turns white on mobile when device moves
58792       */
58793
58794      p5.prototype.setMoveThreshold = function (val) {
58795        p5._validateParameters('setMoveThreshold', arguments);
58796
58797        move_threshold = val;
58798      };
58799      /**
58800       * The <a href="#/p5/setShakeThreshold">setShakeThreshold()</a> function is used to set the movement threshold for
58801       * the <a href="#/p5/deviceShaken">deviceShaken()</a> function. The default threshold is set to 30.
58802       *
58803       * @method setShakeThreshold
58804       * @param {number} value The threshold value
58805       * @example
58806       * <div class="norender">
58807       * <code>
58808       * // Run this example on a mobile device
58809       * // You will need to shake the device more firmly
58810       * // the closer the box's fill gets to white in order to change the value.
58811       *
58812       * let value = 0;
58813       * let threshold = 30;
58814       * function setup() {
58815       *   setShakeThreshold(threshold);
58816       * }
58817       * function draw() {
58818       *   fill(value);
58819       *   rect(25, 25, 50, 50);
58820       * }
58821       * function deviceMoved() {
58822       *   value = value + 5;
58823       *   threshold = threshold + 5;
58824       *   if (value > 255) {
58825       *     value = 0;
58826       *     threshold = 30;
58827       *   }
58828       *   setShakeThreshold(threshold);
58829       * }
58830       * </code>
58831       * </div>
58832       *
58833       * @alt
58834       * 50x50 black rect in center of canvas. turns white on mobile when device
58835       * is being shaked
58836       */
58837
58838
58839      p5.prototype.setShakeThreshold = function (val) {
58840        p5._validateParameters('setShakeThreshold', arguments);
58841
58842        shake_threshold = val;
58843      };
58844      /**
58845       * The <a href="#/p5/deviceMoved">deviceMoved()</a> function is called when the device is moved by more than
58846       * the threshold value along X, Y or Z axis. The default threshold is set to 0.5.
58847       * The threshold value can be changed using <a href="https://p5js.org/reference/#/p5/setMoveThreshold">setMoveThreshold()</a>.
58848       *
58849       * @method deviceMoved
58850       * @example
58851       * <div class="norender">
58852       * <code>
58853       * // Run this example on a mobile device
58854       * // Move the device around
58855       * // to change the value.
58856       *
58857       * let value = 0;
58858       * function draw() {
58859       *   fill(value);
58860       *   rect(25, 25, 50, 50);
58861       * }
58862       * function deviceMoved() {
58863       *   value = value + 5;
58864       *   if (value > 255) {
58865       *     value = 0;
58866       *   }
58867       * }
58868       * </code>
58869       * </div>
58870       *
58871       * @alt
58872       * 50x50 black rect in center of canvas. turns white on mobile when device moves
58873       *
58874       */
58875
58876      /**
58877       * The <a href="#/p5/deviceTurned">deviceTurned()</a> function is called when the device rotates by
58878       * more than 90 degrees continuously.
58879       * <br><br>
58880       * The axis that triggers the <a href="#/p5/deviceTurned">deviceTurned()</a> method is stored in the turnAxis
58881       * variable. The <a href="#/p5/deviceTurned">deviceTurned()</a> method can be locked to trigger on any axis:
58882       * X, Y or Z by comparing the turnAxis variable to 'X', 'Y' or 'Z'.
58883       *
58884       * @method deviceTurned
58885       * @example
58886       * <div class="norender">
58887       * <code>
58888       * // Run this example on a mobile device
58889       * // Rotate the device by 90 degrees
58890       * // to change the value.
58891       *
58892       * let value = 0;
58893       * function draw() {
58894       *   fill(value);
58895       *   rect(25, 25, 50, 50);
58896       * }
58897       * function deviceTurned() {
58898       *   if (value === 0) {
58899       *     value = 255;
58900       *   }
58900 else if (value === 255) {
58901       *     value = 0;
58902       *   }
58903       * }
58904       * </code>
58905       * </div>
58906       * <div>
58907       * <code>
58908       * // Run this example on a mobile device
58909       * // Rotate the device by 90 degrees in the
58910       * // X-axis to change the value.
58911       *
58912       * let value = 0;
58913       * function draw() {
58914       *   fill(value);
58915       *   rect(25, 25, 50, 50);
58916       * }
58917       * function deviceTurned() {
58918       *   if (turnAxis === 'X') {
58919       *     if (value === 0) {
58920       *       value = 255;
58921       *     } else if (value === 255) {
58922       *       value = 0;
58923       *     }
58924       *   }
58925       * }
58926       * </code>
58927       * </div>
58928       *
58929       * @alt
58930       * 50x50 black rect in center of canvas. turns white on mobile when device turns
58931       * 50x50 black rect in center of canvas. turns white on mobile when x-axis turns
58932       *
58933       */
58934
58935      /**
58936       * The <a href="#/p5/deviceShaken">deviceShaken()</a> function is called when the device total acceleration
58937       * changes of accelerationX and accelerationY values is more than
58938       * the threshold value. The default threshold is set to 30.
58939       * The threshold value can be changed using <a href="https://p5js.org/reference/#/p5/setShakeThreshold">setShakeThreshold()</a>.
58940       *
58941       * @method deviceShaken
58942       * @example
58943       * <div class="norender">
58944       * <code>
58945       * // Run this example on a mobile device
58946       * // Shake the device to change the value.
58947       *
58948       * let value = 0;
58949       * function draw() {
58950       *   fill(value);
58951       *   rect(25, 25, 50, 50);
58952       * }
58953       * function deviceShaken() {
58954       *   value = value + 5;
58955       *   if (value > 255) {
58956       *     value = 0;
58957       *   }
58958       * }
58959       * </code>
58960       * </div>
58961       *
58962       * @alt
58963       * 50x50 black rect in center of canvas. turns white on mobile when device shakes
58964       *
58965       */
58966
58967
58968      p5.prototype._ondeviceorientation = function (e) {
58969        this._updatePRotations();
58970
58971        this._setProperty('rotationX', e.beta);
58972
58973        this._setProperty('rotationY', e.gamma);
58974
58975        this._setProperty('rotationZ', e.alpha);
58976
58977        this._handleMotion();
58978      };
58979
58980      p5.prototype._ondevicemotion = function (e) {
58981        this._updatePAccelerations();
58982
58983        this._setProperty('accelerationX', e.acceleration.x * 2);
58984
58985        this._setProperty('accelerationY', e.acceleration.y * 2);
58986
58987        this._setProperty('accelerationZ', e.acceleration.z * 2);
58988
58989        this._handleMotion();
58990      };
58991
58992      p5.prototype._handleMotion = function () {
58993        if (window.orientation === 90 || window.orientation === -90) {
58994          this._setProperty('deviceOrientation', 'landscape');
58995        } else if (window.orientation === 0) {
58996          this._setProperty('deviceOrientation', 'portrait');
58997        } else if (window.orientation === undefined) {
58998          this._setProperty('deviceOrientation', 'undefined');
58999        }
59000
59001        var deviceMoved = this.deviceMoved || window.deviceMoved;
59002
59003        if (typeof deviceMoved === 'function') {
59004          if (Math.abs(this.accelerationX - this.pAccelerationX) > move_threshold || Math.abs(this.accelerationY - this.pAccelerationY) > move_threshold || Math.abs(this.accelerationZ - this.pAccelerationZ) > move_threshold) {
59005            deviceMoved();
59006          }
59007        }
59008
59009        var deviceTurned = this.deviceTurned || window.deviceTurned;
59010
59011        if (typeof deviceTurned === 'function') {
59012          // The angles given by rotationX etc is from range -180 to 180.
59013          // The following will convert them to 0 to 360 for ease of calculation
59014          // of cases when the angles wrapped around.
59015          // _startAngleX will be converted back at the end and updated.
59016          var wRX = this.rotationX + 180;
59017          var wPRX = this.pRotationX + 180;
59018          var wSAX = startAngleX + 180;
59019
59020          if (wRX - wPRX > 0 && wRX - wPRX < 270 || wRX - wPRX < -270) {
59021            rotateDirectionX = 'clockwise';
59022          } else if (wRX - wPRX < 0 || wRX - wPRX > 270) {
59023            rotateDirectionX = 'counter-clockwise';
59024          }
59025
59026          if (rotateDirectionX !== pRotateDirectionX) {
59027            wSAX = wRX;
59028          }
59029
59030          if (Math.abs(wRX - wSAX) > 90 && Math.abs(wRX - wSAX) < 270) {
59031            wSAX = wRX;
59032
59033            this._setProperty('turnAxis', 'X');
59034
59035            deviceTurned();
59036          }
59037
59038          pRotateDirectionX = rotateDirectionX;
59039          startAngleX = wSAX - 180; // Y-axis is identical to X-axis except for changing some names.
59040
59041          var wRY = this.rotationY + 180;
59042          var wPRY = this.pRotationY + 180;
59043          var wSAY = startAngleY + 180;
59044
59045          if (wRY - wPRY > 0 && wRY - wPRY < 270 || wRY - wPRY < -270) {
59046            rotateDirectionY = 'clockwise';
59047          } else if (wRY - wPRY < 0 || wRY - this.pRotationY > 270) {
59048            rotateDirectionY = 'counter-clockwise';
59049          }
59050
59051          if (rotateDirectionY !== pRotateDirectionY) {
59052            wSAY = wRY;
59053          }
59054
59055          if (Math.abs(wRY - wSAY) > 90 && Math.abs(wRY - wSAY) < 270) {
59056            wSAY = wRY;
59057
59058            this._setProperty('turnAxis', 'Y');
59059
59060            deviceTurned();
59061          }
59062
59063          pRotateDirectionY = rotateDirectionY;
59064          startAngleY = wSAY - 180; // Z-axis is already in the range 0 to 360
59065          // so no conversion is needed.
59066
59067          if (this.rotationZ - this.pRotationZ > 0 && this.rotationZ - this.pRotationZ < 270 || this.rotationZ - this.pRotationZ < -270) {
59068            rotateDirectionZ = 'clockwise';
59069          } else if (this.rotationZ - this.pRotationZ < 0 || this.rotationZ - this.pRotationZ > 270) {
59070            rotateDirectionZ = 'counter-clockwise';
59071          }
59072
59073          if (rotateDirectionZ !== pRotateDirectionZ) {
59074            startAngleZ = this.rotationZ;
59075          }
59076
59077          if (Math.abs(this.rotationZ - startAngleZ) > 90 && Math.abs(this.rotationZ - startAngleZ) < 270) {
59078            startAngleZ = this.rotationZ;
59079
59080            this._setProperty('turnAxis', 'Z');
59081
59082            deviceTurned();
59083          }
59084
59085          pRotateDirectionZ = rotateDirectionZ;
59086
59087          this._setProperty('turnAxis', undefined);
59088        }
59089
59090        var deviceShaken = this.deviceShaken || window.deviceShaken;
59091
59092        if (typeof deviceShaken === 'function') {
59093          var accelerationChangeX;
59094          var accelerationChangeY; // Add accelerationChangeZ if acceleration change on Z is needed
59095
59096          if (this.pAccelerationX !== null) {
59097            accelerationChangeX = Math.abs(this.accelerationX - this.pAccelerationX);
59098            accelerationChangeY = Math.abs(this.accelerationY - this.pAccelerationY);
59099          }
59100
59101          if (accelerationChangeX + accelerationChangeY > shake_threshold) {
59102            deviceShaken();
59103          }
59104        }
59105      };
59106
59107      module.exports = p5;
59108    }, {
59109      "../core/main": 24
59110    }],
59111    39: [function (_dereq_, module, exports) {
59112      /**
59113       * @module Events
59114       * @submodule Keyboard
59115       * @for p5
59116       * @requires core
59117       */
59118      'use strict';
59119
59120      var p5 = _dereq_('../core/main');
59121      /**
59122       * Holds the key codes of currently pressed keys.
59123       * @private
59124       */
59125
59126
59127      var downKeys = {};
59128      /**
59129       * The boolean system variable <a href="#/p5/keyIsPressed">keyIsPressed</a> is true if any key is pressed
59130       * and false if no keys are pressed.
59131       *
59132       * @property {Boolean} keyIsPressed
59133       * @readOnly
59134       * @example
59135       * <div>
59136       * <code>
59137       * function draw() {
59138       *   if (keyIsPressed === true) {
59139       *     fill(0);
59140       *   } else {
59141       *     fill(255);
59142       *   }
59143       *   rect(25, 25, 50, 50);
59144       * }
59145       * </code>
59146       * </div>
59147       *
59148       * @alt
59149       * 50x50 white rect that turns black on keypress.
59150       *
59151       */
59152
59153      p5.prototype.isKeyPressed = false;
59154      p5.prototype.keyIsPressed = false; // khan
59155
59156      /**
59157       * The system variable key always contains the value of the most recent
59158       * key on the keyboard that was typed. To get the proper capitalization, it
59159       * is best to use it within <a href="#/p5/keyTyped">keyTyped()</a>. For non-ASCII keys, use the <a href="#/p5/keyCode">keyCode</a>
59160       * variable.
59161       *
59162       * @property {String} key
59163       * @readOnly
59164       * @example
59165       * <div><code>
59166       * // Click any key to display it!
59167       * // (Not Guaranteed to be Case Sensitive)
59168       * function setup() {
59169       *   fill(245, 123, 158);
59170       *   textSize(50);
59171       * }
59172       *
59173       * function draw() {
59174       *   background(200);
59175       *   text(key, 33, 65); // Display last key pressed.
59176       * }
59177       * </code></div>
59178       *
59179       * @alt
59180       * canvas displays any key value that is pressed in pink font.
59181       *
59182       */
59183
59184      p5.prototype.key = '';
59185      /**
59186       * The variable keyCode is used to detect special keys such as BACKSPACE,
59187       * DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW,
59188       * DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.
59189       * You can also check for custom keys by looking up the keyCode of any key
59190       * on a site like this: <a href="http://keycode.info/">keycode.info</a>.
59191       *
59192       * @property {Integer} keyCode
59193       * @readOnly
59194       * @example
59195       * <div><code>
59196       * let fillVal = 126;
59197       * function draw() {
59198       *   fill(fillVal);
59199       *   rect(25, 25, 50, 50);
59200       * }
59201       *
59202       * function keyPressed() {
59203       *   if (keyCode === UP_ARROW) {
59204       *     fillVal = 255;
59205       *   } else if (keyCode === DOWN_ARROW) {
59206       *     fillVal = 0;
59207       *   }
59208       *   return false; // prevent default
59209       * }
59210       * </code></div>
59211       *
59212       * @alt
59213       * Grey rect center. turns white when up arrow pressed and black when down
59214       *
59215       */
59216
59217      p5.prototype.keyCode = 0;
59218      /**
59219       * The <a href="#/p5/keyPressed">keyPressed()</a> function is called once every time a key is pressed. The
59220       * keyCode for the key that was pressed is stored in the <a href="#/p5/keyCode">keyCode</a> variable.
59221       * <br><br>
59222       * For non-ASCII keys, use the keyCode variable. You can check if the keyCode
59223       * equals BACKSPACE, DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL,
59224       * OPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.
59225       * <br><br>
59226       * For ASCII keys, the key that was pressed is stored in the key variable. However, it
59227       * does not distinguish between uppercase and lowercase. For this reason, it
59228       * is recommended to use <a href="#/p5/keyTyped">keyTyped()</a> to read the key variable, in which the
59229       * case of the variable will be distinguished.
59230       * <br><br>
59231       * Because of how operating systems handle key repeats, holding down a key
59232       * may cause multiple calls to <a href="#/p5/keyTyped">keyTyped()</a> (and <a href="#/p5/keyReleased">keyReleased()</a> as well). The
59233       * rate of repeat is set by the operating system and how each computer is
59234       * configured.<br><br>
59235       * Browsers may have different default
59236       * behaviors attached to various key events. To prevent any default
59237       * behavior for this event, add "return false" to the end of the method.
59238       *
59239       * @method keyPressed
59240       * @example
59241       * <div>
59242       * <code>
59243       * let value = 0;
59244       * function draw() {
59245       *   fill(value);
59246       *   rect(25, 25, 50, 50);
59247       * }
59248       * function keyPressed() {
59249       *   if (value === 0) {
59250       *     value = 255;
59251       *   } else {
59252       *     value = 0;
59253       *   }
59254       * }
59255       * </code>
59256       * </div>
59257       * <div>
59258       * <code>
59259       * let value = 0;
59260       * function draw() {
59261       *   fill(value);
59262       *   rect(25, 25, 50, 50);
59263       * }
59264       * function keyPressed() {
59265       *   if (keyCode === LEFT_ARROW) {
59266       *     value = 255;
59267       *   } else if (keyCode === RIGHT_ARROW) {
59268       *     value = 0;
59269       *   }
59270       * }
59271       * </code>
59272       * </div>
59273       * <div class="norender">
59274       * <code>
59275       * function keyPressed() {
59276       *   // Do something
59277       *   return false; // prevent any default behaviour
59278       * }
59279       * </code>
59280       * </div>
59281       *
59282       * @alt
59283       * black rect center. turns white when key pressed and black when released
59284       * black rect center. turns white when left arrow pressed and black when right.
59285       *
59286       */
59287
59288      p5.prototype._onkeydown = function (e) {
59289        if (downKeys[e.which]) {
59290          // prevent multiple firings
59291          return;
59292        }
59293
59294        this._setProperty('isKeyPressed', true);
59295
59296        this._setProperty('keyIsPressed', true);
59297
59298        this._setProperty('keyCode', e.which);
59299
59300        downKeys[e.which] = true;
59301
59302        this._setProperty('key', e.key || String.fromCharCode(e.which) || e.which);
59303
59304        var keyPressed = this.keyPressed || window.keyPressed;
59305
59306        if (typeof keyPressed === 'function' && !e.charCode) {
59307          var executeDefault = keyPressed(e);
59308
59309          if (executeDefault === false) {
59310            e.preventDefault();
59311          }
59312        }
59313      };
59314      /**
59315       * The <a href="#/p5/keyReleased">keyReleased()</a> function is called once every time a key is released.
59316       * See <a href="#/p5/key">key</a> and <a href="#/p5/keyCode">keyCode</a> for more information.<br><br>
59317       * Browsers may have different default
59318       * behaviors attached to various key events. To prevent any default
59319       * behavior for this event, add "return false" to the end of the method.
59320       *
59321       * @method keyReleased
59322       * @example
59323       * <div>
59324       * <code>
59325       * let value = 0;
59326       * function draw() {
59327       *   fill(value);
59328       *   rect(25, 25, 50, 50);
59329       * }
59330       * function keyReleased() {
59331       *   if (value === 0) {
59332       *     value = 255;
59333       *   } else {
59334       *     value = 0;
59335       *   }
59336       *   return false; // prevent any default behavior
59337       * }
59338       * </code>
59339       * </div>
59340       *
59341       * @alt
59342       * black rect center. turns white when key pressed and black when pressed again
59343       *
59344       */
59345
59346
59347      p5.prototype._onkeyup = function (e) {
59348        var keyReleased = this.keyReleased || window.keyReleased;
59349        downKeys[e.which] = false;
59350
59351        if (!areDownKeys()) {
59352          this._setProperty('isKeyPressed', false);
59353
59354          this._setProperty('keyIsPressed', false);
59355        }
59356
59357        this._setProperty('_lastKeyCodeTyped', null);
59358
59359        this._setProperty('key', e.key || String.fromCharCode(e.which) || e.which);
59360
59361        this._setProperty('keyCode', e.which);
59362
59363        if (typeof keyReleased === 'function') {
59364          var executeDefault = keyReleased(e);
59365
59366          if (executeDefault === false) {
59367            e.preventDefault();
59368          }
59369        }
59370      };
59371      /**
59372       * The <a href="#/p5/keyTyped">keyTyped()</a> function is called once every time a key is pressed, but
59373       * action keys such as Ctrl, Shift, and Alt are ignored. The most recent
59374       * key pressed will be stored in the key variable.
59375       * <br><br>
59376       * Because of how operating systems handle key repeats, holding down a key
59377       * will cause multiple calls to <a href="#/p5/keyTyped">keyTyped()</a> (and <a href="#/p5/keyReleased">keyReleased()</a> as well). The
59378       * rate of repeat is set by the operating system and how each computer is
59379       * configured.<br><br>
59380       * Browsers may have different default behaviors attached to various key
59381       * events. To prevent any default behavior for this event, add "return false"
59382       * to the end of the method.
59383       *
59384       * @method keyTyped
59385       * @example
59386       * <div>
59387       * <code>
59388       * let value = 0;
59389       * function draw() {
59390       *   fill(value);
59391       *   rect(25, 25, 50, 50);
59392       * }
59393       * function keyTyped() {
59394       *   if (key === 'a') {
59395       *     value = 255;
59396       *   } else if (key === 'b') {
59397       *     value = 0;
59398       *   }
59399       *   // uncomment to prevent any default behavior
59400       *   // return false;
59401       * }
59402       * </code>
59403       * </div>
59404       *
59405       * @alt
59406       * black rect center. turns white when 'a' key typed and black when 'b' pressed
59407       *
59408       */
59409
59410
59411      p5.prototype._onkeypress = function (e) {
59412        if (e.which === this._lastKeyCodeTyped) {
59413          // prevent multiple firings
59414          return;
59415        }
59416
59417        this._setProperty('keyCode', e.which);
59418
59419        this._setProperty('_lastKeyCodeTyped', e.which); // track last keyCode
59420
59421
59422        this._setProperty('key', String.fromCharCode(e.which));
59423
59424        var keyTyped = this.keyTyped || window.keyTyped;
59425
59426        if (typeof keyTyped === 'function') {
59427          var executeDefault = keyTyped(e);
59428
59429          if (executeDefault === false) {
59430            e.preventDefault();
59431          }
59432        }
59433      };
59434      /**
59435       * The onblur function is called when the user is no longer focused
59436       * on the p5 element. Because the keyup events will not fire if the user is
59437       * not focused on the element we must assume all keys currently down have
59438       * been released.
59439       */
59440
59441
59442      p5.prototype._onblur = function (e) {
59443        downKeys = {};
59444      };
59445      /**
59446       * The <a href="#/p5/keyIsDown">keyIsDown()</a> function checks if the key is currently down, i.e. pressed.
59447       * It can be used if you have an object that moves, and you want several keys
59448       * to be able to affect its behaviour simultaneously, such as moving a
59449       * sprite diagonally. You can put in any number representing the keyCode of
59450       * the key, or use any of the variable <a href="#/p5/keyCode">keyCode</a> names listed
59451       * <a href="http://p5js.org/reference/#p5/keyCode">here</a>.
59452       *
59453       * @method keyIsDown
59454       * @param {Number}          code The key to check for.
59455       * @return {Boolean}        whether key is down or not
59456       * @example
59457       * <div><code>
59458       * let x = 100;
59459       * let y = 100;
59460       *
59461       * function setup() {
59462       *   createCanvas(512, 512);
59463       * }
59464       *
59465       * function draw() {
59466       *   if (keyIsDown(LEFT_ARROW)) {
59467       *     x -= 5;
59468       *   }
59469       *
59470       *   if (keyIsDown(RIGHT_ARROW)) {
59471       *     x += 5;
59472       *   }
59473       *
59474       *   if (keyIsDown(UP_ARROW)) {
59475       *     y -= 5;
59476       *   }
59477       *
59478       *   if (keyIsDown(DOWN_ARROW)) {
59479       *     y += 5;
59480       *   }
59481       *
59482       *   clear();
59483       *   fill(255, 0, 0);
59484       *   ellipse(x, y, 50, 50);
59485       * }
59486       * </code></div>
59487       *
59488       * <div><code>
59489       * let diameter = 50;
59490       *
59491       * function setup() {
59492       *   createCanvas(512, 512);
59493       * }
59494       *
59495       * function draw() {
59496       *   // 107 and 187 are keyCodes for "+"
59497       *   if (keyIsDown(107) || keyIsDown(187)) {
59498       *     diameter += 1;
59499       *   }
59500       *
59501       *   // 109 and 189 are keyCodes for "-"
59502       *   if (keyIsDown(109) || keyIsDown(189)) {
59503       *     diameter -= 1;
59504       *   }
59505       *
59506       *   clear();
59507       *   fill(255, 0, 0);
59508       *   ellipse(50, 50, diameter, diameter);
59509       * }
59510       * </code></div>
59511       *
59512       * @alt
59513       * 50x50 red ellipse moves left, right, up and down with arrow presses.
59514       * 50x50 red ellipse gets bigger or smaller when + or - are pressed.
59515       *
59516       */
59517
59518
59519      p5.prototype.keyIsDown = function (code) {
59520        p5._validateParameters('keyIsDown', arguments);
59521
59522        return downKeys[code];
59523      };
59524      /**
59525       * The checkDownKeys function returns a boolean true if any keys pressed
59526       * and a false if no keys are currently pressed.
59527      
59528       * Helps avoid instances where a multiple keys are pressed simultaneously and
59529       * releasing a single key will then switch the
59530       * keyIsPressed property to true.
59531       * @private
59532      **/
59533
59534
59535      function areDownKeys() {
59536        for (var key in downKeys) {
59537          if (downKeys.hasOwnProperty(key) && downKeys[key] === true) {
59538            return true;
59539          }
59540        }
59541
59542        return false;
59543      }
59544
59545      module.exports = p5;
59546    }, {
59547      "../core/main": 24
59548    }],
59549    40: [function (_dereq_, module, exports) {
59550      /**
59551       * @module Events
59552       * @submodule Mouse
59553       * @for p5
59554       * @requires core
59555       * @requires constants
59556       */
59557      'use strict';
59558
59559      var p5 = _dereq_('../core/main');
59560
59561      var constants = _dereq_('../core/constants');
59562      /*
59563       * This is a flag which is false until the first time
59564       * we receive a mouse event. The pmouseX and pmouseY
59565       * values will match the mouseX and mouseY values until
59566       * this interaction takes place.
59567       */
59568
59569
59570      p5.prototype._hasMouseInteracted = false;
59571      /**
59572       * The system variable mouseX always contains the current horizontal
59573       * position of the mouse, relative to (0, 0) of the canvas. If touch is
59574       * used instead of mouse input, mouseX will hold the x value of the most
59575       * recent touch point.
59576       *
59577       * @property {Number} mouseX
59578       * @readOnly
59579       *
59580       * @example
59581       * <div>
59582       * <code>
59583       * // Move the mouse across the canvas
59584       * function draw() {
59585       *   background(244, 248, 252);
59586       *   line(mouseX, 0, mouseX, 100);
59587       * }
59588       * </code>
59589       * </div>
59590       *
59591       * @alt
59592       * horizontal black line moves left and right with mouse x-position
59593       *
59594       */
59595
59596      p5.prototype.mouseX = 0;
59597      /**
59598       * The system variable mouseY always contains the current vertical position
59599       * of the mouse, relative to (0, 0) of the canvas. If touch is
59600       * used instead of mouse input, mouseY will hold the y value of the most
59601       * recent touch point.
59602       *
59603       * @property {Number} mouseY
59604       * @readOnly
59605       *
59606       * @example
59607       * <div>
59608       * <code>
59609       * // Move the mouse across the canvas
59610       * function draw() {
59611       *   background(244, 248, 252);
59612       *   line(0, mouseY, 100, mouseY);
59613       * }
59614       * </code>
59615       * </div>
59616       *
59617       * @alt
59618       * vertical black line moves up and down with mouse y-position
59619       *
59620       */
59621
59622      p5.prototype.mouseY = 0;
59623      /**
59624       * The system variable pmouseX always contains the horizontal position of
59625       * the mouse or finger in the frame previous to the current frame, relative to
59626       * (0, 0) of the canvas. Note: pmouseX will be reset to the current mouseX
59627       * value at the start of each touch event.
59628       *
59629       * @property {Number} pmouseX
59630       * @readOnly
59631       *
59632       * @example
59633       * <div>
59634       * <code>
59635       * // Move the mouse across the canvas to leave a trail
59636       * function setup() {
59637       *   //slow down the frameRate to make it more visible
59638       *   frameRate(10);
59639       * }
59640       *
59641       * function draw() {
59642       *   background(244, 248, 252);
59643       *   line(mouseX, mouseY, pmouseX, pmouseY);
59644       *   print(pmouseX + ' -> ' + mouseX);
59645       * }
59646       * </code>
59647       * </div>
59648       *
59649       * @alt
59650       * line trail is created from cursor movements. faster movement make longer line.
59651       *
59652       */
59653
59654      p5.prototype.pmouseX = 0;
59655      /**
59656       * The system variable pmouseY always contains the vertical position of the
59657       * mouse or finger in the frame previous to the current frame, relative to
59658       * (0, 0) of the canvas. Note: pmouseY will be reset to the current mouseY
59659       * value at the start of each touch event.
59660       *
59661       * @property {Number} pmouseY
59662       * @readOnly
59663       *
59664       * @example
59665       * <div>
59666       * <code>
59667       * function draw() {
59668       *   background(237, 34, 93);
59669       *   fill(0);
59670       *   //draw a square only if the mouse is not moving
59671       *   if (mouseY === pmouseY && mouseX === pmouseX) {
59672       *     rect(20, 20, 60, 60);
59673       *   }
59674       *
59675       *   print(pmouseY + ' -> ' + mouseY);
59676       * }
59677       * </code>
59678       * </div>
59679       *
59680       * @alt
59681       * 60x60 black rect center, fuschia background. rect flickers on mouse movement
59682       *
59683       */
59684
59685      p5.prototype.pmouseY = 0;
59686      /**
59687       * The system variable winMouseX always contains the current horizontal
59688       * position of the mouse, relative to (0, 0) of the window.
59689       *
59690       * @property {Number} winMouseX
59691       * @readOnly
59692       *
59693       * @example
59694       * <div>
59695       * <code>
59696       * let myCanvas;
59697       *
59698       * function setup() {
59699       *   //use a variable to store a pointer to the canvas
59700       *   myCanvas = createCanvas(100, 100);
59701       * }
59702       *
59703       * function draw() {
59704       *   background(237, 34, 93);
59705       *   fill(0);
59706       *
59707       *   //move the canvas to the horizontal mouse position
59708       *   //rela                    tive to the window
59709       *   myCanvas.position(winMouseX + 1, windowHeight / 2);
59710       *
59711       *   //the y of the square is relative to the canvas
59712       *   rect(20, mouseY, 60, 60);
59713       * }
59714       * </code>
59715       * </div>
59716       *
59717       * @alt
59718       * 60x60 black rect y moves with mouse y and fuschia canvas moves with mouse x
59719       *
59720       */
59721
59722      p5.prototype.winMouseX = 0;
59723      /**
59724       * The system variable winMouseY always contains the current vertical
59725       * position of the mouse, relative to (0, 0) of the window.
59726       *
59727       * @property {Number} winMouseY
59728       * @readOnly
59729       *
59730       * @example
59731       * <div>
59732       * <code>
59733       * let myCanvas;
59734       *
59735       * function setup() {
59736       *   //use a variable to store a pointer to the canvas
59737       *   myCanvas = createCanvas(100, 100);
59738       * }
59739       *
59740       * function draw() {
59741       *   background(237, 34, 93);
59742       *   fill(0);
59743       *
59744       *   //move the canvas to the vertical mouse position
59745       *   //rel                    ative to the window
59746       *   myCanvas.position(windowWidth / 2, winMouseY + 1);
59747       *
59748       *   //the x of the square is relative to the canvas
59749       *   rect(mouseX, 20, 60, 60);
59750       * }
59751       * </code>
59752       * </div>
59753       *
59754       * @alt
59755       * 60x60 black rect x moves with mouse x and fuschia canvas y moves with mouse y
59756       *
59757       */
59758
59759      p5.prototype.winMouseY = 0;
59760      /**
59761       * The system variable pwinMouseX always contains the horizontal position
59762       * of the mouse in the frame previous to the current frame, relative to
59763       * (0, 0) of the window. Note: pwinMouseX will be reset to the current winMouseX
59764       * value at the start of each touch event.
59765       *
59766       * @property {Number} pwinMouseX
59767       * @readOnly
59768       *
59769       * @example
59770       * <div>
59771       * <code>
59772       * let myCanvas;
59773       *
59774       * function setup() {
59775       *   //use a variable to store a pointer to the canvas
59776       *   myCanvas = createCanvas(100, 100);
59777       *   noStroke();
59778       *   fill(237, 34, 93);
59779       * }
59780       *
59781       * function draw() {
59782       *   clear();
59783       *   //the difference between previous and
59784       *   //current x position is the horizontal mouse speed
59785       *   let speed = abs(winMouseX - pwinMouseX);
59786       *   //change the size of the circle
59787       *   //according to the horizontal speed
59788       *   ellipse(50, 50, 10 + speed * 5, 10 + speed * 5);
59789       *   //move the canvas to the mouse position
59790       *   myCanvas.position(winMouseX + 1, winMouseY + 1);
59791       * }
59792       * </code>
59793       * </div>
59794       *
59795       * @alt
59796       * fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed
59797       *
59798       */
59799
59800      p5.prototype.pwinMouseX = 0;
59801      /**
59802       * The system variable pwinMouseY always contains the vertical position of
59803       * the mouse in the frame previous to the current frame, relative to (0, 0)
59804       * of the window. Note: pwinMouseY will be reset to the current winMouseY
59805       * value at the start of each touch event.
59806       *
59807       * @property {Number} pwinMouseY
59808       * @readOnly
59809       *
59810       *
59811       * @example
59812       * <div>
59813       * <code>
59814       * let myCanvas;
59815       *
59816       * function setup() {
59817       *   //use a variable to store a pointer to the canvas
59818       *   myCanvas = createCanvas(100, 100);
59819       *   noStroke();
59820       *   fill(237, 34, 93);
59821       * }
59822       *
59823       * function draw() {
59824       *   clear();
59825       *   //the difference between previous and
59826       *   //current y position is the vertical mouse speed
59827       *   let speed = abs(winMouseY - pwinMouseY);
59828       *   //change the size of the circle
59829       *   //according to the vertical speed
59830       *   ellipse(50, 50, 10 + speed * 5, 10 + speed * 5);
59831       *   //move the canvas to the mouse position
59832       *   myCanvas.position(winMouseX + 1, winMouseY + 1);
59833       * }
59834       * </code>
59835       * </div>
59836       *
59837       * @alt
59838       * fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed
59839       *
59840       */
59841
59842      p5.prototype.pwinMouseY = 0;
59843      /**
59844       * Processing automatically tracks if the mouse button is pressed and which
59845       * button is pressed. The value of the system variable mouseButton is either
59846       * LEFT, RIGHT, or CENTER depending on which button was pressed last.
59847       * Warning: different browsers may track mouseButton differently.
59848       *
59849       * @property {Constant} mouseButton
59850       * @readOnly
59851       *
59852       * @example
59853       * <div>
59854       * <code>
59855       * function draw() {
59856       *   background(237, 34, 93);
59857       *   fill(0);
59858       *
59859       *   if (mouseIsPressed) {
59860       *     if (mouseButton === LEFT) {
59861       *       ellipse(50, 50, 50, 50);
59862       *     }
59863       *     if (mouseButton === RIGHT) {
59864       *       rect(25, 25, 50, 50);
59865       *     }
59866       *     if (mouseButton === CENTER) {
59867       *       triangle(23, 75, 50, 20, 78, 75);
59868       *     }
59869       *   }
59870       *
59871       *   print(mouseButton);
59872       * }
59873       * </code>
59874       * </div>
59875       *
59876       * @alt
59877       * 50x50 black ellipse appears on center of fuschia canvas on mouse click/press.
59878       *
59879       */
59880
59881      p5.prototype.mouseButton = 0;
59882      /**
59883       * The boolean system variable mouseIsPressed is true if the mouse is pressed
59884       * and false if not.
59885       *
59886       * @property {Boolean} mouseIsPressed
59887       * @readOnly
59888       *
59889       * @example
59890       * <div>
59891       * <code>
59892       * function draw() {
59893       *   background(237, 34, 93);
59894       *   fill(0);
59895       *
59896       *   if (mouseIsPressed) {
59897       *     ellipse(50, 50, 50, 50);
59898       *   } else {
59899       *     rect(25, 25, 50, 50);
59900       *   }
59901       *
59902       *   print(mouseIsPressed);
59903       * }
59904       * </code>
59905       * </div>
59906       *
59907       * @alt
59908       * black 50x50 rect becomes ellipse with mouse click/press. fuschia background.
59909       *
59910       */
59911
59912      p5.prototype.mouseIsPressed = false;
59913
59914      p5.prototype._updateNextMouseCoords = function (e) {
59915        if (this._curElement !== null && (!e.touches || e.touches.length > 0)) {
59916          var mousePos = getMousePos(this._curElement.elt, this.width, this.height, e);
59917
59918          this._setProperty('mouseX', mousePos.x);
59919
59920          this._setProperty('mouseY', mousePos.y);
59921
59922          this._setProperty('winMouseX', mousePos.winX);
59923
59924          this._setProperty('winMouseY', mousePos.winY);
59925        }
59926
59927        if (!this._hasMouseInteracted) {
59928          // For first draw, make previous and next equal
59929          this._updateMouseCoords();
59930
59931          this._setProperty('_hasMouseInteracted', true);
59932        }
59933      };
59934
59935      p5.prototype._updateMouseCoords = function () {
59936        this._setProperty('pmouseX', this.mouseX);
59937
59938        this._setProperty('pmouseY', this.mouseY);
59939
59940        this._setProperty('pwinMouseX', this.winMouseX);
59941
59942        this._setProperty('pwinMouseY', this.winMouseY);
59943
59944        this._setProperty('_pmouseWheelDeltaY', this._mouseWheelDeltaY);
59945      };
59946
59947      function getMousePos(canvas, w, h, evt) {
59948        if (evt && !evt.clientX) {
59949          // use touches if touch and not mouse
59950          if (evt.touches) {
59951            evt = evt.touches[0];
59952          } else if (evt.changedTouches) {
59953            evt = evt.changedTouches[0];
59954          }
59955        }
59956
59957        var rect = canvas.getBoundingClientRect();
59958        var sx = canvas.scrollWidth / w;
59959        var sy = canvas.scrollHeight / h;
59960        return {
59961          x: (evt.clientX - rect.left) / sx,
59962          y: (evt.clientY - rect.top) / sy,
59963          winX: evt.clientX,
59964          winY: evt.clientY,
59965          id: evt.identifier
59966        };
59967      }
59968
59969      p5.prototype._setMouseButton = function (e) {
59970        if (e.button === 1) {
59971          this._setProperty('mouseButton', constants.CENTER);
59972        } else if (e.button === 2) {
59973          this._setProperty('mouseButton', constants.RIGHT);
59974        } else {
59975          this._setProperty('mouseButton', constants.LEFT);
59976        }
59977      };
59978      /**
59979       * The <a href="#/p5/mouseMoved">mouseMoved()</a> function is called every time the mouse moves and a mouse
59980       * button is not pressed.<br><br>
59981       * Browsers may have different default
59982       * behaviors attached to various mouse events. To prevent any default
59983       * behavior for this event, add "return false" to the end of the method.
59984       *
59985       * @method mouseMoved
59986       * @param  {Object} [event] optional MouseEvent callback argument.
59987       * @example
59988       * <div>
59989       * <code>
59990       * // Move the mouse across the page
59991       * // to change its value
59992       *
59993       * let value = 0;
59994       * function draw() {
59995       *   fill(value);
59996       *   rect(25, 25, 50, 50);
59997       * }
59998       * function mouseMoved() {
59999       *   value = value + 5;
60000       *   if (value > 255) {
60001       *     value = 0;
60002       *   }
60003       * }
60004       * </code>
60005       * </div>
60006       *
60007       * <div class="norender">
60008       * <code>
60009       * function mouseMoved() {
60010       *   ellipse(mouseX, mouseY, 5, 5);
60011       *   // prevent default
60012       *   return false;
60013       * }
60014       * </code>
60015       * </div>
60016       *
60017       * <div class="norender">
60018       * <code>
60019       * // returns a MouseEvent object
60020       * // as a callback argument
60021       * function mouseMoved(event) {
60022       *   console.log(event);
60023       * }
60024       * </code>
60025       * </div>
60026       *
60027       * @alt
60028       * black 50x50 rect becomes lighter with mouse movements until white then resets
60029       * no image displayed
60030       *
60031       */
60032
60033      /**
60034       * The <a href="#/p5/mouseDragged">mouseDragged()</a> function is called once every time the mouse moves and
60035       * a mouse button is pressed. If no <a href="#/p5/mouseDragged">mouseDragged()</a> function is defined, the
60036       * <a href="#/p5/touchMoved">touchMoved()</a> function will be called instead if it is defined.<br><br>
60037       * Browsers may have different default
60038       * behaviors attached to various mouse events. To prevent any default
60039       * behavior for this event, add "return false" to the end of the method.
60040       *
60041       * @method mouseDragged
60042       * @param  {Object} [event] optional MouseEvent callback argument.
60043       * @example
60044       * <div>
60045       * <code>
60046       * // Drag the mouse across the page
60047       * // to change its value
60048       *
60049       * let value = 0;
60050       * function draw() {
60051       *   fill(value);
60052       *   rect(25, 25, 50, 50);
60053       * }
60054       * function mouseDragged() {
60055       *   value = value + 5;
60056       *   if (value > 255) {
60057       *     value = 0;
60058       *   }
60059       * }
60060       * </code>
60061       * </div>
60062       *
60063       * <div class="norender">
60064       * <code>
60065       * function mouseDragged() {
60066       *   ellipse(mouseX, mouseY, 5, 5);
60067       *   // prevent default
60068       *   return false;
60069       * }
60070       * </code>
60071       * </div>
60072       *
60073       * <div class="norender">
60074       * <code>
60075       * // returns a MouseEvent object
60076       * // as a callback argument
60077       * function mouseDragged(event) {
60078       *   console.log(event);
60079       * }
60080       * </code>
60081       * </div>
60082       *
60083       * @alt
60084       * black 50x50 rect turns lighter with mouse click and drag until white, resets
60085       * no image displayed
60086       *
60087       */
60088
60089
60090      p5.prototype._onmousemove = function (e) {
60091        var context = this._isGlobal ? window : this;
60092        var executeDefault;
60093
60094        this._updateNextMouseCoords(e);
60095
60096        if (!this.mouseIsPressed) {
60097          if (typeof context.mouseMoved === 'function') {
60098            executeDefault = context.mouseMoved(e);
60099
60100            if (executeDefault === false) {
60101              e.preventDefault();
60102            }
60103          }
60104        } else {
60105          if (typeof context.mouseDragged === 'function') {
60106            executeDefault = context.mouseDragged(e);
60107
60108            if (executeDefault === false) {
60109              e.preventDefault();
60110            }
60111          } else if (typeof context.touchMoved === 'function') {
60112            executeDefault = context.touchMoved(e);
60113
60114            if (executeDefault === false) {
60115              e.preventDefault();
60116            }
60117          }
60118        }
60119      };
60120      /**
60121       * The <a href="#/p5/mousePressed">mousePressed()</a> function is called once after every time a mouse button
60122       * is pressed. The mouseButton variable (see the related reference entry)
60123       * can be used to determine which button has been pressed. If no
60124       * <a href="#/p5/mousePressed">mousePressed()</a> function is defined, the <a href="#/p5/touchStarted">touchStarted()</a> function will be
60125       * called instead if it is defined.<br><br>
60126       * Browsers may have different default
60127       * behaviors attached to various mouse events. To prevent any default
60128       * behavior for this event, add "return false" to the end of the method.
60129       *
60130       * @method mousePressed
60131       * @param  {Object} [event] optional MouseEvent callback argument.
60132       * @example
60133       * <div>
60134       * <code>
60135       * // Click within the image to change
60136       * // the value of the rectangle
60137       *
60138       * let value = 0;
60139       * function draw() {
60140       *   fill(value);
60141       *   rect(25, 25, 50, 50);
60142       * }
60143       * function mousePressed() {
60144       *   if (value === 0) {
60145       *     value = 255;
60146       *   } else {
60147       *     value = 0;
60148       *   }
60149       * }
60150       * </code>
60151       * </div>
60152       *
60153       * <div class="norender">
60154       * <code>
60155       * function mousePressed() {
60156       *   ellipse(mouseX, mouseY, 5, 5);
60157       *   // prevent default
60158       *   return false;
60159       * }
60160       * </code>
60161       * </div>
60162       *
60163       * <div class="norender">
60164       * <code>
60165       * // returns a MouseEvent object
60166       * // as a callback argument
60167       * function mousePressed(event) {
60168       *   console.log(event);
60169       * }
60170       * </code>
60171       * </div>
60172       *
60173       * @alt
60174       * black 50x50 rect turns white with mouse click/press.
60175       * no image displayed
60176       *
60177       */
60178
60179
60180      p5.prototype._onmousedown = function (e) {
60181        var context = this._isGlobal ? window : this;
60182        var executeDefault;
60183
60184        this._setProperty('mouseIsPressed', true);
60185
60186        this._setMouseButton(e);
60187
60188        this._updateNextMouseCoords(e);
60189
60190        if (typeof context.mousePressed === 'function') {
60191          executeDefault = context.mousePressed(e);
60192
60193          if (executeDefault === false) {
60194            e.preventDefault();
60195          }
60196        } else if (typeof context.touchStarted === 'function') {
60197          executeDefault = context.touchStarted(e);
60198
60199          if (executeDefault === false) {
60200            e.preventDefault();
60201          }
60202        }
60203      };
60204      /**
60205       * The <a href="#/p5/mouseReleased">mouseReleased()</a> function is called every time a mouse button is
60206       * released. If no <a href="#/p5/mouseReleased">mouseReleased()</a> function is defined, the <a href="#/p5/touchEnded">touchEnded()</a>
60207       * function will be called instead if it is defined.<br><br>
60208       * Browsers may have different default
60209       * behaviors attached to various mouse events. To prevent any default
60210       * behavior for this event, add "return false" to the end of the method.
60211       *
60212       *
60213       * @method mouseReleased
60214       * @param  {Object} [event] optional MouseEvent callback argument.
60215       * @example
60216       * <div>
60217       * <code>
60218       * // Click within the image to change
60219       * // the value of the rectangle
60220       * // after the mouse has been clicked
60221       *
60222       * let value = 0;
60223       * function draw() {
60224       *   fill(value);
60225       *   rect(25, 25, 50, 50);
60226       * }
60227       * function mouseReleased() {
60228       *   if (value === 0) {
60229       *     value = 255;
60230       *   } else {
60231       *     value = 0;
60232       *   }
60233       * }
60234       * </code>
60235       * </div>
60236       *
60237       * <div class="norender">
60238       * <code>
60239       * function mouseReleased() {
60240       *   ellipse(mouseX, mouseY, 5, 5);
60241       *   // prevent default
60242       *   return false;
60243       * }
60244       * </code>
60245       * </div>
60246       *
60247       * <div class="norender">
60248       * <code>
60249       * // returns a MouseEvent object
60250       * // as a callback argument
60251       * function mouseReleased(event) {
60252       *   console.log(event);
60253       * }
60254       * </code>
60255       * </div>
60256       *
60257       * @alt
60258       * black 50x50 rect turns white with mouse click/press.
60259       * no image displayed
60260       *
60261       */
60262
60263
60264      p5.prototype._onmouseup = function (e) {
60265        var context = this._isGlobal ? window : this;
60266        var executeDefault;
60267
60268        this._setProperty('mouseIsPressed', false);
60269
60270        if (typeof context.mouseReleased === 'function') {
60271          executeDefault = context.mouseReleased(e);
60272
60273          if (executeDefault === false) {
60274            e.preventDefault();
60275          }
60276        } else if (typeof context.touchEnded === 'function') {
60277          executeDefault = context.touchEnded(e);
60278
60279          if (executeDefault === false) {
60280            e.preventDefault();
60281          }
60282        }
60283      };
60284
60285      p5.prototype._ondragend = p5.prototype._onmouseup;
60286      p5.prototype._ondragover = p5.prototype._onmousemove;
60287      /**
60288       * The <a href="#/p5/mouseClicked">mouseClicked()</a> function is called once after a mouse button has been
60289       * pressed and then released.<br><br>
60290       * Browsers handle clicks differently, so this function is only guaranteed to be
60291       * run when the left mouse button is clicked. To handle other mouse buttons
60292       * being pressed or released, see <a href="#/p5/mousePressed">mousePressed()</a> or <a href="#/p5/mouseReleased">mouseReleased()</a>.<br><br>
60293       * Browsers may have different default
60294       * behaviors attached to various mouse events. To prevent any default
60295       * behavior for this event, add "return false" to the end of the method.
60296       *
60297       * @method mouseClicked
60298       * @param  {Object} [event] optional MouseEvent callback argument.
60299       * @example
60300       * <div>
60301       * <code>
60302       * // Click within the image to change
60303       * // the value of the rectangle
60304       * // after the mouse has been clicked
60305       *
60306       * let value = 0;
60307       * function draw() {
60308       *   fill(value);
60309       *   rect(25, 25, 50, 50);
60310       * }
60311       *
60312       * function mouseClicked() {
60313       *   if (value === 0) {
60314       *     value = 255;
60315       *   } else {
60316       *     value = 0;
60317       *   }
60318       * }
60319       * </code>
60320       * </div>
60321       *
60322       * <div class="norender">
60323       * <code>
60324       * function mouseClicked() {
60325       *   ellipse(mouseX, mouseY, 5, 5);
60326       *   // prevent default
60327       *   return false;
60328       * }
60329       * </code>
60330       * </div>
60331       *
60332       * <div class="norender">
60333       * <code>
60334       * // returns a MouseEvent object
60335       * // as a callback argument
60336       * function mouseClicked(event) {
60337       *   console.log(event);
60338       * }
60339       * </code>
60340       * </div>
60341       *
60342       * @alt
60343       * black 50x50 rect turns white with mouse click/press.
60344       * no image displayed
60345       *
60346       */
60347
60348      p5.prototype._onclick = function (e) {
60349        var context = this._isGlobal ? window : this;
60350
60351        if (typeof context.mouseClicked === 'function') {
60352          var executeDefault = context.mouseClicked(e);
60353
60354          if (executeDefault === false) {
60355            e.preventDefault();
60356          }
60357        }
60358      };
60359      /**
60360       * The <a href="#/p5/doubleClicked">doubleClicked()</a> function is executed every time a event
60361       * listener has detected a dblclick event which is a part of the
60362       * DOM L3 specification. The doubleClicked event is fired when a
60363       * pointing device button (usually a mouse's primary button)
60364       * is clicked twice on a single element. For more info on the
60365       * dblclick event refer to mozilla's documentation here:
60366       * https://developer.mozilla.org/en-US/docs/Web/Events/dblclick
60367       *
60368       * @method doubleClicked
60369       * @param  {Object} [event] optional MouseEvent callback argument.
60370       * @example
60371       * <div>
60372       * <code>
60373       * // Click within the image to change
60374       * // the value of the rectangle
60375       * // after the mouse has been double clicked
60376       *
60377       * let value = 0;
60378       * function draw() {
60379       *   fill(value);
60380       *   rect(25, 25, 50, 50);
60381       * }
60382       *
60383       * function doubleClicked() {
60384       *   if (value === 0) {
60385       *     value = 255;
60386       *   } else {
60387       *     value = 0;
60388       *   }
60389       * }
60390       * </code>
60391       * </div>
60392       *
60393       * <div class="norender">
60394       * <code>
60395       * function doubleClicked() {
60396       *   ellipse(mouseX, mouseY, 5, 5);
60397       *   // prevent default
60398       *   return false;
60399       * }
60400       * </code>
60401       * </div>
60402       *
60403       * <div class="norender">
60404       * <code>
60405       * // returns a MouseEvent object
60406       * // as a callback argument
60407       * function doubleClicked(event) {
60408       *   console.log(event);
60409       * }
60410       * </code>
60411       * </div>
60412       *
60413       * @alt
60414       * black 50x50 rect turns white with mouse doubleClick/press.
60415       * no image displayed
60416       */
60417
60418
60419      p5.prototype._ondblclick = function (e) {
60420        var context = this._isGlobal ? window : this;
60421
60422        if (typeof context.doubleClicked === 'function') {
60423          var executeDefault = context.doubleClicked(e);
60424
60425          if (executeDefault === false) {
60426            e.preventDefault();
60427          }
60428        }
60429      };
60430      /**
60431       * For use with WebGL orbitControl.
60432       * @property {Number} _mouseWheelDeltaY
60433       * @readOnly
60434       * @private
60435       */
60436
60437
60438      p5.prototype._mouseWheelDeltaY = 0;
60439      /**
60440       * For use with WebGL orbitControl.
60441       * @property {Number} _pmouseWheelDeltaY
60442       * @readOnly
60443       * @private
60444       */
60445
60446      p5.prototype._pmouseWheelDeltaY = 0;
60447      /**
60448       * The function <a href="#/p5/mouseWheel">mouseWheel()</a> is executed every time a vertical mouse wheel
60449       * event is detected either triggered by an actual mouse wheel or by a
60450       * touchpad.<br><br>
60451       * The event.delta property returns the amount the mouse wheel
60452       * have scrolled. The values can be positive or negative depending on the
60453       * scroll direction (on OS X with "natural" scrolling enabled, the signs
60454       * are inverted).<br><br>
60455       * Browsers may have different default behaviors attached to various
60456       * mouse events. To prevent any default behavior for this event, add
60457       * "return false" to the end of the method.<br><br>
60458       * Due to the current support of the "wheel" event on Safari, the function
60459       * may only work as expected if "return false" is included while using Safari.
60460       *
60461       * @method mouseWheel
60462       * @param  {Object} [event] optional WheelEvent callback argument.
60463       *
60464       * @example
60465       * <div>
60466       * <code>
60467       * let pos = 25;
60468       *
60469       * function draw() {
60470       *   background(237, 34, 93);
60471       *   fill(0);
60472       *   rect(25, pos, 50, 50);
60473       * }
60474       *
60475       * function mouseWheel(event) {
60476       *   print(event.delta);
60477       *   //move the square according to the vertical scroll amount
60478       *   pos += event.delta;
60479       *   //uncomment to block page scrolling
60480       *   //return false;
60481       * }
60482       * </code>
60483       * </div>
60484       *
60485       * @alt
60486       * black 50x50 rect moves up and down with vertical scroll. fuschia background
60487       *
60488       */
60489
60490      p5.prototype._onwheel = function (e) {
60491        var context = this._isGlobal ? window : this;
60492
60493        this._setProperty('_mouseWheelDeltaY', e.deltaY);
60494
60495        if (typeof context.mouseWheel === 'function') {
60496          e.delta = e.deltaY;
60497          var executeDefault = context.mouseWheel(e);
60498
60499          if (executeDefault === false) {
60500            e.preventDefault();
60501          }
60502        }
60503      };
60504
60505      module.exports = p5;
60506    }, {
60507      "../core/constants": 18,
60508      "../core/main": 24
60509    }],
60510    41: [function (_dereq_, module, exports) {
60511      /**
60512       * @module Events
60513       * @submodule Touch
60514       * @for p5
60515       * @requires core
60516       */
60517      'use strict';
60518
60519      var p5 = _dereq_('../core/main');
60520      /**
60521       * The system variable touches[] contains an array of the positions of all
60522       * current touch points, relative to (0, 0) of the canvas, and IDs identifying a
60523       * unique touch as it moves. Each element in the array is an object with x, y,
60524       * and id properties.
60525       *
60526       * The touches[] array is not supported on Safari and IE on touch-based
60527       * desktops (laptops).
60528       *
60529       * @property {Object[]} touches
60530       * @readOnly
60531       *
60532       * @example
60533       * <div>
60534       * <code>
60535       * // On a touchscreen device, touch
60536       * // the canvas using one or more fingers
60537       * // at the same time
60538       * function draw() {
60539       *   clear();
60540       *   let display = touches.length + ' touches';
60541       *   text(display, 5, 10);
60542       * }
60543       * </code>
60544       * </div>
60545       *
60546       * @alt
60547       * Number of touches currently registered are displayed on the canvas
60548       */
60549
60550
60551      p5.prototype.touches = [];
60552
60553      p5.prototype._updateTouchCoords = function (e) {
60554        if (this._curElement !== null) {
60555          var touches = [];
60556
60557          for (var i = 0; i < e.touches.length; i++) {
60558            touches[i] = getTouchInfo(this._curElement.elt, this.width, this.height, e, i);
60559          }
60560
60561          this._setProperty('touches', touches);
60562        }
60563      };
60564
60565      function getTouchInfo(canvas, w, h, e, i) {
60566        i = i || 0;
60567        var rect = canvas.getBoundingClientRect();
60568        var sx = canvas.scrollWidth / w;
60569        var sy = canvas.scrollHeight / h;
60570        var touch = e.touches[i] || e.changedTouches[i];
60571        return {
60572          x: (touch.clientX - rect.left) / sx,
60573          y: (touch.clientY - rect.top) / sy,
60574          winX: touch.clientX,
60575          winY: touch.clientY,
60576          id: touch.identifier
60577        };
60578      }
60579      /**
60580       * The touchStarted() function is called once after every time a touch is
60581       * registered. If no <a href="#/p5/touchStarted">touchStarted()</a> function is defined, the <a href="#/p5/mousePressed">mousePressed()</a>
60582       * function will be called instead if it is defined.<br><br>
60583       * Browsers may have different default behaviors attached to various touch
60584       * events. To prevent any default behavior for this event, add "return false"
60585       * to the end of the method.
60586       *
60587       * @method touchStarted
60588       * @param  {Object} [event] optional TouchEvent callback argument.
60589       * @example
60590       * <div>
60591       * <code>
60592       * // Touch within the image to change
60593       * // the value of the rectangle
60594       *
60595       * let value = 0;
60596       * function draw() {
60597       *   fill(value);
60598       *   rect(25, 25, 50, 50);
60599       * }
60600       * function touchStarted() {
60601       *   if (value === 0) {
60602       *     value = 255;
60603       *   } else {
60604       *     value = 0;
60605       *   }
60606       * }
60607       * </code>
60608       * </div>
60609       *
60610       * <div class="norender">
60611       * <code>
60612       * function touchStarted() {
60613       *   ellipse(mouseX, mouseY, 5, 5);
60614       *   // prevent default
60615       *   return false;
60616       * }
60617       * </code>
60618       * </div>
60619       *
60620       * <div class="norender">
60621       * <code>
60622       * // returns a TouchEvent object
60623       * // as a callback argument
60624       * function touchStarted(event) {
60625       *   console.log(event);
60626       * }
60627       * </code>
60628       * </div>
60629       *
60630       * @alt
60631       * 50x50 black rect turns white with touch event.
60632       * no image displayed
60633       */
60634
60635
60636      p5.prototype._ontouchstart = function (e) {
60637        var context = this._isGlobal ? window : this;
60638        var executeDefault;
60639
60640        this._setProperty('mouseIsPressed', true);
60641
60642        this._updateTouchCoords(e);
60643
60644        this._updateNextMouseCoords(e);
60645
60646        this._updateMouseCoords(); // reset pmouseXY at the start of each touch event
60647
60648
60649        if (typeof context.touchStarted === 'function') {
60650          executeDefault = context.touchStarted(e);
60651
60652          if (executeDefault === false) {
60653            e.preventDefault();
60654          }
60655        } else if (typeof context.mousePressed === 'function') {
60656          executeDefault = context.mousePressed(e);
60657
60658          if (executeDefault === false) {
60659            e.preventDefault();
60660          }
60661        }
60662      };
60663      /**
60664       * The <a href="#/p5/touchMoved">touchMoved()</a> function is called every time a touch move is registered.
60665       * If no <a href="#/p5/touchMoved">touchMoved()</a> function is defined, the <a href="#/p5/mouseDragged">mouseDragged()</a> function will
60666       * be called instead if it is defined.<br><br>
60667       * Browsers may have different default behaviors attached to various touch
60668       * events. To prevent any default behavior for this event, add "return false"
60669       * to the end of the method.
60670       *
60671       * @method touchMoved
60672       * @param  {Object} [event] optional TouchEvent callback argument.
60673       * @example
60674       * <div>
60675       * <code>
60676       * // Move your finger across the page
60677       * // to change its value
60678       *
60679       * let value = 0;
60680       * function draw() {
60681       *   fill(value);
60682       *   rect(25, 25, 50, 50);
60683       * }
60684       * function touchMoved() {
60685       *   value = value + 5;
60686       *   if (value > 255) {
60687       *     value = 0;
60688       *   }
60689       * }
60690       * </code>
60691       * </div>
60692       *
60693       * <div class="norender">
60694       * <code>
60695       * function touchMoved() {
60696       *   ellipse(mouseX, mouseY, 5, 5);
60697       *   // prevent default
60698       *   return false;
60699       * }
60700       * </code>
60701       * </div>
60702       *
60703       * <div class="norender">
60704       * <code>
60705       * // returns a TouchEvent object
60706       * // as a callback argument
60707       * function touchMoved(event) {
60708       *   console.log(event);
60709       * }
60710       * </code>
60711       * </div>
60712       *
60713       * @alt
60714       * 50x50 black rect turns lighter with touch until white. resets
60715       * no image displayed
60716       *
60717       */
60718
60719
60720      p5.prototype._ontouchmove = function (e) {
60721        var context = this._isGlobal ? window : this;
60722        var executeDefault;
60723
60724        this._updateTouchCoords(e);
60725
60726        this._updateNextMouseCoords(e);
60727
60728        if (typeof context.touchMoved === 'function') {
60729          executeDefault = context.touchMoved(e);
60730
60731          if (executeDefault === false) {
60732            e.preventDefault();
60733          }
60734        } else if (typeof context.mouseDragged === 'function') {
60735          executeDefault = context.mouseDragged(e);
60736
60737          if (executeDefault === false) {
60738            e.preventDefault();
60739          }
60740        }
60741      };
60742      /**
60743       * The <a href="#/p5/touchEnded">touchEnded()</a> function is called every time a touch ends. If no
60744       * <a href="#/p5/touchEnded">touchEnded()</a> function is defined, the <a href="#/p5/mouseReleased">mouseReleased()</a> function will be
60745       * called instead if it is defined.<br><br>
60746       * Browsers may have different default behaviors attached to various touch
60747       * events. To prevent any default behavior for this event, add "return false"
60748       * to the end of the method.
60749       *
60750       * @method touchEnded
60751       * @param  {Object} [event] optional TouchEvent callback argument.
60752       * @example
60753       * <div>
60754       * <code>
60755       * // Release touch within the image to
60756       * // change the value of the rectangle
60757       *
60758       * let value = 0;
60759       * function draw() {
60760       *   fill(value);
60761       *   rect(25, 25, 50, 50);
60762       * }
60763       * function touchEnded() {
60764       *   if (value === 0) {
60765       *     value = 255;
60766       *   } else {
60767       *     value = 0;
60768       *   }
60769       * }
60770       * </code>
60771       * </div>
60772       *
60773       * <div class="norender">
60774       * <code>
60775       * function touchEnded() {
60776       *   ellipse(mouseX, mouseY, 5, 5);
60777       *   // prevent default
60778       *   return false;
60779       * }
60780       * </code>
60781       * </div>
60782       *
60783       * <div class="norender">
60784       * <code>
60785       * // returns a TouchEvent object
60786       * // as a callback argument
60787       * function touchEnded(event) {
60788       *   console.log(event);
60789       * }
60790       * </code>
60791       * </div>
60792       *
60793       * @alt
60794       * 50x50 black rect turns white with touch.
60795       * no image displayed
60796       *
60797       */
60798
60799
60800      p5.prototype._ontouchend = function (e) {
60801        this._setProperty('mouseIsPressed', false);
60802
60803        this._updateTouchCoords(e);
60804
60805        this._updateNextMouseCoords(e);
60806
60807        var context = this._isGlobal ? window : this;
60808        var executeDefault;
60809
60810        if (typeof context.touchEnded === 'function') {
60811          executeDefault = context.touchEnded(e);
60812
60813          if (executeDefault === false) {
60814            e.preventDefault();
60815          }
60816        } else if (typeof context.mouseReleased === 'function') {
60817          executeDefault = context.mouseReleased(e);
60818
60819          if (executeDefault === false) {
60820            e.preventDefault();
60821          }
60822        }
60823      };
60824
60825      module.exports = p5;
60826    }, {
60827      "../core/main": 24
60828    }],
60829    42: [function (_dereq_, module, exports) {
60830      /*global ImageData:false */
60831
60832      /**
60833       * This module defines the filters for use with image buffers.
60834       *
60835       * This module is basically a collection of functions stored in an object
60836       * as opposed to modules. The functions are destructive, modifying
60837       * the passed in canvas rather than creating a copy.
60838       *
60839       * Generally speaking users of this module will use the Filters.apply method
60840       * on a canvas to create an effect.
60841       *
60842       * A number of functions are borrowed/adapted from
60843       * http://www.html5rocks.com/en/tutorials/canvas/imagefilters/
60844       * or the java processing implementation.
60845       */
60846      'use strict';
60847
60848      var Filters = {};
60849      /*
60850       * Helper functions
60851       */
60852
60853      /**
60854       * Returns the pixel buffer for a canvas
60855       *
60856       * @private
60857       *
60858       * @param  {Canvas|ImageData} canvas the canvas to get pixels from
60859       * @return {Uint8ClampedArray}       a one-dimensional array containing
60860       *                                   the data in thc RGBA order, with integer
60861       *                                   values between 0 and 255
60862       */
60863
60864      Filters._toPixels = function (canvas) {
60865        if (canvas instanceof ImageData) {
60866          return canvas.data;
60867        } else {
60868          return canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height).data;
60869        }
60870      };
60871      /**
60872       * Returns a 32 bit number containing ARGB data at ith pixel in the
60873       * 1D array containing pixels data.
60874       *
60875       * @private
60876       *
60877       * @param  {Uint8ClampedArray} data array returned by _toPixels()
60878       * @param  {Integer}           i    index of a 1D Image Array
60879       * @return {Integer}                32 bit integer value representing
60880       *                                  ARGB value.
60881       */
60882
60883
60884      Filters._getARGB = function (data, i) {
60885        var offset = i * 4;
60886        return data[offset + 3] << 24 & 0xff000000 | data[offset] << 16 & 0x00ff0000 | data[offset + 1] << 8 & 0x0000ff00 | data[offset + 2] & 0x000000ff;
60887      };
60888      /**
60889       * Modifies pixels RGBA values to values contained in the data object.
60890       *
60891       * @private
60892       *
60893       * @param {Uint8ClampedArray} pixels array returned by _toPixels()
60894       * @param {Int32Array}        data   source 1D array where each value
60895       *                                   represents ARGB values
60896       */
60897
60898
60899      Filters._setPixels = function (pixels, data) {
60900        var offset = 0;
60901
60902        for (var i = 0, al = pixels.length; i < al; i++) {
60903          offset = i * 4;
60904          pixels[offset + 0] = (data[i] & 0x00ff0000) >>> 16;
60905          pixels[offset + 1] = (data[i] & 0x0000ff00) >>> 8;
60906          pixels[offset + 2] = data[i] & 0x000000ff;
60907          pixels[offset + 3] = (data[i] & 0xff000000) >>> 24;
60908        }
60909      };
60910      /**
60911       * Returns the ImageData object for a canvas
60912       * https://developer.mozilla.org/en-US/docs/Web/API/ImageData
60913       *
60914       * @private
60915       *
60916       * @param  {Canvas|ImageData} canvas canvas to get image data from
60917       * @return {ImageData}               Holder of pixel data (and width and
60918       *                                   height) for a canvas
60919       */
60920
60921
60922      Filters._toImageData = function (canvas) {
60923        if (canvas instanceof ImageData) {
60924          return canvas;
60925        } else {
60926          return canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
60927        }
60928      };
60929      /**
60930       * Returns a blank ImageData object.
60931       *
60932       * @private
60933       *
60934       * @param  {Integer} width
60935       * @param  {Integer} height
60936       * @return {ImageData}
60937       */
60938
60939
60940      Filters._createImageData = function (width, height) {
60941        Filters._tmpCanvas = document.createElement('canvas');
60942        Filters._tmpCtx = Filters._tmpCanvas.getContext('2d');
60943        return this._tmpCtx.createImageData(width, height);
60944      };
60945      /**
60946       * Applys a filter function to a canvas.
60947       *
60948       * The difference between this and the actual filter functions defined below
60949       * is that the filter functions generally modify the pixel buffer but do
60950       * not actually put that data back to the canvas (where it would actually
60951       * update what is visible). By contrast this method does make the changes
60952       * actually visible in the canvas.
60953       *
60954       * The apply method is the method that callers of this module would generally
60955       * use. It has been separated from the actual filters to support an advanced
60956       * use case of creating a filter chain that executes without actually updating
60957       * the canvas in between everystep.
60958       *
60959       * @private
60960       * @param  {HTMLCanvasElement} canvas [description]
60961       * @param  {function(ImageData,Object)} func   [description]
60962       * @param  {Object} filterParam  [description]
60963       */
60964
60965
60966      Filters.apply = function (canvas, func, filterParam) {
60967        var ctx = canvas.getContext('2d');
60968        var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); //Filters can either return a new ImageData object, or just modify
60969        //the one they received.
60970
60971        var newImageData = func(imageData, filterParam);
60972
60973        if (newImageData instanceof ImageData) {
60974          ctx.putImageData(newImageData, 0, 0, 0, 0, canvas.width, canvas.height);
60975        } else {
60976          ctx.putImageData(imageData, 0, 0, 0, 0, canvas.width, canvas.height);
60977        }
60978      };
60979      /*
60980       * Filters
60981       */
60982
60983      /**
60984       * Converts the image to black and white pixels depending if they are above or
60985       * below the threshold defined by the level parameter. The parameter must be
60986       * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used.
60987       *
60988       * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/
60989       *
60990       * @private
60991       * @param  {Canvas} canvas
60992       * @param  {Float} level
60993       */
60994
60995
60996      Filters.threshold = function (canvas, level) {
60997        var pixels = Filters._toPixels(canvas);
60998
60999        if (level === undefined) {
61000          level = 0.5;
61001        }
61002
61003        var thresh = Math.floor(level * 255);
61004
61005        for (var i = 0; i < pixels.length; i += 4) {
61006          var r = pixels[i];
61007          var g = pixels[i + 1];
61008          var b = pixels[i + 2];
61009          var gray = 0.2126 * r + 0.7152 * g + 0.0722 * b;
61010          var val;
61011
61012          if (gray >= thresh) {
61013            val = 255;
61014          } else {
61015            val = 0;
61016          }
61017
61018          pixels[i] = pixels[i + 1] = pixels[i + 2] = val;
61019        }
61020      };
61021      /**
61022       * Converts any colors in the image to grayscale equivalents.
61023       * No parameter is used.
61024       *
61025       * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/
61026       *
61027       * @private
61028       * @param {Canvas} canvas
61029       */
61030
61031
61032      Filters.gray = function (canvas) {
61033        var pixels = Filters._toPixels(canvas);
61034
61035        for (var i = 0; i < pixels.length; i += 4) {
61036          var r = pixels[i];
61037          var g = pixels[i + 1];
61038          var b = pixels[i + 2]; // CIE luminance for RGB
61039
61040          var gray = 0.2126 * r + 0.7152 * g + 0.0722 * b;
61041          pixels[i] = pixels[i + 1] = pixels[i + 2] = gray;
61042        }
61043      };
61044      /**
61045       * Sets the alpha channel to entirely opaque. No parameter is used.
61046       *
61047       * @private
61048       * @param {Canvas} canvas
61049       */
61050
61051
61052      Filters.opaque = function (canvas) {
61053        var pixels = Filters._toPixels(canvas);
61054
61055        for (var i = 0; i < pixels.length; i += 4) {
61056          pixels[i + 3] = 255;
61057        }
61058
61059        return pixels;
61060      };
61061      /**
61062       * Sets each pixel to its inverse value. No parameter is used.
61063       * @private
61064       * @param  {Canvas} canvas
61065       */
61066
61067
61068      Filters.invert = function (canvas) {
61069        var pixels = Filters._toPixels(canvas);
61070
61071        for (var i = 0; i < pixels.length; i += 4) {
61072          pixels[i] = 255 - pixels[i];
61073          pixels[i + 1] = 255 - pixels[i + 1];
61074          pixels[i + 2] = 255 - pixels[i + 2];
61075        }
61076      };
61077      /**
61078       * Limits each channel of the image to the number of colors specified as
61079       * the parameter. The parameter can be set to values between 2 and 255, but
61080       * results are most noticeable in the lower ranges.
61081       *
61082       * Adapted from java based processing implementation
61083       *
61084       * @private
61085       * @param  {Canvas} canvas
61086       * @param  {Integer} level
61087       */
61088
61089
61090      Filters.posterize = function (canvas, level) {
61091        var pixels = Filters._toPixels(canvas);
61092
61093        if (level < 2 || level > 255) {
61094          throw new Error('Level must be greater than 2 and less than 255 for posterize');
61095        }
61096
61097        var levels1 = level - 1;
61098
61099        for (var i = 0; i < pixels.length; i += 4) {
61100          var rlevel = pixels[i];
61101          var glevel = pixels[i + 1];
61102          var blevel = pixels[i + 2];
61103          pixels[i] = (rlevel * level >> 8) * 255 / levels1;
61104          pixels[i + 1] = (glevel * level >> 8) * 255 / levels1;
61105          pixels[i + 2] = (blevel * level >> 8) * 255 / levels1;
61106        }
61107      };
61108      /**
61109       * reduces the bright areas in an image
61110       * @private
61111       * @param  {Canvas} canvas
61112       *
61113       */
61114
61115
61116      Filters.dilate = function (canvas) {
61117        var pixels = Filters._toPixels(canvas);
61118
61119        var currIdx = 0;
61120        var maxIdx = pixels.length ? pixels.length / 4 : 0;
61121        var out = new Int32Array(maxIdx);
61122        var currRowIdx, maxRowIdx, colOrig, colOut, currLum;
61123        var idxRight, idxLeft, idxUp, idxDown;
61124        var colRight, colLeft, colUp, colDown;
61125        var lumRight, lumLeft, lumUp, lumDown;
61126
61127        while (currIdx < maxIdx) {
61128          currRowIdx = currIdx;
61129          maxRowIdx = currIdx + canvas.width;
61130
61131          while (currIdx < maxRowIdx) {
61132            colOrig = colOut = Filters._getARGB(pixels, currIdx);
61133            idxLeft = currIdx - 1;
61134            idxRight = currIdx + 1;
61135            idxUp = currIdx - canvas.width;
61136            idxDown = currIdx + canvas.width;
61137
61138            if (idxLeft < currRowIdx) {
61139              idxLeft = currIdx;
61140            }
61141
61142            if (idxRight >= maxRowIdx) {
61143              idxRight = currIdx;
61144            }
61145
61146            if (idxUp < 0) {
61147              idxUp = 0;
61148            }
61149
61150            if (idxDown >= maxIdx) {
61151              idxDown = currIdx;
61152            }
61153
61154            colUp = Filters._getARGB(pixels, idxUp);
61155            colLeft = Filters._getARGB(pixels, idxLeft);
61156            colDown = Filters._getARGB(pixels, idxDown);
61157            colRight = Filters._getARGB(pixels, idxRight); //compute luminance
61158
61159            currLum = 77 * (colOrig >> 16 & 0xff) + 151 * (colOrig >> 8 & 0xff) + 28 * (colOrig & 0xff);
61160            lumLeft = 77 * (colLeft >> 16 & 0xff) + 151 * (colLeft >> 8 & 0xff) + 28 * (colLeft & 0xff);
61161            lumRight = 77 * (colRight >> 16 & 0xff) + 151 * (colRight >> 8 & 0xff) + 28 * (colRight & 0xff);
61162            lumUp = 77 * (colUp >> 16 & 0xff) + 151 * (colUp >> 8 & 0xff) + 28 * (colUp & 0xff);
61163            lumDown = 77 * (colDown >> 16 & 0xff) + 151 * (colDown >> 8 & 0xff) + 28 * (colDown & 0xff);
61164
61165            if (lumLeft > currLum) {
61166              colOut = colLeft;
61167              currLum = lumLeft;
61168            }
61169
61170            if (lumRight > currLum) {
61171              colOut = colRight;
61172              currLum = lumRight;
61173            }
61174
61175            if (lumUp > currLum) {
61176              colOut = colUp;
61177              currLum = lumUp;
61178            }
61179
61180            if (lumDown > currLum) {
61181              colOut = colDown;
61182              currLum = lumDown;
61183            }
61184
61185            out[currIdx++] = colOut;
61186          }
61187        }
61188
61189        Filters._setPixels(pixels, out);
61190      };
61191      /**
61192       * increases the bright areas in an image
61193       * @private
61194       * @param  {Canvas} canvas
61195       *
61196       */
61197
61198
61199      Filters.erode = function (canvas) {
61200        var pixels = Filters._toPixels(canvas);
61201
61202        var currIdx = 0;
61203        var maxIdx = pixels.length ? pixels.length / 4 : 0;
61204        var out = new Int32Array(maxIdx);
61205        var currRowIdx, maxRowIdx, colOrig, colOut, currLum;
61206        var idxRight, idxLeft, idxUp, idxDown;
61207        var colRight, colLeft, colUp, colDown;
61208        var lumRight, lumLeft, lumUp, lumDown;
61209
61210        while (currIdx < maxIdx) {
61211          currRowIdx = currIdx;
61212          maxRowIdx = currIdx + canvas.width;
61213
61214          while (currIdx < maxRowIdx) {
61215            colOrig = colOut = Filters._getARGB(pixels, currIdx);
61216            idxLeft = currIdx - 1;
61217            idxRight = currIdx + 1;
61218            idxUp = currIdx - canvas.width;
61219            idxDown = currIdx + canvas.width;
61220
61221            if (idxLeft < currRowIdx) {
61222              idxLeft = currIdx;
61223            }
61224
61225            if (idxRight >= maxRowIdx) {
61226              idxRight = currIdx;
61227            }
61228
61229            if (idxUp < 0) {
61230              idxUp = 0;
61231            }
61232
61233            if (idxDown >= maxIdx) {
61234              idxDown = currIdx;
61235            }
61236
61237            colUp = Filters._getARGB(pixels, idxUp);
61238            colLeft = Filters._getARGB(pixels, idxLeft);
61239            colDown = Filters._getARGB(pixels, idxDown);
61240            colRight = Filters._getARGB(pixels, idxRight); //compute luminance
61241
61242            currLum = 77 * (colOrig >> 16 & 0xff) + 151 * (colOrig >> 8 & 0xff) + 28 * (colOrig & 0xff);
61243            lumLeft = 77 * (colLeft >> 16 & 0xff) + 151 * (colLeft >> 8 & 0xff) + 28 * (colLeft & 0xff);
61244            lumRight = 77 * (colRight >>
61244 16 & 0xff) + 151 * (colRight >> 8 & 0xff) + 28 * (colRight & 0xff);
61245            lumUp = 77 * (colUp >> 16 & 0xff) + 151 * (colUp >> 8 & 0xff) + 28 * (colUp & 0xff);
61246            lumDown = 77 * (colDown >> 16 & 0xff) + 151 * (colDown >> 8 & 0xff) + 28 * (colDown & 0xff);
61247
61248            if (lumLeft < currLum) {
61249              colOut = colLeft;
61250              currLum = lumLeft;
61251            }
61252
61253            if (lumRight < currLum) {
61254              colOut = colRight;
61255              currLum = lumRight;
61256            }
61257
61258            if (lumUp < currLum) {
61259              colOut = colUp;
61260              currLum = lumUp;
61261            }
61262
61263            if (lumDown < currLum) {
61264              colOut = colDown;
61265              currLum = lumDown;
61266            }
61267
61268            out[currIdx++] = colOut;
61269          }
61270        }
61271
61272        Filters._setPixels(pixels, out);
61273      }; // BLUR
61274      // internal kernel stuff for the gaussian blur filter
61275
61276
61277      var blurRadius;
61278      var blurKernelSize;
61279      var blurKernel;
61280      var blurMult;
61281      /*
61282       * Port of https://github.com/processing/processing/blob/
61283       * master/core/src/processing/core/PImage.java#L1250
61284       *
61285       * Optimized code for building the blur kernel.
61286       * further optimized blur code (approx. 15% for radius=20)
61287       * bigger speed gains for larger radii (~30%)
61288       * added support for various image types (ALPHA, RGB, ARGB)
61289       * [toxi 050728]
61290       */
61291
61292      function buildBlurKernel(r) {
61293        var radius = r * 3.5 | 0;
61294        radius = radius < 1 ? 1 : radius < 248 ? radius : 248;
61295
61296        if (blurRadius !== radius) {
61297          blurRadius = radius;
61298          blurKernelSize = 1 + blurRadius << 1;
61299          blurKernel = new Int32Array(blurKernelSize);
61300          blurMult = new Array(blurKernelSize);
61301
61302          for (var l = 0; l < blurKernelSize; l++) {
61303            blurMult[l] = new Int32Array(256);
61304          }
61305
61306          var bk, bki;
61307          var bm, bmi;
61308
61309          for (var i = 1, radiusi = radius - 1; i < radius; i++) {
61310            blurKernel[radius + i] = blurKernel[radiusi] = bki = radiusi * radiusi;
61311            bm = blurMult[radius + i];
61312            bmi = blurMult[radiusi--];
61313
61314            for (var j = 0; j < 256; j++) {
61315              bm[j] = bmi[j] = bki * j;
61316            }
61317          }
61318
61319          bk = blurKernel[radius] = radius * radius;
61320          bm = blurMult[radius];
61321
61322          for (var k = 0; k < 256; k++) {
61323            bm[k] = bk * k;
61324          }
61325        }
61326      } // Port of https://github.com/processing/processing/blob/
61327      // master/core/src/processing/core/PImage.java#L1433
61328
61329
61330      function blurARGB(canvas, radius) {
61331        var pixels = Filters._toPixels(canvas);
61332
61333        var width = canvas.width;
61334        var height = canvas.height;
61335        var numPackedPixels = width * height;
61336        var argb = new Int32Array(numPackedPixels);
61337
61338        for (var j = 0; j < numPackedPixels; j++) {
61339          argb[j] = Filters._getARGB(pixels, j);
61340        }
61341
61342        var sum, cr, cg, cb, ca;
61343        var read, ri, ym, ymi, bk0;
61344        var a2 = new Int32Array(numPackedPixels);
61345        var r2 = new Int32Array(numPackedPixels);
61346        var g2 = new Int32Array(numPackedPixels);
61347        var b2 = new Int32Array(numPackedPixels);
61348        var yi = 0;
61349        buildBlurKernel(radius);
61350        var x, y, i;
61351        var bm;
61352
61353        for (y = 0; y < height; y++) {
61354          for (x = 0; x < width; x++) {
61355            cb = cg = cr = ca = sum = 0;
61356            read = x - blurRadius;
61357
61358            if (read < 0) {
61359              bk0 = -read;
61360              read = 0;
61361            } else {
61362              if (read >= width) {
61363                break;
61364              }
61365
61366              bk0 = 0;
61367            }
61368
61369            for (i = bk0; i < blurKernelSize; i++) {
61370              if (read >= width) {
61371                break;
61372              }
61373
61374              var c = argb[read + yi];
61375              bm = blurMult[i];
61376              ca += bm[(c & -16777216) >>> 24];
61377              cr += bm[(c & 16711680) >> 16];
61378              cg += bm[(c & 65280) >> 8];
61379              cb += bm[c & 255];
61380              sum += blurKernel[i];
61381              read++;
61382            }
61383
61384            ri = yi + x;
61385            a2[ri] = ca / sum;
61386            r2[ri] = cr / sum;
61387            g2[ri] = cg / sum;
61388            b2[ri] = cb / sum;
61389          }
61390
61391          yi += width;
61392        }
61393
61394        yi = 0;
61395        ym = -blurRadius;
61396        ymi = ym * width;
61397
61398        for (y = 0; y < height; y++) {
61399          for (x = 0; x < width; x++) {
61400            cb = cg = cr = ca = sum = 0;
61401
61402            if (ym < 0) {
61403              bk0 = ri = -ym;
61404              read = x;
61405            } else {
61406              if (ym >= height) {
61407                break;
61408              }
61409
61410              bk0 = 0;
61411              ri = ym;
61412              read = x + ymi;
61413            }
61414
61415            for (i = bk0; i < blurKernelSize; i++) {
61416              if (ri >= height) {
61417                break;
61418              }
61419
61420              bm = blurMult[i];
61421              ca += bm[a2[read]];
61422              cr += bm[r2[read]];
61423              cg += bm[g2[read]];
61424              cb += bm[b2[read]];
61425              sum += blurKernel[i];
61426              ri++;
61427              read += width;
61428            }
61429
61430            argb[x + yi] = ca / sum << 24 | cr / sum << 16 | cg / sum << 8 | cb / sum;
61431          }
61432
61433          yi += width;
61434          ymi += width;
61435          ym++;
61436        }
61437
61438        Filters._setPixels(pixels, argb);
61439      }
61440
61441      Filters.blur = function (canvas, radius) {
61442        blurARGB(canvas, radius);
61443      };
61444
61445      module.exports = Filters;
61446    }, {}],
61447    43: [function (_dereq_, module, exports) {
61448      /**
61449       * @module Image
61450       * @submodule Image
61451       * @for p5
61452       * @requires core
61453       */
61454
61455      /**
61456       * This module defines the p5 methods for the <a href="#/p5.Image">p5.Image</a> class
61457       * for drawing images to the main display canvas.
61458       */
61459      'use strict';
61460
61461      var p5 = _dereq_('../core/main'); // This is not global, but ESLint is not aware that
61462      // this module is implicitly enclosed with Browserify: this overrides the
61463      // redefined-global error and permits using the name "frames" for the array
61464      // of saved animation frames.
61465
61466      /* global frames:true */
61467
61468
61469      var frames = [];
61470      /**
61471       * Creates a new <a href="#/p5.Image">p5.Image</a> (the datatype for storing images). This provides a
61472       * fresh buffer of pixels to play with. Set the size of the buffer with the
61473       * width and height parameters.
61474       * <br><br>
61475       * .<a href="#/p5.Image/pixels">pixels</a> gives access to an array containing the values for all the pixels
61476       * in the display window.
61477       * These values are numbers. This array is the size (including an appropriate
61478       * factor for the <a href="#/p5/pixelDensity">pixelDensity</a>) of the display window x4,
61479       * representing the R, G, B, A values in order for each pixel, mov
61479ing from
61480       * left to right across each row, then down each column. See .<a href="#/p5.Image/pixels">pixels</a> for
61481       * more info. It may also be simpler to use <a href="#/p5.Image/set">set()</a> or <a href="#/p5.Image/get">get()</a>.
61482       * <br><br>
61483       * Before accessing the pixels of an image, the data must loaded with the
61484       * <a href="#/p5.Image/loadPixels">loadPixels()</a> function. After the array data has been modified, the
61485       * <a href="#/p5.Image/updatePixels">updatePixels()</a> function must be run to update the changes.
61486       *
61487       * @method createImage
61488       * @param  {Integer} width  width in pixels
61489       * @param  {Integer} height height in pixels
61490       * @return {p5.Image}       the <a href="#/p5.Image">p5.Image</a> object
61491       * @example
61492       * <div>
61493       * <code>
61494       * let img = createImage(66, 66);
61495       * img.loadPixels();
61496       * for (let i = 0; i < img.width; i++) {
61497       *   for (let j = 0; j < img.height; j++) {
61498       *     img.set(i, j, color(0, 90, 102));
61499       *   }
61500       * }
61501       * img.updatePixels();
61502       * image(img, 17, 17);
61503       * </code>
61504       * </div>
61505       *
61506       * <div>
61507       * <code>
61508       * let img = createImage(66, 66);
61509       * img.loadPixels();
61510       * for (let i = 0; i < img.width; i++) {
61511       *   for (let j = 0; j < img.height; j++) {
61512       *     img.set(i, j, color(0, 90, 102, (i % img.width) * 2));
61513       *   }
61514       * }
61515       * img.updatePixels();
61516       * image(img, 17, 17);
61517       * image(img, 34, 34);
61518       * </code>
61519       * </div>
61520       *
61521       * <div>
61522       * <code>
61523       * let pink = color(255, 102, 204);
61524       * let img = createImage(66, 66);
61525       * img.loadPixels();
61526       * let d = pixelDensity();
61527       * let halfImage = 4 * (img.width * d) * (img.height / 2 * d);
61528       * for (let i = 0; i < halfImage; i += 4) {
61529       *   img.pixels[i] = red(pink);
61530       *   img.pixels[i + 1] = green(pink);
61531       *   img.pixels[i + 2] = blue(pink);
61532       *   img.pixels[i + 3] = alpha(pink);
61533       * }
61534       * img.updatePixels();
61535       * image(img, 17, 17);
61536       * </code>
61537       * </div>
61538       *
61539       * @alt
61540       * 66x66 dark turquoise rect in center of canvas.
61541       * 2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas
61542       * no image displayed
61543       *
61544       */
61545
61546      p5.prototype.createImage = function (width, height) {
61547        p5._validateParameters('createImage', arguments);
61548
61549        return new p5.Image(width, height);
61550      };
61551      /**
61552       *  Save the current canvas as an image. The browser will either save the
61553       *  file immediately, or prompt the user with a dialogue window.
61554       *
61555       *  @method saveCanvas
61556       *  @param  {p5.Element|HTMLCanvasElement} selectedCanvas   a variable
61557       *                                  representing a specific html5 canvas (optional)
61558       *  @param  {String} [filename]
61559       *  @param  {String} [extension]      'jpg' or 'png'
61560       *
61561       *  @example
61562       * <div class='norender notest'><code>
61563       * function setup() {
61564       *   let c = createCanvas(100, 100);
61565       *   background(255, 0, 0);
61566       *   saveCanvas(c, 'myCanvas', 'jpg');
61567       * }
61568       * </code></div>
61569       * <div class='norender notest'><code>
61570       * // note that this example has the same result as above
61571       * // if no canvas is specified, defaults to main canvas
61572       * function setup() {
61573       *   let c = createCanvas(100, 100);
61574       *   background(255, 0, 0);
61575       *   saveCanvas('myCanvas', 'jpg');
61576       *
61577       *   // all of the following are valid
61578       *   saveCanvas(c, 'myCanvas', 'jpg');
61579       *   saveCanvas(c, 'myCanvas.jpg');
61580       *   saveCanvas(c, 'myCanvas');
61581       *   saveCanvas(c);
61582       *   saveCanvas('myCanvas', 'png');
61583       *   saveCanvas('myCanvas');
61584       *   saveCanvas();
61585       * }
61586       * </code></div>
61587       *
61588       * @alt
61589       * no image displayed
61590       * no image displayed
61591       * no image displayed
61592       */
61593
61594      /**
61595       *  @method saveCanvas
61596       *  @param  {String} [filename]
61597       *  @param  {String} [extension]
61598       */
61599
61600
61601      p5.prototype.saveCanvas = function () {
61602        p5._validateParameters('saveCanvas', arguments); // copy arguments to array
61603
61604
61605        var args = [].slice.call(arguments);
61606        var htmlCanvas, filename, extension;
61607
61608        if (arguments[0] instanceof HTMLCanvasElement) {
61609          htmlCanvas = arguments[0];
61610          args.shift();
61611        } else if (arguments[0] instanceof p5.Element) {
61612          htmlCanvas = arguments[0].elt;
61613          args.shift();
61614        } else {
61615          htmlCanvas = this._curElement && this._curElement.elt;
61616        }
61617
61618        if (args.length >= 1) {
61619          filename = args[0];
61620        }
61621
61622        if (args.length >= 2) {
61623          extension = args[1];
61624        }
61625
61626        extension = extension || p5.prototype._checkFileExtension(filename, extension)[1] || 'png';
61627        var mimeType;
61628
61629        switch (extension) {
61630          default:
61631            //case 'png':
61632            mimeType = 'image/png';
61633            break;
61634
61635          case 'jpeg':
61636          case 'jpg':
61637            mimeType = 'image/jpeg';
61638            break;
61639        }
61640
61641        htmlCanvas.toBlob(function (blob) {
61642          p5.prototype.downloadFile(blob, filename, extension);
61643        }, mimeType);
61644      };
61645      /**
61646       *  Capture a sequence of frames that can be used to create a movie.
61647       *  Accepts a callback. For example, you may wish to send the frames
61648       *  to a server where they can be stored or converted into a movie.
61649       *  If no callback is provided, the browser will pop up save dialogues in an
61650       *  attempt to download all of the images that have just been created. With the
61651       *  callback provided the image data isn't saved by default but instead passed
61652       *  as an argument to the callback function as an array of objects, with the
61653       *  size of array equal to the total number of frames.
61654       *
61655       *  Note that <a href="#/p5.Image/saveFrames">saveFrames()</a> will only save the first 15 frames of an animation.
61656       *  To export longer animations, you might look into a library like
61657       *  <a href="https://github.com/spite/ccapture.js/">ccapture.js</a>.
61658       *
61659       *  @method saveFrames
61660       *  @param  {String}   filename
61661       *  @param  {String}   extension 'jpg' or 'png'
61662       *  @param  {Number}   duration  Duration in seconds to save the frames for.
61663       *  @param  {Number}   framerate  Framerate to save the frames in.
61664       *  @param  {function(Array)} [callback] A callback function that will be executed
61665                                        to handle the image data. This function
61666                                        should accept an array as argument. The
61667                                        array will contain the specified number of
61668                                        frames of objects. Each object has three
61669                                        properties: imageData - an
61670                                        image/octet-stream, filename and extension.
61671       *  @example
61672       *  <div><code>
61673       * function draw() {
61674       *   background(mouseX);
61675       * }
61676       *
61677       * function mousePressed() {
61678       *   saveFrames('out', 'png', 1, 25, data => {
61679       *     print(data);
61680       *   });
61681       * }
61682      </code></div>
61683       *
61684       * @alt
61685       * canvas background goes from light to dark with mouse x.
61686       *
61687       */
61688
61689
61690      p5.prototype.saveFrames = function (fName, ext, _duration, _fps, callback) {
61691        p5._validateParameters('saveFrames', arguments);
61692
61693        var duration = _duration || 3;
61694        duration = p5.prototype.constrain(duration, 0, 15);
61695        duration = duration * 1000;
61696        var fps = _fps || 15;
61697        fps = p5.prototype.constrain(fps, 0, 22);
61698        var count = 0;
61699        var makeFrame = p5.prototype._makeFrame;
61700        var cnv = this._curElement.elt;
61701        var frameFactory = setInterval(function () {
61702          makeFrame(fName + count, ext, cnv);
61703          count++;
61704        }, 1000 / fps);
61705        setTimeout(function () {
61706          clearInterval(frameFactory);
61707
61708          if (callback) {
61709            callback(frames);
61710          } else {
61711            for (var i = 0; i < frames.length; i++) {
61712              var f = frames[i];
61713              p5.prototype.downloadFile(f.imageData, f.filename, f.ext);
61714            }
61715          }
61716
61717          frames = []; // clear frames
61718        }, duration + 0.01);
61719      };
61720
61721      p5.prototype._makeFrame = function (filename, extension, _cnv) {
61722        var cnv;
61723
61724        if (this) {
61725          cnv = this._curElement.elt;
61726        } else {
61727          cnv = _cnv;
61728        }
61729
61730        var mimeType;
61731
61732        if (!extension) {
61733          extension = 'png';
61734          mimeType = 'image/png';
61735        } else {
61736          switch (extension.toLowerCase()) {
61737            case 'png':
61738              mimeType = 'image/png';
61739              break;
61740
61741            case 'jpeg':
61742              mimeType = 'image/jpeg';
61743              break;
61744
61745            case 'jpg':
61746              mimeType = 'image/jpeg';
61747              break;
61748
61749            default:
61750              mimeType = 'image/png';
61751              break;
61752          }
61753        }
61754
61755        var downloadMime = 'image/octet-stream';
61756        var imageData = cnv.toDataURL(mimeType);
61757        imageData = imageData.replace(mimeType, downloadMime);
61758        var thisFrame = {};
61759        thisFrame.imageData = imageData;
61760        thisFrame.filename = filename;
61761        thisFrame.ext = extension;
61762        frames.push(thisFrame);
61763      };
61764
61765      module.exports = p5;
61766    }, {
61767      "../core/main": 24
61768    }],
61769    44: [function (_dereq_, module, exports) {
61770      /**
61771       * @module Image
61772       * @submodule Loading & Displaying
61773       * @for p5
61774       * @requires core
61775       */
61776      'use strict';
61777
61778      var p5 = _dereq_('../core/main');
61779
61780      var Filters = _dereq_('./filters');
61781
61782      var canvas = _dereq_('../core/helpers');
61783
61784      var constants = _dereq_('../core/constants');
61785
61786      _dereq_('../core/error_helpers');
61787      /**
61788       * Loads an image from a path and creates a <a href="#/p5.Image">p5.Image</a> from it.
61789       * <br><br>
61790       * The image may not be immediately available for rendering
61791       * If you want to ensure that the image is ready before doing
61792       * anything with it, place the <a href="#/p5/loadImage">loadImage()</a> call in <a href="#/p5/preload">preload()</a>.
61793       * You may also supply a callback function to handle the image when it's ready.
61794       * <br><br>
61795       * The path to the image should be relative to the HTML file
61796       * that links in your sketch. Loading an image from a URL or other
61797       * remote location may be blocked due to your browser's built-in
61798       * security.
61799       *
61800       * @method loadImage
61801       * @param  {String} path Path of the image to be loaded
61802       * @param  {function(p5.Image)} [successCallback] Function to be called once
61803       *                                the image is loaded. Will be passed the
61804       *                                <a href="#/p5.Image">p5.Image</a>.
61805       * @param  {function(Event)}    [failureCallback] called with event error if
61806       *                                the image fails to load.
61807       * @return {p5.Image}             the <a href="#/p5.Image">p5.Image</a> object
61808       * @example
61809       * <div>
61810       * <code>
61811       * let img;
61812       * function preload() {
61813       *   img = loadImage('assets/laDefense.jpg');
61814       * }
61815       * function setup() {
61816       *   image(img, 0, 0);
61817       * }
61818       * </code>
61819       * </div>
61820       * <div>
61821       * <code>
61822       * function setup() {
61823       *   // here we use a callback to display the image after loading
61824       *   loadImage('assets/laDefense.jpg', img => {
61825       *     image(img, 0, 0);
61826       *   });
61827       * }
61828       * </code>
61829       * </div>
61830       *
61831       * @alt
61832       * image of the underside of a white umbrella and grided ceililng above
61833       * image of the underside of a white umbrella and grided ceililng above
61834       *
61835       */
61836
61837
61838      p5.prototype.loadImage = function (path, successCallback, failureCallback) {
61839        p5._validateParameters('loadImage', arguments);
61840
61841        var img = new Image();
61842        var pImg = new p5.Image(1, 1, this);
61843        var self = this;
61844
61845        img.onload = function () {
61846          pImg.width = pImg.canvas.width = img.width;
61847          pImg.height = pImg.canvas.height = img.height; // Draw the image into the backing canvas of the p5.Image
61848
61849          pImg.drawingContext.drawImage(img, 0, 0);
61850          pImg.modified = true;
61851
61852          if (typeof successCallback === 'function') {
61853            successCallback(pImg);
61854          }
61855
61856          self._decrementPreload();
61857        };
61858
61859        img.onerror = function (e) {
61860          p5._friendlyFileLoadError(0, img.src);
61861
61862          if (typeof failureCallback === 'function') {
61863            failureCallback(e);
61864          } else {
61865            console.error(e);
61866          }
61867        }; // Set crossOrigin in case image is served with CORS headers.
61868        // This will let us draw to the canvas without tainting it.
61869        // See https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
61870        // When using data-uris the file will be loaded locally
61871        // so we don't need to worry about crossOrigin with base64 file types.
61872
61873
61874        if (path.indexOf('data:image/') !== 0) {
61875          img.crossOrigin = 'Anonymous';
61876        } // start loading the image
61877
61878
61879        img.src = path;
61880        return pImg;
61881      };
61882      /**
61883       * Validates clipping params. Per drawImage spec sWidth and sHight cannot be
61884       * negative or greater than image intrinsic width and height
61885       * @private
61886       * @param {Number} sVal
61887       * @param {Number} iVal
61888       * @returns {Number}
61889       * @private
61890       */
61891
61892
61893      function _sAssign(sVal, iVal) {
61894        if (sVal > 0 && sVal < iVal) {
61895          return sVal;
61896        } else {
61897          return iVal;
61898        }
61899      }
61900      /**
61901       * Draw an image to the p5.js canvas.
61902       *
61903       * This function can be used with different numbers of parameters. The
61904       * simplest use requires only three parameters: img, x, and 
61904y—where (x, y) is
61905       * the position of the image. Two more parameters can optionally be added to
61906       * specify the width and height of the image.
61907       *
61908       * This function can also be used with all eight Number parameters. To
61909       * differentiate between all these parameters, p5.js uses the language of
61910       * "destination rectangle" (which corresponds to "dx", "dy", etc.) and "source
61911       * image" (which corresponds to "sx", "sy", etc.) below. Specifying the
61912       * "source image" dimensions can be useful when you want to display a
61913       * subsection of the source image instead of the whole thing. Here's a diagram
61914       * to explain further:
61915       * <img src="assets/drawImage.png"></img>
61916       *
61917       * @method image
61918       * @param  {p5.Image|p5.Element} img    the image to display
61919       * @param  {Number}   x     the x-coordinate of the top-left corner of the image
61920       * @param  {Number}   y     the y-coordinate of the top-left corner of the image
61921       * @param  {Number}   [width]  the width to draw the image
61922       * @param  {Number}   [height] the height to draw the image
61923       * @example
61924       * <div>
61925       * <code>
61926       * let img;
61927       * function preload() {
61928       *   img = loadImage('assets/laDefense.jpg');
61929       * }
61930       * function setup() {
61931       *   // Top-left corner of the img is at (0, 0)
61932       *   // Width and height are the img's original width and height
61933       *   image(img, 0, 0);
61934       * }
61935       * </code>
61936       * </div>
61937       * <div>
61938       * <code>
61939       * let img;
61940       * function preload() {
61941       *   img = loadImage('assets/laDefense.jpg');
61942       * }
61943       * function setup() {
61944       *   background(50);
61945       *   // Top-left corner of the img is at (10, 10)
61946       *   // Width and height are 50 x 50
61947       *   image(img, 10, 10, 50, 50);
61948       * }
61949       * </code>
61950       * </div>
61951       * <div>
61952       * <code>
61953       * function setup() {
61954       *   // Here, we use a callback to display the image after loading
61955       *   loadImage('assets/laDefense.jpg', img => {
61956       *     image(img, 0, 0);
61957       *   });
61958       * }
61959       * </code>
61960       * </div>
61961       * <div>
61962       * <code>
61963       * let img;
61964       * function preload() {
61965       *   img = loadImage('assets/gradient.png');
61966       * }
61967       * function setup() {
61968       *   // 1. Background image
61969       *   // Top-left corner of the img is at (0, 0)
61970       *   // Width and height are the img's original width and height, 100 x 100
61971       *   image(img, 0, 0);
61972       *   // 2. Top right image
61973       *   // Top-left corner of destination rectangle is at (50, 0)
61974       *   // Destination rectangle width and height are 40 x 20
61975       *   // The next parameters are relative to the source image:
61976       *   // - Starting at position (50, 50) on the source image, capture a 50 x 50
61977       *   // subsection
61978       *   // - Draw this subsection to fill the dimensions of the destination rectangle
61979       *   image(img, 50, 0, 40, 20, 50, 50, 50, 50);
61980       * }
61981       * </code>
61982       * </div>
61983       * @alt
61984       * image of the underside of a white umbrella and gridded ceiling above
61985       * image of the underside of a white umbrella and gridded ceiling above
61986       *
61987       */
61988
61989      /**
61990       * @method image
61991       * @param  {p5.Image|p5.Element} img
61992       * @param  {Number}   dx     the x-coordinate of the destination
61993       *                           rectangle in which to draw the source image
61994       * @param  {Number}   dy     the y-coordinate of the destination
61995       *                           rectangle in which to draw the source image
61996       * @param  {Number}   dWidth  the width of the destination rectangle
61997       * @param  {Number}   dHeight the height of the destination rectangle
61998       * @param  {Number}   sx     the x-coordinate of the subsection of the source
61999       * image to draw into the destination rectangle
62000       * @param  {Number}   sy     the y-coordinate of the subsection of the source
62001       * image to draw into the destination rectangle
62002       * @param {Number}    [sWidth] the width of the subsection of the
62003       *                           source image to draw into the destination
62004       *                           rectangle
62005       * @param {Number}    [sHeight] the height of the subsection of the
62006       *                            source image to draw into the destination rectangle
62007       */
62008
62009
62010      p5.prototype.image = function (img, dx, dy, dWidth, dHeight, sx, sy, sWidth, sHeight) {
62011        // set defaults per spec: https://goo.gl/3ykfOq
62012        p5._validateParameters('image', arguments);
62013
62014        var defW = img.width;
62015        var defH = img.height;
62016
62017        if (img.elt && img.elt.videoWidth && !img.canvas) {
62018          // video no canvas
62019          defW = img.elt.videoWidth;
62020          defH = img.elt.videoHeight;
62021        }
62022
62023        var _dx = dx;
62024        var _dy = dy;
62025
62026        var _dw = dWidth || defW;
62027
62028        var _dh = dHeight || defH;
62029
62030        var _sx = sx || 0;
62031
62032        var _sy = sy || 0;
62033
62034        var _sw = sWidth || defW;
62035
62036        var _sh = sHeight || defH;
62037
62038        _sw = _sAssign(_sw, defW);
62039        _sh = _sAssign(_sh, defH); // This part needs cleanup and unit tests
62040        // see issues https://github.com/processing/p5.js/issues/1741
62041        // and https://github.com/processing/p5.js/issues/1673
62042
62043        var pd = 1;
62044
62045        if (img.elt && !img.canvas && img.elt.style.width) {
62046          //if img is video and img.elt.size() has been used and
62047          //no width passed to image()
62048          if (img.elt.videoWidth && !dWidth) {
62049            pd = img.elt.videoWidth;
62050          } else {
62051            //all other cases
62052            pd = img.elt.width;
62053          }
62054
62055          pd /= parseInt(img.elt.style.width, 10);
62056        }
62057
62058        _sx *= pd;
62059        _sy *= pd;
62060        _sh *= pd;
62061        _sw *= pd;
62062        var vals = canvas.modeAdjust(_dx, _dy, _dw, _dh, this._renderer._imageMode); // tint the image if there is a tint
62063
62064        this._renderer.image(img, _sx, _sy, _sw, _sh, vals.x, vals.y, vals.w, vals.h);
62065      };
62066      /**
62067       * Sets the fill value for displaying images. Images can be tinted to
62068       * specified colors or made transparent by including an alpha value.
62069       * <br><br>
62070       * To apply transparency to an image without affecting its color, use
62071       * white as the tint color and specify an alpha value. For instance,
62072       * tint(255, 128) will make an image 50% transparent (assuming the default
62073       * alpha range of 0-255, which can be changed with <a href="#/p5/colorMode">colorMode()</a>).
62074       * <br><br>
62075       * The value for the gray parameter must be less than or equal to the current
62076       * maximum value as specified by <a href="#/p5/colorMode">colorMode()</a>. The default maximum value is
62077       * 255.
62078       *
62079       *
62080       * @method tint
62081       * @param  {Number}        v1      red or hue value relative to
62082       *                                 the current color range
62083       * @param  {Number}        v2      green or saturation value
62084       *                                 relative to the current color range
62085       * @param  {Number}        v3      blue or brightness value
62086       *                                 relative to the current color range
62087       * @param  {Number}        [alpha]
62088       *
62089       * @example
62090       * <div>
62091       * <code>
62092       * let img;
62093       * function preload() {
62094       *   img = loadImage('assets/laDefense.jpg');
62095       * }
62096       * function setup() {
62097       *   image(img, 0, 0);
62098       *   tint(0, 153, 204); // Tint blue
62099       *   image(img, 50, 0);
62100       * }
62101       * </code>
62102       * </div>
62103       *
62104       * <div>
62105       * <code>
62106       * let img;
62107       * function preload() {
62108       *   img = loadImage('assets/laDefense.jpg');
62109       * }
62110       * function setup() {
62111       *   image(img, 0, 0);
62112       *   tint(0, 153, 204, 126); // Tint blue and set transparency
62113       *   image(img, 50, 0);
62114       * }
62115       * </code>
62116       * </div>
62117       *
62118       * <div>
62119       * <code>
62120       * let img;
62121       * function preload() {
62122       *   img = loadImage('assets/laDefense.jpg');
62123       * }
62124       * function setup() {
62125       *   image(img, 0, 0);
62126       *   tint(255, 126); // Apply transparency without changing color
62127       *   image(img, 50, 0);
62128       * }
62129       * </code>
62130       * </div>
62131       *
62132       * @alt
62133       * 2 side by side images of umbrella and ceiling, one image with blue tint
62134       * Images of umbrella and ceiling, one half of image with blue tint
62135       * 2 side by side images of umbrella and ceiling, one image translucent
62136       *
62137       */
62138
62139      /**
62140       * @method tint
62141       * @param  {String}        value   a color string
62142       */
62143
62144      /**
62145       * @method tint
62146       * @param  {Number}        gray   a gray value
62147       * @param  {Number}        [alpha]
62148       */
62149
62150      /**
62151       * @method tint
62152       * @param  {Number[]}      values  an array containing the red,green,blue &
62153       *                                 and alpha components of the color
62154       */
62155
62156      /**
62157       * @method tint
62158       * @param  {p5.Color}      color   the tint color
62159       */
62160
62161
62162      p5.prototype.tint = function () {
62163        p5._validateParameters('tint', arguments);
62164
62165        var c = this.color.apply(this, arguments);
62166        this._renderer._tint = c.levels;
62167      };
62168      /**
62169       * Removes the current fill value for displaying images and reverts to
62170       * displaying images with their original hues.
62171       *
62172       * @method noTint
62173       * @example
62174       * <div>
62175       * <code>
62176       * let img;
62177       * function preload() {
62178       *   img = loadImage('assets/bricks.jpg');
62179       * }
62180       * function setup() {
62181       *   tint(0, 153, 204); // Tint blue
62182       *   image(img, 0, 0);
62183       *   noTint(); // Disable tint
62184       *   image(img, 50, 0);
62185       * }
62186       * </code>
62187       * </div>
62188       *
62189       * @alt
62190       * 2 side by side images of bricks, left image with blue tint
62191       *
62192       */
62193
62194
62195      p5.prototype.noTint = function () {
62196        this._renderer._tint = null;
62197      };
62198      /**
62199       * Apply the current tint color to the input image, return the resulting
62200       * canvas.
62201       *
62202       * @private
62203       * @param {p5.Image} The image to be tinted
62204       * @return {canvas} The resulting tinted canvas
62205       *
62206       */
62207
62208
62209      p5.prototype._getTintedImageCanvas = function (img) {
62210        if (!img.canvas) {
62211          return img;
62212        }
62213
62214        var pixels = Filters._toPixels(img.canvas);
62215
62216        var tmpCanvas = document.createElement('canvas');
62217        tmpCanvas.width = img.canvas.width;
62218        tmpCanvas.height = img.canvas.height;
62219        var tmpCtx = tmpCanvas.getContext('2d');
62220        var id = tmpCtx.createImageData(img.canvas.width, img.canvas.height);
62221        var newPixels = id.data;
62222
62223        for (var i = 0; i < pixels.length; i += 4) {
62224          var r = pixels[i];
62225          var g = pixels[i + 1];
62226          var b = pixels[i + 2];
62227          var a = pixels[i + 3];
62228          newPixels[i] = r * this._renderer._tint[0] / 255;
62229          newPixels[i + 1] = g * this._renderer._tint[1] / 255;
62230          newPixels[i + 2] = b * this._renderer._tint[2] / 255;
62231          newPixels[i + 3] = a * this._renderer._tint[3] / 255;
62232        }
62233
62234        tmpCtx.putImageData(id, 0, 0);
62235        return tmpCanvas;
62236      };
62237      /**
62238       * Set image mode. Modifies the location from which images are drawn by
62239       * changing the way in which parameters given to <a href="#/p5/image">image()</a> are interpreted.
62240       * The default mode is imageMode(CORNER), which interprets the second and
62241       * third parameters of <a href="#/p5/image">image()</a> as the upper-left corner of the image. If
62242       * two additional parameters are specified, they are used to set the image's
62243       * width and height.
62244       * <br><br>
62245       * imageMode(CORNERS) interprets the second and third parameters of <a href="#/p5/image">image()</a>
62246       * as the location of one corner, and the fourth and fifth parameters as the
62247       * opposite corner.
62248       * <br><br>
62249       * imageMode(CENTER) interprets the second and third parameters of <a href="#/p5/image">image()</a>
62250       * as the image's center point. If two additional parameters are specified,
62251       * they are used to set the image's width and height.
62252       *
62253       * @method imageMode
62254       * @param {Constant} mode either CORNER, CORNERS, or CENTER
62255       * @example
62256       *
62257       * <div>
62258       * <code>
62259       * let img;
62260       * function preload() {
62261       *   img = loadImage('assets/bricks.jpg');
62262       * }
62263       * function setup() {
62264       *   imageMode(CORNER);
62265       *   image(img, 10, 10, 50, 50);
62266       * }
62267       * </code>
62268       * </div>
62269       *
62270       * <div>
62271       * <code>
62272       * let img;
62273       * function preload() {
62274       *   img = loadImage('assets/bricks.jpg');
62275       * }
62276       * function setup() {
62277       *   imageMode(CORNERS);
62278       *   image(img, 10, 10, 90, 40);
62279       * }
62280       * </code>
62281       * </div>
62282       *
62283       * <div>
62284       * <code>
62285       * let img;
62286       * function preload() {
62287       *   img = loadImage('assets/bricks.jpg');
62288       * }
62289       * function setup() {
62290       *   imageMode(CENTER);
62291       *   image(img, 50, 50, 80, 80);
62292       * }
62293       * </code>
62294       * </div>
62295       *
62296       * @alt
62297       * small square image of bricks
62298       * horizontal rectangle image of bricks
62299       * large square image of bricks
62300       *
62301       */
62302
62303
62304      p5.prototype.imageMode = function (m) {
62305        p5._validateParameters('imageMode', arguments);
62306
62307        if (m === constants.CORNER || m === constants.CORNERS || m === constants.CENTER) {
62308          this._renderer._imageMode = m;
62309        }
62310      };
62311
62312      module.exports = p5;
62313    }, {
62314      "../core/constants": 18,
62315      "../core/error_helpers": 20,
62316      "../core/helpers": 21,
62317      "../core/main": 24,
62318      "./filters": 42
62319    }],
62320    45: [function (_dereq_, module, exports) {
62321      /**
62322       * @module Image
62323       * @submodule Image
62324       * @requires core
62325       * @requires constants
62326       * @requires filters
62327       */
62328
62329      /**
62330       * This module defines the <a href="#/p5.Image">p5.Image</a> class and P5 methods for
62331       * drawing images to the main display canvas.
62332       */
62333      'use strict';
62334
62335      var p5 = _dereq_('../core/main');
62336
62337      var Filters = _dereq_('./filters');
62338      /*
62339       * Class methods
62340       */
62341
62342      /**
62343       * Creates a new <a href="#/p5.Image">p5.Image</a>. A <a href="#/p5.Image">p5.Image</a> is a canvas backed representation of an
62344       * image.
62345       * <br><br>
62346       * p5 can display .gif, .jpg and .png images. Images may be displayed
62347       * in 2D and 3D space. Before an image is used, it must be loaded with the
62348       * <a href="#/p5/loadImage">loadImage()</a> function. The <a href="#/p5.Image">p5.Image</a> class contains fields for the width and
62349       * height of the image, as well as an array called <a href="#/p5.Image/pixels">pixels[]</a> that contains the
62350       * values for every pixel in the image.
62351       * <br><br>
62352       * The methods described below allow easy access to the image's pixels and
62353       * alpha channel and simplify the process of compositing.
62354       * <br><br>
62355       * Before using the <a href="#/p5.Image/pixels">pixels[]</a> array, be sure to use the <a href="#/p5.Image/loadPixels">loadPixels()</a> method on
62356       * the image to make sure that the pixel data is properly loaded.
62357       * @example
62358       * <div><code>
62359       * function setup() {
62360       *   let img = createImage(100, 100); // same as new p5.Image(100, 100);
62361       *   img.loadPixels();
62362       *   createCanvas(100, 100);
62363       *   background(0);
62364       *
62365       *   // helper for writing color to array
62366       *   function writeColor(image, x, y, red, green, blue, alpha) {
62367       *     let index = (x + y * width) * 4;
62368       *     image.pixels[index] = red;
62369       *     image.pixels[index + 1] = green;
62370       *     image.pixels[index + 2] = blue;
62371       *     image.pixels[index + 3] = alpha;
62372       *   }
62373       *
62374       *   let x, y;
62375       *   // fill with random colors
62376       *   for (y = 0; y < img.height; y++) {
62377       *     for (x = 0; x < img.width; x++) {
62378       *       let red = random(255);
62379       *       let green = random(255);
62380       *       let blue = random(255);
62381       *       let alpha = 255;
62382       *       writeColor(img, x, y, red, green, blue, alpha);
62383       *     }
62384       *   }
62385       *
62386       *   // draw a red line
62387       *   y = 0;
62388       *   for (x = 0; x < img.width; x++) {
62389       *     writeColor(img, x, y, 255, 0, 0, 255);
62390       *   }
62391       *
62392       *   // draw a green line
62393       *   y = img.height - 1;
62394       *   for (x = 0; x < img.width; x++) {
62395       *     writeColor(img, x, y, 0, 255, 0, 255);
62396       *   }
62397       *
62398       *   img.updatePixels();
62399       *   image(img, 0, 0);
62400       * }
62401       * </code></div>
62402       *
62403       *
62404       * @class p5.Image
62405       * @param {Number} width
62406       * @param {Number} height
62407       */
62408
62409
62410      p5.Image = function (width, height) {
62411        /**
62412         * Image width.
62413         * @property {Number} width
62414         * @readOnly
62415         * @example
62416         * <div><code>
62417         * let img;
62418         * function preload() {
62419         *   img = loadImage('assets/rockies.jpg');
62420         * }
62421         *
62422         * function setup() {
62423         *   createCanvas(100, 100);
62424         *   image(img, 0, 0);
62425         *   for (let i = 0; i < img.width; i++) {
62426         *     let c = img.get(i, img.height / 2);
62427         *     stroke(c);
62428         *     line(i, height / 2, i, height);
62429         *   }
62430         * }
62431         * </code></div>
62432         *
62433         * @alt
62434         * rocky mountains in top and horizontal lines in corresponding colors in bottom.
62435         *
62436         */
62437        this.width = width;
62438        /**
62439         * Image height.
62440         * @property {Number} height
62441         * @readOnly
62442         * @example
62443         * <div><code>
62444         * let img;
62445         * function preload() {
62446         *   img = loadImage('assets/rockies.jpg');
62447         * }
62448         *
62449         * function setup() {
62450         *   createCanvas(100, 100);
62451         *   image(img, 0, 0);
62452         *   for (let i = 0;
62452 i < img.height; i++) {
62453         *     let c = img.get(img.width / 2, i);
62454         *     stroke(c);
62455         *     line(0, i, width / 2, i);
62456         *   }
62457         * }
62458         * </code></div>
62459         *
62460         * @alt
62461         * rocky mountains on right and vertical lines in corresponding colors on left.
62462         *
62463         */
62464
62465        this.height = height;
62466        this.canvas = document.createElement('canvas');
62467        this.canvas.width = this.width;
62468        this.canvas.height = this.height;
62469        this.drawingContext = this.canvas.getContext('2d');
62470        this._pixelDensity = 1; //used for webgl texturing only
62471
62472        this._modified = false;
62473        this._pixelsDirty = true;
62474        /**
62475         * Array containing the values for all the pixels in the display window.
62476         * These values are numbers. This array is the size (include an appropriate
62477         * factor for pixelDensity) of the display window x4,
62478         * representing the R, G, B, A values in order for each pixel, moving from
62479         * left to right across each row, then down each column. Retina and other
62480         * high denisty displays may have more pixels (by a factor of
62481         * pixelDensity^2).
62482         * For example, if the image is 100x100 pixels, there will be 40,000. With
62483         * pixelDensity = 2, there will be 160,000. The first four values
62484         * (indices 0-3) in the array will be the R, G, B, A values of the pixel at
62485         * (0, 0). The second four values (indices 4-7) will contain the R, G, B, A
62486         * values of the pixel at (1, 0). More generally, to set values for a pixel
62487         * at (x, y):
62488         * ```javascript
62489         * let d = pixelDensity();
62490         * for (let i = 0; i < d; i++) {
62491         *   for (let j = 0; j < d; j++) {
62492         *     // loop over
62493         *     index = 4 * ((y * d + j) * width * d + (x * d + i
62493));
62494         *     pixels[index] = r;
62495         *     pixels[index+1] = g;
62496         *     pixels[index+2] = b;
62497         *     pixels[index+3] = a;
62498         *   }
62499         * }
62500         * ```
62501         * <br><br>
62502         * Before accessing this array, the data must loaded with the <a href="#/p5.Image/loadPixels">loadPixels()</a>
62503         * function. After the array data has been modified, the <a href="#/p5.Image/updatePixels">updatePixels()</a>
62504         * function must be run to update the changes.
62505         * @property {Number[]} pixels
62506         * @example
62507         * <div>
62508         * <code>
62509         * let img = createImage(66, 66);
62510         * img.loadPixels();
62511         * for (let i = 0; i < img.width; i++) {
62512         *   for (let j = 0; j < img.height; j++) {
62513         *     img.set(i, j, color(0, 90, 102));
62514         *   }
62515         * }
62516         * img.updatePixels();
62517         * image(img, 17, 17);
62518         * </code>
62519         * </div>
62520         * <div>
62521         * <code>
62522         * let pink = color(255, 102, 204);
62523         * let img = createImage(66, 66);
62524         * img.loadPixels();
62525         * for (let i = 0; i < 4 * (width * height / 2); i += 4) {
62526         *   img.pixels[i] = red(pink);
62527         *   img.pixels[i + 1] = green(pink);
62528         *   img.pixels[i + 2] = blue(pink);
62529         *   img.pixels[i + 3] = alpha(pink);
62530         * }
62531         * img.updatePixels();
62532         * image(img, 17, 17);
62533         * </code>
62534         * </div>
62535         *
62536         * @alt
62537         * 66x66 turquoise rect in center of canvas
62538         * 66x66 pink rect in center of canvas
62539         *
62540         */
62541
62542        this.pixels = [];
62543      };
62544      /**
62545       * Helper fxn for sharing pixel methods
62546       *
62547       */
62548
62549
62550      p5.Image.prototype._setProperty = function (prop, value) {
62551        this[prop] = value;
62552        this.setModified(true);
62553      };
62554      /**
62555       * Loads the pixels data for this image into the [pixels] attribute.
62556       *
62557       * @method loadPixels
62558       * @example
62559       * <div><code>
62560       * let myImage;
62561       * let halfImage;
62562       *
62563       * function preload() {
62564       *   myImage = loadImage('assets/rockies.jpg');
62565       * }
62566       *
62567       * function setup() {
62568       *   myImage.loadPixels();
62569       *   halfImage = 4 * width * height / 2;
62570       *   for (let i = 0; i < halfImage; i++) {
62571       *     myImage.pixels[i + halfImage] = myImage.pixels[i];
62572       *   }
62573       *   myImage.updatePixels();
62574       * }
62575       *
62576       * function draw() {
62577       *   image(myImage, 0, 0);
62578       * }
62579       * </code></div>
62580       *
62581       * @alt
62582       * 2 images of rocky mountains vertically stacked
62583       *
62584       */
62585
62586
62587      p5.Image.prototype.loadPixels = function () {
62588        p5.Renderer2D.prototype.loadPixels.call(this);
62589        this.setModified(true);
62590      };
62591      /**
62592       * Updates the backing canvas for this image with the contents of
62593       * the [pixels] array.
62594       *
62595       * @method updatePixels
62596       * @param {Integer} x x-offset of the target update area for the
62597       *                              underlying canvas
62598       * @param {Integer} y y-offset of the target update area for the
62599       *                              underlying canvas
62600       * @param {Integer} w height of the target update area for the
62601       *                              underlying canvas
62602       * @param {Integer} h height of the target update area for the
62603       *                              underlying canvas
62604       * @example
62605       * <div><code>
62606       * let myImage;
62607       * let halfImage;
62608       *
62609       * function preload() {
62610       *   myImage = loadImage('assets/rockies.jpg');
62611       * }
62612       *
62613       * function setup() {
62614       *   myImage.loadPixels();
62615       *   halfImage = 4 * width * height / 2;
62616       *   for (let i = 0; i < halfImage; i++) {
62617       *     myImage.pixels[i + halfImage] = myImage.pixels[i];
62618       *   }
62619       *   myImage.updatePixels();
62620       * }
62621       *
62622       * function draw() {
62623       *   image(myImage, 0, 0);
62624       * }
62625       * </code></div>
62626       *
62627       * @alt
62628       * 2 images of rocky mountains vertically stacked
62629       *
62630       */
62631
62632      /**
62633       * @method updatePixels
62634       */
62635
62636
62637      p5.Image.prototype.updatePixels = function (x, y, w, h) {
62638        p5.Renderer2D.prototype.updatePixels.call(this, x, y, w, h);
62639        this.setModified(true);
62640      };
62641      /**
62642       * Get a region of pixels from an image.
62643       *
62644       * If no params are passed, those whole image is returned,
62645       * if x and y are the only params passed a single pixel is extracted
62646       * if all params are passed a rectangle region is extracted and a <a href="#/p5.Image">p5.Image</a>
62647       * is returned.
62648       *
62649       * Returns undefined if the region is outside the bounds of the image
62650       *
62651       * @method get
62652       * @param  {Number}               [x] x-coordinate of the pixel
62653       * @param  {Number}               [y] y-coordinate of the pixel
62654       * @param  {Number}               [w] width
62655       * @param  {Number}               [h] height
62656       * @return {Number[]|Color|p5.Image}  color of pixel at x,y in array format
62657       *                                    [R, G, B, A] or <a href="#/p5.Image">p5.Image</a>
62658       * @example
62659       * <div><code>
62660       * let myImage;
62661       * let c;
62662       *
62663       * function preload() {
62664       *   myImage = loadImage('assets/rockies.jpg');
62665       * }
62666       *
62667       * function setup() {
62668       *   background(myImage);
62669       *   noStroke();
62670       *   c = myImage.get(60, 90);
62671       *   fill(c);
62672       *   rect(25, 25, 50, 50);
62673       * }
62674       *
62675       * //get() returns color here
62676       * </code></div>
62677       *
62678       * @alt
62679       * image of rocky mountains with 50x50 green rect in front
62680       *
62681       */
62682
62683
62684      p5.Image.prototype.get = function (x, y, w, h) {
62685        return p5.prototype.get.call(this, x, y, w, h);
62686      };
62687      /**
62688       * Set the color of a single pixel or write an image into
62689       * this <a href="#/p5.Image">p5.Image</a>.
62690       *
62691       * Note that for a large number of pixels this will
62692       * be slower than directly manipulating the pixels array
62693       * and then calling <a href="#/p5.Image/updatePixels">updatePixels()</a>.
62694       *
62695       * @method set
62696       * @param {Number}              x x-coordinate of the pixel
62697       * @param {Number}              y y-coordinate of the pixel
62698       * @param {Number|Number[]|Object}   a grayscale value | pixel array |
62699       *                                a <a href="#/p5.Color">p5.Color</a> | image to copy
62700       * @example
62701       * <div>
62702       * <code>
62703       * let img = createImage(66, 66);
62704       * img.loadPixels();
62705       * for (let i = 0; i < img.width; i++) {
62706       *   for (let j = 0;
62706 j < img.height; j++) {
62707       *     img.set(i, j, color(0, 90, 102, (i % img.width) * 2));
62708       *   }
62709       * }
62710       * img.updatePixels();
62711       * image(img, 17, 17);
62712       * image(img, 34, 34);
62713       * </code>
62714       * </div>
62715       *
62716       * @alt
62717       * 2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas
62718       *
62719       */
62720
62721
62722      p5.Image.prototype.set = function (x, y, imgOrCol) {
62723        p5.Renderer2D.prototype.set.call(this, x, y, imgOrCol);
62724        this.setModified(true);
62725      };
62726      /**
62727       * Resize the image to a new width and height. To make the image scale
62728       * proportionally, use 0 as the value for the wide or high parameter.
62729       * For instance, to make the width of an image 150 pixels, and change
62730       * the height using the same proportion, use resize(150, 0).
62731       *
62732       * @method resize
62733       * @param {Number} width the resized image width
62734       * @param {Number} height the resized image height
62735       * @example
62736       * <div><code>
62737       * let img;
62738       *
62739       * function preload() {
62740       *   img = loadImage('assets/rockies.jpg');
62741       * }
62742      
62743       * function draw() {
62744       *   image(img, 0, 0);
62745       * }
62746       *
62747       * function mousePressed() {
62748       *   img.resize(50, 100);
62749       * }
62750       * </code></div>
62751       *
62752       * @alt
62753       * image of rocky mountains. zoomed in
62754       *
62755       */
62756
62757
62758      p5.Image.prototype.resize = function (width, height) {
62759        // Copy contents to a temporary canvas, resize the original
62760        // and then copy back.
62761        //
62762        // There is a faster approach that involves just one copy and swapping the
62763        // this.canvas reference. We could switch to that approach if (as i think
62764        // is the case) there an expectation that the user would not hold a
62765        // reference to the backing canvas of a p5.Image. But since we do not
62766        // enforce that at the moment, I am leaving in the slower, but safer
62767        // implementation.
62768        // auto-resize
62769        if (width === 0 && height === 0) {
62770          width = this.canvas.width;
62771          height = this.canvas.height;
62772        } else if (width === 0) {
62773          width = this.canvas.width * height / this.canvas.height;
62774        } else if (height === 0) {
62775          height = this.canvas.height * width / this.canvas.width;
62776        }
62777
62778        width = Math.floor(width);
62779        height = Math.floor(height);
62780        var tempCanvas = document.createElement('canvas');
62781        tempCanvas.width = width;
62782        tempCanvas.height = height; // prettier-ignore
62783
62784        tempCanvas.getContext('2d').drawImage(this.canvas, 0, 0, this.canvas.width, this.canvas.height, 0, 0, tempCanvas.width, tempCanvas.height); // Resize the original canvas, which will clear its contents
62785
62786        this.canvas.width = this.width = width;
62787        this.canvas.height = this.height = height; //Copy the image back
62788        // prettier-ignore
62789
62790        this.drawingContext.drawImage(tempCanvas, 0, 0, width, height, 0, 0, width, height);
62791
62792        if (this.pixels.length > 0) {
62793          this.loadPixels();
62794        }
62795
62796        this.setModified(true);
62797        this._pixelsDirty = true;
62798      };
62799      /**
62800       * Copies a region of pixels from one image to another. If no
62801       * srcImage is specified this is used as the source. If the source
62802       * and destination regions aren't the same size, it will
62803       * automatically resize source pixels to fit the specified
62804       * target region.
62805       *
62806       * @method copy
62807       * @param  {p5.Image|p5.Element} srcImage source image
62808       * @param  {Integer} sx X coordinate of the source's upper left corner
62809       * @param  {Integer} sy Y coordinate of the source's upper left corner
62810       * @param  {Integer} sw source image width
62811       * @param  {Integer} sh source image height
62812       * @param  {Integer} dx X coordinate of the destination's upper left corner
62813       * @param  {Integer} dy Y coordinate of the destination's upper left corner
62814       * @param  {Integer} dw destination image width
62815       * @param  {Integer} dh destination image height
62816       * @example
62817       * <div><code>
62818       * let photo;
62819       * let bricks;
62820       * let x;
62821       * let y;
62822       *
62823       * function preload() {
62824       *   photo = loadImage('assets/rockies.jpg');
62825       *   bricks = loadImage('assets/bricks.jpg');
62826       * }
62827       *
62828       * function setup() {
62829       *   x = bricks.width / 2;
62830       *   y = bricks.height / 2;
62831       *   photo.copy(bricks, 0, 0, x, y, 0, 0, x, y);
62832       *   image(photo, 0, 0);
62833       * }
62834       * </code></div>
62835       *
62836       * @alt
62837       * image of rocky mountains and smaller image on top of bricks at top left
62838       *
62839       */
62840
62841      /**
62842       * @method copy
62843       * @param  {Integer} sx
62844       * @param  {Integer} sy
62845       * @param  {Integer} sw
62846       * @param  {Integer} sh
62847       * @param  {Integer} dx
62848       * @param  {Integer} dy
62849       * @param  {Integer} dw
62850       * @param  {Integer} dh
62851       */
62852
62853
62854      p5.Image.prototype.copy = function () {
62855        var srcImage, sx, sy, sw, sh, dx, dy, dw, dh;
62856
62857        if (arguments.length === 9) {
62858          srcImage = arguments[0];
62859          sx = arguments[1];
62860          sy = arguments[2];
62861          sw = arguments[3];
62862          sh = arguments[4];
62863          dx = arguments[5];
62864          dy = arguments[6];
62865          dw = arguments[7];
62866          dh = arguments[8];
62867        } else if (arguments.length === 8) {
62868          srcImage = this;
62869          sx = arguments[0];
62870          sy = arguments[1];
62871          sw = arguments[2];
62872          sh = arguments[3];
62873          dx = arguments[4];
62874          dy = arguments[5];
62875          dw = arguments[6];
62876          dh = arguments[7];
62877        } else {
62878          throw new Error('Signature not supported');
62879        }
62880
62881        p5.Renderer2D._copyHelper(this, srcImage, sx, sy, sw, sh, dx, dy, dw, dh);
62882
62883        this._pixelsDirty = true;
62884      };
62885      /**
62886       * Masks part of an image from displaying by loading another
62887       * image and using it's alpha channel as an alpha channel for
62888       * this image.
62889       *
62890       * @method mask
62891       * @param {p5.Image} srcImage source image
62892       * @example
62893       * <div><code>
62894       * let photo, maskImage;
62895       * function preload() {
62896       *   photo = loadImage('assets/rockies.jpg');
62897       *   maskImage = loadImage('assets/mask2.png');
62898       * }
62899       *
62900       * function setup() {
62901       *   createCanvas(100, 100);
62902       *   photo.mask(maskImage);
62903       *   image(photo, 0, 0);
62904       * }
62905       * </code></div>
62906       *
62907       * @alt
62908       * image of rocky mountains with white at right
62909       *
62910       *
62911       * http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/
62912       *
62913       */
62914      // TODO: - Accept an array of alpha values.
62915      //       - Use other channels of an image. p5 uses the
62916      //       blue channel (which feels kind of arbitrary). Note: at the
62917      //       moment this method does not match native processings original
62918      //       functionality exactly.
62919
62920
62921      p5.Image.prototype.mask = function (p5Image) {
62922        if (p5Image === undefined) {
62923          p5Image = this;
62924        }
62925
62926        var currBlend = this.drawingContext.globalCompositeOperation;
62927        var scaleFactor = 1;
62928
62929        if (p5Image instanceof p5.Renderer) {
62930          scaleFactor = p5Image._pInst._pixelDensity;
62931        }
62932
62933        var copyArgs = [p5Image, 0, 0, scaleFactor * p5Image.width, scaleFactor * p5Image.height, 0, 0, this.width, this.height];
62934        this.drawingContext.globalCompositeOperation = 'destination-in';
62935        p5.Image.prototype.copy.apply(this, copyArgs);
62936        this.drawingContext.globalCompositeOperation = currBlend;
62937        this.setModified(true);
62938      };
62939      /**
62940       * Applies an image filter to a <a href="#/p5.Image">p5.Image</a>
62941       *
62942       * @method filter
62943       * @param  {Constant} filterType  either THRESHOLD, GRAY, OPAQUE, INVERT,
62944       *                                POSTERIZE, BLUR, ERODE, DILATE or BLUR.
62945       *                                See Filters.js for docs on
62946       *                                each available filter
62947       * @param  {Number} [filterParam] an optional parameter unique
62948       *                                to each filter, see above
62949       * @example
62950       * <div><code>
62951       * let photo1;
62952       * let photo2;
62953       *
62954       * function preload() {
62955       *   photo1 = loadImage('assets/rockies.jpg');
62956       *   photo2 = loadImage('assets/rockies.jpg');
62957       * }
62958       *
62959       * function setup() {
62960       *   photo2.filter('gray');
62961       *   image(photo1, 0, 0);
62962       *   image(photo2, width / 2, 0);
62963       * }
62964       * </code></div>
62965       *
62966       * @alt
62967       * 2 images of rocky mountains left one in color, right in black and white
62968       *
62969       */
62970
62971
62972      p5.Image.prototype.filter = function (operation, value) {
62973        Filters.apply(this.canvas, Filters[operation.toLowerCase()], value);
62974        this.setModified(true);
62975      };
62976      /**
62977       * Copies a region of pixels from one image to another, using a specified
62978       * blend mode to do the operation.
62979       *
62980       * @method blend
62981       * @param  {p5.Image} srcImage source image
62982       * @param  {Integer} sx X coordinate of the source's upper left corner
62983       * @param  {Integer} sy Y coordinate of the source's upper left corner
62984       * @param  {Integer} sw source image width
62985       * @param  {Integer} sh source image height
62986       * @param  {Integer} dx X coordinate of the destination's upper left corner
62987       * @param  {Integer} dy Y coordinate of the destination's upper left corner
62988       * @param  {Integer} dw destination image width
62989       * @param  {Integer} dh destination image height
62990       * @param  {Constant} blendMode the blend mode. either
62991       *     BLEND, DARKEST, LIGHTEST, DIFFERENCE,
62992       *     MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,
62993       *     SOFT_LIGHT, DODGE, BURN, ADD or NORMAL.
62994       *
62995       * Available blend modes are: normal | multiply | screen | overlay |
62996       *            darken | lighten | color-dodge | color-burn | hard-light |
62997       *            soft-light | difference | exclusion | hue | saturation |
62998       *            color | luminosity
62999       *
63000       *
63001       * http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/
63002       * @example
63003       * <div><code>
63004       * let mountains;
63005       * let bricks;
63006       *
63007       * function preload() {
63008       *   mountains = loadImage('assets/rockies.jpg');
63009       *   bricks = loadImage('assets/bricks_third.jpg');
63010       * }
63011       *
63012       * function setup() {
63013       *   mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, ADD);
63014       *   image(mountains, 0, 0);
63015       *   image(bricks, 0, 0);
63016       * }
63017       * </code></div>
63018       * <div><code>
63019       * let mountains;
63020       * let bricks;
63021       *
63022       * function preload() {
63023       *   mountains = loadImage('assets/rockies.jpg');
63024       *   bricks = loadImage('assets/bricks_third.jpg');
63025       * }
63026       *
63027       * function setup() {
63028       *   mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST);
63029       *   image(mountains, 0, 0);
63030       *   image(bricks, 0, 0);
63031       * }
63032       * </code></div>
63033       * <div><code>
63034       * let mountains;
63035       * let bricks;
63036       *
63037       * function preload() {
63038       *   mountains = loadImage('assets/rockies.jpg');
63039       *   bricks = loadImage('assets/bricks_third.jpg');
63040       * }
63041       *
63042       * function setup() {
63043       *   mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST);
63044       *   image(mountains, 0, 0);
63045       *   image(bricks, 0, 0);
63046       * }
63047       * </code></div>
63048       *
63049       * @alt
63050       * image of rocky mountains. Brick images on left and right. Right overexposed
63051       * image of rockies. Brickwall images on left and right. Right mortar transparent
63052       * image of rockies. Brickwall images on left and right. Right translucent
63053       *
63054       */
63055
63056      /**
63057       * @method blend
63058       * @param  {Integer} sx
63059       * @param  {Integer} sy
63060       * @param  {Integer} sw
63061       * @param  {Integer} sh
63062       * @param  {Integer} dx
63063       * @param  {Integer} dy
63064       * @param  {Integer} dw
63065       * @param  {Integer} dh
63066       * @param  {Constant} blendMode
63067       */
63068
63069
63070      p5.Image.prototype.blend = function () {
63071        p5.prototype.blend.apply(this, arguments);
63072        this.setModified(true);
63073      };
63074      /**
63075       * helper method for web GL mode to indicate that an image has been
63076       * changed or unchanged since last upload. gl texture upload will
63077       * set this value to false after uploading the texture.
63078       * @method setModified
63079       * @param {boolean} val sets whether or not the image has been
63080       * modified.
63081       * @private
63082       */
63083
63084
63085      p5.Image.prototype.setModified = function (val) {
63086        this._modified = val; //enforce boolean?
63087      };
63088      /**
63089       * helper method for web GL mode to figure out if the image
63090       * has been modified and might need to be re-uploaded to texture
63091       * memory between frames.
63092       * @method isModified
63093       * @private
63094       * @return {boolean} a boolean indicating whether or not the
63095       * image has been updated or modified since last texture upload.
63096       */
63097
63098
63099      p5.Image.prototype.isModified = function () {
63100        return this._modified;
63101      };
63102      /**
63103       * Saves the image to a file and force the browser to download it.
63104       * Accepts two strings for filename and file extension
63105       * Supports png (default) and jpg.
63106       *
63107       * @method save
63108       * @param {String} filename give your file a name
63109       * @param  {String} extension 'png' or 'jpg'
63110       * @example
63111       * <div><code>
63112       * let photo;
63113       *
63114       * function preload() {
63115       *   photo = loadImage('assets/rockies.jpg');
63116       * }
63117       *
63118       * function draw() {
63119       *   image(photo, 0, 0);
63120       * }
63121       *
63122       * function keyTyped() {
63123       *   if (key === 's') {
63124       *     photo.save('photo', 'png');
63125       *   }
63126       * }
63127       * </code></div>
63128       *
63129       * @alt
63130       * image of rocky mountains.
63131       *
63132       */
63133
63134
63135      p5.Image.prototype.save = function (filename, extension) {
63136        p5.prototype.saveCanvas(this.canvas, filename, extension);
63137      };
63138
63139      module.exports = p5.Image;
63140    }, {
63141      "../core/main": 24,
63142      "./filters": 42
63143    }],
63144    46: [function (_dereq_, module, exports) {
63145      /**
63146       * @module Image
63147       * @submodule Pixels
63148       * @for p5
63149       * @requires core
63150       */
63151      'use strict';
63152
63153      var p5 = _dereq_('../core/main');
63154
63155      var Filters = _dereq_('./filters');
63156
63157      _dereq_('../color/p5.Color');
63158      /**
63159       * <a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference
63160       * /Global_Objects/Uint8ClampedArray' target='_blank'>Uint8ClampedArray</a>
63161       * containing the values for all the pixels in the display window.
63162       * These values are numbers. This array is the size (include an appropriate
63163       * factor for <a href="#/p5/pixelDensity">pixelDensity</a>) of the display window x4,
63164       * representing the R, G, B, A values in order for each pixel, moving from
63165       * left to right across each row, then down each column. Retina and other
63166       * high density displays will have more pixels[] (by a factor of
63167       * pixelDensity^2).
63168       * For example, if the image is 100x100 pixels, there will be 40,000. On a
63169       * retina display, there will be 160,000.
63170       * <br><br>
63171       * The first four values (indices 0-3) in the array will be the R, G, B, A
63172       * values of the pixel at (0, 0). The second four values (indices 4-7) will
63173       * contain the R, G, B, A values of the pixel at (1, 0). More generally, to
63174       * set values for a pixel at (x, y):
63175       * ```javascript
63176       * let d = pixelDensity();
63177       * for (let i = 0; i < d; i++) {
63178       *   for (let j = 0; j < d; j++) {
63179       *     // loop over
63180       *     index = 4 * ((y * d + j) * width * d + (x * d + i));
63181       *     pixels[index] = r;
63182       *     pixels[index+1] = g;
63183       *     pixels[index+2] = b;
63184       *     pixels[index+3] = a;
63185       *   }
63186       * }
63187       * ```
63188       * <p>While the above method is complex, it is flexible enough to work with
63189       * any pixelDensity. Note that <a href="#/p5/set">set()</a> will automatically take care of
63190       * setting all the appropriate values in <a href="#/p5/pixels">pixels[]</a> for a given (x, y) at
63191       * any pixelDensity, but the performance may not be as fast when lots of
63192       * modifications are made to the pixel array.
63193       * <br><br>
63194       * Before accessing this array, the data must loaded with the <a href="#/p5/loadPixels">loadPixels()</a>
63195       * function. After the array data has been modified, the <a href="#/p5/updatePixels">updatePixels()</a>
63196       * function must be run to update the changes.
63197       * <br><br>
63198       * Note that this is not a standard javascript array.  This means that
63199       * standard javascript functions such as <a href="#/p5/slice">slice()</a> or
63200       * <a href="#/p5/arrayCopy">arrayCopy()</a> do not
63201       * work.</p>
63202       *
63203       * @property {Number[]} pixels
63204       * @example
63205       * <div>
63206       * <code>
63207       * let pink = color(255, 102, 204);
63208       * loadPixels();
63209       * let d = pixelDensity();
63210       * let halfImage = 4 * (width * d) * (height / 2 * d);
63211       * for (let i = 0; i < halfImage; i += 4) {
63212       *   pixels[i] = red(pink);
63213       *   pixels[i + 1] = green(pink);
63214       *   pixels[i + 2] = blue(pink);
63215       *   pixels[i + 3] = alpha(pink);
63216       * }
63217       * updatePixels();
63218       * </code>
63219       * </div>
63220       *
63221       * @alt
63222       * top half of canvas pink, bottom grey
63223       *
63224       */
63225
63226
63227      p5.prototype.pixels = [];
63228      /**
63229       * Copies a region of pixels from one image to another, using a specified
63230       * blend mode to do the operation.
63231       *
63232       * @method blend
63233       * @param  {p5.Image} srcImage source image
63234       * @param  {Integer} sx X coordinate of the source's upper left corner
63235       * @param  {Integer} sy Y coordinate of the source's upper left corner
63236       * @param  {Integer} sw source image width
63237       * @param  {Integer} sh source image height
63238       * @param  {Integer} dx X coordinate of the destination's upper left corner
63239       * @param  {Integer} dy Y coordinate of the destination's upper left corner
63240       * @param  {Integer} dw destination image width
63241       * @param  {Integer} dh destination image height
63242       * @param  {Constant} blendMode the blend mode. either
63243       *     BLEND, DARKEST, LIGHTEST, DIFFERENCE,
63244       *     MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,
63245       *     SOFT_LIGHT, DODGE, BURN, ADD or NORMAL.
63246       *
63247       * @example
63248       * <div><code>
63249       * let img0;
63250       * let img1;
63251       *
63252       * function preload() {
63253       *   img0 = loadImage('assets/rockies.jpg');
63254       *   img1 = loadImage('assets/bricks_third.jpg');
63255       * }
63256       *
63257       * function setup() {
63258       *   background(img0);
63259       *   image(img1, 0, 0);
63260       *   blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST);
63261       * }
63262       * </code></div>
63263       * <div><code>
63264       * let img0;
63265       * let img1;
63266       *
63267       * function preload() {
63268       *   img0 = loadImage('assets/rockies.jpg');
63269       *   img1 = loadImage('assets/bricks_third.jpg');
63270       * }
63271       *
63272       * function setup() {
63273       *   background(img0);
63274       *   image(img1, 0, 0);
63275       *   blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST);
63276       * }
63277       * </code></div>
63278       * <div><code>
63279       * let img0;
63280       * let img1;
63281       *
63282       * function preload() {
63283       *   img0 = loadImage('assets/rockies.jpg');
63284       *   img1 = loadImage('assets/bricks_third.jpg');
63285       * }
63286       *
63287       * function setup() {
63288       *   background(img0);
63289       *   image(img1, 0, 0);
63290       *   blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, ADD);
63291       * }
63292       * </code></div>
63293       *
63294       * @alt
63295       * image of rocky mountains. Brick images on left and right. Right overexposed
63296       * image of rockies. Brickwall images on left and right. Right mortar transparent
63297       * image of rockies. Brickwall images on left and right. Right translucent
63298       *
63299       *
63300       */
63301
63302      /**
63303       * @method blend
63304       * @param  {Integer} sx
63305       * @param  {Integer} sy
63306       * @param  {Integer} sw
63307       * @param  {Integer} sh
63308       * @param  {Integer} dx
63309       * @param  {Integer} dy
63310       * @param  {Integer} dw
63311       * @param  {Integer} dh
63312       * @param  {Constant} blendMode
63313       */
63314
63315      p5.prototype.blend = function () {
63316        p5._validateParameters('blend', arguments);
63317
63318        if (this._renderer) {
63319          this._renderer.blend.apply(this._renderer, arguments);
63320        } else {
63321          p5.Renderer2D.prototype.blend.apply(this, arguments);
63322        }
63323      };
63324      /**
63325       * Copies a region of the canvas to another region of the canvas
63326       * and copies a region of pixels from an image used as the srcImg parameter
63327       * into the canvas srcImage is specified this is used as the source. If
63328       * the source and destination regions aren't the same size, it will
63329       * automatically resize source pixels to fit the specified
63330       * target region.
63331       *
63332       * @method copy
63333       * @param  {p5.Image|p5.Element} srcImage source image
63334       * @param  {Integer} sx X coordinate of the source's upper left corner
63335       * @param  {Integer} sy Y coordinate of the source's upper left corner
63336       * @param  {Integer} sw source image width
63337       * @param  {Integer} sh source image height
63338       * @param  {Integer} dx X coordinate of the destination's upper left corner
63339       * @param  {Integer} dy Y coordinate of the destination's upper left corner
63340       * @param  {Integer} dw destination image width
63341       * @param  {Integer} dh destination image height
63342       *
63343       * @example
63344       * <div><code>
63345       * let img;
63346       *
63347       * function preload() {
63348       *   img = loadImage('assets/rockies.jpg');
63349       * }
63350       *
63351       * function setup() {
63352       *   background(img);
63353       *   copy(img, 7, 22, 10, 10, 35, 25, 50, 50);
63354       *   stroke(255);
63355       *   noFill();
63356       *   // Rectangle shows area being copied
63357       *   rect(7, 22, 10, 10);
63358       * }
63359       * </code></div>
63360       *
63361       * @alt
63362       * image of rocky mountains. Brick images on left and right. Right overexposed
63363       * image of rockies. Brickwall images on left and right. Right mortar transparent
63364       * image of rockies. Brickwall images on left and right. Right translucent
63365       *
63366       */
63367
63368      /**
63369       * @method copy
63370       * @param  {Integer} sx
63371       * @param  {Integer} sy
63372       * @param  {Integer} sw
63373       * @param  {Integer} sh
63374       * @param  {Integer} dx
63375       * @param  {Integer} dy
63376       * @param  {Integer} dw
63377       * @param  {Integer} dh
63378       */
63379
63380
63381      p5.prototype.copy = function () {
63382        p5._validateParameters('copy', arguments);
63383
63384        p5.Renderer2D.prototype.copy.apply(this._renderer, arguments);
63385      };
63386      /**
63387       * Applies a filter to the canvas.
63388       * <br><br>
63389       *
63390       * The presets options are:
63391       * <br><br>
63392       *
63393       * THRESHOLD
63394       * Converts the image to black and white pixels depending if they are above or
63395       * below the threshold defined by the level parameter. The parameter must be
63396       * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used.
63397       * <br><br>
63398       *
63399       * GRAY
63400       * Converts any colors in the image to grayscale equivalents. No parameter
63401       * is used.
63402       * <br><br>
63403       *
63404       * OPAQUE
63405       * Sets the alpha channel to entirely opaque. No parameter is used.
63406       * <br><br>
63407       *
63408       * INVERT
63409       * Sets each pixel to its inverse value. No parameter is used.
63410       * <br><br>
63411       *
63412       * POSTERIZE
63413       * Limits each channel of the image to the number of colors specified as the
63414       * parameter. The parameter can be set to values between 2 and 255, but
63415       * results are most noticeable in the lower ranges.
63416       * <br><br>
63417       *
63418       * BLUR
63419       * Executes a Gaussian blur with the level parameter specifying the extent
63420       * of the blurring. If no parameter is used, the blur is equivalent to
63421       * Gaussian blur of radius 1. Larger values increase the blur.
63422       * <br><br>
63423       *
63424       * ERODE
63425       * Reduces the light areas. No parameter is used.
63426       * <br><br>
63427       *
63428       * DILATE
63429       * Increases the light areas. No parameter is used.
63430       *
63431       * @method filter
63432       * @param  {Constant} filterType  either THRESHOLD, GRAY, OPAQUE, INVERT,
63433       *                                POSTERIZE, BLUR, ERODE, DILATE or BLUR.
63434       *                                See Filters.js for docs on
63435       *                                each available filter
63436       * @param  {Number} [filterParam] an optional parameter unique
63437       *                                to each filter, see above
63438       *
63439       * @example
63440       * <div>
63441       * <code>
63442       * let img;
63443       * function preload() {
63444       *   img = loadImage('assets/bricks.jpg');
63445       * }
63446       * function setup() {
63447       *   image(img, 0, 0);
63448       *   filter(THRESHOLD);
63449       * }
63450       * </code>
63451       * </div>
63452       *
63453       * <div>
63454       * <code>
63455       * let img;
63456       * function preload() {
63457       *   img = loadImage('assets/bricks.jpg');
63458       * }
63459       * function setup() {
63460       *   image(img, 0, 0);
63461       *   filter(GRAY);
63462       * }
63463       * </code>
63464       * </div>
63465       *
63466       * <div>
63467       * <code>
63468       * let img;
63469       * function preload() {
63470       *   img = loadImage('assets/bricks.jpg');
63471       * }
63472       * function setup() {
63473       *   image(img, 0, 0);
63474       *   filter(OPAQUE);
63475       * }
63476       * </code>
63477       * </div>
63478       *
63479       * <div>
63480       * <code>
63481       * let img;
63482       * function preload() {
63483       *   img = loadImage('assets/bricks.jpg');
63484       * }
63485       * function setup() {
63486       *   image(img, 0, 0);
63487       *   filter(INVERT);
63488       * }
63489       * </code>
63490       * </div>
63491       *
63492       * <div>
63493       * <code>
63494       * let img;
63495       * function preload() {
63496       *   img = loadImage('assets/bricks.jpg');
63497       * }
63498       * function setup() {
63499       *   image(img, 0, 0);
63500       *   filter(POSTERIZE, 3);
63501       * }
63502       * </code>
63503       * </div>
63504       *
63505       * <div>
63506       * <code>
63507       * let img;
63508       * function preload() {
63509       *   img = loadImage('assets/bricks.jpg');
63510       * }
63511       * function setup() {
63512       *   image(img, 0, 0);
63513       *   filter(DILATE);
63514       * }
63515       * </code>
63516       * </div>
63517       *
63518       * <div>
63519       * <code>
63520       * let img;
63521       * function preload() {
63522       *   img = loadImage('assets/bricks.jpg');
63523       * }
63524       * function setup() {
63525       *   image(img, 0, 0);
63526       *   filter(BLUR, 3);
63527       * }
63528       * </code>
63529       * </div>
63530       *
63531       * <div>
63532       * <code>
63533       * let img;
63534       * function preload() {
63535       *   img = loadImage('assets/bricks.jpg');
63536       * }
63537       * function setup() {
63538       *   image(img, 0, 0);
63539       *   filter(ERODE);
63540       * }
63541       * </code>
63542       * </div>
63543       *
63544       * @alt
63545       * black and white image of a brick wall.
63546       * greyscale image of a brickwall
63547       * image of a brickwall
63548       * jade colored image of a brickwall
63549       * red and pink image of a brickwall
63550       * image of a brickwall
63551       * blurry image of a brickwall
63552       * image of a brickwall
63553       * image of a brickwall with less detail
63554       *
63555       */
63556
63557
63558      p5.prototype.filter = function (operation, value) {
63559        p5._validateParameters('filter', arguments);
63560
63561        if (this.canvas !== undefined) {
63562          Filters.apply(this.canvas, Filters[operation.toLowerCase()], value);
63563        } else {
63564          Filters.apply(this.elt, Filters[operation.toLowerCase()], value);
63565        }
63566      };
63567      /**
63568       * Returns an array of [R,G,B,A] values for any pixel or grabs a section of
63569       * an image. If no parameters are specified, the entire image is returned.
63570       * Use the x and y parameters to get the value of one pixel. Get a section of
63571       * the display window by specifying additional w and h parameters. When
63572       * getting an image, the x and y parameters define the coordinates for the
63573       * upper-left corner of the image, regardless of the current <a href="#/p5/imageMode">imageMode()</a>.
63574       * <br><br>
63575       * If the pixel requested is outside of the image window, [0,0,0,255] is
63576       * returned. To get the numbers scaled according to the current color ranges
63577       * and taking into account <a href="#/p5/colorMode">colorMode</a>, use <a href="#/p5/getColor">getColor</a> instead of get.
63578       * <br><br>
63579       * Getting the color of a single pixel with get(x, y) is easy, but not as fast
63580       * as grabbing the data directly from <a href="#/p5/pixels">pixels[]</a>. The equivalent statement to
63581       * get(x, y) using <a href="#/p5/pixels">pixels[]</a> with pixel density d is
63582       * ```javascript
63583       * let x, y, d; // set these to the coordinates
63584       * let off = (y * width + x) * d * 4;
63585       * let components = [
63586       *   pixels[off],
63587       *   pixels[off + 1],
63588       *   pixels[off + 2],
63589       *   pixels[off + 3]
63590       * ];
63591       * print(components);
63592       * ```
63593       * <br><br>
63594       * See the reference for <a href="#/p5/pixels">pixels[]</a> for more information.
63595       *
63596       * If you want to extract an array of colors or a subimage from an p5.Image object,
63597       * take a look at <a href="#/p5.Image/get">p5.Image.get()</a>
63598       *
63599       * @method get
63600       * @param  {Number}         [x] x-coordinate of the pixel
63601       * @param  {Number}         [y] y-coordinate of the pixel
63602       * @param  {Number}         [w] width
63603       * @param  {Number}         [h] height
63604       * @return {Number[]|p5.Image}  values of pixel at x,y in array format
63605       *                              [R, G, B, A] or <a href="#/p5.Image">p5.Image</a>
63606       * @example
63607       * <div>
63608       * <code>
63609       * let img;
63610       * function preload() {
63611       *   img = loadImage('assets/rockies.jpg');
63612       * }
63613       * function setup() {
63614       *   image(img, 0, 0);
63615       *   let c = get();
63616       *   image(c, width / 2, 0);
63617       * }
63618       * </code>
63619       * </div>
63620       *
63621       * <div>
63622       * <code>
63623       * let img;
63624       * function preload() {
63625       *   img = loadImage('assets/rockies.jpg');
63626       * }
63627       * function setup() {
63628       *   image(img, 0, 0);
63629       *   let c = get(50, 90);
63630       *   fill(c);
63631       *   noStroke();
63632       *   rect(25, 25, 50, 50);
63633       * }
63634       * </code>
63635       * </div>
63636       *
63637       * @alt
63638       * 2 images of the rocky mountains, side-by-side
63639       * Image of the rocky mountains with 50x50 green rect in center of canvas
63640       *
63641       */
63642
63643
63644      p5.prototype.get = function (x, y, w, h) {
63645        if (typeof w === 'undefined' && typeof h === 'undefined') {
63646          if (typeof x === 'undefined' && typeof y === 'undefined') {
63647            x = y = 0;
63648            w = this.width;
63649            h = this.height;
63650          } else {
63651            w = h = 1;
63652          }
63653        } // if the section does not overlap the canvas
63654
63655
63656        if (x + w < 0 || y + h < 0 || x >= this.width || y >= this.height) {
63657          // TODO: is this valid for w,h > 1 ?
63658          return [0, 0, 0, 255];
63659        } // round down to get integer numbers
63660
63661
63662        x = Math.floor(x);
63663        y = Math.floor(y);
63664        w = Math.floor(w);
63665        h = Math.floor(h);
63666
63667        if (this instanceof p5.Image) {
63668          return p5.Renderer2D.prototype.get.call(this, x, y, w, h);
63669        } else {
63670          return this._renderer.get(x, y, w, h);
63671        }
63672      };
63673      /**
63674       * Loads the pixel data for the display window into the <a href="#/p5/pixels">pixels[]</a> array. This
63675       * function must always be called before reading from or writing to <a href="#/p5/pixels">pixels[]</a>.
63676       * Note that only changes made with <a href="#/p5/set">set()</a> or direct manipulation of <a href="#/p5/pixels">pixels[]</a>
63677       * will occur.
63678       *
63679       * @method loadPixels
63680       * @example
63681       * <div>
63682       * <code>
63683       * let img;
63684       * function preload() {
63685       *   img = loadImage('assets/rockies.jpg');
63686       * }
63687       *
63688       * function setup() {
63689       *   image(img, 0, 0);
63690       *   let d = pixelDensity();
63691       *   let halfImage = 4 * (img.width * d) * (img.height * d / 2);
63692       *   loadPixels();
63693       *   for (let i = 0; i < halfImage; i++) {
63694       *     pixels[i + halfImage] = pixels[i];
63695       *   }
63696       *   updatePixels();
63697       * }
63698       * </code>
63699       * </div>
63700       *
63701       * @alt
63702       * two images of the rocky mountains. one on top, one on bottom of canvas.
63703       *
63704       */
63705
63706
63707      p5.prototype.loadPixels = function () {
63708        p5._validateParameters('loadPixels', arguments);
63709
63710        this._renderer.loadPixels();
63711      };
63712      /**
63713       * <p>Changes the color of any pixel, or writes an image directly to the
63714       * display window.</p>
63715       * <p>The x and y parameters specify the pixel to change and the c parameter
63716       * specifies the color value. This can be a <a href="#/p5.Color">p5.Color</a> object, or [R, G, B, A]
63717       * pixel array. It can also be a single grayscale value.
63718       * When setting an image, the x and y parameters define the coordinates for
63719       * the upper-left corner of the image, regardless of the current <a href="#/p5/imageMode">imageMode()</a>.
63720       * </p>
63721       * <p>
63722       * After using <a href="#/p5/set">set()</a>, you must call <a href="#/p5/updatePixels">updatePixels()</a> for your changes to appear.
63723       * This should be called once all pixels have been set, and must be called before
63724       * calling .<a href="#/p5/get">get()</a> or drawing the image.
63725       * </p>
63726       * <p>Setting the color of a single pixel with set(x, y) is easy, but not as
63727       * fast as putting the data directly into <a href="#/p5/pixels">pixels[]</a>. Setting the <a href="#/p5/pixels">pixels[]</a>
63728       * values directly may be complicated when working with a retina display,
63729       * but will perform better when lots of pixels need to be set directly on
63730       * every loop.</p>
63731       * <p>See the reference for <a href="#/p5/pixels">pixels[]</a> for more information.</p>
63732       *
63733       * @method set
63734       * @param {Number}              x x-coordinate of the pixel
63735       * @param {Number}              y y-coordinate of the pixel
63736       * @param {Number|Number[]|Object} c insert a grayscale value | a pixel array |
63737       *                                a <a href="#/p5.Color">p5.Color</a> object | a <a href="#/p5.Image">p5.Image</a> to copy
63738       * @example
63739       * <div>
63740       * <code>
63741       * let black = color(0);
63742       * set(30, 20, black);
63743       * set(85, 20, black);
63744       * set(85, 75, black);
63745       * set(30, 75, black);
63746       * updatePixels();
63747       * </code>
63748       * </div>
63749       *
63750       * <div>
63751       * <code>
63752       * for (let i = 30; i < width - 15; i++) {
63753       *   for (let j = 20; j < height - 25; j++) {
63754       *     let c = color(204 - j, 153 - i, 0);
63755       *     set(i, j, c);
63756       *   }
63757       * }
63758       * updatePixels();
63759       * </code>
63760       * </div>
63761       *
63762       * <div>
63763       * <code>
63764       * let img;
63765       * function preload() {
63766       *   img = loadImage('assets/rockies.jpg');
63767       * }
63768       *
63769       * function setup() {
63770       *   set(0, 0, img);
63771       *   updatePixels();
63772       *   line(0, 0, width, height);
63773       *   line(0, height, width, 0);
63774       * }
63775       * </code>
63776       * </div>
63777       *
63778       * @alt
63779       * 4 black points in the shape of a square middle-right of canvas.
63780       * square with orangey-brown gradient lightening at bottom right.
63781       * image of the rocky mountains. with lines like an 'x' through the center.
63782       */
63783
63784
63785      p5.prototype.set = function (x, y, imgOrCol) {
63786        this._renderer.set(x, y, imgOrCol);
63787      };
63788      /**
63789       * Updates the display window with the data in the <a href="#/p5/pixels">pixels[]</a> array.
63790       * Use in conjunction with <a href="#/p5/loadPixels">loadPixels()</a>. If you're only reading pixels from
63791       * the array, there's no need to call <a href="#/p5/updatePixels">updatePixels()</a> — updating is only
63792       * necessary to apply changes. <a href="#/p5/updatePixels">updatePixels()</a> should be called anytime the
63793       * pixels array is manipulated or <a href="#/p5/set">set()</a> is called, and only changes made with
63794       * <a href="#/p5/set">set()</a> or direct changes to <a href="#/p5/pixels">pixels[]</a> will occur.
63795       *
63796       * @method updatePixels
63797       * @param  {Number} [x]    x-coordinate of the upper-left corner of region
63798       *                         to update
63799       * @param  {Number} [y]    y-coordinate of the upper-left corner of region
63800       *                         to update
63801       * @param  {Number} [w]    width of region to update
63802       * @param  {Number} [h]    height of region to update
63803       * @example
63804       * <div>
63805       * <code>
63806       * let img;
63807       * function preload() {
63808       *   img = loadImage('assets/rockies.jpg');
63809       * }
63810       *
63811       * function setup() {
63812       *   image(img, 0, 0);
63813       *   let d = pixelDensity();
63814       *   let halfImage = 4 * (img.width * d) * (img.height * d / 2);
63815       *   loadPixels();
63816       *   for (let i = 0; i < halfImage; i++) {
63817       *     pixels[i + halfImage] = pixels[i];
63818       *   }
63819       *   updatePixels();
63820       * }
63821       * </code>
63822       * </div>
63823       * @alt
63824       * two images of the rocky mountains. one on top, one on bottom of canvas.
63825       */
63826
63827
63828      p5.prototype.updatePixels = function (x, y, w, h) {
63829        p5._validateParameters('updatePixels', arguments); // graceful fail - if loadPixels() or set() has not been called, pixel
63830        // array will be empty, ignore call to updatePixels()
63831
63832
63833        if (this.pixels.length === 0) {
63834          return;
63835        }
63836
63837        this._renderer.updatePixels(x, y, w, h);
63838      };
63839
63840      module.exports = p5;
63841    }, {
63842      "../color/p5.Color": 16,
63843      "../core/main": 24,
63844      "./filters": 42
63845    }],
63846    47: [function (_dereq_, module, exports) {
63847      /**
63848       * @module IO
63849       * @submodule Input
63850       * @for p5
63851       * @requires core
63852       */
63853
63854      /* globals Request: false */
63855
63856      /* globals Headers: false */
63857      'use strict';
63858
63859      var p5 = _dereq_('../core/main');
63860
63861      _dereq_('whatwg-fetch');
63862
63863      _dereq_('es6-promise').polyfill();
63864
63865      var fetchJsonp = _dereq_('fetch-jsonp');
63866
63867      _dereq_('../core/error_helpers');
63868      /**
63869       * Loads a JSON file from a file or a URL, and returns an Object.
63870       * Note that even if the JSON file contains an Array, an Object will be
63871       * returned with index numbers as keys.
63872       *
63873       * This method is asynchronous, meaning it may not finish before the next
63874       * line in your sketch is executed. JSONP is supported via a polyfill and you
63875       * can pass in as the second argument an object with definitions of the json
63876       * callback following the syntax specified <a href="https://github.com/camsong/
63877       * fetch-jsonp">here</a>.
63878       *
63879       * This method is suitable for fetching files up to size of 64MB.
63880       * @method loadJSON
63881       * @param  {String}        path       name of the file or url to load
63882       * @param  {Object}        [jsonpOptions] options object for jsonp related settings
63883       * @param  {String}        [datatype] "json" or "jsonp"
63884       * @param  {function}      [callback] function to be executed after
63885       *                                    <a href="#/p5/loadJSON">loadJSON()</a> completes, data is passed
63886       *                                    in as first argument
63887       * @param  {function}      [errorCallback] function to be executed if
63888       *                                    there is an error, response is passed
63889       *                                    in as first argument
63890       * @return {Object|Array}             JSON data
63891       * @example
63892       *
63893       * <p>Calling <a href="#/p5/loadJSON">loadJSON()</a> inside <a href="#/p5/preload">preload()</a> guarantees to complete the
63894       * operation before <a href="#/p5/setup">setup()</a> and <a href="#/p5/draw">draw()</a> are called.</p>
63895       *
63896       * <div><code>
63897       * // Examples use USGS Earthquake API:
63898       * //   https://earthquake.usgs.gov/fdsnws/event/1/#methods
63899       * let earthquakes;
63900       * function preload() {
63901       *   // Get the most recent earthquake in the database
63902       *   let url =
63903          'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' +
63904       *     'summary/all_day.geojson';
63905       *   earthquakes = loadJSON(url);
63906       * }
63907       *
63908       * function setup() {
63909       *   noLoop();
63910       * }
63911       *
63912       * function draw() {
63913       *   background(200);
63914       *   // Get the magnitude and name of the earthquake out of the loaded JSON
63915       *   let earthquakeMag = earthquakes.features[0].properties.mag;
63916       *   let earthquakeName = earthquakes.features[0].properties.place;
63917       *   ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);
63918       *   textAlign(CENTER);
63919       *   text(earthquakeName, 0, height - 30, width, 30);
63920       * }
63921       * </code></div>
63922       *
63923       *
63924       * <p>Outside of preload(), you may supply a callback function to handle the
63925       * object:</p>
63926       * <div><code>
63927       * function setup() {
63928       *   noLoop();
63929       *   let url =
63930          'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' +
63931       *     'summary/all_day.geojson';
63932       *   loadJSON(url, drawEarthquake);
63933       * }
63934       *
63935       * function draw() {
63936       *   background(200);
63937       * }
63938       *
63939       * function drawEarthquake(earthquakes) {
63940       *   // Get the magnitude and name of the earthquake out of the loaded JSON
63941       *   let earthquakeMag = earthquakes.features[0].properties.mag;
63942       *   let earthquakeName = earthquakes.features[0].properties.place;
63943       *   ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);
63944       *   textAlign(CENTER);
63945       *   text(earthquakeName, 0, height - 30, width, 30);
63946       * }
63947       * </code></div>
63948       *
63949       * @alt
63950       * 50x50 ellipse that changes from black to white depending on the current humidity
63951       * 50x50 ellipse that changes from black to white depending on the current humidity
63952       *
63953       */
63954
63955      /**
63956       * @method loadJSON
63957       * @param  {String}        path
63958       * @param  {String}        datatype
63959       * @param  {function}      [callback]
63960       * @param  {function}      [errorCallback]
63961       * @return {Object|Array}
63962       */
63963
63964      /**
63965       * @method loadJSON
63966       * @param  {String}        path
63967       * @param  {function}      callback
63968       * @param  {function}      [errorCallback]
63969       * @return {Object|Array}
63970       */
63971
63972
63973      p5.prototype.loadJSON = function () {
63974        p5._validateParameters('loadJSON', arguments);
63975
63976        var path = arguments[0];
63977        var callback;
63978        var errorCallback;
63979        var options;
63980        var ret = {}; // object needed for preload
63981
63982        var t = 'json'; // check for explicit data type argument
63983
63984        for (var i = 1; i < arguments.length; i++) {
63985          var arg = arguments[i];
63986
63987          if (typeof arg === 'string') {
63988            if (arg === 'jsonp' || arg === 'json') {
63989              t = arg;
63990            }
63991          } else if (typeof arg === 'function') {
63992            if (!callback) {
63993              callback = arg;
63994            } else {
63995              errorCallback = arg;
63996            }
63997          } else if (typeof arg === 'object' && arg.hasOwnProperty('jsonpCallback')) {
63998            t = 'jsonp';
63999            options = arg;
64000          }
64001        }
64002
64003        var self = this;
64004        this.httpDo(path, 'GET', options, t, function (resp) {
64005          for (var k in resp) {
64006            ret[k] = resp[k];
64007          }
64008
64009          if (typeof callback !== 'undefined') {
64010            callback(resp);
64011          }
64012
64013          self._decrementPreload();
64014        }, function (err) {
64015          // Error handling
64016          p5._friendlyFileLoadError(5, path);
64017
64018          if (errorCallback) {
64019            errorCallback(err);
64020          } else {
64021            throw err;
64022          }
64023        });
64024        return ret;
64025      };
64026      /**
64027       * Reads the contents of a file and creates a String array of its individual
64028       * lines. If the name of the file is used as the parameter, as in the above
64029       * example, the file must be located in the sketch directory/folder.
64030       * <br><br>
64031       * Alternatively, the file maybe be loaded from anywhere on the local
64032       * computer using an absolute path (something that starts with / on Unix and
64033       * Linux, or a drive letter on Windows), or the filename parameter can be a
64034       * URL for a file found on a network.
64035       * <br><br>
64036       * This method is asynchronous, meaning it may not finish before the next
64037       * line in your sketch is executed.
64038       *
64039       * This method is suitable for fetching files up to size of 64MB.
64040       * @method loadStrings
64041       * @param  {String}   filename   name of the file or url to load
64042       * @param  {function} [callback] function to be executed after <a href="#/p5/loadStrings">loadStrings()</a>
64043       *                               completes, Array is passed in as first
64044       *                               argument
64045       * @param  {function} [errorCallback] function to be executed if
64046       *                               there is an error, response is passed
64047       *                               in as first argument
64048       * @return {String[]}            Array of Strings
64049       * @example
64050       *
64051       * <p>Calling loadStrings() inside <a href="#/p5/preload">preload()</a> guarantees to complete the
64052       * operation before <a href="#/p5/setup">setup()</a> and <a href="#/p5/draw">draw()</a> are called.</p>
64053       *
64054       * <div><code>
64055       * let result;
64056       * function preload() {
64057       *   result = loadStrings('assets/test.txt');
64058       * }
64059      
64060       * function setup() {
64061       *   background(200);
64062       *   let ind = floor(random(result.length));
64063       *   text(result[ind], 10, 10, 80, 80);
64064       * }
64065       * </code></div>
64066       *
64067       * <p>Outside of preload(), you may supply a callback function to handle the
64068       * object:</p>
64069       *
64070       * <div><code>
64071       * function setup() {
64072       *   loadStrings('assets/test.txt', pickString);
64073       * }
64074       *
64075       * function pickString(result) {
64076       *   background(200);
64077       *   let ind = floor(random(result.length));
64078       *   text(result[ind], 10, 10, 80, 80);
64079       * }
64080       * </code></div>
64081       *
64082       * @alt
64083       * randomly generated text from a file, for example "i smell like butter"
64084       * randomly generated text from a file, for example "i have three feet"
64085       *
64086       */
64087
64088
64089      p5.prototype.loadStrings = function () {
64090        p5._validateParameters('loadStrings', arguments);
64091
64092        var ret = [];
64093        var callback, errorCallback;
64094
64095        for (var i = 1; i < arguments.length; i++) {
64096          var arg = arguments[i];
64097
64098          if (typeof arg === 'function') {
64099            if (typeof callback === 'undefined') {
64100              callback = arg;
64101            } else if (typeof errorCallback === 'undefined') {
64102              errorCallback = arg;
64103            }
64104          }
64105        }
64106
64107        var self = this;
64108        p5.prototype.httpDo.call(this, arguments[0], 'GET', 'text', function (data) {
64109          // split lines handling mac/windows/linux endings
64110          var lines = data.replace(/\r\n/g, '\r').replace(/\n/g, '\r').split(/\r/);
64111          Array.prototype.push.apply(ret, lines);
64112
64113          if (typeof callback !== 'undefined') {
64114            callback(ret);
64115          }
64116
64117          self._decrementPreload();
64118        }, function (err) {
64119          // Error handling
64120          p5._friendlyFileLoadError(3, arguments[0]);
64121
64122          if (errorCallback) {
64123            errorCallback(err);
64124          } else {
64125            throw err;
64126          }
64127        });
64128        return ret;
64129      };
64130      /**
64131       * <p>Reads the contents of a file or URL and creates a <a href="#/p5.Table">p5.Table</a> object with
64132       * its values. If a file is specified, it must be located in the sketch's
64133       * "data" folder. The filename parameter can also be a URL to a file found
64134       * online. By default, the file is assumed to be comma-separated (in CSV
64135       * format). Table only looks for a header row if the 'header' option is
64136       * included.</p>
64137       *
64138       * <p>Possible options include:
64139       * <ul>
64140       * <li>csv - parse the table as comma-separated values</li>
64141       * <li>tsv - parse the table as tab-separated values</li>
64142       * <li>header - this table has a header (title) row</li>
64143       * </ul>
64144       * </p>
64145       *
64146       * <p>When passing in multiple options, pass them in as separate parameters,
64147       * seperated by commas. For example:
64148       * <br><br>
64149       * <code>
64150       * loadTable('my_csv_file.csv', 'csv', 'header');
64151       * </code>
64152       * </p>
64153       *
64154       * <p> All files loaded and saved use UTF-8 encoding.</p>
64155       *
64156       * <p>This method is asynchronous, meaning it may not finish before the next
64157       * line in your sketch is executed. Calling <a href="#/p5/loadTable">loadTable()</a> inside <a href="#/p5/preload">preload()</a>
64158       * guarantees to complete the operation before <a href="#/p5/setup">setup()</a> and <a href="#/p5/draw">draw()</a> are called.
64159       * <p>Outside of <a href="#/p5/preload">preload()</a>, you may supply a callback function to handle the
64160       * object:</p>
64161       * </p>
64162       *
64163       * This method is suitable for fetching files up to size of 64MB.
64164       * @method loadTable
64165       * @param  {String}         filename   name of the file or URL to load
64166       * @param  {String}         options  "header" "csv" "tsv"
64167       * @param  {function}       [callback] function to be executed after
64168       *                                     <a href="#/p5/loadTable">loadTable()</a> completes. On success, the
64169       *                                     <a href="#/p5.Table">Table</a> object is passed in as the
64170       *                                     first argument.
64171       * @param  {function}  [errorCallback] function to be executed if
64172       *                                     there is an error, response is passed
64173       *                                     in as first argument
64174       * @return {Object}                    <a href="#/p5.Table">Table</a>
64174 object containing data
64175       *
64176       * @example
64177       * <div class='norender'>
64178       * <code>
64179       * // Given the following CSV file called "mammals.csv"
64180       * // located in the project's "assets" folder:
64181       * //
64182       * // id,species,name
64183       * // 0,Capra hircus,Goat
64184       * // 1,Panthera pardus,Leopard
64185       * // 2,Equus zebra,Zebra
64186       *
64187       * let table;
64188       *
64189       * function preload() {
64190       *   //my table is comma separated value "csv"
64191       *   //and has a header specifying the columns labels
64192       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
64193       *   //the file can be remote
64194       *   //table = loadTable("http://p5js.org/reference/assets/mammals.csv",
64195       *   //                  "csv", "header");
64196       * }
64197       *
64198       * function setup() {
64199       *   //count the columns
64200       *   print(table.getRowCount() + ' total rows in table');
64201       *   print(table.getColumnCount() + ' total columns in table');
64202       *
64203       *   print(table.getColumn('name'));
64204       *   //["Goat", "Leopard", "Zebra"]
64205       *
64206       *   //cycle through the table
64207       *   for (let r = 0; r < table.getRowCount(); r++)
64208       *     for (let c = 0; c < table.getColumnCount(); c++) {
64209       *       print(table.getString(r, c));
64210       *     }
64211       * }
64212       * </code>
64213       * </div>
64214       *
64215       * @alt
64216       * randomly generated text from a file, for example "i smell like butter"
64217       * randomly generated text from a file, for example "i have three feet"
64218       *
64219       */
64220
64221      /**
64222       * @method loadTable
64223       * @param  {String}         filename
64224       * @param  {function}       [callback]
64225       * @param  {function}  [errorCallback]
64226       * @return {Object}
64227       */
64228
64229
64230      p5.prototype.loadTable = function (path) {
64231        var callback;
64232        var errorCallback;
64233        var options = [];
64234        var header = false;
64235        var ext = path.substring(path.lastIndexOf('.') + 1, path.length);
64236        var sep = ',';
64237        var separatorSet = false;
64238
64239        if (ext === 'tsv') {
64240          //Only need to check extension is tsv because csv is default
64241          sep = '\t';
64242        }
64243
64244        for (var i = 1; i < arguments.length; i++) {
64245          if (typeof arguments[i] === 'function') {
64246            if (typeof callback === 'undefined') {
64247              callback = arguments[i];
64248            } else if (typeof errorCallback === 'undefined') {
64249              errorCallback = arguments[i];
64250            }
64251          } else if (typeof arguments[i] === 'string') {
64252            options.push(arguments[i]);
64253
64254            if (arguments[i] === 'header') {
64255              header = true;
64256            }
64257
64258            if (arguments[i] === 'csv') {
64259              if (separatorSet) {
64260                throw new Error('Cannot set multiple separator types.');
64261              } else {
64262                sep = ',';
64263                separatorSet = true;
64264              }
64265            } else if (arguments[i] === 'tsv') {
64266              if (separatorSet) {
64267                throw new Error('Cannot set multiple separator types.');
64268              } else {
64269                sep = '\t';
64270                separatorSet = true;
64271              }
64272            }
64273          }
64274        }
64275
64276        var t = new p5.Table();
64277        var self = this;
64278        this.httpDo(path, 'GET', 'table', function (resp) {
64279          var state = {}; // define constants
64280
64281          var PRE_TOKEN = 0,
64282              MID_TOKEN = 1,
64283              POST_TOKEN = 2,
64284              POST_RECORD = 4;
64285          var QUOTE = '"',
64286              CR = '\r',
64287              LF = '\n';
64288          var records = [];
64289          var offset = 0;
64290          var currentRecord = null;
64291          var currentChar;
64292
64293          var tokenBegin = function () {
64294            state.currentState = PRE_TOKEN;
64295            state.token = '';
64296          };
64297
64298          var tokenEnd = function () {
64299            currentRecord.push(state.token);
64300            tokenBegin();
64301          };
64302
64303          var recordBegin = function () {
64304            state.escaped = false;
64305            currentRecord = [];
64306            tokenBegin();
64307          };
64308
64309          var recordEnd = function () {
64310            state.currentState = POST_RECORD;
64311            records.push(currentRecord);
64312            currentRecord = null;
64313          };
64314
64315          for (;;) {
64316            currentChar = resp[offset++]; // EOF
64317
64318            if (currentChar == null) {
64319              if (state.escaped) {
64320                throw new Error('Unclosed quote in file.');
64321              }
64322
64323              if (currentRecord) {
64324                tokenEnd();
64325                recordEnd();
64326                break;
64327              }
64328            }
64329
64330            if (currentRecord === null) {
64331              recordBegin();
64332            } // Handle opening quote
64333
64334
64335            if (state.currentState === PRE_TOKEN) {
64336              if (currentChar === QUOTE) {
64337                state.escaped = true;
64338                state.currentState = MID_TOKEN;
64339                continue;
64340              }
64341
64342              state.currentState = MID_TOKEN;
64343            } // mid-token and escaped, look for sequences and end quote
64344
64345
64346            if (state.currentState === MID_TOKEN && state.escaped) {
64347              if (currentChar === QUOTE) {
64348                if (resp[offset] === QUOTE) {
64349                  state.token += QUOTE;
64350                  offset++;
64351                } else {
64352                  state.escaped = false;
64353                  state.currentState = POST_TOKEN;
64354                }
64355              } else if (currentChar === CR) {
64356                continue;
64357              } else {
64358                state.token += currentChar;
64359              }
64360
64361              continue;
64362            } // fall-through: mid-token or post-token, not escaped
64363
64364
64365            if (currentChar === CR) {
64366              if (resp[offset] === LF) {
64367                offset++;
64368              }
64369
64370              tokenEnd();
64371              recordEnd();
64372            } else if (currentChar === LF) {
64373              tokenEnd();
64374              recordEnd();
64375            } else if (currentChar === sep) {
64376              tokenEnd();
64377            } else if (state.currentState === MID_TOKEN) {
64378              state.token += currentChar;
64379            }
64380          } // set up column names
64381
64382
64383          if (header) {
64384            t.columns = records.shift();
64385          } else {
64386            for (i = 0; i < records[0].length; i++) {
64387              t.columns[i] = 'null';
64388            }
64389          }
64390
64391          var row;
64392
64393          for (i = 0; i < records.length; i++) {
64394            //Handles row of 'undefined' at end of some CSVs
64395            if (records[i].length === 1) {
64396              if (records[i][0] === 'undefined' || records[i][0] === '') {
64397                continue;
64398              }
64399            }
64400
64401            row = new p5.TableRow();
64402            row.arr = records[i];
64403            row.obj = makeObject(records[i], t.columns);
64404            t.addRow(row);
64405          }
64406
64407          if (typeof callback === 'function') {
64408            callback(t);
64409          }
64410
64411          self._decrementPreload();
64412        }, function (err) {
64413          // Error handling
64414          p5._friendlyFileLoadError(2, path);
64415
64416          if (errorCallback) {
64417            errorCallback(err);
64418          } else {
64419            console.error(err);
64420          }
64421        });
64422        return t;
64423      }; // helper function to turn a row into a JSON object
64424
64425
64426      function makeObject(row, headers) {
64427        var ret = {};
64428        headers = headers || [];
64429
64430        if (typeof headers === 'undefined') {
64431          for (var j = 0; j < row.length; j++) {
64432            headers[j.toString()] = j;
64433          }
64434        }
64435
64436        for (var i = 0; i < headers.length; i++) {
64437          var key = headers[i];
64438          var val = row[i];
64439          ret[key] = val;
64440        }
64441
64442        return ret;
64443      }
64444      /**
64445       * Reads the contents of a file and creates an XML object with its values.
64446       * If the name of the file is used as the parameter, as in the above example,
64447       * the file must be located in the sketch directory/folder.
64448       *
64449       * Alternatively, the file maybe be loaded from anywhere on the local
64450       * computer using an absolute path (something that starts with / on Unix and
64451       * Linux, or a drive letter on Windows), or the filename parameter can be a
64452       * URL for a file found on a network.
64453       *
64454       * This method is asynchronous, meaning it may not finish before the next
64455       * line in your sketch is executed. Calling <a href="#/p5/loadXML">loadXML()</a> inside <a href="#/p5/preload">preload()</a>
64456       * guarantees to complete the operation before <a href="#/p5/setup">setup()</a> and <a href="#/p5/draw">draw()</a> are called.
64457       *
64458       * Outside of <a href="#/p5/preload">preload()</a>, you may supply a callback function to handle the
64459       * object.
64460       *
64461       * This method is suitable for fetching files up to size of 64MB.
64462       * @method loadXML
64463       * @param  {String}   filename   name of the file or URL to load
64464       * @param  {function} [callback] function to be executed after <a href="#/p5/loadXML">loadXML()</a>
64465       *                               completes, XML object is passed in as
64466       *                               first argument
64467       * @param  {function} [errorCallback] function to be executed if
64468       *                               there is an error, response is passed
64469       *                               in as first argument
64470       * @return {Object}              XML object containing data
64471       * @example
64472       * <div class='norender'><code>
64473       * // The following short XML file called "mammals.xml" is parsed
64474       * // in the code below.
64475       * //
64476       * // <?xml version="1.0"?>
64477       * // &lt;mammals&gt;
64478       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
64479       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
64480       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
64481       * // &lt;/mammals&gt;
64482       *
64483       * let xml;
64484       *
64485       * function preload() {
64486       *   xml = loadXML('assets/mammals.xml');
64487       * }
64488       *
64489       * function setup() {
64490       *   let children = xml.getChildren('animal');
64491       *
64492       *   for (let i = 0; i < children.length; i++) {
64493       *     let id = children[i].getNum('id');
64494       *     let coloring = children[i].getString('species');
64495       *     let name = children[i].getContent();
64496       *     print(id + ', ' + coloring + ', ' + name);
64497       *   }
64498       * }
64499       *
64500       * // Sketch prints:
64501       * // 0, Capra hircus, Goat
64502       * // 1, Panthera pardus, Leopard
64503       * // 2, Equus zebra, Zebra
64504       * </code></div>
64505       *
64506       * @alt
64507       * no image displayed
64508       *
64509       */
64510
64511
64512      p5.prototype.loadXML = function () {
64513        var ret = new p5.XML();
64514        var callback, errorCallback;
64515
64516        for (var i = 1; i < arguments.length; i++) {
64517          var arg = arguments[i];
64518
64519          if (typeof arg === 'function') {
64520            if (typeof callback === 'undefined') {
64521              callback = arg;
64522            } else if (typeof errorCallback === 'undefined') {
64523              errorCallback = arg;
64524            }
64525          }
64526        }
64527
64528        var self = this;
64529        this.httpDo(arguments[0], 'GET', 'xml', function (xml) {
64530          for (var key in xml) {
64531            ret[key] = xml[key];
64532          }
64533
64534          if (typeof callback !== 'undefined') {
64535            callback(ret);
64536          }
64537
64538          self._decrementPreload();
64539        }, function (err) {
64540          // Error handling
64541          p5._friendlyFileLoadError(1, arguments[0]);
64542
64543          if (errorCallback) {
64544            errorCallback(err);
64545          } else {
64546            throw err;
64547          }
64548        });
64549        return ret;
64550      };
64551      /**
64552       * This method is suitable for fetching files up to size of 64MB.
64553       * @method loadBytes
64554       * @param {string}   file            name of the file or URL to load
64555       * @param {function} [callback]      function to be executed after <a href="#/p5/loadBytes">loadBytes()</a>
64556       *                                    completes
64557       * @param {function} [errorCallback] function to be executed if there
64558       *                                    is an error
64559       * @returns {Object} an object whose 'bytes' property will be the loaded buffer
64560       *
64561       * @example
64562       * <div class='norender'><code>
64563       * let data;
64564       *
64565       * function preload() {
64566       *   data = loadBytes('assets/mammals.xml');
64567       * }
64568       *
64569       * function setup() {
64570       *   for (let i = 0; i < 5; i++) {
64571       *     console.log(data.bytes[i].toString(16));
64572       *   }
64573       * }
64574       * </code></div>
64575       *
64576       * @alt
64577       * no image displayed
64578       *
64579       */
64580
64581
64582      p5.prototype.loadBytes = function (file, callback, errorCallback) {
64583        var ret = {};
64584        var self = this;
64585        this.httpDo(file, 'GET', 'arrayBuffer', function (arrayBuffer) {
64586          ret.bytes = new Uint8Array(arrayBuffer);
64587
64588          if (typeof callback === 'function') {
64589            callback(ret);
64590          }
64591
64592          self._decrementPreload();
64593        }, function (err) {
64594          // Error handling
64595          p5._friendlyFileLoadError(6, file);
64596
64597          if (errorCallback) {
64598            errorCallback(err);
64599          } else {
64600            throw err;
64601          }
64602        });
64603        return ret;
64604      };
64605      /**
64606       * Method for executing an HTTP GET request. If data type is not specified,
64607       * p5 will try to guess based on the URL, defaulting to text. This is equivalent to
64608       * calling <code>httpDo(path, 'GET')</code>. The 'binary' datatype will return
64609       * a Blob object, and the 'arrayBuffer' datatype will return an ArrayBuffer
64610       * which can be used to initialize typed arrays (such as Uint8Array).
64611       *
64612       * @method httpGet
64613       * @param  {String}        path       name of the file or url to load
64614       * @param  {String}        [datatype] "json", "jsonp", "binary", "arrayBuffer",
64615       *                                    "xml", or "text"
64616       * @param  {Object|Boolean} [data]    param data passed sent with request
64617       * @param  {function}      [callback] function to be executed after
64618       *                                    <a href="#/p5/httpGet">httpGet()</a> completes, data is passed in
64619       *                                    as first argument
64620       * @param  {function}      [errorCallback] function to be executed if
64621       *                                    there is an error, response is passed
64622       *                                    in as first argument
64623       * @return {Promise} A promise that resolves with the data when the operation
64624       *                   completes successfully or rejects with the error after
64625       *                   one occurs.
64626       * @example
64627       * <div class='norender'><code>
64628       * // Examples use USGS Earthquake API:
64629       * //   https://earthquake.usgs.gov/fdsnws/event/1/#methods
64630       * let earthquakes;
64631       * function preload() {
64632       *   // Get the most recent earthquake in the database
64633       *   let url =
64634          'https://earthquake.usgs.gov/fdsnws/event/1/query?' +
64635       *     'format=geojson&limit=1&orderby=time';
64636       *   httpGet(url, 'jsonp', false, function(response) {
64637       *     // when the HTTP request completes, populate the variable that holds the
64638       *     // earthquake data used in the visualization.
64639       *     earthquakes = response;
64640       *   });
64641       * }
64642       *
64643       * function draw() {
64644       *   if (!earthquakes) {
64645       *     // Wait until the earthquake data has loaded before drawing.
64646       *     return;
64647       *   }
64648       *   background(200);
64649       *   // Get the magnitude and name of the earthquake out of the loaded JSON
64650       *   let earthquakeMag = earthquakes.features[0].properties.mag;
64651       *   let earthquakeName = earthquakes.features[0].properties.place;
64652       *   ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10);
64653       *   textAlign(CENTER);
64654       *   text(earthquakeName, 0, height - 30, width, 30);
64655       *   noLoop();
64656       * }
64657       * </code></div>
64658       */
64659
64660      /**
64661       * @method httpGet
64662       * @param  {String}        path
64663       * @param  {Object|Boolean} data
64664       * @param  {function}      [callback]
64665       * @param  {function}      [errorCallback]
64666       * @return {Promise}
64667       */
64668
64669      /**
64670       * @method httpGet
64671       * @param  {String}        path
64672       * @param  {function}      callback
64673       * @param  {function}      [errorCallback]
64674       * @return {Promise}
64675       */
64676
64677
64678      p5.prototype.httpGet = function () {
64679        p5._validateParameters('httpGet', arguments);
64680
64681        var args = Array.prototype.slice.call(arguments);
64682        args.splice(1, 0, 'GET');
64683        return p5.prototype.httpDo.apply(this, args);
64684      };
64685      /**
64686       * Method for executing an HTTP POST request. If data type is not specified,
64687       * p5 will try to guess based on the URL, defaulting to text. This is equivalent to
64688       * calling <code>httpDo(path, 'POST')</code>.
64689       *
64690       * @method httpPost
64691       * @param  {String}        path       name of the file or url to load
64692       * @param  {String}        [datatype] "json", "jsonp", "xml", or "text".
64693       *                                    If omitted, <a href="#/p5/httpPost">httpPost()</a> will guess.
64694       * @param  {Object|Boolean} [data]    param data passed sent with request
64695       * @param  {function}      [callback] function to be executed after
64696       *                                    <a href="#/p5/httpPost">httpPost()</a> completes, data is passed in
64697       *                                    as first argument
64698       * @param  {function}      [errorCallback] function to be executed if
64699       *                                    there is an error, response is passed
64700       *                                    in as first argument
64701       * @return {Promise} A promise that resolves with the data when the operation
64702       *                   completes successfully or rejects with the error after
64703       *                   one occurs.
64704       *
64705       * @example
64706       * <div>
64707       * <code>
64708       * // Examples use jsonplaceholder.typicode.com for a Mock Data API
64709       *
64710       * let url = 'https://jsonplaceholder.typicode.com/posts';
64711       * let postData = { userId: 1, title: 'p5 Clicked!', body: 'p5.js is way cool.' };
64712       *
64713       * function setup() {
64714       *   createCanvas(800, 800);
64715       * }
64716       *
64717       * function mousePressed() {
64718       *   // Pick new random color values
64719       *   let r = random(255);
64720       *   let g = random(255);
64721       *   let b = random(255);
64722       *
64723       *   httpPost(url, 'json', postData, function(result) {
64724       *     strokeWeight(2);
64725       *     stroke(r, g, b);
64726       *     fill(r, g, b, 127);
64727       *     ellipse(mouseX, mouseY, 200, 200);
64728       *     text(result.body, mouseX, mouseY);
64729       *   });
64730       * }
64731       * </code>
64732       * </div>
64733       *
64734       *
64735       * <div><code>
64736       * let url = 'https://invalidURL'; // A bad URL that will cause errors
64737       * let postData = { title: 'p5 Clicked!', body: 'p5.js is way cool.' };
64738       *
64739       * function setup() {
64740       *   createCanvas(800, 800);
64741       * }
64742       *
64743       * function mousePressed() {
64744       *   // Pick new random color values
64745       *   let r = random(255);
64746       *   let g = random(255);
64747       *   let b = random(255);
64748       *
64749       *   httpPost(
64750       *     url,
64751       *     'json',
64752       *     postData,
64753       *     function(result) {
64754       *       // ... won't be called
64755       *     },
64756       *     function(error) {
64757       *       strokeWeight(2);
64758       *       stroke(r, g, b);
64759       *       fill(r, g, b, 127);
64760       *       text(error.toString(), mouseX, mouseY);
64761       *     }
64762       *   );
64763       * }
64764       * </code></div>
64765       *
64766       */
64767
64768      /**
64769       * @method httpPost
64770       * @param  {String}        path
64771       * @param  {Object|Boolean} data
64772       * @param  {function}      [callback]
64773       * @param  {function}      [errorCallback]
64774       * @return {Promise}
64775       */
64776
64777      /**
64778       * @method httpPost
64779       * @param  {String}        path
64780       * @param  {function}      callback
64781       * @param  {function}      [errorCallback]
64782       * @return {Promise}
64783       */
64784
64785
64786      p5.prototype.httpPost = function () {
64787        p5._validateParameters('httpPost', arguments);
64788
64789        var args = Array.prototype.slice.call(arguments);
64790        args.splice(1, 0, 'POST');
64791        return p5.prototype.httpDo.apply(this, args);
64792      };
64793      /**
64794       * Method for executing an HTTP request. If data type is not specified,
64795       * p5 will try to guess based on the URL, defaulting to text.<br><br>
64796       * For more advanced use, you may also pass in the path as the first argument
64797       * and a object as the second argument, the signature follows the one specified
64798       * in the Fetch API specification.
64799       * This method is suitable for fetching files up to size of 64MB when "GET" is used.
64800       *
64801       * @method httpDo
64802       * @param  {String}        path       name of the file or url to load
64803       * @param  {String}        [method]   either "GET", "POST", or "PUT",
64804       *                                    defaults to "GET"
64805       * @param  {String}        [datatype] "json", "jsonp", "xml", or "text"
64806       * @param  {Object}        [data]     param data passed sent with request
64807       * @param  {function}      [callback] function to be executed after
64808       *                                    <a href="#/p5/httpGet">httpGet()</a> completes, data is passed in
64809       *                                    as first argument
64810       * @param  {function}      [errorCallback] function to be executed if
64811       *                                    there is an error, response is passed
64812       *                                    in as first argument
64813       * @return {Promise} A promise that resolves with the data when the operation
64814       *                   completes successfully or rejects with the error after
64815       *                   one occurs.
64816       *
64817       * @example
64818       * <div>
64819       * <code>
64820       * // Examples use USGS Earthquake API:
64821       * // https://earthquake.usgs.gov/fdsnws/event/1/#methods
64822       *
64823       * // displays an animation of all USGS earthquakes
64824       * let earthquakes;
64825       * let eqFeatureIndex = 0;
64826       *
64827       * function preload() {
64828       *   let url = 'https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson';
64829       *   httpDo(
64830       *     url,
64831       *     {
64832       *       method: 'GET',
64833       *       // Other Request options, like special headers for apis
64834       *       headers: { authorization: 'Bearer secretKey' }
64835       *     },
64836       *     function(res) {
64837       *       earthquakes = res;
64838       *     }
64839       *   );
64840       * }
64841       *
64842       * function draw() {
64843       *   // wait until the data is loaded
64844       *   if (!earthquakes || !earthquakes.features[eqFeatureIndex]) {
64845       *     return;
64846       *   }
64847       *   clear();
64848       *
64849       *   let feature = earthquakes.features[eqFeatureIndex];
64850       *   let mag = feature.properties.mag;
64851       *   let rad = mag / 11 * ((width + height) / 2);
64852       *   fill(255, 0, 0, 100);
64853       *   ellipse(width / 2 + random(-2, 2), height / 2 + random(-2, 2), rad, rad);
64854       *
64855       *   if (eqFeatureIndex >= earthquakes.features.length) {
64856       *     eqFeatureIndex = 0;
64857       *   } else {
64858       *     eqFeatureIndex += 1;
64859       *   }
64860       * }
64861       * </code>
64862       * </div>
64863       */
64864
64865      /**
64866       * @method httpDo
64867       * @param  {String}        path
64868       * @param  {Object}        options   Request object options as documented in the
64869       *                                    "fetch" API
64870       * <a href="https://developer.mozilla.org/en/docs/Web/API/Fetch_API">reference</a>
64871       * @param  {function}      [callback]
64872       * @param  {function}      [errorCallback]
64873       * @return {Promise}
64874       */
64875
64876
64877      p5.prototype.httpDo = function () {
64878        var type;
64879        var callback;
64880        var errorCallback;
64881        var request;
64882        var promise;
64883        var jsonpOptions = {};
64884        var cbCount = 0;
64885        var contentType = 'text/plain'; // Trim the callbacks off the end to get an idea of how many arguments are passed
64886
64887        for (var i = arguments.length - 1; i > 0; i--) {
64888          if (typeof arguments[i] === 'function') {
64889            cbCount++;
64890          } else {
64891            break;
64892          }
64893        } // The number of arguments minus callbacks
64894
64895
64896        var argsCount = arguments.length - cbCount;
64897        var path = arguments[0];
64898
64899        if (argsCount === 2 && typeof path === 'string' && typeof arguments[1] === 'object') {
64900          // Intended for more advanced use, pass in Request parameters directly
64901          request = new Request(path, arguments[1]);
64902          callback = arguments[2];
64903          errorCallback = arguments[3];
64904        } else {
64905          // Provided with arguments
64906          var method = 'GET';
64907          var data;
64908
64909          for (var j = 1; j < arguments.length; j++) {
64910            var a = arguments[j];
64911
64912            if (typeof a === 'string') {
64913              if (a === 'GET' || a === 'POST' || a === 'PUT' || a === 'DELETE') {
64914                method = a;
64915              } else if (a === 'json' || a === 'jsonp' || a === 'binary' || a === 'arrayBuffer' || a === 'xml' || a === 'text' || a === 'table') {
64916                type = a;
64917              } else {
64918                data = a;
64919              }
64920            } else if (typeof a === 'number') {
64921              data = a.toString();
64922            } else if (typeof a === 'object') {
64923              if (a.hasOwnProperty('jsonpCallback')) {
64924                for (var attr in a) {
64925                  jsonpOptions[attr] = a[attr];
64926                }
64927              } else if (a instanceof p5.XML) {
64928                data = a.serialize();
64929                contentType = 'application/xml';
64930              } else {
64931                data = JSON.stringify(a);
64932                contentType = 'application/json';
64933              }
64934            } else if (typeof a === 'function') {
64935              if (!callback) {
64936                callback = a;
64937              } else {
64938                errorCallback = a;
64939              }
64940            }
64941          }
64942
64943          request = new Request(path, {
64944            method: method,
64945            mode: 'cors',
64946            body: data,
64947            headers: new Headers({
64948              'Content-Type': contentType
64949            })
64950          });
64951        } // do some sort of smart type checking
64952
64953
64954        if (!type) {
64955          if (path.indexOf('json') !== -1) {
64956            type = 'json';
64957          } else if (path.indexOf('xml') !== -1) {
64958            type = 'xml';
64959          } else {
64960            type = 'text';
64961          }
64962        }
64963
64964        if (type === 'jsonp') {
64965          promise = fetchJsonp(path, jsonpOptions);
64966        } else {
64967          promise = fetch(request);
64968        }
64969
64970        promise = promise.then(function (res) {
64971          if (!res.ok) {
64972            var err = new Error(res.body);
64973            err.status = res.status;
64974            err.ok = false;
64975            throw err;
64976          } else {
64977            var fileSize = res.headers.get('content-length');
64978
64979            if (fileSize && fileSize > 64000000) {
64980              p5._friendlyFileLoadError(7, path);
64981            }
64982
64983            switch (type) {
64984              case 'json':
64985              case 'jsonp':
64986                return res.json();
64987
64988              case 'binary':
64989                return res.blob();
64990
64991              case 'arrayBuffer':
64992                return res.arrayBuffer();
64993
64994              case 'xml':
64995                return res.text().then(function (text) {
64996                  var parser = new DOMParser();
64997                  var xml = parser.parseFromString(text, 'text/xml');
64998                  return new p5.XML(xml.documentElement);
64999                });
65000
65001              default:
65002                return res.text();
65003            }
65004          }
65005        });
65006        promise.then(callback || function () {});
65007        promise.catch(errorCallback || console.error);
65008        return promise;
65009      };
65010      /**
65011       * @module IO
65012       * @submodule Output
65013       * @for p5
65014       */
65015
65016
65017      window.URL = window.URL || window.webkitURL; // private array of p5.PrintWriter objects
65018
65019      p5.prototype._pWriters = [];
65020      /**
65021       * @method createWriter
65022       * @param {String} name name of the file to be created
65023       * @param {String} [extension]
65024       * @return {p5.PrintWriter}
65025       * @example
65026       * <div>
65027       * <code>
65028       * function setup() {
65029       *   createCanvas(100, 100);
65030       *   background(200);
65031       *   text('click here to save', 10, 10, 70, 80);
65032       * }
65033       *
65034       * function mousePressed() {
65035       *   if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
65036       *     var writer = createWriter('squares.txt');
65037       *     for (let i = 0; i < 10; i++) {
65038       *       writer.print(i * i);
65039       *     }
65040       *     writer.close();
65041       *     writer.clear();
65042       *   }
65043       * }
65044       * </code>
65045       * </div>
65046       */
65047
65048      p5.prototype.createWriter = function (name, extension) {
65049        var newPW; // check that it doesn't already exist
65050
65051        for (var i in p5.prototype._pWriters) {
65052          if (p5.prototype._pWriters[i].name === name) {
65053            // if a p5.PrintWriter w/ this name already exists...
65054            // return p5.prototype._pWriters[i]; // return it w/ contents intact.
65055            // or, could return a new, empty one with a unique name:
65056            newPW = new p5.PrintWriter(name + this.millis(), extension);
65057
65058            p5.prototype._pWriters.push(newPW);
65059
65060            return newPW;
65061          }
65062        }
65063
65064        newPW = new p5.PrintWriter(name, extension);
65065
65066        p5.prototype._pWriters.push(newPW);
65067
65068        return newPW;
65069      };
65070      /**
65071       *  @class p5.PrintWriter
65072       *  @param  {String}     filename
65073       *  @param  {String}     [extension]
65074       */
65075
65076
65077      p5.PrintWriter = function (filename, extension) {
65078        var self = this;
65079        this.name = filename;
65080        this.content = ''; //Changed to write because it was being overloaded by function below.
65081
65082        /**
65083         * Writes data to the PrintWriter stream
65084         * @method write
65085         * @param {Array} data all data to be written by the PrintWriter
65086         * @example
65087         * <div class="norender notest">
65088         * <code>
65089         * // creates a file called 'newFile.txt'
65090         * let writer = createWriter('newFile.txt');
65091         * // write 'Hello world!'' to the file
65092         * writer.write(['Hello world!']);
65093         * // close the PrintWriter and save the file
65094         * writer.close();
65095         * </code>
65096         * </div>
65097         * <div class='norender notest'>
65098         * <code>
65099         * // creates a file called 'newFile2.txt'
65100         * let writer = createWriter('newFile2.txt');
65101         * // write 'apples,bananas,123' to the file
65102         * writer.write(['apples', 'bananas', 123]);
65103         * // close the PrintWriter and save the file
65104         * writer.close();
65105         * </code>
65106         * </div>
65107         * <div class='norender notest'>
65108         * <code>
65109         * // creates a file called 'newFile3.txt'
65110         * let writer = createWriter('newFile3.txt');
65111         * // write 'My name is: Teddy' to the file
65112         * writer.write('My name is:');
65113         * writer.write(' Teddy');
65114         * // close the PrintWriter and save the file
65115         * writer.close();
65116         * </code>
65117         * </div>
65118         */
65119
65120        this.write = function (data) {
65121          this.content += data;
65122        };
65123        /**
65124         * Writes data to the PrintWriter stream, and adds a new line at the end
65125         * @method print
65126         * @param {Array} data all data to be printed by the PrintWriter
65127         * @example
65128         * <div class='norender notest'>
65129         * <code>
65130         * // creates a file called 'newFile.txt'
65131         * let writer = createWriter('newFile.txt');
65132         * // creates a file containing
65133         * //  My name is:
65134         * //  Teddy
65135         * writer.print('My name is:');
65136         * writer.print('Teddy');
65137         * // close the PrintWriter and save the file
65138         * writer.close();
65139         * </code>
65140         * </div>
65141         * <div class='norender notest'>
65142         * <code>
65143         * let writer;
65144         *
65145         * function setup() {
65146         *   createCanvas(400, 400);
65147         *   // create a PrintWriter
65148         *   writer = createWriter('newFile.txt');
65149         * }
65150         *
65151         * function draw() {
65152         *   // print all mouseX and mouseY coordinates to the stream
65153         *   writer.print([mouseX, mouseY]);
65154         * }
65155         *
65156         * function mouseClicked() {
65157         *   // close the PrintWriter and save the file
65158         *   writer.close();
65159         * }
65160         * </code>
65161         * </div>
65162         */
65163
65164
65165        this.print = function (data) {
65166          this.content += data + '\n';
65167        };
65168        /**
65169         * Clears the data already written to the PrintWriter object
65170         * @method clear
65171         * @example
65172         * <div class ="norender notest"><code>
65173         * // create writer object
65174         * let writer = createWriter('newFile.txt');
65175         * writer.write(['clear me']);
65176         * // clear writer object here
65177         * writer.clear();
65178         * // close writer
65179         * writer.close();
65180         * </code></div>
65181         *
65182         */
65183
65184
65185        this.clear = function () {
65186          this.content = '';
65187        };
65188        /**
65189         * Closes the PrintWriter
65190         * @method close
65191         * @example
65192         * <div class="norender notest">
65193         * <code>
65194         * // create a file called 'newFile.txt'
65195         * let writer = createWriter('newFile.txt');
65196         * // close the PrintWriter and save the file
65197         * writer.close();
65198         * </code>
65199         * </div>
65200         * <div class='norender notest'>
65201         * <code>
65202         * // create a file called 'newFile2.txt'
65203         * let writer = createWriter('newFile2.txt');
65204         * // write some data to the file
65205         * writer.write([100, 101, 102]);
65206         * // close the PrintWriter and save the file
65207         * writer.close();
65208         * </code>
65209         * </div>
65210         */
65211
65212
65213        this.close = function () {
65214          // convert String to Array for the writeFile Blob
65215          var arr = [];
65216          arr.push(this.content);
65217          p5.prototype.writeFile(arr, filename, extension); // remove from _pWriters array and delete self
65218
65219          for (var i in p5.prototype._pWriters) {
65220            if (p5.prototype._pWriters[i].name === this.name) {
65221              // remove from _pWriters array
65222              p5.prototype._pWriters.splice(i, 1);
65223            }
65224          }
65225
65226          self.clear();
65227          self = {};
65228        };
65229      };
65230      /**
65231       * @module IO
65232       * @submodule Output
65233       * @for p5
65234       */
65235      // object, filename, options --> saveJSON, saveStrings,
65236      // filename, [extension] [canvas] --> saveImage
65237
65238      /**
65239       *  <p>Save an image, text, json, csv, wav, or html. Prompts download to
65240       *  the client's computer. <b>Note that it is not recommended to call <a href="#/p5/save">save()</a>
65241       *  within draw if it's looping, as the <a href="#/p5/save">save()</a> function will open a new save
65242       *  dialog every frame.</b></p>
65243       *  <p>The default behavior is to save the canvas as an image. You can
65244       *  optionally specify a filename.
65245       *  For example:</p>
65246       * <pre class='language-javascript'><code>
65247       * save();
65248       * save('myCanvas.jpg'); // save a specific canvas with a filename
65249       * </code></pre>
65250       *
65251       *  <p>Alternately, the first parameter can be a pointer to a canvas
65252       *  <a href="#/p5.Element">p5.Element</a>, an Array of Strings,
65253       *  an Array of JSON, a JSON object, a <a href="#/p5.Table">p5.Table</a>, a <a href="#/p5.Image">p5.Image</a>, or a
65254       *  p5.SoundFile (requires p5.sound). The second parameter is a filename
65255       *  (including extension). The third parameter is for options specific
65256       *  to this type of object. This method will save a file that fits the
65257       *  given parameters. For example:</p>
65258       *
65259       * <pre class='language-javascript'><code>
65260       * // Saves canvas as an image
65261       * save('myCanvas.jpg');
65262       *
65263       * // Saves pImage as a png image
65264       * let img = createImage(10, 10);
65265       * save(img, 'my.png');
65266       *
65267       * // Saves canvas as an image
65268       * let cnv = createCanvas(100, 100);
65269       * save(cnv, 'myCanvas.jpg');
65270       *
65271       * // Saves p5.Renderer object as an image
65272       * let gb = createGraphics(100, 100);
65273       * save(gb, 'myGraphics.jpg');
65274       *
65275       * let myTable = new p5.Table();
65276       *
65277       * // Saves table as html file
65278       * save(myTable, 'myTable.html');
65279       *
65280       * // Comma Separated Values
65281       * save(myTable, 'myTable.csv');
65282       *
65283       * // Tab Separated Values
65284       * save(myTable, 'myTable.tsv');
65285       *
65286       * let myJSON = { a: 1, b: true };
65287       *
65288       * // Saves pretty JSON
65289       * save(myJSON, 'my.json');
65290       *
65291       * // Optimizes JSON filesize
65292       * save(myJSON, 'my.json', true);
65293       *
65294       * // Saves array of strings to a text file with line breaks after each item
65295       * let arrayOfStrings = ['a', 'b'];
65296       * save(arrayOfStrings, 'my.txt');
65297       * </code></pre>
65298       *
65299       *  @method save
65300       *  @param  {Object|String} [objectOrFilename]  If filename is provided, will
65301       *                                             save canvas as an image with
65302       *                                             either png or jpg extension
65303       *                                             depending on the filename.
65304       *                                             If object is provided, will
65305       *                                             save depending on the object
65306       *                                             and filename (see examples
65307       *                                             above).
65308       *  @param  {String} [filename] If an object is provided as the first
65309       *                               parameter, then the second parameter
65310       *                               indicates the filename,
65311       *                               and should include an appropriate
65312       *                               file extension (see examples above).
65313       *  @param  {Boolean|String} [options]  Additional options depend on
65314       *                            filetype. For example, when saving JSON,
65315       *                            <code>true</code> indicates that the
65316       *                            output will be optimized for filesize,
65317       *                            rather than readability.
65318       */
65319
65320
65321      p5.prototype.save = function (object, _filename, _options) {
65322        // parse the arguments and figure out which things we are saving
65323        var args = arguments; // =================================================
65324        // OPTION 1: saveCanvas...
65325        // if no arguments are provided, save canvas
65326
65327        var cnv = this._curElement ? this._curElement.elt : this.elt;
65328
65329        if (args.length === 0) {
65330          p5.prototype.saveCanvas(cnv);
65331          return;
65332        } else if (args[0] instanceof p5.Renderer || args[0] instanceof p5.Graphics) {
65333          // otherwise, parse the arguments
65334          // if first param is a p5Graphics, then saveCanvas
65335          p5.prototype.saveCanvas(args[0].elt, args[1], args[2]);
65336          return;
65337        } else if (args.length === 1 && typeof args[0] === 'string') {
65338          // if 1st param is String and only one arg, assume it is canvas filename
65339          p5.prototype.saveCanvas(cnv, args[0]);
65340        } else {
65341          // =================================================
65342          // OPTION 2: extension clarifies saveStrings vs. saveJSON
65343          var extension = _checkFileExtension(args[1], args[2])[1];
65344
65345          switch (extension) {
65346            case 'json':
65347              p5.prototype.saveJSON(args[0], args[1], args[2]);
65348              return;
65349
65350            case 'txt':
65351              p5.prototype.saveStrings(args[0], args[1], args[2]);
65352              return;
65353            // =================================================
65354            // OPTION 3: decide based on object...
65355
65356            default:
65357              if (args[0] instanceof Array) {
65358                p5.prototype.saveStrings(args[0], args[1], args[2]);
65359              } else if (args[0] instanceof p5.Table) {
65360                p5.prototype.saveTable(args[0], args[1], args[2]);
65361              } else if (args[0] instanceof p5.Image) {
65362                p5.prototype.saveCanvas(args[0].canvas, args[1]);
65363              } else if (args[0] instanceof p5.SoundFile) {
65364                p5.prototype.saveSound(args[0], args[1], args[2], args[3]);
65365              }
65366
65367          }
65368        }
65369      };
65370      /**
65371       *  Writes the contents of an Array or a JSON object to a .json file.
65372       *  The file saving process and location of the saved file will
65373       *  vary between web browsers.
65374       *
65375       *  @method saveJSON
65376       *  @param  {Array|Object} json
65377       *  @param  {String} filename
65378       *  @param  {Boolean} [optimize]   If true, removes line breaks
65379       *                                 and spaces from the output
65380       *                                 file to optimize filesize
65381       *                                 (but not readability).
65382       *  @example
65383       * <div><code>
65384       * let json = {}; // new  JSON Object
65385       *
65386       * json.id = 0;
65387       * json.species = 'Panthera leo';
65388       * json.name = 'Lion';
65389       *
65390       * function setup() {
65391       *   createCanvas(100, 100);
65392       *   background(200);
65393       *   text('click here to save', 10, 10, 70, 80);
65394       * }
65395       *
65396       * function mousePressed() {
65397       *   if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
65398       *     saveJSON(json, 'lion.json');
65399       *   }
65400       * }
65401       *
65402       * // saves the following to a file called "lion.json":
65403       * // {
65404       * //   "id": 0,
65405       * //   "species": "Panthera leo",
65406       * //   "name": "Lion"
65407       * // }
65408       * </code></div>
65409       *
65410       * @alt
65411       * no image displayed
65412       *
65413       */
65414
65415
65416      p5.prototype.saveJSON = function (json, filename, opt) {
65417        p5._validateParameters('saveJSON', arguments);
65418
65419        var stringify;
65420
65421        if (opt) {
65422          stringify = JSON.stringify(json);
65423        } else {
65424          stringify = JSON.stringify(json, undefined, 2);
65425        }
65426
65427        this.saveStrings(stringify.split('\n'), filename, 'json');
65428      };
65429
65430      p5.prototype.saveJSONObject = p5.prototype.saveJSON;
65431      p5.prototype.saveJSONArray = p5.prototype.saveJSON;
65432      /**
65433       *  Writes an array of Strings to a text file, one line per String.
65434       *  The file saving process and location of the saved file will
65435       *  vary between web browsers.
65436       *
65437       *  @method saveStrings
65438       *  @param  {String[]} list   string array to be written
65439       *  @param  {String} filename filename for output
65440       *  @param  {String} [extension] the filename's extension
65441       *  @example
65442       * <div><code>
65443       * let words = 'apple bear cat dog';
65444       *
65445       * // .split() outputs an Array
65446       * let list = split(words, ' ');
65447       *
65448       * function setup() {
65449       *   createCanvas(100, 100);
65450       *   background(200);
65451       *   text('click here to save', 10, 10, 70, 80);
65452       * }
65453       *
65454       * function mousePressed() {
65455       *   if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
65456       *     saveStrings(list, 'nouns.txt');
65457       *   }
65458       * }
65459       *
65460       * // Saves the following to a file called 'nouns.txt':
65461       * //
65462       * // apple
65463       * // bear
65464       * // cat
65465       * // dog
65466       * </code></div>
65467       *
65468       * @alt
65469       * no image displayed
65470       *
65471       */
65472
65473      p5.prototype.saveStrings = function (list, filename, extension) {
65474        p5._validateParameters('saveStrings', arguments);
65475
65476        var ext = extension || 'txt';
65477        var pWriter = this.createWriter(filename, ext);
65478
65479        for (var i = 0; i < list.length; i++) {
65480          if (i < list.length - 1) {
65481            pWriter.print(list[i]);
65482          } else {
65483            pWriter.print(list[i]);
65484          }
65485        }
65486
65487        pWriter.close();
65488        pWriter.clear();
65489      }; // =======
65490      // HELPERS
65491      // =======
65492
65493
65494      function escapeHelper(content) {
65495        return content.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#039;');
65496      }
65497      /**
65498       *  Writes the contents of a <a href="#/p5.Table">Table</a> object to a file. Defaults to a
65499       *  text file with comma-separated-values ('csv') but can also
65500       *  use tab separation ('tsv'), or generate an HTML table ('html').
65501       *  The file saving process and location of the saved file will
65502       *  vary between web browsers.
65503       *
65504       *  @method saveTable
65505       *  @param  {p5.Table} Table  the <a href="#/p5.Table">Table</a> object to save to a file
65506       *  @param  {String} filename the filename to which the Table should be saved
65507       *  @param  {String} [options]  can be one of "tsv", "csv", or "html"
65508       *  @example
65509       *  <div><code>
65510       * let table;
65511       *
65512       * function setup() {
65513       *   table = new p5.Table();
65514       *
65515       *   table.addColumn('id');
65516       *   table.addColumn('species');
65517       *   table.addColumn('name');
65518       *
65519       *   let newRow = table.addRow();
65520       *   newRow.setNum('id', table.getRowCount() - 1);
65521       *   newRow.setString('species', 'Panthera leo');
65522       *   newRow.setString('name', 'Lion');
65523       *
65524       *   // To save, un-comment next line then click 'run'
65525       *   // saveTable(table, 'new.csv');
65526       * }
65527       *
65528       * // Saves the following to a file called 'new.csv':
65529       * // id,species,name
65530       * // 0,Panthera leo,Lion
65531       * </code></div>
65532       *
65533       * @alt
65534       * no image displayed
65535       *
65536       */
65537
65538
65539      p5.prototype.saveTable = function (table, filename, options) {
65540        p5._validateParameters('saveTable', arguments);
65541
65542        var ext;
65543
65544        if (options === undefined) {
65545          ext = filename.substring(filename.lastIndexOf('.') + 1, filename.length);
65546        } else {
65547          ext = options;
65548        }
65549
65550        var pWriter = this.createWriter(filename, ext);
65551        var header = table.columns;
65552        var sep = ','; // default to CSV
65553
65554        if (ext === 'tsv') {
65555          sep = '\t';
65556        }
65557
65558        if (ext !== 'html') {
65559          // make header if it has values
65560          if (header[0] !== '0') {
65561            for (var h = 0; h < header.length; h++) {
65562              if (h < header.length - 1) {
65563                pWriter.write(header[h] + sep);
65564              } else {
65565                pWriter.write(header[h]);
65566              }
65567            }
65568
65569            pWriter.write('\n');
65570          } // make rows
65571
65572
65573          for (var i = 0; i < table.rows.length; i++) {
65574            var j;
65575
65576            for (j = 0; j < table.rows[i].arr.length; j++) {
65577              if (j < table.rows[i].arr.length - 1) {
65578                pWriter.write(table.rows[i].arr[j] + sep);
65579              } else if (i < table.rows.length - 1) {
65580                pWriter.write(table.rows[i].arr[j]);
65581              } else {
65582                pWriter.write(table.rows[i].arr[j]);
65583              }
65584            }
65585
65586            pWriter.write('\n');
65587          }
65588        } else {
65589          // otherwise, make HTML
65590          pWriter.print('<html>');
65591          pWriter.print('<head>');
65592          var str = '  <meta http-equiv="content-type" content';
65593          str += '="text/html;charset=utf-8" />';
65594          pWriter.print(str);
65595          pWriter.print('</head>');
65596          pWriter.print('<body>');
65597          pWriter.print('  <table>'); // make header if it has values
65598
65599          if (header[0] !== '0') {
65600            pWriter.print('    <tr>');
65601
65602            for (var k = 0; k < header.length; k++) {
65603              var e = escapeHelper(header[k]);
65604              pWriter.print('      <td>' + e);
65605              pWriter.print('      </td>');
65606            }
65607
65608            pWriter.print('    </tr>');
65609          } // make rows
65610
65611
65612          for (var row = 0; row < table.rows.length; row++) {
65613            pWriter.print('    <tr>');
65614
65615            for (var col = 0; col < table.columns.length; col++) {
65616              var entry = table.rows[row].getString(col);
65617              var htmlEntry = escapeHelper(entry);
65618              pWriter.print('      <td>' + htmlEntry);
65619              pWriter.print('      </td>');
65620            }
65621
65622            pWriter.print('    </tr>');
65623          }
65624
65625          pWriter.print('  </table>');
65626          pWriter.print('</body>');
65627          pWriter.print('</html>');
65628        } // close and clear the pWriter
65629
65630
65631        pWriter.close();
65632        pWriter.clear();
65633      }; // end saveTable()
65634
65635      /**
65636       *  Generate a blob of file data as a url to prepare for download.
65637       *  Accepts an array of data, a filename, and an extension (optional).
65638       *  This is a private function because it does not do any formatting,
65639       *  but it is used by <a href="#/p5/saveStrings">
65639saveStrings</a>, <a href="#/p5/saveJSON">saveJSON</a>, <a href="#/p5/saveTable">saveTable</a> etc.
65640       *
65641       *  @param  {Array} dataToDownload
65642       *  @param  {String} filename
65643       *  @param  {String} [extension]
65644       *  @private
65645       */
65646
65647
65648      p5.prototype.writeFile = function (dataToDownload, filename, extension) {
65649        var type = 'application/octet-stream';
65650
65651        if (p5.prototype._isSafari()) {
65652          type = 'text/plain';
65653        }
65654
65655        var blob = new Blob(dataToDownload, {
65656          type: type
65657        });
65658        p5.prototype.downloadFile(blob, filename, extension);
65659      };
65660      /**
65661       *  Forces download. Accepts a url to filedata/blob, a filename,
65662       *  and an extension (optional).
65663       *  This is a private function because it does not do any formatting,
65664       *  but it is used by <a href="#/p5/saveStrings">saveStrings</a>, <a href="#/p5/saveJSON">saveJSON</a>, <a href="#/p5/saveTable">saveTable</a> etc.
65665       *
65666       *  @method downloadFile
65667       *  @private
65668       *  @param  {String|Blob} data    either an href generated by createObjectURL,
65669       *                                or a Blob object containing the data
65670       *  @param  {String} [filename]
65671       *  @param  {String} [extension]
65672       */
65673
65674
65675      p5.prototype.downloadFile = function (data, fName, extension) {
65676        var fx = _checkFileExtension(fName, extension);
65677
65678        var filename = fx[0];
65679
65680        if (data instanceof Blob) {
65681          var fileSaver = _dereq_('file-saver');
65682
65683          fileSaver.saveAs(data, filename);
65684          return;
65685        }
65686
65687        var a = document.createElement('a');
65688        a.href = data;
65689        a.download = filename; // Firefox requires the link to be added to the DOM before click()
65690
65691        a.onclick = function (e) {
65692          destroyClickedElement(e);
65693          e.stopPropagation();
65694        };
65695
65696        a.style.display = 'none';
65697        document.body.appendChild(a); // Safari will open this file in the same page as a confusing Blob.
65698
65699        if (p5.prototype._isSafari()) {
65700          var aText = 'Hello, Safari user! To download this file...\n';
65701          aText += '1. Go to File --> Save As.\n';
65702          aText += '2. Choose "Page Source" as the Format.\n';
65703          aText += '3. Name it with this extension: ."' + fx[1] + '"';
65704          alert(aText);
65705        }
65706
65707        a.click();
65708      };
65709      /**
65710       *  Returns a file extension, or another string
65711       *  if the provided parameter has no extension.
65712       *
65713       *  @param   {String} filename
65714       *  @param   {String} [extension]
65715       *  @return  {String[]} [fileName, fileExtension]
65716       *
65717       *  @private
65718       */
65719
65720
65721      function _checkFileExtension(filename, extension) {
65722        if (!extension || extension === true || extension === 'true') {
65723          extension = '';
65724        }
65725
65726        if (!filename) {
65727          filename = 'untitled';
65728        }
65729
65730        var ext = ''; // make sure the file will have a name, see if filename needs extension
65731
65732        if (filename && filename.indexOf('.') > -1) {
65733          ext = filename.split('.').pop();
65734        } // append extension if it doesn't exist
65735
65736
65737        if (extension) {
65738          if (ext !== extension) {
65739            ext = extension;
65740            filename = filename + '.' + ext;
65741          }
65742        }
65743
65744        return [filename, ext];
65745      }
65746
65747      p5.prototype._checkFileExtension = _checkFileExtension;
65748      /**
65749       *  Returns true if the browser is Safari, false if not.
65750       *  Safari makes trouble for downloading files.
65751       *
65752       *  @return  {Boolean} [description]
65753       *  @private
65754       */
65755
65756      p5.prototype._isSafari = function () {
65757        var x = Object.prototype.toString.call(window.HTMLElement);
65758        return x.indexOf('Constructor') > 0;
65759      };
65760      /**
65761       *  Helper function, a callback for download that deletes
65762       *  an invisible anchor element from the DOM once the file
65763       *  has been automatically downloaded.
65764       *
65765       *  @private
65766       */
65767
65768
65769      function destroyClickedElement(event) {
65770        document.body.removeChild(event.target);
65771      }
65772
65773      module.exports = p5;
65774    }, {
65775      "../core/error_helpers": 20,
65776      "../core/main": 24,
65777      "es6-promise": 5,
65778      "fetch-jsonp": 6,
65779      "file-saver": 7,
65780      "whatwg-fetch": 12
65781    }],
65782    48: [function (_dereq_, module, exports) {
65783      /**
65784       * @module IO
65785       * @submodule Table
65786       * @requires core
65787       */
65788      'use strict';
65789
65790      var p5 = _dereq_('../core/main');
65791      /**
65792       *  Table Options
65793       *  <p>Generic class for handling tabular data, typically from a
65794       *  CSV, TSV, or other sort of spreadsheet file.</p>
65795       *  <p>CSV files are
65796       *  <a href="http://en.wikipedia.org/wiki/Comma-separated_values">
65797       *  comma separated values</a>, often with the data in quotes. TSV
65798       *  files use tabs as separators, and usually don't bother with the
65799       *  quotes.</p>
65800       *  <p>File names should end with .csv if they're comma separated.</p>
65801       *  <p>A rough "spec" for CSV can be found
65802       *  <a href="http://tools.ietf.org/html/rfc4180">here</a>.</p>
65803       *  <p>To load files, use the <a href="#/p5/loadTable">loadTable</a> method.</p>
65804       *  <p>To save tables to your computer, use the <a href="#/p5/save">save</a> method
65805       *   or the <a href="#/p5/saveTable">saveTable</a> method.</p>
65806       *
65807       *  Possible options include:
65808       *  <ul>
65809       *  <li>csv - parse the table as comma-separated values
65810       *  <li>tsv - parse the table as tab-separated values
65811       *  <li>header - this table has a header (title) row
65812       *  </ul>
65813       */
65814
65815      /**
65816       *  <a href="#/p5.Table">Table</a> objects store data with multiple rows and columns, much
65817       *  like in a traditional spreadsheet. Tables can be generated from
65818       *  scratch, dynamically, or using data from an existing file.
65819       *
65820       *  @class p5.Table
65821       *  @constructor
65822       *  @param  {p5.TableRow[]}     [rows] An array of p5.TableRow objects
65823       */
65824
65825
65826      p5.Table = function (rows) {
65827        /**
65828         *  @property columns {String[]}
65829         */
65830        this.columns = [];
65831        /**
65832         *  @property rows {p5.TableRow[]}
65833         */
65834
65835        this.rows = [];
65836      };
65837      /**
65838       *  Use <a href="#/p5/addRow">addRow()</a> to add a new row of data to a <a href="#/p5.Table">p5.Table</a> object. By default,
65839       *  an empty row is created. Typically, you would store a reference to
65840       *  the new row in a TableRow object (see newRow in the example above),
65841       *  and then set individual values using <a href="#/p5/set">set()</a>.
65842       *
65843       *  If a <a href="#/p5.TableRow">p5.TableRow</a> object is included as a parameter, then that row is
65844       *  duplicated and added to the table.
65845       *
65846       *  @method  addRow
65847       *  @param   {p5.TableRow} [row] row to be added to the table
65848       *  @return  {p5.TableRow} the row that was added
65849       *
65850       * @example
65851       * <div class="norender">
65852       * <code>
65853       * // Given the CSV file "mammals.csv"
65854       * // in the project's "assets" folder:
65855       * //
65856       * // id,species,name
65857       * // 0,Capra hircus,Goat
65858       * // 1,Panthera pardus,Leopard
65859       * // 2,Equus zebra,Zebra
65860       *
65861       * let table;
65862       *
65863       * function preload() {
65864       *   //my table is comma separated value "csv"
65865       *   //and has a header specifying the columns labels
65866       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
65867       * }
65868       *
65869       * function setup() {
65870       *   //add a row
65871       *   let newRow = table.addRow();
65872       *   newRow.setString('id', table.getRowCount() - 1);
65873       *   newRow.setString('species', 'Canis Lupus');
65874       *   newRow.setString('name', 'Wolf');
65875       *
65876       *   //print the results
65877       *   for (let r = 0; r < table.getRowCount(); r++)
65878       *     for (let c = 0; c < table.getColumnCount(); c++)
65879       *       print(table.getString(r, c));
65880       * }
65881       * </code>
65882       * </div>
65883       *
65884       * @alt
65885       * no image displayed
65886       *
65887       */
65888
65889
65890      p5.Table.prototype.addRow = function (row) {
65891        // make sure it is a valid TableRow
65892        var r = row || new p5.TableRow();
65893
65894        if (typeof r.arr === 'undefined' || typeof r.obj === 'undefined') {
65895          //r = new p5.prototype.TableRow(r);
65896          throw new Error('invalid TableRow: ' + r);
65897        }
65898
65899        r.table = this;
65900        this.rows.push(r);
65901        return r;
65902      };
65903      /**
65904       * Removes a row from the table object.
65905       *
65906       * @method  removeRow
65907       * @param   {Integer} id ID number of the row to remove
65908       *
65909       * @example
65910       * <div class="norender">
65911       * <code>
65912       * // Given the CSV file "mammals.csv"
65913       * // in the project's "assets" folder:
65914       * //
65915       * // id,species,name
65916       * // 0,Capra hircus,Goat
65917       * // 1,Panthera pardus,Leopard
65918       * // 2,Equus zebra,Zebra
65919       *
65920       * let table;
65921       *
65922       * function preload() {
65923       *   //my table is comma separated value "csv"
65924       *   //and has a header specifying the columns labels
65925       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
65926       * }
65927       *
65928       * function setup() {
65929       *   //remove the first row
65930       *   table.removeRow(0);
65931       *
65932       *   //print the results
65933       *   for (let r = 0; r < table.getRowCount(); r++)
65934       *     for (let c = 0; c < table.getColumnCount(); c++)
65935       *       print(table.getString(r, c));
65936       * }
65937       * </code>
65938       * </div>
65939       *
65940       * @alt
65941       * no image displayed
65942       *
65943       */
65944
65945
65946      p5.Table.prototype.removeRow = function (id) {
65947        this.rows[id].table = null; // remove reference to table
65948
65949        var chunk = this.rows.splice(id + 1, this.rows.length);
65950        this.rows.pop();
65951        this.rows = this.rows.concat(chunk);
65952      };
65953      /**
65954       * Returns a reference to the specified <a href="#/p5.TableRow">p5.TableRow</a>. The reference
65955       * can then be used to get and set values of the selected row.
65956       *
65957       * @method  getRow
65958       * @param  {Integer}   rowID ID number of the row to get
65959       * @return {p5.TableRow} <a href="#/p5.TableRow">p5.TableRow</a> object
65960       *
65961       * @example
65962       * <div class="norender">
65963       * <code>
65964       * // Given the CSV file "mammals.csv"
65965       * // in the project's "assets" folder:
65966       * //
65967       * // id,species,name
65968       * // 0,Capra hircus,Goat
65969       * // 1,Panthera pardus,Leopard
65970       * // 2,Equus zebra,Zebra
65971       *
65972       * let table;
65973       *
65974       * function preload() {
65975       *   //my table is comma separated value "csv"
65976       *   //and has a header specifying the columns labels
65977       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
65978       * }
65979       *
65980       * function setup() {
65981       *   let row = table.getRow(1);
65982       *   //print it column by column
65983       *   //note: a row is an object, not an array
65984       *   for (let c = 0; c < table.getColumnCount(); c++) {
65985       *     print(row.getString(c));
65986       *   }
65987       * }
65988       * </code>
65989       * </div>
65990       *
65991       *@alt
65992       * no image displayed
65993       *
65994       */
65995
65996
65997      p5.Table.prototype.getRow = function (r) {
65998        return this.rows[r];
65999      };
66000      /**
66001       *  Gets all rows from the table. Returns an array of <a href="#/p5.TableRow">p5.TableRow</a>s.
66002       *
66003       *  @method  getRows
66004       *  @return {p5.TableRow[]}   Array of <a href="#/p5.TableRow">p5.TableRow</a>s
66005       *
66006       * @example
66007       * <div class="norender">
66008       * <code>
66009       * // Given the CSV file "mammals.csv"
66010       * // in the project's "assets" folder:
66011       * //
66012       * // id,species,name
66013       * // 0,Capra hircus,Goat
66014       * // 1,Panthera pardus,Leopard
66015       * // 2,Equus zebra,Zebra
66016       *
66017       * let table;
66018       *
66019       * function preload() {
66020       *   //my table is comma separated value "csv"
66021       *   //and has a header specifying the columns labels
66022       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
66023       * }
66024       *
66025       * function setup() {
66026       *   let rows = table.getRows();
66027       *
66028       *   //warning: rows is an array of objects
66029       *   for (let r = 0; r < rows.length; r++) {
66030       *     rows[r].set('name', 'Unicorn');
66031       *   }
66032       *
66033       *   //print the results
66034       *   for (let r = 0; r < table.getRowCount(); r++)
66035       *     for (let c = 0; c < table.getColumnCount(); c++)
66036       *       print(table.getString(r, c));
66037       * }
66038       * </code>
66039       * </div>
66040       *
66041       * @alt
66042       * no image displayed
66043       *
66044       */
66045
66046
66047      p5.Table.prototype.getRows = function () {
66048        return this.rows;
66049      };
66050      /**
66051       *  Finds the first row in the Table that contains the value
66052       *  provided, and returns a reference to that row. Even if
66053       *  multiple rows are possible matches, only the first matching
66054       *  row is returned. The column to search may be specified by
66055       *  either its ID or title.
66056       *
66057       *  @method  findRow
66058       *  @param  {String} value  The value to match
66059       *  @param  {Integer|String} column ID number or title of the
66060       *                                 column to search
66061       *  @return {p5.TableRow}
66062       *
66063       * @example
66064       * <div class="norender">
66065       * <code>
66066       * // Given the CSV file "mammals.csv"
66067       * // in the project's "assets" folder:
66068       * //
66069       * // id,species,name
66070       * // 0,Capra hircus,Goat
66071       * // 1,Panthera pardus,Leopard
66072       * // 2,Equus zebra,Zebra
66073       *
66074       * let table;
66075       *
66076       * function preload() {
66077       *   //my table is comma separated value "csv"
66078       *   //and has a header specifying the columns labels
66079       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
66080       * }
66081       *
66082       * function setup() {
66083       *   //find the animal named zebra
66084       *   let row = table.findRow('Zebra', 'name');
66085       *   //find the corresponding species
66086       *   print(row.getString('species'));
66087       * }
66088       * </code>
66089       * </div>
66090       *
66091       * @alt
66092       * no image displayed
66093       *
66094       */
66095
66096
66097      p5.Table.prototype.findRow = function (value, column) {
66098        // try the Object
66099        if (typeof column === 'string') {
66100          for (var i = 0; i < this.rows.length; i++) {
66101            if (this.rows[i].obj[column] === value) {
66102              return this.rows[i];
66103            }
66104          }
66105        } else {
66106          // try the Array
66107          for (var j = 0; j < this.rows.length; j++) {
66108            if (this.rows[j].arr[column] === value) {
66109              return this.rows[j];
66110            }
66111          }
66112        } // otherwise...
66113
66114
66115        return null;
66116      };
66117      /**
66118       *  Finds the rows in the Table that contain the value
66119       *  provided, and returns references to those rows. Returns an
66120       *  Array, so for must be used to iterate through all the rows,
66121       *  as shown in the example above. The column to search may be
66122       *  specified by either its ID or title.
66123       *
66124       *  @method  findRows
66125       *  @param  {String} value  The value to match
66126       *  @param  {Integer|String} column ID number or title of the
66127       *                                 column to search
66128       *  @return {p5.TableRow[]}        An Array of TableRow objects
66129       *
66130       * @example
66131       * <div class="norender">
66132       * <code>
66133       * // Given the CSV file "mammals.csv"
66134       * // in the project's "assets" folder:
66135       * //
66136       * // id,species,name
66137       * // 0,Capra hircus,Goat
66138       * // 1,Panthera pardus,Leopard
66139       * // 2,Equus zebra,Zebra
66140       *
66141       * let table;
66142       *
66143       * function preload() {
66144       *   //my table is comma separated value "csv"
66145       *   //and has a header specifying the columns labels
66146       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
66147       * }
66148       *
66149       * function setup() {
66150       *   //add another goat
66151       *   let newRow = table.addRow();
66152       *   newRow.setString('id', table.getRowCount() - 1);
66153       *   newRow.setString('species', 'Scape Goat');
66154       *   newRow.setString('name', 'Goat');
66155       *
66156       *   //find the rows containing animals named Goat
66157       *   let rows = table.findRows('Goat', 'name');
66158       *   print(rows.length + ' Goats found');
66159       * }
66160       * </code>
66161       * </div>
66162       *
66163       *@alt
66164       * no image displayed
66165       *
66166       */
66167
66168
66169      p5.Table.prototype.findRows = function (value, column) {
66170        var ret = [];
66171
66172        if (typeof column === 'string') {
66173          for (var i = 0; i < this.rows.length; i++) {
66174            if (this.rows[i].obj[column] === value) {
66175              ret.push(this.rows[i]);
66176            }
66177          }
66178        } else {
66179          // try the Array
66180          for (var j = 0; j < this.rows.length; j++) {
66181            if (this.rows[j].arr[column] === value) {
66182              ret.push(this.rows[j]);
66183            }
66184          }
66185        }
66186
66187        return ret;
66188      };
66189      /**
66190       * Finds the first row in the Table that matches the regular
66191       * expression provided, and returns a reference to that row.
66192       * Even if multiple rows are possible matches, only the first
66193       * matching row is returned. The column to search may be
66194       * specified by either its ID or title.
66195       *
66196       * @method  matchRow
66197       * @param  {String|RegExp} regexp The regular expression to match
66198       * @param  {String|Integer} column The column ID (number) or
66199       *                                  title (string)
66200       * @return {p5.TableRow}        TableRow object
66201       *
66202       * @example
66203       * <div class="norender">
66204       * <code>
66205       * // Given the CSV file "mammals.csv"
66206       * // in the project's "assets" folder:
66207       * //
66208       * // id,species,name
66209       * // 0,Capra hircus,Goat
66210       * // 1,Panthera pardus,Leopard
66211       * // 2,Equus zebra,Zebra
66212       *
66213       * let table;
66214       *
66215       * function preload() {
66216       *   //my table is comma separated value "csv"
66217       *   //and has a header specifying the columns labels
66218       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
66219       * }
66220       *
66221       * function setup() {
66222       *   //Search using specified regex on a given column, return TableRow object
66223       *   let mammal = table.matchRow(new RegExp('ant'), 1);
66224       *   print(mammal.getString(1));
66225       *   //Output "Panthera pardus"
66226       * }
66227       * </code>
66228       * </div>
66229       *
66230       */
66231
66232
66233      p5.Table.prototype.matchRow = function (regexp, column) {
66234        if (typeof column === 'number') {
66235          for (var j = 0; j < this.rows.length; j++) {
66236            if (this.rows[j].arr[column].match(regexp)) {
66237              return this.rows[j];
66238            }
66239          }
66240        } else {
66241          for (var i = 0; i < this.rows.length; i++) {
66242            if (this.rows[i].obj[column].match(regexp)) {
66243              return this.rows[i];
66244            }
66245          }
66246        }
66247
66248        return null;
66249      };
66250      /**
66251       * Finds the rows in the Table that match the regular expression provided,
66252       * and returns references to those rows. Returns an array, so for must be
66253       * used to iterate through all the rows, as shown in the example. The
66254       * column to search may be specified by either its ID or title.
66255       *
66256       * @method  matchRows
66257       * @param  {String} regexp The regular expression to match
66258       * @param  {String|Integer} [column] The column ID (number) or
66259       *                                  title (string)
66260       * @return {p5.TableRow[]}          An Array of TableRow objects
66261       * @example
66262       * <div class="norender">
66263       * <code>
66264       * let table;
66265       *
66266       * function setup() {
66267       *   table = new p5.Table();
66268       *
66269       *   table.addColumn('name');
66270       *   table.addColumn('type');
66271       *
66272       *   let newRow = table.addRow();
66273       *   newRow.setString('name', 'Lion');
66274       *   newRow.setString('type', 'Mammal');
66275       *
66276       *   newRow = table.addRow();
66277       *   newRow.setString('name', 'Snake');
66278       *   newRow.setString('type', 'Reptile');
66279       *
66280       *   newRow = table.addRow();
66281       *   newRow.setString('name', 'Mosquito');
66282       *   newRow.setString('type', 'Insect');
66283       *
66284       *   newRow = table.addRow();
66285       *   newRow.setString('name', 'Lizard');
66286       *   newRow.setString('type', 'Reptile');
66287       *
66288       *   let rows = table.matchRows('R.*', 'type');
66289       *   for (let i = 0; i < rows.length; i++) {
66290       *     print(rows[i].getString('name') + ': ' + rows[i].getString('type'));
66291       *   }
66292       * }
66293       * // Sketch prints:
66294       * // Snake: Reptile
66295       * // Lizard: Reptile
66296       * </code>
66297       * </div>
66298       */
66299
66300
66301      p5.Table.prototype.matchRows = function (regexp, column) {
66302        var ret = [];
66303
66304        if (typeof column === 'number') {
66305          for (var j = 0; j < this.rows.length; j++) {
66306            if (this.rows[j].arr[column].match(regexp)) {
66307              ret.push(this.rows[j]);
66308            }
66309          }
66310        } else {
66311          for (var i = 0; i < this.rows.length; i++) {
66312            if (this.rows[i].obj[column].match(regexp)) {
66313              ret.push(this.rows[i]);
66314            }
66315          }
66316        }
66317
66318        return ret;
66319      };
66320      /**
66321       *  Retrieves all values in the specified column, and returns them
66322       *  as an array. The column may be specified by either its ID or title.
66323       *
66324       *  @method  getColumn
66325       *  @param  {String|Number} column String or Number of the column to return
66326       *  @return {Array}       Array of column values
66327       *
66328       * @example
66329       * <div class="norender">
66330       * <code>
66331       * // Given the CSV file "mammals.csv"
66332       * // in the project's "assets" folder:
66333       * //
66334       * // id,species,name
66335       * // 0,Capra hircus,Goat
66336       * // 1,Panthera pardus,Leopard
66337       * // 2,Equus zebra,Zebra
66338       *
66339       * let table;
66340       *
66341       * function preload() {
66342       *   //my table is comma separated value "csv"
66343       *   //and has a header specifying the columns labels
66344       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
66345       * }
66346       *
66347       * function setup() {
66348       *   //getColumn returns an array that can be printed directly
66349       *   print(table.getColumn('species'));
66350       *   //outputs ["Capra hircus", "Panthera pardus", "Equus zebra"]
66351       * }
66352       * </code>
66353       * </div>
66354       *
66355       *@alt
66356       * no image displayed
66357       *
66358       */
66359
66360
66361      p5.Table.prototype.getColumn = function (value) {
66362        var ret = [];
66363
66364        if (typeof value === 'string') {
66365          for (var i = 0; i < this.rows.length; i++) {
66366            ret.push(this.rows[i].obj[value]);
66367          }
66368        } else {
66369          for (var j = 0; j < this.rows.length; j++) {
66370            ret.push(this.rows[j].arr[value]);
66371          }
66372        }
66373
66374        return ret;
66375      };
66376      /**
66377       *  Removes all rows from a Table. While all rows are removed,
66378       *  columns and column titles are maintained.
66379       *
66380       *  @method  clearRows
66381       *
66382       * @example
66383       * <div class="norender">
66384       * <code>
66385       * // Given the CSV file "mammals.csv"
66386       * // in the project's "assets" folder:
66387       * //
66388       * // id,species,name
66389       * // 0,Capra hircus,Goat
66390       * // 1,Panthera pardus,Leopard
66391       * // 2,Equus zebra,Zebra
66392       *
66393       * let table;
66394       *
66395       * function preload() {
66396       *   //my table is comma separated value "csv"
66397       *   //and has a header specifying the columns labels
66398       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
66399       * }
66400       *
66401       * function setup() {
66402       *   table.clearRows();
66403       *   print(table.getRowCount() + ' total rows in table');
66404       *   print(table.getColumnCount() + ' total columns in table');
66405       * }
66406       * </code>
66407       * </div>
66408       *
66409       *@alt
66410       * no image displayed
66411       *
66412       */
66413
66414
66415      p5.Table.prototype.clearRows = function () {
66416        delete this.rows;
66417        this.rows = [];
66418      };
66419      /**
66420       *  Use <a href="#/p5/addColumn">addColumn()</a> to add a new column to a <a href="#/p5.Table">Table</a> object.
66421       *  Typically, you will want to specify a title, so the column
66422       *  may be easily referenced later by name. (If no title is
66423       *  specified, the new column's title will be null.)
66424       *
66425       *  @method  addColumn
66426       *  @param {String} [title] title of the given column
66427       *
66428       * @example
66429       * <div class="norender">
66430       * <code>
66431       * // Given the CSV file "mammals.csv"
66432       * // in the project's "assets" folder:
66433       * //
66434       * // id,species,name
66435       * // 0,Capra hircus,Goat
66436       * // 1,Panthera pardus,Leopard
66437       * // 2,Equus zebra,Zebra
66438       *
66439       * let table;
66440       *
66441       * function preload() {
66442       *   //my table is comma separated value "csv"
66443       *   //and has a header specifying the columns labels
66444       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
66445       * }
66446       *
66447       * function setup() {
66448       *   table.addColumn('carnivore');
66449       *   table.set(0, 'carnivore', 'no');
66450       *   table.set(1, 'carnivore', 'yes');
66451       *   table.set(2, 'carnivore', 'no');
66452       *
66453       *   //print the results
66454       *   for (let r = 0; r < table.getRowCount(); r++)
66455       *     for (let c = 0; c < table.getColumnCount(); c++)
66456       *       print(table.getString(r, c));
66457       * }
66458       * </code>
66459       * </div>
66460       *
66461       *@alt
66462       * no image displayed
66463       *
66464       */
66465
66466
66467      p5.Table.prototype.addColumn = function (title) {
66468        var t = title || null;
66469        this.columns.push(t);
66470      };
66471      /**
66472       *  Returns the total number of columns in a Table.
66473       *
66474       *  @method  getColumnCount
66475       *  @return {Integer} Number of columns in this table
66476       * @example
66477       * <div>
66478       * <code>
66479       * // given the cvs file "blobs.csv" in /assets directory
66480       * // ID, Name, Flavor, Shape, Color
66481       * // Blob1, Blobby, Sweet, Blob, Pink
66482       * // Blob2, Saddy, Savory, Blob, Blue
66483       *
66484       * let table;
66485       *
66486       * function preload() {
66487       *   table = loadTable('assets/blobs.csv');
66488       * }
66489       *
66490       * function setup() {
66491       *   createCanvas(200, 100);
66492       *   textAlign(CENTER);
66493       *   background(255);
66494       * }
66495       *
66496       * function draw() {
66497       *   let numOfColumn = table.getColumnCount();
66498       *   text('There are ' + numOfColumn + ' columns in the table.', 100, 50);
66499       * }
66500       * </code>
66501       * </div>
66502       */
66503
66504
66505      p5.Table.prototype.getColumnCount = function () {
66506        return this.columns.length;
66507      };
66508      /**
66509       *  Returns the total number of rows in a Table.
66510       *
66511       *  @method  getRowCount
66512       *  @return {Integer} Number of rows in this table
66513       * @example
66514       * <div>
66515       * <code>
66516       * // given the cvs file "blobs.csv" in /assets directory
66517       * //
66518       * // ID, Name, Flavor, Shape, Color
66519       * // Blob1, Blobby, Sweet, Blob, Pink
66520       * // Blob2, Saddy, Savory, Blob, Blue
66521       *
66522       * let table;
66523       *
66524       * function preload() {
66525       *   table = loadTable('assets/blobs.csv');
66526       * }
66527       *
66528       * function setup() {
66529       *   createCanvas(200, 100);
66530       *   textAlign(CENTER);
66531       *   background(255);
66532       * }
66533       *
66534       * function draw() {
66535       *   text('There are ' + table.getRowCount() + ' rows in the table.', 100, 50);
66536       * }
66537       * </code>
66538       * </div>
66539       */
66540
66541
66542      p5.Table.prototype.getRowCount = function () {
66543        return this.rows.length;
66544      };
66545      /**
66546       *  <p>Removes any of the specified characters (or "tokens").</p>
66547       *
66548       *  <p>If no column is specified, then the values in all columns and
66549       *  rows are processed. A specific column may be referenced by
66550       *  either its ID or title.</p>
66551       *
66552       *  @method  removeTokens
66553       *  @param  {String} chars  String listing characters to be removed
66554       *  @param  {String|Integer} [column] Column ID (number)
66555       *                                   or name (string)
66556       *
66557       * @example
66558       * <div class="norender"><code>
66559       * function setup() {
66560       *   let table = new p5.Table();
66561       *
66562       *   table.addColumn('name');
66563       *   table.addColumn('type');
66564       *
66565       *   let newRow = table.addRow();
66566       *   newRow.setString('name', '   $Lion  ,');
66567       *   newRow.setString('type', ',,,Mammal');
66568       *
66569       *   newRow = table.addRow();
66570       *   newRow.setString('name', '$Snake  ');
66571       *   newRow.setString('type', ',,,Reptile');
66572       *
66573       *   table.removeTokens(',$ ');
66574       *   print(table.getArray());
66575       * }
66576       *
66577       * // prints:
66578       * //  0  "Lion"   "Mamal"
66579       * //  1  "Snake"  "Reptile"
66580       * </code></div>
66581       */
66582
66583
66584      p5.Table.prototype.removeTokens = function (chars, column) {
66585        var escape = function (s) {
66586          return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
66587        };
66588
66589        var charArray = [];
66590
66591        for (var i = 0; i < chars.length; i++) {
66592          charArray.push(escape(chars.charAt(i)));
66593        }
66594
66595        var regex = new RegExp(charArray.join('|'), 'g');
66596
66597        if (typeof column === 'undefined') {
66598          for (var c = 0; c < this.columns.length; c++) {
66599            for (var d = 0; d < this.rows.length; d++) {
66600              var s = this.rows[d].arr[c];
66601              s = s.replace(regex, '');
66602              this.rows[d].arr[c] = s;
66603              this.rows[d].obj[this.columns[c]] = s;
66604            }
66605          }
66606        } else if (typeof column === 'string') {
66607          for (var j = 0; j < this.rows.length; j++) {
66608            var val = this.rows[j].obj[column];
66609            val = val.replace(regex, '');
66610            this.rows[j].obj[column] = val;
66611            var pos = this.columns.indexOf(column);
66612            this.rows[j].arr[pos] = val;
66613          }
66614        } else {
66615          for (var k = 0; k < this.rows.length; k++) {
66616            var str = this.rows[k].arr[column];
66617            str = str.replace(regex, '');
66618            this.rows[k].arr[column] = str;
66619            this.rows[k].obj[this.columns[column]] = str;
66620          }
66621        }
66622      };
66623      /**
66624       *  Trims leading and trailing whitespace, such as spaces and tabs,
66625       *  from String table values. If no column is specified, then the
66626       *  values in all columns and rows are trimmed. A specific column
66627       *  may be referenced by either its ID or title.
66628       *
66629       *  @method  trim
66630       *  @param  {String|Integer} [column] Column ID (number)
66631       *                                   or name (string)
66632       * @example
66633       * <div class="norender"><code>
66634       * function setup() {
66635       *   let table = new p5.Table();
66636       *
66637       *   table.addColumn('name');
66638       *   table.addColumn('type');
66639       *
66640       *   let newRow = table.addRow();
66641       *   newRow.setString('name', '   Lion  ,');
66642       *   newRow.setString('type', ' Mammal  ');
66643       *
66644       *   newRow = table.addRow();
66645       *   newRow.setString('name', '  Snake  ');
66646       *   newRow.setString('type', '  Reptile  ');
66647       *
66648       *   table.trim();
66649       *   print(table.getArray());
66650       * }
66651       *
66652       * // prints:
66653       * //  0  "Lion"   "Mamal"
66654       * //  1  "Snake"  "Reptile"
66655       * </code></div>
66656       */
66657
66658
66659      p5.Table.prototype.trim = function (column) {
66660        var regex = new RegExp(' ', 'g');
66661
66662        if (typeof column === 'undefined') {
66663          for (var c = 0; c < this.columns.length; c++) {
66664            for (var d = 0; d < this.rows.length; d++) {
66665              var s = this.rows[d].arr[c];
66666              s = s.replace(regex, '');
66667              this.rows[d].arr[c] = s;
66668              this.rows[d].obj[this.columns[c]] = s;
66669            }
66670          }
66671        } else if (typeof column === 'string') {
66672          for (var j = 0; j < this.rows.length; j++) {
66673            var val = this.rows[j].obj[column];
66674            val = val.replace(regex, '');
66675            this.rows[j].obj[column] = val;
66676            var pos = this.columns.indexOf(column);
66677            this.rows[j].arr[pos] = val;
66678          }
66679        } else {
66680          for (var k = 0; k < this.rows.length; k++) {
66681            var str = this.rows[k].arr[column];
66682            str = str.replace(regex, '');
66683            this.rows[k].arr[column] = str;
66684            this.rows[k].obj[this.columns[column]] = str;
66685          }
66686        }
66687      };
66688      /**
66689       *  Use <a href="#/p5/removeColumn">removeColumn()</a> to remove an existing column from a Table
66690       *  object. The column to be removed may be identified by either
66691       *  its title (a String) or its index value (an int).
66692       *  removeColumn(0) would remove the first column, removeColumn(1)
66693       *  would remove the second column, and so on.
66694       *
66695       *  @method  removeColumn
66696       *  @param  {String|Integer} column columnName (string) or ID (number)
66697       *
66698       * @example
66699       * <div class="norender">
66700       * <code>
66701       * // Given the CSV file "mammals.csv"
66702       * // in the project's "assets" folder:
66703       * //
66704       * // id,species,name
66705       * // 0,Capra hircus,Goat
66706       * // 1,Panthera pardus,Leopard
66707       * // 2,Equus zebra,Zebra
66708       *
66709       * let table;
66710       *
66711       * function preload() {
66712       *   //my table is comma separated value "csv"
66713       *   //and has a header specifying the columns labels
66714       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
66715       * }
66716       *
66717       * function setup() {
66718       *   table.removeColumn('id');
66719       *   print(table.getColumnCount());
66720       * }
66721       * </code>
66722       * </div>
66723       *
66724       *@alt
66725       * no image displayed
66726       *
66727       */
66728
66729
66730      p5.Table.prototype.removeColumn = function (c) {
66731        var cString;
66732        var cNumber;
66733
66734        if (typeof c === 'string') {
66735          // find the position of c in the columns
66736          cString = c;
66737          cNumber = this.columns.indexOf(c);
66738        } else {
66739          cNumber = c;
66740          cString = this.columns[c];
66741        }
66742
66743        var chunk = this.columns.splice(cNumber + 1, this.columns.length);
66744        this.columns.pop();
66745        this.columns = this.columns.concat(chunk);
66746
66747        for (var i = 0; i < this.rows.length; i++) {
66748          var tempR = this.rows[i].arr;
66749          var chip = tempR.splice(cNumber + 1, tempR.length);
66750          tempR.pop();
66751          this.rows[i].arr = tempR.concat(chip);
66752          delete this.rows[i].obj[cString];
66753        }
66754      };
66755      /**
66756       * Stores a value in the Table's specified row and column.
66757       * The row is specified by its ID, while the column may be specified
66758       * by either its ID or title.
66759       *
66760       * @method  set
66761       * @param {Integer} row row ID
66762       * @param {String|Integer} column column ID (Number)
66763       *                               or title (String)
66764       * @param {String|Number} value  value to assign
66765       *
66766       * @example
66767       * <div class="norender">
66768       * <code>
66769       * // Given the CSV file "mammals.csv"
66770       * // in the project's "assets" folder:
66771       * //
66772       * // id,species,name
66773       * // 0,Capra hircus,Goat
66774       * // 1,Panthera pardus,Leopard
66775       * // 2,Equus zebra,Zebra
66776       *
66777       * let table;
66778       *
66779       * function preload() {
66780       *   //my table is comma separated value "csv"
66781       *   //and has a header specifying the columns labels
66782       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
66783       * }
66784       *
66785       * function setup() {
66786       *   table.set(0, 'species', 'Canis Lupus');
66787       *   table.set(0, 'name', 'Wolf');
66788       *
66789       *   //print the results
66790       *   for (let r = 0; r < table.getRowCount(); r++)
66791       *     for (let c = 0; c < table.getColumnCount(); c++)
66792       *       print(table.getString(r, c));
66793       * }
66794       * </code>
66795       * </div>
66796       *
66797       *@alt
66798       * no image displayed
66799       *
66800       */
66801
66802
66803      p5.Table.prototype.set = function (row, column, value) {
66804        this.rows[row].set(column, value);
66805      };
66806      /**
66807       * Stores a Float value in the Table's specified row and column.
66808       * The row is specified by its ID, while the column may be specified
66809       * by either its ID or title.
66810       *
66811       * @method setNum
66812       * @param {Integer} row row ID
66813       * @param {String|Integer} column column ID (Number)
66814       *                               or title (String)
66815       * @param {Number} value  value to assign
66816       *
66817       * @example
66818       * <div class="norender">
66819       * <code>
66820       * // Given the CSV file "mammals.csv"
66821       * // in the project's "assets" folder:
66822       * //
66823       * // id,species,name
66824       * // 0,Capra hircus,Goat
66825       * // 1,Panthera pardus,Leopard
66826       * // 2,Equus zebra,Zebra
66827       *
66828       * let table;
66829       *
66830       * function preload() {
66831       *   //my table is comma separated value "csv"
66832       *   //and has a header specifying the columns labels
66833       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
66834       * }
66835       *
66836       * function setup() {
66837       *   table.setNum(1, 'id', 1);
66838       *
66839       *   print(table.getColumn(0));
66840       *   //["0", 1, "2"]
66841       * }
66842       * </code>
66843       * </div>
66844       *
66845       *@alt
66846       * no image displayed
66847       */
66848
66849
66850      p5.Table.prototype.setNum = function (row, column, value) {
66851        this.rows[row].setNum(column, value);
66852      };
66853      /**
66854       * Stores a String value in the Table's specified row and column.
66855       * The row is specified by its ID, while the column may be specified
66856       * by either its ID or title.
66857       *
66858       * @method  setString
66859       * @param {Integer} row row ID
66860       * @param {String|Integer} column column ID (Number)
66861       *                               or title (String)
66862       * @param {String} value  value to assign
66863       * @example
66864       * <div class="norender"><code>
66865       * // Given the CSV file "mammals.csv" in the project's "assets" folder:
66866       * //
66867       * // id,species,name
66868       * // 0,Capra hircus,Goat
66869       * // 1,Panthera pardus,Leopard
66870       * // 2,Equus zebra,Zebra
66871       *
66872       * let table;
66873       *
66874       * function preload() {
66875       *   //my table is comma separated value "csv"
66876       *   //and has a header specifying the columns labels
66877       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
66878       * }
66879       *
66880       * function setup() {
66881       *   //add a row
66882       *   let newRow = table.addRow();
66883       *   newRow.setString('id', table.getRowCount() - 1);
66884       *   newRow.setString('species', 'Canis Lupus');
66885       *   newRow.setString('name', 'Wolf');
66886       *
66887       *   print(table.getArray());
66888       * }
66889       * </code></div>
66890       *
66891       * @alt
66892       * no image displayed
66893       */
66894
66895
66896      p5.Table.prototype.setString = function (row, column, value) {
66897        this.rows[row].setString(column, value);
66898      };
66899      /**
66900       * Retrieves a value from the Table's specified row and column.
66901       * The row is specified by its ID, while the column may be specified by
66902       * either its ID or title.
66903       *
66904       * @method  get
66905       * @param {Integer} row row ID
66906       * @param  {String|Integer} column columnName (string) or
66907       *                                   ID (number)
66908       * @return {String|Number}
66909       *
66910       * @example
66911       * <div class="norender">
66912       * <code>
66913       * // Given the CSV file "mammals.csv"
66914       * // in the project's "assets" folder:
66915       * //
66916       * // id,species,name
66917       * // 0,Capra hircus,Goat
66918       * // 1,Panthera pardus,Leopard
66919       * // 2,Equus zebra,Zebra
66920       *
66921       * let table;
66922       *
66923       * function preload() {
66924       *   //my table is comma separated value "csv"
66925       *   //and has a header specifying the columns labels
66926       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
66927       * }
66928       *
66929       * function setup() {
66930       *   print(table.get(0, 1));
66931       *   //Capra hircus
66932       *   print(table.get(0, 'species'));
66933       *   //Capra hircus
66934       * }
66935       * </code>
66936       * </div>
66937       *
66938       *@alt
66939       * no image displayed
66940       *
66941       */
66942
66943
66944      p5.Table.prototype.get = function (row, column) {
66945        return this.rows[row].get(column);
66946      };
66947      /**
66948       * Retrieves a Float value from the Table's specified row and column.
66949       * The row is specified by its ID, while the column may be specified by
66950       * either its ID or title.
66951       *
66952       * @method  getNum
66953       * @param {Integer} row row ID
66954       * @param  {String|Integer} column columnName (string) or
66955       *                                   ID (number)
66956       * @return {Number}
66957       *
66958       * @example
66959       * <div class="norender">
66960       * <code>
66961       * // Given the CSV file "mammals.csv"
66962       * // in the project's "assets" folder:
66963       * //
66964       * // id,species,name
66965       * // 0,Capra hircus,Goat
66966       * // 1,Panthera pardus,Leopard
66967       * // 2,Equus zebra,Zebra
66968       *
66969       * let table;
66970       *
66971       * function preload() {
66972       *   //my table is comma separated value "csv"
66973       *   //and has a header specifying the columns labels
66974       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
66975       * }
66976       *
66977       * function setup() {
66978       *   print(table.getNum(1, 0) + 100);
66979       *   //id 1 + 100 = 101
66980       * }
66981       * </code>
66982       * </div>
66983       *
66984       *@alt
66985       * no image displayed
66986       *
66987       */
66988
66989
66990      p5.Table.prototype.getNum = function (row, column) {
66991        return this.rows[row].getNum(column);
66992      };
66993      /**
66994       * Retrieves a String value from the Table's specified row and column.
66995       * The row is specified by its ID, while the column may be specified by
66996       * either its ID or title.
66997       *
66998       * @method  getString
66999       * @param {Integer} row row ID
67000       * @param  {String|Integer} column columnName (string) or
67001       *                                   ID (number)
67002       * @return {String}
67003       *
67004       * @example
67005       * <div class="norender">
67006       * <code>
67007       * // Given the CSV file "mammals.csv"
67008       * // in the project's "assets" folder:
67009       * //
67010       * // id,species,name
67011       * // 0,Capra hircus,Goat
67012       * // 1,Panthera pardus,Leopard
67013       * // 2,Equus zebra,Zebra
67014       *
67015       * let table;
67016       *
67017       * function preload() {
67018       *   // table is comma separated value "CSV"
67019       *   // and has specifiying header for column labels
67020       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
67021       * }
67022       *
67023       * function setup() {
67024       *   print(table.getString(0, 0)); // 0
67025       *   print(table.getString(0, 1)); // Capra hircus
67026       *   print(table.getString(0, 2)); // Goat
67027       *   print(table.getString(1, 0)); // 1
67028       *   print(table.getString(1, 1)); // Panthera pardus
67029       *   print(table.getString(1, 2)); // Leopard
67030       *   print(table.getString(2, 0)); // 2
67031       *   print(table.getString(2, 1)); // Equus zebra
67032       *   print(table.getString(2, 2)); // Zebra
67033       * }
67034       * </code>
67035       * </div>
67036       *
67037       *@alt
67038       * no image displayed
67039       *
67040       */
67041
67042
67043      p5.Table.prototype.getString = function (row, column) {
67044        return this.rows[row].getString(column);
67045      };
67046      /**
67047       * Retrieves all table data and returns as an object. If a column name is
67048       * passed in, each row object will be stored with that attribute as its
67049       * title.
67050       *
67051       * @method  getObject
67052       * @param {String} [headerColumn] Name of the column which should be used to
67053       *                              title each row object (optional)
67054       * @return {Object}
67055       *
67056       * @example
67057       * <div class="norender">
67058       * <code>
67059       * // Given the CSV file "mammals.csv"
67060       * // in the project's "assets" folder:
67061       * //
67062       * // id,species,name
67063       * // 0,Capra hircus,Goat
67064       * // 1,Panthera pardus,Leopard
67065       * // 2,Equus zebra,Zebra
67066       *
67067       * let table;
67068       *
67069       * function preload() {
67070       *   //my table is comma separated value "csv"
67071       *   //and has a header specifying the columns labels
67072       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
67073       * }
67074       *
67075       * function setup() {
67076       *   let tableObject = table.getObject();
67077       *
67078       *   print(tableObject);
67079       *   //outputs an object
67080       * }
67081       * </code>
67082       * </div>
67083       *
67084       *@alt
67085       * no image displayed
67086       *
67087       */
67088
67089
67090      p5.Table.prototype.getObject = function (headerColumn) {
67091        var tableObject = {};
67092        var obj, cPos, index;
67093
67094        for (var i = 0; i < this.rows.length; i++) {
67095          obj = this.rows[i].obj;
67096
67097          if (typeof headerColumn === 'string') {
67098            cPos = this.columns.indexOf(headerColumn); // index of columnID
67099
67100            if (cPos >= 0) {
67101              index = obj[headerColumn];
67102              tableObject[index] = obj;
67103            } else {
67104              throw new Error('This table has no column named "' + headerColumn + '"');
67105            }
67106          } else {
67107            tableObject[i] = this.rows[i].obj;
67108          }
67109        }
67110
67111        return tableObject;
67112      };
67113      /**
67114       * Retrieves all table data and returns it as a multidimensional array.
67115       *
67116       * @method  getArray
67117       * @return {Array}
67118       *
67119       * @example
67120       * <div class="norender">
67121       * <code>
67122       * // Given the CSV file "mammals.csv"
67123       * // in the project's "assets" folder
67124       * //
67125       * // id,species,name
67126       * // 0,Capra hircus,Goat
67127       * // 1,Panthera pardus,Leoperd
67128       * // 2,Equus zebra,Zebra
67129       *
67130       * let table;
67131       *
67132       * function preload() {
67133       *   // table is comma separated value "CSV"
67134       *   // and has specifiying header for column labels
67135       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
67136       * }
67137       *
67138       * function setup() {
67139       *   let tableArray = table.getArray();
67140       *   for (let i = 0; i < tableArray.length; i++) {
67141       *     print(tableArray[i]);
67142       *   }
67143       * }
67144       * </code>
67145       * </div>
67146       *
67147       *@alt
67148       * no image displayed
67149       *
67150       */
67151
67152
67153      p5.Table.prototype.getArray = function () {
67154        var tableArray = [];
67155
67156        for (var i = 0; i < this.rows.length; i++) {
67157          tableArray.push(this.rows[i].arr);
67158        }
67159
67160        return tableArray;
67161      };
67162
67163      module.exports = p5;
67164    }, {
67165      "../core/main": 24
67166    }],
67167    49: [function (_dereq_, module, exports) {
67168      /**
67169       * @module IO
67170       * @submodule Table
67171       * @requires core
67172       */
67173      'use strict';
67174
67175      var p5 = _dereq_('../core/main');
67176      /**
67177       *  A TableRow object represents a single row of data values,
67178       *  stored in columns, from a table.
67179       *
67180       *  A Table Row contains both an ordered array, and an unordered
67181       *  JSON object.
67182       *
67183       *  @class p5.TableRow
67184       *  @constructor
67185       *  @param {String} [str]       optional: populate the row with a
67186       *                              string of values, separated by the
67187       *                              separator
67188       *  @param {String} [separator] comma separated values (csv) by default
67189       */
67190
67191
67192      p5.TableRow = function (str, separator) {
67193        var arr = [];
67194        var obj = {};
67195
67196        if (str) {
67197          separator = separator || ',';
67198          arr = str.split(separator);
67199        }
67200
67201        for (var i = 0; i < arr.length; i++) {
67202          var key = i;
67203          var val = arr[i];
67204          obj[key] = val;
67205        }
67206
67207        this.arr = arr;
67208        this.obj = obj;
67209        this.table = null;
67210      };
67211      /**
67212       *  Stores a value in the TableRow's specified column.
67213       *  The column may be specified by either its ID or title.
67214       *
67215       *  @method  set
67216       *  @param {String|Integer} column Column ID (Number)
67217       *                                or Title (String)
67218       *  @param {String|Number} value  The value to be stored
67219       *
67220       * @example
67221       * <div class="norender"><code>
67222       * // Given the CSV file "mammals.csv" in the project's "assets" folder:
67223       * //
67224       * // id,species,name
67225       * // 0,Capra hircus,Goat
67226       * // 1,Panthera pardus,Leopard
67227       * // 2,Equus zebra,Zebra
67228       *
67229       * let table;
67230       *
67231       * function preload() {
67232       *   //my table is comma separated value "csv"
67233       *   //and has a header specifying the columns labels
67234       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
67235       * }
67236       *
67237       * function setup() {
67238       *   let rows = table.getRows();
67239       *   for (let r = 0; r < rows.length; r++) {
67240       *     rows[r].set('name', 'Unicorn');
67241       *   }
67242       *
67243       *   //print the results
67244       *   print(table.getArray());
67245       * }
67246       * </code></div>
67247       *
67248       * @alt
67249       * no image displayed
67250       */
67251
67252
67253      p5.TableRow.prototype.set = function (column, value) {
67254        // if typeof column is string, use .obj
67255        if (typeof column === 'string') {
67256          var cPos = this.table.columns.indexOf(column); // index of columnID
67257
67258          if (cPos >= 0) {
67259            this.obj[column] = value;
67260            this.arr[cPos] = value;
67261          } else {
67262            throw new Error('This table has no column named "' + column + '"');
67263          }
67264        } else {
67265          // if typeof column is number, use .arr
67266          if (column < this.table.columns.length) {
67267            this.arr[column] = value;
67268            var cTitle = this.table.columns[column];
67269            this.obj[cTitle] = value;
67270          } else {
67271            throw new Error('Column #' + column + ' is out of the range of this table');
67272          }
67273        }
67274      };
67275      /**
67276       *  Stores a Float value in the TableRow's specified column.
67277       *  The column may be specified by either its ID or title.
67278       *
67279       *  @method  setNum
67280       *  @param {String|Integer} column Column ID (Number)
67281       *                                or Title (String)
67282       *  @param {Number|String} value  The value to be stored
67283       *                                as a Float
67284       * @example
67285       * <div class="norender"><code>
67286       * // Given the CSV file "mammals.csv" in the project's "assets" folder:
67287       * //
67288       * // id,species,name
67289       * // 0,Capra hircus,Goat
67290       * // 1,Panthera pardus,Leopard
67291       * // 2,Equus zebra,Zebra
67292       *
67293       * let table;
67294       *
67295       * function preload() {
67296       *   //my table is comma separated value "csv"
67297       *   //and has a header specifying the columns labels
67298       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
67299       * }
67300       *
67301       * function setup() {
67302       *   let rows = table.getRows();
67303       *   for (let r = 0; r < rows.length; r++) {
67304       *     rows[r].setNum('id', r + 10);
67305       *   }
67306       *
67307       *   print(table.getArray());
67308       * }
67309       * </code></div>
67310       *
67311       * @alt
67312       * no image displayed
67313       */
67314
67315
67316      p5.TableRow.prototype.setNum = function (column, value) {
67317        var floatVal = parseFloat(value);
67318        this.set(column, floatVal);
67319      };
67320      /**
67321       *  Stores a String value in the TableRow's specified column.
67322       *  The column may be specified by either its ID or title.
67323       *
67324       *  @method  setString
67325       *  @param {String|Integer} column Column ID (Number)
67326       *                                or Title (String)
67327       *  @param {String|Number|Boolean|Object} value  The value to be stored
67328       *                                as a String
67329       * @example
67330       * <div class="norender"><code>
67331       * // Given the CSV file "mammals.csv" in the project's "assets" folder:
67332       * //
67333       * // id,species,name
67334       * // 0,Capra hircus,Goat
67335       * // 1,Panthera pardus,Leopard
67336       * // 2,Equus zebra,Zebra
67337       *
67338       * let table;
67339       *
67340       * function preload() {
67341       *   //my table is comma separated value "csv"
67342       *   //and has a header specifying the columns labels
67343       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
67344       * }
67345       *
67346       * function setup() {
67347       *   let rows = table.getRows();
67348       *   for (let r = 0; r < rows.length; r++) {
67349       *     let name = rows[r].getString('name');
67350       *     rows[r].setString('name', 'A ' + name + ' named George');
67351       *   }
67352       *
67353       *   print(table.getArray());
67354       * }
67355       * </code></div>
67356       *
67357       * @alt
67358       * no image displayed
67359       */
67360
67361
67362      p5.TableRow.prototype.setString = function (column, value) {
67363        var stringVal = value.toString();
67364        this.set(column, stringVal);
67365      };
67366      /**
67367       *  Retrieves a value from the TableRow's specified column.
67368       *  The column may be specified by either its ID or title.
67369       *
67370       *  @method  get
67371       *  @param  {String|Integer} column columnName (string) or
67372       *                                   ID (number)
67373       *  @return {String|Number}
67374       *
67375       * @example
67376       * <div class="norender"><code>
67377       * // Given the CSV file "mammals.csv" in the project's "assets" folder:
67378       * //
67379       * // id,species,name
67380       * // 0,Capra hircus,Goat
67381       * // 1,Panthera pardus,Leopard
67382       * // 2,Equus zebra,Zebra
67383       *
67384       * let table;
67385       *
67386       * function preload() {
67387       *   //my table is comma separated value "csv"
67388       *   //and has a header specifying the columns labels
67389       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
67390       * }
67391       *
67392       * function setup() {
67393       *   let names = [];
67394       *   let rows = table.getRows();
67395       *   for (let r = 0; r < rows.length; r++) {
67396       *     names.push(rows[r].get('name'));
67397       *   }
67398       *
67399       *   print(names);
67400       * }
67401       * </code></div>
67402       *
67403       * @alt
67404       * no image displayed
67405       */
67406
67407
67408      p5.TableRow.prototype.get = function (column) {
67409        if (typeof column === 'string') {
67410          return this.obj[column];
67411        } else {
67412          return this.arr[column];
67413        }
67414      };
67415      /**
67416       *  Retrieves a Float value from the TableRow's specified
67417       *  column. The column may be specified by either its ID or
67418       *  title.
67419       *
67420       *  @method  getNum
67421       *  @param  {String|Integer} column columnName (string) or
67422       *                                   ID (number)
67423       *  @return {Number}  Float Floating point number
67424       * @example
67425       * <div class="norender"><code>
67426       * // Given the CSV file "mammals.csv" in the project's "assets" folder:
67427       * //
67428       * // id,species,name
67429       * // 0,Capra hircus,Goat
67430       * // 1,Panthera pardus,Leopard
67431       * // 2,Equus zebra,Zebra
67432       *
67433       * let table;
67434       *
67435       * function preload() {
67436       *   //my table is comma separated value "csv"
67437       *   //and has a header specifying the columns labels
67438       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
67439       * }
67440       *
67441       * function setup() {
67442       *   let rows = table.getRows();
67443       *   let minId = Infinity;
67444       *   let maxId = -Infinity;
67445       *   for (let r = 0; r < rows.length; r++) {
67446       *     let id = rows[r].getNum('id');
67447       *     minId = min(minId, id);
67448       *     maxId = min(maxId, id);
67449       *   }
67450       *   print('minimum id = ' + minId + ', maximum id = ' + maxId);
67451       * }
67452       * </code></div>
67453       *
67454       * @alt
67455       * no image displayed
67456       */
67457
67458
67459      p5.TableRow.prototype.getNum = function (column) {
67460        var ret;
67461
67462        if (typeof column === 'string') {
67463          ret = parseFloat(this.obj[column]);
67464        } else {
67465          ret = parseFloat(this.arr[column]);
67466        }
67467
67468        if (ret.toString() === 'NaN') {
67469          throw 'Error: ' + this.obj[column] + ' is NaN (Not a Number)';
67470        }
67471
67472        return ret;
67473      };
67474      /**
67475       *  Retrieves an String value from the TableRow's specified
67476       *  column. The column may be specified by either its ID or
67477       *  title.
67478       *
67479       *  @method  getString
67480       *  @param  {String|Integer} column columnName (string) or
67481       *                                   ID (number)
67482       *  @return {String}  String
67483       * @example
67484       * <div class="norender"><code>
67485       * // Given the CSV file "mammals.csv" in the project's "assets" folder:
67486       * //
67487       * // id,species,name
67488       * // 0,Capra hircus,Goat
67489       * // 1,Panthera pardus,Leopard
67490       * // 2,Equus zebra,Zebra
67491       *
67492       * let table;
67493       *
67494       * function preload() {
67495       *   //my table is comma separated value "csv"
67496       *   //and has a header specifying the columns labels
67497       *   table = loadTable('assets/mammals.csv', 'csv', 'header');
67498       * }
67499       *
67500       * function setup() {
67501       *   let rows = table.getRows();
67502       *   let longest = '';
67503       *   for (let r = 0; r < rows.length; r++) {
67504       *     let species = rows[r].getString('species');
67505       *     if (longest.length < species.length) {
67506       *       longest = species;
67507       *     }
67508       *   }
67509       *
67510       *   print('longest: ' + longest);
67511       * }
67512       * </code></div>
67513       *
67514       * @alt
67515       * no image displayed
67516       */
67517
67518
67519      p5.TableRow.prototype.getString = function (column) {
67520        if (typeof column === 'string') {
67521          return this.obj[column].toString();
67522        } else {
67523          return this.arr[column].toString();
67524        }
67525      };
67526
67527      module.exports = p5;
67528    }, {
67529      "../core/main": 24
67530    }],
67531    50: [function (_dereq_, module, exports) {
67532      /**
67533       * @module IO
67534       * @submodule XML
67535       * @requires core
67536       */
67537      'use strict';
67538
67539      var p5 = _dereq_('../core/main');
67540      /**
67541       * XML is a representation of an XML object, able to parse XML code. Use
67542       * <a href="#/p5/loadXML">loadXML()</a> to load external XML files and create XML objects.
67543       *
67544       * @class p5.XML
67545       * @constructor
67546       * @example
67547       * <div class='norender'><code>
67548       * // The following short XML file called "mammals.xml" is parsed
67549       * // in the code below.
67550       * //
67551       * // <?xml version="1.0"?>
67552       * // &lt;mammals&gt;
67553       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
67554       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
67555       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
67556       * // &lt;/mammals&gt;
67557       *
67558       * let xml;
67559       *
67560       * function preload() {
67561       *   xml = loadXML('assets/mammals.xml');
67562       * }
67563       *
67564       * function setup() {
67565       *   let children = xml.getChildren('animal');
67566       *
67567       *   for (let i = 0; i < children.length; i++) {
67568       *     let id = children[i].getNum('id');
67569       *     let coloring = children[i].getString('species');
67570       *     let name = children[i].getContent();
67571       *     print(id + ', ' + coloring + ', ' + name);
67572       *   }
67573       * }
67574       *
67575       * // Sketch prints:
67576       * // 0, Capra hircus, Goat
67577       * // 1, Panthera pardus, Leopard
67578       * // 2, Equus zebra, Zebra
67579       * </code></div>
67580       *
67581       * @alt
67582       * no image displayed
67583       *
67584       */
67585
67586
67587      p5.XML = function (DOM) {
67588        if (!DOM) {
67589          var xmlDoc = document.implementation.createDocument(null, 'doc');
67590          this.DOM = xmlDoc.createElement('root');
67591        } else {
67592          this.DOM = DOM;
67593        }
67594      };
67595      /**
67596       * Gets a copy of the element's parent. Returns the parent as another
67597       * <a href="#/p5.XML">p5.XML</a> object.
67598       *
67599       * @method getParent
67600       * @return {p5.XML}   element parent
67601       * @example
67602       * <div class='norender'><code>
67603       * // The following short XML file called "mammals.xml" is parsed
67604       * // in the code below.
67605       * //
67606       * // <?xml version="1.0"?>
67607       * // &lt;mammals&gt;
67608       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
67609       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
67610       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
67611       * // &lt;/mammals&gt;
67612       *
67613       * let xml;
67614       *
67615       * function preload() {
67616       *   xml = loadXML('assets/mammals.xml');
67617       * }
67618       *
67619       * function setup() {
67620       *   let children = xml.getChildren('animal');
67621       *   let parent = children[1].getParent();
67622       *   print(parent.getName());
67623       * }
67624       *
67625       * // Sketch prints:
67626       * // mammals
67627       * </code></div>
67628       */
67629
67630
67631      p5.XML.prototype.getParent = function () {
67632        return new p5.XML(this.DOM.parentElement);
67633      };
67634      /**
67635       *  Gets the element's full name, which is returned as a String.
67636       *
67637       * @method getName
67638       * @return {String} the name of the node
67639       * @example&lt;animal
67640       * <div class='norender'><code>
67641       * // The following short XML file called "mammals.xml" is parsed
67642       * // in the code below.
67643       * //
67644       * // <?xml version="1.0"?>
67645       * // &lt;mammals&gt;
67646       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
67647       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
67648       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
67649       * // &lt;/mammals&gt;
67650       *
67651       * let xml;
67652       *
67653       * function preload() {
67654       *   xml = loadXML('assets/mammals.xml');
67655       * }
67656       *
67657       * function setup() {
67658       *   print(xml.getName());
67659       * }
67660       *
67661       * // Sketch prints:
67662       * // mammals
67663       * </code></div>
67664       */
67665
67666
67667      p5.XML.prototype.getName = function () {
67668        return this.DOM.tagName;
67669      };
67670      /**
67671       * Sets the element's name, which is specified as a String.
67672       *
67673       * @method setName
67674       * @param {String} the new name of the node
67675       * @example&lt;animal
67676       * <div class='norender'><code>
67677       * // The following short XML file called "mammals.xml" is parsed
67678       * // in the code below.
67679       * //
67680       * // <?xml version="1.0"?>
67681       * // &lt;mammals&gt;
67682       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
67683       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
67684       * //   &lt;animal id="2" species="Equus zebra">
67684Zebra&lt;/animal&gt;
67685       * // &lt;/mammals&gt;
67686       *
67687       * let xml;
67688       *
67689       * function preload() {
67690       *   xml = loadXML('assets/mammals.xml');
67691       * }
67692       *
67693       * function setup() {
67694       *   print(xml.getName());
67695       *   xml.setName('fish');
67696       *   print(xml.getName());
67697       * }
67698       *
67699       * // Sketch prints:
67700       * // mammals
67701       * // fish
67702       * </code></div>
67703       */
67704
67705
67706      p5.XML.prototype.setName = function (name) {
67707        var content = this.DOM.innerHTML;
67708        var attributes = this.DOM.attributes;
67709        var xmlDoc = document.implementation.createDocument(null, 'default');
67710        var newDOM = xmlDoc.createElement(name);
67711        newDOM.innerHTML = content;
67712
67713        for (var i = 0; i < attributes.length; i++) {
67714          newDOM.setAttribute(attributes[i].nodeName, attributes.nodeValue);
67715        }
67716
67717        this.DOM = newDOM;
67718      };
67719      /**
67720       * Checks whether or not the element has any children, and returns the result
67721       * as a boolean.
67722       *
67723       * @method hasChildren
67724       * @return {boolean}
67725       * @example&lt;animal
67726       * <div class='norender'><code>
67727       * // The following short XML file called "mammals.xml" is parsed
67728       * // in the code below.
67729       * //
67730       * // <?xml version="1.0"?>
67731       * // &lt;mammals&gt;
67732       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
67733       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
67734       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
67735       * // &lt;/mammals&gt;
67736       *
67737       * let xml;
67738       *
67739       * function preload() {
67740       *   xml = loadXML('assets/mammals.xml');
67741       * }
67742       *
67743       * function setup() {
67744       *   print(xml.hasChildren());
67745       * }
67746       *
67747       * // Sketch prints:
67748       * // true
67749       * </code></div>
67750       */
67751
67752
67753      p5.XML.prototype.hasChildren = function () {
67754        return this.DOM.children.length > 0;
67755      };
67756      /**
67757       * Get the names of all of the element's children, and returns the names as an
67758       * array of Strings. This is the same as looping through and calling <a href="#/p5.XML/getName">getName()</a>
67759       * on each child element individually.
67760       *
67761       * @method listChildren
67762       * @return {String[]} names of the children of the element
67763       * @example&lt;animal
67764       * <div class='norender'><code>
67765       * // The following short XML file called "mammals.xml" is parsed
67766       * // in the code below.
67767       * //
67768       * // <?xml version="1.0"?>
67769       * // &lt;mammals&gt;
67770       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
67771       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
67772       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
67773       * // &lt;/mammals&gt;
67774       *
67775       * let xml;
67776       *
67777       * function preload() {
67778       *   xml = loadXML('assets/mammals.xml');
67779       * }
67780       *
67781       * function setup() {
67782       *   print(xml.listChildren());
67783       * }
67784       *
67785       * // Sketch prints:
67786       * // ["animal", "animal", "animal"]
67787       * </code></div>
67788       */
67789
67790
67791      p5.XML.prototype.listChildren = function () {
67792        var arr = [];
67793
67794        for (var i = 0; i < this.DOM.childNodes.length; i++) {
67795          arr.push(this.DOM.childNodes[i].nodeName);
67796        }
67797
67798        return arr;
67799      };
67800      /**
67801       * Returns all of the element's children as an array of <a href="#/p5.XML">p5.XML</a> objects. When
67802       * the name parameter is specified, then it will return all children that match
67803       * that name.
67804       *
67805       * @method getChildren
67806       * @param {String} [name] element name
67807       * @return {p5.XML[]} children of the element
67808       * @example&lt;animal
67809       * <div class='norender'><code>
67810       * // The following short XML file called "mammals.xml" is parsed
67811       * // in the code below.
67812       * //
67813       * // <?xml version="1.0"?>
67814       * // &lt;mammals&gt;
67815       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
67816       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
67817       * //   &lt;animal id="2" species="Equus zebra">
67817Zebra&lt;/animal&gt;
67818       * // &lt;/mammals&gt;
67819       *
67820       * let xml;
67821       *
67822       * function preload() {
67823       *   xml = loadXML('assets/mammals.xml');
67824       * }
67825       *
67826       * function setup() {
67827       *   let animals = xml.getChildren('animal');
67828       *
67829       *   for (let i = 0; i < animals.length; i++) {
67830       *     print(animals[i].getContent());
67831       *   }
67832       * }
67833       *
67834       * // Sketch prints:
67835       * // "Goat"
67836       * // "Leopard"
67837       * // "Zebra"
67838       * </code></div>
67839       */
67840
67841
67842      p5.XML.prototype.getChildren = function (param) {
67843        if (param) {
67844          return elementsToP5XML(this.DOM.getElementsByTagName(param));
67845        } else {
67846          return elementsToP5XML(this.DOM.children);
67847        }
67848      };
67849
67850      function elementsToP5XML(elements) {
67851        var arr = [];
67852
67853        for (var i = 0; i < elements.length; i++) {
67854          arr.push(new p5.XML(elements[i]));
67855        }
67856
67857        return arr;
67858      }
67859      /**
67860       * Returns the first of the element's children that matches the name parameter
67861       * or the child of the given index.It returns undefined if no matching
67862       * child is found.
67863       *
67864       * @method getChild
67865       * @param {String|Integer} name element name or index
67866       * @return {p5.XML}
67867       * @example&lt;animal
67868       * <div class='norender'><code>
67869       * // The following short XML file called "mammals.xml" is parsed
67870       * // in the code below.
67871       * //
67872       * // <?xml version="1.0"?>
67873       * // &lt;mammals&gt;
67874       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
67875       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
67876       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
67877       * // &lt;/mammals&gt;
67878       *
67879       * let xml;
67880       *
67881       * function preload() {
67882       *   xml = loadXML('assets/mammals.xml');
67883       * }
67884       *
67885       * function setup() {
67886       *   let firstChild = xml.getChild('animal');
67887       *   print(firstChild.getContent());
67888       * }
67889       *
67890       * // Sketch prints:
67891       * // "Goat"
67892       * </code></div>
67893       * <div class='norender'><code>
67894       * let xml;
67895       *
67896       * function preload() {
67897       *   xml = loadXML('assets/mammals.xml');
67898       * }
67899       *
67900       * function setup() {
67901       *   let secondChild = xml.getChild(1);
67902       *   print(secondChild.getContent());
67903       * }
67904       *
67905       * // Sketch prints:
67906       * // "Leopard"
67907       * </code></div>
67908       */
67909
67910
67911      p5.XML.prototype.getChild = function (param) {
67912        if (typeof param === 'string') {
67913          for (var i = 0; i < this.DOM.children.length; i++) {
67914            var child = this.DOM.children[i];
67915            if (child.tagName === param) return new p5.XML(child);
67916          }
67917        } else {
67918          return new p5.XML(this.DOM.children[param]);
67919        }
67920      };
67921      /**
67922       * Appends a new child to the element. The child can be specified with
67923       * either a String, which will be used as the new tag's name, or as a
67924       * reference to an existing <a href="#/p5.XML">p5.XML</a> object.
67925       * A reference to the newly created child is returned as an <a href="#/p5.XML">p5.XML</a> object.
67926       *
67927       * @method addChild
67928       * @param {p5.XML} node a <a href="#/p5.XML">p5.XML</a> Object which will be the child to be added
67929       * @example
67930       * <div class='norender'><code>
67931       * // The following short XML file called "mammals.xml" is parsed
67932       * // in the code below.
67933       * //
67934       * // <?xml version="1.0"?>
67935       * // &lt;mammals&gt;
67936       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
67937       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
67938       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
67939       * // &lt;/mammals&gt;
67940       *
67941       * let xml;
67942       *
67943       * function preload() {
67944       *   xml = loadXML('assets/mammals.xml');
67945       * }
67946       *
67947       * function setup() {
67948       *   let child = new p5.XML();
67949       *   child.setName('animal');
67950       *   child.setAttribute('id', '3');
67951       *   child.setAttribute('species', 'Ornithorhynchus anatinu
67951s');
67952       *   child.setContent('Platypus');
67953       *   xml.addChild(child);
67954       *
67955       *   let animals = xml.getChildren('animal');
67956       *   print(animals[animals.length - 1].getContent());
67957       * }
67958       *
67959       * // Sketch prints:
67960       * // "Goat"
67961       * // "Leopard"
67962       * // "Zebra"
67963       * </code></div>
67964       */
67965
67966
67967      p5.XML.prototype.addChild = function (node) {
67968        if (node instanceof p5.XML) {
67969          this.DOM.appendChild(node.DOM);
67970        } else {// PEND
67971        }
67972      };
67973      /**
67974       * Removes the element specified by name or index.
67975       *
67976       * @method removeChild
67977       * @param {String|Integer} name element name or index
67978       * @example
67979       * <div class='norender'><code>
67980       * // The following short XML file called "mammals.xml" is parsed
67981       * // in the code below.
67982       * //
67983       * // <?xml version="1.0"?>
67984       * // &lt;mammals&gt;
67985       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
67986       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
67987       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
67988       * // &lt;/mammals&gt;
67989       *
67990       * let xml;
67991       *
67992       * function preload() {
67993       *   xml = loadXML('assets/mammals.xml');
67994       * }
67995       *
67996       * function setup() {
67997       *   xml.removeChild('animal');
67998       *   let children = xml.getChildren();
67999       *   for (let i = 0; i < children.length; i++) {
68000       *     print(children[i].getContent());
68001       *   }
68002       * }
68003       *
68004       * // Sketch prints:
68005       * // "Leopard"
68006       * // "Zebra"
68007       * </code></div>
68008       * <div class='norender'><code>
68009       * let xml;
68010       *
68011       * function preload() {
68012       *   xml = loadXML('assets/mammals.xml');
68013       * }
68014       *
68015       * function setup() {
68016       *   xml.removeChild(1);
68017       *   let children = xml.getChildren();
68018       *   for (let i = 0; i < children.length; i++) {
68019       *     print(children[i].getContent());
68020       *   }
68021       * }
68022       *
68023       * // Sketch prints:
68024       * // "Goat"
68025       * // "Zebra"
68026       * </code></div>
68027       */
68028
68029
68030      p5.XML.prototype.removeChild = function (param) {
68031        var ind = -1;
68032
68033        if (typeof param === 'string') {
68034          for (var i = 0; i < this.DOM.children.length; i++) {
68035            if (this.DOM.children[i].tagName === param) {
68036              ind = i;
68037              break;
68038            }
68039          }
68040        } else {
68041          ind = param;
68042        }
68043
68044        if (ind !== -1) {
68045          this.DOM.removeChild(this.DOM.children[ind]);
68046        }
68047      };
68048      /**
68049       * Counts the specified element's number of attributes, returned as an Number.
68050       *
68051       * @method getAttributeCount
68052       * @return {Integer}
68053       * @example
68054       * <div class='norender'><code>
68055       * // The following short XML file called "mammals.xml" is parsed
68056       * // in the code below.
68057       * //
68058       * // <?xml version="1.0"?>
68059       * // &lt;mammals&gt;
68060       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
68061       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
68062       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
68063       * // &lt;/mammals&gt;
68064       *
68065       * let xml;
68066       *
68067       * function preload() {
68068       *   xml = loadXML('assets/mammals.xml');
68069       * }
68070       *
68071       * function setup() {
68072       *   let firstChild = xml.getChild('animal');
68073       *   print(firstChild.getAttributeCount());
68074       * }
68075       *
68076       * // Sketch prints:
68077       * // 2
68078       * </code></div>
68079       */
68080
68081
68082      p5.XML.prototype.getAttributeCount = function () {
68083        return this.DOM.attributes.length;
68084      };
68085      /**
68086       * Gets all of the specified element's attributes, and returns them as an
68087       * array of Strings.
68088       *
68089       * @method listAttributes
68090       * @return {String[]} an array of strings containing the names of attributes
68091       * @example
68092       * <div class='norender'><code>
68093       * // The following short XML file called "mammals.xml" is parsed
68094       * // in the code below.
68095       * //
68096       * // <?xml version="1.0"?>
68097       * // &lt;mammals&gt;
68098       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
68099       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
68100       * //   &lt;animal id="2" species="Equus zebra">
68100Zebra&lt;/animal&gt;
68101       * // &lt;/mammals&gt;
68102       *
68103       * let xml;
68104       *
68105       * function preload() {
68106       *   xml = loadXML('assets/mammals.xml');
68107       * }
68108       *
68109       * function setup() {
68110       *   let firstChild = xml.getChild('animal');
68111       *   print(firstChild.listAttributes());
68112       * }
68113       *
68114       * // Sketch prints:
68115       * // ["id", "species"]
68116       * </code></div>
68117       */
68118
68119
68120      p5.XML.prototype.listAttributes = function () {
68121        var arr = [];
68122
68123        for (var i = 0; i < this.DOM.attributes.length; i++) {
68124          var attribute = this.DOM.attributes[i];
68125          arr.push(attribute.nodeName);
68126        }
68127
68128        return arr;
68129      };
68130      /**
68131       *  Checks whether or not an element has the specified attribute.
68132       *
68133       * @method hasAttribute
68134       * @param {String} the attribute to be checked
68135       * @return {boolean} true if attribute found else false
68136       * @example
68137       * <div class='norender'><code>
68138       * // The following short XML file called "mammals.xml" is parsed
68139       * // in the code below.
68140       * //
68141       * // <?xml version="1.0"?>
68142       * // &lt;mammals&gt;
68143       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
68144       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
68145       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
68146       * // &lt;/mammals&gt;
68147       *
68148       * let xml;
68149       *
68150       * function preload() {
68151       *   xml = loadXML('assets/mammals.xml');
68152       * }
68153       *
68154       * function setup() {
68155       *   let firstChild = xml.getChild('animal');
68156       *   print(firstChild.hasAttribute('species'));
68157       *   print(firstChild.hasAttribute('color'));
68158       * }
68159       *
68160       * // Sketch prints:
68161       * // true
68162       * // false
68163       * </code></div>
68164       */
68165
68166
68167      p5.XML.prototype.hasAttribute = function (name) {
68168        var obj = {};
68169
68170        for (var i = 0; i < this.DOM.attributes.length; i++) {
68171          var attribute = this.DOM.attributes[i];
68172          obj[attribute.nodeName] = attribute.nodeValue;
68173        }
68174
68175        return obj[name] ? true : false;
68176      };
68177      /**
68178       * Returns an attribute value of the element as an Number. If the defaultValue
68179       * parameter is specified and the attribute doesn't exist, then defaultValue
68180       * is returned. If no defaultValue is specified and the attribute doesn't
68181       * exist, the value 0 is returned.
68182       *
68183       * @method getNum
68184       * @param {String} name            the non-null full name of the attribute
68185       * @param {Number} [defaultValue]  the default value of the attribute
68186       * @return {Number}
68187       * @example
68188       * <div class='norender'><code>
68189       * // The following short XML file called "mammals.xml" is parsed
68190       * // in the code below.
68191       * //
68192       * // <?xml version="1.0"?>
68193       * // &lt;mammals&gt;
68194       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
68195       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
68196       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
68197       * // &lt;/mammals&gt;
68198       *
68199       * let xml;
68200       *
68201       * function preload() {
68202       *   xml = loadXML('assets/mammals.xml');
68203       * }
68204       *
68205       * function setup() {
68206       *   let firstChild = xml.getChild('animal');
68207       *   print(firstChild.getNum('id'));
68208       * }
68209       *
68210       * // Sketch prints:
68211       * // 0
68212       * </code></div>
68213       */
68214
68215
68216      p5.XML.prototype.getNum = function (name, defaultValue) {
68217        var obj = {};
68218
68219        for (var i = 0; i < this.DOM.attributes.length; i++) {
68220          var attribute = this.DOM.attributes[i];
68221          obj[attribute.nodeName] = attribute.nodeValue;
68222        }
68223
68224        return Number(obj[name]) || defaultValue || 0;
68225      };
68226      /**
68227       * Returns an attribute value of the element as an String. If the defaultValue
68228       * parameter is specified and the attribute doesn't exist, then defaultValue
68229       * is returned. If no defaultValue is specified and the attribute doesn't
68230       * exist, null is returned.
68231       *
68232       * @method getString
68233       * @param {String} name            the non-null full name of the attribute
68234       * @param {Number} [defaultValue]  the default value of the attribute
68235       * @return {String}
68236       * @example
68237       * <div class='norender'><code>
68238       * // The following short XML file called "mammals.xml" is parsed
68239       * // in the code below.
68240       * //
68241       * // <?xml version="1.0"?>
68242       * // &lt;mammals&gt;
68243       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
68244       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
68245       * //   &lt;animal id="2" species="Equus zebra">
68245Zebra&lt;/animal&gt;
68246       * // &lt;/mammals&gt;
68247       *
68248       * let xml;
68249       *
68250       * function preload() {
68251       *   xml = loadXML('assets/mammals.xml');
68252       * }
68253       *
68254       * function setup() {
68255       *   let firstChild = xml.getChild('animal');
68256       *   print(firstChild.getString('species'));
68257       * }
68258       *
68259       * // Sketch prints:
68260       * // "Capra hircus"
68261       * </code></div>
68262       */
68263
68264
68265      p5.XML.prototype.getString = function (name, defaultValue) {
68266        var obj = {};
68267
68268        for (var i = 0; i < this.DOM.attributes.length; i++) {
68269          var attribute = this.DOM.attributes[i];
68270          obj[attribute.nodeName] = attribute.nodeValue;
68271        }
68272
68273        return obj[name] ? String(obj[name]) : defaultValue || null;
68274      };
68275      /**
68276       * Sets the content of an element's attribute. The first parameter specifies
68277       * the attribute name, while the second specifies the new content.
68278       *
68279       * @method setAttribute
68280       * @param {String} name            the full name of the attribute
68281       * @param {Number|String|Boolean} value  the value of the attribute
68282       * @example
68283       * <div class='norender'><code>
68284       * // The following short XML file called "mammals.xml" is parsed
68285       * // in the code below.
68286       * //
68287       * // <?xml version="1.0"?>
68288       * // &lt;mammals&gt;
68289       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
68290       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
68291       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
68292       * // &lt;/mammals&gt;
68293       *
68294       * let xml;
68295       *
68296       * function preload() {
68297       *   xml = loadXML('assets/mammals.xml');
68298       * }
68299       *
68300       * function setup() {
68301       *   let firstChild = xml.getChild('animal');
68302       *   print(firstChild.getString('species'));
68303       *   firstChild.setAttribute('species', 'Jamides zebra');
68304       *   print(firstChild.getString('species'));
68305       * }
68306       *
68307       * // Sketch prints:
68308       * // "Capra hircus"
68309       * // "Jamides zebra"
68310       * </code></div>
68311       */
68312
68313
68314      p5.XML.prototype.setAttribute = function (name, value) {
68315        this.DOM.setAttribute(name, value);
68316      };
68317      /**
68318       * Returns the content of an element. If there is no such content,
68319       * defaultValue is returned if specified, otherwise null is returned.
68320       *
68321       * @method getContent
68322       * @param {String} [defaultValue] value returned if no content is found
68323       * @return {String}
68324       * @example
68325       * <div class='norender'><code>
68326       * // The following short XML file called "mammals.xml" is parsed
68327       * // in the code below.
68328       * //
68329       * // <?xml version="1.0"?>
68330       * // &lt;mammals&gt;
68331       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
68332       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
68333       * //   &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
68334       * // &lt;/mammals&gt;
68335       *
68336       * let xml;
68337       *
68338       * function preload() {
68339       *   xml = loadXML('assets/mammals.xml');
68340       * }
68341       *
68342       * function setup() {
68343       *   let firstChild = xml.getChild('animal');
68344       *   print(firstChild.getContent());
68345       * }
68346       *
68347       * // Sketch prints:
68348       * // "Goat"
68349       * </code></div>
68350       */
68351
68352
68353      p5.XML.prototype.getContent = function (defaultValue) {
68354        var str;
68355        str = this.DOM.textContent;
68356        str = str.replace(/\s\s+/g, ',');
68357        return str || defaultValue || null;
68358      };
68359      /**
68360       * Sets the element's content.
68361       *
68362       * @method setContent
68363       * @param {String} text the new content
68364       * @example
68365       * <div class='norender'><code>
68366       * // The following short XML file called "mammals.xml" is parsed
68367       * // in the code below.
68368       * //
68369       * // <?xml version="1.0"?>
68370       * // &lt;mammals&gt;
68371       * //   &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
68372       * //   &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
68373       * //   &lt;animal id="2" species="Equus zebra">
68373Zebra&lt;/animal&gt;
68374       * // &lt;/mammals&gt;
68375       *
68376       * let xml;
68377       *
68378       * function preload() {
68379       *   xml = loadXML('assets/mammals.xml');
68380       * }
68381       *
68382       * function setup() {
68383       *   let firstChild = xml.getChild('animal');
68384       *   print(firstChild.getContent());
68385       *   firstChild.setContent('Mountain Goat');
68386       *   print(firstChild.getContent());
68387       * }
68388       *
68389       * // Sketch prints:
68390       * // "Goat"
68391       * // "Mountain Goat"
68392       * </code></div>
68393       */
68394
68395
68396      p5.XML.prototype.setContent = function (content) {
68397        if (!this.DOM.children.length) {
68398          this.DOM.textContent = content;
68399        }
68400      };
68401      /**
68402       * Serializes the element into a string. This function is useful for preparing
68403       * the content to be sent over a http request or saved to file.
68404       *
68405       * @method serialize
68406       * @return {String} Serialized string of the element
68407       * @example
68408       * <div class='norender'><code>
68409       * let xml;
68410       *
68411       * function preload() {
68412       *   xml = loadXML('assets/mammals.xml');
68413       * }
68414       *
68415       * function setup() {
68416       *   print(xml.serialize());
68417       * }
68418       *
68419       * // Sketch prints:
68420       * // <mammals>
68421       * //   <animal id="0" species="Capra hircus">Goat</animal>
68422       * //   <animal id="1" species="Panthera pardus">Leopard</animal>
68423       * //   <animal id="2" species="Equus zebra">Zebra</animal>
68424       * // </mammals>
68425       * </code></div>
68426       */
68427
68428
68429      p5.XML.prototype.serialize = function () {
68430        var xmlSerializer = new XMLSerializer();
68431        return xmlSerializer.serializeToString(this.DOM);
68432      };
68433
68434      module.exports = p5;
68435    }, {
68436      "../core/main": 24
68437    }],
68438    51: [function (_dereq_, module, exports) {
68439      /**
68440       * @module Math
68441       * @submodule Calculation
68442       * @for p5
68443       * @requires core
68444       */
68445      'use strict';
68446
68447      var p5 = _dereq_('../core/main');
68448      /**
68449       * Calculates the absolute value (magnitude) of a number. Maps to Math.abs().
68450       * The absolute value of a number is always positive.
68451       *
68452       * @method abs
68453       * @param  {Number} n number to compute
68454       * @return {Number}   absolute value of given number
68455       * @example
68456       * <div class = "norender"><code>
68457       * function setup() {
68458       *   let x = -3;
68459       *   let y = abs(x);
68460       *
68461       *   print(x); // -3
68462       *   print(y); // 3
68463       * }
68464       * </code></div>
68465       *
68466       * @alt
68467       * no image displayed
68468       *
68469       */
68470
68471
68472      p5.prototype.abs = Math.abs;
68473      /**
68474       * Calculates the closest int value that is greater than or equal to the
68475       * value of the parameter. Maps to Math.ceil(). For example, ceil(9.03)
68476       * returns the value 10.
68477       *
68478       * @method ceil
68479       * @param  {Number} n number to round up
68480       * @return {Integer}   rounded up number
68481       * @example
68482       * <div><code>
68483       * function draw() {
68484       *   background(200);
68485       *   // map, mouseX between 0 and 5.
68486       *   let ax = map(mouseX, 0, 100, 0, 5);
68487       *   let ay = 66;
68488       *
68489       *   //Get the ceiling of the mapped number.
68490       *   let bx = ceil(map(mouseX, 0, 100, 0, 5));
68491       *   let by = 33;
68492       *
68493       *   // Multiply the mapped numbers by 20 to more easily
68494       *   // see the changes.
68495       *   stroke(0);
68496       *   fill(0);
68497       *   line(0, ay, ax * 20, ay);
68498       *   line(0, by, bx * 20, by);
68499       *
68500       *   // Reformat the float returned by map and draw it.
68501       *   noStroke();
68502       *   text(nfc(ax, 2), ax, ay - 5);
68503       *   text(nfc(bx, 1), bx, by - 5);
68504       * }
68505       * </code></div>
68506       *
68507       * @alt
68508       * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals
68509       *
68510       */
68511
68512      p5.prototype.ceil = Math.ceil;
68513      /**
68514       * Constrains a value between a minimum and maximum value.
68515       *
68516       * @method constrain
68517       * @param  {Number} n    number to constrain
68518       * @param  {Number} low  minimum limit
68519       * @param  {Number} high maximum limit
68520       * @return {Number}      constrained number
68521       * @example
68522       * <div><code>
68523       * function draw() {
68524       *   background(200);
68525       *
68526       *   let leftWall = 25;
68527       *   let rightWall = 75;
68528       *
68529       *   // xm is just the mouseX, while
68530       *   // xc is the mouseX, but constrained
68531       *   // between the leftWall and rightWall!
68532       *   let xm = mouseX;
68533       *   let xc = constrain(mouseX, leftWall, rightWall);
68534       *
68535       *   // Draw the walls.
68536       *   stroke(150);
68537       *   line(leftWall, 0, leftWall, height);
68538       *   line(rightWall, 0, rightWall, height);
68539       *
68540       *   // Draw xm and xc as circles.
68541       *   noStroke();
68542       *   fill(150);
68543       *   ellipse(xm, 33, 9, 9); // Not Constrained
68544       *   fill(0);
68545       *   ellipse(xc, 66, 9, 9); // Constrained
68546       * }
68547       * </code></div>
68548       *
68549       * @alt
68550       * 2 vertical lines. 2 ellipses move with mouse X 1 does not move passed lines
68551       *
68552       */
68553
68554      p5.prototype.constrain = function (n, low, high) {
68555        p5._validateParameters('constrain', arguments);
68556
68557        return Math.max(Math.min(n, high), low);
68558      };
68559      /**
68560       * Calculates the distance between two points.
68561       *
68562       * @method dist
68563       * @param  {Number} x1 x-coordinate of the first point
68564       * @param  {Number} y1 y-coordinate of the first point
68565       * @param  {Number} x2 x-coordinate of the second point
68566       * @param  {Number} y2 y-coordinate of the second point
68567       * @return {Number}    distance between the two points
68568       *
68569       * @example
68570       * <div><code>
68571       * // Move your mouse inside the canvas to see the
68572       * // change in distance between two points!
68573       * function draw() {
68574       *   background(200);
68575       *   fill(0);
68576       *
68577       *   let x1 = 10;
68578       *   let y1 = 90;
68579       *   let x2 = mouseX;
68580       *   let y2 = mouseY;
68581       *
68582       *   line(x1, y1, x2, y2);
68583       *   ellipse(x1, y1, 7, 7);
68584       *   ellipse(x2, y2, 7, 7);
68585       *
68586       *   // d is the length of the line
68587       *   // the distance from point 1 to point 2.
68588       *   let d = int(dist(x1, y1, x2, y2));
68589       *
68590       *   // Let's write d along the line we are drawing!
68591       *   push();
68592       *   translate((x1 + x2) / 2, (y1 + y2) / 2);
68593       *   rotate(atan2(y2 - y1, x2 - x1));
68594       *   text(nfc(d, 1), 0, -5);
68595       *   pop();
68596       *   // Fancy!
68597       * }
68598       * </code></div>
68599       *
68600       * @alt
68601       * 2 ellipses joined by line. 1 ellipse moves with mouse X&Y. Distance displayed.
68602       */
68603
68604      /**
68605       * @method dist
68606       * @param  {Number} x1
68607       * @param  {Number} y1
68608       * @param  {Number} z1 z-coordinate of the first point
68609       * @param  {Number} x2
68610       * @param  {Number} y2
68611       * @param  {Number} z2 z-coordinate of the second point
68612       * @return {Number}    distance between the two points
68613       */
68614
68615
68616      p5.prototype.dist = function () {
68617        p5._validateParameters('dist', arguments);
68618
68619        if (arguments.length === 4) {
68620          //2D
68621          return hypot(arguments[2] - arguments[0], arguments[3] - arguments[1]);
68622        } else if (arguments.length === 6) {
68623          //3D
68624          return hypot(arguments[3] - arguments[0], arguments[4] - arguments[1], arguments[5] - arguments[2]);
68625        }
68626      };
68627      /**
68628       * Returns Euler's number e (2.71828...) raised to the power of the n
68629       * parameter. Maps to Math.exp().
68630       *
68631       * @method exp
68632       * @param  {Number} n exponent to raise
68633       * @return {Number}   e^n
68634       * @example
68635       * <div><code>
68636       * function draw() {
68637       *   background(200);
68638       *
68639       *   // Compute the exp() function with a value between 0 and 2
68640       *   let xValue = map(mouseX, 0, width, 0, 2);
68641       *   let yValue = exp(xValue);
68642       *
68643       *   let y = map(yValue, 0, 8, height, 0);
68644       *
68645       *   let legend = 'exp (' + nfc(xValue, 3) + ')\n= ' + nf(yValue, 1, 4);
68646       *   stroke(150);
68647       *   line(mouseX, y, mouseX, height);
68648       *   fill(0);
68649       *   text(legend, 5, 15);
68650       *   noStroke();
68651       *   ellipse(mouseX, y, 7, 7);
68652       *
68653       *   // Draw the exp(x) curve,
68654       *   // over the domain of x from 0 to 2
68655       *   noFill();
68656       *   stroke(0);
68657       *   beginShape();
68658       *   for (let x = 0; x < width; x++) {
68659       *     xValue = map(x, 0, width, 0, 2);
68660       *     yValue = exp(xValue);
68661       *     y = map(yValue, 0, 8, height, 0);
68662       *     vertex(x, y);
68663       *   }
68664       *
68665       *   endShape();
68666       *   line(0, 0, 0, height);
68667       *   line(0, height - 1, width, height - 1);
68668       * }
68669       * </code></div>
68670       *
68671       * @alt
68672       * ellipse moves along a curve with mouse x. e^n displayed.
68673       *
68674       */
68675
68676
68677      p5.prototype.exp = Math.exp;
68678      /**
68679       * Calculates the closest int value that is less than or equal to the
68680       * value of the parameter. Maps to Math.floor().
68681       *
68682       * @method floor
68683       * @param  {Number} n number to round down
68684       * @return {Integer}  rounded down number
68685       * @example
68686       * <div><code>
68687       * function draw() {
68688       *   background(200);
68689       *   //map, mouseX between 0 and 5.
68690       *   let ax = map(mouseX, 0, 100, 0, 5);
68691       *   let ay = 66;
68692       *
68693       *   //Get the floor of the mapped number.
68694       *   let bx = floor(map(mouseX, 0, 100, 0, 5));
68695       *   let by = 33;
68696       *
68697       *   // Multiply the mapped numbers by 20 to more easily
68698       *   // see the changes.
68699       *   stroke(0);
68700       *   fill(0);
68701       *   line(0, ay, ax * 20, ay);
68702       *   line(0, by, bx * 20, by);
68703       *
68704       *   // Reformat the float returned by map and draw it.
68705       *   noStroke();
68706       *   text(nfc(ax, 2), ax, ay - 5);
68707       *   text(nfc(bx, 1), bx, by - 5);
68708       * }
68709       * </code></div>
68710       *
68711       * @alt
68712       * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals
68713       *
68714       */
68715
68716      p5.prototype.floor = Math.floor;
68717      /**
68718       * Calculates a number between two numbers at a specific increment. The amt
68719       * parameter is the amount to interpolate between the two values where 0.0
68720       * equal to the first point, 0.1 is very near the first point, 0.5 is
68721       * half-way in between, and 1.0 is equal to the second point. If the
68722       * value of amt is more than 1.0 or less than 0.0, the number will be
68723       * calculated accordingly in the ratio of the two given numbers. The lerp
68724       * function is convenient for creating motion along a straight
68725       * path and for drawing dotted lines.
68726       *
68727       * @method lerp
68728       * @param  {Number} start first value
68729       * @param  {Number} stop  second value
68730       * @param  {Number} amt   number
68731       * @return {Number}       lerped value
68732       * @example
68733       * <div><code>
68734       * function setup() {
68735       *   background(200);
68736       *   let a = 20;
68737       *   let b = 80;
68738       *   let c = lerp(a, b, 0.2);
68739       *   let d = lerp(a, b, 0.5);
68740       *   let e = lerp(a, b, 0.8);
68741       *
68742       *   let y = 50;
68743       *
68744       *   strokeWeight(5);
68745       *   stroke(0); // Draw the original points in black
68746       *   point(a, y);
68747       *   point(b, y);
68748       *
68749       *   stroke(100); // Draw the lerp points in gray
68750       *   point(c, y);
68751       *   point(d, y);
68752       *   point(e, y);
68753       * }
68754       * </code></div>
68755       *
68756       * @alt
68757       * 5 points horizontally staggered mid-canvas. mid 3 are grey, outer black
68758       *
68759       */
68760
68761      p5.prototype.lerp = function (start, stop, amt) {
68762        p5._validateParameters('lerp', arguments);
68763
68764        return amt * (stop - start) + start;
68765      };
68766      /**
68767       * Calculates the natural logarithm (the base-e logarithm) of a number. This
68768       * function expects the n parameter to be a value greater than 0.0. Maps to
68769       * Math.log().
68770       *
68771       * @method log
68772       * @param  {Number} n number greater than 0
68773       * @return {Number}   natural logarithm of n
68774       * @example
68775       * <div><code>
68776       * function draw() {
68777       *   background(200);
68778       *   let maxX = 2.8;
68779       *   let maxY = 1.5;
68780       *
68781       *   // Compute the natural log of a value between 0 and maxX
68782       *   let xValue = map(mouseX, 0, width, 0, maxX);
68783       *   let yValue, y;
68784       *   if (xValue > 0) {
68785          // Cannot take the log of a negative number.
68786       *     yValue = log(xValue);
68787       *     y = map(yValue, -maxY, maxY, height, 0);
68788       *
68789       *     // Display the calculation occurring.
68790       *     let legend = 'log(' + nf(xValue, 1, 2) + ')\n= ' + nf(yValue, 1, 3);
68791       *     stroke(150);
68792       *     line(mouseX, y, mouseX, height);
68793       *     fill(0);
68794       *     text(legend, 5, 15);
68795       *     noStroke();
68796       *     ellipse(mouseX, y, 7, 7);
68797       *   }
68798       *
68799       *   // Draw the log(x) curve,
68800       *   // over the domain of x from 0 to maxX
68801       *   noFill();
68802       *   stroke(0);
68803       *   beginShape();
68804       *   for (let x = 0; x < width; x++) {
68805       *     xValue = map(x, 0, width, 0, maxX);
68806       *     yValue = log(xValue);
68807       *     y = map(yValue, -maxY, maxY, height, 0);
68808       *     vertex(x, y);
68809       *   }
68810       *   endShape();
68811       *   line(0, 0, 0, height);
68812       *   line(0, height / 2, width, height / 2);
68813       * }
68814       * </code></div>
68815       *
68816       * @alt
68817       * ellipse moves along a curve with mouse x. natural logarithm of n displayed.
68818       *
68819       */
68820
68821
68822      p5.prototype.log = Math.log;
68823      /**
68824       * Calculates the magnitude (or length) of a vector. A vector is a direction
68825       * in space commonly used in computer graphics and linear algebra. Because it
68826       * has no "start" position, the magnitude of a vector can be thought of as
68827       * the distance from the coordinate 0,0 to its x,y value. Therefore, <a href="#/p5/mag">mag()</a> is
68828       * a shortcut for writing dist(0, 0, x, y).
68829       *
68830       * @method mag
68831       * @param  {Number} a first value
68832       * @param  {Number} b second value
68833       * @return {Number}   magnitude of vector from (0,0) to (a,b)
68834       * @example
68835       * <div><code>
68836       * function setup() {
68837       *   let x1 = 20;
68838       *   let x2 = 80;
68839       *   let y1 = 30;
68840       *   let y2 = 70;
68841       *
68842       *   line(0, 0, x1, y1);
68843       *   print(mag(x1, y1)); // Prints "36.05551275463989"
68844       *   line(0, 0, x2, y1);
68845       *   print(mag(x2, y1)); // Prints "85.44003745317531"
68846       *   line(0, 0, x1, y2);
68847       *   print(mag(x1, y2)); // Prints "72.80109889280519"
68848       *   line(0, 0, x2, y2);
68849       *   print(mag(x2, y2)); // Prints "106.3014581273465"
68850       * }
68851       * </code></div>
68852       *
68853       * @alt
68854       * 4 lines of different length radiate from top left of canvas.
68855       *
68856       */
68857
68858      p5.prototype.mag = function (x, y) {
68859        p5._validateParameters('mag', arguments);
68860
68861        return hypot(x, y);
68862      };
68863      /**
68864       * Re-maps a number from one range to another.
68865       * <br><br>
68866       * In the first example above, the number 25 is converted from a value in the
68867       * range of 0 to 100 into a value that ranges from the left edge of the
68868       * window (0) to the right edge (width).
68869       *
68870       * @method map
68871       * @param  {Number} value  the incoming value to be converted
68872       * @param  {Number} start1 lower bound of the value's current range
68873       * @param  {Number} stop1  upper bound of the value's current range
68874       * @param  {Number} start2 lower bound of the value's target range
68875       * @param  {Number} stop2  upper bound of the value's target range
68876       * @param  {Boolean} [withinBounds] constrain the value to the newly mapped range
68877       * @return {Number}        remapped number
68878       * @example
68879       *   <div><code>
68880       * let value = 25;
68881       * let m = map(value, 0, 100, 0, width);
68882       * ellipse(m, 50, 10, 10);
68883      </code></div>
68884       *
68885       *   <div><code>
68886       * function setup() {
68887       *   noStroke();
68888       * }
68889       *
68890       * function draw() {
68891       *   background(204);
68892       *   let x1 = map(mouseX, 0, width, 25, 75);
68893       *   ellipse(x1, 25, 25, 25);
68894       *   //This ellipse is constrained to the 0-100 range
68895       *   //after setting withinBounds to true
68896       *   let x2 = map(mouseX, 0, width, 0, 100, true);
68897       *   ellipse(x2, 75, 25, 25);
68898       * }
68899      </code></div>
68900       *
68901       * @alt
68902       * 10 by 10 white ellipse with in mid left canvas
68903       * 2 25 by 25 white ellipses move with mouse x. Bottom has more range from X
68904       *
68905       */
68906
68907
68908      p5.prototype.map = function (n, start1, stop1, start2, stop2, withinBounds) {
68909        p5._validateParameters('map', arguments);
68910
68911        var newval = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2;
68912
68913        if (!withinBounds) {
68914          return newval;
68915        }
68916
68917        if (start2 < stop2) {
68918          return this.constrain(newval, start2, stop2);
68919        } else {
68920          return this.constrain(newval, stop2, start2);
68921        }
68922      };
68923      /**
68924       * Determines the largest value in a sequence of numbers, and then returns
68925       * that value. <a href="#/p5/max">max()</a> accepts any number of Number parameters, or an Array
68926       * of any length.
68927       *
68928       * @method max
68929       * @param  {Number} n0 Number to compare
68930       * @param  {Number} n1 Number to compare
68931       * @return {Number}             maximum Number
68932       * @example
68933       * <div><code>
68934       * function setup() {
68935       *   // Change the elements in the array and run the sketch
68936       *   // to show how max() works!
68937       *   let numArray = [2, 1, 5, 4, 8, 9];
68938       *   fill(0);
68939       *   noStroke();
68940       *   text('Array Elements', 0, 10);
68941       *   // Draw all numbers in the array
68942       *   let spacing = 15;
68943       *   let elemsY = 25;
68944       *   for (let i = 0; i < numArray.length; i++) {
68945       *     text(numArray[i], i * spacing, elemsY);
68946       *   }
68947       *   let maxX = 33;
68948       *   let maxY = 80;
68949       *   // Draw the Maximum value in the array.
68950       *   textSize(32);
68951       *   text(max(numArray), maxX, maxY);
68952       * }
68953       * </code></div>
68954       *
68955       * @alt
68956       * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 9
68957       *
68958       */
68959
68960      /**
68961       * @method max
68962       * @param  {Number[]} nums Numbers to compare
68963       * @return {Number}
68964       */
68965
68966
68967      p5.prototype.max = function () {
68968        p5._validateParameters('max', arguments);
68969
68970        if (arguments[0] instanceof Array) {
68971          return Math.max.apply(null, arguments[0]);
68972        } else {
68973          return Math.max.apply(null, arguments);
68974        }
68975      };
68976      /**
68977       * Determines the smallest value in a sequence of numbers, and then returns
68978       * that value. <a href="#/p5/min">min()</a> accepts any number of Number parameters, or an Array
68979       * of any length.
68980       *
68981       * @method min
68982       * @param  {Number} n0 Number to compare
68983       * @param  {Number} n1 Number to compare
68984       * @return {Number}             minimum Number
68985       * @example
68986       * <div><code>
68987       * function setup() {
68988       *   // Change the elements in the array and run the sketch
68989       *   // to show how min() works!
68990       *   let numArray = [2, 1, 5, 4, 8, 9];
68991       *   fill(0);
68992       *   noStroke();
68993       *   text('Array Elements', 0, 10);
68994       *   // Draw all numbers in the array
68995       *   let spacing = 15;
68996       *   let elemsY = 25;
68997       *   for (let i = 0; i < numArray.length; i++) {
68998       *     text(numArray[i], i * spacing, elemsY);
68999       *   }
69000       *   let maxX = 33;
69001       *   let maxY = 80;
69002       *   // Draw the Minimum value in the array.
69003       *   textSize(32);
69004       *   text(min(numArray), maxX, maxY);
69005       * }
69006       * </code></div>
69007       *
69008       * @alt
69009       * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 1
69010       *
69011       */
69012
69013      /**
69014       * @method min
69015       * @param  {Number[]} nums Numbers to compare
69016       * @return {Number}
69017       */
69018
69019
69020      p5.prototype.min = function () {
69021        p5._validateParameters('min', arguments);
69022
69023        if (arguments[0] instanceof Array) {
69024          return Math.min.apply(null, arguments[0]);
69025        } else {
69026          return Math.min.apply(null, arguments);
69027        }
69028      };
69029      /**
69030       * Normalizes a number from another range into a value between 0 and 1.
69031       * Identical to map(value, low, high, 0, 1).
69032       * Numbers outside of the range are not clamped to 0 and 1, because
69033       * out-of-range values are often intentional and useful. (See the second
69034       * example above.)
69035       *
69036       * @method norm
69037       * @param  {Number} value incoming value to be normalized
69038       * @param  {Number} start lower bound of the value's current range
69039       * @param  {Number} stop  upper bound of the value's current range
69040       * @return {Number}       normalized number
69041       * @example
69042       * <div><code>
69043       * function draw() {
69044       *   background(200);
69045       *   let currentNum = mouseX;
69046       *   let lowerBound = 0;
69047       *   let upperBound = width; //100;
69048       *   let normalized = norm(currentNum, lowerBound, upperBound);
69049       *   let lineY = 70;
69050       *   line(0, lineY, width, lineY);
69051       *   //Draw an ellipse mapped to the non-normalized value.
69052       *   noStroke();
69053       *   fill(50);
69054       *   let s = 7; // ellipse size
69055       *   ellipse(currentNum, lineY, s, s);
69056       *
69057       *   // Draw the guide
69058       *   let guideY = lineY + 15;
69059       *   text('0', 0, guideY);
69060       *   textAlign(RIGHT);
69061       *   text('100', width, guideY);
69062       *
69063       *   // Draw the normalized value
69064       *   textAlign(LEFT);
69065       *   fill(0);
69066       *   textSize(32);
69067       *   let normalY = 40;
69068       *   let normalX = 20;
69069       *   text(normalized, normalX, normalY);
69070       * }
69071       * </code></div>
69072       *
69073       * @alt
69074       * ellipse moves with mouse. 0 shown left & 100 right and updating values center
69075       *
69076       */
69077
69078
69079      p5.prototype.norm = function (n, start, stop) {
69080        p5._validateParameters('norm', arguments);
69081
69082        return this.map(n, start, stop, 0, 1);
69083      };
69084      /**
69085       * Facilitates exponential expressions. The <a href="#/p5/pow">pow()</a>
69085 function is an efficient
69086       * way of multiplying numbers by themselves (or their reciprocals) in large
69087       * quantities. For example, pow(3, 5) is equivalent to the expression
69088       * 3*3*3*3*3 and pow(3, -5) is equivalent to 1 / 3*3*3*3*3. Maps to
69089       * Math.pow().
69090       *
69091       * @method pow
69092       * @param  {Number} n base of the exponential expression
69093       * @param  {Number} e power by which to raise the base
69094       * @return {Number}   n^e
69095       * @example
69096       * <div><code>
69097       * function setup() {
69098       *   //Exponentially increase the size of an ellipse.
69099       *   let eSize = 3; // Original Size
69100       *   let eLoc = 10; // Original Location
69101       *
69102       *   ellipse(eLoc, eLoc, eSize, eSize);
69103       *
69104       *   ellipse(eLoc * 2, eLoc * 2, pow(eSize, 2), pow(eSize, 2));
69105       *
69106       *   ellipse(eLoc * 4, eLoc * 4, pow(eSize, 3), pow(eSize, 3));
69107       *
69108       *   ellipse(eLoc * 8, eLoc * 8, pow(eSize, 4), pow(eSize, 4));
69109       * }
69110       * </code></div>
69111       *
69112       * @alt
69113       * small to large ellipses radiating from top left of canvas
69114       *
69115       */
69116
69117
69118      p5.prototype.pow = Math.pow;
69119      /**
69120       * Calculates the integer closest to the n parameter. For example,
69121       * round(133.8) returns the value 134. Maps to Math.round().
69122       *
69123       * @method round
69124       * @param  {Number} n number to round
69125       * @return {Integer}  rounded number
69126       * @example
69127       * <div><code>
69128       * function draw() {
69129       *   background(200);
69130       *   //map, mouseX between 0 and 5.
69131       *   let ax = map(mouseX, 0, 100, 0, 5);
69132       *   let ay = 66;
69133       *
69134       *   // Round the mapped number.
69135       *   let bx = round(map(mouseX, 0, 100, 0, 5));
69136       *   let by = 33;
69137       *
69138       *   // Multiply the mapped numbers by 20 to more easily
69139       *   // see the changes.
69140       *   stroke(0);
69141       *   fill(0);
69142       *   line(0, ay, ax * 20, ay);
69143       *   line(0, by, bx * 20, by);
69144       *
69145       *   // Reformat the float returned by map and draw it.
69146       *   noStroke();
69147       *   text(nfc(ax, 2), ax, ay - 5);
69148       *   text(nfc(bx, 1), bx, by - 5);
69149       * }
69150       * </code></div>
69151       *
69152       * @alt
69153       * horizontal center line squared values displayed on top and regular on bottom.
69154       *
69155       */
69156
69157      p5.prototype.round = Math.round;
69158      /**
69159       * Squares a number (multiplies a number by itself). The result is always a
69160       * positive number, as multiplying two negative numbers always yields a
69161       * positive result. For example, -1 * -1 = 1.
69162       *
69163       * @method sq
69164       * @param  {Number} n number to square
69165       * @return {Number}   squared number
69166       * @example
69167       * <div><code>
69168       * function draw() {
69169       *   background(200);
69170       *   let eSize = 7;
69171       *   let x1 = map(mouseX, 0, width, 0, 10);
69172       *   let y1 = 80;
69173       *   let x2 = sq(x1);
69174       *   let y2 = 20;
69175       *
69176       *   // Draw the non-squared.
69177       *   line(0, y1, width, y1);
69178       *   ellipse(x1, y1, eSize, eSize);
69179       *
69180       *   // Draw the squared.
69181       *   line(0, y2, width, y2);
69182       *   ellipse(x2, y2, eSize, eSize);
69183       *
69184       *   // Draw dividing line.
69185       *   stroke(100);
69186       *   line(0, height / 2, width, height / 2);
69187       *
69188       *   // Draw text.
69189       *   let spacing = 15;
69190       *   noStroke();
69191       *   fill(0);
69192       *   text('x = ' + x1, 0, y1 + spacing);
69193       *   text('sq(x) = ' + x2, 0, y2 + spacing);
69194       * }
69195       * </code></div>
69196       *
69197       * @alt
69198       * horizontal center line squared values displayed on top and regular on bottom.
69199       *
69200       */
69201
69202      p5.prototype.sq = function (n) {
69203        return n * n;
69204      };
69205      /**
69206       * Calculates the square root of a number. The square root of a number is
69207       * always positive, even though there may be a valid negative root. The
69208       * square root s of number a is such that s*s = a. It is the opposite of
69209       * squaring. Maps to Math.sqrt().
69210       *
69211       * @method sqrt
69212       * @param  {Number} n non-negative number to square root
69213       * @return {Number}   square root of number
69214       * @example
69215       * <div><code>
69216       * function draw() {
69217       *   background(200);
69218       *   let eSize = 7;
69219       *   let x1 = mouseX;
69220       *   let y1 = 80;
69221       *   let x2 = sqrt(x1);
69222       *   let y2 = 20;
69223       *
69224       *   // Draw the non-squared.
69225       *   line(0, y1, width, y1);
69226       *   ellipse(x1, y1, eSize, eSize);
69227       *
69228       *   // Draw the squared.
69229       *   line(0, y2, width, y2);
69230       *   ellipse(x2, y2, eSize, eSize);
69231       *
69232       *   // Draw dividing line.
69233       *   stroke(100);
69234       *   line(0, height / 2, width, height / 2);
69235       *
69236       *   // Draw text.
69237       *   noStroke();
69238       *   fill(0);
69239       *   let spacing = 15;
69240       *   text('x = ' + x1, 0, y1 + spacing);
69241       *   text('sqrt(x) = ' + x2, 0, y2 + spacing);
69242       * }
69243       * </code></div>
69244       *
69245       * @alt
69246       * horizontal center line squareroot values displayed on top and regular on bottom.
69247       *
69248       */
69249
69250
69251      p5.prototype.sqrt = Math.sqrt; // Calculate the length of the hypotenuse of a right triangle
69252      // This won't under- or overflow in intermediate steps
69253      // https://en.wikipedia.org/wiki/Hypot
69254
69255      function hypot(x, y, z) {
69256        // Use the native implementation if it's available
69257        if (typeof Math.hypot === 'function') {
69258          return Math.hypot.apply(null, arguments);
69259        } // Otherwise use the V8 implementation
69260        // https://github.com/v8/v8/blob/8cd3cf297287e581a49e487067f5cbd991b27123/src/js/math.js#L217
69261
69262
69263        var length = arguments.length;
69264        var args = [];
69265        var max = 0;
69266
69267        for (var i = 0; i < length; i++) {
69268          var n = arguments[i];
69269          n = +n;
69270
69271          if (n === Infinity || n === -Infinity) {
69272            return Infinity;
69273          }
69274
69275          n = Math.abs(n);
69276
69277          if (n > max) {
69278            max = n;
69279          }
69280
69281          args[i] = n;
69282        }
69283
69284        if (max === 0) {
69285          max = 1;
69286        }
69287
69288        var sum = 0;
69289        var compensation = 0;
69290
69291        for (var j = 0; j < length; j++) {
69292          var m = args[j] / max;
69293          var summand = m * m - compensation;
69294          var preliminary = sum + summand;
69295          compensation = preliminary - sum - summand;
69296          sum = preliminary;
69297        }
69298
69299        return Math.sqrt(sum) * max;
69300      }
69301
69302      module.exports = p5;
69303    }, {
69304      "../core/main": 24
69305    }],
69306    52: [function (_dereq_, module, exports) {
69307      /**
69308       * @module Math
69309       * @submodule Math
69310       * @for p5
69311       * @requires core
69312       */
69313      'use strict';
69314
69315      var p5 = _dereq_('../core/main');
69316      /**
69317       * Creates a new <a href="#/p5.Vector">p5.Vector</a> (the datatype for storing vectors). This provides a
69318       * two or three dimensional vector, specifically a Euclidean (also known as
69319       * geometric) vector. A vector is an entity that has both magnitude and
69320       * direction.
69321       *
69322       * @method createVector
69323       * @param {Number} [x] x component of the vector
69324       * @param {Number} [y] y component of the vector
69325       * @param {Number} [z] z component of the vector
69326       * @return {p5.Vector}
69327       * @example
69328       * <div modernizr='webgl'><code>
69329       * function setup() {
69330       *   createCanvas(100, 100, WEBGL);
69331       *   noStroke();
69332       *   fill(255, 102, 204);
69333       * }
69334       *
69335       * function draw() {
69336       *   background(255);
69337       *   pointLight(color(255), createVector(sin(millis() / 1000) * 20, -40, -10));
69338       *   scale(0.75);
69339       *   sphere();
69340       * }
69341       * </code></div>
69342       *
69343       * @alt
69344       * a purple sphere lit by a point light oscillating horizontally
69345       */
69346
69347
69348      p5.prototype.createVector = function (x, y, z) {
69349        if (this instanceof p5) {
69350          return new p5.Vector(this, arguments);
69351        } else {
69352          return new p5.Vector(x, y, z);
69353        }
69354      };
69355
69356      module.exports = p5;
69357    }, {
69358      "../core/main": 24
69359    }],
69360    53: [function (_dereq_, module, exports) {
69361      //////////////////////////////////////////////////////////////
69362      // http://mrl.nyu.edu/~perlin/noise/
69363      // Adapting from PApplet.java
69364      // which was adapted from toxi
69365      // which was adapted from the german demo group farbrausch
69366      // as used in their demo "art": http://www.farb-rausch.de/fr010src.zip
69367      // someday we might consider using "improved noise"
69368      // http://mrl.nyu.edu/~perlin/paper445.pdf
69369      // See: https://github.com/shiffman/The-Nature-of-Code-Examples-p5.js/
69370      //      blob/master/introduction/Noise1D/noise.js
69371
69372      /**
69373       * @module Math
69374       * @submodule Noise
69375       * @for p5
69376       * @requires core
69377       */
69378      'use strict';
69379
69380      var p5 = _dereq_('../core/main');
69381
69382      var PERLIN_YWRAPB = 4;
69383      var PERLIN_YWRAP = 1 << PERLIN_YWRAPB;
69384      var PERLIN_ZWRAPB = 8;
69385      var PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB;
69386      var PERLIN_SIZE = 4095;
69387      var perlin_octaves = 4; // default to medium smooth
69388
69389      var perlin_amp_falloff = 0.5; // 50% reduction/octave
69390
69391      var scaled_cosine = function (i) {
69392        return 0.5 * (1.0 - Math.cos(i * Math.PI));
69393      };
69394
69395      var perlin; // will be initialized lazily by noise() or noiseSeed()
69396
69397      /**
69398       * Returns the Perlin noise value at specified coordinates. Perlin noise is
69399       * a random sequence generator producing a more natural ordered, harmonic
69400       * succession of numbers compared to the standard <b>random()</b> function.
69401       * It was invented by Ken Perlin in the 1980s and been used since in
69402       * graphical applications to produce procedural textures, natural motion,
69403       * shapes, terrains etc.<br /><br /> The main difference to the
69404       * <b>random()</b> function is that Perlin noise is defined in an infinite
69405       * n-dimensional space where each pair of coordinates corresponds to a
69406       * fixed semi-random value (fixed only for the lifespan of the program; see
69407       * the <a href="#/p5/noiseSeed">noiseSeed()</a> function). p5.js can compute 1D, 2D and 3D noise,
69408       * depending on the number of coordinates given. The resulting value will
69409       * always be between 0.0 and 1.0. The noise value can be animated by moving
69410       * through the noise space as demonstrated in the example above. The 2nd
69411       * and 3rd dimension can also be interpreted as time.<br /><br />The actual
69412       * noise is structured similar to an audio signal, in respect to the
69413       * function's use of frequencies. Similar to the concept of harmonics in
69414       * physics, perlin noise is computed over several octaves which are added
69415       * together for the final result. <br /><br />Another way to adjust the
69416       * character of the resulting sequence is the scale of the input
69417       * coordinates. As the function works within an infinite space the value of
69418       * the coordinates doesn't matter as such, only the distance between
69419       * successive coordinates does (eg. when using <b>noise()</b> within a
69420       * loop). As a general rule the smaller the difference between coordinates,
69421       * the smoother the resulting noise sequence will be. Steps of 0.005-0.03
69422       * work best for most applications, but this will differ depending on use.
69423       *
69424       *
69425       * @method noise
69426       * @param  {Number} x   x-coordinate in noise space
69427       * @param  {Number} [y] y-coordinate in noise space
69428       * @param  {Number} [z] z-coordinate in noise space
69429       * @return {Number}     Perlin noise value (between 0 and 1) at specified
69430       *                      coordinates
69431       * @example
69432       * <div>
69433       * <code>
69434       * let xoff = 0.0;
69435       *
69436       * function draw() {
69437       *   background(204);
69438       *   xoff = xoff + 0.01;
69439       *   let n = noise(xoff) * width;
69440       *   line(n, 0, n, height);
69441       * }
69442       * </code>
69443       * </div>
69444       * <div>
69445       * <code>let noiseScale=0.02;
69446       *
69447       * function draw() {
69448       *   background(0);
69449       *   for (let x=0; x < width; x++) {
69450       *     let noiseVal = noise((mouseX+x)*noiseScale, mouseY*noiseScale);
69451       *     stroke(noiseVal*255);
69452       *     line(x, mouseY+noiseVal*80, x, height);
69453       *   }
69454       * }
69455       * </code>
69456       * </div>
69457       *
69458       * @alt
69459       * vertical line moves left to right with updating noise values.
69460       * horizontal wave pattern effected by mouse x-position & updating noise values.
69461       *
69462       */
69463
69464      p5.prototype.noise = function (x, y, z) {
69465        y = y || 0;
69466        z = z || 0;
69467
69468        if (perlin == null) {
69469          perlin = new Array(PERLIN_SIZE + 1);
69470
69471          for (var i = 0; i < PERLIN_SIZE + 1; i++) {
69472            perlin[i] = Math.random();
69473          }
69474        }
69475
69476        if (x < 0) {
69477          x = -x;
69478        }
69479
69480        if (y < 0) {
69481          y = -y;
69482        }
69483
69484        if (z < 0) {
69485          z = -z;
69486        }
69487
69488        var xi = Math.floor(x),
69489            yi = Math.floor(y),
69490            zi = Math.floor(z);
69491        var xf = x - xi;
69492        var yf = y - yi;
69493        var zf = z - zi;
69494        var rxf, ryf;
69495        var r = 0;
69496        var ampl = 0.5;
69497        var n1, n2, n3;
69498
69499        for (var o = 0; o < perlin_octaves; o++) {
69500          var of = xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB);
69501          rxf = scaled_cosine(xf);
69502          ryf = scaled_cosine(yf);
69503          n1 = perlin[of & PERLIN_SIZE];
69504          n1 += rxf * (perlin[of + 1 & PERLIN_SIZE] - n1);
69505          n2 = perlin[of + PERLIN_YWRAP & PERLIN_SIZE];
69506          n2 += rxf * (perlin[of + PERLIN_YWRAP + 1 & PERLIN_SIZE] - n2);
69507          n1 += ryf * (n2 - n1);
69508          of += PERLIN_ZWRAP;
69509          n2 = perlin[of & PERLIN_SIZE];
69510          n2 += rxf * (perlin[of + 1 & PERLIN_SIZE] - n2);
69511          n3 = perlin[of + PERLIN_YWRAP & PERLIN_SIZE];
69512          n3 += rxf * (perlin[of + PERLIN_YWRAP + 1 & PERLIN_SIZE] - n3);
69513          n2 += ryf * (n3 - n2);
69514          n1 += scaled_cosine(zf) * (n2 - n1);
69515          r += n1 * ampl;
69516          ampl *= perlin_amp_falloff;
69517          xi <<= 1;
69518          xf *= 2;
69519          yi <<= 1;
69520          yf *= 2;
69521          zi <<= 1;
69522          zf *= 2;
69523
69524          if (xf >= 1.0) {
69525            xi++;
69526            xf--;
69527          }
69528
69529          if (yf >= 1.0) {
69530            yi++;
69531            yf--;
69532          }
69533
69534          if (zf >= 1.0) {
69535            zi++;
69536            zf--;
69537          }
69538        }
69539
69540        return r;
69541      };
69542      /**
69543       *
69544       * Adjusts the character and level of detail produced by the Perlin noise
69545       * function. Similar to harmonics in physics, noise is computed over
69546       * several octaves. Lower octaves contribute more to the output signal and
69547       * as such define the overall intensity of the noise, whereas higher octaves
69548       * create finer grained details in the noise sequence.
69549       * <br><br>
69550       * By default, noise is computed over 4 octaves with each octave contributing
69551       * exactly half than its predecessor, starting at 50% strength for the 1st
69552       * octave. This falloff amount can be changed by adding an additional function
69553       * parameter. Eg. a falloff factor of 0.75 means each octave will now have
69554       * 75% impact (25% less) of the previous lower octave. Any value between
69555       * 0.0 and 1.0 is valid, however note that values greater than 0.5 might
69556       * result in greater than 1.0 values returned by <b>noise()</b>.
69557       * <br><br>
69558       * By changing these parameters, the signal created by the <b>noise()</b>
69559       * function can be adapted to fit very specific needs and characteristics.
69560       *
69561       * @method noiseDetail
69562       * @param {Number} lod number of octaves to be used by the noise
69563       * @param {Number} falloff falloff factor for each octave
69564       * @example
69565       * <div>
69566       * <code>
69567       * let noiseVal;
69568       * let noiseScale = 0.02;
69569       *
69570       * function setup() {
69571       *   createCanvas(100, 100);
69572       * }
69573       *
69574       * function draw() {
69575       *   background(0);
69576       *   for (let y = 0; y < height; y++) {
69577       *     for (let x = 0; x < width / 2; x++) {
69578       *       noiseDetail(2, 0.2);
69579       *       noiseVal = noise((mouseX + x) * noiseScale, (mouseY + y) * noiseScale);
69580       *       stroke(noiseVal * 255);
69581       *       point(x, y);
69582       *       noiseDetail(8, 0.65);
69583       *       noiseVal = noise(
69584       *         (mouseX + x + width / 2) * noiseScale,
69585       *         (mouseY + y) * noiseScale
69586       *       );
69587       *       stroke(noiseVal * 255);
69588       *       point(x + width / 2, y);
69589       *     }
69590       *   }
69591       * }
69592       * </code>
69593       * </div>
69594       *
69595       * @alt
69596       * 2 vertical grey smokey patterns affected my mouse x-position and noise.
69597       *
69598       */
69599
69600
69601      p5.prototype.noiseDetail = function (lod, falloff) {
69602        if (lod > 0) {
69603          perlin_octaves = lod;
69604        }
69605
69606        if (falloff > 0) {
69607          perlin_amp_falloff = falloff;
69608        }
69609      };
69610      /**
69611       * Sets the seed value for <b>noise()</b>. By default, <b>noise()</b>
69612       * produces different results each time the program is run. Set the
69613       * <b>value</b> parameter to a constant to return the same pseudo-random
69614       * numbers each time the software is run.
69615       *
69616       * @method noiseSeed
69617       * @param {Number} seed   the seed value
69618       * @example
69619       * <div>
69620       * <code>let xoff = 0.0;
69621       *
69622       * function setup() {
69623       *   noiseSeed(99);
69624       *   stroke(0, 10);
69625       * }
69626       *
69627       * function draw() {
69628       *   xoff = xoff + .01;
69629       *   let n = noise(xoff) * width;
69630       *   line(n, 0, n, height);
69631       * }
69632       * </code>
69633       * </div>
69634       *
69635       * @alt
69636       * vertical grey lines drawing in pattern affected by noise.
69637       *
69638       */
69639
69640
69641      p5.prototype.noiseSeed = function (seed) {
69642        // Linear Congruential Generator
69643        // Variant of a Lehman Generator
69644        var lcg = function () {
69645          // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes
69646          // m is basically chosen to be large (as it is the max period)
69647          // and for its relationships to a and c
69648          var m = 4294967296; // a - 1 should be divisible by m's prime factors
69649
69650          var a = 1664525; // c and m should be co-prime
69651
69652          var c = 1013904223;
69653          var seed, z;
69654          return {
69655            setSeed: function (val) {
69656              // pick a random seed if val is undefined or null
69657              // the >>> 0 casts the seed to an unsigned 32-bit integer
69658              z = seed = (val == null ? Math.random() * m : val) >>> 0;
69659            },
69660            getSeed: function () {
69661              return seed;
69662            },
69663            rand: function () {
69664              // define the recurrence relationship
69665              z = (a * z + c) % m; // return a float in [0, 1)
69666              // if z = m then z / m = 0 therefore (z % m) / m < 1 always
69667
69668              return z / m;
69669            }
69670          };
69671        }();
69672
69673        lcg.setSeed(seed);
69674        perlin = new Array(PERLIN_SIZE + 1);
69675
69676        for (var i = 0; i < PERLIN_SIZE + 1; i++) {
69677          perlin[i] = lcg.rand();
69678        }
69679      };
69680
69681      module.exports = p5;
69682    }, {
69683      "../core/main": 24
69684    }],
69685    54: [function (_dereq_, module, exports) {
69686      /**
69687       * @module Math
69688       * @submodule Math
69689       * @requires constants
69690       */
69691      'use strict';
69692
69693      var p5 = _dereq_('../core/main');
69694
69695      var constants = _dereq_('../core/constants');
69696      /**
69697       * A class to describe a two or three dimensional vector, specifically
69698       * a Euclidean (also known as geometric) vector. A vector is an entity
69699       * that has both magnitude and direction. The datatype, however, stores
69700       * the components of the vector (x, y for 2D, and x, y, z for 3D). The magnitude
69701       * and direction can be accessed via the methods <a href="#/p5/mag">mag()</a> and <a href="#/p5/heading">heading()</a>.
69702       * <br><br>
69703       * In many of the p5.js examples, you will see <a href="#/p5.Vector">p5.Vector</a> used to describe a
69704       * position, velocity, or acceleration. For example, if you consider a rectangle
69705       * moving across the screen, at any given instant it has a position (a vector
69706       * that points from the origin to its location), a velocity (the rate at which
69707       * the object's position changes per time unit, expressed as a vector), and
69708       * acceleration (the rate at which the object's velocity changes per time
69709       * unit, expressed as a vector).
69710       * <br><br>
69711       * Since vectors represent groupings of values, we cannot simply use
69712       * traditional addition/multiplication/etc. Instead, we'll need to do some
69713       * "vector" math, which is made easy by the methods inside the <a href="#/p5.Vector">p5.Vector</a> class.
69714       *
69715       * @class p5.Vector
69716       * @param {Number} [x] x component of the vector
69717       * @param {Number} [y] y component of the vector
69718       * @param {Number} [z] z component of the vector
69719       * @example
69720       * <div>
69721       * <code>
69722       * let v1 = createVector(40, 50);
69723       * let v2 = createVector(40, 50);
69724       *
69725       * ellipse(v1.x, v1.y, 50, 50);
69726       * ellipse(v2.x, v2.y, 50, 50);
69727       * v1.add(v2);
69728       * ellipse(v1.x, v1.y, 50, 50);
69729       * </code>
69730       * </div>
69731       *
69732       * @alt
69733       * 2 white ellipses. One center-left the other bottom right and off canvas
69734       *
69735       */
69736
69737
69738      p5.Vector = function Vector() {
69739        var x, y, z; // This is how it comes in with createVector()
69740
69741        if (arguments[0] instanceof p5) {
69742          // save reference to p5 if passed in
69743          this.p5 = arguments[0];
69744          x = arguments[1][0] || 0;
69745          y = arguments[1][1] || 0;
69746          z = arguments[1][2] || 0; // This is what we'll get with new p5.Vector()
69747        } else {
69748          x = arguments[0] || 0;
69749          y = arguments[1] || 0;
69750          z = arguments[2] || 0;
69751        }
69752        /**
69753         * The x component of the vector
69754         * @property x {Number}
69755         */
69756
69757
69758        this.x = x;
69759        /**
69760         * The y component of the vector
69761         * @property y {Number}
69762         */
69763
69764        this.y = y;
69765        /**
69766         * The z component of the vector
69767         * @property z {Number}
69768         */
69769
69770        this.z = z;
69771      };
69772      /**
69773       * Returns a string representation of a vector v by calling String(v)
69774       * or v.toString(). This method is useful for logging vectors in the
69775       * console.
69776       * @method  toString
69777       * @return {String}
69778       * @example
69779       * <div class = "norender">
69780       * <code>
69781       * function setup() {
69782       *   let v = createVector(20, 30);
69783       *   print(String(v)); // prints "p5.Vector Object : [20, 30, 0]"
69784       * }
69785       * </code>
69786       * </div>
69787       *
69788       * <div>
69789       * <code>
69790       * function draw() {
69791       *   background(240);
69792       *
69793       *   let v0 = createVector(0, 0);
69794       *   let v1 = createVector(mouseX, mouseY);
69795       *   drawArrow(v0, v1, 'black');
69796       *
69797       *   noStroke();
69798       *   text(v1.toString(), 10, 25, 90, 75);
69799       * }
69800       *
69801       * // draw an arrow for a vector at a given base position
69802       * function drawArrow(base, vec, myColor) {
69803       *   push();
69804       *   stroke(myColor);
69805       *   strokeWeight(3);
69806       *   fill(myColor);
69807       *   translate(base.x, base.y);
69808       *   line(0, 0, vec.x, vec.y);
69809       *   rotate(vec.heading());
69810       *   let arrowSize = 7;
69811       *   translate(vec.mag() - arrowSize, 0);
69812       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
69813       *   pop();
69814       * }
69815       * </code>
69816       * </div>
69817       */
69818
69819
69820      p5.Vector.prototype.toString = function p5VectorToString() {
69821        return 'p5.Vector Object : [' + this.x + ', ' + this.y + ', ' + this.z + ']';
69822      };
69823      /**
69824       * Sets the x, y, and z component of the vector using two or three separate
69825       * variables, the data from a <a href="#/p5.Vector">p5.Vector</a>, or the values from a float array.
69826       * @method set
69827       * @param {Number} [x] the x component of the vector
69828       * @param {Number} [y] the y component of the vector
69829       * @param {Number} [z] the z component of the vector
69830       * @chainable
69831       * @example
69832       * <div class="norender">
69833       * <code>
69834       * function setup() {
69835       *   let v = createVector(1, 2, 3);
69836       *   v.set(4, 5, 6); // Sets vector to [4, 5, 6]
69837       *
69838       *   let v1 = createVector(0, 0, 0);
69839       *   let arr = [1, 2, 3];
69840       *   v1.set(arr); // Sets vector to [1, 2, 3]
69841       * }
69842       * </code>
69843       * </div>
69844       *
69845       * <div>
69846       * <code>
69847       * let v0, v1;
69848       * function setup() {
69849       *   createCanvas(100, 100);
69850       *
69851       *   v0 = createVector(0, 0);
69852       *   v1 = createVector(50, 50);
69853       * }
69854       *
69855       * function draw() {
69856       *   background(240);
69857       *
69858       *   drawArrow(v0, v1, 'black');
69859       *   v1.set(v1.x + random(-1, 1), v1.y + random(-1, 1));
69860       *
69861       *   noStroke();
69862       *   text('x: ' + round(v1.x) + ' y: ' + round(v1.y), 20, 90);
69863       * }
69864       *
69865       * // draw an arrow for a vector at a given base position
69866       * function drawArrow(base, vec, myColor) {
69867       *   push();
69868       *   stroke(myColor);
69869       *   strokeWeight(3);
69870       *   fill(myColor);
69871       *   translate(base.x, base.y);
69872       *   line(0, 0, vec.x, vec.y);
69873       *   rotate(vec.heading());
69874       *   let arrowSize = 7;
69875       *   translate(vec.mag() - arrowSize, 0);
69876       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
69877       *   pop();
69878       * }
69879       * </code>
69880       * </div>
69881       */
69882
69883      /**
69884       * @method set
69885       * @param {p5.Vector|Number[]} value the vector to set
69886       * @chainable
69887       */
69888
69889
69890      p5.Vector.prototype.set = function set(x, y, z) {
69891        if (x instanceof p5.Vector) {
69892          this.x = x.x || 0;
69893          this.y = x.y || 0;
69894          this.z = x.z || 0;
69895          return this;
69896        }
69897
69898        if (x instanceof Array) {
69899          this.x = x[0] || 0;
69900          this.y = x[1] || 0;
69901          this.z = x[2] || 0;
69902          return this;
69903        }
69904
69905        this.x = x || 0;
69906        this.y = y || 0;
69907        this.z = z || 0;
69908        return this;
69909      };
69910      /**
69911       * Gets a copy of the vector, returns a <a href="#/p5.Vector">p5.Vector</a> object.
69912       *
69913       * @method copy
69914       * @return {p5.Vector} the copy of the <a href="#/p5.Vector">p5.Vector</a> object
69915       * @example
69916       * <div class="norender">
69917       * <code>
69918       * let v1 = createVector(1, 2, 3);
69919       * let v2 = v1.copy();
69920       * print(v1.x === v2.x && v1.y === v2.y && v1.z === v2.z);
69921       * // Prints "true"
69922       * </code>
69923       * </div>
69924       */
69925
69926
69927      p5.Vector.prototype.copy = function copy() {
69928        if (this.p5) {
69929          return new p5.Vector(this.p5, [this.x, this.y, this.z]);
69930        } else {
69931          return new p5.Vector(this.x, this.y, this.z);
69932        }
69933      };
69934      /**
69935       * Adds x, y, and z components to a vector, adds one vector to another, or
69936       * adds two independent vectors together. The version of the method that adds
69937       * two vectors together is a static method and returns a <a href="#/p5.Vector">p5.Vector</a>, the others
69938       * acts directly on the vector. See the examples for more context.
69939       *
69940       * @method add
69941       * @param  {Number} x   the x component of the vector to be added
69942       * @param  {Number} [y] the y component of the vector to be added
69943       * @param  {Number} [z] the z component of the vector to be added
69944       * @chainable
69945       * @example
69946       * <div class="norender">
69947       * <code>
69948       * let v = createVector(1, 2, 3);
69949       * v.add(4, 5, 6);
69950       * // v's components are set to [5, 7, 9]
69951       * </code>
69952       * </div>
69953       *
69954       * <div class="norender">
69955       * <code>
69956       * // Static method
69957       * let v1 = createVector(1, 2, 3);
69958       * let v2 = createVector(2, 3, 4);
69959       *
69960       * let v3 = p5.Vector.add(v1, v2);
69961       * // v3 has components [3, 5, 7]
69962       * print(v3);
69963       * </code>
69964       * </div>
69965       *
69966       * <div>
69967       * <code>
69968       * // red vector + blue vector = purple vector
69969       * function draw() {
69970       *   background(240);
69971       *
69972       *   let v0 = createVector(0, 0);
69973       *   let v1 = createVector(mouseX, mouseY);
69974       *   drawArrow(v0, v1, 'red');
69975       *
69976       *   let v2 = createVector(-30, 20);
69977       *   drawArrow(v1, v2, 'blue');
69978       *
69979       *   let v3 = p5.Vector.add(v1, v2);
69980       *   drawArrow(v0, v3, 'purple');
69981       * }
69982       *
69983       * // draw an arrow for a vector at a given base position
69984       * function drawArrow(base, vec, myColor) {
69985       *   push();
69986       *   stroke(myColor);
69987       *   strokeWeight(3);
69988       *   fill(myColor);
69989       *   translate(base.x, base.y);
69990       *   line(0, 0, vec.x, vec.y);
69991       *   rotate(vec.heading());
69992       *   let arrowSize = 7;
69993       *   translate(vec.mag() - arrowSize, 0);
69994       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
69995       *   pop();
69996       * }
69997       * </code>
69998       * </div>
69999       */
70000
70001      /**
70002       * @method add
70003       * @param  {p5.Vector|Number[]} value the vector to add
70004       * @chainable
70005       */
70006
70007
70008      p5.Vector.prototype.add = function add(x, y, z) {
70009        if (x instanceof p5.Vector) {
70010          this.x += x.x || 0;
70011          this.y += x.y || 0;
70012          this.z += x.z || 0;
70013          return this;
70014        }
70015
70016        if (x instanceof Array) {
70017          this.x += x[0] || 0;
70018          this.y += x[1] || 0;
70019          this.z += x[2] || 0;
70020          return this;
70021        }
70022
70023        this.x += x || 0;
70024        this.y += y || 0;
70025        this.z += z || 0;
70026        return this;
70027      };
70028      /**
70029       * Subtracts x, y, and z components from a vector, subtracts one vector from
70030       * another, or subtracts two independent vectors. The version of the method
70031       * that subtracts two vectors is a static method and returns a <a href="#/p5.Vector">p5.Vector</a>, the
70032       * other acts directly on the vector. See the examples for more context.
70033       *
70034       * @method sub
70035       * @param  {Number} x   the x component of the vector to subtract
70036       * @param  {Number} [y] the y component of the vector to subtract
70037       * @param  {Number} [z] the z component of the vector to subtract
70038       * @chainable
70039       * @example
70040       * <div class="norender">
70041       * <code>
70042       * let v = createVector(4, 5, 6);
70043       * v.sub(1, 1, 1);
70044       * // v's components are set to [3, 4, 5]
70045       * </code>
70046       * </div>
70047       *
70048       * <div class="norender">
70049       * <code>
70050       * // Static method
70051       * let v1 = createVector(2, 3, 4);
70052       * let v2 = createVector(1, 2, 3);
70053       *
70054       * let v3 = p5.Vector.sub(v1, v2);
70055       * // v3 has components [1, 1, 1]
70056       * print(v3);
70057       * </code>
70058       * </div>
70059       *
70060       * <div>
70061       * <code>
70062       * // red vector - blue vector = purple vector
70063       * function draw() {
70064       *   background(240);
70065       *
70066       *   let v0 = createVector(0, 0);
70067       *   let v1 = createVector(70, 50);
70068       *   drawArrow(v0, v1, 'red');
70069       *
70070       *   let v2 = createVector(mouseX, mouseY);
70071       *   drawArrow(v0, v2, 'blue');
70072       *
70073       *   let v3 = p5.Vector.sub(v1, v2);
70074       *   drawArrow(v2, v3, 'purple');
70075       * }
70076       *
70077       * // draw an arrow for a vector at a given base position
70078       * function drawArrow(base, vec, myColor) {
70079       *   push();
70080       *   stroke(myColor);
70081       *   strokeWeight(3);
70082       *   fill(myColor);
70083       *   translate(base.x, base.y);
70084       *   line(0, 0, vec.x, vec.y);
70085       *   rotate(vec.heading());
70086       *   let arrowSize = 7;
70087       *   translate(vec.mag() - arrowSize, 0);
70088       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
70089       *   pop();
70090       * }
70091       * </code>
70092       * </div>
70093       */
70094
70095      /**
70096       * @method sub
70097       * @param  {p5.Vector|Number[]} value the vector to subtract
70098       * @chainable
70099       */
70100
70101
70102      p5.Vector.prototype.sub = function sub(x, y, z) {
70103        if (x instanceof p5.Vector) {
70104          this.x -= x.x || 0;
70105          this.y -= x.y || 0;
70106          this.z -= x.z || 0;
70107          return this;
70108        }
70109
70110        if (x instanceof Array) {
70111          this.x -= x[0] || 0;
70112          this.y -= x[1] || 0;
70113          this.z -= x[2] || 0;
70114          return this;
70115        }
70116
70117        this.x -= x || 0;
70118        this.y -= y || 0;
70119        this.z -= z || 0;
70120        return this;
70121      };
70122      /**
70123       * Multiply the vector by a scalar. The static version of this method
70124       * creates a new <a href="#/p5.Vector">p5.Vector</a> while the non static version acts on the vector
70125       * directly. See the examples for more context.
70126       *
70127       * @method mult
70128       * @param  {Number}    n the number to multiply with the vector
70129       * @chainable
70130       * @example
70131       * <div class="norender">
70132       * <code>
70133       * let v = createVector(1, 2, 3);
70134       * v.mult(2);
70135       * // v's components are set to [2, 4, 6]
70136       * </code>
70137       * </div>
70138       *
70139       * <div class="norender">
70140       * <code>
70141       * // Static method
70142       * let v1 = createVector(1, 2, 3);
70143       * let v2 = p5.Vector.mult(v1, 2);
70144       * // v2 has components [2, 4, 6]
70145       * print(v2);
70146       * </code>
70147       * </div>
70148       *
70149       * <div>
70150       * <code>
70151       * function draw() {
70152       *   background(240);
70153       *
70154       *   let v0 = createVector(50, 50);
70155       *   let v1 = createVector(25, -25);
70156       *   drawArrow(v0, v1, 'red');
70157       *
70158       *   let num = map(mouseX, 0, width, -2, 2, true);
70159       *   let v2 = p5.Vector.mult(v1, num);
70160       *   drawArrow(v0, v2, 'blue');
70161       *
70162       *   noStroke();
70163       *   text('multiplied by ' + num.toFixed(2), 5, 90);
70164       * }
70165       *
70166       * // draw an arrow for a vector at a given base position
70167       * function drawArrow(base, vec, myColor) {
70168       *   push();
70169       *   stroke(myColor);
70170       *   strokeWeight(3);
70171       *   fill(myColor);
70172       *   translate(base.x, base.y);
70173       *   line(0, 0, vec.x, vec.y);
70174       *   rotate(vec.heading());
70175       *   let arrowSize = 7;
70176       *   translate(vec.mag() - arrowSize, 0);
70177       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
70178       *   pop();
70179       * }
70180       * </code>
70181       * </div>
70182       */
70183
70184
70185      p5.Vector.prototype.mult = function mult(n) {
70186        if (!(typeof n === 'number' && isFinite(n))) {
70187          console.warn('p5.Vector.prototype.mult:', 'n is undefined or not a finite number');
70188          return this;
70189        }
70190
70191        this.x *= n;
70192        this.y *= n;
70193        this.z *= n;
70194        return this;
70195      };
70196      /**
70197       * Divide the vector by a scalar. The static version of this method creates a
70198       * new <a href="#/p5.Vector">p5.Vector</a> while the non static version acts on the vector directly.
70199       * See the examples for more context.
70200       *
70201       * @method div
70202       * @param  {number}    n the number to divide the vector by
70203       * @chainable
70204       * @example
70205       * <div class="norender">
70206       * <code>
70207       * let v = createVector(6, 4, 2);
70208       * v.div(2); //v's components are set to [3, 2, 1]
70209       * </code>
70210       * </div>
70211       *
70212       * <div class="norender">
70213       * <code>
70214       * // Static method
70215       * let v1 = createVector(6, 4, 2);
70216       * let v2 = p5.Vector.div(v1, 2);
70217       * // v2 has components [3, 2, 1]
70218       * print(v2);
70219       * </code>
70220       * </div>
70221       *
70222       * <div>
70223       * <code>
70224       * function draw() {
70225       *   background(240);
70226       *
70227       *   let v0 = createVector(0, 100);
70228       *   let v1 = createVector(50, -50);
70229       *   drawArrow(v0, v1, 'red');
70230       *
70231       *   let num = map(mouseX, 0, width, 10, 0.5, true);
70232       *   let v2 = p5.Vector.div(v1, num);
70233       *   drawArrow(v0, v2, 'blue');
70234       *
70235       *   noStroke();
70236       *   text('divided by ' + num.toFixed(2), 10, 90);
70237       * }
70238       *
70239       * // draw an arrow for a vector at a given base position
70240       * function drawArrow(base, vec, myColor) {
70241       *   push();
70242       *   stroke(myColor);
70243       *   strokeWeight(3);
70244       *   fill(myColor);
70245       *   translate(base.x, base.y);
70246       *   line(0, 0, vec.x, vec.y);
70247       *   rotate(vec.heading());
70248       *   let arrowSize = 7;
70249       *   translate(vec.mag() - arrowSize, 0);
70250       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
70251       *   pop();
70252       * }
70253       * </code>
70254       * </div>
70255       */
70256
70257
70258      p5.Vector.prototype.div = function div(n) {
70259        if (!(typeof n === 'number' && isFinite(n))) {
70260          console.warn('p5.Vector.prototype.div:', 'n is undefined or not a finite number');
70261          return this;
70262        }
70263
70264        if (n === 0) {
70265          console.warn('p5.Vector.prototype.div:', 'divide by 0');
70266          return this;
70267        }
70268
70269        this.x /= n;
70270        this.y /= n;
70271        this.z /= n;
70272        return this;
70273      };
70274      /**
70275       * Calculates the magnitude (length) of the vector and returns the result as
70276       * a float (this is simply the equation sqrt(x*x + y*y + z*z).)
70277       *
70278       * @method mag
70279       * @return {Number} magnitude of the vector
70280       * @example
70281       * <div>
70282       * <code>
70283       * function draw() {
70284       *   background(240);
70285       *
70286       *   let v0 = createVector(0, 0);
70287       *   let v1 = createVector(mouseX, mouseY);
70288       *   drawArrow(v0, v1, 'black');
70289       *
70290       *   noStroke();
70291       *   text('vector length: ' + v1.mag().toFixed(2), 10, 70, 90, 30);
70292       * }
70293       *
70294       * // draw an arrow for a vector at a given base position
70295       * function drawArrow(base, vec, myColor) {
70296       *   push();
70297       *   stroke(myColor);
70298       *   strokeWeight(3);
70299       *   fill(myColor);
70300       *   translate(base.x, base.y);
70301       *   line(0, 0, vec.x, vec.y);
70302       *   rotate(vec.heading());
70303       *   let arrowSize = 7;
70304       *   translate(vec.mag() - arrowSize, 0);
70305       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
70306       *   pop();
70307       * }
70308       * </code>
70309       * </div>
70310       * <div class="norender">
70311       * <code>
70312       * let v = createVector(20.0, 30.0, 40.0);
70313       * let m = v.mag();
70314       * print(m); // Prints "53.85164807134504"
70315       * </code>
70316       * </div>
70317       */
70318
70319
70320      p5.Vector.prototype.mag = function mag() {
70321        return Math.sqrt(this.magSq());
70322      };
70323      /**
70324       * Calculates the squared magnitude of the vector and returns the result
70325       * as a float (this is simply the equation <em>(x*x + y*y + z*z)</em>.)
70326       * Faster if the real length is not required in the
70327       * case of comparing vectors, etc.
70328       *
70329       * @method magSq
70330       * @return {number} squared magnitude of the vector
70331       * @example
70332       * <div class="norender">
70333       * <code>
70334       * // Static method
70335       * let v1 = createVector(6, 4, 2);
70336       * print(v1.magSq()); // Prints "56"
70337       * </code>
70338       * </div>
70339       *
70340       * <div>
70341       * <code>
70342       * function draw() {
70343       *   background(240);
70344       *
70345       *   let v0 = createVector(0, 0);
70346       *   let v1 = createVector(mouseX, mouseY);
70347       *   drawArrow(v0, v1, 'black');
70348       *
70349       *   noStroke();
70350       *   text('vector length squared: ' + v1.magSq().toFixed(2), 10, 45, 90, 55);
70351       * }
70352       *
70353       * // draw an arrow for a vector at a given base position
70354       * function drawArrow(base, vec, myColor) {
70355       *   push();
70356       *   stroke(myColor);
70357       *   strokeWeight(3);
70358       *   fill(myColor);
70359       *   translate(base.x, base.y);
70360       *   line(0, 0, vec.x, vec.y);
70361       *   rotate(vec.heading());
70362       *   let arrowSize = 7;
70363       *   translate(vec.mag() - arrowSize, 0);
70364       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
70365       *   pop();
70366       * }
70367       * </code>
70368       * </div>
70369       */
70370
70371
70372      p5.Vector.prototype.magSq = function magSq() {
70373        var x = this.x;
70374        var y = this.y;
70375        var z = this.z;
70376        return x * x + y * y + z * z;
70377      };
70378      /**
70379       * Calculates the dot product of two vectors. The version of the method
70380       * that computes the dot product of two independent vectors is a static
70381       * method. See the examples for more context.
70382       *
70383       *
70384       * @method dot
70385       * @param  {Number} x   x component of the vector
70386       * @param  {Number} [y] y component of the vector
70387       * @param  {Number} [z] z component of the vector
70388       * @return {Number}       the dot product
70389       *
70390       * @example
70391       * <div class="norender">
70392       * <code>
70393       * let v1 = createVector(1, 2, 3);
70394       * let v2 = createVector(2, 3, 4);
70395       *
70396       * print(v1.dot(v2)); // Prints "20"
70397       * </code>
70398       * </div>
70399       *
70400       * <div class="norender">
70401       * <code>
70402       * //Static method
70403       * let v1 = createVector(1, 2, 3);
70404       * let v2 = createVector(3, 2, 1);
70405       * print(p5.Vector.dot(v1, v2)); // Prints "10"
70406       * </code>
70407       * </div>
70408       */
70409
70410      /**
70411       * @method dot
70412       * @param  {p5.Vector} value value component of the vector or a <a href="#/p5.Vector">p5.Vector</a>
70413       * @return {Number}
70414       */
70415
70416
70417      p5.Vector.prototype.dot = function dot(x, y, z) {
70418        if (x instanceof p5.Vector) {
70419          return this.dot(x.x, x.y, x.z);
70420        }
70421
70422        return this.x * (x || 0) + this.y * (y || 0) + this.z * (z || 0);
70423      };
70424      /**
70425       * Calculates and returns a vector composed of the cross product between
70426       * two vectors. Both the static and non static methods return a new <a href="#/p5.Vector">p5.Vector</a>.
70427       * See the examples for more context.
70428       *
70429       * @method cross
70430       * @param  {p5.Vector} v <a href="#/p5.Vector">p5.Vector</a> to be crossed
70431       * @return {p5.Vector}   <a href="#/p5.Vector">p5.Vector</a> composed of cross product
70432       * @example
70433       * <div class="norender">
70434       * <code>
70435       * let v1 = createVector(1, 2, 3);
70436       * let v2 = createVector(1, 2, 3);
70437       *
70438       * v1.cross(v2); // v's components are [0, 0, 0]
70439       * </code>
70440       * </div>
70441       *
70442       * <div class="norender">
70443       * <code>
70444       * // Static method
70445       * let v1 = createVector(1, 0, 0);
70446       * let v2 = createVector(0, 1, 0);
70447       *
70448       * let crossProduct = p5.Vector.cross(v1, v2);
70449       * // crossProduct has components [0, 0, 1]
70450       * print(crossProduct);
70451       * </code>
70452       * </div>
70453       */
70454
70455
70456      p5.Vector.prototype.cross = function cross(v) {
70457        var x = this.y * v.z - this.z * v.y;
70458        var y = this.z * v.x - this.x * v.z;
70459        var z = this.x * v.y - this.y * v.x;
70460
70461        if (this.p5) {
70462          return new p5.Vector(this.p5, [x, y, z]);
70463        } else {
70464          return new p5.Vector(x, y, z);
70465        }
70466      };
70467      /**
70468       * Calculates the Euclidean distance between two points (considering a
70469       * point as a vector object).
70470       *
70471       * @method dist
70472       * @param  {p5.Vector} v the x, y, and z coordinates of a <a href="#/p5.Vector">p5.Vector</a>
70473       * @return {Number}      the distance
70474       * @example
70475       * <div class="norender">
70476       * <code>
70477       * let v1 = createVector(1, 0, 0);
70478       * let v2 = createVector(0, 1, 0);
70479       *
70480       * let distance = v1.dist(v2); // distance is 1.4142...
70481       * print(distance);
70482       * </code>
70483       * </div>
70484       *
70485       * <div class="norender">
70486       * <code>
70487       * // Static method
70488       * let v1 = createVector(1, 0, 0);
70489       * let v2 = createVector(0, 1, 0);
70490       *
70491       * let distance = p5.Vector.dist(v1, v2);
70492       * // distance is 1.4142...
70493       * print(distance);
70494       * </code>
70495       * </div>
70496       *
70497       * <div>
70498       * <code>
70499       * function draw() {
70500       *   background(240);
70501       *
70502       *   let v0 = createVector(0, 0);
70503       *
70504       *   let v1 = createVector(70, 50);
70505       *   drawArrow(v0, v1, 'red');
70506       *
70507       *   let v2 = createVector(mouseX, mouseY);
70508       *   drawArrow(v0, v2, 'blue');
70509       *
70510       *   noStroke();
70511       *   text('distance between vectors: ' + v2.dist(v1).toFixed(2), 5, 50, 95, 50);
70512       * }
70513       *
70514       * // draw an arrow for a vector at a given base position
70515       * function drawArrow(base, vec, myColor) {
70516       *   push();
70517       *   stroke(myColor);
70518       *   strokeWeight(3);
70519       *   fill(myColor);
70520       *   translate(base.x, base.y);
70521       *   line(0, 0, vec.x, vec.y);
70522       *   rotate(vec.heading());
70523       *   let arrowSize = 7;
70524       *   translate(vec.mag() - arrowSize, 0);
70525       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
70526       *   pop();
70527       * }
70528       * </code>
70529       * </div>
70530       */
70531
70532
70533      p5.Vector.prototype.dist = function dist(v) {
70534        return v.copy().sub(this).mag();
70535      };
70536      /**
70537       * Normalize the vector to length 1 (make it a unit vector).
70538       *
70539       * @method normalize
70540       * @return {p5.Vector} normalized <a href="#/p5.Vector">p5.Vector</a>
70541       * @example
70542       * <div class="norender">
70543       * <code>
70544       * let v = createVector(10, 20, 2);
70545       * // v has components [10.0, 20.0, 2.0]
70546       * v.normalize();
70547       * // v's components are set to
70548       * // [0.4454354, 0.8908708, 0.089087084]
70549       * </code>
70550       * </div>
70551       * <div>
70552       * <code>
70553       * function draw() {
70554       *   background(240);
70555       *
70556       *   let v0 = createVector(50, 50);
70557       *   let v1 = createVector(mouseX - 50, mouseY - 50);
70558       *
70559       *   drawArrow(v0, v1, 'red');
70560       *   v1.normalize();
70561       *   drawArrow(v0, v1.mult(35), 'blue');
70562       *
70563       *   noFill();
70564       *   ellipse(50, 50, 35 * 2);
70565       * }
70566       *
70567       * // draw an arrow for a vector at a given base position
70568       * function drawArrow(base, vec, myColor) {
70569       *   push();
70570       *   stroke(myColor);
70571       *   strokeWeight(3);
70572       *   fill(myColor);
70573       *   translate(base.x, base.y);
70574       *   line(0, 0, vec.x, vec.y);
70575       *   rotate(vec.heading());
70576       *   let arrowSize = 7;
70577       *   translate(vec.mag() - arrowSize, 0);
70578       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
70579       *   pop();
70580       * }
70581       * </code>
70582       * </div>
70583       */
70584
70585
70586      p5.Vector.prototype.normalize = function normalize() {
70587        var len = this.mag(); // here we multiply by the reciprocal instead of calling 'div()'
70588        // since div duplicates this zero check.
70589
70590        if (len !== 0) this.mult(1 / len);
70591        return this;
70592      };
70593      /**
70594       * Limit the magnitude of this vector to the value used for the <b>max</b>
70595       * parameter.
70596       *
70597       * @method limit
70598       * @param  {Number}    max the maximum magnitude for the vector
70599       * @chainable
70600       * @example
70601       * <div class="norender">
70602       * <code>
70603       * let v = createVector(10, 20, 2);
70604       * // v has components [10.0, 20.0, 2.0]
70605       * v.limit(5);
70606       * // v's components are set to
70607       * // [2.2271771, 4.4543543, 0.4454354]
70608       * </code>
70609       * </div>
70610       * <div>
70611       * <code>
70612       * function draw() {
70613       *   background(240);
70614       *
70615       *   let v0 = createVector(50, 50);
70616       *   let v1 = createVector(mouseX - 50, mouseY - 50);
70617       *
70618       *   drawArrow(v0, v1, 'red');
70619       *   drawArrow(v0, v1.limit(35), 'blue');
70620       *
70621       *   noFill();
70622       *   ellipse(50, 50, 35 * 2);
70623       * }
70624       *
70625       * // draw an arrow for a vector at a given base position
70626       * function drawArrow(base, vec, myColor) {
70627       *   push();
70628       *   stroke(myColor);
70629       *   strokeWeight(3);
70630       *   fill(myColor);
70631       *   translate(base.x, base.y);
70632       *   line(0, 0, vec.x, vec.y);
70633       *   rotate(vec.heading());
70634       *   let arrowSize = 7;
70635       *   translate(vec.mag() - arrowSize, 0);
70636       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
70637       *   pop();
70638       * }
70639       * </code>
70640       * </div>
70641       */
70642
70643
70644      p5.Vector.prototype.limit = function limit(max) {
70645        var mSq = this.magSq();
70646
70647        if (mSq > max * max) {
70648          this.div(Math.sqrt(mSq)) //normalize it
70649          .mult(max);
70650        }
70651
70652        return this;
70653      };
70654      /**
70655       * Set the magnitude of this vector to the value used for the <b>len</b>
70656       * parameter.
70657       *
70658       * @method setMag
70659       * @param  {number}    len the new length for this vector
70660       * @chainable
70661       * @example
70662       * <div class="norender">
70663       * <code>
70664       * let v = createVector(10, 20, 2);
70665       * // v has components [10.0, 20.0, 2.0]
70666       * v.setMag(10);
70667       * // v's components are set to [6.0, 8.0, 0.0]
70668       * </code>
70669       * </div>
70670       *
70671       * <div>
70672       * <code>
70673       * function draw() {
70674       *   background(240);
70675       *
70676       *   let v0 = createVector(0, 0);
70677       *   let v1 = createVector(50, 50);
70678       *
70679       *   drawArrow(v0, v1, 'red');
70680       *
70681       *   let length = map(mouseX, 0, width, 0, 141, true);
70682       *   v1.setMag(length);
70683       *   drawArrow(v0, v1, 'blue');
70684       *
70685       *   noStroke();
70686       *   text('magnitude set to: ' + length.toFixed(2), 10, 70, 90, 30);
70687       * }
70688       *
70689       * // draw an arrow for a vector at a given base position
70690       * function drawArrow(base, vec, myColor) {
70691       *   push();
70692       *   stroke(myColor);
70693       *   strokeWeight(3);
70694       *   fill(myColor);
70695       *   translate(base.x, base.y);
70696       *   line(0, 0, vec.x, vec.y);
70697       *   rotate(vec.heading());
70698       *   let arrowSize = 7;
70699       *   translate(vec.mag() - arrowSize, 0);
70700       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
70701       *   pop();
70702       * }
70703       * </code>
70704       * </div>
70705       */
70706
70707
70708      p5.Vector.prototype.setMag = function setMag(n) {
70709        return this.normalize().mult(n);
70710      };
70711      /**
70712       * Calculate the angle of rotation for this vector (only 2D vectors)
70713       *
70714       * @method heading
70715       * @return {Number} the angle of rotation
70716       * @example
70717       * <div class = "norender">
70718       * <code>
70719       * function setup() {
70720       *   let v1 = createVector(30, 50);
70721       *   print(v1.heading()); // 1.0303768265243125
70722       *
70723       *   v1 = createVector(40, 50);
70724       *   print(v1.heading());
70724 // 0.8960553845713439
70725       *
70726       *   v1 = createVector(30, 70);
70727       *   print(v1.heading()); // 1.1659045405098132
70728       * }
70729       * </code>
70730       * </div>
70731       *
70732       * <div>
70733       * <code>
70734       * function draw() {
70735       *   background(240);
70736       *
70737       *   let v0 = createVector(50, 50);
70738       *   let v1 = createVector(mouseX - 50, mouseY - 50);
70739       *
70740       *   drawArrow(v0, v1, 'black');
70741       *
70742       *   let myHeading = v1.heading();
70743       *   noStroke();
70744       *   text(
70745       *     'vector heading: ' +
70746       *       myHeading.toFixed(2) +
70747       *       ' radians or ' +
70748       *       degrees(myHeading).toFixed(2) +
70749       *       ' degrees',
70750       *     10,
70751       *     50,
70752       *     90,
70753       *     50
70754       *   );
70755       * }
70756       *
70757       * // draw an arrow for a vector at a given base position
70758       * function drawArrow(base, vec, myColor) {
70759       *   push();
70760       *   stroke(myColor);
70761       *   strokeWeight(3);
70762       *   fill(myColor);
70763       *   translate(base.x, base.y);
70764       *   line(0, 0, vec.x, vec.y);
70765       *   rotate(vec.heading());
70766       *   let arrowSize = 7;
70767       *   translate(vec.mag() - arrowSize, 0);
70768       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
70769       *   pop();
70770       * }
70771       * </code>
70772       * </div>
70773       */
70774
70775
70776      p5.Vector.prototype.heading = function heading() {
70777        var h = Math.atan2(this.y, this.x);
70778        if (this.p5) return this.p5._fromRadians(h);
70779        return h;
70780      };
70781      /**
70782       * Rotate the vector by an angle (only 2D vectors), magnitude remains the
70783       * same
70784       *
70785       * @method rotate
70786       * @param  {number}    angle the angle of rotation
70787       * @chainable
70788       * @example
70789       * <div class="norender">
70790       * <code>
70791       * let v = createVector(10.0, 20.0);
70792       * // v has components [10.0, 20.0, 0.0]
70793       * v.rotate(HALF_PI);
70794       * // v's components are set to [-20.0, 9.999999, 0.0]
70795       * </code>
70796       * </div>
70797       *
70798       * <div>
70799       * <code>
70800       * let angle = 0;
70801       * function draw() {
70802       *   background(240);
70803       *
70804       *   let v0 = createVector(50, 50);
70805       *   let v1 = createVector(50, 0);
70806       *
70807       *   drawArrow(v0, v1.rotate(angle), 'black');
70808       *   angle += 0.01;
70809       * }
70810       *
70811       * // draw an arrow for a vector at a given base position
70812       * function drawArrow(base, vec, myColor) {
70813       *   push();
70814       *   stroke(myColor);
70815       *   strokeWeight(3);
70816       *   fill(myColor);
70817       *   translate(base.x, base.y);
70818       *   line(0, 0, vec.x, vec.y);
70819       *   rotate(vec.heading());
70820       *   let arrowSize = 7;
70821       *   translate(vec.mag() - arrowSize, 0);
70822       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
70823       *   pop();
70824       * }
70825       * </code>
70826       * </div>
70827       */
70828
70829
70830      p5.Vector.prototype.rotate = function rotate(a) {
70831        var newHeading = this.heading() + a;
70832        if (this.p5) newHeading = this.p5._toRadians(newHeading);
70833        var mag = this.mag();
70834        this.x = Math.cos(newHeading) * mag;
70835        this.y = Math.sin(newHeading) * mag;
70836        return this;
70837      };
70838      /**
70839       * Calculates and returns the angle (in radians) between two vectors.
70840       * @method angleBetween
70841       * @param  {p5.Vector}    the x, y, and z components of a <a href="#/p5.Vector">p5.Vector</a>
70842       * @return {Number}       the angle between (in radians)
70843       * @example
70844       * <div class="norender">
70845       * <code>
70846       * let v1 = createVector(1, 0, 0);
70847       * let v2 = createVector(0, 1, 0);
70848       *
70849       * let angle = v1.angleBetween(v2);
70850       * // angle is PI/2
70851       * print(angle);
70852       * </code>
70853       * </div>
70854       *
70855       * <div>
70856       * <code>
70857       * function draw() {
70858       *   background(240);
70859       *   let v0 = createVector(50, 50);
70860       *
70861       *   let v1 = createVector(50, 0);
70862       *   drawArrow(v0, v1, 'red');
70863       *
70864       *   let v2 = createVector(mouseX - 50, mouseY - 50);
70865       *   drawArrow(v0, v2, 'blue');
70866       *
70867       *   let angleBetween = v1.angleBetween(v2);
70868       *   noStroke();
70869       *   text(
70870       *     'angle between: ' +
70871       *       angleBetween.toFixed(2) +
70872       *       ' radians or ' +
70873       *       degrees(angleBetween).toFixed(2) +
70874       *       ' degrees',
70875       *     10,
70876       *     50,
70877       *     90,
70878       *     50
70879       *   );
70880       * }
70881       *
70882       * // draw an arrow for a vector at a given base position
70883       * function drawArrow(base, vec, myColor) {
70884       *   push();
70885       *   stroke(myColor);
70886       *   strokeWeight(3);
70887       *   fill(myColor);
70888       *   translate(base.x, base.y);
70889       *   line(0, 0, vec.x, vec.y);
70890       *   rotate(vec.heading());
70891       *   let arrowSize = 7;
70892       *   translate(vec.mag() - arrowSize, 0);
70893       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
70894       *   pop();
70895       * }
70896       * </code>
70897       * </div>
70898       */
70899
70900
70901      p5.Vector.prototype.angleBetween = function angleBetween(v) {
70902        var dotmagmag = this.dot(v) / (this.mag() * v.mag()); // Mathematically speaking: the dotmagmag variable will be between -1 and 1
70903        // inclusive. Practically though it could be slightly outside this range due
70904        // to floating-point rounding issues. This can make Math.acos return NaN.
70905        //
70906        // Solution: we'll clamp the value to the -1,1 range
70907
70908        var angle = Math.acos(Math.min(1, Math.max(-1, dotmagmag)));
70909        if (this.p5) return this.p5._fromRadians(angle);
70910        return angle;
70911      };
70912      /**
70913       * Linear interpolate the vector to another vector
70914       *
70915       * @method lerp
70916       * @param  {Number}    x   the x component
70917       * @param  {Number}    y   the y component
70918       * @param  {Number}    z   the z component
70919       * @param  {Number}    amt the amount of interpolation; some value between 0.0
70920       *                         (old vector) and 1.0 (new vector). 0.9 is very near
70921       *                         the new vector. 0.5 is halfway in between.
70922       * @chainable
70923       *
70924       * @example
70925       * <div class="norender">
70926       * <code>
70927       * let v = createVector(1, 1, 0);
70928       *
70929       * v.lerp(3, 3, 0, 0.5); // v now has components [2,2,0]
70930       * </code>
70931       * </div>
70932       *
70933       * <div class="norender">
70934       * <code>
70935       * let v1 = createVector(0, 0, 0);
70936       * let v2 = createVector(100, 100, 0);
70937       *
70938       * let v3 = p5.Vector.lerp(v1, v2, 0.5);
70939       * // v3 has components [50,50,0]
70940       * print(v3);
70941       * </code>
70942       * </div>
70943       *
70944       * <div>
70945       * <code>
70946       * let step = 0.01;
70947       * let amount = 0;
70948       *
70949       * function draw() {
70950       *   background(240);
70951       *   let v0 = createVector(0, 0);
70952       *
70953       *   let v1 = createVector(mouseX, mouseY);
70954       *   drawArrow(v0, v1, 'red');
70955       *
70956       *   let v2 = createVector(90, 90);
70957       *   drawArrow(v0, v2, 'blue');
70958       *
70959       *   if (amount > 1 || amount < 0) {
70960       *     step *= -1;
70961       *   }
70962       *   amount += step;
70963       *   let v3 = p5.Vector.lerp(v1, v2, amount);
70964       *
70965       *   drawArrow(v0, v3, 'purple');
70966       * }
70967       *
70968       * // draw an arrow for a vector at a given base position
70969       * function drawArrow(base, vec, myColor) {
70970       *   push();
70971       *   stroke(myColor);
70972       *   strokeWeight(3);
70973       *   fill(myColor);
70974       *   translate(base.x, base.y);
70975       *   line(0, 0, vec.x, vec.y);
70976       *   rotate(vec.heading());
70977       *   let arrowSize = 7;
70978       *   translate(vec.mag() - arrowSize, 0);
70979       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
70980       *   pop();
70981       * }
70982       * </code>
70983       * </div>
70984       */
70985
70986      /**
70987       * @method lerp
70988       * @param  {p5.Vector} v   the <a href="#/p5.Vector">p5.Vector</a> to lerp to
70989       * @param  {Number}    amt
70990       * @chainable
70991       */
70992
70993
70994      p5.Vector.prototype.lerp = function lerp(x, y, z, amt) {
70995        if (x instanceof p5.Vector) {
70996          return this.lerp(x.x, x.y, x.z, y);
70997        }
70998
70999        this.x += (x - this.x) * amt || 0;
71000        this.y += (y - this.y) * amt || 0;
71001        this.z += (z - this.z) * amt || 0;
71002        return this;
71003      };
71004      /**
71005       * Return a representation of this vector as a float array. This is only
71006       * for temporary use. If used in any other fashion, the contents should be
71007       * copied by using the <b>p5.Vector.<a href="#/p5.Vector/copy">copy()</a></b> method to copy into your own
71008       * array.
71009       *
71010       * @method array
71011       * @return {Number[]} an Array with the 3 values
71012       * @example
71013       * <div class = "norender">
71014       * <code>
71015       * function setup() {
71016       *   let v = createVector(20, 30);
71017       *   print(v.array()); // Prints : Array [20, 30, 0]
71018       * }
71019       * </code>
71020       * </div>
71021       *
71022       * <div class="norender">
71023       * <code>
71024       * let v = createVector(10.0, 20.0, 30.0);
71025       * let f = v.array();
71026       * print(f[0]); // Prints "10.0"
71027       * print(f[1]); // Prints "20.0"
71028       * print(f[2]); // Prints "30.0"
71029       * </code>
71030       * </div>
71031       */
71032
71033
71034      p5.Vector.prototype.array = function array() {
71035        return [this.x || 0, this.y || 0, this.z || 0];
71036      };
71037      /**
71038       * Equality check against a <a href="#/p5.Vector">p5.Vector</a>
71039       *
71040       * @method equals
71041       * @param {Number} [x] the x component of the vector
71042       * @param {Number} [y] the y component of the vector
71043       * @param {Number} [z] the z component of the vector
71044       * @return {Boolean} whether the vectors are equals
71045       * @example
71046       * <div class = "norender">
71047       * <code>
71048       * let v1 = createVector(5, 10, 20);
71049       * let v2 = createVector(5, 10, 20);
71050       * let v3 = createVector(13, 10, 19);
71051       *
71052       * print(v1.equals(v2.x, v2.y, v2.z)); // true
71053       * print(v1.equals(v3.x, v3.y, v3.z)); // false
71054       * </code>
71055       * </div>
71056       *
71057       * <div class="norender">
71058       * <code>
71059       * let v1 = createVector(10.0, 20.0, 30.0);
71060       * let v2 = createVector(10.0, 20.0, 30.0);
71061       * let v3 = createVector(0.0, 0.0, 0.0);
71062       * print(v1.equals(v2)); // true
71063       * print(v1.equals(v3)); // false
71064       * </code>
71065       * </div>
71066       */
71067
71068      /**
71069       * @method equals
71070       * @param {p5.Vector|Array} value the vector to compare
71071       * @return {Boolean}
71072       */
71073
71074
71075      p5.Vector.prototype.equals = function equals(x, y, z) {
71076        var a, b, c;
71077
71078        if (x instanceof p5.Vector) {
71079          a = x.x || 0;
71080          b = x.y || 0;
71081          c = x.z || 0;
71082        } else if (x instanceof Array) {
71083          a = x[0] || 0;
71084          b = x[1] || 0;
71085          c = x[2] || 0;
71086        } else {
71087          a = x || 0;
71088          b = y || 0;
71089          c = z || 0;
71090        }
71091
71092        return this.x === a && this.y === b && this.z === c;
71093      }; // Static Methods
71094
71095      /**
71096       * Make a new 2D vector from an angle
71097       *
71098       * @method fromAngle
71099       * @static
71100       * @param {Number}     angle the desired angle, in radians
71101       * @param {Number}     [length] the length of the new vector (defaults to 1)
71102       * @return {p5.Vector}       the new <a href="#/p5.Vector">p5.Vector</a> object
71103       * @example
71104       * <div>
71105       * <code>
71106       * function draw() {
71107       *   background(200);
71108       *
71109       *   // Create a variable, proportional to the mouseX,
71110       *   // varying from 0-360, to represent an angle in degrees.
71111       *   angleMode(DEGREES);
71112       *   let myDegrees = map(mouseX, 0, width, 0, 360);
71113       *
71114       *   // Display that variable in an onscreen text.
71115       *   // (Note the nfc() function to truncate additional decimal places,
71116       *   // and the "\xB0" character for the degree symbol.)
71117       *   let readout = 'angle = ' + nfc(myDegrees, 1) + '\xB0';
71118       *   noStroke();
71119       *   fill(0);
71120       *   text(readout, 5, 15);
71121       *
71122       *   // Create a p5.Vector using the fromAngle function,
71123       *   // and extract its x and y components.
71124       *   let v = p5.Vector.fromAngle(radians(myDegrees), 30);
71125       *   let vx = v.x;
71126       *   let vy = v.y;
71127       *
71128       *   push();
71129       *   translate(width / 2, height / 2);
71130       *   noFill();
71131       *   stroke(150);
71132       *   line(0, 0, 30, 0);
71133       *   stroke(0);
71134       *   line(0, 0, vx, vy);
71135       *   pop();
71136       * }
71137       * </code>
71138       * </div>
71139       */
71140
71141
71142      p5.Vector.fromAngle = function fromAngle(angle, length) {
71143        if (typeof length === 'undefined') {
71144          length = 1;
71145        }
71146
71147        return new p5.Vector(length * Math.cos(angle), length * Math.sin(angle), 0);
71148      };
71149      /**
71150       * Make a new 3D vector from a pair of ISO spherical angles
71151       *
71152       * @method fromAngles
71153       * @static
71154       * @param {Number}     theta    the polar angle, in radians (zero is up)
71155       * @param {Number}     phi      the azimuthal angle, in radians
71156       *                               (zero is out of the screen)
71157       * @param {Number}     [length] the length of the new vector (defaults to 1)
71158       * @return {p5.Vector}          the new <a href="#/p5.Vector">p5.Vector</a> object
71159       * @example
71160       * <div modernizr='webgl'>
71161       * <code>
71162       * function setup() {
71163       *   createCanvas(100, 100, WEBGL);
71164       *   fill(255);
71165       *   noStroke();
71166       * }
71167       * function draw() {
71168       *   background(255);
71169       *
71170       *   let t = millis() / 1000;
71171       *
71172       *   // add three point lights
71173       *   pointLight(color('#f00'), p5.Vector.fromAngles(t * 1.0, t * 1.3, 100));
71174       *   pointLight(color('#0f0'), p5.Vector.fromAngles(t * 1.1, t * 1.2, 100));
71175       *   pointLight(color('#00f'), p5.Vector.fromAngles(t * 1.2, t * 1.1, 100));
71176       *
71177       *   sphere(35);
71178       * }
71179       * </code>
71180       * </div>
71181       */
71182
71183
71184      p5.Vector.fromAngles = function (theta, phi, length) {
71185        if (typeof length === 'undefined') {
71186          length = 1;
71187        }
71188
71189        var cosPhi = Math.cos(phi);
71190        var sinPhi = Math.sin(phi);
71191        var cosTheta = Math.cos(theta);
71192        var sinTheta = Math.sin(theta);
71193        return new p5.Vector(length * sinTheta * sinPhi, -length * cosTheta, length * sinTheta * cosPhi);
71194      };
71195      /**
71196       * Make a new 2D unit vector from a random angle
71197       *
71198       * @method random2D
71199       * @static
71200       * @return {p5.Vector} the new <a href="#/p5.Vector">p5.Vector</a> object
71201       * @example
71202       * <div class="norender">
71203       * <code>
71204       * let v = p5.Vector.random2D();
71205       * // May make v's attributes something like:
71206       * // [0.61554617, -0.51195765, 0.0] or
71207       * // [-0.4695841, -0.14366731, 0.0] or
71208       * // [0.6091097, -0.22805278, 0.0]
71209       * print(v);
71210       * </code>
71211       * </div>
71212       *
71213       * <div>
71214       * <code>
71215       * function setup() {
71216       *   frameRate(1);
71217       * }
71218       *
71219       * function draw() {
71220       *   background(240);
71221       *
71222       *   let v0 = createVector(50, 50);
71223       *   let v1 = p5.Vector.random2D();
71224       *   drawArrow(v0, v1.mult(50), 'black');
71225       * }
71226       *
71227       * // draw an arrow for a vector at a given base position
71228       * function drawArrow(base, vec, myColor) {
71229       *   push();
71230       *   stroke(myColor);
71231       *   strokeWeight(3);
71232       *   fill(myColor);
71233       *   translate(base.x, base.y);
71234       *   line(0, 0, vec.x, vec.y);
71235       *   rotate(vec.heading());
71236       *   let arrowSize = 7;
71237       *   translate(vec.mag() - arrowSize, 0);
71238       *   triangle(0, arrowSize / 2, 0, -arrowSize / 2, arrowSize, 0);
71239       *   pop();
71240       * }
71241       * </code>
71242       * </div>
71243       */
71244
71245
71246      p5.Vector.random2D = function random2D() {
71247        return this.fromAngle(Math.random() * constants.TWO_PI);
71248      };
71249      /**
71250       * Make a new random 3D unit vector.
71251       *
71252       * @method random3D
71253       * @static
71254       * @return {p5.Vector} the new <a href="#/p5.Vector">p5.Vector</a> object
71255       * @example
71256       * <div class="norender">
71257       * <code>
71258       * let v = p5.Vector.random3D();
71259       * // May make v's attributes something like:
71260       * // [0.61554617, -0.51195765, 0.599168] or
71261       * // [-0.4695841, -0.14366731, -0.8711202] or
71262       * // [0.6091097, -0.22805278, -0.7595902]
71263       * print(v);
71264       * </code>
71265       * </div>
71266       */
71267
71268
71269      p5.Vector.random3D = function random3D() {
71270        var angle = Math.random() * constants.TWO_PI;
71271        var vz = Math.random() * 2 - 1;
71272        var vzBase = Math.sqrt(1 - vz * vz);
71273        var vx = vzBase * Math.cos(angle);
71274        var vy = vzBase * Math.sin(angle);
71275        return new p5.Vector(vx, vy, vz);
71276      }; // Adds two vectors together and returns a new one.
71277
71278      /**
71279       * @method add
71280       * @static
71281       * @param  {p5.Vector} v1 a <a href="#/p5.Vector">p5.Vector</a> to add
71282       * @param  {p5.Vector} v2 a <a href="#/p5.Vector">p5.Vector</a> to add
71283       * @param  {p5.Vector} target the vector to receive the result
71284       */
71285
71286      /**
71287       * @method add
71288       * @static
71289       * @param  {p5.Vector} v1
71290       * @param  {p5.Vector} v2
71291       * @return {p5.Vector} the resulting <a href="#/p5.Vector">p5.Vector</a>
71292       *
71293       */
71294
71295
71296      p5.Vector.add = function add(v1, v2, target) {
71297        if (!target) {
71298          target = v1.copy();
71299        } else {
71300          target.set(v1);
71301        }
71302
71303        target.add(v2);
71304        return target;
71305      };
71306      /*
71307       * Subtracts one <a href="#/p5.Vector">p5.Vector</a> from another and returns a new one.  The second
71308       * vector (v2) is subtracted from the first (v1), resulting in v1-v2.
71309       */
71310
71311      /**
71312       * @method sub
71313       * @static
71314       * @param  {p5.Vector} v1 a <a href="#/p5.Vector">p5.Vector</a> to subtract from
71315       * @param  {p5.Vector} v2 a <a href="#/p5.Vector">p5.Vector</a> to subtract
71316       * @param  {p5.Vector} target if undefined a new vector will be created
71317       */
71318
71319      /**
71320       * @method sub
71321       * @static
71322       * @param  {p5.Vector} v1
71323       * @param  {p5.Vector} v2
71324       * @return {p5.Vector} the resulting <a href="#/p5.Vector">p5.Vector</a>
71325       */
71326
71327
71328      p5.Vector.sub = function sub(v1, v2, target) {
71329        if (!target) {
71330          target = v1.copy();
71331        } else {
71332          target.set(v1);
71333        }
71334
71335        target.sub(v2);
71336        return target;
71337      };
71338      /**
71339       * Multiplies a vector by a scalar and returns a new vector.
71340       */
71341
71342      /**
71343       * @method mult
71344       * @static
71345       * @param  {p5.Vector} v the vector to multiply
71346       * @param  {Number}  n
71347       * @param  {p5.Vector} target if undefined a new vector will be created
71348       */
71349
71350      /**
71351       * @method mult
71352       * @static
71353       * @param  {p5.Vector} v
71354       * @param  {Number}  n
71355       * @return {p5.Vector}  the resulting new <a href="#/p5.Vector">p5.Vector</a>
71356       */
71357
71358
71359      p5.Vector.mult = function mult(v, n, target) {
71360        if (!target) {
71361          target = v.copy();
71362        } else {
71363          target.set(v);
71364        }
71365
71366        target.mult(n);
71367        return target;
71368      };
71369      /**
71370       * Divides a vector by a scalar and returns a new vector.
71371       */
71372
71373      /**
71374       * @method div
71375       * @static
71376       * @param  {p5.Vector} v the vector to divide
71377       * @param  {Number}  n
71378       * @param  {p5.Vector} target if undefined a new vector will be created
71379       */
71380
71381      /**
71382       * @method div
71383       * @static
71384       * @param  {p5.Vector} v
71385       * @param  {Number}  n
71386       * @return {p5.Vector} the resulting new <a href="#/p5.Vector">p5.Vector</a>
71387       */
71388
71389
71390      p5.Vector.div = function div(v, n, target) {
71391        if (!target) {
71392          target = v.copy();
71393        } else {
71394          target.set(v);
71395        }
71396
71397        target.div(n);
71398        return target;
71399      };
71400      /**
71401       * Calculates the dot product of two vectors.
71402       */
71403
71404      /**
71405       * @method dot
71406       * @static
71407       * @param  {p5.Vector} v1 the first <a href="#/p5.Vector">p5.Vector</a>
71408       * @param  {p5.Vector} v2 the second <a href="#/p5.Vector">p5.Vector</a>
71409       * @return {Number}     the dot product
71410       */
71411
71412
71413      p5.Vector.dot = function dot(v1, v2) {
71414        return v1.dot(v2);
71415      };
71416      /**
71417       * Calculates the cross product of two vectors.
71418       */
71419
71420      /**
71421       * @method cross
71422       * @static
71423       * @param  {p5.Vector} v1 the first <a href="#/p5.Vector">p5.Vector</a>
71424       * @param  {p5.Vector} v2 the second <a href="#/p5.Vector">p5.Vector</a>
71425       * @return {Number}     the cross product
71426       */
71427
71428
71429      p5.Vector.cross = function cross(v1, v2) {
71430        return v1.cross(v2);
71431      };
71432      /**
71433       * Calculates the Euclidean distance between two points (considering a
71434       * point as a vector object).
71435       */
71436
71437      /**
71438       * @method dist
71439       * @static
71440       * @param  {p5.Vector} v1 the first <a href="#/p5.Vector">p5.Vector</a>
71441       * @param  {p5.Vector} v2 the second <a href="#/p5.Vector">p5.Vector</a>
71442       * @return {Number}     the distance
71443       */
71444
71445
71446      p5.Vector.dist = function dist(v1, v2) {
71447        return v1.dist(v2);
71448      };
71449      /**
71450       * Linear interpolate a vector to another vector and return the result as a
71451       * new vector.
71452       */
71453
71454      /**
71455       * @method lerp
71456       * @static
71457       * @param {p5.Vector} v1
71458       * @param {p5.Vector} v2
71459       * @param {Number} amt
71460       * @param {p5.Vector} target if undefined a new vector will be created
71461       */
71462
71463      /**
71464       * @method lerp
71465       * @static
71466       * @param {p5.Vector} v1
71467       * @param {p5.Vector} v2
71468       * @param {Number} amt
71469       * @return {Number}      the lerped value
71470       */
71471
71472
71473      p5.Vector.lerp = function lerp(v1, v2, amt, target) {
71474        if (!target) {
71475          target = v1.copy();
71476        } else {
71477          target.set(v1);
71478        }
71479
71480        target.lerp(v2, amt);
71481        return target;
71482      };
71483      /**
71484       * @method mag
71485       * @param {p5.Vector} vecT the vector to return the magnitude of
71486       * @return {Number}        the magnitude of vecT
71487       * @static
71488       */
71489
71490
71491      p5.Vector.mag = function mag(vecT) {
71492        var x = vecT.x,
71493            y = vecT.y,
71494            z = vecT.z;
71495        var magSq = x * x + y * y + z * z;
71496        return Math.sqrt(magSq);
71497      };
71498
71499      module.exports = p5.Vector;
71500    }, {
71501      "../core/constants": 18,
71502      "../core/main": 24
71503    }],
71504    55: [function (_dereq_, module, exports) {
71505      /**
71506       * @module Math
71507       * @submodule Random
71508       * @for p5
71509       * @requires core
71510       */
71511      'use strict';
71512
71513      var p5 = _dereq_('../core/main');
71514
71515      var seeded = false;
71516      var previous = false;
71517      var y2 = 0; // Linear Congruential Generator
71518      // Variant of a Lehman Generator
71519
71520      var lcg = function () {
71521        // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes
71522        // m is basically chosen to be large (as it is the max period)
71523        // and for its relationships to a and c
71524        var m = 4294967296,
71525            // a - 1 should be divisible by m's prime factors
71526        a = 1664525,
71527            // c and m should be co-prime
71528        c = 1013904223,
71529            seed,
71530            z;
71531        return {
71532          setSeed: function (val) {
71533            // pick a random seed if val is undefined or null
71534            // the >>> 0 casts the seed to an unsigned 32-bit integer
71535            z = seed = (val == null ? Math.random() * m : val) >>> 0;
71536          },
71537          getSeed: function () {
71538            return seed;
71539          },
71540          rand: function () {
71541            // define the recurrence relationship
71542            z = (a * z + c) % m; // return a float in [0, 1)
71543            // if z = m then z / m = 0 therefore (z % m) / m < 1 always
71544
71545            return z / m;
71546          }
71547        };
71548      }();
71549      /**
71550       * Sets the seed value for <a href="#/p5/random">random()</a>.
71551       *
71552       * By default, <a href="#/p5/random">random()</a> produces different results each time the program
71553       * is run. Set the seed parameter to a constant to return the same
71554       * pseudo-random numbers each time the software is run.
71555       *
71556       * @method randomSeed
71557       * @param {Number} seed   the seed value
71558       * @example
71559       * <div>
71560       * <code>
71561       * randomSeed(99);
71562       * for (let i = 0; i < 100; i++) {
71563       *   let r = random(0, 255);
71564       *   stroke(r);
71565       *   line(i, 0, i, 100);
71566       * }
71567       * </code>
71568       * </div>
71569       *
71570       * @alt
71571       * many vertical lines drawn in white, black or grey.
71572       *
71573       */
71574
71575
71576      p5.prototype.randomSeed = function (seed) {
71577        lcg.setSeed(seed);
71578        seeded = true;
71579        previous = false;
71580      };
71581      /**
71582       * Return a random floating-point number.
71583       *
71584       * Takes either 0, 1 or 2 arguments.
71585       *
71586       * If no argument is given, returns a random number from 0
71587       * up to (but not including) 1.
71588       *
71589       * If one argument is given and it is a number, returns a random number from 0
71590       * up to (but not including) the number.
71591       *
71592       * If one argument is given and it is an array, returns a random element from
71593       * that array.
71594       *
71595       * If two arguments are given, returns a random number from the
71596       * first argument up to (but not including) the second argument.
71597       *
71598       * @method random
71599       * @param  {Number} [min]   the lower bound (inclusive)
71600       * @param  {Number} [max]   the upper bound (exclusive)
71601       * @return {Number} the random number
71602       * @example
71603       * <div>
71604       * <code>
71605       * for (let i = 0; i < 100; i++) {
71606       *   let r = random(50);
71607       *   stroke(r * 5);
71608       *   line(50, i, 50 + r, i);
71609       * }
71610       * </code>
71611       * </div>
71612       * <div>
71613       * <code>
71614       * for (let i = 0; i < 100; i++) {
71615       *   let r = random(-50, 50);
71616       *   line(50, i, 50 + r, i);
71617       * }
71618       * </code>
71619       * </div>
71620       * <div>
71621       * <code>
71622       * // Get a random element from an array using the random(Array) syntax
71623       * let words = ['apple', 'bear', 'cat', 'dog'];
71624       * let word = random(words); // select random word
71625       * text(word, 10, 50); // draw the word
71626       * </code>
71627       * </div>
71628       *
71629       * @alt
71630       * 100 horizontal lines from center canvas to right. size+fill change each time
71631       * 100 horizontal lines from center of canvas. height & side change each render
71632       * word displayed at random. Either apple, bear, cat, or dog
71633       *
71634       */
71635
71636      /**
71637       * @method random
71638       * @param  {Array} choices   the array to choose from
71639       * @return {*} the random element from the array
71640       * @example
71641       */
71642
71643
71644      p5.prototype.random = function (min, max) {
71645        var rand;
71646
71647        if (seeded) {
71648          rand = lcg.rand();
71649        } else {
71650          rand = Math.random();
71651        }
71652
71653        if (typeof min === 'undefined') {
71654          return rand;
71655        } else if (typeof max === 'undefined') {
71656          if (min instanceof Array) {
71657            return min[Math.floor(rand * min.length)];
71658          } else {
71659            return rand * min;
71660          }
71661        } else {
71662          if (min > max) {
71663            var tmp = min;
71664            min = max;
71665            max = tmp;
71666          }
71667
71668          return rand * (max - min) + min;
71669        }
71670      };
71671      /**
71672       *
71673       * Returns a random number fitting a Gaussian, or
71674       * normal, distribution. There is theoretically no minimum or maximum
71675       * value that <a href="#/p5/randomGaussian">randomGaussian()</a> might return. Rather, there is
71676       * just a very low probability that values far from the mean will be
71677       * returned; and a higher probability that numbers near the mean will
71678       * be returned.
71679       * <br><br>
71680       * Takes either 0, 1 or 2 arguments.<br>
71681       * If no args, returns a mean of 0 and standard deviation of 1.<br>
71682       * If one arg, that arg is the mean (standard deviation is 1).<br>
71683       * If two args, first is mean, second is standard deviation.
71684       *
71685       * @method randomGaussian
71686       * @param  {Number} mean  the mean
71687       * @param  {Number} sd    the standard deviation
71688       * @return {Number} the random number
71689       * @example
71690       * <div>
71691       * <code>
71692       * for (let y = 0; y < 100; y++) {
71693       *   let x = randomGaussian(50, 15);
71694       *   line(50, y, x, y);
71695       * }
71696       * </code>
71697       * </div>
71698       * <div>
71699       * <code>
71700       * let distribution = new Array(360);
71701       *
71702       * function setup() {
71703       *   createCanvas(100, 100);
71704       *   for (let i = 0; i < distribution.length; i++) {
71705       *     distribution[i] = floor(randomGaussian(0, 15));
71706       *   }
71707       * }
71708       *
71709       * function draw() {
71710       *   background(204);
71711       *
71712       *   translate(width / 2, width / 2);
71713       *
71714       *   for (let i = 0; i < distribution.length; i++) {
71715       *     rotate(TWO_PI / distribution.length);
71716       *     stroke(0);
71717       *     let dist = abs(distribution[i]);
71718       *     line(0, 0, dist, 0);
71719       *   }
71720       * }
71721       * </code>
71722       * </div>
71723       * @alt
71724       * 100 horizontal lines from center of canvas. height & side change each render
71725       * black lines radiate from center of canvas. size determined each render
71726       */
71727
71728
71729      p5.prototype.randomGaussian = function (mean, sd) {
71730        var y1, x1, x2, w;
71731
71732        if (previous) {
71733          y1 = y2;
71734          previous = false;
71735        } else {
71736          do {
71737            x1 = this.random(2) - 1;
71738            x2 = this.random(2) - 1;
71739            w = x1 * x1 + x2 * x2;
71740          } while (w >= 1);
71741
71742          w = Math.sqrt(-2 * Math.log(w) / w);
71743          y1 = x1 * w;
71744          y2 = x2 * w;
71745          previous = true;
71746        }
71747
71748        var m = mean || 0;
71749        var s = sd || 1;
71750        return y1 * s + m;
71751      };
71752
71753      module.exports = p5;
71754    }, {
71755      "../core/main": 24
71756    }],
71757    56: [function (_dereq_, module, exports) {
71758      /**
71759       * @module Math
71760       * @submodule Trigonometry
71761       * @for p5
71762       * @requires core
71763       * @requires constants
71764       */
71765      'use strict';
71766
71767      var p5 = _dereq_('../core/main');
71768
71769      var constants = _dereq_('../core/constants');
71770      /*
71771       * all DEGREES/RADIANS conversion should be done in the p5 instance
71772       * if possible, using the p5._toRadians(), p5._fromRadians() methods.
71773       */
71774
71775
71776      p5.prototype._angleMode = constants.RADIANS;
71777      /**
71778       * The inverse of <a href="#/p5/cos">cos()</a>, returns the arc cosine of a value. This function
71779       * expects the values in the range of -1 to 1 and values are returned in
71780       * the range 0 to PI (3.1415927).
71781       *
71782       * @method acos
71783       * @param  {Number} value the value whose arc cosine is to be returned
71784       * @return {Number}       the arc cosine of the given value
71785       *
71786       * @example
71787       * <div class= “norender">
71788       * <code>
71789       * let a = PI;
71790       * let c = cos(a);
71791       * let ac = acos(c);
71792       * // Prints: "3.1415927 : -1.0 : 3.1415927"
71793       * print(a + ' : ' + c + ' : ' + ac);
71794       * </code>
71795       * </div>
71796       *
71797       * <div class= “norender">
71798       * <code>
71799       * let a = PI + PI / 4.0;
71800       * let c = cos(a);
71801       * let ac = acos(c);
71802       * // Prints: "3.926991 : -0.70710665 : 2.3561943"
71803       * print(a + ' : ' + c + ' : ' + ac);
71804       * </code>
71805       * </div>
71806       */
71807
71808      p5.prototype.acos = function (ratio) {
71809        return this._fromRadians(Math.acos(ratio));
71810      };
71811      /**
71812       * The inverse of <a href="#/p5/sin">sin()</a>, returns the arc sine of a value. This function
71813       * expects the values in the range of -1 to 1 and values are returned
71814       * in the range -PI/2 to PI/2.
71815       *
71816       * @method asin
71817       * @param  {Number} value the value whose arc sine is to be returned
71818       * @return {Number}       the arc sine of the given value
71819       *
71820       * @example
71821       * <div class= “norender">
71822       * <code>
71823       * let a = PI + PI / 3;
71824       * let s = sin(a);
71825       * let as = asin(s);
71826       * // Prints: "1.0471976 : 0.86602545 : 1.0471976"
71827       * print(a + ' : ' + s + ' : ' + as);
71828       * </code>
71829       * </div>
71830       *
71831       * <div class= “norender">
71832       * <code>
71833       * let a = PI + PI / 3.0;
71834       * let s = sin(a);
71835       * let as = asin(s);
71836       * // Prints: "4.1887903 : -0.86602545 : -1.0471976"
71837       * print(a + ' : ' + s + ' : ' + as);
71838       * </code>
71839       * </div>
71840       *
71841       */
71842
71843
71844      p5.prototype.asin = function (ratio) {
71845        return this._fromRadians(Math.asin(ratio));
71846      };
71847      /**
71848       * The inverse of <a href="#/p5/tan">tan()</a>, returns the arc tangent of a value. This function
71849       * expects the values in the range of -Infinity to Infinity (exclusive) and
71850       * values are returned in the range -PI/2 to PI/2.
71851       *
71852       * @method atan
71853       * @param  {Number} value the value whose arc tangent is to be returned
71854       * @return {Number}       the arc tangent of the given value
71855       *
71856       * @example
71857       * <div class= “norender">
71858       * <code>
71859       * let a = PI + PI / 3;
71860       * let t = tan(a);
71861       * let at = atan(t);
71862       * // Prints: "1.0471976 : 1.7320509 : 1.0471976"
71863       * print(a + ' : ' + t + ' : ' + at);
71864       * </code>
71865       * </div>
71866       *
71867       * <div class= “norender">
71868       * <code>
71869       * let a = PI + PI / 3.0;
71870       * let t = tan(a);
71871       * let at = atan(t);
71872       * // Prints: "4.1887903 : 1.7320513 : 1.0471977"
71873       * print(a + ' : ' + t + ' : ' + at);
71874       * </code>
71875       * </div>
71876       *
71877       */
71878
71879
71880      p5.prototype.atan = function (ratio) {
71881        return this._fromRadians(Math.atan(ratio));
71882      };
71883      /**
71884       * Calculates the angle (in radians) from a specified point to the coordinate
71885       * origin as measured from the positive x-axis. Values are returned as a
71886       * float in the range from PI to -PI. The atan2<a href="#/p5/">()</a> function is most often used
71887       * for orienting geometry to the position of the cursor.
71888       * <br><br>
71889       * Note: The y-coordinate of the point is the first parameter, and the
71890       * x-coordinate is the second parameter, due the the structure of calculating
71891       * the tangent.
71892       *
71893       * @method atan2
71894       * @param  {Number} y y-coordinate of the point
71895       * @param  {Number} x x-coordinate of the point
71896       * @return {Number}   the arc tangent of the given point
71897       *
71898       * @example
71899       * <div>
71900       * <code>
71901       * function draw() {
71902       *   background(204);
71903       *   translate(width / 2, height / 2);
71904       *   let a = atan2(mouseY - height / 2, mouseX - width / 2);
71905       *   rotate(a);
71906       *   rect(-30, -5, 60, 10);
71907       * }
71908       * </code>
71909       * </div>
71910       *
71911       * @alt
71912       * 60 by 10 rect at center of canvas rotates with mouse movements
71913       *
71914       */
71915
71916
71917      p5.prototype.atan2 = function (y, x) {
71918        return this._fromRadians(Math.atan2(y, x));
71919      };
71920      /**
71921       * Calculates the cosine of an angle. This function takes into account the
71922       * current <a href="#/p5/angleMode">angleMode</a>. Values are returned in the range -1 to 1.
71923       *
71924       * @method cos
71925       * @param  {Number} angle the angle
71926       * @return {Number}       the cosine of the angle
71927       *
71928       * @example
71929       * <div>
71930       * <code>
71931       * let a = 0.0;
71932       * let inc = TWO_PI / 25.0;
71933       * for (let i = 0; i < 25; i++) {
71934       *   line(i * 4, 50, i * 4, 50 + cos(a) * 40.0);
71935       *   a = a + inc;
71936       * }
71937       * </code>
71938       * </div>
71939       *
71940       * @alt
71941       * vertical black lines form wave patterns, extend-down on left and right side
71942       *
71943       */
71944
71945
71946      p5.prototype.cos = function (angle) {
71947        return Math.cos(this._toRadians(angle));
71948      };
71949      /**
71950       * Calculates the sine of an angle. This function takes into account the
71951       * current <a href="#/p5/angleMode">angleMode</a>. Values are returned in the range -1 to 1.
71952       *
71953       * @method sin
71954       * @param  {Number} angle the angle
71955       * @return {Number}       the sine of the angle
71956       *
71957       * @example
71958       * <div>
71959       * <code>
71960       * let a = 0.0;
71961       * let inc = TWO_PI / 25.0;
71962       * for (let i = 0; i < 25; i++) {
71963       *   line(i * 4, 50, i * 4, 50 + sin(a) * 40.0);
71964       *   a = a + inc;
71965       * }
71966       * </code>
71967       * </div>
71968       *
71969       * @alt
71970       * vertical black lines extend down and up from center to form wave pattern
71971       *
71972       */
71973
71974
71975      p5.prototype.sin = function (angle) {
71976        return Math.sin(this._toRadians(angle));
71977      };
71978      /**
71979       * Calculates the tangent of an angle. This function takes into account
71980       * the current <a href="#/p5/angleMode">angleMode</a>. Values are returned in the range -1 to 1.
71981       *
71982       * @method tan
71983       * @param  {Number} angle the angle
71984       * @return {Number}       the tangent of the angle
71985       *
71986       * @example
71987       * <div>
71988       * <code>
71989       * let a = 0.0;
71990       * let inc = TWO_PI / 50.0;
71991       * for (let i = 0; i < 100; i = i + 2) {
71992       *   line(i, 50, i, 50 + tan(a) * 2.0);
71993       *   a = a + inc;
71994       * }
71995       * </code>
71996       *
71997       *
71998       * @alt
71999       * vertical black lines end down and up from center to form spike pattern
72000       *
72001       */
72002
72003
72004      p5.prototype.tan = function (angle) {
72005        return Math.tan(this._toRadians(angle));
72006      };
72007      /**
72008       * Converts a radian measurement to its corresponding value in degrees.
72009       * Radians and degrees are two ways of measuring the same thing. There are
72010       * 360 degrees in a circle and 2*PI radians in a circle. For example,
72011       * 90° = PI/2 = 1.5707964. This function does not take into account the
72012       * current <a href="#/p5/angleMode">angleMode</a>.
72013       *
72014       * @method degrees
72015       * @param  {Number} radians the radians value to convert to degrees
72016       * @return {Number}         the converted angle
72017       *
72018       *
72019       * @example
72020       * <div class= “norender">
72021       * <code>
72022       * let rad = PI / 4;
72023       * let deg = degrees(rad);
72024       * print(rad + ' radians is ' + deg + ' degrees');
72025       * // Prints: 0.7853981633974483 radians is 45 degrees
72026       * </code>
72027       * </div>
72028       *
72029       */
72030
72031
72032      p5.prototype.degrees = function (angle) {
72033        return angle * constants.RAD_TO_DEG;
72034      };
72035      /**
72036       * Converts a degree measurement to its corresponding value in radians.
72037       * Radians and degrees are two ways of measuring the same thing. There are
72038       * 360 degrees in a circle and 2*PI radians in a circle. For example,
72039       * 90° = PI/2 = 1.5707964. This function does not take into account the
72040       * current <a href="#/p5/angleMode">angleMode</a>.
72041       *
72042       * @method radians
72043       * @param  {Number} degrees the degree value to convert to radians
72044       * @return {Number}         the converted angle
72045       *
72046       * @example
72047       * <div class= “norender">
72048       * <code>
72049       * let deg = 45.0;
72050       * let rad = radians(deg);
72051       * print(deg + ' degrees is ' + rad + ' radians');
72052       * // Prints: 45 degrees is 0.7853981633974483 radians
72053       * </code>
72054       * </div>
72055       */
72056
72057
72058      p5.prototype.radians = function (angle) {
72059        return angle * constants.DEG_TO_RAD;
72060      };
72061      /**
72062       * Sets the current mode of p5 to given mode. Default mode is RADIANS.
72063       *
72064       * @method angleMode
72065       * @param {Constant} mode either RADIANS or DEGREES
72066       *
72067       * @example
72068       * <div>
72069       * <code>
72070       * function draw() {
72071       *   background(204);
72072       *   angleMode(DEGREES); // Change the mode to DEGREES
72073       *   let a = atan2(mouseY - height / 2, mouseX - width / 2);
72074       *   translate(width / 2, height / 2);
72075       *   push();
72076       *   rotate(a);
72077       *   rect(-20, -5, 40, 10); // Larger rectangle is rotating in degrees
72078       *   pop();
72079       *   angleMode(RADIANS); // Change the mode to RADIANS
72080       *   rotate(a); // variable a stays the same
72081       *   rect(-40, -5, 20, 10); // Smaller rectangle is rotating in radians
72082       * }
72083       * </code>
72084       * </div>
72085       *
72086       * @alt
72087       * 40 by 10 rect in center rotates with mouse moves. 20 by 10 rect moves faster.
72088       *
72089       *
72090       */
72091
72092
72093      p5.prototype.angleMode = function (mode) {
72094        if (mode === constants.DEGREES || mode === constants.RADIANS) {
72095          this._angleMode = mode;
72096        }
72097      };
72098      /**
72099       * converts angles from the current angleMode to RADIANS
72100       *
72101       * @method _toRadians
72102       * @private
72103       * @param {Number} angle
72104       * @returns {Number}
72105       */
72106
72107
72108      p5.prototype._toRadians = function (angle) {
72109        if (this._angleMode === constants.DEGREES) {
72110          return angle * constants.DEG_TO_RAD;
72111        }
72112
72113        return angle;
72114      };
72115      /**
72116       * converts angles from the current angleMode to DEGREES
72117       *
72118       * @method _toDegrees
72119       * @private
72120       * @param {Number} angle
72121       * @returns {Number}
72122       */
72123
72124
72125      p5.prototype._toDegrees = function (angle) {
72126        if (this._angleMode === constants.RADIANS) {
72127          return angle * constants.RAD_TO_DEG;
72128        }
72129
72130        return angle;
72131      };
72132      /**
72133       * converts angles from RADIANS into the current angleMode
72134       *
72135       * @method _fromRadians
72136       * @private
72137       * @param {Number} angle
72138       * @returns {Number}
72139       */
72140
72141
72142      p5.prototype._fromRadians = function (angle) {
72143        if (this._angleMode === constants.DEGREES) {
72144          return angle * constants.RAD_TO_DEG;
72145        }
72146
72147        return angle;
72148      };
72149
72150      module.exports = p5;
72151    }, {
72152      "../core/constants": 18,
72153      "../core/main": 24
72154    }],
72155    57: [function (_dereq_, module, exports) {
72156      /**
72157       * @module Typography
72158       * @submodule Attributes
72159       * @for p5
72160       * @requires core
72161       * @requires constants
72162       */
72163      'use strict';
72164
72165      var p5 = _dereq_('../core/main');
72166      /**
72167       * Sets the current alignment for drawing text. Accepts two
72168       * arguments: horizAlign (LEFT, CENTER, or RIGHT) and
72169       * vertAlign (TOP, BOTTOM, CENTER, or BASELINE).
72170       *
72171       * The horizAlign parameter is in reference to the x value
72172       * of the <a href="#/p5/text">text()</a> function, while the vertAlign parameter is
72173       * in reference to the y value.
72174       *
72175       * So if you write textAlign(LEFT), you are aligning the left
72176       * edge of your text to the x value you give in <a href="#/p5/text">text()</a>. If you
72177       * write textAlign(RIGHT, TOP), you are aligning the right edge
72178       * of your text to the x value and the top of edge of the text
72179       * to the y value.
72180       *
72181       * @method textAlign
72182       * @param {Constant} horizAlign horizontal alignment, either LEFT,
72183       *                            CENTER, or RIGHT
72184       * @param {Constant} [vertAlign] vertical alignment, either TOP,
72185       *                            BOTTOM, CENTER, or BASELINE
72186       * @chainable
72187       * @example
72188       * <div>
72189       * <code>
72190       * textSize(16);
72191       * textAlign(RIGHT);
72192       * text('ABCD', 50, 30);
72193       * textAlign(CENTER);
72194       * text('EFGH', 50, 50);
72195       * textAlign(LEFT);
72196       * text('IJKL', 50, 70);
72197       * </code>
72198       * </div>
72199       *
72200       * <div>
72201       * <code>
72202       * textSize(16);
72203       * strokeWeight(0.5);
72204       *
72205       * line(0, 12, width, 12);
72206       * textAlign(CENTER, TOP);
72207       * text('TOP', 0, 12, width);
72208       *
72209       * line(0, 37, width, 37);
72210       * textAlign(CENTER, CENTER);
72211       * text('CENTER', 0, 37, width);
72212       *
72213       * line(0, 62, width, 62);
72214       * textAlign(CENTER, BASELINE);
72215       * text('BASELINE', 0, 62, width);
72216       *
72217       * line(0, 87, width, 87);
72218       * textAlign(CENTER, BOTTOM);
72219       * text('BOTTOM', 0, 87, width);
72220       * </code>
72221       * </div>
72222       *
72223       * @alt
72224       *Letters ABCD displayed at top right, EFGH at center and IJKL at bottom left.
72225       * The names of the four vertical alignments rendered each showing that alignment's placement relative to a horizontal line.
72226       *
72227       */
72228
72229      /**
72230       * @method textAlign
72231       * @return {Object}
72232       */
72233
72234
72235      p5.prototype.textAlign = function (horizAlign, vertAlign) {
72236        p5._validateParameters('textAlign', arguments);
72237
72238        return this._renderer.textAlign.apply(this._renderer, arguments);
72239      };
72240      /**
72241       * Sets/gets the spacing, in pixels, between lines of text. This
72242       * setting will be used in all subsequent calls to the <a href="#/p5/text">text()</a> function.
72243       *
72244       * @method textLeading
72245       * @param {Number} leading the size in pixels for spacing between lines
72246       * @chainable
72247       *
72248       * @example
72249       * <div>
72250       * <code>
72251       * // Text to display. The "\n" is a "new line" character
72252       * let lines = 'L1\nL2\nL3';
72253       * textSize(12);
72254       *
72255       * textLeading(10); // Set leading to 10
72256       * text(lines, 10, 25);
72257       *
72258       * textLeading(20); // Set leading to 20
72259       * text(lines, 40, 25);
72260       *
72261       * textLeading(30); // Set leading to 30
72262       * text(lines, 70, 25);
72263       * </code>
72264       * </div>
72265       *
72266       * @alt
72267       *set L1 L2 & L3 displayed vertically 3 times. spacing increases for each set
72268       */
72269
72270      /**
72271       * @method textLeading
72272       * @return {Number}
72273       */
72274
72275
72276      p5.prototype.textLeading = function (theLeading) {
72277        p5._validateParameters('textLeading', arguments);
72278
72279        return this._renderer.textLeading.apply(this._renderer, arguments);
72280      };
72281      /**
72282       * Sets/gets the current font size. This size will be used in all subsequent
72283       * calls to the <a href="#/p5/text">text()</a> function. Font size is measured in pixels.
72284       *
72285       * @method textSize
72286       * @param {Number} theSize the size of the letters in units of pixels
72287       * @chainable
72288       *
72289       * @example
72290       * <div>
72291       * <code>
72292       * textSize(12);
72293       * text('Font Size 12', 10, 30);
72294       * textSize(14);
72295       * text('Font Size 14', 10, 60);
72296       * textSize(16);
72297       * text('Font Size 16', 10, 90);
72298       * </code>
72299       * </div>
72300       *
72301       * @alt
72302       *Font Size 12 displayed small, Font Size 14 medium & Font Size 16 large
72303       */
72304
72305      /**
72306       * @method textSize
72307       * @return {Number}
72308       */
72309
72310
72311      p5.prototype.textSize = function (theSize) {
72312        p5._validateParameters('textSize', arguments);
72313
72314        return this._renderer.textSize.apply(this._renderer, arguments);
72315      };
72316      /**
72317       * Sets/gets the style of the text for system fonts to NORMAL, ITALIC, BOLD or BOLDITALIC.
72318       * Note: this may be is overridden by CSS styling. For non-system fonts
72319       * (opentype, truetype, etc.) please load styled fonts instead.
72320       *
72321       * @method textStyle
72322       * @param {Constant} theStyle styling for text, either NORMAL,
72323       *                            ITALIC, BOLD or BOLDITALIC
72324       * @chainable
72325       * @example
72326       * <div>
72327       * <code>
72328       * strokeWeight(0);
72329       * textSize(12);
72330       * textStyle(NORMAL);
72331       * text('Font Style Normal', 10, 15);
72332       * textStyle(ITALIC);
72333       * text('Font Style Italic', 10, 40);
72334       * textStyle(BOLD);
72335       * text('Font Style Bold', 10, 65);
72336       * textStyle(BOLDITALIC);
72337       * text('Font Style Bold Italic', 10, 90);
72338       * </code>
72339       * </div>
72340       *
72341       * @alt
72342       *words Font Style Normal displayed normally, Italic in italic, bold in bold and bold italic in bold italics.
72343       */
72344
72345      /**
72346       * @method textStyle
72347       * @return {String}
72348       */
72349
72350
72351      p5.prototype.textStyle = function (theStyle) {
72352        p5._validateParameters('textStyle', arguments);
72353
72354        return this._renderer.textStyle.apply(this._renderer, arguments);
72355      };
72356      /**
72357       * Calculates and returns the width of any character or text str
72357ing.
72358       *
72359       * @method textWidth
72360       * @param {String} theText the String of characters to measure
72361       * @return {Number}
72362       * @example
72363       * <div>
72364       * <code>
72365       * textSize(28);
72366       *
72367       * let aChar = 'P';
72368       * let cWidth = textWidth(aChar);
72369       * text(aChar, 0, 40);
72370       * line(cWidth, 0, cWidth, 50);
72371       *
72372       * let aString = 'p5.js';
72373       * let sWidth = textWidth(aString);
72374       * text(aString, 0, 85);
72375       * line(sWidth, 50, sWidth, 100);
72376       * </code>
72377       * </div>
72378       *
72379       * @alt
72380       *Letter P and p5.js are displayed with vertical lines at end. P is wide
72381       *
72382       */
72383
72384
72385      p5.prototype.textWidth = function (theText) {
72386        p5._validateParameters('textWidth', arguments);
72387
72388        if (theText.length === 0) {
72389          return 0;
72390        }
72391
72392        return this._renderer.textWidth.apply(this._renderer, arguments);
72393      };
72394      /**
72395       * Returns the ascent of the current font at its current size. The ascent
72396       * represents the distance, in pixels, of the tallest character above
72397       * the baseline.
72398       * @method textAscent
72399       * @return {Number}
72400       * @example
72401       * <div>
72402       * <code>
72403       * let base = height * 0.75;
72404       * let scalar = 0.8; // Different for each font
72405       *
72406       * textSize(32); // Set initial text size
72407       * let asc = textAscent() * scalar; // Calc ascent
72408       * line(0, base - asc, width, base - asc);
72409       * text('dp', 0, base); // Draw text on baseline
72410       *
72411       * textSize(64); // Increase text size
72412       * asc = textAscent() * scalar; // Recalc ascent
72413       * line(40, base - asc, width, base - asc);
72414       * text('dp', 40, base); // Draw text on baseline
72415       * </code>
72416       * </div>
72417       */
72418
72419
72420      p5.prototype.textAscent = function () {
72421        p5._validateParameters('textAscent', arguments);
72422
72423        return this._renderer.textAscent();
72424      };
72425      /**
72426       * Returns the descent of the current font at its current size. The descent
72427       * represents the distance, in pixels, of the character with the longest
72428       * descender below the baseline.
72429       * @method textDescent
72430       * @return {Number}
72431       * @example
72432       * <div>
72433       * <code>
72434       * let base = height * 0.75;
72435       * let scalar = 0.8; // Different for each font
72436       *
72437       * textSize(32); // Set initial text size
72438       * let desc = textDescent() * scalar; // Calc ascent
72439       * line(0, base + desc, width, base + desc);
72440       * text('dp', 0, base); // Draw text on baseline
72441       *
72442       * textSize(64); // Increase text size
72443       * desc = textDescent() * scalar; // Recalc ascent
72444       * line(40, base + desc, width, base + desc);
72445       * text('dp', 40, base); // Draw text on baseline
72446       * </code>
72447       * </div>
72448       */
72449
72450
72451      p5.prototype.textDescent = function () {
72452        p5._validateParameters('textDescent', arguments);
72453
72454        return this._renderer.textDescent();
72455      };
72456      /**
72457       * Helper function to measure ascent and descent.
72458       */
72459
72460
72461      p5.prototype._updateTextMetrics = function () {
72462        return this._renderer._updateTextMetrics();
72463      };
72464
72465      module.exports = p5;
72466    }, {
72467      "../core/main": 24
72468    }],
72469    58: [function (_dereq_, module, exports) {
72470      /**
72471       * @module Typography
72472       * @submodule Loading & Displaying
72473       * @for p5
72474       * @requires core
72475       */
72476      'use strict';
72477
72478      var p5 = _dereq_('../core/main');
72479
72480      var constants = _dereq_('../core/constants');
72481
72482      var opentype = _dereq_('opentype.js');
72483
72484      _dereq_('../core/error_helpers');
72485      /**
72486       * Loads an opentype font file (.otf, .ttf) from a file or a URL,
72487       * and returns a PFont Object. This method is asynchronous,
72488       * meaning it may not finish before the next line in your sketch
72489       * is executed.
72490       * <br><br>
72491       * The path to the font should be relative to the HTML file
72492       * that links in your sketch. Loading fonts from a URL or other
72493       * remote location may be blocked due to your browser's built-in
72494       * security.
72495       *
72496       * @method loadFont
72497       * @param  {String}        path       name of the file or url to load
72498       * @param  {Function}      [callback] function to be executed after
72499       *                                    <a href="#/p5/loadFont">loadFont()</a> completes
72500       * @param  {Function}      [onError]  function to be executed if
72501       *                                    an error occurs
72502       * @return {p5.Font}                  <a href="#/p5.Font">p5.Font</a> object
72503       * @example
72504       *
72505       * <p>Calling loadFont() inside <a href="#/p5/preload">preload()</a> guarantees that the load
72506       * operation will have completed before <a href="#/p5/setup">setup()</a> and <a href="#/p5/draw">draw()</a> are called.</p>
72507       *
72508       * <div><code>
72509       * let myFont;
72510       * function preload() {
72511       *   myFont = loadFont('assets/AvenirNextLTPro-Demi.otf');
72512       * }
72513       *
72514       * function setup() {
72515       *   fill('#ED225D');
72516       *   textFont(myFont);
72517       *   textSize(36);
72518       *   text('p5*js', 10, 50);
72519       * }
72520       * </code></div>
72521       *
72522       * Outside of <a href="#/p5/preload">preload()</a>, you may supply a callback function to handle the
72523       * object:
72524       *
72525       * <div><code>
72526       * function setup() {
72527       *   loadFont('assets/AvenirNextLTPro-Demi.otf', drawText);
72528       * }
72529       *
72530       * function drawText(font) {
72531       *   fill('#ED225D');
72532       *   textFont(font, 36);
72533       *   text('p5*js', 10, 50);
72534       * }
72535       * </code></div>
72536       *
72537       * <p>You can also use the font filename string (without the file extension) to style other HTML
72538       * elements.</p>
72539       *
72540       * <div><code>
72541       * function preload() {
72542       *   loadFont('assets/Avenir.otf');
72543       * }
72544       *
72545       * function setup() {
72546       *   let myDiv = createDiv('hello there');
72547       *   myDiv.style('font-family', 'Avenir');
72548       * }
72549       * </code></div>
72550       *
72551       * @alt
72552       * p5*js in p5's theme dark pink
72553       * p5*js in p5's theme dark pink
72554       *
72555       */
72556
72557
72558      p5.prototype.loadFont = function (path, onSuccess, onError) {
72559        p5._validateParameters('loadFont', arguments);
72560
72561        var p5Font = new p5.Font(this);
72562        var self = this;
72563        opentype.load(path, function (err, font) {
72564          if (err) {
72565            p5._friendlyFileLoadError(4, path);
72566
72567            if (typeof onError !== 'undefined') {
72568              return onError(err);
72569            }
72570
72571            console.error(err, path);
72572            return;
72573          }
72574
72575          p5Font.font = font;
72576
72577          if (typeof onSuccess !== 'undefined') {
72578            onSuccess(p5Font);
72579          }
72580
72581          self._decrementPreload(); // check that we have an acceptable font type
72582
72583
72584          var validFontTypes = ['ttf', 'otf', 'woff', 'woff2'],
72585              fileNoPath = path.split('\\').pop().split('/').pop(),
72586              lastDotIdx = fileNoPath.lastIndexOf('.'),
72587              fontFamily,
72588              newStyle,
72589              fileExt = lastDotIdx < 1 ? null : fileNoPath.substr(lastDotIdx + 1); // if so, add it to the DOM (name-only) for use with p5.dom
72590
72591          if (validFontTypes.indexOf(fileExt) > -1) {
72592            fontFamily = fileNoPath.substr(0, lastDotIdx);
72593            newStyle = document.createElement('style');
72594            newStyle.appendChild(document.createTextNode('\n@font-face {' + '\nfont-family: ' + fontFamily + ';\nsrc: url(' + path + ');\n}\n'));
72595            document.head.appendChild(newStyle);
72596          }
72597        });
72598        return p5Font;
72599      };
72600      /**
72601       * Draws text to the screen. Displays the information specified in the first
72602       * parameter on the screen in the position specified by the additional
72603       * parameters. A default font will be used unless a font is set with the
72604       * <a href="#/p5/textFont">textFont()</a> function and a default size will be used unless a font is set
72605       * with <a href="#/p5/textSize">textSize()</a>. Change the color of the text with the <a href="#/p5/fill">fill()</a> function.
72606       * Change the outline of the text with the <a href="#/p5/stroke">stroke()</a> and <a href="#/p5/strokeWeight">
72606strokeWeight()</a>
72607       * functions.
72608       * <br><br>
72609       * The text displays in relation to the <a href="#/p5/textAlign">textAlign()</a> function, which gives the
72610       * option to draw to the left, right, and center of the coordinates.
72611       * <br><br>
72612       * The x2 and y2 parameters define a rectangular area to display within and
72613       * may only be used with string data. When these parameters are specified,
72614       * they are interpreted based on the current <a href="#/p5/rectMode">rectMode()</a> setting. Text that
72615       * does not fit completely within the rectangle specified will not be drawn
72616       * to the screen. If x2 and y2 are not specified, the baseline alignment is the
72617       * default, which means that the text will be drawn upwards from x and y.
72618       * <br><br>
72619       * <b>WEBGL</b>: Only opentype/truetype fonts are supported. You must load a font using the
72620       * <a href="#/p5/loadFont">loadFont()</a> method (see the example above).
72621       * <a href="#/p5/stroke">stroke()</a> currently has no effect in webgl mode.
72622       *
72623       * @method text
72624       * @param {String|Object|Array|Number|Boolean} str the alphanumeric
72625       *                                             symbols to be displayed
72626       * @param {Number} x   x-coordinate of text
72627       * @param {Number} y   y-coordinate of text
72628       * @param {Number} [x2]  by default, the width of the text box,
72629       *                     see <a href="#/p5/rectMode">rectMode()</a> for more info
72630       * @param {Number} [y2]  by default, the height of the text box,
72631       *                     see <a href="#/p5/rectMode">rectMode()</a> for more info
72632       * @chainable
72633       * @example
72634       * <div>
72635       * <code>
72636       * textSize(32);
72637       * text('word', 10, 30);
72638       * fill(0, 102, 153);
72639       * text('word', 10, 60);
72640       * fill(0, 102, 153, 51);
72641       * text('word', 10, 90);
72642       * </code>
72643       * </div>
72644       * <div>
72645       * <code>
72646       * let s = 'The quick brown fox jumped over the lazy dog.';
72647       * fill(50);
72648       * text(s, 10, 10, 70, 80); // Text wraps within text box
72649       * </code>
72650       * </div>
72651       *
72652       * <div modernizr='webgl'>
72653       * <code>
72654       * let avenir;
72655       * function preload() {
72656       *   avenir = loadFont('assets/Avenir.otf');
72657       * }
72658       * function setup() {
72659       *   createCanvas(100, 100, WEBGL);
72660       *   textFont(avenir);
72661       *   textSize(width / 3);
72662       *   textAlign(CENTER, CENTER);
72663       * }
72664       * function draw() {
72665       *   background(0);
72666       *   let time = millis();
72667       *   rotateX(time / 1000);
72668       *   rotateZ(time / 1234);
72669       *   text('p5.js', 0, 0);
72670       * }
72671       * </code>
72672       * </div>
72673       *
72674       * @alt
72675       *'word' displayed 3 times going from black, blue to translucent blue
72676       * The quick brown fox jumped over the lazy dog.
72677       * the text 'p5.js' spinning in 3d
72678       *
72679       */
72680
72681
72682      p5.prototype.text = function (str, x, y, maxWidth, maxHeight) {
72683        p5._validateParameters('text', arguments);
72684
72685        return !(this._renderer._doFill || this._renderer._doStroke) ? this : this._renderer.text.apply(this._renderer, arguments);
72686      };
72687      /**
72688       * Sets the current font that will be drawn with the <a href="#/p5/text">text()</a> function.
72689       * <br><br>
72690       * <b>WEBGL</b>: Only fonts loaded via <a href="#/p5/loadFont">loadFont()</a> are supported.
72691       *
72692       * @method textFont
72693       * @return {Object} the current font
72694       *
72695       * @example
72696       * <div>
72697       * <code>
72698       * fill(0);
72699       * textSize(12);
72700       * textFont('Georgia');
72701       * text('Georgia', 12, 30);
72702       * textFont('Helvetica');
72703       * text('Helvetica', 12, 60);
72704       * </code>
72705       * </div>
72706       * <div>
72707       * <code>
72708       * let fontRegular, fontItalic, fontBold;
72709       * function preload() {
72710       *   fontRegular = loadFont('assets/Regular.otf');
72711       *   fontItalic = loadFont('assets/Italic.ttf');
72712       *   fontBold = loadFont('assets/Bold.ttf');
72713       * }
72714       * function setup() {
72715       *   background(210);
72716       *   fill(0)
72717          .strokeWeight(0)
72718          .textSize(10);
72719       *   textFont(fontRegular);
72720       *   text('Font Style Normal', 10, 30);
72721       *   textFont(fontItalic);
72722       *   text('Font Style Italic', 10, 50);
72723       *   textFont(fontBold);
72724       *   text('Font Style Bold', 10, 70);
72725       * }
72726       * </code>
72727       * </div>
72728       *
72729       * @alt
72730       *words Font Style Normal displayed normally, Italic in italic and bold in bold
72731       */
72732
72733      /**
72734       * @method textFont
72735       * @param {Object|String} font a font loaded via <a href="#/p5/loadFont">loadFont()</a>, or a String
72736       * representing a <a href="https://mzl.la/2dOw8WD">web safe font</a> (a font
72737       * that is generally available across all systems)
72738       * @param {Number} [size] the font size to use
72739       * @chainable
72740       */
72741
72742
72743      p5.prototype.textFont = function (theFont, theSize) {
72744        p5._validateParameters('textFont', arguments);
72745
72746        if (arguments.length) {
72747          if (!theFont) {
72748            throw new Error('null font passed to textFont');
72749          }
72750
72751          this._renderer._setProperty('_textFont', theFont);
72752
72753          if (theSize) {
72754            this._renderer._setProperty('_textSize', theSize);
72755
72756            this._renderer._setProperty('_textLeading', theSize * constants._DEFAULT_LEADMULT);
72757          }
72758
72759          return this._renderer._applyTextProperties();
72760        }
72761
72762        return this._renderer._textFont;
72763      };
72764
72765      module.exports = p5;
72766    }, {
72767      "../core/constants": 18,
72768      "../core/error_helpers": 20,
72769      "../core/main": 24,
72770      "opentype.js": 10
72771    }],
72772    59: [function (_dereq_, module, exports) {
72773      /**
72774       * This module defines the <a href="#/p5.Font">p5.Font</a> class and functions for
72775       * drawing text to the display canvas.
72776       * @module Typography
72777       * @submodule Font
72778       * @requires core
72779       * @requires constants
72780       */
72781      'use strict';
72782
72783      var p5 = _dereq_('../core/main');
72784
72785      var constants = _dereq_('../core/constants');
72786      /**
72787       * Base class for font handling
72788       * @class p5.Font
72789       * @param {p5} [pInst] pointer to p5 instance
72790       */
72791
72792
72793      p5.Font = function (p) {
72794        this.parent = p;
72795        this.cache = {};
72796        /**
72797         * Underlying opentype font implementation
72798         * @property font
72799         */
72800
72801        this.font = undefined;
72802      };
72803      /**
72804       * Returns a tight bounding box for the given text string using this
72805       * font (currently only supports single lines)
72806       *
72807       * @method textBounds
72808       * @param  {String} line     a line of text
72809       * @param  {Number} x        x-position
72810       * @param  {Number} y        y-position
72811       * @param  {Number} [fontSize] font size to use (optional) Default is 12.
72812       * @param  {Object} [options] opentype options (optional)
72813       *                            opentype fonts contains alignment and baseline options.
72814       *                            Default is 'LEFT' and 'alphabetic'
72815       *
72816       *
72817       * @return {Object}          a rectangle object with properties: x, y, w, h
72818       *
72819       * @example
72820       * <div>
72821       * <code>
72822       * let font;
72823       * let textString = 'Lorem ipsum dolor sit amet.';
72824       * function preload() {
72825       *   font = loadFont('./assets/Regular.otf');
72826       * }
72827       * function setup() {
72828       *   background(210);
72829       *
72830       *   let bbox = font.textBounds(textString, 10, 30, 12);
72831       *   fill(255);
72832       *   stroke(0);
72833       *   rect(bbox.x, bbox.y, bbox.w, bbox.h);
72834       *   fill(0);
72835       *   noStroke();
72836       *
72837       *   textFont(font);
72838       *   textSize(12);
72839       *   text(textString, 10, 30);
72840       * }
72841       * </code>
72842       * </div>
72843       *
72844       * @alt
72845       *words Lorem ipsum dol go off canvas and contained by white bounding box
72846       *
72847       */
72848
72849
72850      p5.Font.prototype.textBounds = function (str, x, y, fontSize, opts) {
72851        x = x !== undefined ? x : 0;
72852        y = y !== undefined ? y : 0; // Check cache for existing bounds. Take into consideration the text alignment
72853        // settings. Default alignment should match opentype's origin: left-aligned &
72854        // alphabetic baseline.
72855
72856        var p = opts && opts.renderer && opts.renderer._pInst || this.parent,
72857            ctx = p._renderer.drawingContext,
72858            alignment = ctx.textAlign || constants.LEFT,
72859            baseline = ctx.textBaseline || constants.BASELINE,
72860            cacheResults = false,
72861            result,
72862            key;
72863        fontSize = fontSize || p._renderer._textSize; // NOTE: cache disabled for now pending further discussion of #3436
72864
72865        if (cacheResults) {
72866          key = cacheKey('textBounds', str, x, y, fontSize, alignment, baseline);
72867          result = this.cache[key];
72868        }
72869
72870        if (!result) {
72871          var minX,
72872              minY,
72873              maxX,
72874              maxY,
72875              pos,
72876              xCoords = [],
72877              yCoords = [],
72878              scale = this._scale(fontSize);
72879
72880          this.font.forEachGlyph(str, x, y, fontSize, opts, function (glyph, gX, gY, gFontSize) {
72881            var gm = glyph.getMetrics();
72882            xCoords.push(gX + gm.xMin * scale);
72883            xCoords.push(gX + gm.xMax * scale);
72884            yCoords.push(gY + -gm.yMin * scale);
72885            yCoords.push(gY + -gm.yMax * scale);
72886          });
72887          minX = Math.min.apply(null, xCoords);
72888          minY = Math.min.apply(null, yCoords);
72889          maxX = Math.max.apply(null, xCoords);
72890          maxY = Math.max.apply(null, yCoords);
72891          result = {
72892            x: minX,
72893            y: minY,
72894            h: maxY - minY,
72895            w: maxX - minX,
72896            advance: minX - x
72897          }; // Bounds are now calculated, so shift the x & y to match alignment settings
72898
72899          pos = this._handleAlignment(p._renderer, str, result.x, result.y, result.w + result.advance);
72900          result.x = pos.x;
72901          result.y = pos.y;
72902
72903          if (cacheResults) {
72904            this.cache[key] = result;
72905          }
72906        }
72907
72908        return result;
72909      };
72910      /**
72911       * Computes an array of points following the path for specified text
72912       *
72913       * @method textToPoints
72914       * @param  {String} txt     a line of text
72915       * @param  {Number} x        x-position
72916       * @param  {Number} y        y-position
72917       * @param  {Number} fontSize font size to use (optional)
72918       * @param  {Object} [options] an (optional) object that can contain:
72919       *
72920       * <br>sampleFactor - the ratio of path-length to number of samples
72921       * (default=.25); higher values yield more points and are therefore
72922       * more precise
72923       *
72924       * <br>simplifyThreshold - if set to a non-zero value, collinear points will be
72925       * be removed from the polygon; the value represents the threshold angle to use
72926       * when determining whether two edges are collinear
72927       *
72928       * @return {Array}  an array of points, each with x, y, alpha (the path angle)
72929       * @example
72930       * <div>
72931       * <code>
72932       * let font;
72933       * function preload() {
72934       *   font = loadFont('./assets/Avenir.otf');
72935       * }
72936       *
72937       * let points;
72938       * let bounds;
72939       * function setup() {
72940       *   createCanvas(100, 100);
72941       *   stroke(0);
72942       *   fill(255, 104, 204);
72943       *
72944       *   points = font.textToPoints('p5', 0, 0, 10, {
72945       *     sampleFactor: 5,
72946       *     simplifyThreshold: 0
72947       *   });
72948       *   bounds = font.textBounds(' p5 ', 0, 0, 10);
72949       * }
72950       *
72951       * function draw() {
72952       *   background(255);
72953       *   beginShape();
72954       *   translate(-bounds.x * width / bounds.w, -bounds.y * height / bounds.h);
72955       *   for (let i = 0; i < points.length; i++) {
72956       *     let p = points[i];
72957       *     vertex(
72958       *       p.x * width / bounds.w +
72959       *         sin(20 * p.y / bounds.h + millis() / 1000) * width / 30,
72960       *       p.y * height / bounds.h
72961       *     );
72962       *   }
72963       *   endShape(CLOSE);
72964       * }
72965       * </code>
72966       * </div>
72967       *
72968       */
72969
72970
72971      p5.Font.prototype.textToPoints = function (txt, x, y, fontSize, options) {
72972        var xoff = 0,
72973            result = [],
72974            glyphs = this._getGlyphs(txt);
72975
72976        function isSpace(i) {
72977          return glyphs[i].name && glyphs[i].name === 'space' || txt.length === glyphs.length && txt[i] === ' ' || glyphs[i].index && glyphs[i].index === 3;
72978        }
72979
72980        fontSize = fontSize || this.parent._renderer._textSize;
72981
72982        for (var i = 0; i < glyphs.length; i++) {
72983          if (!isSpace(i)) {
72984            // fix to #1817, #2069
72985            var gpath = glyphs[i].getPath(x, y, fontSize),
72986                paths = splitPaths(gpath.commands);
72987
72988            for (var j = 0; j < paths.length; j++) {
72989              var pts = pathToPoints(paths[j], options);
72990
72991              for (var k = 0; k < pts.length; k++) {
72992                pts[k].x += xoff;
72993                result.push(pts[k]);
72994              }
72995            }
72996          }
72997
72998          xoff += glyphs[i].advanceWidth * this._scale(fontSize);
72999        }
73000
73001        return result;
73002      }; // ----------------------------- End API ------------------------------
73003
73004      /**
73005       * Returns the set of opentype glyphs for the supplied string.
73006       *
73007       * Note that there is not a strict one-to-one mapping between characters
73008       * and glyphs, so the list of returned glyphs can be larger or smaller
73009       *  than the length of the given string.
73010       *
73011       * @private
73012       * @param  {String} str the string to be converted
73013       * @return {Array}     the opentype glyphs
73014       */
73015
73016
73017      p5.Font.prototype._getGlyphs = function (str) {
73018        return this.font.stringToGlyphs(str);
73019      };
73020      /**
73021       * Returns an opentype path for the supplied string and position.
73022       *
73023       * @private
73024       * @param  {String} line     a line of text
73025       * @param  {Number} x        x-position
73026       * @param  {Number} y        y-position
73027       * @param  {Object} options opentype options (optional)
73028       * @return {Object}     the opentype path
73029       */
73030
73031
73032      p5.Font.prototype._getPath = function (line, x, y, options) {
73033        var p = options && options.renderer && options.renderer._pInst || this.parent,
73034            renderer = p._renderer,
73035            pos = this._handleAlignment(renderer, line, x, y);
73036
73037        return this.font.getPath(line, pos.x, pos.y, renderer._textSize, options);
73038      };
73039      /*
73040       * Creates an SVG-formatted path-data string
73041       * (See http://www.w3.org/TR/SVG/paths.html#PathData)
73042       * from the given opentype path or string/position
73043       *
73044       * @param  {Object} path    an opentype path, OR the following:
73045       *
73046       * @param  {String} line     a line of text
73047       * @param  {Number} x        x-position
73048       * @param  {Number} y        y-position
73049       * @param  {Object} options opentype options (optional), set options.decimals
73050       * to set the decimal precision of the path-data
73051       *
73052       * @return {Object}     this p5.Font object
73053       */
73054
73055
73056      p5.Font.prototype._getPathData = function (line, x, y, options) {
73057        var decimals = 3; // create path from string/position
73058
73059        if (typeof line === 'string' && arguments.length > 2) {
73060          line = this._getPath(line, x, y, options);
73061        } else if (typeof x === 'object') {
73062          // handle options specified in 2nd arg
73063          options = x;
73064        } // handle svg arguments
73065
73066
73067        if (options && typeof options.decimals === 'number') {
73068          decimals = options.decimals;
73069        }
73070
73071        return line.toPathData(decimals);
73072      };
73073      /*
73074       * Creates an SVG <path> element, as a string,
73075       * from the given opentype path or string/position
73076       *
73077       * @param  {Object} path    an opentype path, OR the following:
73078       *
73079       * @param  {String} line     a line of text
73080       * @param  {Number} x        x-position
73081       * @param  {Number} y        y-position
73082       * @param  {Object} options opentype options (optional), set options.decimals
73083       * to set the decimal precision of the path-data in the <path> element,
73084       *  options.fill to set the fill color for the <path> element,
73085       *  options.stroke to set the stroke color for the <path> element,
73086       *  options.strokeWidth to set the strokeWidth for the <path> element.
73087       *
73088       * @return {Object}     this p5.Font object
73089       */
73090
73091
73092      p5.Font.prototype._getSVG = function (line, x, y, options) {
73093        var decimals = 3; // create path from string/position
73094
73095        if (typeof line === 'string' && arguments.length > 2) {
73096          line = this._getPath(line, x, y, options);
73097        } else if (typeof x === 'object') {
73098          // handle options specified in 2nd arg
73099          options = x;
73100        } // handle svg arguments
73101
73102
73103        if (options) {
73104          if (typeof options.decimals === 'number') {
73105            decimals = options.decimals;
73106          }
73107
73108          if (typeof options.strokeWidth === 'number') {
73109            line.strokeWidth = options.strokeWidth;
73110          }
73111
73112          if (typeof options.fill !== 'undefined') {
73113            line.fill = options.fill;
73114          }
73115
73116          if (typeof options.stroke !== 'undefined') {
73117            line.stroke = options.stroke;
73118          }
73119        }
73120
73121        return line.toSVG(decimals);
73122      };
73123      /*
73124       * Renders an opentype path or string/position
73125       * to the current graphics context
73126       *
73127       * @param  {Object} path    an opentype path, OR the following:
73128       *
73129       * @param  {String} line     a line of text
73130       * @param  {Number} x        x-position
73131       * @param  {Number} y        y-position
73132       * @param  {Object} options opentype options (optional)
73133       *
73134       * @return {p5.Font}     this p5.Font object
73135       */
73136
73137
73138      p5.Font.prototype._renderPath = function (line, x, y, options) {
73139        var pdata,
73140            pg = options && options.renderer || this.parent._renderer,
73141            ctx = pg.drawingContext;
73142
73143        if (typeof line === 'object' && line.commands) {
73144          pdata = line.commands;
73145        } else {
73146          //pos = handleAlignment(p, ctx, line, x, y);
73147          pdata = this._getPath(line, x, y, options).commands;
73148        }
73149
73150        ctx.beginPath();
73151
73152        for (var i = 0; i < pdata.length; i += 1) {
73153          var cmd = pdata[i];
73154
73155          if (cmd.type === 'M') {
73156            ctx.moveTo(cmd.x, cmd.y);
73157          } else if (cmd.type === 'L') {
73158            ctx.lineTo(cmd.x, cmd.y);
73159          } else if (cmd.type === 'C') {
73160            ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
73161          } else if (cmd.type === 'Q') {
73162            ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);
73163          } else if (cmd.type === 'Z') {
73164            ctx.closePath();
73165          }
73166        } // only draw stroke if manually set by user
73167
73168
73169        if (pg._doStroke && pg._strokeSet) {
73170          ctx.stroke();
73171        }
73172
73173        if (pg._doFill) {
73174          // if fill hasn't been set by user, use default-text-fill
73175          if (!pg._fillSet) {
73176            pg._setFill(constants._DEFAULT_TEXT_FILL);
73177          }
73178
73179          ctx.fill();
73180        }
73181
73182        return this;
73183      };
73184
73185      p5.Font.prototype._textWidth = function (str, fontSize) {
73186        return this.font.getAdvanceWidth(str, fontSize);
73187      };
73188
73189      p5.Font.prototype._textAscent = function (fontSize) {
73190        return this.font.ascender * this._scale(fontSize);
73191      };
73192
73193      p5.Font.prototype._textDescent = function (fontSize) {
73194        return -this.font.descender * this._scale(fontSize);
73195      };
73196
73197      p5.Font.prototype._scale = function (fontSize) {
73198        return 1 / this.font.unitsPerEm * (fontSize || this.parent._renderer._textSize);
73199      };
73200
73201      p5.Font.prototype._handleAlignment = function (renderer, line, x, y, textWidth) {
73202        var fontSize = renderer._textSize;
73203
73204        if (typeof textWidth === 'undefined') {
73205          textWidth = this._textWidth(line, fontSize);
73206        }
73207
73208        switch (renderer._textAlign) {
73209          case constants.CENTER:
73210            x -= textWidth / 2;
73211            break;
73212
73213          case constants.RIGHT:
73214            x -= textWidth;
73215            break;
73216        }
73217
73218        switch (renderer._textBaseline) {
73219          case constants.TOP:
73220            y += this._textAscent(fontSize);
73221            break;
73222
73223          case constants.CENTER:
73224            y += this._textAscent(fontSize) / 2;
73225            break;
73226
73227          case constants.BOTTOM:
73228            y -= this._textDescent(fontSize);
73229            break;
73230        }
73231
73232        return {
73233          x: x,
73234          y: y
73235        };
73236      }; // path-utils
73237
73238
73239      function pathToPoints(cmds, options) {
73240        var opts = parseOpts(options, {
73241          sampleFactor: 0.1,
73242          simplifyThreshold: 0
73243        });
73244        var len = pointAtLength(cmds, 0, 1),
73245            // total-length
73246        t = len / (len * opts.sampleFactor),
73247            pts = [];
73248
73249        for (var i = 0; i < len; i += t) {
73250          pts.push(pointAtLength(cmds, i));
73251        }
73252
73253        if (opts.simplifyThreshold) {
73254          simplify(pts, opts.simplifyThreshold);
73255        }
73256
73257        return pts;
73258      }
73259
73260      function simplify(pts, angle) {
73261        angle = typeof angle === 'undefined' ? 0 : angle;
73262        var num = 0;
73263
73264        for (var i = pts.length - 1; pts.length > 3 && i >= 0; --i) {
73265          if (collinear(at(pts, i - 1), at(pts, i), at(pts, i + 1), angle)) {
73266            // Remove the middle point
73267            pts.splice(i % pts.length, 1);
73268            num++;
73269          }
73270        }
73271
73272        return num;
73273      }
73274
73275      function splitPaths(cmds) {
73276        var paths = [],
73277            current;
73278
73279        for (var i = 0; i < cmds.length; i++) {
73280          if (cmds[i].type === 'M') {
73281            if (current) {
73282              paths.push(current);
73283            }
73284
73285            current = [];
73286          }
73287
73288          current.push(cmdToArr(cmds[i]));
73289        }
73290
73291        paths.push(current);
73292        return paths;
73293      }
73294
73295      function cmdToArr(cmd) {
73296        var arr = [cmd.type];
73297
73298        if (cmd.type === 'M' || cmd.type === 'L') {
73299          // moveto or lineto
73300          arr.push(cmd.x, cmd.y);
73301        } else if (cmd.type === 'C') {
73302          arr.push(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
73303        } else if (cmd.type === 'Q') {
73304          arr.push(cmd.x1, cmd.y1, cmd.x, cmd.y);
73305        } // else if (cmd.type === 'Z') { /* no-op */ }
73306
73307
73308        return arr;
73309      }
73310
73311      function parseOpts(options, defaults) {
73312        if (typeof options !== 'object') {
73313          options = defaults;
73314        } else {
73315          for (var key in defaults) {
73316            if (typeof options[key] === 'undefined') {
73317              options[key] = defaults[key];
73318            }
73319          }
73320        }
73321
73322        return options;
73323      } //////////////////////// Helpers ////////////////////////////
73324
73325
73326      function at(v, i) {
73327        var s = v.length;
73328        return v[i < 0 ? i % s + s : i % s];
73329      }
73330
73331      function collinear(a, b, c, thresholdAngle) {
73332        if (!thresholdAngle) {
73333          return areaTriangle(a, b, c) === 0;
73334        }
73335
73336        if (typeof collinear.tmpPoint1 === 'undefined') {
73337          collinear.tmpPoint1 = [];
73338          collinear.tmpPoint2 = [];
73339        }
73340
73341        var ab = collinear.tmpPoint1,
73342            bc = collinear.tmpPoint2;
73343        ab.x = b.x - a.x;
73344        ab.y = b.y - a.y;
73345        bc.x = c.x - b.x;
73346        bc.y = c.y - b.y;
73347        var dot = ab.x * bc.x + ab.y * bc.y,
73348            magA = Math.sqrt(ab.x * ab.x + ab.y * ab.y),
73349            magB = Math.sqrt(bc.x * bc.x + bc.y * bc.y),
73350            angle = Math.acos(dot / (magA * magB));
73351        return angle < thresholdAngle;
73352      }
73353
73354      function areaTriangle(a, b, c) {
73355        return (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]);
73356      } // Portions of below code copyright 2008 Dmitry Baranovskiy (via MIT license)
73357
73358
73359      function findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
73360        var t1 = 1 - t,
73361            t13 = Math.pow(t1, 3),
73362            t12 = Math.pow(t1, 2),
73363            t2 = t * t,
73364            t3 = t2 * t,
73365            x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,
73366            y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y,
73367            mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),
73368            my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),
73369            nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),
73370            ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),
73371            ax = t1 * p1x + t * c1x,
73372            ay = t1 * p1y + t * c1y,
73373            cx = t1 * c2x + t * p2x,
73374            cy = t1 * c2y + t * p2y,
73375            alpha = 90 - Math.atan2(mx - nx, my - ny) * 180 / Math.PI;
73376
73377        if (mx > nx || my < ny) {
73378          alpha += 180;
73379        }
73380
73381        return {
73382          x: x,
73383          y: y,
73384          m: {
73385            x: mx,
73386            y: my
73387          },
73388          n: {
73389            x: nx,
73390            y: ny
73391          },
73392          start: {
73393            x: ax,
73394            y: ay
73395          },
73396          end: {
73397            x: cx,
73398            y: cy
73399          },
73400          alpha: alpha
73401        };
73402      }
73403
73404      function getPointAtSegmentLength(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {
73405        return length == null ? bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) : findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length));
73406      }
73407
73408      function pointAtLength(path, length, istotal) {
73409        path = path2curve(path);
73410        var x,
73411            y,
73412            p,
73413            l,
73414            sp = '',
73415            subpaths = {},
73416            point,
73417            len = 0;
73418
73419        for (var i = 0, ii = path.length; i < ii; i++) {
73420          p = path[i];
73421
73422          if (p[0] === 'M') {
73423            x = +p[1];
73424            y = +p[2];
73425          } else {
73426            l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
73427
73428            if (len + l > length) {
73429              if (!istotal) {
73430                point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
73431                return {
73432                  x: point.x,
73433                  y: point.y,
73434                  alpha: point.alpha
73435                };
73436              }
73437            }
73438
73439            len += l;
73440            x = +p[5];
73441            y = +p[6];
73442          }
73443
73444          sp += p.shift() + p;
73445        }
73446
73447        subpaths.end = sp;
73448        point = istotal ? len : findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
73449
73450        if (point.alpha) {
73451          point = {
73452            x: point.x,
73453            y: point.y,
73454            alpha: point.alpha
73455          };
73456        }
73457
73458        return point;
73459      }
73460
73461      function pathToAbsolute(pathArray) {
73462        var res = [],
73463            x = 0,
73464            y = 0,
73465            mx = 0,
73466            my = 0,
73467            start = 0;
73468
73469        if (!pathArray) {
73470          // console.warn("Unexpected state: undefined pathArray"); // shouldn't happen
73471          return res;
73472        }
73473
73474        if (pathArray[0][0] === 'M') {
73475          x = +pathArray[0][1];
73476          y = +pathArray[0][2];
73477          mx = x;
73478          my = y;
73479          start++;
73480          res[0] = ['M', x, y];
73481        }
73482
73483        var dots,
73484            crz = pathArray.length === 3 && pathArray[0][0] === 'M' && pathArray[1][0].toUpperCase() === 'R' && pathArray[2][0].toUpperCase() === 'Z';
73485
73486        for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
73487          res.push(r = []);
73488          pa = pathArray[i];
73489
73490          if (pa[0] !== String.prototype.toUpperCase.call(pa[0])) {
73491            r[0] = String.prototype.toUpperCase.call(pa[0]);
73492
73493            switch (r[0]) {
73494              case 'A':
73495                r[1] = pa[1];
73496                r[2] = pa[2];
73497                r[3] = pa[3];
73498                r[4] = pa[4];
73499                r[5] = pa[5];
73500                r[6] = +(pa[6] + x);
73501                r[7] = +(pa[7] + y);
73502                break;
73503
73504              case 'V':
73505                r[1] = +pa[1] + y;
73506                break;
73507
73508              case 'H':
73509                r[1] = +pa[1] + x;
73510                break;
73511
73512              case 'R':
73513                dots = [x, y].concat(pa.slice(1));
73514
73515                for (var j = 2, jj = dots.length; j < jj; j++) {
73516                  dots[j] = +dots[j] + x;
73517                  dots[++j] = +dots[j] + y;
73518                }
73519
73520                res.pop();
73521                res = res.concat(catmullRom2bezier(dots, crz));
73522                break;
73523
73524              case 'M':
73525                mx = +pa[1] + x;
73526                my = +pa[2] + y;
73527                break;
73528
73529              default:
73530                for (j = 1, jj = pa.length; j < jj; j++) {
73531                  r[j] = +pa[j] + (j % 2 ? x : y);
73532                }
73533
73534            }
73535          } else if (pa[0] === 'R') {
73536            dots = [x, y].concat(pa.slice(1));
73537            res.pop();
73538            res = res.concat(catmullRom2bezier(dots, crz));
73539            r = ['R'].concat(pa.slice(-2));
73540          } else {
73541            for (var k = 0, kk = pa.length; k < kk; k++) {
73542              r[k] = pa[k];
73543            }
73544          }
73545
73546          switch (r[0]) {
73547            case 'Z':
73548              x = mx;
73549              y = my;
73550              break;
73551
73552            case 'H':
73553              x = r[1];
73554              break;
73555
73556            case 'V':
73557              y = r[1];
73558              break;
73559
73560            case 'M':
73561              mx = r[r.length - 2];
73562              my = r[r.length - 1];
73563              break;
73564
73565            default:
73566              x = r[r.length - 2];
73567              y = r[r.length - 1];
73568          }
73569        }
73570
73571        return res;
73572      }
73573
73574      function path2curve(path, path2) {
73575        var p = pathToAbsolute(path),
73576            p2 = path2 && pathToAbsolute(path2);
73577        var attrs = {
73578          x: 0,
73579          y: 0,
73580          bx: 0,
73581          by: 0,
73582          X: 0,
73583          Y: 0,
73584          qx: null,
73585          qy: null
73586        };
73587        var attrs2 = {
73588          x: 0,
73589          y: 0,
73590          bx: 0,
73591          by: 0,
73592          X: 0,
73593          Y: 0,
73594          qx: null,
73595          qy: null
73596        };
73597        var pcoms1 = []; // path commands of original path p
73598
73599        var pcoms2 = []; // path commands of original path p2
73600
73601        var ii;
73602
73603        var processPath = function (path, d, pcom) {
73604          var nx,
73605              ny,
73606              tq = {
73607            T: 1,
73608            Q: 1
73609          };
73610
73611          if (!path) {
73612            return ['C', d.x, d.y, d.x, d.y, d.x, d.y];
73613          }
73614
73615          if (!(path[0] in tq)) {
73616            d.qx = d.qy = null;
73617          }
73618
73619          switch (path[0]) {
73620            case 'M':
73621              d.X = path[1];
73622              d.Y = path[2];
73623              break;
73624
73625            case 'A':
73626              path = ['C'].concat(a2c.apply(0, [d.x, d.y].concat(path.slice(1))));
73627              break;
73628
73629            case 'S':
73630              if (pcom === 'C' || pcom === 'S') {
73631                nx = d.x * 2 - d.bx;
73632                ny = d.y * 2 - d.by;
73633              } else {
73634                nx = d.x;
73635                ny = d.y;
73636              }
73637
73638              path = ['C', nx, ny].concat(path.slice(1));
73639              break;
73640
73641            case 'T':
73642              if (pcom === 'Q' || pcom === 'T') {
73643                d.qx = d.x * 2 - d.qx;
73644                d.qy = d.y * 2 - d.qy;
73645              } else {
73646                d.qx = d.x;
73647                d.qy = d.y;
73648              }
73649
73650              path = ['C'].concat(q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
73651              break;
73652
73653            case 'Q':
73654              d.qx = path[1];
73655              d.qy = path[2];
73656              path = ['C'].concat(q2c(d.x, d.y, path[1], path[2], path[3], path[4]));
73657              break;
73658
73659            case 'L':
73660              path = ['C'].concat(l2c(d.x, d.y, path[1], path[2]));
73661              break;
73662
73663            case 'H':
73664              path = ['C'].concat(l2c(d.x, d.y, path[1], d.y));
73665              break;
73666
73667            case 'V':
73668              path = ['C'].concat(l2c(d.x, d.y, d.x, path[1]));
73669              break;
73670
73671            case 'Z':
73672              path = ['C'].concat(l2c(d.x, d.y, d.X, d.Y));
73673              break;
73674          }
73675
73676          return path;
73677        },
73678            fixArc = function (pp, i) {
73679          if (pp[i].length > 7) {
73680            pp[i].shift();
73681            var pi = pp[i];
73682
73683            while (pi.length) {
73684              pcoms1[i] = 'A';
73685
73686              if (p2) {
73687                pcoms2[i] = 'A';
73688              }
73689
73690              pp.splice(i++, 0, ['C'].concat(pi.splice(0, 6)));
73691            }
73692
73693            pp.splice(i, 1);
73694            ii = Math.max(p.length, p2 && p2.length || 0);
73695          }
73696        },
73697            fixM = function (path1, path2, a1, a2, i) {
73698          if (path1 && path2 && path1[i][0] === 'M' && path2[i][0] !== 'M') {
73699            path2.splice(i, 0, ['M', a2.x, a2.y]);
73700            a1.bx = 0;
73701            a1.by = 0;
73702            a1.x = path1[i][1];
73703            a1.y = path1[i][2];
73704            ii = Math.max(p.length, p2 && p2.length || 0);
73705          }
73706        };
73707
73708        var pfirst = ''; // temporary holder for original path command
73709
73710        var pcom = ''; // holder for previous path command of original path
73711
73712        ii = Math.max(p.length, p2 && p2.length || 0);
73713
73714        for (var i = 0; i < ii; i++) {
73715          if (p[i]) {
73716            pfirst = p[i][0];
73717          } // save current path command
73718
73719
73720          if (pfirst !== 'C') {
73721            pcoms1[i] = pfirst; // Save current path command
73722
73723            if (i) {
73724              pcom = pcoms1[i - 1];
73725            } // Get previous path command pcom
73726
73727          }
73728
73729          p[i] = processPath(p[i], attrs, pcom);
73730
73731          if (pcoms1[i] !== 'A' && pfirst === 'C') {
73732            pcoms1[i] = 'C';
73733          }
73734
73735          fixArc(p, i);
73735 // fixArc adds also the right amount of A:s to pcoms1
73736
73737          if (p2) {
73738            // the same procedures is done to p2
73739            if (p2[i]) {
73740              pfirst = p2[i][0];
73741            }
73742
73743            if (pfirst !== 'C') {
73744              pcoms2[i] = pfirst;
73745
73746              if (i) {
73747                pcom = pcoms2[i - 1];
73748              }
73749            }
73750
73751            p2[i] = processPath(p2[i], attrs2, pcom);
73752
73753            if (pcoms2[i] !== 'A' && pfirst === 'C') {
73754              pcoms2[i] = 'C';
73755            }
73756
73757            fixArc(p2, i);
73758          }
73759
73760          fixM(p, p2, attrs, attrs2, i);
73761          fixM(p2, p, attrs2, attrs, i);
73762          var seg = p[i],
73763              seg2 = p2 && p2[i],
73764              seglen = seg.length,
73765              seg2len = p2 && seg2.length;
73766          attrs.x = seg[seglen - 2];
73767          attrs.y = seg[seglen - 1];
73768          attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x;
73769          attrs.by = parseFloat(seg[seglen - 3]) || attrs.y;
73770          attrs2.bx = p2 && (parseFloat(seg2[seg2len - 4]) || attrs2.x);
73771          attrs2.by = p2 && (parseFloat(seg2[seg2len - 3]) || attrs2.y);
73772          attrs2.x = p2 && seg2[seg2len - 2];
73773          attrs2.y = p2 && seg2[seg2len - 1];
73774        }
73775
73776        return p2 ? [p, p2] : p;
73777      }
73778
73779      function a2c(x1, y1, rx, ry, angle, lac, sweep_flag, x2, y2, recursive) {
73780        // for more information of where this Math came from visit:
73781        // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
73782        var PI = Math.PI,
73783            _120 = PI * 120 / 180,
73784            f1,
73785            f2,
73786            cx,
73787            cy,
73788            rad = PI / 180 * (+angle || 0),
73789            res = [],
73790            xy,
73791            rotate = function (x, y, rad) {
73792          var X = x * Math.cos(rad) - y * Math.sin(rad),
73793              Y = x * Math.sin(rad) + y * Math.cos(rad);
73794          return {
73795            x: X,
73796            y: Y
73797          };
73798        };
73799
73800        if (!recursive) {
73801          xy = rotate(x1, y1, -rad);
73802          x1 = xy.x;
73803          y1 = xy.y;
73804          xy = rotate(x2, y2, -rad);
73805          x2 = xy.x;
73806          y2 = xy.y;
73807          var x = (x1 - x2) / 2,
73808              y = (y1 - y2) / 2,
73809              h = x * x / (rx * rx) + y * y / (ry * ry);
73810
73811          if (h > 1) {
73812            h = Math.sqrt(h);
73813            rx = h * rx;
73814            ry = h * ry;
73815          }
73816
73817          var rx2 = rx * rx,
73818              ry2 = ry * ry;
73819          var k = (lac === sweep_flag ? -1 : 1) * Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)));
73820          cx = k * rx * y / ry + (x1 + x2) / 2;
73821          cy = k * -ry * x / rx + (y1 + y2) / 2;
73822          f1 = Math.asin(((y1 - cy) / ry).toFixed(9));
73823          f2 = Math.asin(((y2 - cy) / ry).toFixed(9));
73824          f1 = x1 < cx ? PI - f1 : f1;
73825          f2 = x2 < cx ? PI - f2 : f2;
73826
73827          if (f1 < 0) {
73828            f1 = PI * 2 + f1;
73829          }
73830
73831          if (f2 < 0) {
73832            f2 = PI * 2 + f2;
73833          }
73834
73835          if (sweep_flag && f1 > f2) {
73836            f1 = f1 - PI * 2;
73837          }
73838
73839          if (!sweep_flag && f2 > f1) {
73840            f2 = f2 - PI * 2;
73841          }
73842        } else {
73843          f1 = recursive[0];
73844          f2 = recursive[1];
73845          cx = recursive[2];
73846          cy = recursive[3];
73847        }
73848
73849        var df = f2 - f1;
73850
73851        if (Math.abs(df) > _120) {
73852          var f2old = f2,
73853              x2old = x2,
73854              y2old = y2;
73855          f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
73856          x2 = cx + rx * Math.cos(f2);
73857          y2 = cy + ry * Math.sin(f2);
73858          res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
73859        }
73860
73861        df = f2 - f1;
73862        var c1 = Math.cos(f1),
73863            s1 = Math.sin(f1),
73864            c2 = Math.cos(f2),
73865            s2 = Math.sin(f2),
73866            t = Math.tan(df / 4),
73867            hx = 4 / 3 * rx * t,
73868            hy = 4 / 3 * ry * t,
73869            m1 = [x1, y1],
73870            m2 = [x1 + hx * s1, y1 - hy * c1],
73871            m3 = [x2 + hx * s2, y2 - hy * c2],
73872            m4 = [x2, y2];
73873        m2[0] = 2 * m1[0] - m2[0];
73874        m2[1] = 2 * m1[1] - m2[1];
73875
73876        if (recursive) {
73877          return [m2, m3, m4].concat(res);
73878        } else {
73879          res = [m2, m3, m4].concat(res).join().split(',');
73880          var newres = [];
73881
73882          for (var i = 0, ii = res.length; i < ii; i++) {
73883            newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;
73884          }
73885
73886          return newres;
73887        }
73888      } // http://schepers.cc/getting-to-the-point
73889
73890
73891      function catmullRom2bezier(crp, z) {
73892        var d = [];
73893
73894        for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {
73895          var p = [{
73896            x: +crp[i - 2],
73897            y: +crp[i - 1]
73898          }, {
73899            x: +crp[i],
73900            y: +crp[i + 1]
73901          }, {
73902            x: +crp[i + 2],
73903            y: +crp[i + 3]
73904          }, {
73905            x: +crp[i + 4],
73906            y: +crp[i + 5]
73907          }];
73908
73909          if (z) {
73910            if (!i) {
73911              p[0] = {
73912                x: +crp[iLen - 2],
73913                y: +crp[iLen - 1]
73914              };
73915            } else if (iLen - 4 === i) {
73916              p[3] = {
73917                x: +crp[0],
73918                y: +crp[1]
73919              };
73920            } else if (iLen - 2 === i) {
73921              p[2] = {
73922                x: +crp[0],
73923                y: +crp[1]
73924              };
73925              p[3] = {
73926                x: +crp[2],
73927                y: +crp[3]
73928              };
73929            }
73930          } else {
73931            if (iLen - 4 === i) {
73932              p[3] = p[2];
73933            } else if (!i) {
73934              p[0] = {
73935                x: +crp[i],
73936                y: +crp[i + 1]
73937              };
73938            }
73939          }
73940
73941          d.push(['C', (-p[0].x + 6 * p[1].x + p[2].x) / 6, (-p[0].y + 6 * p[1].y + p[2].y) / 6, (p[1].x + 6 * p[2].x - p[3].x) / 6, (p[1].y + 6 * p[2].y - p[3].y) / 6, p[2].x, p[2].y]);
73942        }
73943
73944        return d;
73945      }
73946
73947      function l2c(x1, y1, x2, y2) {
73948        return [x1, y1, x2, y2, x2, y2];
73949      }
73950
73951      function q2c(x1, y1, ax, ay, x2, y2) {
73952        var _13 = 1 / 3,
73953            _23 = 2 / 3;
73954
73955        return [_13 * x1 + _23 * ax, _13 * y1 + _23 * ay, _13 * x2 + _23 * ax, _13 * y2 + _23 * ay, x2, y2];
73956      }
73957
73958      function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {
73959        if (z == null) {
73960          z = 1;
73961        }
73962
73963        z = z > 1 ? 1 : z < 0 ? 0 : z;
73964        var z2 = z / 2;
73965        var n = 12;
73966        var Tvalues = [-0.1252, 0.1252, -0.3678, 0.3678, -0.5873, 0.5873, -0.7699, 0.7699, -0.9041, 0.9041, -0.9816, 0.9816];
73967        var sum = 0;
73968        var Cvalues = [0.2491, 0.2491, 0.2335, 0.2335, 0.2032, 0.2032, 0.1601, 0.1601, 0.1069, 0.1069, 0.0472, 0.0472];
73969
73970        for (var i = 0; i < n; i++) {
73971          var ct = z2 * Tvalues[i] + z2,
73972              xbase = base3(ct, x1, x2, x3, x4),
73973              ybase = base3(ct, y1, y2, y3, y4),
73974              comb = xbase * xbase + ybase * ybase;
73975          sum += Cvalues[i] * Math.sqrt(comb);
73976        }
73977
73978        return z2 * sum;
73979      }
73980
73981      function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) {
73982        if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) {
73983          return;
73984        }
73985
73986        var t = 1,
73987            step = t / 2,
73988            t2 = t - step,
73989            l,
73990            e = 0.01;
73991        l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
73992
73993        while (Math.abs(l - ll) > e) {
73994          step /= 2;
73995          t2 += (l < ll ? 1 : -1) * step;
73996          l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
73997        }
73998
73999        return t2;
74000      }
74001
74002      function base3(t, p1, p2, p3, p4) {
74003        var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,
74004            t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;
74005        return t * t2 - 3 * p1 + 3 * p2;
74006      }
74007
74008      function cacheKey() {
74009        var hash = '';
74010
74011        for (var i = arguments.length - 1; i >= 0; --i) {
74012          hash += '?' + arguments[i];
74013        }
74014
74015        return hash;
74016      }
74017
74018      module.exports = p5;
74019    }, {
74020      "../core/constants": 18,
74021      "../core/main": 24
74022    }],
74023    60: [function (_dereq_, module, exports) {
74024      /**
74025       * @module Data
74026       * @submodule Array Functions
74027       * @for p5
74028       * @requires core
74029       */
74030      'use strict';
74031
74032      var p5 = _dereq_('../core/main');
74033      /**
74034       * Adds a value to the end of an array. Extends the length of
74035       * the array by one. Maps to Array.push().
74036       *
74037       * @method append
74038       * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push">array.push(value)</a> instead.
74039       * @param {Array} array Array to append
74040       * @param {any} value to be added to the Array
74041       * @return {Array} the array that was appended to
74042       * @example
74043       * <div class='norender'><code>
74044       * function setup() {
74045       *   var myArray = ['Mango', 'Apple', 'Papaya'];
74046       *   print(myArray); // ['Mango', 'Apple', 'Papaya']
74047       *
74048       *   append(myArray, 'Peach');
74049       *   print(myArray); // ['Mango', 'Apple', 'Papaya', 'Peach']
74050       * }
74051       * </code></div>
74052       */
74053
74054
74055      p5.prototype.append = function (array, value) {
74056        array.push(value);
74057        return array;
74058      };
74059      /**
74060       * Copies an array (or part of an array) to another array. The src array is
74061       * copied to the dst array, beginning at the position specified by
74062       * srcPosition and into the position specified by dstPosition. The number of
74063       * elements to copy is determined by length. Note that copying values
74064       * overwrites existing values in the destination array. To append values
74065       * instead of overwriting them, use <a href="#/p5/concat">concat()</a>.
74066       * <br><br>
74067       * The simplified version with only two arguments, arrayCopy(src, dst),
74068       * copies an entire array to another of the same size. It is equivalent to
74069       * arrayCopy(src, 0, dst, 0, src.length).
74070       * <br><br>
74071       * Using this function is far more efficient for copying array data than
74072       * iterating through a for() loop and copying each element individually.
74073       *
74074       * @method arrayCopy
74075       * @deprecated
74076       * @param {Array}  src           the source Array
74077       * @param {Integer} srcPosition  starting position in the source Array
74078       * @param {Array}  dst           the destination Array
74079       * @param {Integer} dstPosition   starting position in the destination Array
74080       * @param {Integer} length        number of Array elements to be copied
74081       *
74082       * @example
74083       * <div class='norender'><code>
74084       * var src = ['A', 'B', 'C'];
74085       * var dst = [1, 2, 3];
74086       * var srcPosition = 1;
74087       * var dstPosition = 0;
74088       * var length = 2;
74089       *
74090       * print(src); // ['A', 'B', 'C']
74091       * print(dst); // [ 1 ,  2 ,  3 ]
74092       *
74093       * arrayCopy(src, srcPosition, dst, dstPosition, length);
74094       * print(dst); // ['B', 'C', 3]
74095       * </code></div>
74096       */
74097
74098      /**
74099       * @method arrayCopy
74100       * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin">arr1.copyWithin(arr2)</a> instead.
74101       * @param {Array}  src
74102       * @param {Array}  dst
74103       * @param {Integer} [length]
74104       */
74105
74106
74107      p5.prototype.arrayCopy = function (src, srcPosition, dst, dstPosition, length) {
74108        // the index to begin splicing from dst array
74109        var start;
74110        var end;
74111
74112        if (typeof length !== 'undefined') {
74113          end = Math.min(length, src.length);
74114          start = dstPosition;
74115          src = src.slice(srcPosition, end + srcPosition);
74116        } else {
74117          if (typeof dst !== 'undefined') {
74118            // src, dst, length
74119            // rename  so we don't get confused
74120            end = dst;
74121            end = Math.min(end, src.length);
74122          } else {
74123            // src, dst
74124            end = src.length;
74125          }
74126
74127          start = 0; // rename  so we don't get confused
74128
74129          dst = srcPosition;
74130          src = src.slice(0, end);
74131        } // Since we are not returning the array and JavaScript is pass by reference
74132        // we must modify the actual values of the array
74133        // instead of reassigning arrays
74134
74135
74136        Array.prototype.splice.apply(dst, [start, end].concat(src));
74137      };
74138      /**
74139       * Concatenates two arrays, maps to Array.concat(). Does not modify the
74140       * input arrays.
74141       *
74142       * @method concat
74143       * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat">arr1.concat(arr2)</a> instead.
74144       * @param {Array} a first Array to concatenate
74145       * @param {Array} b second Array to concatenate
74146       * @return {Array} concatenated array
74147       *
74148       * @example
74149       * <div class = 'norender'><code>
74150       * function setup() {
74151       *   var arr1 = ['A', 'B', 'C'];
74152       *   var arr2 = [1, 2, 3];
74153       *
74154       *   print(arr1); // ['A','B','C']
74155       *   print(arr2); // [1,2,3]
74156       *
74157       *   var arr3 = concat(arr1, arr2);
74158       *
74159       *   print(arr1); // ['A','B','C']
74160       *   print(arr2); // [1, 2, 3]
74161       *   print(arr3); // ['A','B','C', 1, 2, 3]
74162       * }
74163       * </code></div>
74164       */
74165
74166
74167      p5.prototype.concat = function (list0, list1) {
74168        return list0.concat(list1);
74169      };
74170      /**
74171       * Reverses the order of an array, maps to Array.reverse()
74172       *
74173       * @method reverse
74174       * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse">array.reverse()</a> instead.
74175       * @param {Array} list Array to reverse
74176       * @return {Array} the reversed list
74177       * @example
74178       * <div class='norender'><code>
74179       * function setup() {
74180       *   var myArray = ['A', 'B', 'C'];
74181       *   print(myArray); // ['A','B','C']
74182       *
74183       *   reverse(myArray);
74184       *   print(myArray); // ['C','B','A']
74185       * }
74186       * </code></div>
74187       */
74188
74189
74190      p5.prototype.reverse = function (list) {
74191        return list.reverse();
74192      };
74193      /**
74194       * Decreases an array by one element and returns the shortened array,
74195       * maps to Array.pop().
74196       *
74197       * @method shorten
74198       * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop">array.pop()</a> instead.
74199       * @param  {Array} list Array to shorten
74200       * @return {Array} shortened Array
74201       * @example
74202       * <div class = 'norender'><code>
74203       * function setup() {
74204       *   var myArray = ['A', 'B', 'C'];
74205       *   print(myArray); // ['A', 'B', 'C']
74206       *   var newArray = shorten(myArray);
74207       *   print(myArray); // ['A','B','C']
74208       *   print(newArray); // ['A','B']
74209       * }
74210       * </code></div>
74211       */
74212
74213
74214      p5.prototype.shorten = function (list) {
74215        list.pop();
74216        return list;
74217      };
74218      /**
74219       * Randomizes the order of the elements of an array. Implements
74220       * <a href='http://Bost.Ocks.org/mike/shuffle/' target=_blank>
74221       * Fisher-Yates Shuffle Algorithm</a>.
74222       *
74223       * @method shuffle
74224       * @param  {Array}   array  Array to shuffle
74225       * @param  {Boolean} [bool] modify passed array
74226       * @return {Array}   shuffled Array
74227       * @example
74228       * <div><code>
74229       * function setup() {
74230       *   var regularArr = ['ABC', 'def', createVector(), TAU, Math.E];
74231       *   print(regularArr);
74232       *   shuffle(regularArr, true); // force modifications to passed array
74233       *   print(regularArr);
74234       *
74235       *   // By default shuffle() returns a shuffled cloned array:
74236       *   var newArr = shuffle(regularArr);
74237       *   print(regularArr);
74238       *   print(newArr);
74239       * }
74240       * </code></div>
74241       */
74242
74243
74244      p5.prototype.shuffle = function (arr, bool) {
74245        var isView = ArrayBuffer && ArrayBuffer.isView && ArrayBuffer.isView(arr);
74246        arr = bool || isView ? arr : arr.slice();
74247        var rnd,
74248            tmp,
74249            idx = arr.length;
74250
74251        while (idx > 1) {
74252          rnd = Math.random() * idx | 0;
74253          tmp = arr[--idx];
74254          arr[idx] = arr[rnd];
74255          arr[rnd] = tmp;
74256        }
74257
74258        return arr;
74259      };
74260      /**
74261       * Sorts an array of numbers from smallest to largest, or puts an array of
74262       * words in alphabetical order. The original array is not modified; a
74263       * re-ordered array is returned. The count parameter states the number of
74264       * elements to sort. For example, if there are 12 elements in an array and
74265       * count is set to 5, only the first 5 elements in the array will be sorted.
74266       *
74267       * @method sort
74268       * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort">array.sort()</a> instead.
74269       * @param {Array} list Array to sort
74270       * @param {Integer} [count] number of elements to sort, starting from 0
74271       * @return {Array} the sorted list
74272       *
74273       * @example
74274       * <div class = 'norender'><code>
74275       * function setup() {
74276       *   var words = ['banana', 'apple', 'pear', 'lime'];
74277       *   print(words); // ['banana', 'apple', 'pear', 'lime']
74278       *   var count = 4; // length of array
74279       *
74280       *   words = sort(words, count);
74281       *   print(words); // ['apple', 'banana', 'lime', 'pear']
74282       * }
74283       * </code></div>
74284       * <div class = 'norender'><code>
74285       * function setup() {
74286       *   var numbers = [2, 6, 1, 5, 14, 9, 8, 12];
74287       *   print(numbers); // [2, 6, 1, 5, 14, 9, 8, 12]
74288       *   var count = 5; // Less than the length of the array
74289       *
74290       *   numbers = sort(numbers, count);
74291       *   print(numbers); // [1,2,5,6,14,9,8,12]
74292       * }
74293       * </code></div>
74294       */
74295
74296
74297      p5.prototype.sort = function (list, count) {
74298        var arr = count ? list.slice(0, Math.min(count, list.length)) : list;
74299        var rest = count ? list.slice(Math.min(count, list.length)) : [];
74300
74301        if (typeof arr[0] === 'string') {
74302          arr = arr.sort();
74303        } else {
74304          arr = arr.sort(function (a, b) {
74305            return a - b;
74306          });
74307        }
74308
74309        return arr.concat(rest);
74310      };
74311      /**
74312       * Inserts a value or an array of values into an existing array. The first
74313       * parameter specifies the initial array to be modified, and the second
74314       * parameter defines the data to be inserted. The third parameter is an index
74315       * value which specifies the array position from which to insert data.
74316       * (Remember that array index numbering starts at zero, so the first position
74317       * is 0, the second position is 1, and so on.)
74318       *
74319       * @method splice
74320       * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice">array.splice()</a> instead.
74321       * @param {Array}  list Array to splice into
74322       * @param {any}    value value to be spliced in
74323       * @param {Integer} position in the array from which to insert data
74324       * @return {Array} the list
74325       *
74326       * @example
74327       * <div class = 'norender'><code>
74328       * function setup() {
74329       *   var myArray = [0, 1, 2, 3, 4];
74330       *   var insArray = ['A', 'B', 'C'];
74331       *   print(myArray); // [0, 1, 2, 3, 4]
74332       *   print(insArray); // ['A','B','C']
74333       *
74334       *   splice(myArray, insArray, 3);
74335       *   print(myArray); // [0,1,2,'A','B','C',3,4]
74336       * }
74337       * </code></div>
74338       */
74339
74340
74341      p5.prototype.splice = function (list, value, index) {
74342        // note that splice returns spliced elements and not an array
74343        Array.prototype.splice.apply(list, [index, 0].concat(value));
74344        return list;
74345      };
74346      /**
74347       * Extracts an array of elements from an existing array. The list parameter
74348       * defines the array from which the elements will be copied, and the start
74349       * and count parameters specify which elements to extract. If no count is
74350       * given, elements will be extracted from the start to the end of the array.
74351       * When specifying the start, remember that the first array element is 0.
74352       * This function does not change the source array.
74353       *
74354       * @method subset
74355       * @deprecated Use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice">array.slice()</a> instead.
74356       * @param  {Array}  list    Array to extract from
74357       * @param  {Integer} start   position to begin
74358       * @param  {Integer} [count] number of values to extract
74359       * @return {Array}          Array of extracted elements
74360       *
74361       * @example
74362       * <div class = 'norender'><code>
74363       * function setup() {
74364       *   var myArray = [1, 2, 3, 4, 5];
74365       *   print(myArray); // [1, 2, 3, 4, 5]
74366       *
74367       *   var sub1 = subset(myArray, 0, 3);
74368       *   var sub2 = subset(myArray, 2, 2);
74369       *   print(sub1); // [1,2,3]
74370       *   print(sub2); // [3,4]
74371       * }
74372       * </code></div>
74373       */
74374
74375
74376      p5.prototype.subset = function (list, start, count) {
74377        if (typeof count !== 'undefined') {
74378          return list.slice(start, start + count);
74379        } else {
74380          return list.slice(start, list.length);
74381        }
74382      };
74383
74384      module.exports = p5;
74385    }, {
74386      "../core/main": 24
74387    }],
74388    61: [function (_dereq_, module, exports) {
74389      /**
74390       * @module Data
74391       * @submodule Conversion
74392       * @for p5
74393       * @requires core
74394       */
74395      'use strict';
74396
74397      var p5 = _dereq_('../core/main');
74398      /**
74399       * Converts a string to its floating point representation. The contents of a
74400       * string must resemble a number, or NaN (not a number) will be returned.
74401       * For example, float("1234.56") evaluates to 1234.56, but float("giraffe")
74402       * will return NaN.
74403       *
74404       * When an array of values is passed in, then an array of floats of the same
74405       * length is returned.
74406       *
74407       * @method float
74408       * @param {String}  str float string to parse
74409       * @return {Number}     floating point representation of string
74410       * @example
74411       * <div><code>
74412       * var str = '20';
74413       * var diameter = float(str);
74414       * ellipse(width / 2, height / 2, diameter, diameter);
74415       * </code></div>
74416       *
74417       * @alt
74418       * 20 by 20 white ellipse in the center of the canvas
74419       *
74420       */
74421
74422
74423      p5.prototype.float = function (str) {
74424        if (str instanceof Array) {
74425          return str.map(parseFloat);
74426        }
74427
74428        return parseFloat(str);
74429      };
74430      /**
74431       * Converts a boolean, string, or float to its integer representation.
74432       * When an array of values is passed in, then an int array of the same length
74433       * is returned.
74434       *
74435       * @method int
74436       * @param {String|Boolean|Number}       n value to parse
74437       * @param {Integer}       [radix] the radix to convert to (default: 10)
74438       * @return {Number}                     integer representation of value
74439       *
74440       * @example
74441       * <div class='norender'><code>
74442       * print(int('10')); // 10
74443       * print(int(10.31)); // 10
74444       * print(int(-10)); // -10
74445       * print(int(true)); // 1
74446       * print(int(false)); // 0
74447       * print(int([false, true, '10.3', 9.8])); // [0, 1, 10, 9]
74448       * </code></div>
74449       */
74450
74451      /**
74452       * @method int
74453       * @param {Array} ns                    values to parse
74454       * @return {Number[]}                   integer representation of values
74455       */
74456
74457
74458      p5.prototype.int = function (n, radix) {
74459        radix = radix || 10;
74460
74461        if (typeof n === 'string') {
74462          return parseInt(n, radix);
74463        } else if (typeof n === 'number') {
74464          return n | 0;
74465        } else if (typeof n === 'boolean') {
74466          return n ? 1 : 0;
74467        } else if (n instanceof Array) {
74468          return n.map(function (n) {
74469            return p5.prototype.int(n, radix);
74470          });
74471        }
74472      };
74473      /**
74474       * Converts a boolean, string or number to its string representation.
74475       * When an array of values is passed in, then an array of strings of the same
74476       * length is returned.
74477       *
74478       * @method str
74479       * @param {String|Boolean|Number|Array} n value to parse
74480       * @return {String}                     string representation of value
74481       * @example
74482       * <div class='norender'><code>
74483       * print(str('10')); // "10"
74484       * print(str(10.31)); // "10.31"
74485       * print(str(-10)); // "-10"
74486       * print(str(true)); // "true"
74487       * print(str(false)); // "false"
74488       * print(str([true, '10.3', 9.8])); // [ "true", "10.3", "9.8" ]
74489       * </code></div>
74490       */
74491
74492
74493      p5.prototype.str = function (n) {
74494        if (n instanceof Array) {
74495          return n.map(p5.prototype.str);
74496        } else {
74497          return String(n);
74498        }
74499      };
74500      /**
74501       * Converts a number or string to its boolean representation.
74502       * For a number, any non-zero value (positive or negative) evaluates to true,
74503       * while zero evaluates to false. For a string, the value "true" evaluates to
74504       * true, while any other value evaluates to false. When an array of number or
74505       * string values is passed in, then a array of booleans of the same length is
74506       * returned.
74507       *
74508       * @method boolean
74509       * @param {String|Boolean|Number|Array} n value to parse
74510       * @return {Boolean}                    boolean representation of value
74511       * @example
74512       * <div class='norender'><code>
74513       * print(boolean(0)); // false
74514       * print(boolean(1)); // true
74515       * print(boolean('true')); // true
74516       * print(boolean('abcd')); // false
74517       * print(boolean([0, 12, 'true'])); // [false, true, false]
74518       * </code></div>
74519       */
74520
74521
74522      p5.prototype.boolean = function (n) {
74523        if (typeof n === 'number') {
74524          return n !== 0;
74525        } else if (typeof n === 'string') {
74526          return n.toLowerCase() === 'true';
74527        } else if (typeof n === 'boolean') {
74528          return n;
74529        } else if (n instanceof Array) {
74530          return n.map(p5.prototype.boolean);
74531        }
74532      };
74533      /**
74534       * Converts a number, string representation of a number, or boolean to its byte
74535       * representation. A byte can be only a whole number between -128 and 127, so
74536       * when a value outside of this range is converted, it wraps around to the
74537       * corresponding byte representation. When an array of number, string or boolean
74538       * values is passed in, then an array of bytes the same length is returned.
74539       *
74540       * @method byte
74541       * @param {String|Boolean|Number}       n value to parse
74542       * @return {Number}                     byte representation of value
74543       *
74544       * @example
74545       * <div class='norender'><code>
74546       * print(byte(127)); // 127
74547       * print(byte(128)); // -128
74548       * print(byte(23.4)); // 23
74549       * print(byte('23.4')); // 23
74550       * print(byte('hello')); // NaN
74551       * print(byte(true)); // 1
74552       * print(byte([0, 255, '100'])); // [0, -1, 100]
74553       * </code></div>
74554       */
74555
74556      /**
74557       * @method byte
74558       * @param {Array} ns                   values to parse
74559       * @return {Number[]}                  array of byte representation of values
74560       */
74561
74562
74563      p5.prototype.byte = function (n) {
74564        var nn = p5.prototype.int(n, 10);
74565
74566        if (typeof nn === 'number') {
74567          return (nn + 128) % 256 - 128;
74568        } else if (nn instanceof Array) {
74569          return nn.map(p5.prototype.byte);
74570        }
74571      };
74572      /**
74573       * Converts a number or string to its corresponding single-character
74574       * string representation. If a string parameter is provided, it is first
74575       * parsed as an integer and then translated into a single-character string.
74576       * When an array of number or string values is passed in, then an array of
74577       * single-character strings of the same length is returned.
74578       *
74579       * @method char
74580       * @param {String|Number}       n value to parse
74581       * @return {String}             string representation of value
74582       *
74583       * @example
74584       * <div class='norender'><code>
74585       * print(char(65)); // "A"
74586       * print(char('65')); // "A"
74587       * print(char([65, 66, 67])); // [ "A", "B", "C" ]
74588       * print(join(char([65, 66, 67]), '')); // "ABC"
74589       * </code></div>
74590       */
74591
74592      /**
74593       * @method char
74594       * @param {Array} ns              values to parse
74595       * @return {String[]}             array of string representation of values
74596       */
74597
74598
74599      p5.prototype.char = function (n) {
74600        if (typeof n === 'number' && !isNaN(n)) {
74601          return String.fromCharCode(n);
74602        } else if (n instanceof Array) {
74603          return n.map(p5.prototype.char);
74604        } else if (typeof n === 'string') {
74605          return p5.prototype.char(parseInt(n, 10));
74606        }
74607      };
74608      /**
74609       * Converts a single-character string to its corresponding integer
74610       * representation. When an array of single-character string values is passed
74611       * in, then an array of integers of the same length is returned.
74612       *
74613       * @method unchar
74614       * @param {String} n     value to parse
74615       * @return {Number}      integer representation of value
74616       *
74617       * @example
74618       * <div class='norender'><code>
74619       * print(unchar('A')); // 65
74620       * print(unchar(['A', 'B', 'C'])); // [ 65, 66, 67 ]
74621       * print(unchar(split('ABC', ''))); // [ 65, 66, 67 ]
74622       * </code></div>
74623       */
74624
74625      /**
74626       * @method unchar
74627       * @param {Array} ns       values to parse
74628       * @return {Number[]}      integer representation of values
74629       */
74630
74631
74632      p5.prototype.unchar = function (n) {
74633        if (typeof n === 'string' && n.length === 1) {
74634          return n.charCodeAt(0);
74635        } else if (n instanceof Array) {
74636          return n.map(p5.prototype.unchar);
74637        }
74638      };
74639      /**
74640       * Converts a number to a string in its equivalent hexadecimal notation. If a
74641       * second parameter is passed, it is used to set the number of characters to
74642       * generate in the hexadecimal notation. When an array is passed in, an
74643       * array of strings in hexadecimal notation of the same length is returned.
74644       *
74645       * @method hex
74646       * @param {Number} n     value to parse
74647       * @param {Number} [digits]
74648       * @return {String}      hexadecimal string representation of value
74649       *
74650       * @example
74651       * <div class='norender'><code>
74652       * print(hex(255)); // "000000FF"
74653       * print(hex(255, 6)); // "0000FF"
74654       * print(hex([0, 127, 255], 6)); // [ "000000", "00007F", "0000FF" ]
74655       * </code></div>
74656       */
74657
74658      /**
74659       * @method hex
74660       * @param {Number[]} ns    array of values to parse
74661       * @param {Number} [digits]
74662       * @return {String[]}      hexadecimal string representation of values
74663       */
74664
74665
74666      p5.prototype.hex = function (n, digits) {
74667        digits = digits === undefined || digits === null ? digits = 8 : digits;
74668
74669        if (n instanceof Array) {
74670          return n.map(function (n) {
74671            return p5.prototype.hex(n, digits);
74672          });
74673        } else if (typeof n === 'number') {
74674          if (n < 0) {
74675            n = 0xffffffff + n + 1;
74676          }
74677
74678          var hex = Number(n).toString(16).toUpperCase();
74679
74680          while (hex.length < digits) {
74681            hex = '0' + hex;
74682          }
74683
74684          if (hex.length >= digits) {
74685            hex = hex.substring(hex.length - digits, hex.length);
74686          }
74687
74688          return hex;
74689        }
74690      };
74691      /**
74692       * Converts a string representation of a hexadecimal number to its equivalent
74693       * integer value. When an array of strings in hexadecimal notation is passed
74694       * in, an array of integers of the same length is returned.
74695       *
74696       * @method unhex
74697       * @param {String} n value to parse
74698       * @return {Number}      integer representation of hexadecimal value
74699       *
74700       * @example
74701       * <div class='norender'><code>
74702       * print(unhex('A')); // 10
74703       * print(unhex('FF')); // 255
74704       * print(unhex(['FF', 'AA', '00'])); // [ 255, 170, 0 ]
74705       * </code></div>
74706       */
74707
74708      /**
74709       * @method unhex
74710       * @param {Array} ns values to parse
74711       * @return {Number[]}      integer representations of hexadecimal value
74712       */
74713
74714
74715      p5.prototype.unhex = function (n) {
74716        if (n instanceof Array) {
74717          return n.map(p5.prototype.unhex);
74718        } else {
74719          return parseInt('0x' + n, 16);
74720        }
74721      };
74722
74723      module.exports = p5;
74724    }, {
74725      "../core/main": 24
74726    }],
74727    62: [function (_dereq_, module, exports) {
74728      /**
74729       * @module Data
74730       * @submodule String Functions
74731       * @for p5
74732       * @requires core
74733       */
74734      'use strict';
74735
74736      var p5 = _dereq_('../core/main');
74737
74738      _dereq_('../core/error_helpers'); //return p5; //LM is this a mistake?
74739
74740      /**
74741       * Combines an array of Strings into one String, each separated by the
74742       * character(s) used for the separator parameter. To join arrays of ints or
74743       * floats, it's necessary to first convert them to Strings using <a href="#/p5/nf">nf()</a> or
74744       * nfs().
74745       *
74746       * @method join
74747       * @param  {Array}  list      array of Strings to be joined
74748       * @param  {String} separator String to be placed between each item
74749       * @return {String}           joined String
74750       * @example
74751       * <div>
74752       * <code>
74753       * var array = ['Hello', 'world!'];
74754       * var separator = ' ';
74755       * var message = join(array, separator);
74756       * text(message, 5, 50);
74757       * </code>
74758       * </div>
74759       *
74760       * @alt
74761       * "hello world!" displayed middle left of canvas.
74762       *
74763       */
74764
74765
74766      p5.prototype.join = function (list, separator) {
74767        p5._validateParameters('join', arguments);
74768
74769        return list.join(separator);
74770      };
74771      /**
74772       * This function is used to apply a regular expression to a piece of text,
74773       * and return matching groups (elements found inside parentheses) as a
74774       * String array. If there are no matches, a null value will be returned.
74775       * If no groups are specified in the regular expression, but the sequence
74776       * matches, an array of length 1 (with the matched text as the first element
74777       * of the array) will be returned.
74778       * <br><br>
74779       * To use the function, first check to see if the result is null. If the
74780       * result is null, then the sequence did not match at all. If the sequence
74781       * did match, an array is returned.
74782       * <br><br>
74783       * If there are groups (specified by sets of parentheses) in the regular
74784       * expression, then the contents of each will be returned in the array.
74785       * Element [0] of a regular expression match returns the entire matching
74786       * string, and the match groups start at element [1] (the first group is [1],
74787       * the second [2], and so on).
74788       *
74789       * @method match
74790       * @param  {String} str    the String to be searched
74791       * @param  {String} regexp the regexp to be used for matching
74792       * @return {String[]}      Array of Strings found
74793       * @example
74794       * <div>
74795       * <code>
74796       * var string = 'Hello p5js*!';
74797       * var regexp = 'p5js\\*';
74798       * var m = match(string, regexp);
74799       * text(m, 5, 50);
74800       * </code>
74801       * </div>
74802       *
74803       * @alt
74804       * "p5js*" displayed middle left of canvas.
74805       *
74806       */
74807
74808
74809      p5.prototype.match = function (str, reg) {
74810        p5._validateParameters('match', arguments);
74811
74812        return str.match(reg);
74813      };
74814      /**
74815       * This function is used to apply a regular expression to a piece of text,
74816       * and return a list of matching groups (elements found inside parentheses)
74817       * as a two-dimensional String array. If there are no matches, a null value
74818       * will be returned. If no groups are specified in the regular expression,
74819       * but the sequence matches, a two dimensional array is still returned, but
74820       * the second dimension is only of length one.
74821       * <br><br>
74822       * To use the function, first check to see if the result is null. If the
74823       * result is null, then the sequence did not match at all. If the sequence
74824       * did match, a 2D array is returned.
74825       * <br><br>
74826       * If there are groups (specified by sets of parentheses) in the regular
74827       * expression, then the contents of each will be returned in the array.
74828       * Assuming a loop with counter variable i, element [i][0] of a regular
74829       * expression match returns the entire matching string, and the match groups
74830       * start at element [i][1] (the first group is [i][1], the second [i][2],
74831       * and so on).
74832       *
74833       * @method matchAll
74834       * @param  {String} str    the String to be searched
74835       * @param  {String} regexp the regexp to be used for matching
74836       * @return {String[]}         2d Array of Strings found
74837       * @example
74838       * <div class="norender">
74839       * <code>
74840       * var string = 'Hello p5js*! Hello world!';
74841       * var regexp = 'Hello';
74842       * matchAll(string, regexp);
74843       * </code>
74844       * </div>
74845       */
74846
74847
74848      p5.prototype.matchAll = function (str, reg) {
74849        p5._validateParameters('matchAll', arguments);
74850
74851        var re = new RegExp(reg, 'g');
74852        var match = re.exec(str);
74853        var matches = [];
74854
74855        while (match !== null) {
74856          matches.push(match); // matched text: match[0]
74857          // match start: match.index
74858          // capturing group n: match[n]
74859
74860          match = re.exec(str);
74861        }
74862
74863        return matches;
74864      };
74865      /**
74866       * Utility function for formatting numbers into strings. There are two
74867       * versions: one for formatting floats, and one for formatting ints.
74868       * The values for the digits, left, and right parameters should always
74869       * be positive integers.
74870       * (NOTE): Be cautious when using left and right parameters as it prepends numbers of 0's if the parameter
74871       * if greater than the current length of the number.
74872       * For example if number is 123.2 and left parameter passed is 4 which is greater than length of 123
74873       * (integer part) i.e 3 than result will be 0123.2. Same case for right parameter i.e. if right is 3 than
74874       * the result will be 123.200.
74875       *
74876       * @method nf
74877       * @param {Number|String}       num      the Number to format
74878       * @param {Integer|String}      [left]   number of digits to the left of the
74879       *                                decimal point
74880       * @param {Integer|String}      [right]  number of digits to the right of the
74881       *                                decimal point
74882       * @return {String}               formatted String
74883       *
74884       * @example
74885       * <div>
74886       * <code>
74887       * var myFont;
74888       * function preload() {
74889       *   myFont = loadFont('assets/fonts/inconsolata.ttf');
74890       * }
74891       * function setup() {
74892       *   background(200);
74893       *   var num1 = 321;
74894       *   var num2 = -1321;
74895       *
74896       *   noStroke();
74897       *   fill(0);
74898       *   textFont(myFont);
74899       *   textSize(22);
74900       *
74901       *   text(nf(num1, 4, 2), 10, 30);
74902       *   text(nf(num2, 4, 2), 10, 80);
74903       *   // Draw dividing line
74904       *   stroke(120);
74905       *   line(0, 50, width, 50);
74906       * }
74907       * </code>
74908       * </div>
74909       *
74910       * @alt
74911       * "0321.00" middle top, -1321.00" middle bottom canvas
74912       */
74913
74914      /**
74915       * @method nf
74916       * @param {Array}        nums     the Numbers to format
74917       * @param {Integer|String}      [left]
74918       * @param {Integer|String}      [right]
74919       * @return {String[]}                formatted Strings
74920       */
74921
74922
74923      p5.prototype.nf = function (nums, left, right) {
74924        p5._validateParameters('nf', arguments);
74925
74926        if (nums instanceof Array) {
74927          return nums.map(function (x) {
74928            return doNf(x, left, right);
74929          });
74930        } else {
74931          var typeOfFirst = Object.prototype.toString.call(nums);
74932
74933          if (typeOfFirst === '[object Arguments]') {
74934            if (nums.length === 3) {
74935              return this.nf(nums[0], nums[1], nums[2]);
74936            } else if (nums.length === 2) {
74937              return this.nf(nums[0], nums[1]);
74938            } else {
74939              return this.nf(nums[0]);
74940            }
74941          } else {
74942            return doNf(nums, left, right);
74943          }
74944        }
74945      };
74946
74947      function doNf(num, left, right) {
74948        var neg = num < 0;
74949        var n = neg ? num.toString().substring(1) : num.toString();
74950        var decimalInd = n.indexOf('.');
74951        var intPart = decimalInd !== -1 ? n.substring(0, decimalInd) : n;
74952        var decPart = decimalInd !== -1 ? n.substring(decimalInd + 1) : '';
74953        var str = neg ? '-' : '';
74954
74955        if (typeof right !== 'undefined') {
74956          var decimal = '';
74957
74958          if (decimalInd !== -1 || right - decPart.length > 0) {
74959            decimal = '.';
74960          }
74961
74962          if (decPart.length > right) {
74963            decPart = decPart.substring(0, right);
74964          }
74965
74966          for (var i = 0; i < left - intPart.length; i++) {
74967            str += '0';
74968          }
74969
74970          str += intPart;
74971          str += decimal;
74972          str += decPart;
74973
74974          for (var j = 0; j < right - decPart.length; j++) {
74975            str += '0';
74976          }
74977
74978          return str;
74979        } else {
74980          for (var k = 0; k < Math.max(left - intPart.length, 0); k++) {
74981            str += '0';
74982          }
74983
74984          str += n;
74985          return str;
74986        }
74987      }
74988      /**
74989       * Utility function for formatting numbers into strings and placing
74990       * appropriate commas to mark units of 1000. There are two versions: one
74991       * for formatting ints, and one for formatting an array of ints. The value
74992       * for the right parameter should always be a positive integer.
74993       *
74994       * @method nfc
74995       * @param  {Number|String}   num     the Number to format
74996       * @param  {Integer|String}  [right] number of digits to the right of the
74997       *                                  decimal point
74998       * @return {String}           formatted String
74999       *
75000       * @example
75001       * <div>
75002       * <code>
75003       * function setup() {
75004       *   background(200);
75005       *   var num = 11253106.115;
75006       *   var numArr = [1, 1, 2];
75007       *
75008       *   noStroke();
75009       *   fill(0);
75010       *   textSize(12);
75011       *
75012       *   // Draw formatted numbers
75013       *   text(nfc(num, 4), 10, 30);
75014       *   text(nfc(numArr, 2), 10, 80);
75015       *
75016       *   // Draw dividing line
75017       *   stroke(120);
75018       *   line(0, 50, width, 50);
75019       * }
75020       * </code>
75021       * </div>
75022       *
75023       * @alt
75024       * "11,253,106.115" top middle and "1.00,1.00,2.00" displayed bottom mid
75025       */
75026
75027      /**
75028       * @method nfc
75029       * @param  {Array}    nums     the Numbers to format
75030       * @param  {Integer|String}  [right]
75031       * @return {String[]}           formatted Strings
75032       */
75033
75034
75035      p5.prototype.nfc = function (num, right) {
75036        p5._validateParameters('nfc', arguments);
75037
75038        if (num instanceof Array) {
75039          return num.map(function (x) {
75040            return doNfc(x, right);
75041          });
75042        } else {
75043          return doNfc(num, right);
75044        }
75045      };
75046
75047      function doNfc(num, right) {
75048        num = num.toString();
75049        var dec = num.indexOf('.');
75050        var rem = dec !== -1 ? num.substring(dec) : '';
75051        var n = dec !== -1 ? num.substring(0, dec) : num;
75052        n = n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
75053
75054        if (right === 0) {
75055          rem = '';
75056        } else if (typeof right !== 'undefined') {
75057          if (right > rem.length) {
75058            rem += dec === -1 ? '.' : '';
75059            var len = right - rem.length + 1;
75060
75061            for (var i = 0; i < len; i++) {
75062              rem += '0';
75063            }
75064          } else {
75065            rem = rem.substring(0, right + 1);
75066          }
75067        }
75068
75069        return n + rem;
75070      }
75071      /**
75072       * Utility function for formatting numbers into strings. Similar to <a href="#/p5/nf">nf()</a> but
75073       * puts a "+" in front of positive numbers and a "-" in front of negative
75074       * numbers. There are two versions: one for formatting floats, and one for
75075       * formatting ints. The values for left, and right parameters
75076       * should always be positive integers.
75077       *
75078       * @method nfp
75079       * @param {Number} num      the Number to format
75080       * @param {Integer}      [left]   number of digits to the left of the decimal
75081       *                                point
75082       * @param {Integer}      [right]  number of digits to the right of the
75083       *                                decimal point
75084       * @return {String}         formatted String
75085       *
75086       * @example
75087       * <div>
75088       * <code>
75089       * function setup() {
75090       *   background(200);
75091       *   var num1 = 11253106.115;
75092       *   var num2 = -11253106.115;
75093       *
75094       *   noStroke();
75095       *   fill(0);
75096       *   textSize(12);
75097       *
75098       *   // Draw formatted numbers
75099       *   text(nfp(num1, 4, 2), 10, 30);
75100       *   text(nfp(num2, 4, 2), 10, 80);
75101       *
75102       *   // Draw dividing line
75103       *   stroke(120);
75104       *   line(0, 50, width, 50);
75105       * }
75106       * </code>
75107       * </div>
75108       *
75109       * @alt
75110       * "+11253106.11" top middle and "-11253106.11" displayed bottom middle
75111       */
75112
75113      /**
75114       * @method nfp
75115       * @param {Number[]} nums      the Numbers to format
75116       * @param {Integer}      [left]
75117       * @param {Integer}      [right]
75118       * @return {String[]}         formatted Strings
75119       */
75120
75121
75122      p5.prototype.nfp = function () {
75123        p5._validateParameters('nfp', arguments);
75124
75125        var nfRes = p5.prototype.nf.apply(this, arguments);
75126
75127        if (nfRes instanceof Array) {
75128          return nfRes.map(addNfp);
75129        } else {
75130          return addNfp(nfRes);
75131        }
75132      };
75133
75134      function addNfp(num) {
75135        return parseFloat(num) > 0 ? '+' + num.toString() : num.toString();
75136      }
75137      /**
75138       * Utility function for formatting numbers into strings. Similar to <a href="#/p5/nf">nf()</a> but
75139       * puts an additional "_" (space) in front of positive numbers just in case to align it with negative
75140       * numbers which includes "-" (minus) sign.
75141       * The main usecase of nfs() can be seen when one wants to align the digits (place values) of a positive
75142       * number with some negative number (See the example to get a clear picture).
75143       * There are two versions: one for formatting float, and one for formatting int.
75144       * The values for the digits, left, and right parameters should always be positive integers.
75145       * (IMP): The result on the canvas basically the expected alignment can vary based on the typeface you are using.
75146       * (NOTE): Be cautious when using left and right parameters as it prepends numbers of 0's if the parameter
75147       * if greater than the current length of the number.
75148       * For example if number is 123.2 and left parameter passed is 4 which is greater than length of 123
75149       * (integer part) i.e 3 than result will be 0123.2. Same case for right parameter i.e. if right is 3 than
75150       * the result will be 123.200.
75151       *
75152       * @method nfs
75153       * @param {Number}       num      the Number to format
75154       * @param {Integer}      [left]   number of digits to the left of the decimal
75155       *                                point
75156       * @param {Integer}      [right]  number of digits to the right of the
75157       *                                decimal point
75158       * @return {String}         formatted String
75159       *
75160       * @example
75161       * <div>
75162       * <code>
75163       * var myFont;
75164       * function preload() {
75165       *   myFont = loadFont('assets/fonts/inconsolata.ttf');
75166       * }
75167       * function setup() {
75168       *   background(200);
75169       *   var num1 = 321;
75170       *   var num2 = -1321;
75171       *
75172       *   noStroke();
75173       *   fill(0);
75174       *   textFont(myFont);
75175       *   textSize(22);
75176       *
75177       *   // nfs() aligns num1 (positive number) with num2 (negative number) by
75178       *   // adding a blank space in front of the num1 (positive number)
75179       *   // [left = 4] in num1 add one 0 in front, to align the digits with num2
75180       *   // [right = 2] in num1 and num2 adds two 0's after both numbers
75181       *   // To see the differences check the example of nf() too.
75182       *   text(nfs(num1, 4, 2), 10, 30);
75183       *   text(nfs(num2, 4, 2), 10, 80);
75184       *   // Draw dividing line
75185       *   stroke(120);
75186       *   line(0, 50, width, 50);
75187       * }
75188       * </code>
75189       * </div>
75190       *
75191       * @alt
75192       * "0321.00" top middle and "-1321.00" displayed bottom middle
75193       */
75194
75195      /**
75196       * @method nfs
75197       * @param {Array}        nums     the Numbers to format
75198       * @param {Integer}      [left]
75199       * @param {Integer}      [right]
75200       * @return {String[]}         formatted Strings
75201       */
75202
75203
75204      p5.prototype.nfs = function () {
75205        p5._validateParameters('nfs', arguments);
75206
75207        var nfRes = p5.prototype.nf.apply(this, arguments);
75208
75209        if (nfRes instanceof Array) {
75210          return nfRes.map(addNfs);
75211        } else {
75212          return addNfs(nfRes);
75213        }
75214      };
75215
75216      function addNfs(num) {
75217        return parseFloat(num) > 0 ? ' ' + num.toString() : num.toString();
75218      }
75219      /**
75220       * The <a href="#/p5/split">split()</a> function maps to String.split(), it breaks a String into
75221       * pieces using a character or string as the delimiter. The delim parameter
75222       * specifies the character or characters that mark the boundaries between
75223       * each piece. A String[] array is returned that contains each of the pieces.
75224       *
75225       * The <a href="#/p5/splitTokens">splitTokens()</a> function works in a similar fashion, except that it
75226       * splits using a range of characters instead of a specific character or
75227       * sequence.
75228       *
75229       * @method split
75230       * @param  {String} value the String to be split
75231       * @param  {String} delim the String used to separate the data
75232       * @return {String[]}  Array of Strings
75233       * @example
75234       * <div>
75235       * <code>
75236       * var names = 'Pat,Xio,Alex';
75237       * var splitString = split(names, ',');
75238       * text(splitString[0], 5, 30);
75239       * text(splitString[1], 5, 50);
75240       * text(splitString[2], 5, 70);
75241       * </code>
75242       * </div>
75243       *
75244       * @alt
75245       * "pat" top left, "Xio" mid left and "Alex" displayed bottom left
75246       *
75247       */
75248
75249
75250      p5.prototype.split = function (str, delim) {
75251        p5._validateParameters('split', arguments);
75252
75253        return str.split(delim);
75254      };
75255      /**
75256       * The <a href="#/p5/splitTokens">splitTokens()</a> function splits a String at one or many character
75257       * delimiters or "tokens." The delim parameter specifies the character or
75258       * characters to be used as a boundary.
75259       * <br><br>
75260       * If no delim characters are specified, any whitespace character is used to
75261       * split. Whitespace characters include tab (\t), line feed (\n), carriage
75262       * return (\r), form feed (\f), and space.
75263       *
75264       * @method splitTokens
75265       * @param  {String} value   the String to be split
75266       * @param  {String} [delim] list of individual Strings that will be used as
75267       *                          separators
75268       * @return {String[]}          Array of Strings
75269       * @example
75270       * <div class = "norender">
75271       * <code>
75272       * function setup() {
75273       *   var myStr = 'Mango, Banana, Lime';
75274       *   var myStrArr = splitTokens(myStr, ',');
75275       *
75276       *   print(myStrArr); // prints : ["Mango"," Banana"," Lime"]
75277       * }
75278       * </code>
75279       * </div>
75280       */
75281
75282
75283      p5.prototype.splitTokens = function (value, delims) {
75284        p5._validateParameters('splitTokens', arguments);
75285
75286        var d;
75287
75288        if (typeof delims !== 'undefined') {
75289          var str = delims;
75290          var sqc = /\]/g.exec(str);
75291          var sqo = /\[/g.exec(str);
75292
75293          if (sqo && sqc) {
75294            str = str.slice(0, sqc.index) + str.slice(sqc.index + 1);
75295            sqo = /\[/g.exec(str);
75296            str = str.slice(0, sqo.index) + str.slice(sqo.index + 1);
75297            d = new RegExp('[\\[' + str + '\\]]', 'g');
75298          } else if (sqc) {
75299            str = str.slice(0, sqc.index) + str.slice(sqc.index + 1);
75300            d = new RegExp('[' + str + '\\]]', 'g');
75301          } else if (sqo) {
75302            str = str.slice(0, sqo.index) + str.slice(sqo.index + 1);
75303            d = new RegExp('[' + str + '\\[]', 'g');
75304          } else {
75305            d = new RegExp('[' + str + ']', 'g');
75306          }
75307        } else {
75308          d = /\s/g;
75309        }
75310
75311        return value.split(d).filter(function (n) {
75312          return n;
75313        });
75314      };
75315      /**
75316       * Removes whitespace characters from the beginning and end of a String. In
75317       * addition to standard whitespace characters such as space, carriage return,
75318       * and tab, this function also removes the Unicode "nbsp" character.
75319       *
75320       * @method trim
75321       * @param  {String} str a String to be trimmed
75322       * @return {String}       a trimmed String
75323       *
75324       * @example
75325       * <div>
75326       * <code>
75327       * var string = trim('  No new lines\n   ');
75328       * text(string + ' here', 2, 50);
75329       * </code>
75330       * </div>
75331       *
75332       * @alt
75333       * "No new lines here" displayed center canvas
75334       */
75335
75336      /**
75337       * @method trim
75338       * @param  {Array} strs an Array of Strings to be trimmed
75339       * @return {String[]}   an Array of trimmed Strings
75340       */
75341
75342
75343      p5.prototype.trim = function (str) {
75344        p5._validateParameters('trim', arguments);
75345
75346        if (str instanceof Array) {
75347          return str.map(this.trim);
75348        } else {
75349          return str.trim();
75350        }
75351      };
75352
75353      module.exports = p5;
75354    }, {
75355      "../core/error_helpers": 20,
75356      "../core/main": 24
75357    }],
75358    63: [function (_dereq_, module, exports) {
75359      /**
75360       * @module IO
75361       * @submodule Time & Date
75362       * @for p5
75363       * @requires core
75364       */
75365      'use strict';
75366
75367      var p5 = _dereq_('../core/main');
75368      /**
75369       * p5.js communicates with the clock on your computer. The <a href="#/p5/day">day()</a> function
75370       * returns the current day as a value from 1 - 31.
75371       *
75372       * @method day
75373       * @return {Integer} the current day
75374       * @example
75375       * <div>
75376       * <code>
75377       * var d = day();
75378       * text('Current day: \n' + d, 5, 50);
75379       * </code>
75380       * </div>
75381       *
75382       * @alt
75383       * Current day is displayed
75384       *
75385       */
75386
75387
75388      p5.prototype.day = function () {
75389        return new Date().getDate();
75390      };
75391      /**
75392       * p5.js communicates with the clock on your computer. The <a href="#/p5/hour">hour()</a> function
75393       * returns the current hour as a value from 0 - 23.
75394       *
75395       * @method hour
75396       * @return {Integer} the current hour
75397       * @example
75398       * <div>
75399       * <code>
75400       * var h = hour();
75401       * text('Current hour:\n' + h, 5, 50);
75402       * </code>
75403       * </div>
75404       *
75405       * @alt
75406       * Current hour is displayed
75407       *
75408       */
75409
75410
75411      p5.prototype.hour = function () {
75412        return new Date().getHours();
75413      };
75414      /**
75415       * p5.js communicates with the clock on your computer. The <a href="#/p5/minute">minute()</a> function
75416       * returns the current minute as a value from 0 - 59.
75417       *
75418       * @method minute
75419       * @return {Integer} the current minute
75420       * @example
75421       * <div>
75422       * <code>
75423       * var m = minute();
75424       * text('Current minute: \n' + m, 5, 50);
75425       * </code>
75426       * </div>
75427       *
75428       * @alt
75429       * Current minute is displayed
75430       *
75431       */
75432
75433
75434      p5.prototype.minute = function () {
75435        return new Date().getMinutes();
75436      };
75437      /**
75438       * Returns the number of milliseconds (thousandths of a second) since
75439       * starting the program. This information is often used for timing events and
75440       * animation sequences.
75441       *
75442       * @method millis
75443       * @return {Number} the number of milliseconds since starting the program
75444       * @example
75445       * <div>
75446       * <code>
75447       * var millisecond = millis();
75448       * text('Milliseconds \nrunning: \n' + millisecond, 5, 40);
75449       * </code>
75450       * </div>
75451       *
75452       * @alt
75453       * number of milliseconds since program has started displayed
75454       *
75455       */
75456
75457
75458      p5.prototype.millis = function () {
75459        return window.performance.now();
75460      };
75461      /**
75462       * p5.js communicates with the clock on your computer. The <a href="#/p5/month">month()</a> function
75463       * returns the current month as a value from 1 - 12.
75464       *
75465       * @method month
75466       * @return {Integer} the current month
75467       * @example
75468       * <div>
75469       * <code>
75470       * var m = month();
75471       * text('Current month: \n' + m, 5, 50);
75472       * </code>
75473       * </div>
75474       *
75475       * @alt
75476       * Current month is displayed
75477       *
75478       */
75479
75480
75481      p5.prototype.month = function () {
75482        return new Date().getMonth() + 1; //January is 0!
75483      };
75484      /**
75485       * p5.js communicates with the clock on your computer. The <a href="#/p5/second">second()</a> function
75486       * returns the current second as a value from 0 - 59.
75487       *
75488       * @method second
75489       * @return {Integer} the current second
75490       * @example
75491       * <div>
75492       * <code>
75493       * var s = second();
75494       * text('Current second: \n' + s, 5, 50);
75495       * </code>
75496       * </div>
75497       *
75498       * @alt
75499       * Current second is displayed
75500       *
75501       */
75502
75503
75504      p5.prototype.second = function () {
75505        return new Date().getSeconds();
75506      };
75507      /**
75508       * p5.js communicates with the clock on your computer. The <a href="#/p5/year">year()</a> function
75509       * returns the current year as an integer (2014, 2015, 2016, etc).
75510       *
75511       * @method year
75512       * @return {Integer} the current year
75513       * @example
75514       * <div>
75515       * <code>
75516       * var y = year();
75517       * text('Current year: \n' + y, 5, 50);
75518       * </code>
75519       * </div>
75520       *
75521       * @alt
75522       * Current year is displayed
75523       *
75524       */
75525
75526
75527      p5.prototype.year = function () {
75528        return new Date().getFullYear();
75529      };
75530
75531      module.exports = p5;
75532    }, {
75533      "../core/main": 24
75534    }],
75535    64: [function (_dereq_, module, exports) {
75536      /**
75537       * @module Shape
75538       * @submodule 3D Primitives
75539       * @for p5
75540       * @requires core
75541       * @requires p5.Geometry
75542       */
75543      'use strict';
75544
75545      var p5 = _dereq_('../core/main');
75546
75547      _dereq_('./p5.Geometry');
75548
75549      var constants = _dereq_('../core/constants');
75550      /**
75551       * Draw a plane with given a width and height
75552       * @method plane
75553       * @param  {Number} [width]    width of the plane
75554       * @param  {Number} [height]   height of the plane
75555       * @param  {Integer} [detailX]  Optional number of triangle
75556       *                             subdivisions in x-dimension
75557       * @param {Integer} [detailY]   Optional number of triangle
75558       *                             subdivisions in y-dimension
75559       * @chainable
75560       * @example
75561       * <div>
75562       * <code>
75563       * //draw a plane with width 50 and height 50
75564       * function setup() {
75565       *   createCanvas(100, 100, WEBGL);
75566       * }
75567       *
75568       * function draw() {
75569       *   background(200);
75570       *   plane(50, 50);
75571       * }
75572       * </code>
75573       * </div>
75574       *
75575       * @alt
75576       * Nothing displayed on canvas
75577       * Rotating interior view of a box with sides that change color.
75578       * 3d red and green gradient.
75579       * Rotating interior view of a cylinder with sides that change color.
75580       * Rotating view of a cylinder with sides that change color.
75581       * 3d red and green gradient.
75582       * rotating view of a multi-colored cylinder with concave sides.
75583       */
75584
75585
75586      p5.prototype.plane = function (width, height, detailX, detailY) {
75587        this._assert3d('plane');
75588
75589        p5._validateParameters('plane', arguments);
75590
75591        if (typeof width === 'undefined') {
75592          width = 50;
75593        }
75594
75595        if (typeof height === 'undefined') {
75596          height = width;
75597        }
75598
75599        if (typeof detailX === 'undefined') {
75600          detailX = 1;
75601        }
75602
75603        if (typeof detailY === 'undefined') {
75604          detailY = 1;
75605        }
75606
75607        var gId = 'plane|' + detailX + '|' + detailY;
75608
75609        if (!this._renderer.geometryInHash(gId)) {
75610          var _plane = function () {
75611            var u, v, p;
75612
75613            for (var i = 0; i <= this.detailY; i++) {
75614              v = i / this.detailY;
75615
75616              for (var j = 0; j <= this.detailX; j++) {
75617                u = j / this.detailX;
75618                p = new p5.Vector(u - 0.5, v - 0.5, 0);
75619                this.vertices.push(p);
75620                this.uvs.push(u, v);
75621              }
75622            }
75623          };
75624
75625          var planeGeom = new p5.Geometry(detailX, detailY, _plane);
75626          planeGeom.computeFaces().computeNormals();
75627
75628          if (detailX <= 1 && detailY <= 1) {
75629            planeGeom._makeTriangleEdges()._edgesToVertices();
75630          } else {
75631            console.log('Cannot draw stroke on plane objects with more' + ' than 1 detailX or 1 detailY');
75632          }
75633
75634          this._renderer.createBuffers(gId, planeGeom);
75635        }
75636
75637        this._renderer.drawBuffersScaled(gId, width, height, 1);
75638
75639        return this;
75640      };
75641      /**
75642       * Draw a box with given width, height and depth
75643       * @method  box
75644       * @param  {Number} [width]     width of the box
75645       * @param  {Number} [Height]    height of the box
75646       * @param  {Number} [depth]     depth of the box
75647       * @param {Integer} [detailX]  Optional number of triangle
75648       *                            subdivisions in x-dimension
75649       * @param {Integer} [detailY]  Optional number of triangle
75650       *                            subdivisions in y-dimension
75651       * @chainable
75652       * @example
75653       * <div>
75654       * <code>
75655       * //draw a spinning box with width, height and depth 200
75656       * function setup() {
75657       *   createCanvas(100, 100, WEBGL);
75658       * }
75659       *
75660       * function draw() {
75661       *   background(200);
75662       *   rotateX(frameCount * 0.01);
75663       *   rotateY(frameCount * 0.01);
75664       *   box(50);
75665       * }
75666       * </code>
75667       * </div>
75668       */
75669
75670
75671      p5.prototype.box = function (width, height, depth, detailX, detailY) {
75672        this._assert3d('box');
75673
75674        p5._validateParameters('box', arguments);
75675
75676        if (typeof width === 'undefined') {
75677          width = 50;
75678        }
75679
75680        if (typeof height === 'undefined') {
75681          height = width;
75682        }
75683
75684        if (typeof depth === 'undefined') {
75685          depth = height;
75686        }
75687
75688        var perPixelLighting = this._renderer.attributes && this._renderer.attributes.perPixelLighting;
75689
75690        if (typeof detailX === 'undefined') {
75691          detailX = perPixelLighting ? 1 : 4;
75692        }
75693
75694        if (typeof detailY === 'undefined') {
75695          detailY = perPixelLighting ? 1 : 4;
75696        }
75697
75698        var gId = 'box|' + detailX + '|' + detailY;
75699
75700        if (!this._renderer.geometryInHash(gId)) {
75701          var _box = function () {
75702            var cubeIndices = [[0, 4, 2, 6], // -1, 0, 0],// -x
75703            [1, 3, 5, 7], // +1, 0, 0],// +x
75704            [0, 1, 4, 5], // 0, -1, 0],// -y
75705            [2, 6, 3, 7], // 0, +1, 0],// +y
75706            [0, 2, 1, 3], // 0, 0, -1],// -z
75707            [4, 5, 6, 7] // 0, 0, +1] // +z
75708            ]; //using strokeIndices instead of faces for strokes
75709            //to avoid diagonal stroke lines across face of box
75710
75711            this.strokeIndices = [[0, 1], [1, 3], [3, 2], [6, 7], [8, 9], [9, 11], [14, 15], [16, 17], [17, 19], [18, 19], [20, 21], [22, 23]];
75712
75713            for (var i = 0; i < cubeIndices.length; i++) {
75714              var cubeIndex = cubeIndices[i];
75715              var v = i * 4;
75716
75717              for (var j = 0; j < 4; j++) {
75718                var d = cubeIndex[j]; //inspired by lightgl:
75719                //https://github.com/evanw/lightgl.js
75720                //octants:https://en.wikipedia.org/wiki/Octant_(solid_geometry)
75721
75722                var octant = new p5.Vector(((d & 1) * 2 - 1) / 2, ((d & 2) - 1) / 2, ((d & 4) / 2 - 1) / 2);
75723                this.vertices.push(octant);
75724                this.uvs.push(j & 1, (j & 2) / 2);
75725              }
75726
75727              this.faces.push([v, v + 1, v + 2]);
75728              this.faces.push([v + 2, v + 1, v + 3]);
75729            }
75730          };
75731
75732          var boxGeom = new p5.Geometry(detailX, detailY, _box);
75733          boxGeom.computeNormals();
75734
75735          if (detailX <= 4 && detailY <= 4) {
75736            boxGeom._makeTriangleEdges()._edgesToVertices();
75737          } else {
75738            console.log('Cannot draw stroke on box objects with more' + ' than 4 detailX or 4 detailY');
75739          } //initialize our geometry buffer with
75740          //the key val pair:
75741          //geometry Id, Geom object
75742
75743
75744          this._renderer.createBuffers(gId, boxGeom);
75745        }
75746
75747        this._renderer.drawBuffersScaled(gId, width, height, depth);
75748
75749        return this;
75750      };
75751      /**
75752       * Draw a sphere with given radius
75753       * @method sphere
75754       * @param  {Number} [radius]          radius of circle
75755       * @param  {Integer} [detailX]        number of segments,
75756       *                                    the more segments the smoother geometry
75757       *                                    default is 24
75758       * @param  {Integer} [detailY]        number of segments,
75759       *                                    the more segments the smoother geometry
75760       *                                    default is 16
75761       * @chainable
75762       * @example
75763       * <div>
75764       * <code>
75765       * // draw a sphere with radius 200
75766       * function setup() {
75767       *   createCanvas(100, 100, WEBGL);
75768       * }
75769       *
75770       * function draw() {
75771       *   background(200);
75772       *   sphere(40);
75773       * }
75774       * </code>
75775       * </div>
75776       */
75777
75778
75779      p5.prototype.sphere = function (radius, detailX, detailY) {
75780        this._assert3d('sphere');
75781
75782        p5._validateParameters('sphere', arguments);
75783
75784        if (typeof radius === 'undefined') {
75785          radius = 50;
75786        }
75787
75788        if (typeof detailX === 'undefined') {
75789          detailX = 24;
75790        }
75791
75792        if (typeof detailY === 'undefined') {
75793          detailY = 16;
75794        }
75795
75796        this.ellipsoid(radius, radius, radius, detailX, detailY);
75797        return this;
75798      };
75799      /**
75800       * @private
75801       * Helper function for creating both cones and cyllinders
75802       * Will only generate well-defined geometry when bottomRadius, height > 0
75803       * and topRadius >= 0
75804       * If topRadius == 0, topCap should be false
75805       */
75806
75807
75808      var _truncatedCone = function (bottomRadius, topRadius, height, detailX, detailY, bottomCap, topCap) {
75809        bottomRadius = bottomRadius <= 0 ? 1 : bottomRadius;
75810        topRadius = topRadius < 0 ? 0 : topRadius;
75811        height = height <= 0 ? bottomRadius : height;
75812        detailX = detailX < 3 ? 3 : detailX;
75813        detailY = detailY < 1 ? 1 : detailY;
75814        bottomCap = bottomCap === undefined ? true : bottomCap;
75815        topCap = topCap === undefined ? topRadius !== 0 : topCap;
75816        var start = bottomCap ? -2 : 0;
75817        var end = detailY + (topCap ? 2 : 0);
75818        var vertsOnLayer = {}; //ensure constant slant for interior vertex normals
75819
75820        var slant = Math.atan2(bottomRadius - topRadius, height);
75821        var yy, ii, jj, nextii, nextjj;
75822
75823        for (yy = start; yy <= end; ++yy) {
75824          var v = yy / detailY;
75825          var y = height * v;
75826          var ringRadius;
75827
75828          if (yy < 0) {
75829            //for the bottomCap edge
75830            y = 0;
75831            v = 0;
75832            ringRadius = bottomRadius;
75833          } else if (yy > detailY) {
75834            //for the topCap edge
75835            y = height;
75836            v = 1;
75837            ringRadius = topRadius;
75838          } else {
75839            //for the middle
75840            ringRadius = bottomRadius + (topRadius - bottomRadius) * v;
75841          }
75842
75843          if (yy === -2 || yy === detailY + 2) {
75844            //center of bottom or top caps
75845            ringRadius = 0;
75846          }
75847
75848          y -= height / 2; //shift coordiate origin to the center of object
75849
75850          vertsOnLayer[yy] = ringRadius === 0 ? 1 : detailX;
75851
75852          for (ii = 0; ii < vertsOnLayer[yy]; ++ii) {
75853            var u = ii / detailX; //VERTICES
75854
75855            this.vertices.push(new p5.Vector(Math.sin(u * 2 * Math.PI) * ringRadius, y, Math.cos(u * 2 * Math.PI) * ringRadius)); //VERTEX NORMALS
75856
75857            this.vertexNormals.push(new p5.Vector(yy < 0 || yy > detailY ? 0 : Math.sin(u * 2 * Math.PI) * Math.cos(slant), yy < 0 ? -1 : yy > detailY ? 1 : Math.sin(slant), yy < 0 || yy > detailY ? 0 : Math.cos(u * 2 * Math.PI) * Math.cos(slant))); //UVs
75858
75859            this.uvs.push(u, v);
75860          }
75861        }
75862
75863        var startIndex = 0;
75864
75865        if (bottomCap) {
75866          for (jj = 0; jj < vertsOnLayer[-1]; ++jj) {
75867            nextjj = (jj + 1) % vertsOnLayer[-1];
75868            this.faces.push([startIndex, startIndex + 1 + nextjj, startIndex + 1 + jj]);
75869          }
75870
75871          startIndex += vertsOnLayer[-2] + vertsOnLayer[-1];
75872        }
75873
75874        for (yy = 0; yy < detailY; ++yy) {
75875          for (ii = 0; ii < vertsOnLayer[yy]; ++ii) {
75876            if (vertsOnLayer[yy + 1] === 1) {
75877              //top layer
75878              nextii = (ii + 1) % vertsOnLayer[yy];
75879              this.faces.push([startIndex + ii, startIndex + nextii, startIndex + vertsOnLayer[yy]]);
75880            } else {
75881              //other side faces
75882              //should have vertsOnLayer[yy] === vertsOnLayer[yy + 1]
75883              nextii = (ii + 1) % vertsOnLayer[yy];
75884              this.faces.push([startIndex + ii, startIndex + nextii, startIndex + vertsOnLayer[yy] + nextii]);
75885              this.faces.push([startIndex + ii, startIndex + vertsOnLayer[yy] + nextii, startIndex + vertsOnLayer[yy] + ii]);
75886            }
75887          }
75888
75889          startIndex += vertsOnLayer[yy];
75890        }
75891
75892        if (topCap) {
75893          startIndex += vertsOnLayer[detailY];
75894
75895          for (ii = 0; ii < vertsOnLayer[detailY + 1]; ++ii) {
75896            nextii = (ii + 1) % vertsOnLayer[detailY + 1];
75897            this.faces.push([startIndex + ii, startIndex + nextii, startIndex + vertsOnLayer[detailY + 1]]);
75898          }
75899        }
75900      };
75901      /**
75902       * Draw a cylinder with given radius and height
75903       * @method cylinder
75904       * @param  {Number}  [radius]    radius of the surface
75905       * @param  {Number}  [height]    height of the cylinder
75906       * @param  {Integer} [detailX]   number of segments,
75907       *                               the more segments the smoother geometry
75908       *                               default is 24
75909       * @param  {Integer} [detailY]   number of segments in y-dimension,
75910       *                               the more segments the smoother geometry
75911       *                               default is 1
75912       * @param  {Boolean} [bottomCap] whether to draw the bottom of the cylinder
75913       * @param  {Boolean} [topCap]    whether to draw the top of the cylinder
75914       * @chainable
75915       * @example
75916       * <div>
75917       * <code>
75918       * //draw a spinning cylinder with radius 20 and height 50
75919       * function setup() {
75920       *   createCanvas(100, 100, WEBGL);
75921       * }
75922       *
75923       * function draw() {
75924       *   background(200);
75925       *   rotateX(frameCount * 0.01);
75926       *   rotateZ(frameCount * 0.01);
75927       *   cylinder(20, 50);
75928       * }
75929       * </code>
75930       * </div>
75931       */
75932
75933
75934      p5.prototype.cylinder = function (radius, height, detailX, detailY, bottomCap, topCap) {
75935        this._assert3d('cylinder');
75936
75937        p5._validateParameters('cylinder', arguments);
75938
75939        if (typeof radius === 'undefined') {
75940          radius = 50;
75941        }
75942
75943        if (typeof height === 'undefined') {
75944          height = radius;
75945        }
75946
75947        if (typeof detailX === 'undefined') {
75948          detailX = 24;
75949        }
75950
75951        if (typeof detailY === 'undefined') {
75952          detailY = 1;
75953        }
75954
75955        if (typeof topCap === 'undefined') {
75956          topCap = true;
75957        }
75958
75959        if (typeof bottomCap === 'undefined') {
75960          bottomCap = true;
75961        }
75962
75963        var gId = 'cylinder|' + detailX + '|' + detailY + '|' + bottomCap + '|' + topCap;
75964
75965        if (!this._renderer.geometryInHash(gId)) {
75966          var cylinderGeom = new p5.Geometry(detailX, detailY);
75967
75968          _truncatedCone.call(cylinderGeom, 1, 1, 1, detailX, detailY, bottomCap, topCap);
75969
75970          cylinderGeom.computeNormals();
75971
75972          if (detailX <= 24 && detailY <= 16) {
75973            cylinderGeom._makeTriangleEdges()._edgesToVertices();
75974          } else {
75975            console.log('Cannot draw stroke on cylinder objects with more' + ' than 24 detailX or 16 detailY');
75976          }
75977
75978          this._renderer.createBuffers(gId, cylinderGeom);
75979        }
75980
75981        this._renderer.drawBuffersScaled(gId, radius, height, radius);
75982
75983        return this;
75984      };
75985      /**
75986       * Draw a cone with given radius and height
75987       * @method cone
75988       * @param  {Number}  [radius]  radius of the bottom surface
75989       * @param  {Number}  [height]  height of the cone
75990       * @param  {Integer} [detailX] number of segments,
75991       *                             the more segments the smoother geometry
75992       *                             default is 24
75993       * @param  {Integer} [detailY] number of segments,
75994       *                             the more segments the smoother geometry
75995       *                             default is 1
75996       * @param  {Boolean} [cap]     whether to draw the base of the cone
75997       * @chainable
75998       * @example
75999       * <div>
76000       * <code>
76001       * //draw a spinning cone with radius 40 and height 70
76002       * function setup() {
76003       *   createCanvas(100, 100, WEBGL);
76004       * }
76005       *
76006       * function draw() {
76007       *   background(200);
76008       *   rotateX(frameCount * 0.01);
76009       *   rotateZ(frameCount * 0.01);
76010       *   cone(40, 70);
76011       * }
76012       * </code>
76013       * </div>
76014       */
76015
76016
76017      p5.prototype.cone = function (radius, height, detailX, detailY, cap) {
76018        this._assert3d('cone');
76019
76020        p5._validateParameters('cone', arguments);
76021
76022        if (typeof radius === 'undefined') {
76023          radius = 50;
76024        }
76025
76026        if (typeof height === 'undefined') {
76027          height = radius;
76028        }
76029
76030        if (typeof detailX === 'undefined') {
76031          detailX = 24;
76032        }
76033
76034        if (typeof detailY === 'undefined') {
76035          detailY = 1;
76036        }
76037
76038        if (typeof cap === 'undefi
76038ned') {
76039          cap = true;
76040        }
76041
76042        var gId = 'cone|' + detailX + '|' + detailY + '|' + cap;
76043
76044        if (!this._renderer.geometryInHash(gId)) {
76045          var coneGeom = new p5.Geometry(detailX, detailY);
76046
76047          _truncatedCone.call(coneGeom, 1, 0, 1, detailX, detailY, cap, false); //for cones we need to average Normals
76048
76049
76050          coneGeom.computeNormals();
76051
76052          if (detailX <= 24 && detailY <= 16) {
76053            coneGeom._makeTriangleEdges()._edgesToVertices();
76054          } else {
76055            console.log('Cannot draw stroke on cone objects with more' + ' than 24 detailX or 16 detailY');
76056          }
76057
76058          this._renderer.createBuffers(gId, coneGeom);
76059        }
76060
76061        this._renderer.drawBuffersScaled(gId, radius, height, radius);
76062
76063        return this;
76064      };
76065      /**
76066       * Draw an ellipsoid with given radius
76067       * @method ellipsoid
76068       * @param  {Number} [radiusx]         xradius of circle
76069       * @param  {Number} [radiusy]         yradius of circle
76070       * @param  {Number} [radiusz]         zradius of circle
76071       * @param  {Integer} [detailX]        number of segments,
76072       *                                    the more segments the smoother geometry
76073       *                                    default is 24. Avoid detail number above
76074       *                                    150, it may crash the browser.
76075       * @param  {Integer} [detailY]        number of segments,
76076       *                                    the more segments the smoother geometry
76077       *                                    default is 16. Avoid detail number above
76078       *                                    150, it may crash the browser.
76079       * @chainable
76080       * @example
76081       * <div>
76082       * <code>
76083       * // draw an ellipsoid with radius 20, 30 and 40.
76084       * function setup() {
76085       *   createCanvas(100, 100, WEBGL);
76086       * }
76087       *
76088       * function draw() {
76089       *   background(200);
76090       *   ellipsoid(20, 30, 40);
76091       * }
76092       * </code>
76093       * </div>
76094       */
76095
76096
76097      p5.prototype.ellipsoid = function (radiusX, radiusY, radiusZ, detailX, detailY) {
76098        this._assert3d('ellipsoid');
76099
76100        p5._validateParameters('ellipsoid', arguments);
76101
76102        if (typeof radiusX === 'undefined') {
76103          radiusX = 50;
76104        }
76105
76106        if (typeof radiusY === 'undefined') {
76107          radiusY = radiusX;
76108        }
76109
76110        if (typeof radiusZ === 'undefined') {
76111          radiusZ = radiusX;
76112        }
76113
76114        if (typeof detailX === 'undefined') {
76115          detailX = 24;
76116        }
76117
76118        if (typeof detailY === 'undefined') {
76119          detailY = 16;
76120        }
76121
76122        var gId = 'ellipsoid|' + detailX + '|' + detailY;
76123
76124        if (!this._renderer.geometryInHash(gId)) {
76125          var _ellipsoid = function () {
76126            for (var i = 0; i <= this.detailY; i++) {
76127              var v = i / this.detailY;
76128              var phi = Math.PI * v - Math.PI / 2;
76129              var cosPhi = Math.cos(phi);
76130              var sinPhi = Math.sin(phi);
76131
76132              for (var j = 0; j <= this.detailX; j++) {
76133                var u = j / this.detailX;
76134                var theta = 2 * Math.PI * u;
76135                var cosTheta = Math.cos(theta);
76136                var sinTheta = Math.sin(theta);
76137                var p = new p5.Vector(cosPhi * sinTheta, sinPhi, cosPhi * cosTheta);
76138                this.vertices.push(p);
76139                this.vertexNormals.push(p);
76140                this.uvs.push(u, v);
76141              }
76142            }
76143          };
76144
76145          var ellipsoidGeom = new p5.Geometry(detailX, detailY, _ellipsoid);
76146          ellipsoidGeom.computeFaces();
76147
76148          if (detailX <= 24 && detailY <= 24) {
76149            ellipsoidGeom._makeTriangleEdges()._edgesToVertices();
76150          } else {
76151            console.log('Cannot draw stroke on ellipsoids with more' + ' than 24 detailX or 24 detailY');
76152          }
76153
76154          this._renderer.createBuffers(gId, ellipsoidGeom);
76155        }
76156
76157        this._renderer.drawBuffersScaled(gId, radiusX, radiusY, radiusZ);
76158
76159        return this;
76160      };
76161      /**
76162       * Draw a torus with given radius and tube radius
76163       * @method torus
76164       * @param  {Number} [radius]      radius of the whole ring
76165       * @param  {Number} [tubeRadius]  radius of the tube
76166       * @param  {Integer} [detailX]    number of segments in x-dimension,
76167       *                                the more segments the smoother geometry
76168       *                                default is 24
76169       * @param  {Integer} [detailY]    number of segments in y-dimension,
76170       *                                the more segments the smoother geometry
76171       *                                default is 16
76172       * @chainable
76173       * @example
76174       * <div>
76175       * <code>
76176       * //draw a spinning torus with radius 200 and tube radius 60
76177       * function setup() {
76178       *   createCanvas(100, 100, WEBGL);
76179       * }
76180       *
76181       * function draw() {
76182       *   background(200);
76183       *   rotateX(frameCount * 0.01);
76184       *   rotateY(frameCount * 0.01);
76185       *   torus(50, 15);
76186       * }
76187       * </code>
76188       * </div>
76189       */
76190
76191
76192      p5.prototype.torus = function (radius, tubeRadius, detailX, detailY) {
76193        this._assert3d('torus');
76194
76195        p5._validateParameters('torus', arguments);
76196
76197        if (typeof radius === 'undefined') {
76198          radius = 50;
76199        } else if (!radius) {
76200          return; // nothing to draw
76201        }
76202
76203        if (typeof tubeRadius === 'undefined') {
76204          tubeRadius = 10;
76205        } else if (!tubeRadius) {
76206          return; // nothing to draw
76207        }
76208
76209        if (typeof detailX === 'undefined') {
76210          detailX = 24;
76211        }
76212
76213        if (typeof detailY === 'undefined') {
76214          detailY = 16;
76215        }
76216
76217        var tubeRatio = (tubeRadius / radius).toPrecision(4);
76218        var gId = 'torus|' + tubeRatio + '|' + detailX + '|' + detailY;
76219
76220        if (!this._renderer.geometryInHash(gId)) {
76221          var _torus = function () {
76222            for (var i = 0; i <= this.detailY; i++) {
76223              var v = i / this.detailY;
76224              var phi = 2 * Math.PI * v;
76225              var cosPhi = Math.cos(phi);
76226              var sinPhi = Math.sin(phi);
76227              var r = 1 + tubeRatio * cosPhi;
76228
76229              for (var j = 0; j <= this.detailX; j++) {
76230                var u = j / this.detailX;
76231                var theta = 2 * Math.PI * u;
76232                var cosTheta = Math.cos(theta);
76233                var sinTheta = Math.sin(theta);
76234                var p = new p5.Vector(r * cosTheta, r * sinTheta, tubeRatio * sinPhi);
76235                var n = new p5.Vector(cosPhi * cosTheta, cosPhi * sinTheta, sinPhi);
76236                this.vertices.push(p);
76237                this.vertexNormals.push(n);
76238                this.uvs.push(u, v);
76239              }
76240            }
76241          };
76242
76243          var torusGeom = new p5.Geometry(detailX, detailY, _torus);
76244          torusGeom.computeFaces();
76245
76246          if (detailX <= 24 && detailY <= 16) {
76247            torusGeom._makeTriangleEdges()._edgesToVertices();
76248          } else {
76249            console.log('Cannot draw strokes on torus object with more' + ' than 24 detailX or 16 detailY');
76250          }
76251
76252          this._renderer.createBuffers(gId, torusGeom);
76253        }
76254
76255        this._renderer.drawBuffersScaled(gId, radius, radius, radius);
76256
76257        return this;
76258      }; ///////////////////////
76259      /// 2D primitives
76260      /////////////////////////
76261
76262      /**
76263       * Draws a point, a coordinate in space at the dimension of one pixel,
76264       * given x, y and z coordinates. The color of the point is determined
76265       * by the current stroke, while the point size is determined by current
76266       * stroke weight.
76267       * @private
76268       * @param {Number} x x-coordinate of point
76269       * @param {Number} y y-coordinate of point
76270       * @param {Number} z z-coordinate of point
76271       * @chainable
76272       * @example
76273       * <div>
76274       * <code>
76275       * function setup() {
76276       *   createCanvas(100, 100, WEBGL);
76277       * }
76278       *
76279       * function draw() {
76280       *   background(50);
76281       *   stroke(255);
76282       *   strokeWeight(4);
76283       *   point(25, 0);
76284       *   strokeWeight(3);
76285       *   point(-25, 0);
76286       *   strokeWeight(2);
76287       *   point(0, 25);
76288       *   strokeWeight(1);
76289       *   point(0, -25);
76290       * }
76291       * </code>
76292       * </div>
76293       */
76294
76295
76296      p5.RendererGL.prototype.point = function (x, y, z) {
76297        this._usePointShader();
76298
76299        this.curPointShader.bindShader();
76300
76301        if (typeof z === 'undefined') {
76302          z = 0;
76303        }
76304
76305        var _vertex = [];
76306
76307        _vertex.push(new p5.Vector(x, y, z));
76308
76309        this._drawPoints(_vertex, this._pointVertexBuffer);
76310
76311        this.curPointShader.unbindShader();
76312        return this;
76313      };
76314
76315      p5.RendererGL.prototype.triangle = function (args) {
76316        var x1 = args[0],
76317            y1 = args[1];
76318        var x2 = args[2],
76319            y2 = args[3];
76320        var x3 = args[4],
76321            y3 = args[5];
76322        var gId = 'tri';
76323
76324        if (!this.geometryInHash(gId)) {
76325          var _triangle = function () {
76326            var vertices = [];
76327            vertices.push(new p5.Vector(0, 0, 0));
76328            vertices.push(new p5.Vector(0, 1, 0));
76329            vertices.push(new p5.Vector(1, 0, 0));
76330            this.strokeIndices = [[0, 1], [1, 2], [2, 0]];
76331            this.vertices = vertices;
76332            this.faces = [[0, 1, 2]];
76333            this.uvs = [0, 0, 0, 1, 1, 1];
76334          };
76335
76336          var triGeom = new p5.Geometry(1, 1, _triangle);
76337
76338          triGeom._makeTriangleEdges()._edgesToVertices();
76339
76340          triGeom.computeNormals();
76341          this.createBuffers(gId, triGeom);
76342        } // only one triangle is cached, one point is at the origin, and the
76343        // two adjacent sides are tne unit vectors along the X & Y axes.
76344        //
76345        // this matrix multiplication transforms those two unit vectors
76346        // onto the required vector prior to rendering, and moves the
76347        // origin appropriately.
76348
76349
76350        var uMVMatrix = this.uMVMatrix.copy();
76351
76352        try {
76353          // prettier-ignore
76354          var mult = new p5.Matrix([x2 - x1, y2 - y1, 0, 0, // the resulting unit X-axis
76355          x3 - x1, y3 - y1, 0, 0, // the resulting unit Y-axis
76356          0, 0, 1, 0, // the resulting unit Z-axis (unchanged)
76357          x1, y1, 0, 1 // the resulting origin
76358          ]).mult(this.uMVMatrix);
76359          this.uMVMatrix = mult;
76360          this.drawBuffers(gId);
76361        } finally {
76362          this.uMVMatrix = uMVMatrix;
76363        }
76364
76365        return this;
76366      };
76367
76368      p5.RendererGL.prototype.ellipse = function (args) {
76369        this.arc(args[0], args[1], args[2], args[3], 0, constants.TWO_PI, constants.OPEN, args[4]);
76370      };
76371
76372      p5.RendererGL.prototype.arc = function (args) {
76373        var x = arguments[0];
76374        var y = arguments[1];
76375        var width = arguments[2];
76376        var height = arguments[3];
76377        var start = arguments[4];
76378        var stop = arguments[5];
76379        var mode = arguments[6];
76380        var detail = arguments[7] || 25;
76381        var shape;
76382        var gId; // check if it is an ellipse or an arc
76383
76384        if (Math.abs(stop - start) >= constants.TWO_PI) {
76385          shape = 'ellipse';
76386          gId = shape + '|' + detail + '|';
76387        } else {
76388          shape = 'arc';
76389          gId = shape + '|' + start + '|' + stop + '|' + mode + '|' + detail + '|';
76390        }
76391
76392        if (!this.geometryInHash(gId)) {
76393          var _arc = function () {
76394            this.strokeIndices = []; // if the start and stop angles are not the same, push vertices to the array
76395
76396            if (start.toFixed(10) !== stop.toFixed(10)) {
76397              // if the mode specified is PIE or null, push the mid point of the arc in vertices
76398              if (mode === constants.PIE || typeof mode === 'undefined') {
76399                this.vertices.push(new p5.Vector(0.5, 0.5, 0));
76400                this.uvs.push([0.5, 0.5]);
76401              } // vertices for the perimeter of the circle
76402
76403
76404              for (var i = 0; i <= detail; i++) {
76405                var u = i / detail;
76406                var theta = (stop - start) * u + start;
76407
76408                var _x = 0.5 + Math.cos(theta) / 2;
76409
76410                var _y = 0.5 + Math.sin(theta) / 2;
76411
76412                this.vertices.push(new p5.Vector(_x, _y, 0));
76413                this.uvs.push([_x, _y]);
76414
76415                if (i < detail - 1) {
76416                  this.faces.push([0, i + 1, i + 2]);
76417                  this.strokeIndices.push([i + 1, i + 2]);
76418                }
76419              } // check the mode specified in order to push vertices and faces, different for each mode
76420
76421
76422              switch (mode) {
76423                case constants.PIE:
76424                  this.faces.push([0, this.vertices.length - 2, this.vertices.length - 1]);
76425                  this.strokeIndices.push([0, 1]);
76426                  this.strokeIndices.push([this.vertices.length - 2, this.vertices.length - 1]);
76427                  this.strokeIndices.push([0, this.vertices.length - 1]);
76428                  break;
76429
76430                case constants.CHORD:
76431                  this.strokeIndices.push([0, 1]);
76432                  this.strokeIndices.push([0, this.vertices.length - 1]);
76433                  break;
76434
76435                case constants.OPEN:
76436                  this.strokeIndices.push([0, 1]);
76437                  break;
76438
76439                default:
76440                  this.faces.push([0, this.vertices.length - 2, this.vertices.length - 1]);
76441                  this.strokeIndices.push([this.vertices.length - 2, this.vertices.length - 1]);
76442              }
76443            }
76444          };
76445
76446          var arcGeom = new p5.Geometry(detail, 1, _arc);
76447          arcGeom.computeNormals();
76448
76449          if (detail <= 50) {
76450            arcGeom._makeTriangleEdges()._edgesToVertices(arcGeom);
76451          } else {
76452            console.log('Cannot stroke ' + shape + ' with more than 50 detail');
76453          }
76454
76455          this.createBuffers(gId, arcGeom);
76456        }
76457
76458        var uMVMatrix = this.uMVMatrix.copy();
76459
76460        try {
76461          this.uMVMatrix.translate([x, y, 0]);
76462          this.uMVMatrix.scale(width, height, 1);
76463          this.drawBuffers(gId);
76464        } finally {
76465          this.uMVMatrix = uMVMatrix;
76466        }
76467
76468        return this;
76469      };
76470
76471      p5.RendererGL.prototype.rect = function (args) {
76472        var perPixelLighting = this.attributes.perPixelLighting;
76473        var x = args[0];
76474        var y = args[1];
76475        var width = args[2];
76476        var height = args[3];
76477        var detailX = args[4] || (perPixelLighting ? 1 : 24);
76478        var detailY = args[5] || (perPixelLighting ? 1 : 16);
76479        var gId = 'rect|' + detailX + '|' + detailY;
76480
76481        if (!this.geometryInHash(gId)) {
76482          var _rect = function () {
76483            for (var i = 0; i <= this.detailY; i++) {
76484              var v = i / this.detailY;
76485
76486              for (var j = 0; j <= this.detailX; j++) {
76487                var u = j / this.detailX;
76488                var p = new p5.Vector(u, v, 0);
76489                this.vertices.push(p);
76490                this.uvs.push(u, v);
76491              }
76492            } // using stroke indices to avoid stroke over face(s) of rectangle
76493
76494
76495            if (detailX > 0 && detailY > 0) {
76496              this.strokeIndices = [[0, detailX], [detailX, (detailX + 1) * (detailY + 1) - 1], [(detailX + 1) * (detailY + 1) - 1, (detailX + 1) * detailY], [(detailX + 1) * detailY, 0]];
76497            }
76498          };
76499
76500          var rectGeom = new p5.Geometry(detailX, detailY, _rect);
76501
76502          rectGeom.computeFaces().computeNormals()._makeTriangleEdges()._edgesToVertices();
76503
76504          this.createBuffers(gId, rectGeom);
76505        } // only a single rectangle (of a given detail) is cached: a square with
76506        // opposite corners at (0,0) & (1,1).
76507        //
76508        // before rendering, this square is scaled & moved to the required location.
76509
76510
76511        var uMVMatrix = this.uMVMatrix.copy();
76512
76513        try {
76514          this.uMVMatrix.translate([x, y, 0]);
76515          this.uMVMatrix.scale(width, height, 1);
76516          this.drawBuffers(gId);
76517        } finally {
76518          this.uMVMatrix = uMVMatrix;
76519        }
76520
76521        return this;
76522      };
76523
76524      p5.RendererGL.prototype.quad = function (x1, y1, x2, y2, x3, y3, x4, y4) {
76525        var gId = 'quad|' + x1 + '|' + y1 + '|' + x2 + '|' + y2 + '|' + x3 + '|' + y3 + '|' + x4 + '|' + y4;
76526
76527        if (!this.geometryInHash(gId)) {
76528          var _quad = function () {
76529            this.vertices.push(new p5.Vector(x1, y1, 0));
76530            this.vertices.push(new p5.Vector(x2, y2, 0));
76531            this.vertices.push(new p5.Vector(x3, y3, 0));
76532            this.vertices.push(new p5.Vector(x4, y4, 0));
76533            this.uvs.push(0, 0, 1, 0, 1, 1, 0, 1);
76534            this.strokeIndices = [[0, 1], [1, 2], [2, 3], [3, 0]];
76535          };
76536
76537          var quadGeom = new p5.Geometry(2, 2, _quad);
76538
76539          quadGeom.computeNormals()._makeTriangleEdges()._edgesToVertices();
76540
76541          quadGeom.faces = [[0, 1, 2], [2, 3, 0]];
76542          this.createBuffers(gId, quadGeom);
76543        }
76544
76545        this.drawBuffers(gId);
76546        return this;
76547      }; //this implementation of bezier curve
76548      //is based on Bernstein polynomial
76549      // pretier-ignore
76550
76551
76552      p5.RendererGL.prototype.bezier = function (x1, y1, z1, // x2
76553      x2, // y2
76554      y2, // x3
76555      z2, // y3
76556      x3, // x4
76557      y3, // y4
76558      z3, x4, y4, z4) {
76559        if (arguments.length === 8) {
76560          x4 = x3;
76561          y4 = y3;
76562          x3 = y2;
76563          y3 = x2;
76564          x2 = z1;
76565          y2 = x2;
76566          z1 = z2 = z3 = z4 = 0;
76567        }
76568
76569        var bezierDetail = this._pInst._bezierDetail || 20; //value of Bezier detail
76570
76571        this.beginShape();
76572
76573        for (var i = 0; i <= bezierDetail; i++) {
76574          var c1 = Math.pow(1 - i / bezierDetail, 3);
76575          var c2 = 3 * (i / bezierDetail) * Math.pow(1 - i / bezierDetail, 2);
76576          var c3 = 3 * Math.pow(i / bezierDetail, 2) * (1 - i / bezierDetail);
76577          var c4 = Math.pow(i / bezierDetail, 3);
76578          this.vertex(x1 * c1 + x2 * c2 + x3 * c3 + x4 * c4, y1 * c1 + y2 * c2 + y3 * c3 + y4 * c4, z1 * c1 + z2 * c2 + z3 * c3 + z4 * c4);
76579        }
76580
76581        this.endShape();
76582        return this;
76583      }; // pretier-ignore
76584
76585
76586      p5.RendererGL.prototype.curve = function (x1, y1, z1, // x2
76587      x2, // y2
76588      y2, // x3
76589      z2, // y3
76590      x3, // x4
76591      y3, // y4
76592      z3, x4, y4, z4) {
76593        if (arguments.length === 8) {
76594          x4 = x3;
76595          y4 = y3;
76596          x3 = y2;
76597          y3 = x2;
76598          x2 = z1;
76599          y2 = x2;
76600          z1 = z2 = z3 = z4 = 0;
76601        }
76602
76603        var curveDetail = this._pInst._curveDetail;
76604        this.beginShape();
76605
76606        for (var i = 0; i <= curveDetail; i++) {
76607          var c1 = Math.pow(i / curveDetail, 3) * 0.5;
76608          var c2 = Math.pow(i / curveDetail, 2) * 0.5;
76609          var c3 = i / curveDetail * 0.5;
76610          var c4 = 0.5;
76611          var vx = c1 * (-x1 + 3 * x2 - 3 * x3 + x4) + c2 * (2 * x1 - 5 * x2 + 4 * x3 - x4) + c3 * (-x1 + x3) + c4 * (2 * x2);
76612          var vy = c1 * (-y1 + 3 * y2 - 3 * y3 + y4) + c2 * (2 * y1 - 5 * y2 + 4 * y3 - y4) + c3 * (-y1 + y3) + c4 * (2 * y2);
76613          var vz = c1 * (-z1 + 3 * z2 - 3 * z3 + z4) + c2 * (2 * z1 - 5 * z2 + 4 * z3 - z4) + c3 * (-z1 + z3) + c4 * (2 * z2);
76614          this.vertex(vx, vy, vz);
76615        }
76616
76617        this.endShape();
76618        return this;
76619      };
76620      /**
76621       * Draw a line given two points
76622       * @private
76623       * @param {Number} x0 x-coordinate of first vertex
76624       * @param {Number} y0 y-coordinate of first vertex
76625       * @param {Number} z0 z-coordinate of first vertex
76626       * @param {Number} x1 x-coordinate of second vertex
76627       * @param {Number} y1 y-coordinate of second vertex
76628       * @param {Number} z1 z-coordinate of second vertex
76629       * @chainable
76630       * @example
76631       * <div>
76632       * <code>
76633       * //draw a line
76634       * function setup() {
76635       *   createCanvas(100, 100, WEBGL);
76636       * }
76637       *
76638       * function draw() {
76639       *   background(200);
76640       *   rotateX(frameCount * 0.01);
76641       *   rotateY(frameCount * 0.01);
76642       *   // Use fill instead of stroke to change the color of shape.
76643       *   fill(255, 0, 0);
76644       *   line(10, 10, 0, 60, 60, 20);
76645       * }
76646       * </code>
76647       * </div>
76648       */
76649
76650
76651      p5.RendererGL.prototype.line = function () {
76652        if (arguments.length === 6) {
76653          this.beginShape();
76654          this.vertex(arguments[0], arguments[1], arguments[2]);
76655          this.vertex(arguments[3], arguments[4], arguments[5]);
76656          this.endShape();
76657        } else if (arguments.length === 4) {
76658          this.beginShape();
76659          this.vertex(arguments[0], arguments[1], 0);
76660          this.vertex(arguments[2], arguments[3], 0);
76661          this.endShape();
76662        }
76663
76664        return this;
76665      };
76666
76667      p5.RendererGL.prototype.bezierVertex = function () {
76668        if (this.immediateMode._bezierVertex.length === 0) {
76669          throw Error('vertex() must be used once before calling bezierVertex()');
76670        } else {
76671          var w_x = [];
76672          var w_y = [];
76673          var w_z = [];
76674
76675          var t, _x, _y, _z, i;
76676
76677          var argLength = arguments.length;
76678          t = 0;
76679
76680          if (this._lookUpTableBezier.length === 0 || this._lutBezierDetail !== this._pInst._curveDetail) {
76681            this._lookUpTableBezier = [];
76682            this._lutBezierDetail = this._pInst._curveDetail;
76683            var step = 1 / this._lutBezierDetail;
76684            var start = 0;
76685            var end = 1;
76686            var j = 0;
76687
76688            while (start < 1) {
76689              t = parseFloat(start.toFixed(6));
76690              this._lookUpTableBezier[j] = this._bezierCoefficients(t);
76691
76692              if (end.toFixed(6) === step.toFixed(6)) {
76693                t = parseFloat(end.toFixed(6)) + parseFloat(start.toFixed(6));
76694                ++j;
76695                this._lookUpTableBezier[j] = this._bezierCoefficients(t);
76696                break;
76697              }
76698
76699              start += step;
76700              end -= step;
76701              ++j;
76702            }
76703          }
76704
76705          var LUTLength = this._lookUpTableBezier.length;
76706
76707          if (argLength === 6) {
76708            this.isBezier = true;
76709            w_x = [this.immediateMode._bezierVertex[0], arguments[0], arguments[2], arguments[4]];
76710            w_y = [this.immediateMode._bezierVertex[1], arguments[1], arguments[3], arguments[5]];
76711
76712            for (i = 0; i < LUTLength; i++) {
76713              _x = w_x[0] * this._lookUpTableBezier[i][0] + w_x[1] * this._lookUpTableBezier[i][1] + w_x[2] * this._lookUpTableBezier[i][2] + w_x[3] * this._lookUpTableBezier[i][3];
76714              _y = w_y[0] * this._lookUpTableBezier[i][0] + w_y[1] * this._lookUpTableBezier[i][1] + w_y[2] * this._lookUpTableBezier[i][2] + w_y[3] * this._lookUpTableBezier[i][3];
76715              this.vertex(_x, _y);
76716            }
76717
76718            this.immediateMode._bezierVertex[0] = arguments[4];
76719            this.immediateMode._bezierVertex[1] = arguments[5];
76720          } else if (argLength === 9) {
76721            this.isBezier = true;
76722            w_x = [this.immediateMode._bezierVertex[0], arguments[0], arguments[3], arguments[6]];
76723            w_y = [this.immediateMode._bezierVertex[1], arguments[1], arguments[4], arguments[7]];
76724            w_z = [this.immediateMode._bezierVertex[2], arguments[2], arguments[5], arguments[8]];
76725
76726            for (i = 0; i < LUTLength; i++) {
76727              _x = w_x[0] * this._lookUpTableBezier[i][0] + w_x[1] * this._lookUpTableBezier[i][1] + w_x[2] * this._lookUpTableBezier[i][2] + w_x[3] * this._lookUpTableBezier[i][3];
76728              _y = w_y[0] * this._lookUpTableBezier[i][0] + w_y[1] * this._lookUpTableBezier[i][1] + w_y[2] * this._lookUpTableBezier[i][2] + w_y[3] * this._lookUpTableBezier[i][3];
76729              _z = w_z[0] * this._lookUpTableBezier[i][0] + w_z[1] * this._lookUpTableBezier[i][1] + w_z[2] * this._lookUpTableBezier[i][2] + w_z[3] * this._lookUpTableBezier[i][3];
76730              this.vertex(_x, _y, _z);
76731            }
76732
76733            this.immediateMode._bezierVertex[0] = arguments[6];
76734            this.immediateMode._bezierVertex[1] = arguments[7];
76735            this.immediateMode._bezierVertex[2] = arguments[8];
76736          }
76737        }
76738      };
76739
76740      p5.RendererGL.prototype.quadraticVertex = function () {
76741        if (this.immediateMode._quadraticVertex.length === 0) {
76742          throw Error('vertex() must be used once before calling quadraticVertex()');
76743        } else {
76744          var w_x = [];
76745          var w_y = [];
76746          var w_z = [];
76747
76748          var t, _x, _y, _z, i;
76749
76750          var argLength = arguments.length;
76751          t = 0;
76752
76753          if (this._lookUpTableQuadratic.length === 0 || this._lutQuadraticDetail !== this._pInst._curveDetail) {
76754            this._lookUpTableQuadratic = [];
76755            this._lutQuadraticDetail = this._pInst._curveDetail;
76756            var step = 1 / this._lutQuadraticDetail;
76757            var start = 0;
76758            var end = 1;
76759            var j = 0;
76760
76761            while (start < 1) {
76762              t = parseFloat(start.toFixed(6));
76763              this._lookUpTableQuadratic[j] = this._quadraticCoefficients(t);
76764
76765              if (end.toFixed(6) === step.toFixed(6)) {
76766                t = parseFloat(end.toFixed(6)) + parseFloat(start.toFixed(6));
76767                ++j;
76768                this._lookUpTableQuadratic[j] = this._quadraticCoefficients(t);
76769                break;
76770              }
76771
76772              start += step;
76773              end -= step;
76774              ++j;
76775            }
76776          }
76777
76778          var LUTLength = this._lookUpTableQuadratic.length;
76779
76780          if (argLength === 4) {
76781            this.isQuadratic = true;
76782            w_x = [this.immediateMode._quadraticVertex[0], arguments[0], arguments[2]];
76783            w_y = [this.immediateMode._quadraticVertex[1], arguments[1], arguments[3]];
76784
76785            for (i = 0; i < LUTLength; i++) {
76786              _x = w_x[0] * this._lookUpTableQuadratic[i][0] + w_x[1] * this._lookUpTableQuadratic[i][1] + w_x[2] * this._lookUpTableQuadratic[i][2];
76787              _y = w_y[0] * this._lookUpTableQuadratic[i][0] + w_y[1] * this._lookUpTableQuadratic[i][1] + w_y[2] * this._lookUpTableQuadratic[i][2];
76788              this.vertex(_x, _y);
76789            }
76790
76791            this.immediateMode._quadraticVertex[0] = arguments[2];
76792            this.immediateMode._quadraticVertex[1] = arguments[3];
76793          } else if (argLength === 6) {
76794            this.isQuadratic = true;
76795            w_x = [this.immediateMode._quadraticVertex[0], arguments[0], arguments[3]];
76796            w_y = [this.immediateMode._quadraticVertex[1], arguments[1], arguments[4]];
76797            w_z = [this.immediateMode._quadraticVertex[2], arguments[2], arguments[5]];
76798
76799            for (i = 0; i < LUTLength; i++) {
76800              _x = w_x[0] * this._lookUpTableQuadratic[i][0] + w_x[1] * this._lookUpTableQuadratic[i][1] + w_x[2] * this._lookUpTableQuadratic[i][2];
76801              _y = w_y[0] * this._lookUpTableQuadratic[i][0] + w_y[1] * this._lookUpTableQuadratic[i][1] + w_y[2] * this._lookUpTableQuadratic[i][2];
76802              _z = w_z[0] * this._lookUpTableQuadratic[i][0] + w_z[1] * this._lookUpTableQuadratic[i][1] + w_z[2] * this._lookUpTableQuadratic[i][2];
76803              this.vertex(_x, _y, _z);
76804            }
76805
76806            this.immediateMode._quadraticVertex[0] = arguments[3];
76807            this.immediateMode._quadraticVertex[1] = arguments[4];
76808            this.immediateMode._quadraticVertex[2] = arguments[5];
76809          }
76810        }
76811      };
76812
76813      p5.RendererGL.prototype.curveVertex = function () {
76814        var w_x = [];
76815        var w_y = [];
76816        var w_z = [];
76817
76818        var t, _x, _y, _z, i;
76819
76820        t = 0;
76821        var argLength = arguments.length;
76822
76823        if (this._lookUpTableBezier.length === 0 || this._lutBezierDetail !== this._pInst._curveDetail) {
76824          this._lookUpTableBezier = [];
76825          this._lutBezierDetail = this._pInst._curveDetail;
76826          var step = 1 / this._lutBezierDetail;
76827          var start = 0;
76828          var end = 1;
76829          var j = 0;
76830
76831          while (start < 1) {
76832            t = parseFloat(start.toFixed(6));
76833            this._lookUpTableBezier[j] = this._bezierCoefficients(t);
76834
76835            if (end.toFixed(6) === step.toFixed(6)) {
76836              t = parseFloat(end.toFixed(6)) + parseFloat(start.toFixed(6));
76837              ++j;
76838              this._lookUpTableBezier[j] = this._bezierCoefficients(t);
76839              break;
76840            }
76841
76842            start += step;
76843            end -= step;
76844            ++j;
76845          }
76846        }
76847
76848        var LUTLength = this._lookUpTableBezier.length;
76849
76850        if (argLength === 2) {
76851          this.immediateMode._curveVertex.push(arguments[0]);
76852
76853          this.immediateMode._curveVertex.push(arguments[1]);
76854
76855          if (this.immediateMode._curveVertex.length === 8) {
76856            this.isCurve = true;
76857            w_x = this._bezierToCatmull([this.immediateMode._curveVertex[0], this.immediateMode._curveVertex[2], this.immediateMode._curveVertex[4], this.immediateMode._curveVertex[6]]);
76858            w_y = this._bezierToCatmull([this.immediateMode._curveVertex[1], this.immediateMode._curveVertex[3], this.immediateMode._curveVertex[5], this.immediateMode._curveVertex[7]]);
76859
76860            for (i = 0; i < LUTLength; i++) {
76861              _x = w_x[0] * this._lookUpTableBezier[i][0] + w_x[1] * this._lookUpTableBezier[i][1] + w_x[2] * this._lookUpTableBezier[i][2] + w_x[3] * this._lookUpTableBezier[i][3];
76862              _y = w_y[0] * this._lookUpTableBezier[i][0] + w_y[1] * this._lookUpTableBezier[i][1] + w_y[2] * this._lookUpTableBezier[i][2] + w_y[3] * this._lookUpTableBezier[i][3];
76863              this.vertex(_x, _y);
76864            }
76865
76866            for (i = 0; i < argLength; i++) {
76867              this.immediateMode._curveVertex.shift();
76868            }
76869          }
76870        } else if (argLength === 3) {
76871          this.immediateMode._curveVertex.push(arguments[0]);
76872
76873          this.immediateMode._curveVertex.push(arguments[1]);
76874
76875          this.immediateMode._curveVertex.push(arguments[2]);
76876
76877          if (this.immediateMode._curveVertex.length === 12) {
76878            this.isCurve = true;
76879            w_x = this._bezierToCatmull([this.immediateMode._curveVertex[0], this.immediateMode._curveVertex[3], this.immediateMode._curveVertex[6], this.immediateMode._curveVertex[9]]);
76880            w_y = this._bezierToCatmull([this.immediateMode._curveVertex[1], this.immediateMode._curveVertex[4], this.immediateMode._curveVertex[7], this.immediateMode._curveVertex[10]]);
76881            w_z = this._bezierToCatmull([this.immediateMode._curveVertex[2], this.immediateMode._curveVertex[5], this.immediateMode._curveVertex[8], this.immediateMode._curveVertex[11]]);
76882
76883            for (i = 0; i < LUTLength; i++) {
76884              _x = w_x[0] * this._lookUpTableBezier[i][0] + w_x[1] * this._lookUpTableBezier[i][1] + w_x[2] * this._lookUpTableBezier[i][2] + w_x[3] * this._lookUpTableBezier[i][3];
76885              _y = w_y[0] * this._lookUpTableBezier[i][0] + w_y[1] * this._lookUpTableBezier[i][1] + w_y[2] * this._lookUpTableBezier[i][2] + w_y[3] * this._lookUpTableBezier[i][3];
76886              _z = w_z[0] * this._lookUpTableBezier[i][0] + w_z[1] * this._lookUpTableBezier[i][1] + w_z[2] * this._lookUpTableBezier[i][2] + w_z[3] * this._lookUpTableBezier[i][3];
76887              this.vertex(_x, _y, _z);
76888            }
76889
76890            for (i = 0; i < argLength; i++) {
76891              this.immediateMode._curveVertex.shift();
76892            }
76893          }
76894        }
76895      };
76896
76897      module.exports = p5;
76898    }, {
76899      "../core/constants": 18,
76900      "../core/main": 24,
76901      "./p5.Geometry": 70
76902    }],
76903    65: [function (_dereq_, module, exports) {
76904      /**
76905       * @module Lights, Camera
76906       * @submodule Interaction
76907       * @for p5
76908       * @requires core
76909       */
76910      'use strict';
76911
76912      var p5 = _dereq_('../core/main');
76913
76914      var constants = _dereq_('../core/constants');
76915      /**
76916       * Allows movement around a 3D sketch using a mouse or trackpad.  Left-clicking
76917       * and dragging will rotate the camera position about the center of the sketch,
76918       * right-clicking and dragging will pan the camera position without rotation,
76919       * and using the mouse wheel (scrolling) will move the camera closer or further
76920       * from the center of the sketch. This function can be called with parameters
76921       * dictating sensitivity to mouse movement along the X and Y axes.  Calling
76922       * this function without parameters is equivalent to calling orbitControl(1,1).
76923       * To reverse direction of movement in either axis, enter a negative number
76924       * for sensitivity.
76925       * @method orbitControl
76926       * @for p5
76927       * @param  {Number} [sensitivityX] sensitivity to mouse movement along X axis
76928       * @param  {Number} [sensitivityY] sensitivity to mouse movement along Y axis
76929       * @chainable
76930       * @example
76931       * <div>
76932       * <code>
76933       * function setup() {
76934       *   createCanvas(100, 100, WEBGL);
76935       *   normalMaterial();
76936       * }
76937       * function draw() {
76938       *   background(200);
76939       *   orbitControl();
76940       *   rotateY(0.5);
76941       *   box(30, 50);
76942       * }
76943       * </code>
76944       * </div>
76945       *
76946       * @alt
76947       * Camera orbits around a box when mouse is hold-clicked & then moved.
76948       */
76949      // implementation based on three.js 'orbitControls':
76950      // https://github.com/mrdoob/three.js/blob/dev/examples/js/controls/OrbitControls.js
76951
76952
76953      p5.prototype.orbitControl = function (sensitivityX, sensitivityY) {
76954        this._assert3d('orbitControl');
76955
76956        p5._validateParameters('orbitControl', arguments); // If the mouse is not in bounds of the canvas, disable all behaviors:
76957
76958
76959        var mouseInCanvas = this.mouseX < this.width && this.mouseX > 0 && this.mouseY < this.height && this.mouseY > 0;
76960        if (!mouseInCanvas) return;
76961        var cam = this._renderer._curCamera;
76962
76963        if (typeof sensitivityX === 'undefined') {
76964          sensitivityX = 1;
76965        }
76966
76967        if (typeof sensitivityY === 'undefined') {
76968          sensitivityY = sensitivityX;
76969        } // default right-mouse and mouse-wheel behaviors (context menu and scrolling,
76970        // respectively) are disabled here to allow use of those events for panning and
76971        // zooming
76972        // disable context menu for canvas element and add 'contextMenuDisabled'
76973        // flag to p5 instance
76974
76975
76976        if (this.contextMenuDisabled !== true) {
76977          this.canvas.oncontextmenu = function () {
76978            return false;
76979          };
76980
76981          this._setProperty('contextMenuDisabled', true);
76982        } // disable default scrolling behavior on the canvas element and add
76983        // 'wheelDefaultDisabled' flag to p5 instance
76984
76985
76986        if (this.wheelDefaultDisabled !== true) {
76987          this.canvas.onwheel = function () {
76988            return false;
76989          };
76990
76991          this._setProperty('wheelDefaultDisabled', true);
76992        }
76993
76994        var scaleFactor = this.height < this.width ? this.height : this.width; // ZOOM if there is a change in mouseWheelDelta
76995
76996        if (this._mouseWheelDeltaY !== this._pmouseWheelDeltaY) {
76997          // zoom according to direction of mouseWheelDeltaY rather than value
76998          if (this._mouseWheelDeltaY > 0) {
76999            this._renderer._curCamera._orbit(0, 0, 0.5 * scaleFactor);
77000          } else {
77001            this._renderer._curCamera._orbit(0, 0, -0.5 * scaleFactor);
77002          }
77003        }
77004
77005        if (this.mouseIsPressed) {
77006          // ORBIT BEHAVIOR
77007          if (this.mouseButton === this.LEFT) {
77008            var deltaTheta = -sensitivityX * (this.mouseX - this.pmouseX) / scaleFactor;
77009            var deltaPhi = sensitivityY * (this.mouseY - this.pmouseY) / scaleFactor;
77010
77011            this._renderer._curCamera._orbit(deltaTheta, deltaPhi, 0);
77012          } else if (this.mouseButton === this.RIGHT) {
77013            // PANNING BEHAVIOR along X/Z camera axes and restricted to X/Z plane
77014            // in world space
77015            var local = cam._getLocalAxes(); // normalize portions along X/Z axes
77016
77017
77018            var xmag = Math.sqrt(local.x[0] * local.x[0] + local.x[2] * local.x[2]);
77019
77020            if (xmag !== 0) {
77021              local.x[0] /= xmag;
77022              local.x[2] /= xmag;
77023            } // normalize portions along X/Z axes
77024
77025
77026            var ymag = Math.sqrt(local.y[0] * local.y[0] + local.y[2] * local.y[2]);
77027
77028            if (ymag !== 0) {
77029              local.y[0] /= ymag;
77030              local.y[2] /= ymag;
77031            } // move along those vectors by amount controlled by mouseX, pmouseY
77032
77033
77034            var dx = -1 * sensitivityX * (this.mouseX - this.pmouseX);
77035            var dz = -1 * sensitivityY * (this.mouseY - this.pmouseY); // restrict movement to XZ plane in world space
77036
77037            cam.setPosition(cam.eyeX + dx * local.x[0] + dz * local.z[0], cam.eyeY, cam.eyeZ + dx * local.x[2] + dz * local.z[2]);
77038          }
77039        }
77040
77041        return this;
77042      };
77043      /**
77044       * debugMode() helps visualize 3D space by adding a grid to indicate where the
77045       * ‘ground’ is in a sketch and an axes icon which indicates the +X, +Y, and +Z
77046       * directions. This function can be called without parameters to create a
77047       * default grid and axes icon, or it can be called according to the examples
77048       * above to customize the size and position of the grid and/or axes icon.  The
77049       * grid is drawn using the most recently set stroke color and weight.  To
77050       * specify these parameters, add a call to stroke() and strokeWeight()
77051       * just before the end of the draw() loop.
77052       *
77053       * By default, the grid will run through the origin (0,0,0) of the sketch
77054       * along the XZ plane
77055       * and the axes icon will be offset from the origin.  Both the grid and axes
77056       * icon will be sized according to the current canvas size.  Note that because the
77057       * grid runs parallel to the default camera view, it is often helpful to use
77058       * debugMode along with orbitControl to allow full view of the grid.
77059       * @method debugMode
77060       * @example
77061       * <div>
77062       * <code>
77063       * function setup() {
77064       *   createCanvas(100, 100, WEBGL);
77065       *   camera(0, -30, 100, 0, 0, 0, 0, 1, 0);
77066       *   normalMaterial();
77067       *   debugMode();
77068       * }
77069       *
77070       * function draw() {
77071       *   background(200);
77072       *   orbitControl();
77073       *   box(15, 30);
77074       *   // Press the spacebar to turn debugMode off!
77075       *   if (keyIsDown(32)) {
77076       *     noDebugMode();
77077       *   }
77078       * }
77079       * </code>
77080       * </div>
77081       * @alt
77082       * a 3D box is centered on a grid in a 3D sketch. an icon
77083       * indicates the direction of each axis: a red line points +X,
77084       * a green line +Y, and a blue line +Z. the grid and icon disappear when the
77085       * spacebar is pressed.
77086       *
77087       * @example
77088       * <div>
77089       * <code>
77090       * function setup() {
77091       *   createCanvas(100, 100, WEBGL);
77092       *   camera(0, -30, 100, 0, 0, 0, 0, 1, 0);
77093       *   normalMaterial();
77094       *   debugMode(GRID);
77095       * }
77096       *
77097       * function draw() {
77098       *   background(200);
77099       *   orbitControl();
77100       *   box(15, 30);
77101       * }
77102       * </code>
77103       * </div>
77104       * @alt
77105       * a 3D box is centered on a grid in a 3D sketch.
77106       *
77107       * @example
77108       * <div>
77109       * <code>
77110       * function setup() {
77111       *   createCanvas(100, 100, WEBGL);
77112       *   camera(0, -30, 100, 0, 0, 0, 0, 1, 0);
77113       *   normalMaterial();
77114       *   debugMode(AXES);
77115       * }
77116       *
77117       * function draw() {
77118       *   background(200);
77119       *   orbitControl();
77120       *   box(15, 30);
77121       * }
77122       * </code>
77123       * </div>
77124       * @alt
77125       * a 3D box is centered in a 3D sketch. an icon
77126       * indicates the direction of each axis: a red line points +X,
77127       * a green line +Y, and a blue line +Z.
77128       *
77129       * @example
77130       * <div>
77131       * <code>
77132       * function setup() {
77133       *   createCanvas(100, 100, WEBGL);
77134       *   camera(0, -30, 100, 0, 0, 0, 0, 1, 0);
77135       *   normalMaterial();
77136       *   debugMode(GRID, 100, 10, 0, 0, 0);
77137       * }
77138       *
77139       * function draw() {
77140       *   background(200);
77141       *   orbitControl();
77142       *   box(15, 30);
77143       * }
77144       * </code>
77145       * </div>
77146       * @alt
77147       * a 3D box is centered on a grid in a 3D sketch
77148       *
77149       * @example
77150       * <div>
77151       * <code>
77152       * function setup() {
77153       *   createCanvas(100, 100, WEBGL);
77154       *   camera(0, -30, 100, 0, 0, 0, 0, 1, 0);
77155       *   normalMaterial();
77156       *   debugMode(100, 10, 0, 0, 0, 20, 0, -40, 0);
77157       * }
77158       *
77159       * function draw() {
77160       *   noStroke();
77161       *   background(200);
77162       *   orbitControl();
77163       *   box(15, 30);
77164       *   // set the stroke color and weight for the grid!
77165       *   stroke(255, 0, 150);
77166       *   strokeWeight(0.8);
77167       * }
77168       * </code>
77169       * </div>
77170       * @alt
77171       * a 3D box is centered on a grid in a 3D sketch. an icon
77172       * indicates the direction of each axis: a red line points +X,
77173       * a green line +Y, and a blue line +Z.
77174       */
77175
77176      /**
77177       * @method debugMode
77178       * @param {Constant} mode either GRID or AXES
77179       */
77180
77181      /**
77182       * @method debugMode
77183       * @param {Constant} mode
77184       * @param {Number} [gridSize] size of one side of the grid
77185       * @param {Number} [gridDivisions] number of divisions in the grid
77186       * @param {Number} [xOff] X axis offset from origin (0,0,0)
77187       * @param {Number} [yOff] Y axis offset from origin (0,0,0)
77188       * @param {Number} [zOff] Z axis offset from origin (0,0,0)
77189       */
77190
77191      /**
77192       * @method debugMode
77193       * @param {Constant} mode
77194       * @param {Number} [axesSize] size of axes icon
77195       * @param {Number} [xOff]
77196       * @param {Number} [yOff]
77197       * @param {Number} [zOff]
77198       */
77199
77200      /**
77201       * @method debugMode
77202       * @param {Number} [gridSize]
77203       * @param {Number} [gridDivisions]
77204       * @param {Number} [gridXOff]
77205       * @param {Number} [gridYOff]
77206       * @param {Number} [gridZOff]
77207       * @param {Number} [axesSize]
77208       * @param {Number} [axesXOff]
77209       * @param {Number} [axesYOff]
77210       * @param {Number} [axesZOff]
77211       */
77212
77213
77214      p5.prototype.debugMode = function () {
77215        this._assert3d('debugMode');
77216
77217        p5._validateParameters('debugMode', arguments); // start by removing existing 'post' registered debug methods
77218
77219
77220        for (var i = this._registeredMethods.post.length - 1; i >= 0; i--) {
77221          // test for equality...
77222          if (this._registeredMethods.post[i].toString() === this._grid().toString() || this._registeredMethods.post[i].toString() === this._axesIcon().toString()) {
77223            this._registeredMethods.post.splice(i, 1);
77224          }
77225        } // then add new debugMode functions according to the argument list
77226
77227
77228        if (arguments[0] === constants.GRID) {
77229          this.registerMethod('post', this._grid.call(this, arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]));
77230        } else if (arguments[0] === constants.AXES) {
77231          this.registerMethod('post', this._axesIcon.call(this, arguments[1], arguments[2], arguments[3], arguments[4]));
77232        } else {
77233          this.registerMethod('post', this._grid.call(this, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]));
77234          this.registerMethod('post', this._axesIcon.call(this, arguments[5], arguments[6], arguments[7], arguments[8]));
77235        }
77236      };
77237      /**
77238       * Turns off debugMode() in a 3D sketch.
77239       * @method noDebugMode
77240       * @example
77241       * <div>
77242       * <code>
77243       * function setup() {
77244       *   createCanvas(100, 100, WEBGL);
77245       *   camera(0, -30, 100, 0, 0, 0, 0, 1, 0);
77246       *   normalMaterial();
77247       *   debugMode();
77248       * }
77249       *
77250       * function draw() {
77251       *   background(200);
77252       *   orbitControl();
77253       *   box(15, 30);
77254       *   // Press the spacebar to turn debugMode off!
77255       *   if (keyIsDown(32)) {
77256       *     noDebugMode();
77257       *   }
77258       * }
77259       * </code>
77260       * </div>
77261       * @alt
77262       * a 3D box is centered on a grid in a 3D sketch. an icon
77263       * indicates the direction of each axis: a red line points +X,
77264       * a green line +Y, and a blue line +Z. the grid and icon disappear when the
77265       * spacebar is pressed.
77266       */
77267
77268
77269      p5.prototype.noDebugMode = function () {
77270        this._assert3d('noDebugMode'); // start by removing existing 'post' registered debug methods
77271
77272
77273        for (var i = this._registeredMethods.post.length - 1; i >= 0; i--) {
77274          // test for equality...
77275          if (this._registeredMethods.post[i].toString() === this._grid().toString() || this._registeredMethods.post[i].toString() === this._axesIcon().toString()) {
77276            this._registeredMethods.post.splice(i, 1);
77277          }
77278        }
77279      };
77280      /**
77281       * For use with debugMode
77282       * @private
77283       * @method _grid
77284       * @param {Number}
77284 [size] size of grid sides
77285       * @param {Number} [div] number of grid divisions
77286       * @param {Number} [xOff] offset of grid center from origin in X axis
77287       * @param {Number} [yOff] offset of grid center from origin in Y axis
77288       * @param {Number} [zOff] offset of grid center from origin in Z axis
77289       */
77290
77291
77292      p5.prototype._grid = function (size, numDivs, xOff, yOff, zOff) {
77293        if (typeof size === 'undefined') {
77294          size = this.width / 2;
77295        }
77296
77297        if (typeof numDivs === 'undefined') {
77298          // ensure at least 2 divisions
77299          numDivs = Math.round(size / 30) < 4 ? 4 : Math.round(size / 30);
77300        }
77301
77302        if (typeof xOff === 'undefined') {
77303          xOff = 0;
77304        }
77305
77306        if (typeof yOff === 'undefined') {
77307          yOff = 0;
77308        }
77309
77310        if (typeof zOff === 'undefined') {
77311          zOff = 0;
77312        }
77313
77314        var spacing = size / numDivs;
77315        var halfSize = size / 2;
77316        return function () {
77317          this.push();
77318          this.stroke(this._renderer.curStrokeColor[0] * 255, this._renderer.curStrokeColor[1] * 255, this._renderer.curStrokeColor[2] * 255);
77319
77320          this._renderer.uMVMatrix.set(this._renderer._curCamera.cameraMatrix.mat4[0], this._renderer._curCamera.cameraMatrix.mat4[1], this._renderer._curCamera.cameraMatrix.mat4[2], this._renderer._curCamera.cameraMatrix.mat4[3], this._renderer._curCamera.cameraMatrix.mat4[4], this._renderer._curCamera.cameraMatrix.mat4[5], this._renderer._curCamera.cameraMatrix.mat4[6], this._renderer._curCamera.cameraMatrix.mat4[7], this._renderer._curCamera.cameraMatrix.mat4[8], this._renderer._curCamera.cameraMatrix.mat4[9], this._renderer._curCamera.cameraMatrix.mat4[10], this._renderer._curCamera.cameraMatrix.mat4[11], this._renderer._curCamera.cameraMatrix.mat4[12], this._renderer._curCamera.cameraMatrix.mat4[13], this._renderer._curCamera.cameraMatrix.mat4[14], this._renderer._curCamera.cameraMatrix.mat4[15]); // Lines along X axis
77321
77322
77323          for (var q = 0; q <= numDivs; q++) {
77324            this.beginShape(this.LINES);
77325            this.vertex(-halfSize + xOff, yOff, q * spacing - halfSize + zOff);
77326            this.vertex(+halfSize + xOff, yOff, q * spacing - halfSize + zOff);
77327            this.endShape();
77328          } // Lines along Z axis
77329
77330
77331          for (var i = 0; i <= numDivs; i++) {
77332            this.beginShape(this.LINES);
77333            this.vertex(i * spacing - halfSize + xOff, yOff, -halfSize + zOff);
77334            this.vertex(i * spacing - halfSize + xOff, yOff, +halfSize + zOff);
77335            this.endShape();
77336          }
77337
77338          this.pop();
77339        };
77340      };
77341      /**
77342       * For use with debugMode
77343       * @private
77344       * @method _axesIcon
77345       * @param {Number} [size] size of axes icon lines
77346       * @param {Number} [xOff] offset of icon from origin in X axis
77347       * @param {Number} [yOff] offset of icon from origin in Y axis
77348       * @param {Number} [zOff] offset of icon from origin in Z axis
77349       */
77350
77351
77352      p5.prototype._axesIcon = function (size, xOff, yOff, zOff) {
77353        if (typeof size === 'undefined') {
77354          size = this.width / 20 > 40 ? this.width / 20 : 40;
77355        }
77356
77357        if (typeof xOff === 'undefined') {
77358          xOff = -this.width / 4;
77359        }
77360
77361        if (typeof yOff === 'undefined') {
77362          yOff = xOff;
77363        }
77364
77365        if (typeof zOff === 'undefined') {
77366          zOff = xOff;
77367        }
77368
77369        return function () {
77370          this.push();
77371
77372          this._renderer.uMVMatrix.set(this._renderer._curCamera.cameraMatrix.mat4[0], this._renderer._curCamera.cameraMatrix.mat4[1], this._renderer._curCamera.cameraMatrix.mat4[2], this._renderer._curCamera.cameraMatrix.mat4[3], this._renderer._curCamera.cameraMatrix.mat4[4], this._renderer._curCamera.cameraMatrix.mat4[5], this._renderer._curCamera.cameraMatrix.mat4[6], this._renderer._curCamera.cameraMatrix.mat4[7], this._renderer._curCamera.cameraMatrix.mat4[8], this._renderer._curCamera.cameraMatrix.mat4[9], this._renderer._curCamera.cameraMatrix.mat4[10], this._renderer._curCamera.cameraMatrix.mat4[11], this._renderer._curCamera.cameraMatrix.mat4[12], this._renderer._curCamera.cameraMatrix.mat4[13], this._renderer._curCamera.cameraMatrix.mat4[14], this._renderer._curCamera.cameraMatrix.mat4[15]); // X axis
77373
77374
77375          this.strokeWeight(2);
77376          this.stroke(255, 0, 0);
77377          this.beginShape(this.LINES);
77378          this.vertex(xOff, yOff, zOff);
77379          this.vertex(xOff + size, yOff, zOff);
77380          this.endShape(); // Y axis
77381
77382          this.stroke(0, 255, 0);
77383          this.beginShape(this.LINES);
77384          this.vertex(xOff, yOff, zOff);
77385          this.vertex(xOff, yOff + size, zOff);
77386          this.endShape(); // Z axis
77387
77388          this.stroke(0, 0, 255);
77389          this.beginShape(this.LINES);
77390          this.vertex(xOff, yOff, zOff);
77391          this.vertex(xOff, yOff, zOff + size);
77392          this.endShape();
77393          this.pop();
77394        };
77395      };
77396
77397      module.exports = p5;
77398    }, {
77399      "../core/constants": 18,
77400      "../core/main": 24
77401    }],
77402    66: [function (_dereq_, module, exports) {
77403      /**
77404       * @module Lights, Camera
77405       * @submodule Lights
77406       * @for p5
77407       * @requires core
77408       */
77409      'use strict';
77410
77411      var p5 = _dereq_('../core/main');
77412      /**
77413       * Creates an ambient light with a color
77414       *
77415       * @method ambientLight
77416       * @param  {Number}        v1      red or hue value relative to
77417       *                                 the current color range
77418       * @param  {Number}        v2      green or saturation value
77419       *                                 relative to the current color range
77420       * @param  {Number}        v3      blue or brightness value
77421       *                                 relative to the current color range
77422       * @param  {Number}        [alpha] the alpha value
77423       * @chainable
77424       *
77425       * @example
77426       * <div>
77427       * <code>
77428       * function setup() {
77429       *   createCanvas(100, 100, WEBGL);
77430       * }
77431       * function draw() {
77432       *   background(0);
77433       *   ambientLight(150);
77434       *   ambientMaterial(250);
77435       *   noStroke();
77436       *   sphere(25);
77437       * }
77438       * </code>
77439       * </div>
77440       *
77441       * @alt
77442       * evenly distributed light across a sphere
77443       *
77444       */
77445
77446      /**
77447       * @method ambientLight
77448       * @param  {String}        value   a color string
77449       * @chainable
77450       */
77451
77452      /**
77453       * @method ambientLight
77454       * @param  {Number}        gray   a gray value
77455       * @param  {Number}        [alpha]
77456       * @chainable
77457       */
77458
77459      /**
77460       * @method ambientLight
77461       * @param  {Number[]}      values  an array containing the red,green,blue &
77462       *                                 and alpha components of the color
77463       * @chainable
77464       */
77465
77466      /**
77467       * @method ambientLight
77468       * @param  {p5.Color}      color   the ambient light color
77469       * @chainable
77470       */
77471
77472
77473      p5.prototype.ambientLight = function (v1, v2, v3, a) {
77474        this._assert3d('ambientLight');
77475
77476        p5._validateParameters('ambientLight', arguments);
77477
77478        var color = this.color.apply(this, arguments);
77479
77480        var shader = this._renderer._useLightShader(); //@todo this is a bit icky. array uniforms have
77481        //to be multiples of the type 3(rgb) in this case.
77482        //a preallocated Float32Array(24) that we copy into
77483        //would be better
77484
77485
77486        shader.setUniform('uUseLighting', true); //in case there's no material color for the geometry
77487
77488        shader.setUniform('uMaterialColor', this._renderer.curFillColor);
77489
77490        this._renderer.ambientLightColors.push(color._array[0], color._array[1], color._array[2]);
77491
77492        shader.setUniform('uAmbientColor', this._renderer.ambientLightColors);
77493        shader.setUniform('uAmbientLightCount', this._renderer.ambientLightColors.length / 3);
77494        return this;
77495      };
77496      /**
77497       * Creates a directional light with a color and a direction
77498       * @method directionalLight
77499       * @param  {Number}    v1       red or hue value (depending on the current
77500       * color mode),
77501       * @param  {Number}    v2       green or saturation value
77502       * @param  {Number}    v3       blue or brightness value
77503       * @param  {p5.Vector} position the direction of the light
77504       * @chainable
77505       * @example
77506       * <div>
77507       * <code>
77508       * function setup() {
77509       *   createCanvas(100, 100, WEBGL);
77510       * }
77511       * function draw() {
77512       *   background(0);
77513       *   //move your mouse to change light direction
77514       *   let dirX = (mouseX / width - 0.5) * 2;
77515       *   let dirY = (mouseY / height - 0.5) * 2;
77516       *   directionalLight(250, 250, 250, -dirX, -dirY, 0.25);
77517       *   ambientMaterial(250);
77518       *   noStroke();
77519       *   sphere(25);
77520       * }
77521       * </code>
77522       * </div>
77523       *
77524       * @alt
77525       * light source on canvas changeable with mouse position
77526       *
77527       */
77528
77529      /**
77530       * @method directionalLight
77531       * @param  {Number[]|String|p5.Color} color   color Array, CSS color string,
77532       *                                             or <a href="#/p5.Color">p5.Color</a> value
77533       * @param  {Number}                   x       x axis direction
77534       * @param  {Number}                   y       y axis direction
77535       * @param  {Number}                   z       z axis direction
77536       * @chainable
77537       */
77538
77539      /**
77540       * @method directionalLight
77541       * @param  {Number[]|String|p5.Color} color
77542       * @param  {p5.Vector}                position
77543       * @chainable
77544       */
77545
77546      /**
77547       * @method directionalLight
77548       * @param  {Number}    v1
77549       * @param  {Number}    v2
77550       * @param  {Number}    v3
77551       * @param  {Number}    x
77552       * @param  {Number}    y
77553       * @param  {Number}    z
77554       * @chainable
77555       */
77556
77557
77558      p5.prototype.directionalLight = function (v1, v2, v3, x, y, z) {
77559        this._assert3d('directionalLight');
77560
77561        p5._validateParameters('directionalLight', arguments);
77562
77563        var shader = this._renderer._useLightShader(); //@TODO: check parameters number
77564
77565
77566        var color;
77567
77568        if (v1 instanceof p5.Color) {
77569          color = v1;
77570        } else {
77571          color = this.color(v1, v2, v3);
77572        }
77573
77574        var _x, _y, _z;
77575
77576        var v = arguments[arguments.length - 1];
77577
77578        if (typeof v === 'number') {
77579          _x = arguments[arguments.length - 3];
77580          _y = arguments[arguments.length - 2];
77581          _z = arguments[arguments.length - 1];
77582        } else {
77583          _x = v.x;
77584          _y = v.y;
77585          _z = v.z;
77586        }
77587
77588        shader.setUniform('uUseLighting', true); //in case there's no material color for the geometry
77589
77590        shader.setUniform('uMaterialColor', this._renderer.curFillColor); // normalize direction
77591
77592        var l = Math.sqrt(_x * _x + _y * _y + _z * _z);
77593
77594        this._renderer.directionalLightDirections.push(_x / l, _y / l, _z / l);
77595
77596        shader.setUniform('uLightingDirection', this._renderer.directionalLightDirections);
77597
77598        this._renderer.directionalLightColors.push(color._array[0], color._array[1], color._array[2]);
77599
77600        shader.setUniform('uDirectionalColor', this._renderer.directionalLightColors);
77601        shader.setUniform('uDirectionalLightCount', this._renderer.directionalLightColors.length / 3);
77602        return this;
77603      };
77604      /**
77605       * Creates a point light with a color and a light position
77606       * @method pointLight
77607       * @param  {Number}    v1       red or hue value (depending on the current
77608       * color mode),
77609       * @param  {Number}    v2       green or saturation value
77610       * @param  {Number}    v3       blue or brightness value
77611       * @param  {Number}    x        x axis position
77612       * @param  {Number}    y        y axis position
77613       * @param  {Number}    z        z axis position
77614       * @chainable
77615       * @example
77616       * <div>
77617       * <code>
77618       * function setup() {
77619       *   createCanvas(100, 100, WEBGL);
77620       * }
77621       * function draw() {
77622       *   background(0);
77623       *   //move your mouse to change light position
77624       *   let locX = mouseX - width / 2;
77625       *   let locY = mouseY - height / 2;
77626       *   // to set the light position,
77627       *   // think of the world's coordinate as:
77628       *   // -width/2,-height/2 -------- width/2,-height/2
77629       *   //                |            |
77630       *   //                |     0,0    |
77631       *   //                |            |
77632       *   // -width/2,height/2--------width/2,height/2
77633       *   pointLight(250, 250, 250, locX, locY, 50);
77634       *   ambientMaterial(250);
77635       *   noStroke();
77636       *   sphere(25);
77637       * }
77638       * </code>
77639       * </div>
77640       *
77641       * @alt
77642       * spot light on canvas changes position with mouse
77643       *
77644       */
77645
77646      /**
77647       * @method pointLight
77648       * @param  {Number}    v1
77649       * @param  {Number}    v2
77650       * @param  {Number}    v3
77651       * @param  {p5.Vector} position the position of the light
77652       * @chainable
77653       */
77654
77655      /**
77656       * @method pointLight
77657       * @param  {Number[]|String|p5.Color} color   color Array, CSS color string,
77658       * or <a href="#/p5.Color">p5.Color</a> value
77659       * @param  {Number}                   x
77660       * @param  {Number}                   y
77661       * @param  {Number}                   z
77662       * @chainable
77663       */
77664
77665      /**
77666       * @method pointLight
77667       * @param  {Number[]|String|p5.Color} color
77668       * @param  {p5.Vector}                position
77669       * @chainable
77670       */
77671
77672
77673      p5.prototype.pointLight = function (v1, v2, v3, x, y, z) {
77674        this._assert3d('pointLight');
77675
77676        p5._validateParameters('pointLight', arguments); //@TODO: check parameters number
77677
77678
77679        var color;
77680
77681        if (v1 instanceof p5.Color) {
77682          color = v1;
77683        } else {
77684          color = this.color(v1, v2, v3);
77685        }
77686
77687        var _x, _y, _z;
77688
77689        var v = arguments[arguments.length - 1];
77690
77691        if (typeof v === 'number') {
77692          _x = arguments[arguments.length - 3];
77693          _y = arguments[arguments.length - 2];
77694          _z = arguments[arguments.length - 1];
77695        } else {
77696          _x = v.x;
77697          _y = v.y;
77698          _z = v.z;
77699        }
77700
77701        var shader = this._renderer._useLightShader();
77702
77703        shader.setUniform('uUseLighting', true); //in case there's no material color for the geometry
77704
77705        shader.setUniform('uMaterialColor', this._renderer.curFillColor);
77706
77707        this._renderer.pointLightPositions.push(_x, _y, _z);
77708
77709        shader.setUniform('uPointLightLocation', this._renderer.pointLightPositions);
77710
77711        this._renderer.pointLightColors.push(color._array[0], color._array[1], color._array[2]);
77712
77713        shader.setUniform('uPointLightColor', this._renderer.pointLightColors);
77714        shader.setUniform('uPointLightCount', this._renderer.pointLightColors.length / 3);
77715        return this;
77716      };
77717
77718      module.exports = p5;
77719    }, {
77720      "../core/main": 24
77721    }],
77722    67: [function (_dereq_, module, exports) {
77723      /**
77724       * @module Shape
77725       * @submodule 3D Models
77726       * @for p5
77727       * @requires core
77728       * @requires p5.Geometry
77729       */
77730      'use strict';
77731
77732      var p5 = _dereq_('../core/main');
77733
77734      _dereq_('./p5.Geometry');
77735      /**
77736       * Load a 3d model from an OBJ file.
77737       * <br><br>
77738       * One of the limitations of the OBJ format is that it doesn't have a built-in
77739       * sense of scale. This means that models exported from different programs might
77740       * be very different sizes. If your model isn't displaying, try calling
77741       * <a href="#/p5/loadModel">loadModel()</a> with the normalized parameter set to true. This will resize the
77742       * model to a scale appropriate for p5. You can also make additional changes to
77743       * the final size of your model with the <a href="#/p5/scale">scale()</a> function.
77744       *
77745       * @method loadModel
77746       * @param  {String} path              Path of the model to be loaded
77747       * @param  {Boolean} normalize        If true, scale the model to a
77748       *                                      standardized size when loading
77749       * @param  {function(p5.Geometry)} [successCallback] Function to be called
77750       *                                     once the model is loaded. Will be passed
77751       *                                     the 3D model object.
77752       * @param  {function(Event)} [failureCallback] called with event error if
77753       *                                         the image fails to load.
77754       * @return {p5.Geometry} the <a href="#/p5.Geometry">p5.Geometry</a> object
77755       *
77756       * @example
77757       * <div>
77758       * <code>
77759       * //draw a spinning octahedron
77760       * let octahedron;
77761       *
77762       * function preload() {
77763       *   octahedron = loadModel('assets/octahedron.obj');
77764       * }
77765       *
77766       * function setup() {
77767       *   createCanvas(100, 100, WEBGL);
77768       * }
77769       *
77770       * function draw() {
77771       *   background(200);
77772       *   rotateX(frameCount * 0.01);
77773       *   rotateY(frameCount * 0.01);
77774       *   model(octahedron);
77775       * }
77776       * </code>
77777       * </div>
77778       *
77779       * @alt
77780       * Vertically rotating 3-d octahedron.
77781       *
77782       * @example
77783       * <div>
77784       * <code>
77785       * //draw a spinning teapot
77786       * let teapot;
77787       *
77788       * function preload() {
77789       *   // Load model with normalise parameter set to true
77790       *   teapot = loadModel('assets/teapot.obj', true);
77791       * }
77792       *
77793       * function setup() {
77794       *   createCanvas(100, 100, WEBGL);
77795       * }
77796       *
77797       * function draw() {
77798       *   background(200);
77799       *   scale(0.4); // Scaled to make model fit into canvas
77800       *   rotateX(frameCount * 0.01);
77801       *   rotateY(frameCount * 0.01);
77802       *   normalMaterial(); // For effect
77803       *   model(teapot);
77804       * }
77805       * </code>
77806       * </div>
77807       *
77808       * @alt
77809       * Vertically rotating 3-d teapot with red, green and blue gradient.
77810       */
77811
77812      /**
77813       * @method loadModel
77814       * @param  {String} path
77815       * @param  {function(p5.Geometry)} [successCallback]
77816       * @param  {function(Event)} [failureCallback]
77817       * @return {p5.Geometry} the <a href="#/p5.Geometry">p5.Geometry</a> object
77818       */
77819
77820
77821      p5.prototype.loadModel = function (path) {
77822        p5._validateParameters('loadModel', arguments);
77823
77824        var normalize;
77825        var successCallback;
77826        var failureCallback;
77827
77828        if (typeof arguments[1] === 'boolean') {
77829          normalize = arguments[1];
77830          successCallback = arguments[2];
77831          failureCallback = arguments[3];
77832        } else {
77833          normalize = false;
77834          successCallback = arguments[1];
77835          failureCallback = arguments[2];
77836        }
77837
77838        var model = new p5.Geometry();
77839        model.gid = path + '|' + normalize;
77840        var self = this;
77841        this.loadStrings(path, function (strings) {
77842          parseObj(model, strings);
77843
77844          if (normalize) {
77845            model.normalize();
77846          }
77847
77848          self._decrementPreload();
77849
77850          if (typeof successCallback === 'function') {
77851            successCallback(model);
77852          }
77853        }.bind(this), failureCallback);
77854        return model;
77855      };
77856      /**
77857       * Parse OBJ lines into model. For reference, this is what a simple model of a
77858       * square might look like:
77859       *
77860       * v -0.5 -0.5 0.5
77861       * v -0.5 -0.5 -0.5
77862       * v -0.5 0.5 -0.5
77863       * v -0.5 0.5 0.5
77864       *
77865       * f 4 3 2 1
77866       */
77867
77868
77869      function parseObj(model, lines) {
77870        // OBJ allows a face to specify an index for a vertex (in the above example),
77871        // but it also allows you to specify a custom combination of vertex, UV
77872        // coordinate, and vertex normal. So, "3/4/3" would mean, "use vertex 3 with
77873        // UV coordinate 4 and vertex normal 3". In WebGL, every vertex with different
77874        // parameters must be a different vertex, so loadedVerts is used to
77875        // temporarily store the parsed vertices, normals, etc., and indexedVerts is
77876        // used to map a specific combination (keyed on, for example, the string
77877        // "3/4/3"), to the actual index of the newly created vertex in the final
77878        // object.
77879        var loadedVerts = {
77880          v: [],
77881          vt: [],
77882          vn: []
77883        };
77884        var indexedVerts = {};
77885
77886        for (var line = 0; line < lines.length; ++line) {
77887          // Each line is a separate object (vertex, face, vertex normal, etc)
77888          // For each line, split it into tokens on whitespace. The first token
77889          // describes the type.
77890          var tokens = lines[line].trim().split(/\b\s+/);
77891
77892          if (tokens.length > 0) {
77893            if (tokens[0] === 'v' || tokens[0] === 'vn') {
77894              // Check if this line describes a vertex or vertex normal.
77895              // It will have three numeric parameters.
77896              var vertex = new p5.Vector(parseFloat(tokens[1]), parseFloat(tokens[2]), parseFloat(tokens[3]));
77897              loadedVerts[tokens[0]].push(vertex);
77898            } else if (tokens[0] === 'vt') {
77899              // Check if this line describes a texture coordinate.
77900              // It will have two numeric parameters.
77901              var texVertex = [parseFloat(tokens[1]), parseFloat(tokens[2])];
77902              loadedVerts[tokens[0]].push(texVertex);
77903            } else if (tokens[0] === 'f') {
77904              // Check if this line describes a face.
77905              // OBJ faces can have more than three points. Triangulate points.
77906              for (var tri = 3; tri < tokens.length; ++tri) {
77907                var face = [];
77908                var vertexTokens = [1, tri - 1, tri];
77909
77910                for (var tokenInd = 0; tokenInd < vertexTokens.length; ++tokenInd) {
77911                  // Now, convert the given token into an index
77912                  var vertString = tokens[vertexTokens[tokenInd]];
77913                  var vertIndex = 0; // TODO: Faces can technically use negative numbers to refer to the
77914                  // previous nth vertex. I haven't seen this used in practice, but
77915                  // it might be good to implement this in the future.
77916
77917                  if (indexedVerts[vertString] !== undefined) {
77918                    vertIndex = indexedVerts[vertString];
77919                  } else {
77920                    var vertParts = vertString.split('/');
77921
77922                    for (var i = 0; i < vertParts.length; i++) {
77923                      vertParts[i] = parseInt(vertParts[i]) - 1;
77924                    }
77925
77926                    vertIndex = indexedVerts[vertString] = model.vertices.length;
77927                    model.vertices.push(loadedVerts.v[vertParts[0]].copy());
77928
77929                    if (loadedVerts.vt[vertParts[1]]) {
77930                      model.uvs.push(loadedVerts.vt[vertParts[1]].slice());
77931                    } else {
77932                      model.uvs.push([0, 0]);
77933                    }
77934
77935                    if (loadedVerts.vn[vertParts[2]]) {
77936                      model.vertexNormals.push(loadedVerts.vn[vertParts[2]].copy());
77937                    }
77938                  }
77939
77940                  face.push(vertIndex);
77941                }
77942
77943                if (face[0] !== face[1] && face[0] !== face[2] && face[1] !== face[2]) {
77944                  model.faces.push(face);
77945                }
77946              }
77947            }
77948          }
77949        } // If the model doesn't have normals, compute the normals
77950
77951
77952        if (model.vertexNormals.length === 0) {
77953          model.computeNormals();
77954        }
77955
77956        return model;
77957      }
77958      /**
77959       * Render a 3d model to the screen.
77960       *
77961       * @method model
77962       * @param  {p5.Geometry} model Loaded 3d model to be rendered
77963       * @example
77964       * <div>
77965       * <code>
77966       * //draw a spinning octahedron
77967       * let octahedron;
77968       *
77969       * function preload() {
77970       *   octahedron = loadModel('assets/octahedron.obj');
77971       * }
77972       *
77973       * function setup() {
77974       *   createCanvas(100, 100, WEBGL);
77975       * }
77976       *
77977       * function draw() {
77978       *   background(200);
77979       *   rotateX(frameCount * 0.01);
77980       *   rotateY(frameCount * 0.01);
77981       *   model(octahedron);
77982       * }
77983       * </code>
77984       * </div>
77985       *
77986       * @alt
77987       * Vertically rotating 3-d octahedron.
77988       *
77989       */
77990
77991
77992      p5.prototype.model = function (model) {
77993        this._assert3d('model');
77994
77995        p5._validateParameters('model', arguments);
77996
77997        if (model.vertices.length > 0) {
77998          if (!this._renderer.geometryInHash(model.gid)) {
77999            model._makeTriangleEdges()._edgesToVertices();
78000
78001            this._renderer.createBuffers(model.gid, model);
78002          }
78003
78004          this._renderer.drawBuffers(model.gid);
78005        }
78006      };
78007
78008      module.exports = p5;
78009    }, {
78010      "../core/main": 24,
78011      "./p5.Geometry": 70
78012    }],
78013    68: [function (_dereq_, module, exports) {
78014      /**
78015       * @module Lights, Camera
78016       * @submodule Material
78017       * @for p5
78018       * @requires core
78019       */
78020      'use strict';
78021
78022      var p5 = _dereq_('../core/main');
78023
78024      var constants = _dereq_('../core/constants');
78025
78026      _dereq_('./p5.Texture');
78027      /**
78028       * Loads a custom shader from the provided vertex and fragment
78029       * shader paths. The shader files are loaded asynchronously in the
78030       * background, so this method should be used in <a href="#/p5/preload">preload()</a>.
78031       *
78032       * For now, there are three main types of shaders. p5 will automatically
78033       * supply appropriate vertices, normals, colors, and lighting attributes
78034       * if the parameters defined in the shader match the names.
78035       *
78036       * @method loadShader
78037       * @param {String} [vertFilename] path to file containing vertex shader
78038       * source code
78039       * @param {String} [fragFilename] path to file containing fragment shader
78040       * source code
78041       * @return {p5.Shader} a shader object created from the provided
78042       * vertex and fragment shader files.
78043       *
78044       * @example
78045       * <div modernizr='webgl'>
78046       * <code>
78047       * let mandel;
78048       * function preload() {
78049       *   // load the shader definitions from files
78050       *   mandel = loadShader('assets/shader.vert', 'assets/shader.frag');
78051       * }
78052       * function setup() {
78053       *   createCanvas(100, 100, WEBGL);
78054       *   // use the shader
78055       *   shader(mandel);
78056       *   noStroke();
78057       *   mandel.setUniform('p', [-0.74364388703, 0.13182590421]);
78058       * }
78059       *
78060       * function draw() {
78061       *   mandel.setUniform('r', 1.5 * exp(-6.5 * (1 + sin(millis() / 2000))));
78062       *   quad(-1, -1, 1, -1, 1, 1, -1, 1);
78063       * }
78064       * </code>
78065       * </div>
78066       *
78067       * @alt
78068       * zooming Mandelbrot set. a colorful, infinitely detailed fractal.
78069       */
78070
78071
78072      p5.prototype.loadShader = function (vertFilename, fragFilename) {
78073        p5._validateParameters('loadShader', arguments);
78074
78075        var loadedShader = new p5.Shader();
78076        var self = this;
78077        var loadedFrag = false;
78078        var loadedVert = false;
78079        this.loadStrings(fragFilename, function (result) {
78080          loadedShader._fragSrc = result.join('\n');
78081          loadedFrag = true;
78082
78083          if (loadedVert) {
78084            self._decrementPreload();
78085          }
78086        });
78087        this.loadStrings(vertFilename, function (result) {
78088          loadedShader._vertSrc = result.join('\n');
78089          loadedVert = true;
78090
78091          if (loadedFrag) {
78092            self._decrementPreload();
78093          }
78094        });
78095        return loadedShader;
78096      };
78097      /**
78098       * @method createShader
78099       * @param {String} vertSrc source code for the vertex shader
78100       * @param {String} fragSrc source code for the fragment shader
78101       * @returns {p5.Shader} a shader object created from the provided
78102       * vertex and fragment shaders.
78103       *
78104       * @example
78105       * <div modernizr='webgl'>
78106       * <code>
78107       * // the 'varying's are shared between both vertex & fragment shaders
78108       * let varying = 'precision highp float; varying vec2 vPos;';
78109       *
78110       * // the vertex shader is called for each vertex
78111       * let vs =
78112       *   varying +
78113       *   'attribute vec3 aPosition;' +
78114       *   'void main() { vPos = (gl_Position = vec4(aPosition,1.0)).xy; }';
78115       *
78116       * // the fragment shader is called for each pixel
78117       * let fs =
78118       *   varying +
78119       *   'uniform vec2 p;' +
78120       *   'uniform float r;' +
78121       *   'const int I = 500;' +
78122       *   'void main() {' +
78123       *   '  vec2 c = p + vPos * r, z = c;' +
78124       *   '  float n = 0.0;' +
78125       *   '  for (int i = I; i > 0; i --) {' +
78126       *   '    if(z.x*z.x+z.y*z.y > 4.0) {' +
78127       *   '      n = float(i)/float(I);' +
78128       *   '      break;' +
78129       *   '    }' +
78130       *   '    z = vec2(z.x*z.x-z.y*z.y, 2.0*z.x*z.y) + c;' +
78131       *   '  }' +
78132       *   '  gl_FragColor = vec4(0.5-cos(n*17.0)/2.0,0.5-cos(n*13.0)/2.0,0.5-cos(n*23.0)/2.0,1.0);' +
78133       *   '}';
78134       *
78135       * let mandel;
78136       * function setup() {
78137       *   createCanvas(100, 100, WEBGL);
78138       *
78139       *   // create and initialize the shader
78140       *   mandel = createShader(vs, fs);
78141       *   shader(mandel);
78142       *   noStroke();
78143       *
78144       *   // 'p' is the center point of the Mandelbrot image
78145       *   mandel.setUniform('p', [-0.74364388703, 0.13182590421]);
78146       * }
78147       *
78148       * function draw() {
78149       *   // 'r' is the size of the image in Mandelbrot-space
78150       *   mandel.setUniform('r', 1.5 * exp(-6.5 * (1 + sin(millis() / 2000))));
78151       *   quad(-1, -1, 1, -1, 1, 1, -1, 1);
78152       * }
78153       * </code>
78154       * </div>
78155       *
78156       * @alt
78157       * zooming Mandelbrot set. a colorful, infinitely detailed fractal.
78158       */
78159
78160
78161      p5.prototype.createShader = function (vertSrc, fragSrc) {
78162        this._assert3d('createShader');
78163
78164        p5._validateParameters('createShader', arguments);
78165
78166        return new p5.Shader(this._renderer, vertSrc, fragSrc);
78167      };
78168      /**
78169       * The <a href="#/p5/shader">shader()</a> function lets the user provide a custom shader
78170       * to fill in shapes in WEBGL mode. Users can create their
78171       * own shaders by loading vertex and fragment shaders with
78172       * <a href="#/p5/loadShader">loadShader()</a>.
78173       *
78174       * @method shader
78175       * @chainable
78176       * @param {p5.Shader} [s] the desired <a href="#/p5.Shader">p5.Shader</a> to use for rendering
78177       * shapes.
78178       */
78179
78180
78181      p5.prototype.shader = function (s) {
78182        this._assert3d('shader');
78183
78184        p5._validateParameters('shader', arguments);
78185
78186        if (s._renderer === undefined) {
78187          s._renderer = this._renderer;
78188        }
78189
78190        if (s.isStrokeShader()) {
78191          this._renderer.setStrokeShader(s);
78192        } else {
78193          this._renderer.setFillShader(s);
78194        }
78195
78196        return this;
78197      };
78198      /**
78199       * Normal material for geometry. You can view all
78200       * possible materials in this
78201       * <a href="https://p5js.org/examples/3d-materials.html">example</a>.
78202       * @method normalMaterial
78203       * @chainable
78204       * @example
78205       * <div>
78206       * <code>
78207       * function setup() {
78208       *   createCanvas(100, 100, WEBGL);
78209       * }
78210       *
78211       * function draw() {
78212       *   background(200);
78213       *   normalMaterial();
78214       *   sphere(50);
78215       * }
78216       * </code>
78217       * </div>
78218       *
78219       * @alt
78220       * Red, green and blue gradient.
78221       *
78222       */
78223
78224
78225      p5.prototype.normalMaterial = function () {
78226        this._assert3d('normalMaterial');
78227
78228        p5._validateParameters('normalMaterial', arguments);
78229
78230        this._renderer.drawMode = constants.FILL;
78231
78232        this._renderer.setFillShader(this._renderer._getNormalShader());
78233
78234        this._renderer.curFillColor = [1, 1, 1, 1];
78235        this.noStroke();
78236        return this;
78237      };
78238      /**
78239       * Texture for geometry.  You can view other possible materials in this
78240       * <a href="https://p5js.org/examples/3d-materials.html">example</a>.
78241       * @method texture
78242       * @param {p5.Image|p5.MediaElement|p5.Graphics} tex 2-dimensional graphics
78243       *                    to render as texture
78244       * @chainable
78245       * @example
78246       * <div>
78247       * <code>
78248       * let img;
78249       * function preload() {
78250       *   img = loadImage('assets/laDefense.jpg');
78251       * }
78252       *
78253       * function setup() {
78254       *   createCanvas(100, 100, WEBGL);
78255       * }
78256       *
78257       * function draw() {
78258       *   background(0);
78259       *   rotateZ(frameCount * 0.01);
78260       *   rotateX(frameCount * 0.01);
78261       *   rotateY(frameCount * 0.01);
78262       *   //pass image as texture
78263       *   texture(img);
78264       *   box(200, 200, 200);
78265       * }
78266       * </code>
78267       * </div>
78268       *
78269       * <div>
78270       * <code>
78271       * let pg;
78272       * function setup() {
78273       *   createCanvas(100, 100, WEBGL);
78274       *   pg = createGraphics(200, 200);
78275       *   pg.textSize(100);
78276       * }
78277       *
78278       * function draw() {
78279       *   background(0);
78280       *   pg.background(255);
78281       *   pg.text('hello!', 0, 100);
78282       *   //pass image as texture
78283       *   texture(pg);
78284       *   plane(200);
78285       * }
78286       * </code>
78287       * </div>
78288       *
78289       * <div>
78290       * <code>
78291       * let vid;
78292       * function preload() {
78293       *   vid = createVideo('assets/fingers.mov');
78294       *   vid.hide();
78295       *   vid.loop();
78296       * }
78297       * function setup() {
78298       *   createCanvas(100, 100, WEBGL);
78299       * }
78300       *
78301       * function draw() {
78302       *   background(0);
78303       *   //pass video frame as texture
78304       *   texture(vid);
78305       *   plane(200);
78306       * }
78307       * </code>
78308       * </div>
78309       *
78310       * @alt
78311       * Rotating view of many images umbrella and grid roof on a 3d plane
78312       * black canvas
78313       * black canvas
78314       *
78315       */
78316
78317
78318      p5.prototype.texture = function (tex) {
78319        this._assert3d('texture');
78320
78321        p5._validateParameters('texture', arguments);
78322
78323        this._renderer.drawMode = constants.TEXTURE;
78324        this._renderer.textureImage = tex;
78325
78326        var shader = this._renderer._useLightShader();
78327
78328        shader.setUniform('uSpecular', false);
78329        shader.setUniform('isTexture', true);
78330        shader.setUniform('uSampler', tex);
78331        this.noStroke();
78332        return this;
78333      };
78334      /**
78335       * Sets the coordinate space for texture mapping. The default mode is IMAGE
78336       * which refers to the actual coordinates of the image.
78337       * NORMAL refers to a normalized space of values ranging from 0 to 1.
78338       * This function only works in WEBGL mode.
78339       *
78340       * With IMAGE, if an image is 100 x 200 pixels, mapping the image onto the entire
78341       * size of a quad would require the points (0,0) (100, 0) (100,200) (0,200).
78342       * The same mapping in NORMAL is (0,0) (1,0) (1,1) (0,1).
78343       * @method  textureMode
78344       * @param {Constant} mode either IMAGE or NORMAL
78345       * @example
78346       * <div>
78347       * <code>
78348       * let img;
78349       *
78350       * function preload() {
78351       *   img = loadImage('assets/laDefense.jpg');
78352       * }
78353       *
78354       * function setup() {
78355       *   createCanvas(100, 100, WEBGL);
78356       * }
78357       *
78358       * function draw() {
78359       *   texture(img);
78360       *   textureMode(NORMAL);
78361       *   beginShape();
78362       *   vertex(-50, -50, 0, 0);
78363       *   vertex(50, -50, 1, 0);
78364       *   vertex(50, 50, 1, 1);
78365       *   vertex(-50, 50, 0, 1);
78366       *   endShape();
78367       * }
78368       * </code>
78369       * </div>
78370       *
78371       * @alt
78372       * the underside of a white umbrella and gridded ceiling above
78373       *
78374       * <div>
78375       * <code>
78376       * let img;
78377       *
78378       * function preload() {
78379       *   img = loadImage('assets/laDefense.jpg');
78380       * }
78381       *
78382       * function setup() {
78383       *   createCanvas(100, 100, WEBGL);
78384       * }
78385       *
78386       * function draw() {
78387       *   texture(img);
78388       *   textureMode(NORMAL);
78389       *   beginShape();
78390       *   vertex(-50, -50, 0, 0);
78391       *   vertex(50, -50, img.width, 0);
78392       *   vertex(50, 50, img.width, img.height);
78393       *   vertex(-50, 50, 0, img.height);
78394       *   endShape();
78395       * }
78396       * </code>
78397       * </div>
78398       *
78399       * @alt
78400       * the underside of a white umbrella and gridded ceiling above
78401       *
78402       */
78403
78404
78405      p5.prototype.textureMode = function (mode) {
78406        if (mode !== constants.IMAGE && mode !== constants.NORMAL) {
78407          console.warn('You tried to set ' + mode + ' textureMode only supports IMAGE & NORMAL ');
78408        } else {
78409          this._renderer.textureMode = mode;
78410        }
78411      };
78412      /**
78413       * Ambient material for geometry with a given color. You can view all
78414       * possible materials in this
78415       * <a href="https://p5js.org/examples/3d-materials.html">example</a>.
78416       * @method  ambientMaterial
78417       * @param  {Number} v1  gray value, red or hue value
78418       *                         (depending on the current color mode),
78419       * @param  {Number} [v2] green or saturation value
78420       * @param  {Number} [v3] blue or brightness value
78421       * @param  {Number} [a]  opacity
78422       * @chainable
78423       * @example
78424       * <div>
78425       * <code>
78426       * function setup() {
78427       *   createCanvas(100, 100, WEBGL);
78428       * }
78429       * function draw() {
78430       *   background(0);
78431       *   ambientLight(100);
78432       *   pointLight(250, 250, 250, 100, 100, 0);
78433       *   ambientMaterial(250);
78434       *   sphere(50);
78435       * }
78436       * </code>
78437       * </div>
78438       *
78439       * @alt
78440       * radiating light source from top right of canvas
78441       *
78442       */
78443
78444      /**
78445       * @method  ambientMaterial
78446       * @param  {Number[]|String|p5.Color} color  color, color Array, or CSS color string
78447       * @chainable
78448       */
78449
78450
78451      p5.prototype.ambientMaterial = function (v1, v2, v3, a) {
78452        this._assert3d('ambientMaterial');
78453
78454        p5._validateParameters('ambientMaterial', arguments);
78455
78456        var color = p5.prototype.color.apply(this, arguments);
78457        this._renderer.curFillColor = color._array;
78458
78459        var shader = this._renderer._useLightShader();
78460
78461        shader.setUniform('uMaterialColor', this._renderer.curFillColor);
78462        shader.setUniform('uSpecular', false);
78463        shader.setUniform('isTexture', false);
78464        return this;
78465      };
78466      /**
78467       * Specular material for geometry with a given color. You can view all
78468       * possible materials in this
78469       * <a href="https://p5js.org/examples/3d-materials.html">example</a>.
78470       * @method specularMaterial
78471       * @param  {Number} v1  gray value, red or hue value
78472       *                       (depending on the current color mode),
78473       * @param  {Number} [v2] green or saturation value
78474       * @param  {Number} [v3] blue or brightness value
78475       * @param  {Number} [a]  opacity
78476       * @chainable
78477       * @example
78478       * <div>
78479       * <code>
78480       * function setup() {
78481       *   createCanvas(100, 100, WEBGL);
78482       * }
78483       * function draw() {
78484       *   background(0);
78485       *   ambientLight(100);
78486       *   pointLight(250, 250, 250, 100, 100, 0);
78487       *   specularMaterial(250);
78488       *   sphere(50);
78489       * }
78490       * </code>
78491       * </div>
78492       *
78493       * @alt
78494       * diffused radiating light source from top right of canvas
78495       *
78496       */
78497
78498      /**
78499       * @method specularMaterial
78500       * @param  {Number[]|String|p5.Color} color color Array, or CSS color string
78501       * @chainable
78502       */
78503
78504
78505      p5.prototype.specularMaterial = function (v1, v2, v3, a) {
78506        this._assert3d('specularMaterial');
78507
78508        p5._validateParameters('specularMaterial', arguments);
78509
78510        var color = p5.prototype.color.apply(this, arguments);
78511        this._renderer.curFillColor = color._array;
78512
78513        var shader = this._renderer._useLightShader();
78514
78515        shader.setUniform('uMaterialColor', this._renderer.curFillColor);
78516        shader.setUniform('uSpecular', true);
78517        shader.setUniform('isTexture', false);
78518        return this;
78519      };
78520      /**
78521       * @private blends colors according to color components.
78522       * If alpha value is less than 1, we need to enable blending
78523       * on our gl context.  Otherwise opaque objects need to a depthMask.
78524       * @param  {Number[]} color [description]
78525       * @return {Number[]]}  Normalized numbers array
78526       */
78527
78528
78529      p5.RendererGL.prototype._applyColorBlend = function (colors) {
78530        var gl = this.GL;
78531        var isTexture = this.drawMode === constants.TEXTURE;
78532
78533        if (isTexture || colors[colors.length - 1] < 1.0) {
78534          gl.depthMask(isTexture);
78535          gl.enable(gl.BLEND);
78536          gl.blendEquation(gl.FUNC_ADD);
78537          gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
78538        } else {
78539          gl.depthMask(true);
78540          gl.disable(gl.BLEND);
78541        }
78542
78543        return colors;
78544      };
78545
78546      module.exports = p5;
78547    }, {
78548      "../core/constants": 18,
78549      "../core/main": 24,
78550      "./p5.Texture": 76
78551    }],
78552    69: [function (_dereq_, module, exports) {
78553      /**
78554       * @module Lights, Camera
78555       * @submodule Camera
78556       * @requires core
78557       */
78558      'use strict';
78559
78560      var p5 = _dereq_('../core/main'); ////////////////////////////////////////////////////////////////////////////////
78561      // p5.Prototype Methods
78562      ////////////////////////////////////////////////////////////////////////////////
78563
78564      /**
78565       * Sets the camera position for a 3D sketch. Parameters for this function define
78566       * the position for the camera, the center of the sketch (where the camera is
78567       * pointing), and an up direction (the orientation of the camera).
78568       *
78569       * When called with no arguments, this function creates a default camera
78570       * equivalent to
78571       * camera(0, 0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0);
78572       * @method camera
78573       * @for p5
78574       * @param  {Number} [x]        camera position value on x axis
78575       * @param  {Number} [y]        camera position value on y axis
78576       * @param  {Number} [z]        camera position value on z axis
78577       * @param  {Number} [centerX]  x coordinate representing center of the sketch
78578       * @param  {Number} [centerY]  y coordinate representing center of the sketch
78579       * @param  {Number} [centerZ]  z coordinate representing center of the sketch
78580       * @param  {Number} [upX]      x component of direction 'up' from camera
78581       * @param  {Number} [upY]      y component of direction 'up' from camera
78582       * @param  {Number} [upZ]      z component of direction 'up' from camera
78583       * @chainable
78584       * @example
78585       * <div>
78586       * <code>
78587       * function setup() {
78588       *   createCanvas(100, 100, WEBGL);
78589       * }
78590       * function draw() {
78591       *   background(204);
78592       *   //move the camera away from the plane by a sin wave
78593       *   camera(0, 0, 20 + sin(frameCount * 0.01) * 10, 0, 0, 0, 0, 1, 0);
78594       *   plane(10, 10);
78595       * }
78596       * </code>
78597       * </div>
78598       *
78599       * @alt
78600       * White square repeatedly grows to fill canvas and then shrinks.
78601       *
78602       */
78603
78604
78605      p5.prototype.camera = function () {
78606        this._assert3d('camera');
78607
78608        p5._validateParameters('camera', arguments);
78609
78610        this._renderer._curCamera.camera.apply(this._renderer._curCamera, arguments);
78611
78612        return this;
78613      };
78614      /**
78615       * Sets a perspective projection for the camera in a 3D sketch. This projection
78616       * represents depth through foreshortening: objects that are close to the camera
78617       * appear their actual size while those that are further away from the camera
78618       * appear smaller. The parameters to this function define the viewing frustum
78619       * (the truncated pyramid within which objects are seen by the camera) through
78620       * vertical field of view, aspect ratio (usually width/height), and near and far
78621       * clipping planes.
78622       *
78623       * When called with no arguments, the defaults
78624       * provided are equivalent to
78625       * perspective(PI/3.0, width/height, eyeZ/10.0, eyeZ*10.0), where eyeZ
78626       * is equal to ((height/2.0) / tan(PI*60.0/360.0));
78627       * @method  perspective
78628       * @for p5
78629       * @param  {Number} [fovy]   camera frustum vertical field of view,
78630       *                           from bottom to top of view, in <a href="#/p5/angleMode">angleMode</a> units
78631       * @param  {Number} [aspect] camera frustum aspect ratio
78632       * @param  {Number} [near]   frustum near plane length
78633       * @param  {Number} [far]    frustum far plane length
78634       * @chainable
78635       * @example
78636       * <div>
78637       * <code>
78638       * //drag the mouse to look around!
78639       * //you will see there's a vanishing point
78640       * function setup() {
78641       *   createCanvas(100, 100, WEBGL);
78642       *   perspective(PI / 3.0, width / height, 0.1, 500);
78643       * }
78644       * function draw() {
78645       *   background(200);
78646       *   orbitControl();
78647       *   normalMaterial();
78648       *
78649       *   rotateX(-0.3);
78650       *   rotateY(-0.2);
78651       *   translate(0, 0, -50);
78652       *
78653       *   push();
78654       *   translate(-15, 0, sin(frameCount / 30) * 95);
78655       *   box(30);
78656       *   pop();
78657       *   push();
78658       *   translate(15, 0, sin(frameCount / 30 + PI) * 95);
78659       *   box(30);
78660       *   pop();
78661       * }
78662       * </code>
78663       * </div>
78664       *
78665       * @alt
78666       * two colored 3D boxes move back and forth, rotating as mouse is dragged.
78667       *
78668       */
78669
78670
78671      p5.prototype.perspective = function () {
78672        this._assert3d('perspective');
78673
78674        p5._validateParameters('perspective', arguments);
78675
78676        this._renderer._curCamera.perspective.apply(this._renderer._curCamera, arguments);
78677
78678        return this;
78679      };
78680      /**
78681       * Sets an orthographic projection for the camera in a 3D sketch and defines a
78682       * box-shaped viewing frustum within which objects are seen. In this projection,
78683       * all objects with the same dimension appear the same size, regardless of
78684       * whether they are near or far from the camera. The parameters to this
78685       * function specify the viewing frustum where left and right are the minimum and
78686       * maximum x values, top and bottom are the minimum and maximum y values, and near
78687       * and far are the minimum and maximum z values. If no parameters are given, the
78688       * default is used: ortho(-width/2, width/2, -height/2, height/2).
78689       * @method  ortho
78690       * @for p5
78691       * @param  {Number} [left]   camera frustum left plane
78692       * @param  {Number} [right]  camera frustum right plane
78693       * @param  {Number} [bottom] camera frustum bottom plane
78694       * @param  {Number} [top]    camera frustum top plane
78695       * @param  {Number} [near]   camera frustum near plane
78696       * @param  {Number} [far]    camera frustum far plane
78697       * @chainable
78698       * @example
78699       * <div>
78700       * <code>
78701       * //drag the mouse to look around!
78702       * //there's no vanishing point
78703       * function setup() {
78704       *   createCanvas(100, 100, WEBGL);
78705       *   ortho(-width / 2, width / 2, height / 2, -height / 2, 0, 500);
78706       * }
78707       * function draw() {
78708       *   background(200);
78709       *   orbitControl();
78710       *   normalMaterial();
78711       *
78712       *   rotateX(0.2);
78713       *   rotateY(-0.2);
78714       *   push();
78715       *   translate(-15, 0, sin(frameCount / 30) * 65);
78716       *   box(30);
78717       *   pop();
78718       *   push();
78719       *   translate(15, 0, sin(frameCount / 30 + PI) * 65);
78720       *   box(30);
78721       *   pop();
78722       * }
78723       * </code>
78724       * </div>
78725       *
78726       * @alt
78727       * two 3D boxes move back and forth along same plane, rotating as mouse is dragged.
78728       *
78729       */
78730
78731
78732      p5.prototype.ortho = function () {
78733        this._assert3d('ortho');
78734
78735        p5._validateParameters('ortho', arguments);
78736
78737        this._renderer._curCamera.ortho.apply(this._renderer._curCamera, arguments);
78738
78739        return this;
78740      }; ////////////////////////////////////////////////////////////////////////////////
78741      // p5.Camera
78742      ////////////////////////////////////////////////////////////////////////////////
78743
78744      /**
78745       * Creates a new <a href="#/p5.Camera">p5.Camera</a> object and tells the
78746       * renderer to use that camera.
78747       * Returns the p5.Camera object.
78748       * @method createCamera
78749       * @return {p5.Camera} The newly created camera object.
78750       * @for p5
78751       */
78752
78753
78754      p5.prototype.createCamera = function () {
78755        this._assert3d('createCamera');
78756
78757        var _cam = new p5.Camera(this._renderer); // compute default camera settings, then set a default camera
78758
78759
78760        _cam._computeCameraDefaultSettings();
78761
78762        _cam._setDefaultCamera(); // set renderer current camera to the new camera
78763
78764
78765        this._renderer._curCamera = _cam;
78766        return _cam;
78767      };
78768      /**
78769       * This class describes a camera for use in p5's
78770       * <a href="https://github.com/processing/p5.js/wiki/Getting-started-with-WebGL-in-p5">
78771       * WebGL mode</a>. It contains camera position, orientation, and projection
78772       * information necessary for rendering a 3D scene.
78773       *
78774       * New p5.Camera objects can be made through the
78775       * <a href="#/p5/createCamera">createCamera()</a> function and controlled through
78776       * the methods described below. A camera created in this way will use a default
78777       * position in the scene and a default perspective projection until these
78778       * properties are changed through the various methods available. It is possible
78779       * to create multiple cameras, in which case the current camera
78780       * can be set through the <a href="#/p5/setCamera">setCamera()</a> method.
78781       *
78782       *
78783       * Note:
78784       * The methods below operate in two coordinate systems: the 'world' coordinate
78785       * system describe positions in terms of their relationship to the origin along
78786       * the X, Y and Z axes whereas the camera's 'local' coordinate system
78787       * describes positions from the camera's point of view: left-right, up-down,
78788       * and forward-backward. The <a href="#/p5.Camera/move">move()</a> method,
78789       * for instance, moves the camera along its own axes, whereas the
78790       * <a href="#/p5.Camera/setPosition">setPosition()</a>
78791       * method sets the camera's position in world-space.
78792       *
78793       *
78794       * @class p5.Camera
78795       * @param {rendererGL} rendererGL instance of WebGL renderer
78796       * @example
78797       * <div>
78798       * <code>
78799       * let cam;
78800       * let delta = 0.01;
78801       *
78802       * function setup() {
78803       *   createCanvas(100, 100, WEBGL);
78804       *   normalMaterial();
78805       *   cam = createCamera();
78806       *   // set initial pan angle
78807       *   cam.pan(-0.8);
78808       * }
78809       *
78810       * function draw() {
78811       *   background(200);
78812       *
78813       *   // pan camera according to angle 'delta'
78814       *   cam.pan(delta);
78815       *
78816       *   // every 160 frames, switch direction
78817       *   if (frameCount % 160 === 0) {
78818       *     delta *= -1;
78819       *   }
78820       *
78821       *   rotateX(frameCount * 0.01);
78822       *   translate(-100, 0, 0);
78823       *   box(20);
78824       *   translate(35, 0, 0);
78825       *   box(20);
78826       *   translate(35, 0, 0);
78827       *   box(20);
78828       *   translate(35, 0, 0);
78829       *   box(20);
78830       *   translate(35, 0, 0);
78831       *   box(20);
78832       *   translate(35, 0, 0);
78833       *   box(20);
78834       *   translate(35, 0, 0);
78835       *   box(20);
78836       * }
78837       * </code>
78838       * </div>
78839       *
78840       * @alt
78841       * camera view pans left and right across a series of rotating 3D boxes.
78842       *
78843       */
78844
78845
78846      p5.Camera = function (renderer) {
78847        this._renderer = renderer;
78848        this.cameraType = 'default';
78849        this.cameraMatrix = new p5.Matrix();
78850        this.projMatrix = new p5.Matrix();
78851      }; ////////////////////////////////////////////////////////////////////////////////
78852      // Camera Projection Methods
78853      ////////////////////////////////////////////////////////////////////////////////
78854
78855      /**
78856       * Sets a perspective projection for a p5.Camera object and sets parameters
78857       * for that projection according to <a href="#/p5/perspective">perspective()</a>
78858       * syntax.
78859       * @method perspective
78860       * @for p5.Camera
78861       */
78862
78863
78864      p5.Camera.prototype.perspective = function (fovy, aspect, near, far) {
78865        if (typeof fovy === 'undefined') {
78866          fovy = this.defaultCameraFOV; // this avoids issue where setting angleMode(DEGREES) before calling
78867          // perspective leads to a smaller than expected FOV (because
78868          // _computeCameraDefaultSettings computes in radians)
78869
78870          this.cameraFOV = fovy;
78871        } else {
78872          this.cameraFOV = this._renderer._pInst._toRadians(fovy);
78873        }
78874
78875        if (typeof aspect === 'undefined') {
78876          aspect = this.defaultAspectRatio;
78877        }
78878
78879        if (typeof near === 'undefined') {
78880          near = this.defaultCameraNear;
78881        }
78882
78883        if (typeof far === 'undefined') {
78884          far = this.defaultCameraFar;
78885        }
78886
78887        if (near <= 0.0001) {
78888          near = 0.01;
78889          console.log('Avoid perspective near plane values close to or below 0. ' + 'Setting value to 0.01.');
78890        }
78891
78892        if (far < near) {
78893          console.log('Perspective far plane value is less than near plane value. ' + 'Nothing will be shown.');
78894        }
78895
78896        this.aspectRatio = aspect;
78897        this.cameraNear = near;
78898        this.cameraFar = far;
78899        this.projMatrix = p5.Matrix.identity();
78900        var f = 1.0 / Math.tan(this.cameraFOV / 2);
78901        var nf = 1.0 / (this.cameraNear - this.cameraFar); // prettier-ignore
78902
78903        this.projMatrix.set(f / aspect, 0, 0, 0, 0, -f, 0, 0, 0, 0, (far + near) * nf, -1, 0, 0, 2 * far * near * nf, 0);
78904
78905        if (this._isActive()) {
78906          this._renderer.uPMatrix.set(this.projMatrix.mat4[0], this.projMatrix.mat4[1], this.projMatrix.mat4[2], this.projMatrix.mat4[3], this.projMatrix.mat4[4], this.projMatrix.mat4[5], this.projMatrix.mat4[6], this.projMatrix.mat4[7], this.projMatrix.mat4[8], this.projMatrix.mat4[9], this.projMatrix.mat4[10], this.projMatrix.mat4[11], this.projMatrix.mat4[12], this.projMatrix.mat4[13], this.projMatrix.mat4[14], this.projMatrix.mat4[15]);
78907        }
78908
78909        this.cameraType = 'custom';
78910      };
78911      /**
78912       * Sets an orthographic projection for a p5.Camera object and sets parameters
78913       * for that projection according to <a href="#/p5/ortho">ortho()</a> syntax.
78914       * @method ortho
78915       * @for p5.Camera
78916       */
78917
78918
78919      p5.Camera.prototype.ortho = function (left, right, bottom, top, near, far) {
78920        if (left === undefined) left = -this._renderer.width / 2;
78921        if (right === undefined) right = +this._renderer.width / 2;
78922        if (bottom === undefined) bottom = -this._renderer.height / 2;
78923        if (top === undefined) top = +this._renderer.height / 2;
78924        if (near === undefined) near = 0;
78925        if (far === undefined) far = Math.max(this._renderer.width, this._renderer.height);
78926        var w = right - left;
78927        var h = top - bottom;
78928        var d = far - near;
78929        var x = +2.0 / w;
78930        var y = +2.0 / h;
78931        var z = -2.0 / d;
78932        var tx = -(right + left) / w;
78933        var ty = -(top + bottom) / h;
78934        var tz = -(far + near) / d;
78935        this.projMatrix = p5.Matrix.identity(); // prettier-ignore
78936
78937        this.projMatrix.set(x, 0, 0, 0, 0, -y, 0, 0, 0, 0, z, 0, tx, ty, tz, 1);
78938
78939        if (this._isActive()) {
78940          this._renderer.uPMatrix.set(this.projMatrix.mat4[0], this.projMatrix.mat4[1], this.projMatrix.mat4[2], this.projMatrix.mat4[3], this.projMatrix.mat4[4], this.projMatrix.mat4[5], this.projMatrix.mat4[6], this.projMatrix.mat4[7], this.projMatrix.mat4[8], this.projMatrix.mat4[9], this.projMatrix.mat4[10], this.projMatrix.mat4[11], this.projMatrix.mat4[12], this.projMatrix.mat4[13], this.projMatrix.mat4[14], this.projMatrix.mat4[15]);
78941        }
78942
78943        this.cameraType = 'custom';
78944      }; ////////////////////////////////////////////////////////////////////////////////
78945      // Camera Orientation Methods
78946      ////////////////////////////////////////////////////////////////////////////////
78947
78948      /**
78949       * Rotate camera view about arbitrary axis defined by x,y,z
78950       * based on http://learnwebgl.brown37.net/07_cameras/camera_rotating_motion.html
78951       * @method _rotateView
78952       * @private
78953       */
78954
78955
78956      p5.Camera.prototype._rotateView = function (a, x, y, z) {
78957        var centerX = this.centerX;
78958        var centerY = this.centerY;
78959        var centerZ = this.centerZ; // move center by eye position such that rotation happens around eye position
78960
78961        centerX -= this.eyeX;
78962        centerY -= this.eyeY;
78963        centerZ -= this.eyeZ;
78964        var rotation = p5.Matrix.identity(this._renderer._pInst);
78965        rotation.rotate(a, x, y, z); // prettier-ignore
78966
78967        var rotatedCenter = [centerX * rotation.mat4[0] + centerY * rotation.mat4[4] + centerZ * rotation.mat4[8], centerX * rotation.mat4[1] + centerY * rotation.mat4[5] + centerZ * rotation.mat4[9], centerX * rotation.mat4[2] + centerY * rotation.mat4[6] + centerZ * rotation.mat4[10]]; // add eye position back into center
78968
78969        rotatedCenter[0] += this.eyeX;
78970        rotatedCenter[1] += this.eyeY;
78971        rotatedCenter[2] += this.eyeZ;
78972        this.camera(this.eyeX, this.eyeY, this.eyeZ, rotatedCenter[0], rotatedCenter[1], rotatedCenter[2], this.upX, this.upY, this.upZ);
78973      };
78974      /**
78975       * Panning rotates the camera view to the left and right.
78976       * @method pan
78977       * @param {Number} angle amount to rotate camera in current
78978       * <a href="#/p5/angleMode">angleMode</a> units.
78979       * Greater than 0 values rotate counterclockwise (to the left).
78980       * @example
78981       * <div>
78982       * <code>
78983       * let cam;
78984       * let delta = 0.01;
78985       *
78986       * function setup() {
78987       *   createCanvas(100, 100, WEBGL);
78988       *   normalMaterial();
78989       *   cam = createCamera();
78990       *   // set initial pan angle
78991       *   cam.pan(-0.8);
78992       * }
78993       *
78994       * function draw() {
78995       *   background(200);
78996       *
78997       *   // pan camera according to angle 'delta'
78998       *   cam.pan(delta);
78999       *
79000       *   // every 160 frames, switch direction
79001       *   if (frameCount % 160 === 0) {
79002       *     delta *= -1;
79003       *   }
79004       *
79005       *   rotateX(frameCount * 0.01);
79006       *   translate(-100, 0, 0);
79007       *   box(20);
79008       *   translate(35, 0, 0);
79009       *   box(20);
79010       *   translate(35, 0, 0);
79011       *   box(20);
79012       *   translate(35, 0, 0);
79013       *   box(20);
79014       *   translate(35, 0, 0);
79015       *   box(20);
79016       *   translate(35, 0, 0);
79017       *   box(20);
79018       *   translate(35, 0, 0);
79019       *   box(20);
79020       * }
79021       * </code>
79022       * </div>
79023       *
79024       * @alt
79025       * camera view pans left and right across a series of rotating 3D boxes.
79026       *
79027       */
79028
79029
79030      p5.Camera.prototype.pan = function (amount) {
79031        var local = this._getLocalAxes();
79032
79033        this._rotateView(amount, local.y[0], local.y[1], local.y[2]);
79034      };
79035      /**
79036       * Tilting rotates the camera view up and down.
79037       * @method tilt
79038       * @param {Number} angle amount to rotate camera in current
79039       * <a href="#/p5/angleMode">angleMode</a> units.
79040       * Greater than 0 values rotate counterclockwise (to the left).
79041       * @example
79042       * <div>
79043       * <code>
79044       * let cam;
79045       * let delta = 0.01;
79046       *
79047       * function setup() {
79048       *   createCanvas(100, 100, WEBGL);
79049       *   normalMaterial();
79050       *   cam = createCamera();
79051       *   // set initial tilt
79052       *   cam.tilt(-0.8);
79053       * }
79054       *
79055       * function draw() {
79056       *   background(200);
79057       *
79058       *   // pan camera according to angle 'delta'
79059       *   cam.tilt(delta);
79060       *
79061       *   // every 160 frames, switch direction
79062       *   if (frameCount % 160 === 0) {
79063       *     delta *= -1;
79064       *   }
79065       *
79066       *   rotateY(frameCount * 0.01);
79067       *   translate(0, -100, 0);
79068       *   box(20);
79069       *   translate(0, 35, 0);
79070       *   box(20);
79071       *   translate(0, 35, 0);
79072       *   box(20);
79073       *   translate(0, 35, 0);
79074       *   box(20);
79075       *   translate(0, 35, 0);
79076       *   box(20);
79077       *   translate(0, 35, 0);
79078       *   box(20);
79079       *   translate(0, 35, 0);
79080       *   box(20);
79081       * }
79082       * </code>
79083       * </div>
79084       *
79085       * @alt
79086       * camera view tilts up and down across a series of rotating 3D boxes.
79087       */
79088
79089
79090      p5.Camera.prototype.tilt = function (amount) {
79091        var local = this._getLocalAxes();
79092
79093        this._rotateView(amount, local.x[0], local.x[1], local.x[2]);
79094      };
79095      /**
79096       * Reorients the camera to look at a position in world space.
79097       * @method lookAt
79098       * @for p5.Camera
79099       * @param {Number} x x position of a point in world space
79100       * @param {Number} y y position of a point in world space
79101       * @param {Number} z z position of a point in world space
79102       * @example
79103       * <div>
79104       * <code>
79105       * let cam;
79106       *
79107       * function setup() {
79108       *   createCanvas(100, 100, WEBGL);
79109       *   normalMaterial();
79110       *   cam = createCamera();
79111       * }
79112       *
79113       * function draw() {
79114       *   background(200);
79115       *
79116       *   // look at a new random point every 60 frames
79117       *   if (frameCount % 60 === 0) {
79118       *     cam.lookAt(random(-100, 100), random(-50, 50), 0);
79119       *   }
79120       *
79121       *   rotateX(frameCount * 0.01);
79122       *   translate(-100, 0, 0);
79123       *   box(20);
79124       *   translate(35, 0, 0);
79125       *   box(20);
79126       *   translate(35, 0, 0);
79127       *   box(20);
79128       *   translate(35, 0, 0);
79129       *   box(20);
79130       *   translate(35, 0, 0);
79131       *   box(20);
79132       *   translate(35, 0, 0);
79133       *   box(20);
79134       *   translate(35, 0, 0);
79135       *   box(20);
79136       * }
79137       * </code>
79138       * </div>
79139       *
79140       * @alt
79141       * camera view of rotating 3D cubes changes to look at a new random
79142       * point every second .
79143       */
79144
79145
79146      p5.Camera.prototype.lookAt = function (x, y, z) {
79147        this.camera(this.eyeX, this.eyeY, this.eyeZ, x, y, z, this.upX, this.upY, this.upZ);
79148      }; ////////////////////////////////////////////////////////////////////////////////
79149      // Camera Position Methods
79150      ////////////////////////////////////////////////////////////////////////////////
79151
79152      /**
79153       * Sets a camera's position and orientation.  This is equivalent to calling
79154       * <a href="#/p5/camera">camera()</a> on a p5.Camera object.
79155       * @method camera
79156       * @for p5.Camera
79157       */
79158
79159
79160      p5.Camera.prototype.camera = function (eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ) {
79161        if (typeof eyeX === 'undefined') {
79162          eyeX = this.defaultEyeX;
79163          eyeY = this.defaultEyeY;
79164          eyeZ = this.defaultEyeZ;
79165          centerX = eyeX;
79166          centerY = eyeY;
79167          centerZ = 0;
79168          upX = 0;
79169          upY = 1;
79170          upZ = 0;
79171        }
79172
79173        this.eyeX = eyeX;
79174        this.eyeY = eyeY;
79175        this.eyeZ = eyeZ;
79176        this.centerX = centerX;
79177        this.centerY = centerY;
79178        this.centerZ = centerZ;
79179        this.upX = upX;
79180        this.upY = upY;
79181        this.upZ = upZ;
79182
79183        var local = this._getLocalAxes(); // the camera affects the model view matrix, insofar as it
79184        // inverse translates the world to the eye position of the camera
79185        // and rotates it.
79186        // prettier-ignore
79187
79188
79189        this.cameraMatrix.set(local.x[0], local.y[0], local.z[0], 0, local.x[1], local.y[1], local.z[1], 0, local.x[2], local.y[2], local.z[2], 0, 0, 0, 0, 1);
79190        var tx = -eyeX;
79191        var ty = -eyeY;
79192        var tz = -eyeZ;
79193        this.cameraMatrix.translate([tx, ty, tz]);
79194
79195        if (this._isActive()) {
79196          this._renderer.uMVMatrix.set(this.cameraMatrix.mat4[0], this.cameraMatrix.mat4[1], this.cameraMatrix.mat4[2], this.cameraMatrix.mat4[3], this.cameraMatrix.mat4[4], this.cameraMatrix.mat4[5], this.cameraMatrix.mat4[6], this.cameraMatrix.mat4[7], this.cameraMatrix.mat4[8], this.cameraMatrix.mat4[9], this.cameraMatrix.mat4[10], this.cameraMatrix.mat4[11], this.cameraMatrix.mat4[12], this.cameraMatrix.mat4[13], this.cameraMatrix.mat4[14], this.cameraMatrix.mat4[15]);
79197        }
79198
79199        return this;
79200      };
79201      /**
79202       * Move camera along its local axes while maintaining current camera orientation.
79203       * @method move
79204       * @param {Number} x amount to move along camera's left-right axis
79205       * @param {Number} y amount to move along camera's up-down axis
79206       * @param {Number} z amount to move along camera's forward-backward axis
79207       * @example
79208       * <div>
79209       * <code>
79210       * // see the camera move along its own axes while maintaining its orientation
79211       * let cam;
79212       * let delta = 0.5;
79213       *
79214       * function setup() {
79215       *   createCanvas(100, 100, WEBGL);
79216       *   normalMaterial();
79217       *   cam = createCamera();
79218       * }
79219       *
79220       * function draw() {
79221       *   background(200);
79222       *
79223       *   // move the camera along its local axes
79224       *   cam.move(delta, delta, 0);
79225       *
79226       *   // every 100 frames, switch direction
79227       *   if (frameCount % 150 === 0) {
79228       *     delta *= -1;
79229       *   }
79230       *
79231       *   translate(-10, -10, 0);
79232       *   box(50, 8, 50);
79233       *   translate(15, 15, 0);
79234       *   box(50, 8, 50);
79235       *   translate(15, 15, 0);
79236       *   box(50, 8, 50);
79237       *   translate(15, 15, 0);
79238       *   box(50, 8, 50);
79239       *   translate(15, 15, 0);
79240       *   box(50, 8, 50);
79241       *   translate(15, 15, 0);
79242       *   box(50, 8, 50);
79243       * }
79244       * </code>
79245       * </div>
79246       *
79247       * @alt
79248       * camera view moves along a series of 3D boxes, maintaining the same
79249       * orientation throughout the move
79250       */
79251
79252
79253      p5.Camera.prototype.move = function (x, y, z) {
79254        var local = this._getLocalAxes(); // scale local axes by movement amounts
79255        // based on http://learnwebgl.brown37.net/07_cameras/camera_linear_motion.html
79256
79257
79258        var dx = [local.x[0] * x, local.x[1] * x, local.x[2] * x];
79259        var dy = [local.y[0] * y, local.y[1] * y, local.y[2] * y];
79260        var dz = [local.z[0] * z, local.z[1] * z, local.z[2] * z];
79261        this.camera(this.eyeX + dx[0] + dy[0] + dz[0], this.eyeY + dx[1] + dy[1] + dz[1], this.eyeZ + dx[2] + dy[2] + dz[2], this.centerX + dx[0] + dy[0] + dz[0], this.centerY + dx[1] + dy[1] + dz[1], this.centerZ + dx[2] + dy[2] + dz[2], 0, 1, 0);
79262      };
79263      /**
79264       * Set camera position in world-space while maintaining current camera
79265       * orientation.
79266       * @method setPosition
79267       * @param {Number} x x position of a point in world space
79268       * @param {Number} y y position of a point in world space
79269       * @param {Number} z z position of a point in world space
79270       * @example
79271       * <div>
79272       * <code>
79273       * // press '1' '2' or '3' keys to set camera position
79274       *
79275       * let cam;
79276       *
79277       * function setup() {
79278       *   createCanvas(100, 100, WEBGL);
79279       *   normalMaterial();
79280       *   cam = createCamera();
79281       * }
79282       *
79283       * function draw() {
79284       *   background(200);
79285       *
79286       *   // '1' key
79287       *   if (keyIsDown(49)) {
79288       *     cam.setPosition(30, 0, 80);
79289       *   }
79290       *   // '2' key
79291       *   if (keyIsDown(50)) {
79292       *     cam.setPosition(0, 0, 80);
79293       *   }
79294       *   // '3' key
79295       *   if (keyIsDown(51)) {
79296       *     cam.setPosition(-30, 0, 80);
79297       *   }
79298       *
79299       *   box(20);
79300       * }
79301       * </code>
79302       * </div>
79303       *
79304       * @alt
79305       * camera position changes as the user presses keys, altering view of a 3D box
79306       */
79307
79308
79309      p5.Camera.prototype.setPosition = function (x, y, z) {
79310        var diffX = x - this.eyeX;
79311        var diffY = y - this.eyeY;
79312        var diffZ = z - this.eyeZ;
79313        this.camera(x, y, z, this.centerX + diffX, this.centerY + diffY, this.centerZ + diffZ, 0, 1, 0);
79314      }; ////////////////////////////////////////////////////////////////////////////////
79315      // Camera Helper Methods
79316      ////////////////////////////////////////////////////////////////////////////////
79317      // @TODO: combine this function with _setDefaultCamera to compute these values
79318      // as-needed
79319
79320
79321      p5.Camera.prototype._computeCameraDefaultSettings = function () {
79322        this.defaultCameraFOV = 60 / 180 * Math.PI;
79323        this.defaultAspectRatio = this._renderer.width / this._renderer.height;
79324        this.defaultEyeX = 0;
79325        this.defaultEyeY = 0;
79326        this.defaultEyeZ = this._renderer.height / 2.0 / Math.tan(this.defaultCameraFOV / 2.0);
79327        this.defaultCenterX = 0;
79328        this.defaultCenterY = 0;
79329        this.defaultCenterZ = 0;
79330        this.defaultCameraNear = this.defaultEyeZ * 0.1;
79331        this.defaultCameraFar = this.defaultEyeZ * 10;
79332      }; //detect if user didn't set the camera
79333      //then call this function below
79334
79335
79336      p5.Camera.prototype._setDefaultCamera = function () {
79337        this.cameraFOV = this.defaultCameraFOV;
79338        this.aspectRatio = this.defaultAspectRatio;
79339        this.eyeX = this.defaultEyeX;
79340        this.eyeY = this.defaultEyeY;
79341        this.eyeZ = this.defaultEyeZ;
79342        this.centerX = this.defaultCenterX;
79343        this.centerY = this.defaultCenterY;
79344        this.centerZ = this.defaultCenterZ;
79345        this.upX = 0;
79346        this.upY = 1;
79347        this.upZ = 0;
79348        this.cameraNear = this.defaultCameraNear;
79349        this.cameraFar = this.defaultCameraFar;
79350        this.perspective();
79351        this.camera();
79352        this.cameraType = 'default';
79353      };
79354
79355      p5.Camera.prototype._resize = function () {
79356        // If we're using the default camera, update the aspect ratio
79357        if (this.cameraType === 'default') {
79358          this._computeCameraDefaultSettings();
79359
79360          this._setDefaultCamera();
79361        } else {
79362          this.perspective(this.cameraFOV, this._renderer.width / this._renderer.height);
79363        }
79364      };
79365      /**
79366       * Returns a copy of a camera.
79367       * @method copy
79368       * @private
79369       */
79370
79371
79372      p5.Camera.prototype.copy = function () {
79373        var _cam = new p5.Camera(this._renderer);
79374
79375        _cam.cameraFOV = this.cameraFOV;
79376        _cam.aspectRatio = this.aspectRatio;
79377        _cam.eyeX = this.eyeX;
79378        _cam.eyeY = this.eyeY;
79379        _cam.eyeZ = this.eyeZ;
79380        _cam.centerX = this.centerX;
79381        _cam.centerY = this.centerY;
79382        _cam.centerZ = this.centerZ;
79383        _cam.cameraNear = this.cameraNear;
79384        _cam.cameraFar = this.cameraFar;
79385        _cam.cameraType = this.cameraType;
79386        _cam.cameraMatrix = this.cameraMatrix.copy();
79387        _cam.projMatrix = this.projMatrix.copy();
79388        return _cam;
79389      };
79390      /**
79391       * Returns a camera's local axes: left-right, up-down, and forward-backward,
79392       * as defined by vectors in world-space.
79393       * @method _getLocalAxes
79394       * @private
79395       */
79396
79397
79398      p5.Camera.prototype._getLocalAxes = function () {
79399        // calculate camera local Z vector
79400        var z0 = this.eyeX - this.centerX;
79401        var z1 = this.eyeY - this.centerY;
79402        var z2 = this.eyeZ - this.centerZ; // normalize camera local Z vector
79403
79404        var eyeDist = Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
79405
79406        if (eyeDist !== 0) {
79407          z0 /= eyeDist;
79408          z1 /= eyeDist;
79409          z2 /= eyeDist;
79410        } // calculate camera Y vector
79411
79412
79413        var y0 = this.upX;
79414        var y1 = this.upY;
79415        var y2 = this.upZ; // compute camera local X vector as up vector (local Y) cross local Z
79416
79417        var x0 = y1 * z2 - y2 * z1;
79418        var x1 = -y0 * z2 + y2 * z0;
79419        var x2 = y0 * z1 - y1 * z0; // recompute y = z cross x
79420
79421        y0 = z1 * x2 - z2 * x1;
79422        y1 = -z0 * x2 + z2 * x0;
79423        y2 = z0 * x1 - z1 * x0; // cross product gives area of parallelogram, which is < 1.0 for
79424        // non-perpendicular unit-length vectors; so normalize x, y here:
79425
79426        var xmag = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
79427
79428        if (xmag !== 0) {
79429          x0 /= xmag;
79430          x1 /= xmag;
79431          x2 /= xmag;
79432        }
79433
79434        var ymag = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
79435
79436        if (ymag !== 0) {
79437          y0 /= ymag;
79438          y1 /= ymag;
79439          y2 /= ymag;
79440        }
79441
79442        return {
79443          x: [x0, x1, x2],
79444          y: [y0, y1, y2],
79445          z: [z0, z1, z2]
79446        };
79447      };
79448      /**
79449       * Orbits the camera about center point. For use with orbitControl().
79450       * @method _orbit
79451       * @private
79452       * @param {Number} dTheta change in spherical coordinate theta
79453       * @param {Number} dPhi change in spherical coordinate phi
79454       * @param {Number} dRadius change in radius
79455       */
79456
79457
79458      p5.Camera.prototype._orbit = function (dTheta, dPhi, dRadius) {
79459        var diffX = this.eyeX - this.centerX;
79460        var diffY = this.eyeY - this.centerY;
79461        var diffZ = this.eyeZ - this.centerZ; // get spherical coorinates for current camera position about origin
79462
79463        var camRadius = Math.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ); // from https://github.com/mrdoob/three.js/blob/dev/src/math/Spherical.js#L72-L73
79464
79465        var camTheta = Math.atan2(diffX, diffZ); // equatorial angle
79466
79467        var camPhi = Math.acos(Math.max(-1, Math.min(1, diffY / camRadius))); // polar angle
79468        // add change
79469
79470        camTheta += dTheta;
79471        camPhi += dPhi;
79472        camRadius += dRadius; // prevent zooming through the center:
79473
79474        if (camRadius < 0) {
79475          camRadius = 0.1;
79476        } // prevent rotation over the zenith / under bottom
79477
79478
79479        if (camPhi > Math.PI) {
79480          camPhi = Math.PI;
79481        } else if (camPhi <= 0) {
79482          camPhi = 0.001;
79483        } // from https://github.com/mrdoob/three.js/blob/dev/src/math/Vector3.js#L628-L632
79484
79485
79486        var _x = Math.sin(camPhi) * camRadius * Math.sin(camTheta);
79487
79488        var _y = Math.cos(camPhi) * camRadius;
79489
79490        var _z = Math.sin(camPhi) * camRadius * Math.cos(camTheta);
79491
79492        this.camera(_x + this.centerX, _y + this.centerY, _z + this.centerZ, this.centerX, this.centerY, this.centerZ, 0, 1, 0);
79493      };
79494      /**
79495       * Returns true if camera is currently attached to renderer.
79496       * @method _isActive
79497       * @private
79498       */
79499
79500
79501      p5.Camera.prototype._isActive = function () {
79502        return this === this._renderer._curCamera;
79503      };
79504      /**
79505       * Sets rendererGL's current camera to a p5.Camera object.  Allows switching
79506       * between multiple cameras.
79507       * @method setCamera
79508       * @param  {p5.Camera} cam  p5.Camera object
79509       * @for p5
79510       * @example
79511       * <div>
79512       * <code>
79513       * let cam1, cam2;
79514       * let currentCamera;
79515       *
79516       * function setup() {
79517       *   createCanvas(100, 100, WEBGL);
79518       *   normalMaterial();
79519       *
79520       *   cam1 = createCamera();
79521       *   cam2 = createCamera();
79522       *   cam2.setPosition(30, 0, 50);
79523       *   cam2.lookAt(0, 0, 0);
79524       *   cam2.ortho();
79525       *
79526       *   // set variable for previously active camera:
79527       *   currentCamera = 1;
79528       * }
79529       *
79530       * function draw() {
79531       *   background(200);
79532       *
79533       *   // camera 1:
79534       *   cam1.lookAt(0, 0, 0);
79535       *   cam1.setPosition(sin(frameCount / 60) * 200, 0, 100);
79536       *
79537       *   // every 100 frames, switch between the two cameras
79538       *   if (frameCount % 100 === 0) {
79539       *     if (currentCamera === 1) {
79540       *       setCamera(cam1);
79541       *       currentCamera = 0;
79542       *     } else {
79543       *       setCamera(cam2);
79544       *       currentCamera = 1;
79545       *     }
79546       *   }
79547       *
79548       *   drawBoxes();
79549       * }
79550       *
79551       * function drawBoxes() {
79552       *   rotateX(frameCount * 0.01);
79553       *   translate(-100, 0, 0);
79554       *   box(20);
79555       *   translate(35, 0, 0);
79556       *   box(20);
79557       *   translate(35, 0, 0);
79558       *   box(20);
79559       *   translate(35, 0, 0);
79560       *   box(20);
79561       *   translate(35, 0, 0);
79562       *   box(20);
79563       *   translate(35, 0, 0);
79564       *   box(20);
79565       *   translate(35, 0, 0);
79566       *   box(20);
79567       * }
79568       * </code>
79569       * </div>
79570       *
79571       * @alt
79572       * Canvas switches between two camera views, each showing a series of spinning
79573       * 3D boxes.
79574       */
79575
79576
79577      p5.prototype.setCamera = function (cam) {
79578        this._renderer._curCamera = cam; // set the projection matrix (which is not normally updated each frame)
79579
79580        this._renderer.uPMatrix.set(cam.projMatrix.mat4[0], cam.projMatrix.mat4[1], cam.projMatrix.mat4[2], cam.projMatrix.mat4[3], cam.projMatrix.mat4[4], cam.projMatrix.mat4[5], cam.projMatrix.mat4[6], cam.projMatrix.mat4[7], cam.projMatrix.mat4[8], cam.projMatrix.mat4[9], cam.projMatrix.mat4[10], cam.projMatrix.mat4[11], cam.projMatrix.mat4[12], cam.projMatrix.mat4[13], cam.projMatrix.mat4[14], cam.projMatrix.mat4[15]);
79581      };
79582
79583      module.exports = p5.Camera;
79584    }, {
79585      "../core/main": 24
79586    }],
79587    70: [function (_dereq_, module, exports) {
79588      //some of the functions are adjusted from Three.js(http://threejs.org)
79589      'use strict';
79590
79591      var p5 = _dereq_('../core/main');
79592      /**
79593       * p5 Geometry class
79594       * @class p5.Geometry
79595       * @constructor
79596       * @param  {Integer} [detailX] number of vertices on horizontal surface
79597       * @param  {Integer} [detailY] number of vertices on horizontal surface
79598       * @param {function} [callback] function to call upon object instantiation.
79599       *
79600       */
79601
79602
79603      p5.Geometry = function (detailX, detailY, callback) {
79604        //an array containing every vertex
79605        //@type [p5.Vector]
79606        this.vertices = []; //an array containing every vertex for stroke drawing
79607
79608        this.lineVertices = []; //an array 1 normal per lineVertex with
79609        //final position representing which direction to
79610        //displace for strokeWeight
79611        //[[0,0,-1,1], [0,1,0,-1] ...];
79612
79613        this.lineNormals = []; //an array containing 1 normal per vertex
79614        //@type [p5.Vector]
79615        //[p5.Vector, p5.Vector, p5.Vector,p5.Vector, p5.Vector, p5.Vector,...]
79616
79617        this.vertexNormals = []; //an array containing each three vertex indices that form a face
79618        //[[0, 1, 2], [2, 1, 3], ...]
79619
79620        this.faces = []; //a 2D array containing uvs for every vertex
79621        //[[0.0,0.0],[1.0,0.0], ...]
79622
79623        this.uvs = []; // a 2D array containing edge connectivity pattern for create line vertices
79624        //based on faces for most objects;
79625
79626        this.edges = [];
79627        this.detailX = detailX !== undefined ? detailX : 1;
79628        this.detailY = detailY !== undefined ? detailY : 1;
79629
79630        if (callback instanceof Function) {
79631          callback.call(this);
79632        }
79633
79634        return this; // TODO: is this a constructor?
79635      };
79636      /**
79637       * @method computeFaces
79638       * @chainable
79639       */
79640
79641
79642      p5.Geometry.prototype.computeFaces = function () {
79643        this.faces.length = 0;
79644        var sliceCount = this.detailX + 1;
79645        var a, b, c, d;
79646
79647        for (var i = 0; i < this.detailY; i++) {
79648          for (var j = 0; j < this.detailX; j++) {
79649            a = i * sliceCount + j; // + offset;
79650
79651            b = i * sliceCount + j + 1; // + offset;
79652
79653            c = (i + 1) * sliceCount + j + 1; // + offset;
79654
79655            d = (i + 1) * sliceCount + j; // + offset;
79656
79657            this.faces.push([a, b, d]);
79658            this.faces.push([d, b, c]);
79659          }
79660        }
79661
79662        return this;
79663      };
79664
79665      p5.Geometry.prototype._getFaceNormal = function (faceId) {
79666        //This assumes that vA->vB->vC is a counter-clockwise ordering
79667        var face = this.faces[faceId];
79668        var vA = this.vertices[face[0]];
79669        var vB = this.vertices[face[1]];
79670        var vC = this.vertices[face[2]];
79671        var ab = p5.Vector.sub(vB, vA);
79672        var ac = p5.Vector.sub(vC, vA);
79673        var n = p5.Vector.cross(ab, ac);
79674        var ln = p5.Vector.mag(n);
79675        var sinAlpha = ln / (p5.Vector.mag(ab) * p5.Vector.mag(ac));
79676
79677        if (sinAlpha === 0 || isNaN(sinAlpha)) {
79678          console.warn('p5.Geometry.prototype._getFaceNormal:', 'face has colinear sides or a repeated vertex');
79679          return n;
79680        }
79681
79682        if (sinAlpha > 1) sinAlpha = 1; // handle float rounding error
79683
79684        return n.mult(Math.asin(sinAlpha) / ln);
79685      };
79686      /**
79687       * computes smooth normals per vertex as an average of each
79688       * face.
79689       * @method computeNormals
79690       * @chainable
79691       */
79692
79693
79694      p5.Geometry.prototype.computeNormals = function () {
79695        var vertexNormals = this.vertexNormals;
79696        var vertices = this.vertices;
79697        var faces = this.faces;
79698        var iv; // initialize the vertexNormals array with empty vectors
79699
79700        vertexNormals.length = 0;
79701
79702        for (iv = 0; iv < vertices.length; ++iv) {
79703          vertexNormals.push(new p5.Vector());
79704        } // loop through all the faces adding its normal to the normal
79705        // of each of its vertices
79706
79707
79708        for (var f = 0; f < faces.length; ++f) {
79709          var face = faces[f];
79710
79711          var faceNormal = this._getFaceNormal(f); // all three vertices get the normal added
79712
79713
79714          for (var fv = 0; fv < 3; ++fv) {
79715            var vertexIndex = face[fv];
79716            vertexNormals[vertexIndex].add(faceNormal);
79717          }
79718        } // normalize the normals
79719
79720
79721        for (iv = 0; iv < vertices.length; ++iv) {
79722          vertexNormals[iv].normalize();
79723        }
79724
79725        return this;
79726      };
79727      /**
79728       * Averages the vertex normals. Used in curved
79729       * surfaces
79730       * @method averageNormals
79731       * @chainable
79732       */
79733
79734
79735      p5.Geometry.prototype.averageNormals = function () {
79736        for (var i = 0; i <= this.detailY; i++) {
79737          var offset = this.detailX + 1;
79738          var temp = p5.Vector.add(this.vertexNormals[i * offset], this.vertexNormals[i * offset + this.detailX]);
79739          temp = p5.Vector.div(temp, 2);
79740          this.vertexNormals[i * offset] = temp;
79741          this.vertexNormals[i * offset + this.detailX] = temp;
79742        }
79743
79744        return this;
79745      };
79746      /**
79747       * Averages pole normals.  Used in spherical primitives
79748       * @method averagePoleNormals
79749       * @chainable
79750       */
79751
79752
79753      p5.Geometry.prototype.averagePoleNormals = function () {
79754        //average the north pole
79755        var sum = new p5.Vector(0, 0, 0);
79756
79757        for (var i = 0; i < this.detailX; i++) {
79758          sum.add(this.vertexNormals[i]);
79759        }
79760
79761        sum = p5.Vector.div(sum, this.detailX);
79762
79763        for (i = 0; i < this.detailX; i++) {
79764          this.vertexNormals[i] = sum;
79765        } //average the south pole
79766
79767
79768        sum = new p5.Vector(0, 0, 0);
79769
79770        for (i = this.vertices.length - 1; i > this.vertices.length - 1 - this.detailX; i--) {
79771          sum.add(this.vertexNormals[i]);
79772        }
79773
79774        sum = p5.Vector.div(sum, this.detailX);
79775
79776        for (i = this.vertices.length - 1; i > this.vertices.length - 1 - this.detailX; i--) {
79777          this.vertexNormals[i] = sum;
79778        }
79779
79780        return this;
79781      };
79782      /**
79783       * Create a 2D array for establishing stroke connections
79784       * @private
79785       * @chainable
79786       */
79787
79788
79789      p5.Geometry.prototype._makeTriangleEdges = function () {
79790        this.edges.length = 0;
79791
79792        if (Array.isArray(this.strokeIndices)) {
79793          for (var i = 0, max = this.strokeIndices.length; i < max; i++) {
79794            this.edges.push(this.strokeIndices[i]);
79795          }
79796        } else {
79797          for (var j = 0; j < this.faces.length; j++) {
79798            this.edges.push([this.faces[j][0], this.faces[j][1]]);
79799            this.edges.push([this.faces[j][1], this.faces[j][2]]);
79800            this.edges.push([this.faces[j][2], this.faces[j][0]]);
79801          }
79802        }
79803
79804        return this;
79805      };
79806      /**
79807       * Create 4 vertices for each stroke line, two at the beginning position
79808       * and two at the end position. These vertices are displaced relative to
79809       * that line's normal on the GPU
79810       * @private
79811       * @chainable
79812       */
79813
79814
79815      p5.Geometry.prototype._edgesToVertices = function () {
79816        this.lineVertices.length = 0;
79817        this.lineNormals.length = 0;
79818
79819        for (var i = 0; i < this.edges.length; i++) {
79820          var begin = this.vertices[this.edges[i][0]];
79821          var end = this.vertices[this.edges[i][1]];
79822          var dir = end.copy().sub(begin).normalize();
79823          var a = begin.array();
79824          var b = begin.array();
79825          var c = end.array();
79826          var d = end.array();
79827          var dirAdd = dir.array();
79828          var dirSub = dir.array(); // below is used to displace the pair of vertices at beginning and end
79829          // in opposite directions
79830
79831          dirAdd.push(1);
79832          dirSub.push(-1);
79833          this.lineNormals.push(dirAdd, dirSub, dirAdd, dirAdd, dirSub, dirSub);
79834          this.lineVertices.push(a, b, c, c, b, d);
79835        }
79836
79837        return this;
79838      };
79839      /**
79840       * Modifies all vertices to be centered within the range -100 to 100.
79841       * @method normalize
79842       * @chainable
79843       */
79844
79845
79846      p5.Geometry.prototype.normalize = function () {
79847        if (this.vertices.length > 0) {
79848          // Find the corners of our bounding box
79849          var maxPosition = this.vertices[0].copy();
79850          var minPosition = this.vertices[0].copy();
79851
79852          for (var i = 0; i < this.vertices.length; i++) {
79853            maxPosition.x = Math.max(maxPosition.x, this.vertices[i].x);
79854            minPosition.x = Math.min(minPosition.x, this.vertices[i].x);
79855            maxPosition.y = Math.max(maxPosition.y, this.vertices[i].y);
79856            minPosition.y = Math.min(minPosition.y, this.vertices[i].y);
79857            maxPosition.z = Math.max(maxPosition.z, this.vertices[i].z);
79858            minPosition.z = Math.min(minPosition.z, this.vertices[i].z);
79859          }
79860
79861          var center = p5.Vector.lerp(maxPosition, minPosition, 0.5);
79862          var dist = p5.Vector.sub(maxPosition, minPosition);
79863          var longestDist = Math.max(Math.max(dist.x, dist.y), dist.z);
79864          var scale = 200 / longestDist;
79865
79866          for (i = 0; i < this.vertices.length; i++) {
79867            this.vertices[i].sub(center);
79868            this.vertices[i].mult(scale);
79869          }
79870        }
79871
79872        return this;
79873      };
79874
79875      module.exports = p5.Geometry;
79876    }, {
79877      "../core/main": 24
79878    }],
79879    71: [function (_dereq_, module, exports) {
79880      /**
79881       * @requires constants
79882       * @todo see methods below needing further implementation.
79883       * future consideration: implement SIMD optimizations
79884       * when browser compatibility becomes available
79885       * https://developer.mozilla.org/en-US/docs/Web/JavaScript/
79886       *   Reference/Global_Objects/SIMD
79887       */
79888      'use strict';
79889
79890      var p5 = _dereq_('../core/main');
79891
79892      var GLMAT_ARRAY_TYPE = Array;
79893
79894      var isMatrixArray = function (x) {
79895        return x instanceof Array;
79896      };
79897
79898      if (typeof Float32Array !== 'undefined') {
79899        GLMAT_ARRAY_TYPE = Float32Array;
79900
79901        isMatrixArray = function (x) {
79902          return x instanceof Array || x instanceof Float32Array;
79903        };
79904      }
79905      /**
79906       * A class to describe a 4x4 matrix
79907       * for model and view matrix manipulation in the p5js webgl renderer.
79908       * @class p5.Matrix
79909       * @private
79910       * @constructor
79911       * @param {Array} [mat4] array literal of our 4x4 matrix
79912       */
79913
79914
79915      p5.Matrix = function () {
79916        var args = new Array(arguments.length);
79917
79918        for (var i = 0; i < args.length; ++i) {
79919          args[i] = arguments[i];
79920        } // This is default behavior when object
79921        // instantiated using createMatrix()
79922        // @todo implement createMatrix() in core/math.js
79923
79924
79925        if (args.length && args[args.length - 1] instanceof p5) {
79926          this.p5 = args[args.length - 1];
79927        }
79928
79929        if (args[0] === 'mat3') {
79930          this.mat3 = Array.isArray(args[1]) ? args[1] : new GLMAT_ARRAY_TYPE([1, 0, 0, 0, 1, 0, 0, 0, 1]);
79931        } else {
79932          this.mat4 = Array.isArray(args[0]) ? args[0] : new GLMAT_ARRAY_TYPE([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
79933        }
79934
79935        return this;
79936      };
79937      /**
79938       * Sets the x, y, and z component of the vector using two or three separate
79939       * variables, the data from a p5.Matrix, or the values from a float array.
79940       *
79941       * @method set
79942       * @param {p5.Matrix|Float32Array|Number[]} [inMatrix] the input p5.Matrix or
79943       *                                     an Array of length 16
79944       * @chainable
79945       */
79946
79947      /**
79948       * @method set
79949       * @param {Number[]} elements 16 numbers passed by value to avoid
79950       *                                     array copying.
79951       * @chainable
79952       */
79953
79954
79955      p5.Matrix.prototype.set = function (inMatrix) {
79956        if (inMatrix instanceof p5.Matrix) {
79957          this.mat4 = inMatrix.mat4;
79958          return this;
79959        } else if (isMatrixArray(inMatrix)) {
79960          this.mat4 = inMatrix;
79961          return this;
79962        } else if (arguments.length === 16) {
79963          this.mat4[0] = arguments[0];
79964          this.mat4[1] = arguments[1];
79965          this.mat4[2] = arguments[2];
79966          this.mat4[3] = arguments[3];
79967          this.mat4[4] = arguments[4];
79968          this.mat4[5] = arguments[5];
79969          this.mat4[6] = arguments[6];
79970          this.mat4[7] = arguments[7];
79971          this.mat4[8] = arguments[8];
79972          this.mat4[9] = arguments[9];
79973          this.mat4[10] = arguments[10];
79974          this.mat4[11] = arguments[11];
79975          this.mat4[12] = arguments[12];
79976          this.mat4[13] = arguments[13];
79977          this.mat4[14] = arguments[14];
79978          this.mat4[15] = arguments[15];
79979        }
79980
79981        return this;
79982      };
79983      /**
79984       * Gets a copy of the vector, returns a p5.Matrix object.
79985       *
79986       * @method get
79987       * @return {p5.Matrix} the copy of the p5.Matrix object
79988       */
79989
79990
79991      p5.Matrix.prototype.get = function () {
79992        return new p5.Matrix(this.mat4, this.p5);
79993      };
79994      /**
79995       * return a copy of a matrix
79996       * @method copy
79997       * @return {p5.Matrix}   the result matrix
79998       */
79999
80000
80001      p5.Matrix.prototype.copy = function () {
80002        var copied = new p5.Matrix(this.p5);
80003        copied.mat4[0] = this.mat4[0];
80004        copied.mat4[1] = this.mat4[1];
80005        copied.mat4[2] = this.mat4[2];
80006        copied.mat4[3] = this.mat4[3];
80007        copied.mat4[4] = this.mat4[4];
80008        copied.mat4[5] = this.mat4[5];
80009        copied.mat4[6] = this.mat4[6];
80010        copied.mat4[7] = this.mat4[7];
80011        copied.mat4[8] = this.mat4[8];
80012        copied.mat4[9] = this.mat4[9];
80013        copied.mat4[10] = this.mat4[10];
80014        copied.mat4[11] = this.mat4[11];
80015        copied.mat4[12] = this.mat4[12];
80016        copied.mat4[13] = this.mat4[13];
80017        copied.mat4[14] = this.mat4[14];
80018        copied.mat4[15] = this.mat4[15];
80019        return copied;
80020      };
80021      /**
80022       * return an identity matrix
80023       * @method identity
80024       * @return {p5.Matrix}   the result matrix
80025       */
80026
80027
80028      p5.Matrix.identity = function (pInst) {
80029        return new p5.Matrix(pInst);
80030      };
80031      /**
80032       * transpose according to a given matrix
80033       * @method transpose
80034       * @param  {p5.Matrix|Float32Array|Number[]} a  the matrix to be
80035       *                                               based on to transpose
80036       * @chainable
80037       */
80038
80039
80040      p5.Matrix.prototype.transpose = function (a) {
80041        var a01, a02, a03, a12, a13, a23;
80042
80043        if (a instanceof p5.Matrix) {
80044          a01 = a.mat4[1];
80045          a02 = a.mat4[2];
80046          a03 = a.mat4[3];
80047          a12 = a.mat4[6];
80048          a13 = a.mat4[7];
80049          a23 = a.mat4[11];
80050          this.mat4[0] = a.mat4[0];
80051          this.mat4[1] = a.mat4[4];
80052          this.mat4[2] = a.mat4[8];
80053          this.mat4[3] = a.mat4[12];
80054          this.mat4[4] = a01;
80055          this.mat4[5] = a.mat4[5];
80056          this.mat4[6] = a.mat4[9];
80057          this.mat4[7] = a.mat4[13];
80058          this.mat4[8] = a02;
80059          this.mat4[9] = a12;
80060          this.mat4[10] = a.mat4[10];
80061          this.mat4[11] = a.mat4[14];
80062          this.mat4[12] = a03;
80063          this.mat4[13] = a13;
80064          this.mat4[14] = a23;
80065          this.mat4[15] = a.mat4[15];
80066        } else if (isMatrixArray(a)) {
80067          a01 = a[1];
80068          a02 = a[2];
80069          a03 = a[3];
80070          a12 = a[6];
80071          a13 = a[7];
80072          a23 = a[11];
80073          this.mat4[0] = a[0];
80074          this.mat4[1] = a[4];
80075          this.mat4[2] = a[8];
80076          this.mat4[3] = a[12];
80077          this.mat4[4] = a01;
80078          this.mat4[5] = a[5];
80079          this.mat4[6] = a[9];
80080          this.mat4[7] = a[13];
80081          this.mat4[8] = a02;
80082          this.mat4[9] = a12;
80083          this.mat4[10] = a[10];
80084          this.mat4[11] = a[14];
80085          this.mat4[12] = a03;
80086          this.mat4[13] = a13;
80087          this.mat4[14] = a23;
80088          this.mat4[15] = a[15];
80089        }
80090
80091        return this;
80092      };
80093      /**
80094       * invert  matrix according to a give matrix
80095       * @method invert
80096       * @param  {p5.Matrix|Float32Array|Number[]} a   the matrix to be
80097       *                                                based on to invert
80098       * @chainable
80099       */
80100
80101
80102      p5.Matrix.prototype.invert = function (a) {
80103        var a00, a01, a02, a03, a10, a11, a12, a13;
80104        var a20, a21, a22, a23, a30, a31, a32, a33;
80105
80106        if (a instanceof p5.Matrix) {
80107          a00 = a.mat4[0];
80108          a01 = a.mat4[1];
80109          a02 = a.mat4[2];
80110          a03 = a.mat4[3];
80111          a10 = a.mat4[4];
80112          a11 = a.mat4[5];
80113          a12 = a.mat4[6];
80114          a13 = a.mat4[7];
80115          a20 = a.mat4[8];
80116          a21 = a.mat4[9];
80117          a22 = a.mat4[10];
80118          a23 = a.mat4[11];
80119          a30 = a.mat4[12];
80120          a31 = a.mat4[13];
80121          a32 = a.mat4[14];
80122          a33 = a.mat4[15];
80123        } else if (isMatrixArray(a)) {
80124          a00 = a[0];
80125          a01 = a[1];
80126          a02 = a[2];
80127          a03 = a[3];
80128          a10 = a[4];
80129          a11 = a[5];
80130          a12 = a[6];
80131          a13 = a[7];
80132          a20 = a[8];
80133          a21 = a[9];
80134          a22 = a[10];
80135          a23 = a[11];
80136          a30 = a[12];
80137          a31 = a[13];
80138          a32 = a[14];
80139          a33 = a[15];
80140        }
80141
80142        var b00 = a00 * a11 - a01 * a10;
80143        var b01 = a00 * a12 - a02 * a10;
80144        var b02 = a00 * a13 - a03 * a10;
80145        var b03 = a01 * a12 - a02 * a11;
80146        var b04 = a01 * a13 - a03 * a11;
80147        var b05 = a02 * a13 - a03 * a12;
80148        var b06 = a20 * a31 - a21 * a30;
80149        var b07 = a20 * a32 - a22 * a30;
80150        var b08 = a20 * a33 - a23 * a30;
80151        var b09 = a21 * a32 - a22 * a31;
80152        var b10 = a21 * a33 - a23 * a31;
80153        var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
80154
80155        var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
80156
80157        if (!det) {
80158          return null;
80159        }
80160
80161        det = 1.0 / det;
80162        this.mat4[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
80163        this.mat4[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
80164        this.mat4[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
80165        this.mat4[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
80166        this.mat4[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
80167        this.mat4[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
80168        this.mat4[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
80169        this.mat4[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
80170        this.mat4[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
80171        this.mat4[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
80172        this.mat4[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
80173        this.mat4[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
80174        this.mat4[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
80175        this.mat4[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
80176        this.mat4[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
80177        this.mat4[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
80178        return this;
80179      };
80180      /**
80181       * Inverts a 3x3 matrix
80182       * @method invert3x3
80183       * @chainable
80184       */
80185
80186
80187      p5.Matrix.prototype.invert3x3 = function () {
80188        var a00 = this.mat3[0];
80189        var a01 = this.mat3[1];
80190        var a02 = this.mat3[2];
80191        var a10 = this.mat3[3];
80192        var a11 = this.mat3[4];
80193        var a12 = this.mat3[5];
80194        var a20 = this.mat3[6];
80195        var a21 = this.mat3[7];
80196        var a22 = this.mat3[8];
80197        var b01 = a22 * a11 - a12 * a21;
80198        var b11 = -a22 * a10 + a12 * a20;
80199        var b21 = a21 * a10 - a11 * a20; // Calculate the determinant
80200
80201        var det = a00 * b01 + a01 * b11 + a02 * b21;
80202
80203        if (!det) {
80204          return null;
80205        }
80206
80207        det = 1.0 / det;
80208        this.mat3[0] = b01 * det;
80209        this.mat3[1] = (-a22 * a01 + a02 * a21) * det;
80210        this.mat3[2] = (a12 * a01 - a02 * a11) * det;
80211        this.mat3[3] = b11 * det;
80212        this.mat3[4] = (a22 * a00 - a02 * a20) * det;
80213        this.mat3[5] = (-a12 * a00 + a02 * a10) * det;
80214        this.mat3[6] = b21 * det;
80215        this.mat3[7] = (-a21 * a00 + a01 * a20) * det;
80216        this.mat3[8] = (a11 * a00 - a01 * a10) * det;
80217        return this;
80218      };
80219      /**
80220       * transposes a 3x3 p5.Matrix by a mat3
80221       * @method transpose3x3
80222       * @param  {Number[]} mat3 1-dimensional array
80223       * @chainable
80224       */
80225
80226
80227      p5.Matrix.prototype.transpose3x3 = function (mat3) {
80228        var a01 = mat3[1],
80229            a02 = mat3[2],
80230            a12 = mat3[5];
80231        this.mat3[1] = mat3[3];
80232        this.mat3[2] = mat3[6];
80233        this.mat3[3] = a01;
80234        this.mat3[5] = mat3[7];
80235        this.mat3[6] = a02;
80236        this.mat3[7] = a12;
80237        return this;
80238      };
80239      /**
80240       * converts a 4x4 matrix to its 3x3 inverse tranform
80241       * commonly used in MVMatrix to NMatrix conversions.
80242       * @method invertTranspose
80243       * @param  {p5.Matrix} mat4 the matrix to be based on to invert
80244       * @chainable
80245       * @todo  finish implementation
80246       */
80247
80248
80249      p5.Matrix.prototype.inverseTranspose = function (matrix) {
80250        if (this.mat3 === undefined) {
80251          console.error('sorry, this function only works with mat3');
80252        } else {
80253          //convert mat4 -> mat3
80254          this.mat3[0] = matrix.mat4[0];
80255          this.mat3[1] = matrix.mat4[1];
80256          this.mat3[2] = matrix.mat4[2];
80257          this.mat3[3] = matrix.mat4[4];
80258          this.mat3[4] = matrix.mat4[5];
80259          this.mat3[5] = matrix.mat4[6];
80260          this.mat3[6] = matrix.mat4[8];
80261          this.mat3[7] = matrix.mat4[9];
80262          this.mat3[8] = matrix.mat4[10];
80263        }
80264
80265        var inverse = this.invert3x3(); // check inverse succeded
80266
80267        if (inverse) {
80268          inverse.transpose3x3(this.mat3);
80269        } else {
80270          // in case of singularity, just zero the matrix
80271          for (var i = 0; i < 9; i++) {
80272            this.mat3[i] = 0;
80273          }
80274        }
80275
80276        return this;
80277      };
80278      /**
80279       * inspired by Toji's mat4 determinant
80280       * @method determinant
80281       * @return {Number} Determinant of our 4x4 matrix
80282       */
80283
80284
80285      p5.Matrix.prototype.determinant = function () {
80286        var d00 = this.mat4[0] * this.mat4[5] - this.mat4[1] * this.mat4[4],
80287            d01 = this.mat4[0] * this.mat4[6] - this.mat4[2] * this.mat4[4],
80288            d02 = this.mat4[0] * this.mat4[7] - this.mat4[3] * this.mat4[4],
80289            d03 = this.mat4[1] * this.mat4[6] - this.mat4[2] * this.mat4[5],
80290            d04 = this.mat4[1] * this.mat4[7] - this.mat4[3] * this.mat4[5],
80291            d05 = this.mat4[2] * this.mat4[7] - this.mat4[3] * this.mat4[6],
80292            d06 = this.mat4[8] * this.mat4[13] - this.mat4[9] * this.mat4[12],
80293            d07 = this.mat4[8] * this.mat4[14] - this.mat4[10] * this.mat4[12],
80294            d08 = this.mat4[8] * this.mat4[15] - this.mat4[11] * this.mat4[12],
80295            d09 = this.mat4[9] * this.mat4[14] - this.mat4[10] * this.mat4[13],
80296            d10 = this.mat4[9] * this.mat4[15] - this.mat4[11] * this.mat4[13],
80297            d11 = this.mat4[10] * this.mat4[15] - this.mat4[11] * this.mat4[14]; // Calculate the determinant
80298
80299        return d00 * d11 - d01 * d10 + d02 * d09 + d03 * d08 - d04 * d07 + d05 * d06;
80300      };
80301      /**
80302       * multiply two mat4s
80303       * @method mult
80304       * @param {p5.Matrix|Float32Array|Number[]} multMatrix The matrix
80305       *                                                we want to multiply by
80306       * @chainable
80307       */
80308
80309
80310      p5.Matrix.prototype.mult = function (multMatrix) {
80311        var _src;
80312
80313        if (multMatrix === this || multMatrix === this.mat4) {
80314          _src = this.copy().mat4; // only need to allocate in this rare case
80315        } else if (multMatrix instanceof p5.Matrix) {
80316          _src = multMatrix.mat4;
80317        } else if (isMatrixArray(multMatrix)) {
80318          _src = multMatrix;
80319        } else {
80320          return; // nothing to do.
80321        } // each row is used for the multiplier
80322
80323
80324        var b0 = this.mat4[0],
80325            b1 = this.mat4[1],
80326            b2 = this.mat4[2],
80327            b3 = this.mat4[3];
80328        this.mat4[0] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12];
80329        this.mat4[1] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13];
80330        this.mat4[2] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14];
80331        this.mat4[3] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15];
80332        b0 = this.mat4[4];
80333        b1 = this.mat4[5];
80334        b2 = this.mat4[6];
80335        b3 = this.mat4[7];
80336        this.mat4[4] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12];
80337        this.mat4[5] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13];
80338        this.mat4[6] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14];
80339        this.mat4[7] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15];
80340        b0 = this.mat4[8];
80341        b1 = this.mat4[9];
80342        b2 = this.mat4[10];
80343        b3 = this.mat4[11];
80344        this.mat4[8] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12];
80345        this.mat4[9] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13];
80346        this.mat4[10] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14];
80347        this.mat4[11] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15];
80348        b0 = this.mat4[12];
80349        b1 = this.mat4[13];
80350        b2 = this.mat4[14];
80351        b3 = this.mat4[15];
80352        this.mat4[12] = b0 * _src[0] + b1 * _src[4] + b2 * _src[8] + b3 * _src[12];
80353        this.mat4[13] = b0 * _src[1] + b1 * _src[5] + b2 * _src[9] + b3 * _src[13];
80354        this.mat4[14] = b0 * _src[2] + b1 * _src[6] + b2 * _src[10] + b3 * _src[14];
80355        this.mat4[15] = b0 * _src[3] + b1 * _src[7] + b2 * _src[11] + b3 * _src[15];
80356        return this;
80357      };
80358      /**
80359       * scales a p5.Matrix by scalars or a vector
80360       * @method scale
80361       * @param  {p5.Vector|Float32Array|Number[]} s vector to scale by
80362       * @chainable
80363       */
80364
80365
80366      p5.Matrix.prototype.scale = function (x, y, z) {
80367        if (x instanceof p5.Vector) {
80368          // x is a vector, extract the components from it.
80369          y = x.y;
80370          z = x.z;
80371          x = x.x; // must be last
80372        } else if (x instanceof Array) {
80373          // x is an array, extract the components from it.
80374          y = x[1];
80375          z = x[2];
80376          x = x[0]; // must be last
80377        }
80378
80379        this.mat4[0] *= x;
80380        this.mat4[1] *= x;
80381        this.mat4[2] *= x;
80382        this.mat4[3] *= x;
80383        this.mat4[4] *= y;
80384        this.mat4[5] *= y;
80385        this.mat4[6] *= y;
80386        this.mat4[7] *= y;
80387        this.mat4[8] *= z;
80388        this.mat4[9] *= z;
80389        this.mat4[10] *= z;
80390        this.mat4[11] *= z;
80391        return this;
80392      };
80393      /**
80394       * rotate our Matrix around an axis by the given angle.
80395       * @method rotate
80396       * @param  {Number} a The angle of rotation in radians
80397       * @param  {p5.Vector|Number[]} axis  the axis(es) to rotate around
80398       * @chainable
80399       * inspired by Toji's gl-matrix lib, mat4 rotation
80400       */
80401
80402
80403      p5.Matrix.prototype.rotate = function (a, x, y, z) {
80404        if (x instanceof p5.Vector) {
80405          // x is a vector, extract the components from it.
80406          y = x.y;
80407          z = x.z;
80408          x = x.x; //must be last
80409        } else if (x instanceof Array) {
80410          // x is an array, extract the components from it.
80411          y = x[1];
80412          z = x[2];
80413          x = x[0]; //must be last
80414        }
80415
80416        var len = Math.sqrt(x * x + y * y + z * z);
80417        x *= 1 / len;
80418        y *= 1 / len;
80419        z *= 1 / len;
80420        var a00 = this.mat4[0];
80421        var a01 = this.mat4[1];
80422        var a02 = this.mat4[2];
80423        var a03 = this.mat4[3];
80424        var a10 = this.mat4[4];
80425        var a11 = this.mat4[5];
80426        var a12 = this.mat4[6];
80427        var a13 = this.mat4[7];
80428        var a20 = this.mat4[8];
80429        var a21 = this.mat4[9];
80430        var a22 = this.mat4[10];
80431        var a23 = this.mat4[11]; //sin,cos, and tan of respective angle
80432
80433        var sA = Math.sin(a);
80434        var cA = Math.cos(a);
80435        var tA = 1 - cA; // Construct the elements of the rotation matrix
80436
80437        var b00 = x * x * tA + cA;
80438        var b01 = y * x * tA + z * sA;
80439        var b02 = z * x * tA - y * sA;
80440        var b10 = x * y * tA - z * sA;
80441        var b11 = y * y * tA + cA;
80442        var b12 = z * y * tA + x * sA;
80443        var b20 = x * z * tA + y * sA;
80444        var b21 = y * z * tA - x * sA;
80445        var b22 = z * z * tA + cA; // rotation-specific matrix multiplication
80446
80447        this.mat4[0] = a00 * b00 + a10 * b01 + a20 * b02;
80448        this.mat4[1] = a01 * b00 + a11 * b01 + a21 * b02;
80449        this.mat4[2] = a02 * b00 + a12 * b01 + a22 * b02;
80450        this.mat4[3] = a03 * b00 + a13 * b01 + a23 * b02;
80451        this.mat4[4] = a00 * b10 + a10 * b11 + a20 * b12;
80452        this.mat4[5] = a01 * b10 + a11 * b11 + a21 * b12;
80453        this.mat4[6] = a02 * b10 + a12 * b11 + a22 * b12;
80454        this.mat4[7] = a03 * b10 + a13 * b11 + a23 * b12;
80455        this.mat4[8] = a00 * b20 + a10 * b21 + a20 * b22;
80456        this.mat4[9] = a01 * b20 + a11 * b21 + a21 * b22;
80457        this.mat4[10] = a02 * b20 + a12 * b21 + a22 * b22;
80458        this.mat4[11] = a03 * b20 + a13 * b21 + a23 * b22;
80459        return this;
80460      };
80461      /**
80462       * @todo  finish implementing this method!
80463       * translates
80464       * @method translate
80465       * @param  {Number[]} v vector to translate by
80466       * @chainable
80467       */
80468
80469
80470      p5.Matrix.prototype.translate = function (v) {
80471        var x = v[0],
80472            y = v[1],
80473            z = v[2] || 0;
80474        this.mat4[12] += this.mat4[0] * x + this.mat4[4] * y + this.mat4[8] * z;
80475        this.mat4[13] += this.mat4[1] * x + this.mat4[5] * y + this.mat4[9] * z;
80476        this.mat4[14] += this.mat4[2] * x + this.mat4[6] * y + this.mat4[10] * z;
80477        this.mat4[15] += this.mat4[3] * x + this.mat4[7] * y + this.mat4[11] * z;
80478      };
80479
80480      p5.Matrix.prototype.rotateX = function (a) {
80481        this.rotate(a, 1, 0, 0);
80482      };
80483
80484      p5.Matrix.prototype.rotateY = function (a) {
80485        this.rotate(a, 0, 1, 0);
80486      };
80487
80488      p5.Matrix.prototype.rotateZ = function (a) {
80489        this.rotate(a, 0, 0, 1);
80490      };
80491      /**
80492       * sets the perspective matrix
80493       * @method perspective
80494       * @param  {Number} fovy   [description]
80495       * @param  {Number} aspect [description]
80496       * @param  {Number} near   near clipping plane
80497       * @param  {Number} far    far clipping plane
80498       * @chainable
80499       */
80500
80501
80502      p5.Matrix.prototype.perspective = function (fovy, aspect, near, far) {
80503        var f = 1.0 / Math.tan(fovy / 2),
80504            nf = 1 / (near - far);
80505        this.mat4[0] = f / aspect;
80506        this.mat4[1] = 0;
80507        this.mat4[2] = 0;
80508        this.mat4[3] = 0;
80509        this.mat4[4] = 0;
80510        this.mat4[5] = f;
80511        this.mat4[6] = 0;
80512        this.mat4[7] = 0;
80513        this.mat4[8] = 0;
80514        this.mat4[9] = 0;
80515        this.mat4[10] = (far + near) * nf;
80516        this.mat4[11] = -1;
80517        this.mat4[12] = 0;
80518        this.mat4[13] = 0;
80519        this.mat4[14] = 2 * far * near * nf;
80520        this.mat4[15] = 0;
80521        return this;
80522      };
80523      /**
80524       * sets the ortho matrix
80525       * @method ortho
80526       * @param  {Number} left   [description]
80527       * @param  {Number} right  [description]
80528       * @param  {Number} bottom [description]
80529       * @param  {Number} top    [description]
80530       * @param  {Number} near   near clipping plane
80531       * @param  {Number} far    far clipping plane
80532       * @chainable
80533       */
80534
80535
80536      p5.Matrix.prototype.ortho = function (left, right, bottom, top, near, far) {
80537        var lr = 1 / (left - right),
80538            bt = 1 / (bottom - top),
80539            nf = 1 / (near - far);
80540        this.mat4[0] = -2 * lr;
80541        this.mat4[1] = 0;
80542        this.mat4[2] = 0;
80543        this.mat4[3] = 0;
80544        this.mat4[4] = 0;
80545        this.mat4[5] = -2 * bt;
80546        this.mat4[6] = 0;
80547        this.mat4[7] = 0;
80548        this.mat4[8] = 0;
80549        this.mat4[9] = 0;
80550        this.mat4[10] = 2 * nf;
80551        this.mat4[11] = 0;
80552        this.mat4[12] = (left + right) * lr;
80553        this.mat4[13] = (top + bottom) * bt;
80554        this.mat4[14] = (far + near) * nf;
80555        this.mat4[15] = 1;
80556        return this;
80557      };
80558      /**
80559       * PRIVATE
80560       */
80561      // matrix methods adapted from:
80562      // https://developer.mozilla.org/en-US/docs/Web/WebGL/
80563      // gluPerspective
80564      //
80565      // function _makePerspective(fovy, aspect, znear, zfar){
80566      //    var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
80567      //    var ymin = -ymax;
80568      //    var xmin = ymin * aspect;
80569      //    var xmax = ymax * aspect;
80570      //    return _makeFrustum(xmin, xmax, ymin, ymax, znear, zfar);
80571      //  }
80572      ////
80573      //// glFrustum
80574      ////
80575      //function _makeFrustum(left, right, bottom, top, znear, zfar){
80576      //  var X = 2*znear/(right-left);
80577      //  var Y = 2*znear/(top-bottom);
80578      //  var A = (right+left)/(right-left);
80579      //  var B = (top+bottom)/(top-bottom);
80580      //  var C = -(zfar+znear)/(zfar-znear);
80581      //  var D = -2*zfar*znear/(zfar-znear);
80582      //  var frustrumMatrix =[
80583      //  X, 0, A, 0,
80584      //  0, Y, B, 0,
80585      //  0, 0, C, D,
80586      //  0, 0, -1, 0
80587      //];
80588      //return frustrumMatrix;
80589      // }
80590      // function _setMVPMatrices(){
80591      ////an identity matrix
80592      ////@TODO use the p5.Matrix class to abstract away our MV matrices and
80593      ///other math
80594      //var _mvMatrix =
80595      //[
80596      //  1.0,0.0,0.0,0.0,
80597      //  0.0,1.0,0.0,0.0,
80598      //  0.0,0.0,1.0,0.0,
80599      //  0.0,0.0,0.0,1.0
80600      //];
80601
80602
80603      module.exports = p5.Matrix;
80604    }, {
80605      "../core/main": 24
80606    }],
80607    72: [function (_dereq_, module, exports) {
80608      /**
80609       * Welcome to RendererGL Immediate Mode.
80610       * Immediate mode is used for drawing custom shapes
80611       * from a set of vertices.  Immediate Mode is activated
80612       * when you call <a href="#/p5/beginShape">beginShape()</a> & de-activated when you call <a href="#/p5/endShape">endShape()</a>.
80613       * Immediate mode is a style of programming borrowed
80614       * from OpenGL's (now-deprecated) immediate mode.
80615       * It differs from p5.js' default, Retained Mode, which caches
80616       * geometries and buffers on the CPU to reduce the number of webgl
80617       * draw calls. Retained mode is more efficient & performative,
80618       * however, Immediate Mode is useful for sketching quick
80619       * geometric ideas.
80620       */
80621      'use strict';
80622
80623      var p5 = _dereq_('../core/main');
80624
80625      var constants = _dereq_('../core/constants');
80626      /**
80627       * Begin shape drawing.  This is a helpful way of generating
80628       * custom shapes quickly.  However in WEBGL mode, application
80629       * performance will likely drop as a result of too many calls to
80630       * <a href="#/p5/beginShape">beginShape()</a> / <a href="#/p5/endShape">endShape()</a>.  As a high performance alternative,
80631       * please use p5.js geometry primitives.
80632       * @private
80633       * @method beginShape
80634       * @param  {Number} mode webgl primitives mode.  beginShape supports the
80635       *                       following modes:
80636       *                       POINTS,LINES,LINE_STRIP,LINE_LOOP,TRIANGLES,
80637       *                       TRIANGLE_STRIP,and TRIANGLE_FAN.
80638       * @chainable
80639       */
80640
80641
80642      p5.RendererGL.prototype.beginShape = function (mode) {
80643        //default shape mode is line_strip
80644        this.immediateMode.shapeMode = mode !== undefined ? mode : constants.LINE_STRIP; //if we haven't yet initialized our
80645        //immediateMode vertices & buffers, create them now!
80646
80647        if (this.immediateMode.vertices === undefined) {
80648          this.immediateMode.vertices = [];
80649          this.immediateMode.edges = [];
80650          this.immediateMode.lineVertices = [];
80651          this.immediateMode.vertexColors = [];
80652          this.immediateMode.lineNormals = [];
80653          this.immediateMode.uvCoords = [];
80654          this.immediateMode.vertexBuffer = this.GL.createBuffer();
80655          this.immediateMode.colorBuffer = this.GL.createBuffer();
80656          this.immediateMode.uvBuffer = this.GL.createBuffer();
80657          this.immediateMode.lineVertexBuffer = this.GL.createBuffer();
80658          this.immediateMode.lineNormalBuffer = this.GL.createBuffer();
80659          this.immediateMode.pointVertexBuffer = this.GL.createBuffer();
80660          this.immediateMode._bezierVertex = [];
80661          this.immediateMode._quadraticVertex = [];
80662          this.immediateMode._curveVertex = [];
80663        } else {
80664          this.immediateMode.vertices.length = 0;
80665          this.immediateMode.edges.length = 0;
80666          this.immediateMode.lineVertices.length = 0;
80667          this.immediateMode.lineNormals.length = 0;
80668          this.immediateMode.vertexColors.length = 0;
80669          this.immediateMode.uvCoords.length = 0;
80670        }
80671
80672        this.isImmediateDrawing = true;
80673        return this;
80674      };
80675      /**
80676       * adds a vertex to be drawn in a custom Shape.
80677       * @private
80678       * @method vertex
80679       * @param  {Number} x x-coordinate of vertex
80680       * @param  {Number} y y-coordinate of vertex
80681       * @param  {Number} z z-coordinate of vertex
80682       * @chainable
80683       * @TODO implement handling of <a href="#/p5.Vector">p5.Vector</a> args
80684       */
80685
80686
80687      p5.RendererGL.prototype.vertex = function (x, y) {
80688        var z, u, v; // default to (x, y) mode: all other arugments assumed to be 0.
80689
80690        z = u = v = 0;
80691
80692        if (arguments.length === 3) {
80693          // (x, y, z) mode: (u, v) assumed to be 0.
80694          z = arguments[2];
80695        } else if (arguments.length === 4) {
80696          // (x, y, u, v) mode: z assumed to be 0.
80697          u = arguments[2];
80698          v = arguments[3];
80699        } else if (arguments.length === 5) {
80700          // (x, y, z, u, v) mode
80701          z = arguments[2];
80702          u = arguments[3];
80703          v = arguments[4];
80704        }
80705
80706        var vert = new p5.Vector(x, y, z);
80707        this.immediateMode.vertices.push(vert);
80708        var vertexColor = this.curFillColor || [0.5, 0.5, 0.5, 1.0];
80709        this.immediateMode.vertexColors.push(vertexColor[0], vertexColor[1], vertexColor[2], vertexColor[3]);
80710
80711        if (this.textureMode === constants.IMAGE) {
80712          if (this.textureImage !== undefined) {
80713            if (this.textureImage.width > 0 && this.textureImage.height > 0) {
80714              u /= this.textureImage.width;
80715              v /= this.textureImage.height;
80716            }
80717          } else {
80718            console.warn('You must first call texture() before using' + ' vertex() with image based u and v coordinates');
80719          }
80720        }
80721
80722        this.immediateMode.uvCoords.push(u, v);
80723        this.immediateMode._bezierVertex[0] = x;
80724        this.immediateMode._bezierVertex[1] = y;
80725        this.immediateMode._bezierVertex[2] = z;
80726        this.immediateMode._quadraticVertex[0] = x;
80727        this.immediateMode._quadraticVertex[1] = y;
80728        this.immediateMode._quadraticVertex[2] = z;
80729        return this;
80730      };
80731      /**
80732       * End shape drawing and render vertices to screen.
80733       * @chainable
80734       */
80735
80736
80737      p5.RendererGL.prototype.endShape = function (mode, isCurve, isBezier, isQuadratic, isContour, shapeKind) {
80738        if (this.immediateMode.shapeMode === constants.POINTS) {
80739          this._usePointShader();
80740
80741          this.curPointShader.bindShader();
80742
80743          this._drawPoints(this.immediateMode.vertices, this.immediateMode.pointVertexBuffer);
80744
80745          this.curPointShader.unbindShader();
80746        } else if (this.immediateMode.vertices.length > 1) {
80747          this._useImmediateModeShader();
80748
80749          if (this._doStroke && this.drawMode !== constants.TEXTURE) {
80750            if (this.immediateMode.shapeMode === constants.TRIANGLE_STRIP) {
80751              var i;
80752
80753              for (i = 0; i < this.immediateMode.vertices.length - 2; i++) {
80754                this.immediateMode.edges.push([i, i + 1]);
80755                this.immediateMode.edges.push([i, i + 2]);
80756              }
80757
80758              this.immediateMode.edges.push([i, i + 1]);
80759            } else if (this.immediateMode.shapeMode === constants.TRIANGLES) {
80760              for (i = 0; i < this.immediateMode.vertices.length - 2; i = i + 3) {
80761                this.immediateMode.edges.push([i, i + 1]);
80762                this.immediateMode.edges.push([i + 1, i + 2]);
80763                this.immediateMode.edges.push([i + 2, i]);
80764              }
80765            } else {
80766              for (i = 0; i < this.immediateMode.vertices.length - 1; i++) {
80767                this.immediateMode.edges.push([i, i + 1]);
80768              }
80769            }
80770
80771            if (mode === constants.CLOSE) {
80772              this.immediateMode.edges.push([this.immediateMode.vertices.length - 1, 0]);
80773            }
80774
80775            p5.Geometry.prototype._edgesToVertices.call(this.immediateMode);
80776
80777            this._drawStrokeImmediateMode();
80778          }
80779
80780          if (this._doFill) {
80781            if (this.isBezier || this.isQuadratic || this.isCurve) {
80782              var contours = [new Float32Array(this._vToNArray(this.immediateMode.vertices))];
80783
80784              var polyTriangles = this._triangulate(contours);
80785
80786              this.immediateMode.vertices = [];
80787
80788              for (var j = 0, polyTriLength = polyTriangles.length; j < polyTriLength; j = j + 3) {
80789                this.vertex(polyTriangles[j], polyTriangles[j + 1], polyTriangles[j + 2]);
80790              }
80791            }
80792
80793            this._drawFillImmediateMode(mode, isCurve, isBezier, isQuadratic, isContour, shapeKind);
80794          }
80795        } //clear out our vertexPositions & colors arrays
80796        //after rendering
80797
80798
80799        this.immediateMode.vertices.length = 0;
80800        this.immediateMode.vertexColors.length = 0;
80801        this.immediateMode.uvCoords.length = 0;
80802        this.isImmediateDrawing = false;
80803        this.isBezier = false;
80804        this.isQuadratic = false;
80805        this.isCurve = false;
80806        this.immediateMode._bezierVertex.length = 0;
80807        this.immediateMode._quadraticVertex.length = 0;
80808        this.immediateMode._curveVertex.length = 0;
80809        return this;
80810      };
80811
80812      p5.RendererGL.prototype._drawFillImmediateMode = function (mode, isCurve, isBezier, isQuadratic, isContour, shapeKind) {
80813        var gl = this.GL;
80814        this.curFillShader.bindShader(); // initialize the fill shader's 'aPosition' buffer
80815
80816        if (this.curFillShader.attributes.aPosition) {
80817          //vertex position Attribute
80818          this._bindBuffer(this.immediateMode.vertexBuffer, gl.ARRAY_BUFFER, this._vToNArray(this.immediateMode.vertices), Float32Array, gl.DYNAMIC_DRAW);
80819
80820          this.curFillShader.enableAttrib(this.curFillShader.attributes.aPosition.location, 3, gl.FLOAT, false, 0, 0);
80821        } // initialize the fill shader's 'aVertexColor' buffer
80822
80823
80824        if (this.drawMode === constants.FILL && this.curFillShader.attributes.aVertexColor) {
80825          this._bindBuffer(this.immediateMode.colorBuffer, gl.ARRAY_BUFFER, this.immediateMode.vertexColors, Float32Array, gl.DYNAMIC_DRAW);
80826
80827          this.curFillShader.enableAttrib(this.curFillShader.attributes.aVertexColor.location, 4, gl.FLOAT, false, 0, 0);
80828        } // initialize the fill shader's 'aTexCoord' buffer
80829
80830
80831        if (this.drawMode === constants.TEXTURE && this.curFillShader.attributes.aTexCoord) {
80832          //texture coordinate Attribute
80833          this._bindBuffer(this.immediateMode.uvBuffer, gl.ARRAY_BUFFER, this.immediateMode.uvCoords, Float32Array, gl.DYNAMIC_DRAW);
80834
80835          this.curFillShader.enableAttrib(this.curFillShader.attributes.aTexCoord.location, 2, gl.FLOAT, false, 0, 0);
80836        } //if (true || mode) {
80837
80838
80839        if (this.drawMode === constants.FILL || this.drawMode === constants.TEXTURE) {
80840          switch (this.immediateMode.shapeMode) {
80841            case constants.LINE_STRIP:
80842            case constants.LINES:
80843            case constants.TRIANGLES:
80844              this.immediateMode.shapeMode = this.isBezier || this.isQuadratic || this.isCurve || this.immediateMode.shapeMode === constants.TRIANGLES ? constants.TRIANGLES : constants.TRIANGLE_FAN;
80845              break;
80846          }
80847        } else {
80848          switch (this.immediateMode.shapeMode) {
80849            case constants.LINE_STRIP:
80850            case constants.LINES:
80851              this.immediateMode.shapeMode = constants.LINE_LOOP;
80852              break;
80853          }
80854        } //}
80855        //QUADS & QUAD_STRIP are not supported primitives modes
80856        //in webgl.
80857
80858
80859        if (this.immediateMode.shapeMode === constants.QUADS || this.immediateMode.shapeMode === constants.QUAD_STRIP) {
80860          throw new Error('sorry, ' + this.immediateMode.shapeMode + ' not yet implemented in webgl mode.');
80861        } else {
80862          this._applyColorBlend(this.curFillColor);
80863
80864          gl.enable(gl.BLEND);
80865          gl.drawArrays(this.immediateMode.shapeMode, 0, this.immediateMode.vertices.length);
80866          this._pInst._pixelsDirty = true;
80867        } // todo / optimizations? leave bound until another shader is set?
80868
80869
80870        this.curFillShader.unbindShader();
80871      };
80872
80873      p5.RendererGL.prototype._drawStrokeImmediateMode = function () {
80874        var gl = this.GL;
80875        this.curStrokeShader.bindShader(); // initialize the stroke shader's 'aPosition' buffer
80876
80877        if (this.curStrokeShader.attributes.aPosition) {
80878          this._bindBuffer(this.immediateMode.lineVertexBuffer, gl.ARRAY_BUFFER, this._flatten(this.immediateMode.lineVertices), Float32Array, gl.STATIC_DRAW);
80879
80880          this.curStrokeShader.enableAttrib(this.curStrokeShader.attributes.aPosition.location, 3, gl.FLOAT, false, 0, 0);
80881        } // initialize the stroke shader's 'aDirection' buffer
80882
80883
80884        if (this.curStrokeShader.attributes.aDirection) {
80885          this._bindBuffer(this.immediateMode.lineNormalBuffer, gl.ARRAY_BUFFER, this._flatten(this.immediateMode.lineNormals), Float32Array, gl.STATIC_DRAW);
80886
80887          this.curStrokeShader.enableAttrib(this.curStrokeShader.attributes.aDirection.location, 4, gl.FLOAT, false, 0, 0);
80888        }
80889
80890        this._applyColorBlend(this.curStrokeColor);
80891
80892        gl.drawArrays(gl.TRIANGLES, 0, this.immediateMode.lineVertices.length); // todo / optimizations? leave bound until another shader is set?
80893
80894        this.curStrokeShader.unbindShader();
80895        this._pInst._pixelsDirty = true;
80896      };
80897
80898      module.exports = p5.RendererGL;
80899    }, {
80900      "../core/constants": 18,
80901      "../core/main": 24
80902    }],
80903    73: [function (_dereq_, module, exports) {
80904      //Retained Mode. The default mode for rendering 3D primitives
80905      //in WEBGL.
80906      'use strict';
80907
80908      var p5 = _dereq_('../core/main');
80909
80910      var hashCount = 0;
80911      /**
80912       * _initBufferDefaults
80913       * @private
80914       * @description initializes buffer defaults. runs each time a new geometry is
80915       * registered
80916       * @param  {String} gId  key of the geometry object
80917       */
80918
80919      p5.RendererGL.prototype._initBufferDefaults = function (gId) {
80920        this._freeBuffers(gId); //@TODO remove this limit on hashes in gHash
80921
80922
80923        hashCount++;
80924
80925        if (hashCount > 1000) {
80926          var key = Object.keys(this.gHash)[0];
80927          delete this.gHash[key];
80928          hashCount--;
80929        } //create a new entry in our gHash
80930
80931
80932        this.gHash[gId] = {};
80933      };
80934
80935      p5.RendererGL.prototype._freeBuffers = function (gId) {
80936        var geometry = this.gHash[gId];
80937
80938        if (!geometry) {
80939          return;
80940        }
80941
80942        delete this.gHash[gId];
80943        hashCount--;
80944        var gl = this.GL;
80945        geometry.vertexBuffer && gl.deleteBuffer(geometry.vertexBuffer);
80946        geometry.normalBuffer && gl.deleteBuffer(geometry.normalBuffer);
80947        geometry.lineNormalBuffer && gl.deleteBuffer(geometry.lineNormalBuffer);
80948        geometry.uvBuffer && gl.deleteBuffer(geometry.uvBuffer);
80949        geometry.indexBuffer && gl.deleteBuffer(geometry.indexBuffer);
80950        geometry.lineVertexBuffer && gl.deleteBuffer(geometry.lineVertexBuffer);
80951      };
80952      /**
80953       * createBuffers description
80954       * @private
80955       * @param  {String} gId    key of the geometry object
80956       * @param  {p5.Geometry}  obj contains geometry data
80957       */
80958
80959
80960      p5.RendererGL.prototype.createBuffers = function (gId, obj) {
80961        var gl = this.GL; //initialize the gl buffers for our geom groups
80962
80963        this._initBufferDefaults(gId);
80964
80965        var geometry = this.gHash[gId];
80966        geometry.numberOfItems = obj.faces.length * 3;
80967        geometry.lineVertexCount = obj.lineVertices.length;
80968
80969        this._useColorShader(); // initialize the stroke shader's 'aPosition' buffer, if used
80970
80971
80972        if (this.curStrokeShader.attributes.aPosition) {
80973          geometry.lineVertexBuffer = gl.createBuffer();
80974
80975          this._bindBuffer(geometry.lineVertexBuffer, gl.ARRAY_BUFFER, this._flatten(obj.lineVertices), Float32Array, gl.STATIC_DRAW);
80976
80977          this.curStrokeShader.enableAttrib(this.curStrokeShader.attributes.aPosition.location, 3, gl.FLOAT, false, 0, 0);
80978        } // initialize the stroke shader's 'aDirection' buffer, if used
80979
80980
80981        if (this.curStrokeShader.attributes.aDirection) {
80982          geometry.lineNormalBuffer = gl.createBuffer();
80983
80984          this._bindBuffer(geometry.lineNormalBuffer, gl.ARRAY_BUFFER, this._flatten(obj.lineNormals), Float32Array, gl.STATIC_DRAW);
80985
80986          this.curStrokeShader.enableAttrib(this.curStrokeShader.attributes.aDirection.location, 4, gl.FLOAT, false, 0, 0);
80987        } // initialize the fill shader's 'aPosition' buffer, if used
80988
80989
80990        if (this.curFillShader.attributes.aPosition) {
80991          geometry.vertexBuffer = gl.createBuffer(); // allocate space for vertex positions
80992
80993          this._bindBuffer(geometry.vertexBuffer, gl.ARRAY_BUFFER, this._vToNArray(obj.vertices), Float32Array, gl.STATIC_DRAW);
80994
80995          this.curFillShader.enableAttrib(this.curFillShader.attributes.aPosition.location, 3, gl.FLOAT, false, 0, 0);
80996        } // allocate space for faces
80997
80998
80999        geometry.indexBuffer = gl.createBuffer();
81000
81001        this._bindBuffer(geometry.indexBuffer, gl.ELEMENT_ARRAY_BUFFER, this._flatten(obj.faces), Uint16Array, gl.STATIC_DRAW); // initialize the fill shader's 'aNormal' buffer, if used
81002
81003
81004        if (this.curFillShader.attributes.aNormal) {
81005          geometry.normalBuffer = gl.createBuffer(); // allocate space for normals
81006
81007          this._bindBuffer(geometry.normalBuffer, gl.ARRAY_BUFFER, this._vToNArray(obj.vertexNormals), Float32Array, gl.STATIC_DRAW);
81008
81009          this.curFillShader.enableAttrib(this.curFillShader.attributes.aNormal.location, 3, gl.FLOAT, false, 0, 0);
81010        } // initialize the fill shader's 'aTexCoord' buffer, if used
81011
81012
81013        if (this.curFillShader.attributes.aTexCoord) {
81014          geometry.uvBuffer = gl.createBuffer(); // tex coords
81015
81016          this._bindBuffer(geometry.uvBuffer, gl.ARRAY_BUFFER, this._flatten(obj.uvs), Float32Array, gl.STATIC_DRAW);
81017
81018          this.curFillShader.enableAttrib(this.curFillShader.attributes.aTexCoord.location, 2, gl.FLOAT, false, 0, 0);
81019        } //}
81020
81021
81022        return geometry;
81023      };
81024      /**
81025       * Draws buffers given a geometry key ID
81026       * @private
81027       * @param  {String} gId     ID in our geom hash
81028       * @chainable
81029       */
81030
81031
81032      p5.RendererGL.prototype.drawBuffers = function (gId) {
81033        var gl = this.GL;
81034
81035        this._useColorShader();
81036
81037        var geometry = this.gHash[gId];
81038
81039        if (this._doStroke && geometry.lineVertexCount > 0) {
81040          this.curStrokeShader.bindShader(); // bind the stroke shader's 'aPosition' buffer
81041
81042          if (geometry.lineVertexBuffer) {
81043            this._bindBuffer(geometry.lineVertexBuffer, gl.ARRAY_BUFFER);
81044
81045            this.curStrokeShader.enableAttrib(this.curStrokeShader.attributes.aPosition.location, 3, gl.FLOAT, false, 0, 0);
81046          } // bind the stroke shader's 'aDirection' buffer
81047
81048
81049          if (geometry.lineNormalBuffer) {
81050            this._bindBuffer(geometry.lineNormalBuffer, gl.ARRAY_BUFFER);
81051
81052            this.curStrokeShader.enableAttrib(this.curStrokeShader.attributes.aDirection.location, 4, gl.FLOAT, false, 0, 0);
81053          }
81054
81055          this._applyColorBlend(this.curStrokeColor);
81056
81057          this._drawArrays(gl.TRIANGLES, gId);
81058
81059          this.curStrokeShader.unbindShader();
81060        }
81061
81062        if (this._doFill !== false) {
81063          this.curFillShader.bindShader(); // bind the fill shader's 'aPosition' buffer
81064
81065          if (geometry.vertexBuffer) {
81066            //vertex position buffer
81067            this._bindBuffer(geometry.vertexBuffer, gl.ARRAY_BUFFER);
81068
81069            this.curFillShader.enableAttrib(this.curFillShader.attributes.aPosition.location, 3, gl.FLOAT, false, 0, 0);
81070          }
81071
81072          if (geometry.indexBuffer) {
81073            //vertex index buffer
81074            this._bindBuffer(geometry.indexBuffer, gl.ELEMENT_ARRAY_BUFFER);
81075          } // bind the fill shader's 'aNormal' buffer
81076
81077
81078          if (geometry.normalBuffer) {
81079            this._bindBuffer(geometry.normalBuffer, gl.ARRAY_BUFFER);
81080
81081            this.curFillShader.enableAttrib(this.curFillShader.attributes.aNormal.location, 3, gl.FLOAT, false, 0, 0);
81082          } // bind the fill shader's 'aTexCoord' buffer
81083
81084
81085          if (geometry.uvBuffer) {
81086            // uv buffer
81087            this._bindBuffer(geometry.uvBuffer, gl.ARRAY_BUFFER);
81088
81089            this.curFillShader.enableAttrib(this.curFillShader.attributes.aTexCoord.location, 2, gl.FLOAT, false, 0, 0);
81090          }
81091
81092          this._applyColorBlend(this.curFillColor);
81093
81094          this._drawElements(gl.TRIANGLES, gId);
81095
81096          this.curFillShader.unbindShader();
81097        }
81098
81099        return this;
81100      };
81101      /**
81102       * Calls drawBuffers() with a scaled model/view matrix.
81103       *
81104       * This is used by various 3d primitive methods (in primitives.js, eg. plane,
81105       * box, torus, etc...) to allow caching of un-scaled geometries. Those
81106       * geometries are generally created with unit-length dimensions, cached as
81107       * such, and then scaled appropriately in this method prior to rendering.
81108       *
81109       * @private
81110       * @method drawBuffersScaled
81111       * @param {String} gId     ID in our geom hash
81112       * @param {Number} scaleX  the amount to scale in the X direction
81113       * @param {Number} scaleY  the amount to scale in the Y direction
81114       * @param {Number} scaleZ  the amount to scale in the Z direction
81115       */
81116
81117
81118      p5.RendererGL.prototype.drawBuffersScaled = function (gId, scaleX, scaleY, scaleZ) {
81119        var uMVMatrix = this.uMVMatrix.copy();
81120
81121        try {
81122          this.uMVMatrix.scale(scaleX, scaleY, scaleZ);
81123          this.drawBuffers(gId);
81124        } finally {
81125          this.uMVMatrix = uMVMatrix;
81126        }
81127      };
81128
81129      p5.RendererGL.prototype._drawArrays = function (drawMode, gId) {
81130        this.GL.drawArrays(drawMode, 0, this.gHash[gId].lineVertexCount);
81131        this._pInst._pixelsDirty = true;
81132        return this;
81133      };
81134
81135      p5.RendererGL.prototype._drawElements = function (drawMode, gId) {
81136        this.GL.drawElements(drawMode, this.gHash[gId].numberOfItems, this.GL.UNSIGNED_SHORT, 0);
81137        this._pInst._pixelsDirty = true;
81138      };
81139
81140      p5.RendererGL.prototype._drawPoints = function (vertices, vertexBuffer) {
81141        var gl = this.GL;
81142
81143        this._bindBuffer(vertexBuffer, gl.ARRAY_BUFFER, this._vToNArray(vertices), Float32Array, gl.STATIC_DRAW);
81144
81145        this.curPointShader.enableAttrib(this.curPointShader.attributes.aPosition.location, 3, gl.FLOAT, false, 0, 0);
81146        gl.drawArrays(gl.Points, 0, vertices.length);
81147      };
81148
81149      module.exports = p5.RendererGL;
81150    }, {
81151      "../core/main": 24
81152    }],
81153    74: [function (_dereq_, module, exports) {
81154      'use strict';
81155
81156      var p5 = _dereq_('../core/main');
81157
81158      var constants = _dereq_('../core/constants');
81159
81160      var libtess = _dereq_('libtess');
81161
81162      _dereq_('./p5.Shader');
81163
81164      _dereq_('./p5.Camera');
81165
81166      _dereq_('../core/p5.Renderer');
81167
81168      _dereq_('./p5.Matrix');
81169
81170      var defaultShaders = {
81171        immediateVert: "attribute vec3 aPosition;\nattribute vec4 aVertexColor;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uResolution;\nuniform float uPointSize;\n\nvarying vec4 vColor;\nvoid main(void) {\n  vec4 positionVec4 = vec4(aPosition, 1.0);\n  gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n  vColor = aVertexColor;\n  gl_PointSize = uPointSize;\n}\n",
81172        vertexColorVert: "attribute vec3 aPosition;\nattribute vec4 aVertexColor;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\n\nvarying vec4 vColor;\n\nvoid main(void) {\n  vec4 positionVec4 = vec4(aPosition, 1.0
81172);\n  gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n  vColor = aVertexColor;\n}\n",
81173        vertexColorFrag: "precision mediump float;\nvarying vec4 vColor;\nvoid main(void) {\n  gl_FragColor = vColor;\n}",
81174        normalVert: "attribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\n\nvarying vec3 vVertexNormal;\nvarying highp vec2 vVertTexCoord;\n\nvoid main(void) {\n  vec4 positionVec4 = vec4(aPosition, 1.0);\n  gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n  vVertexNormal = normalize(vec3( uNormalMatrix * aNormal ));\n  vVertTexCoord = aTexCoord;\n}\n",
81175        normalFrag: "precision mediump float;\nvarying vec3 vVertexNormal;\nvoid main(void) {\n  gl_FragColor = vec4(vVertexNormal, 1.0);\n}",
81176        basicFrag: "precision mediump float;\nvarying vec3 vVertexNormal;\nuniform vec4 uMaterialColor;\nvoid main(void) {\n  gl_FragColor = uMaterialColor;\n}",
81177        lightVert: "attribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nuniform mat4 uViewMatrix;\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\nuniform int uAmbientLightCount;\nuniform int uDirectionalLightCount;\nuniform int uPointLightCount;\n\nuniform vec3 uAmbientColor[8];\nuniform vec3 uLightingDirection[8];\nuniform vec3 uDirectionalColor[8];\nuniform vec3 uPointLightLocation[8];\nuniform vec3 uPointLightColor[8];\nuniform bool uSpecular;\n\nvarying vec3 vVertexNormal;\nvarying vec2 vVertTexCoord;\nvarying vec3 vLightWeighting;\n\nvoid main(void){\n\n  vec4 positionVec4 = vec4(aPosition, 1.0
81177);\n  gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n\n  vec3 vertexNormal = normalize(vec3( uNormalMatrix * aNormal ));\n  vVertexNormal = vertexNormal;\n  vVertTexCoord = aTexCoord;\n\n  vec4 mvPosition = uModelViewMatrix * vec4(aPosition, 1.0);\n  vec3 eyeDirection = normalize(-mvPosition.xyz);\n\n  float shininess = 32.0;\n  float specularFactor = 2.0;\n  float diffuseFactor = 0.3;\n\n  vec3 ambientLightFactor = vec3(0.0);\n\n  for (int i = 0; i < 8; i++) {\n    if (uAmbientLightCount == i) break;\n    ambientLightFactor += uAmbientColor[i];\n  }\n\n\n  vec3 directionalLightFactor = vec3(0.0);\n\n  for (int j = 0; j < 8; j++) {\n    if (uDirectionalLightCount == j) break;\n    vec3 dir = uLightingDirection[j];\n    float directionalLightWeighting = max(dot(vertexNormal, -dir), 0.0);\n    directionalLightFactor += uDirectionalColor[j] * directionalLightWeighting;\n  }\n\n\n  vec3 pointLightFactor = vec3(0.0);\n\n  for (int k = 0; k < 8; k++) {\n    if (uPointLightCount == k) break;\n    vec3 loc = (uViewMatrix * vec4(uPointLightLocation[k], 1.0)).xyz;\n    vec3 lightDirection = normalize(loc - mvPosition.xyz);\n\n    float directionalLightWeighting = max(dot(vertexNormal, lightDirection), 0.0);\n\n    float specularLightWeighting = 0.0;\n    if (uSpecular ){\n      vec3 reflectionDirection = reflect(-lightDirection, vertexNormal);\n      specularLightWeighting = pow(max(dot(reflectionDirection, eyeDirection), 0.0), shininess);\n    }\n\n    pointLightFactor += uPointLightColor[k] * (specularFactor * specularLightWeighting\n      + directionalLightWeighting * diffuseFactor);\n  }\n\n  vLightWeighting =  ambientLightFactor + directionalLightFactor + pointLightFactor;\n}\n",
81178        lightTextureFrag: "precision mediump float;\n\nuniform vec4 uMaterialColor;\nuniform sampler2D uSampler;\nuniform bool isTexture;\nuniform bool uUseLighting;\n\nvarying vec3 vLightWeighting;\nvarying highp vec2 vVertTexCoord;\n\nvoid main(void) {\n  gl_FragColor = isTexture ? texture2D(uSampler, vVertTexCoord) : uMaterialColor;\n  if (uUseLighting)\n    gl_FragColor.rgb *= vLightWeighting;\n}",
81179        phongVert: "precision mediump float;\n\nattribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nuniform vec3 uAmbientColor[8];\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\nuniform int uAmbientLightCount;\n\nvarying vec3 vNormal;\nvarying vec2 vTexCoord;\nvarying vec3 vViewPosition;\nvarying vec3 vAmbientColor;\n\nvoid main(void){\n\n  vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0
81179);\n\n  // Pass varyings to fragment shader\n  vViewPosition = viewModelPosition.xyz;\n  gl_Position = uProjectionMatrix * viewModelPosition;  \n\n  vNormal = normalize(uNormalMatrix * normalize(aNormal));\n  vTexCoord = aTexCoord;\n\n  vAmbientColor = vec3(0.0);\n  for (int i = 0; i < 8; i++) {\n    if (uAmbientLightCount == i) break;\n    vAmbientColor += uAmbientColor[i];\n  }\n}\n",
81180        phongFrag: "precision mediump float;\n\n//uniform mat4 uModelViewMatrix;\nuniform mat4 uViewMatrix;\n\nuniform vec4 uMaterialColor;\nuniform sampler2D uSampler;\nuniform bool isTexture;\nuniform bool uUseLighting;\n\nuniform vec3 uLightingDirection[8];\nuniform vec3 uDirectionalColor[8];\nuniform vec3 uPointLightLocation[8];\nuniform vec3 uPointLightColor[8];\nuniform bool uSpecular;\n\nuniform int uDirectionalLightCount;\nuniform int uPointLightCount;\n\nvarying vec3 vNormal;\nvarying vec2 vTexCoord;\nvarying vec3 vViewPosition;\nvarying vec3 vAmbientColor;\n\nvec3 V;\nvec3 N;\n\nconst float shininess = 32.0;\nconst float specularFactor = 2.0;\nconst float diffuseFactor = 0.73;\n\nstruct LightResult {\n\tfloat specular;\n\tfloat diffuse;\n};\n\nfloat phongSpecular(\n  vec3 lightDirection,\n  vec3 viewDirection,\n  vec3 surfaceNormal,\n  float shininess) {\n\n  vec3 R = normalize(reflect(-lightDirection, surfaceNormal));  \n  return pow(max(0.0, dot(R, viewDirection)), shininess);\n}\n\nfloat lambertDiffuse(\n  vec3 lightDirection,\n  vec3 surfaceNormal) {\n  return max(0.0, dot(-lightDirection, surfaceNormal));\n}\n\nLightResult light(vec3 lightVector) {\n\n  vec3 L = normalize(lightVector);\n\n  //compute our diffuse & specular terms\n  LightResult lr;\n  if (uSpecular)\n    lr.specular = phongSpecular(L, V, N, shininess);\n  lr.diffuse = lambertDiffuse(L, N);\n  return lr;\n}\n\nvoid main(void) {\n\n  V = normalize(vViewPosition);\n  N = vNormal;\n\n  vec3 diffuse = vec3(0.0);\n  float specular = 0.0;\n\n  for (int j = 0; j < 8; j++) {\n    if (uDirectionalLightCount == j) break;\n\n    LightResult result = light(uLightingDirection[j]);\n    diffuse += result.diffuse * uDirectionalColor[j];\n    specular += result.specular;\n  }\n\n  for (int k = 0; k < 8; k++) {\n    if (uPointLightCount == k) break;\n\n    vec3 lightPosition = (uViewMatrix * vec4(uPointLightLocation[k], 1.0)).xyz;\n    vec3 lightVector = vViewPosition - lightPosition;\n\t\n    //calculate attenuation\n    float lightDistance = length(lightVector);\n    float falloff = 500.0 / (lightDistance + 500.0);\n\n    LightResult result = light(lightVector);\n    diffuse += result.diffuse * falloff * uPointLightColor[k];\n    specular += result.specular * falloff;\n  }\n\n  gl_FragColor = isTexture ? texture2D(uSampler, vTexCoord) : uMaterialColor;\n  gl_FragColor.rgb = gl_FragColor.rgb * (diffuse * diffuseFactor + vAmbientColor) + specular * specularFactor;\n}",
81181        fontVert: "precision mediump float;\n\nattribute vec3 aPosition;\nattribute vec2 aTexCoord;\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\n\nuniform vec4 uGlyphRect;\nuniform float uGlyphOffset;\n\nvarying vec2 vTexCoord;\nvarying float w;
81181\n\nvoid main() {\n  vec4 positionVec4 = vec4(aPosition, 1.0);\n\n  // scale by the size of the glyph's rectangle\n  positionVec4.xy *= uGlyphRect.zw - uGlyphRect.xy;\n\n  // move to the corner of the glyph\n  positionVec4.xy += uGlyphRect.xy;\n\n  // move to the letter's line offset\n  positionVec4.x += uGlyphOffset;\n  \n  gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n  vTexCoord = aTexCoord;\n  w = gl_Position.w;\n}\n",
81182        fontFrag: "#extension GL_OES_standard_derivatives : enable\nprecision mediump float;\n\n#if 0\n  // simulate integer math using floats\n\t#define int float\n\t#define ivec2 vec2\n\t#define INT(x) float(x)\n\n\tint ifloor(float v) { return floor(v); }\n\tivec2 ifloor(vec2 v) { return floor(v); }\n\n#else\n  // use native integer math\n\tprecision mediump int;\n\t#define INT(x) x\n\n\tint ifloor(float v) { return int(v); }\n\tint ifloor(int v) { return v; }\n\tivec2 ifloor(vec2 v) { return ivec2(v); }\n\n#endif\n\nuniform sampler2D uSamplerStrokes;\nuniform sampler2D uSamplerRowStrokes;\nuniform sampler2D uSamplerRows;\nuniform sampler2D uSamplerColStrokes;\nuniform sampler2D uSamplerCols;\n\nuniform ivec2 uStrokeImageSize;\nuniform ivec2 uCellsImageSize;\nuniform ivec2 uGridImageSize;\n\nuniform ivec2 uGridOffset;\nuniform ivec2 uGridSize;\nuniform vec4 uMaterialColor;\n\nvarying vec2 vTexCoord;\n\n// some helper functions\nint round(float v) { return ifloor(v + 0.5); }\nivec2 round(vec2 v) { return ifloor(v + 0.5); }\nfloat saturate(float v) { return clamp(v, 0.0, 1.0); }\nvec2 saturate(vec2 v) { return clamp(v, 0.0, 1.0); }\n\nint mul(float v1, int v2) {\n  return ifloor(v1 * float(v2));\n}\n\nivec2 mul(vec2 v1, ivec2 v2) {\n  return ifloor(v1 * vec2(v2) + 0.5);\n}\n\n// unpack a 16-bit integer from a float vec2\nint getInt16(vec2 v) {\n  ivec2 iv = round(v * 255.0);\n  return iv.x * INT(128) + iv.y;\n}\n\nvec2 pixelScale;\nvec2 coverage = vec2(0.0);\nvec2 weight = vec2(0.5);\nconst float minDistance = 1.0/8192.0;\nconst float hardness = 1.05; // amount of antialias\n\n// the maximum number of curves in a glyph\nconst int N = INT(250);\n\n// retrieves an indexed pixel from a sampler\nvec4 getTexel(sampler2D sampler, int pos, ivec2 size) {\n  int width = size.x;\n  int y = ifloor(pos / width);\n  int x = pos - y * width;  // pos % width\n\n  return texture2D(sampler, (vec2(x, y) + 0.5) / vec2(size));\n}\n\nvoid calulateCrossings(vec2 p0, vec2 p1, vec2 p2, out vec2 C1, out vec2 C2) {\n\n  // get the coefficients of the quadratic in t\n  vec2 a = p0 - p1 * 2.0 + p2;\n  vec2 b = p0 - p1;\n  vec2 c = p0 - vTexCoord;\n\n  // found out which values of 't' it crosses the axes\n  vec2 surd = sqrt(max(vec2(0.0), b * b - a * c));\n  vec2 t1 = ((b - surd) / a).yx;\n  vec2 t2 = ((b + surd) / a).yx;\n\n  // approximate straight lines to avoid rounding errors\n  if (abs(a.y) < 0.001)\n    t1.x = t2.x = c.y / (2.0 * b.y);\n\n  if (abs(a.x) < 0.001)\n    t1.y = t2.y = c.x / (2.0 * b.x);\n\n  // plug into quadratic formula to find the corrdinates of the crossings\n  C1 = ((a * t1 - b * 2.0) * t1 + c) * pixelScale;\n  C2 = ((a * t2 - b * 2.0) * t2 + c) * pixelScale;\n}\n\nvoid coverageX(vec2 p0, vec2 p1, vec2 p2) {\n\n  vec2 C1, C2;\n  calulateCrossings(p0, p1, p2, C1, C2);\n\n  // determine on which side of the x-axis the points lie\n  bool y0 = p0.y > vTexCoord.y;\n  bool y1 = p1.y > vTexCoord.y;\n  bool y2 = p2.y > vTexCoord.y;\n\n  // could web be under the curve (after t1)?\n  if (y1 ? !y2 : y0) {\n    // add the coverage for t1\n    coverage.x += saturate(C1.x + 0.5);\n    // calculate the anti-aliasing for t1\n    weight.x = min(weight.x, abs(C1.x));\n  }\n\n  // are we outside the curve (after t2)?\n  if (y1 ? !y0 : y2) {\n    // subtract the coverage for t2\n    coverage.x -= saturate(C2.x + 0.5);\n    // calculate the anti-aliasing for t2\n    weight.x = min(weight.x, abs(C2.x));\n  }\n}\n\n// this is essentially the same as coverageX, but with the axes swapped\nvoid coverageY(vec2 p0, vec2 p1, vec2 p2) {\n\n  vec2 C1, C2;\n  calulateCrossings(p0, p1, p2, C1, C2);\n\n  bool x0 = p0.x > vTexCoord.x;\n  bool x1 = p1.x > vTexCoord.x;\n  bool x2 = p2.x > vTexCoord.x;
81182\n\n  if (x1 ? !x2 : x0) {\n    coverage.y -= saturate(C1.y + 0.5);\n    weight.y = min(weight.y, abs(C1.y));\n  }\n\n  if (x1 ? !x0 : x2) {\n    coverage.y += saturate(C2.y + 0.5);\n    weight.y = min(weight.y, abs(C2.y));\n  }\n}\n\nvoid main() {\n\n  // calculate the pixel scale based on screen-coordinates\n  pixelScale = hardness / fwidth(vTexCoord);\n\n  // which grid cell is this pixel in?\n  ivec2 gridCoord = ifloor(vTexCoord * vec2(uGridSize));\n\n  // intersect curves in this row\n  {\n    // the index into the row info bitmap\n    int rowIndex = gridCoord.y + uGridOffset.y;\n    // fetch the info texel\n    vec4 rowInfo = getTexel(uSamplerRows, rowIndex, uGridImageSize);\n    // unpack the rowInfo\n    int rowStrokeIndex = getInt16(rowInfo.xy);\n    int rowStrokeCount = getInt16(rowInfo.zw);\n\n    for (int iRowStroke = INT(0); iRowStroke < N; iRowStroke++) {\n      if (iRowStroke >= rowStrokeCount)\n        break;\n\n      // each stroke is made up of 3 points: the start and control point\n      // and the start of the next curve.\n      // fetch the indices of this pair of strokes:\n      vec4 strokeIndices = getTexel(uSamplerRowStrokes, rowStrokeIndex++, uCellsImageSize);\n\n      // unpack the stroke index\n      int strokePos = getInt16(strokeIndices.xy);\n\n      // fetch the two strokes\n      vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize);\n      vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize);\n\n      // calculate the coverage\n      coverageX(stroke0.xy, stroke0.zw, stroke1.xy);\n    }\n  }\n\n  // intersect curves in this column\n  {\n    int colIndex = gridCoord.x + uGridOffset.x;\n    vec4 colInfo = getTexel(uSamplerCols, colIndex, uGridImageSize);\n    int colStrokeIndex = getInt16(colInfo.xy);\n    int colStrokeCount = getInt16(colInfo.zw);\n    \n    for (int iColStroke = INT(0); iColStroke < N; iColStroke++) {\n      if (iColStroke >= colStrokeCount)\n        break;\n\n      vec4 strokeIndices = getTexel(uSamplerColStrokes, colStrokeIndex++, uCellsImageSize);\n\n      int strokePos = getInt16(strokeIndices.xy);\n      vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize);\n      vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize);\n      coverageY(stroke0.xy, stroke0.zw, stroke1.xy);\n    }\n  }\n\n  weight = saturate(1.0 - weight * 2.0);\n  float distance = max(weight.x + weight.y, minDistance); // manhattan approx.\n  float antialias = abs(dot(coverage, weight) / distance);\n  float cover = min(abs(coverage.x), abs(coverage.y));\n  gl_FragColor = uMaterialColor;\n  gl_FragColor.a *= saturate(max(antialias, cover));\n}",
81183        lineVert: "/*\n  Part of the Processing project - http://processing.org\n  Copyright (c) 2012-15 The Processing Foundation\n  Copyright (c) 2004-12 Ben Fry and Casey Reas\n  Copyright (c) 2001-04 Massachusetts Institute of Technology\n  This library is free software; you can redistribute it and/or\n  modify it under the terms of the GNU Lesser General Public\n  License as published by the Free Software Foundation, version 2.1.\n  This library is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n  Lesser General Public License for more details.\n  You should have received a copy of the GNU Lesser General\n  Public License along with this library; if not, write to the\n  Free Software Foundation, Inc., 59 Temple Place, Suite 330,\n  Boston, MA  02111-1307  USA\n*/\n\n#define PROCESSING_LINE_SHADER\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uStrokeWeight;\n\nuniform vec4 uViewport;\n\n// using a scale <1 moves the lines towards the camera\n// in order to prevent popping effects due to half of\n// the line disappearing behind the geometry faces.\nvec3 scale = vec3(0.9995);\n\nattribute vec4 aPosition;\nattribute vec4 aDirection;\n  \nvoid main() {\n  vec4 posp = uModelViewMatrix * aPosition;\n  vec4 posq = uModelViewMatrix * (aPosition + vec4(aDirection.xyz, 0));\n\n  // Moving vertices slightly toward the camera\n  // to avoid depth-fighting with the fill triangles.\n  // Discussed here:\n  // http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=252848  \n  posp.xyz = posp.xyz * scale;\n  posq.xyz = posq.xyz * scale;\n\n  vec4 p = uProjectionMatrix * posp;\n  vec4 q = uProjectionMatrix * posq;\n\n  // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height])\n  // screen_p = (p.xy/p.w + <1,1>) * 0.5 * uViewport.zw\n\n  // prevent division by W by transforming the tangent formula (div by 0 causes\n  // the line to disappear, see https://github.com/processing/processing/issues/5183)\n  // t = screen_q - screen_p\n  //\n  // tangent is normalized and we don't care which aDirection it points to (+-)\n  // t = +- normalize( screen_q - screen_p )\n  // t = +- normalize( (q.xy/q.w+<1,1>)*0.5*uViewport.zw - (p.xy/p.w+<1,1>)*0.5*uViewport.zw )\n  //\n  // extract common factor, <1,1> - <1,1> cancels out\n  // t = +- normalize( (q.xy/q.w - p.xy/p.w) * 0.5 * uViewport.zw )\n  //\n  // convert to common divisor\n  // t = +- normalize( ((q.xy*p.w - p.xy*q.w) / (p.w*q.w)) * 0.5 * uViewport.zw )\n  //\n  // remove the common scalar divisor/factor, not needed due to normalize and +-\n  // (keep uViewport - can't remove because it has different c
81183omponents for x and y\n  //  and corrects for aspect ratio, see https://github.com/processing/processing/issues/5181)\n  // t = +- normalize( (q.xy*p.w - p.xy*q.w) * uViewport.zw )\n\n  vec2 tangent = normalize((q.xy*p.w - p.xy*q.w) * uViewport.zw);\n\n  // flip tangent to normal (it's already normalized)\n  vec2 normal = vec2(-tangent.y, tangent.x);\n\n  float thickness = aDirection.w * uStrokeWeight;\n  vec2 offset = normal * thickness / 2.0;\n\n  // Perspective ---\n  // convert from world to clip by multiplying with projection scaling factor\n  // to get the right thickness (see https://github.com/processing/processing/issues/5182)\n  // invert Y, projections in Processing invert Y\n  vec2 perspScale = (uProjectionMatrix * vec4(1, -1, 0, 0)).xy;\n\n  // No Perspective ---\n  // multiply by W (to cancel out division by W later in the pipeline) and\n  // convert from screen to clip (derived from clip to screen above)\n  vec2 noPerspScale = p.w / (0.5 * uViewport.zw);\n\n  //gl_Position.xy = p.xy + offset.xy * mix(noPerspScale, perspScale, float(perspective > 0));\n  gl_Position.xy = p.xy + offset.xy * perspScale;\n  gl_Position.zw = p.zw;\n}\n",
81184        lineFrag: "precision mediump float;\nprecision mediump int;\n\nuniform vec4 uMaterialColor;\n\nvoid main() {\n  gl_FragColor = uMaterialColor;\n}",
81185        pointVert: "attribute vec3 aPosition;\nuniform float uPointSize;\nvarying float vStrokeWeight;\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;
81185\nvoid main() {\n\tvec4 positionVec4 =  vec4(aPosition, 1.0);\n\tgl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n\tgl_PointSize = uPointSize;\n\tvStrokeWeight = uPointSize;\n}",
81186        pointFrag: "precision mediump float;\nprecision mediump int;\nuniform vec4 uMaterialColor;\nvarying float vStrokeWeight;\n\nvoid main(){\n\tfloat mask = 0.0;\n\n\t// make a circular mask using the gl_PointCoord (goes from 0 - 1 on a point)\n    // might be able to get a nicer edge on big strokeweights with smoothstep but slightly less performant\n\n\tmask = step(0.98, length(gl_PointCoord * 2.0 - 1.0));\n\n\t// if strokeWeight is 1 or less lets just draw a square\n\t// this prevents weird artifacting from carving circles when our points are really small\n\t// if strokeWeight is larger than 1, we just use it as is\n\n\tmask = mix(0.0, mask, clamp(floor(vStrokeWeight - 0.5),0.0,1.0));\n\n\t// throw away the borders of the mask\n    // otherwise we get weird alpha blending issues\n\n\tif(mask > 0.98){\n      discard;\n  \t}\n\n  \tgl_FragColor = vec4(uMaterialColor.rgb * (1.0 - mask), uMaterialColor.a) ;\n}"
81187      };
81188      /**
81189       * 3D graphics class
81190       * @private
81191       * @class p5.RendererGL
81192       * @constructor
81193       * @extends p5.Renderer
81194       * @todo extend class to include public method for offscreen
81195       * rendering (FBO).
81196       *
81197       */
81198
81199      p5.RendererGL = function (elt, pInst, isMainCanvas, attr) {
81200        p5.Renderer.call(this, elt, pInst, isMainCanvas);
81201        this.attributes = {};
81202        attr = attr || {};
81203        this.attributes.alpha = attr.alpha === undefined ? true : attr.alpha;
81204        this.attributes.depth = attr.depth === undefined ? true : attr.depth;
81205        this.attributes.stencil = attr.stencil === undefined ? true : attr.stencil;
81206        this.attributes.antialias = attr.antialias === undefined ? false : attr.antialias;
81207        this.attributes.premultipliedAlpha = attr.premultipliedAlpha === undefined ? false : attr.premultipliedAlpha;
81208        this.attributes.preserveDrawingBuffer = attr.preserveDrawingBuffer === undefined ? true : attr.preserveDrawingBuffer;
81209        this.attributes.perPixelLighting = attr.perPixelLighting === undefined ? false : attr.perPixelLighting;
81210
81211        this._initContext();
81212
81213        this.isP3D = true; //lets us know we're in 3d mode
81214
81215        this.GL = this.drawingContext; // lights
81216
81217        this.ambientLightColors = [];
81218        this.directionalLightDirections = [];
81219        this.directionalLightColors = [];
81220        this.pointLightPositions = [];
81221        this.pointLightColors = [];
81222        /**
81223         * model view, projection, & normal
81224         * matrices
81225         */
81226
81227        this.uMVMatrix = new p5.Matrix();
81228        this.uPMatrix = new p5.Matrix();
81229        this.uNMatrix = new p5.Matrix('mat3'); // Camera
81230
81231        this._curCamera = new p5.Camera(this);
81232
81233        this._curCamera._computeCameraDefaultSettings();
81234
81235        this._curCamera._setDefaultCamera(); //Geometry & Material hashes
81236
81237
81238        this.gHash = {};
81239        this._defaultLightShader = undefined;
81240        this._defaultImmediateModeShader = undefined;
81241        this._defaultNormalShader = undefined;
81242        this._defaultColorShader = undefined;
81243        this._defaultPointShader = undefined;
81244        this.curFillShader = undefined;
81245        this.curStrokeShader = undefined;
81246        this.curPointShader = undefined;
81247
81248        this._useColorShader();
81249
81250        this.setStrokeShader(this._getLineShader());
81251
81252        this._usePointShader();
81253
81254        this._pointVertexBuffer = this.GL.createBuffer(); //Imediate Mode
81255        //default drawing is done in Retained Mode
81256
81257        this.isImmediateDrawing = false;
81258        this.immediateMode = {}; // note: must call fill() and stroke () AFTER
81259        // default shader has been set.
81260
81261        this.fill(255, 255, 255, 255); //this.stroke(0, 0, 0, 255);
81262
81263        this.pointSize = 5.0; //default point size
81264
81265        this.strokeWeight(1);
81266        this.stroke(0, 0, 0); // array of textures created in this gl context via this.getTexture(src)
81267
81268        this.textures = [];
81269        this.textureImage = undefined;
81270        this.textureMode = constants.IMAGE;
81271        this._curveTightness = 6; // lookUpTable for coefficients needed to be calculated for bezierVertex, same are used for curveVertex
81272
81273        this._lookUpTableBezier = []; // lookUpTable for coefficients needed to be calculated for quadraticVertex
81274
81275        this._lookUpTableQuadratic = []; // current curveDetail in the Bezier lookUpTable
81276
81277        this._lutBezierDetail = 0; // current curveDetail in the Quadratic lookUpTable
81278
81279        this._lutQuadraticDetail = 0;
81280        this._tessy = this._initTessy();
81281        this.fontInfos = {};
81282        return this;
81283      };
81284
81285      p5.RendererGL.prototype = Object.create(p5.Renderer.prototype); //////////////////////////////////////////////
81286      // Setting
81287      //////////////////////////////////////////////
81288
81289      p5.RendererGL.prototype._initContext = function () {
81290        try {
81291          this.drawingContext = this.canvas.getContext('webgl', this.attributes) || this.canvas.getContext('experimental-webgl', this.attributes);
81292
81293          if (this.drawingContext === null) {
81294            throw new Error('Error creating webgl context');
81295          } else {
81296            console.log('p5.RendererGL: enabled webgl context');
81297            var gl = this.drawingContext;
81298            gl.enable(gl.DEPTH_TEST);
81299            gl.depthFunc(gl.LEQUAL);
81300            gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
81301            this._viewport = this.drawingContext.getParameter(this.drawingContext.VIEWPORT);
81302          }
81303        } catch (er) {
81304          throw er;
81305        }
81306      }; //This is helper function to reset the context anytime the attributes
81307      //are changed with setAttributes()
81308
81309
81310      p5.RendererGL.prototype._resetContext = function (attr, options, callback) {
81311        var w = this.width;
81312        var h = this.height;
81313        var defaultId = this.canvas.id;
81314        var c = this.canvas;
81315
81316        if (c) {
81317          c.parentNode.removeChild(c);
81318        }
81319
81320        c = document.createElement('canvas');
81321        c.id = defaultId;
81322
81323        if (this._pInst._userNode) {
81324          this._pInst._userNode.appendChild(c);
81325        } else {
81326          document.body.appendChild(c);
81327        }
81328
81329        this._pInst.canvas = c;
81330        var renderer = new p5.RendererGL(this._pInst.canvas, this._pInst, true, attr);
81331
81332        this._pInst._setProperty('_renderer', renderer);
81333
81334        renderer.resize(w, h);
81335
81336        renderer._applyDefaults();
81337
81338        this._pInst._elements.push(renderer);
81339
81340        if (typeof callback === 'function') {
81341          //setTimeout with 0 forces the task to the back of the queue, this ensures that
81342          //we finish switching out the renderer
81343          setTimeout(function () {
81344            callback.apply(window._renderer, options);
81345          }, 0);
81346        }
81347      };
81348      /**
81349       * @module Rendering
81350       * @submodule Rendering
81351       * @for p5
81352       */
81353
81354      /**
81355       * Set attributes for the WebGL Drawing context.
81356       * This is a way of adjusting ways that the WebGL
81357       * renderer works to fine-tune the display and performance.
81358       * This should be put in setup().
81359       * The available attributes are:
81360       * <br>
81361       * alpha - indicates if the canvas contains an alpha buffer
81362       * default is true
81363       * <br><br>
81364       * depth - indicates whether the drawing buffer has a depth buffer
81365       * of at least 16 bits - default is true
81366       * <br><br>
81367       * stencil - indicates whether the drawing buffer has a stencil buffer
81368       * of at least 8 bits
81369       * <br><br>
81370       * antialias - indicates whether or not to perform anti-aliasing
81371       * default is false
81372       * <br><br>
81373       * premultipliedAlpha - indicates that the page compositor will assume
81374       * the drawing buffer contains colors with pre-multiplied alpha
81375       * default is false
81376       * <br><br>
81377       * preserveDrawingBuffer - if true the buffers will not be cleared and
81378       * and will preserve their values until cleared or overwritten by author
81379       * (note that p5 clears automatically on draw loop)
81380       * default is true
81381       * <br><br>
81382       * perPixelLighting - if true, per-pixel lighting will be used in the
81383       * lighting shader.
81384       * default is false
81385       * <br><br>
81386       * @method setAttributes
81387       * @for p5
81388       * @param  {String}  key Name of attribute
81389       * @param  {Boolean}        value New value of named attribute
81390       * @example
81391       * <div>
81392       * <code>
81393       * function setup() {
81394       *   createCanvas(100, 100, WEBGL);
81395       * }
81396       *
81397       * function draw() {
81398       *   background(255);
81399       *   push();
81400       *   rotateZ(frameCount * 0.02);
81401       *   rotateX(frameCount * 0.02);
81402       *   rotateY(frameCount * 0.02);
81403       *   fill(0, 0, 0);
81404       *   box(50);
81405       *   pop();
81406       * }
81407       * </code>
81408       * </div>
81409       * <br>
81410       * Now with the antialias attribute set to true.
81411       * <br>
81412       * <div>
81413       * <code>
81414       * function setup() {
81415       *   createCanvas(100, 100, WEBGL);
81416       *   setAttributes('antialias', true);
81417       * }
81418       *
81419       * function draw() {
81420       *   background(255);
81421       *   push();
81422       *   rotateZ(frameCount * 0.02);
81423       *   rotateX(frameCount * 0.02);
81424       *   rotateY(frameCount * 0.02);
81425       *   fill(0, 0, 0);
81426       *   box(50);
81427       *   pop();
81428       * }
81429       * </code>
81430       * </div>
81431       *
81432       * <div>
81433       * <code>
81434       * // press the mouse button to enable perPixelLighting
81435       * function setup() {
81436       *   createCanvas(100, 100, WEBGL);
81437       *   noStroke();
81438       *   fill(255);
81439       * }
81440       *
81441       * var lights = [
81442       *   { c: '#f00', t: 1.12, p: 1.91, r: 0.2 },
81443       *   { c: '#0f0', t: 1.21, p: 1.31, r: 0.2 },
81444       *   { c: '#00f', t: 1.37, p: 1.57, r: 0.2 },
81445       *   { c: '#ff0', t: 1.12, p: 1.91, r: 0.7 },
81446       *   { c: '#0ff', t: 1.21, p: 1.31, r: 0.7 },
81447       *   { c: '#f0f', t: 1.37, p: 1.57, r: 0.7 }
81448       * ];
81449       *
81450       * function draw() {
81451       *   var t = millis() / 1000 + 1000;
81452       *   background(0);
81453       *   directionalLight(color('#222'), 1, 1, 1);
81454       *
81455       *   for (var i = 0; i < lights.length; i++) {
81456       *     var light = lights[i];
81457       *     pointLight(
81458       *       color(light.c),
81459       *       p5.Vector.fromAngles(t * light.t, t * light.p, width * light.r)
81460       *     );
81461       *   }
81462       *
81463       *   specularMaterial(255);
81464       *   sphere(width * 0.1);
81465       *
81466       *   rotateX(t * 0.77);
81467       *   rotateY(t * 0.83);
81468       *   rotateZ(t * 0.91);
81469       *   torus(width * 0.3, width * 0.07, 24, 10);
81470       * }
81471       *
81472       * function mousePressed() {
81473       *   setAttributes('perPixelLighting', true);
81474       *   noStroke();
81475       *   fill(255);
81476       * }
81477       * function mouseReleased() {
81478       *   setAttributes('perPixelLighting', false);
81479       *   noStroke();
81480       *   fill(255);
81481       * }
81482       * </code>
81483       * </div>
81484       *
81485       * @alt a rotating cube with smoother edges
81486       */
81487
81488      /**
81489       * @method setAttributes
81490       * @for p5
81491       * @param  {Object}  obj object with key-value pairs
81492       */
81493
81494
81495      p5.prototype.setAttributes = function (key, value) {
81496        this._assert3d('setAttributes'); //@todo_FES
81497
81498
81499        var attr;
81500
81501        if (typeof value !== 'undefined') {
81502          attr = {};
81503          attr[key] = value;
81504        } else if (key instanceof Object) {
81505          attr = key;
81506        }
81507
81508        this.push();
81509
81510        this._renderer._resetContext(attr);
81511
81512        this.pop();
81513      };
81514      /**
81515       * @class p5.RendererGL
81516       */
81517
81518
81519      p5.RendererGL.prototype._update = function () {
81520        // reset model view and apply initial camera transform
81521        // (containing only look at info; no projection).
81522        this.uMVMatrix.set(this._curCamera.cameraMatrix.mat4[0], this._curCamera.cameraMatrix.mat4[1], this._curCamera.cameraMatrix.mat4[2], this._curCamera.cameraMatrix.mat4[3], this._curCamera.cameraMatrix.mat4[4], this._curCamera.cameraMatrix.mat4[5], this._curCamera.cameraMatrix.mat4[6], this._curCamera.cameraMatrix.mat4[7], this._curCamera.cameraMatrix.mat4[8], this._curCamera.cameraMatrix.mat4[9], this._curCamera.cameraMatrix.mat4[10], this._curCamera.cameraMatrix.mat4[11], this._curCamera.cameraMatrix.mat4[12], this._curCamera.cameraMatrix.mat4[13], this._curCamera.cameraMatrix.mat4[14], this._curCamera.cameraMatrix.mat4[15]); // reset light data for new frame.
81523
81524        this.ambientLightColors.length = 0;
81525        this.directionalLightDirections.length = 0;
81526        this.directionalLightColors.length = 0;
81527        this.pointLightPositions.length = 0;
81528        this.pointLightColors.length = 0;
81529      };
81530      /**
81531       * [background description]
81532       */
81533
81534
81535      p5.RendererGL.prototype.background = function () {
81536        var _col = this._pInst.color.apply(this._pInst, arguments);
81537
81538        var _r = _col.levels[0] / 255;
81539
81540        var _g = _col.levels[1] / 255;
81541
81542        var _b = _col.levels[2] / 255;
81543
81544        var _a = _col.levels[3] / 255;
81545
81546        this.GL.clearColor(_r, _g, _b, _a);
81547        this.GL.depthMask(true);
81548        this.GL.clear(this.GL.COLOR_BUFFER_BIT | this.GL.DEPTH_BUFFER_BIT);
81549      }; //@TODO implement this
81550      // p5.RendererGL.prototype.clear = function() {
81551      //@TODO
81552      // };
81553      //////////////////////////////////////////////
81554      // COLOR
81555      //////////////////////////////////////////////
81556
81557      /**
81558       * Basic fill material for geometry with a given color
81559       * @method  fill
81560       * @class p5.RendererGL
81561       * @param  {Number|Number[]|String|p5.Color} v1  gray value,
81562       * red or hue value (depending on the current color mode),
81563       * or color Array, or CSS color string
81564       * @param  {Number}            [v2] green or saturation value
81565       * @param  {Number}            [v3] blue or brightness value
81566       * @param  {Number}            [a]  opacity
81567       * @chainable
81568       * @example
81569       * <div>
81570       * <code>
81571       * function setup() {
81572       *   createCanvas(200, 200, WEBGL);
81573       * }
81574       *
81575       * function draw() {
81576       *   background(0);
81577       *   noStroke();
81578       *   fill(100, 100, 240);
81579       *   rotateX(frameCount * 0.01);
81580       *   rotateY(frameCount * 0.01);
81581       *   box(75, 75, 75);
81582       * }
81583       * </code>
81584       * </div>
81585       *
81586       * @alt
81587       * black canvas with purple cube spinning
81588       *
81589       */
81590
81591
81592      p5.RendererGL.prototype.fill = function (v1, v2, v3, a) {
81593        //see material.js for more info on color blending in webgl
81594        var color = p5.prototype.color.apply(this._pInst, arguments);
81595        this.curFillColor = color._array;
81596
81597        if (this.isImmediateDrawing) {
81598          this.setFillShader(this._getImmediateModeShader());
81599        } else {
81600          this.setFillShader(this._getColorShader());
81601        }
81602
81603        this.drawMode = constants.FILL;
81604        this.curFillShader.setUniform('uMaterialColor', this.curFillColor);
81605      };
81606      /**
81607       * Basic stroke material for geometry with a given color
81608       * @method  stroke
81609       * @param  {Number|Number[]|String|p5.Color} v1  gray value,
81610       * red or hue value (depending on the current color mode),
81611       * or color Array, or CSS color string
81612       * @param  {Number}            [v2] green or saturation value
81613       * @param  {Number}            [v3] blue or brightness value
81614       * @param  {Number}            [a]  opacity
81615       * @example
81616       * <div>
81617       * <code>
81618       * function setup() {
81619       *   createCanvas(200, 200, WEBGL);
81620       * }
81621       *
81622       * function draw() {
81623       *   background(0);
81624       *   stroke(240, 150, 150);
81625       *   fill(100, 100, 240);
81626       *   rotateX(frameCount * 0.01);
81627       *   rotateY(frameCount * 0.01);
81628       *   box(75, 75, 75);
81629       * }
81630       * </code>
81631       * </div>
81632       *
81633       * @alt
81634       * black canvas with purple cube with pink outline spinning
81635       *
81636       */
81637
81638
81639      p5.RendererGL.prototype.stroke = function (r, g, b, a) {
81640        //@todo allow transparency in stroking currently doesn't have
81641        //any impact and causes problems with specularMaterial
81642        arguments[3] = 255;
81643        var color = p5.prototype.color.apply(this._pInst, arguments);
81644        this.curStrokeColor = color._array;
81645        this.curStrokeShader.setUniform('uMaterialColor', this.curStrokeColor);
81646        this.curPointShader.setUniform('uMaterialColor', color._array);
81647      };
81648      /**
81649       * Change weight of stroke
81650       * @method  strokeWeight
81651       * @param  {Number} stroke weight to be used for drawing
81652       * @example
81653       * <div>
81654       * <code>
81655       * function setup() {
81656       *   createCanvas(200, 400, WEBGL);
81657       *   setAttributes('antialias', true);
81658       * }
81659       *
81660       * function draw() {
81661       *   background(0);
81662       *   noStroke();
81663       *   translate(0, -100, 0);
81664       *   stroke(240, 150, 150);
81665       *   fill(100, 100, 240);
81666       *   push();
81667       *   strokeWeight(8);
81668       *   rotateX(frameCount * 0.01);
81669       *   rotateY(frameCount * 0.01);
81670       *   sphere(75);
81671       *   pop();
81672       *   push();
81673       *   translate(0, 200, 0);
81674       *   strokeWeight(1);
81675       *   rotateX(frameCount * 0.01);
81676       *   rotateY(frameCount * 0.01);
81677       *   sphere(75);
81678       *   pop();
81679       * }
81680       * </code>
81681       * </div>
81682       *
81683       * @alt
81684       * black canvas with two purple rotating spheres with pink
81685       * outlines the sphere on top has much heavier outlines,
81686       *
81687       */
81688
81689
81690      p5.RendererGL.prototype.strokeWeight = function (w) {
81691        if (this.curStrokeWeight !== w) {
81692          this.pointSize = w;
81693          this.curStrokeWeight = w;
81694          this.curStrokeShader.setUniform('uStrokeWeight', w);
81695          this.curPointShader.setUniform('uPointSize', w);
81696        }
81697      };
81698      /**
81699       * Returns an array of [R,G,B,A] values for any pixel or grabs a section of
81700       * an image. If no parameters are specified, the entire image is returned.
81701       * Use the x and y parameters to get the value of one pixel. Get a section of
81702       * the display window by specifying additional w and h parameters. When
81703       * getting an image, the x and y parameters define the coordinates for the
81704       * upper-left corner of the image, regardless of the current imageMode().
81705       * <br><br>
81706       * If the pixel requested is outside of the image window, [0,0,0,255] is
81707       * returned.
81708       * <br><br>
81709       * Getting the color of a single pixel with get(x, y) is easy, but not as fast
81710       * as grabbing the data directly from pixels[]. The equivalent statement to
81711       * get(x, y) is using pixels[] with pixel density d
81712       *
81713       * @private
81714       * @method get
81715       * @param  {Number}               [x] x-coordinate of the pixel
81716       * @param  {Number}               [y] y-coordinate of the pixel
81717       * @param  {Number}               [w] width
81718       * @param  {Number}               [h] height
81719       * @return {Number[]|Color|p5.Image}  color of pixel at x,y in array format
81720       *                                    [R, G, B, A] or <a href="#/p5.Image">p5.Image</a>
81721       */
81722
81723
81724      p5.RendererGL.prototype.get = function (x, y, w, h) {
81725        var ctx = this._pInst || this;
81726        var pd = ctx._pixelDensity;
81727        var sx = x * pd;
81728        var sy = y * pd;
81729
81730        if (w === 1 && h === 1) {
81731          var pixels = new Uint8Array(4);
81732          this.drawingContext.readPixels(sx, sy, 1, 1, this.drawingContext.RGBA, this.drawingContext.UNSIGNED_BYTE, pixels);
81733          return [pixels[0], pixels[1], pixels[2], pixels[3]];
81734        } else {
81735          //auto constrain the width and height to
81736          //dimensions of the source image
81737          var dw = Math.min(w, ctx.width);
81738          var dh = Math.min(h, ctx.height);
81739          var sw = dw * pd;
81740          var sh = dh * pd;
81741          var region = new p5.Image(dw, dh);
81742          region.canvas.getContext('2d') // not sure this is correct
81743          .drawImage(this.canvas, sx, sy, sw, sh, 0, 0, dw, dh);
81744          return region;
81745        }
81746      };
81747      /**
81748       * Loads the pixels data for this canvas into the pixels[] attribute.
81749       * Note that updatePixels() and set() do not work.
81750       * Any pixel manipulation must be done directly to the pixels[] array.
81751       *
81752       * @private
81753       * @method loadPixels
81754       *
81755       */
81756
81757
81758      p5.RendererGL.prototype.loadPixels = function () {
81759        //@todo_FES
81760        if (this.attributes.preserveDrawingBuffer !== true) {
81761          console.log('loadPixels only works in WebGL when preserveDrawingBuffer ' + 'is true.');
81762          return;
81763        }
81764
81765        var pd = this._pInst._pixelDensity;
81766        var x = 0;
81767        var y = 0;
81768        var w = this.width;
81769        var h = this.height;
81770        w *= pd;
81771        h *= pd; //if there isn't a renderer-level temporary pixels buffer
81772        //make a new one
81773
81774        if (typeof this.pixels === 'undefined') {
81775          this.pixels = new Uint8Array(this.GL.drawingBufferWidth * this.GL.drawingBufferHeight * 4);
81776        }
81777
81778        this.GL.readPixels(x, y, w, h, this.GL.RGBA, this.GL.UNSIGNED_BYTE, this.pixels);
81779
81780        this._pInst._setProperty('pixels', this.pixels);
81781      }; //////////////////////////////////////////////
81782      // HASH | for geometry
81783      //////////////////////////////////////////////
81784
81785
81786      p5.RendererGL.prototype.geometryInHash = function (gId) {
81787        return this.gHash[gId] !== undefined;
81788      };
81789      /**
81790       * [resize description]
81791       * @private
81792       * @param  {Number} w [description]
81793       * @param  {Number} h [description]
81794       */
81795
81796
81797      p5.RendererGL.prototype.resize = function (w, h) {
81798        p5.Renderer.prototype.resize.call(this, w, h);
81799        this.GL.viewport(0, 0, this.GL.drawingBufferWidth, this.GL.drawingBufferHeight);
81800        this._viewport = this.GL.getParameter(this.GL.VIEWPORT);
81801
81802        this._curCamera._resize(); //resize pixels buffer
81803
81804
81805        if (typeof this.pixels !== 'undefined') {
81806          this.pixels = new Uint8Array(this.GL.drawingBufferWidth * this.GL.drawingBufferHeight * 4);
81807        }
81808      };
81809      /**
81810       * clears color and depth buffers
81811       * with r,g,b,a
81812       * @private
81813       * @param {Number} r normalized red val.
81814       * @param {Number} g normalized green val.
81815       * @param {Number} b normalized blue val.
81816       * @param {Number} a normalized alpha val.
81817       */
81818
81819
81820      p5.RendererGL.prototype.clear = function () {
81821        var _r = arguments[0] || 0;
81822
81823        var _g = arguments[1] || 0;
81824
81825        var _b = arguments[2] || 0;
81826
81827        var _a = arguments[3] || 0;
81828
81829        this.GL.clearColor(_r, _g, _b, _a);
81830        this.GL.clear(this.GL.COLOR_BUFFER_BIT | this.GL.DEPTH_BUFFER_BIT);
81831      };
81832      /**
81833       * [translate description]
81834       * @private
81835       * @param  {Number} x [description]
81836       * @param  {Number} y [description]
81837       * @param  {Number} z [description]
81838       * @chainable
81839       * @todo implement handle for components or vector as args
81840       */
81841
81842
81843      p5.RendererGL.prototype.translate = function (x, y, z) {
81844        if (x instanceof p5.Vector) {
81845          z = x.z;
81846          y = x.y;
81847          x = x.x;
81848        }
81849
81850        this.uMVMatrix.translate([x, y, z]);
81851        return this;
81852      };
81853      /**
81854       * Scales the Model View Matrix by a vector
81855       * @private
81856       * @param  {Number | p5.Vector | Array} x [description]
81857       * @param  {Number} [y] y-axis scalar
81858       * @param  {Number} [z] z-axis scalar
81859       * @chainable
81860       */
81861
81862
81863      p5.RendererGL.prototype.scale = function (x, y, z) {
81864        this.uMVMatrix.scale(x, y, z);
81865        return this;
81866      };
81867
81868      p5.RendererGL.prototype.rotate = function (rad, axis) {
81869        if (typeof axis === 'undefined') {
81870          return this.rotateZ(rad);
81871        }
81872
81873        arguments[0] = this._pInst._fromRadians(rad);
81874        p5.Matrix.prototype.rotate.apply(this.uMVMatrix, arguments);
81875        return this;
81876      };
81877
81878      p5.RendererGL.prototype.rotateX = function (rad) {
81879        this.rotate(rad, 1, 0, 0);
81880        return this;
81881      };
81882
81883      p5.RendererGL.prototype.rotateY = function (rad) {
81884        this.rotate(rad, 0, 1, 0);
81885        return this;
81886      };
81887
81888      p5.RendererGL.prototype.rotateZ = function (rad) {
81889        this.rotate(rad, 0, 0, 1);
81890        return this;
81891      };
81892
81893      p5.RendererGL.prototype.push = function () {
81894        // get the base renderer style
81895        var style = p5.Renderer.prototype.push.apply(this); // add webgl-specific style properties
81896
81897        var properties = style.properties;
81898        properties.uMVMatrix = this.uMVMatrix.copy();
81899        properties.uPMatrix = this.uPMatrix.copy();
81900        properties._curCamera = this._curCamera; // make a copy of the current camera for the push state
81901        // this preserves any references stored using 'createCamera'
81902
81903        this._curCamera = this._curCamera.copy();
81904        return style;
81905      };
81906
81907      p5.RendererGL.prototype.resetMatrix = function () {
81908        this.uMVMatrix = p5.Matrix.identity(this._pInst);
81909        return this;
81910      }; //////////////////////////////////////////////
81911      // SHADER
81912      //////////////////////////////////////////////
81913
81914      /*
81915       * Initializes and uses the specified shader, then returns
81916       * that shader. Note: initialization and resetting the program
81917       * is only used if needed (say, if a new value is provided)
81918       * so it is safe to call this method with the same shader multiple
81919       * times without a signficant performance hit).
81920       *
81921       * @method setFillShader
81922       * @param {p5.Shader} [s] a p5.Shader object
81923       * @return {p5.Shader} the current, updated fill shader
81924       */
81925
81926
81927      p5.RendererGL.prototype.setFillShader = function (s) {
81928        if (this.curFillShader !== s) {
81929          // only do setup etc. if shader is actually new.
81930          this.curFillShader = s; // safe to do this multiple times;
81931          // init() will bail early if has already been run.
81932
81933          this.curFillShader.init(); //this.curFillShader.useProgram();
81934        } // always return this.curFillShader, even if no change was made.
81935
81936
81937        return this.curFillShader;
81938      };
81939
81940      p5.RendererGL.prototype.setPointShader = function (s) {
81941        if (this.curPointShader !== s) {
81942          // only do setup etc. if shader is actually new.
81943          this.curPointShader = s; // safe to do this multiple times;
81944          // init() will bail early if has already been run.
81945
81946          this.curPointShader.init();
81947        }
81948
81949        return this.curPointShader;
81950      };
81951      /*
81952       * @method setStrokeShader
81953       * @param {p5.Shader} [s] a p5.Shader object
81954       * @return {p5.Shader} the current, updated stroke shader
81955       */
81956
81957
81958      p5.RendererGL.prototype.setStrokeShader = function (s) {
81959        if (this.curStrokeShader !== s) {
81960          // only do setup etc. if shader is actually new.
81961          this.curStrokeShader = s; // safe to do this multiple times;
81962          // init() will bail early if has already been run.
81963
81964          this.curStrokeShader.init(); //this.curStrokeShader.useProgram();
81965        } // always return this.curLineShader, even if no change was made.
81966
81967
81968        return this.curStrokeShader;
81969      };
81970      /*
81971       * shaders are created and cached on a per-renderer basis,
81972       * on the grounds that each renderer will have its own gl context
81973       * and the shader must be valid in that context.
81974       *
81975       *
81976       */
81977
81978
81979      p5.RendererGL.prototype._useLightShader = function () {
81980        if (!this.curFillShader || !this.curFillShader.isLightShader()) {
81981          this.setFillShader(this._getLightShader());
81982        }
81983
81984        return this.curFillShader;
81985      };
81986
81987      p5.RendererGL.prototype._useColorShader = function () {
81988        // looking at the code within the glsl files, I'm not really
81989        // sure why these are two different shaders. but, they are,
81990        // and if we're drawing in retain mode but the shader is the
81991        // immediate mode one, we need to switch.
81992        // TODO: what if curFillShader is _any_ other shader?
81993        if (!this.curFillShader || this.curFillShader === this._defaultImmediateModeShader) {
81994          // there are different immediate mode and retain mode color shaders.
81995          // if we're using the immediate mode one, we need to switch to
81996          // one that works for retain mode.
81997          this.setFillShader(this._getColorShader());
81998        }
81999
82000        return this.curFillShader;
82001      };
82002
82003      p5.RendererGL.prototype._usePointShader = function () {
82004        if (!this.curPointShader) {
82005          this.setPointShader(this._getPointShader());
82006        }
82007
82008        return this.curPointShader;
82009      };
82010
82011      p5.RendererGL.prototype._useImmediateModeShader = function () {
82012        // TODO: what if curFillShader is _any_ other shader?
82013        if (!this.curFillShader || this.curFillShader === this._defaultColorShader) {
82014          // this is the fill/stroke shader for retain mode.
82015          // must switch to immediate mode shader before drawing!
82016          this.setFillShader(this._getImmediateModeShader()); // note that if we're using the texture shader...
82017          // this shouldn't change. :)
82018        }
82019
82020        return this.curFillShader;
82021      };
82022
82023      p5.RendererGL.prototype._getLightShader = function () {
82024        if (!this._defaultLightShader) {
82025          if (this.attributes.perPixelLighting) {
82026            this._defaultLightShader = new p5.Shader(this, defaultShaders.phongVert, defaultShaders.phongFrag);
82027          } else {
82028            this._defaultLightShader = new p5.Shader(this, defaultShaders.lightVert, defaultShaders.lightTextureFrag);
82029          }
82030        } //this.drawMode = constants.FILL;
82031
82032
82033        return this._defaultLightShader;
82034      };
82035
82036      p5.RendererGL.prototype._getImmediateModeShader = function () {
82037        if (!this._defaultImmediateModeShader) {
82038          this._defaultImmediateModeShader = new p5.Shader(this, defaultShaders.immediateVert, defaultShaders.vertexColorFrag);
82039        } //this.drawMode = constants.FILL;
82040
82041
82042        return this._defaultImmediateModeShader;
82043      };
82044
82045      p5.RendererGL.prototype._getNormalShader = function () {
82046        if (!this._defaultNormalShader) {
82047          this._defaultNormalShader = new p5.Shader(this, defaultShaders.normalVert, defaultShaders.normalFrag);
82048        } //this.drawMode = constants.FILL;
82049
82050
82051        return this._defaultNormalShader;
82052      };
82053
82054      p5.RendererGL.prototype._getColorShader = function () {
82055        if (!this._defaultColorShader) {
82056          this._defaultColorShader = new p5.Shader(this, defaultShaders.normalVert, defaultShaders.basicFrag);
82057        } //this.drawMode = constants.FILL;
82058
82059
82060        return this._defaultColorShader;
82061      };
82062
82063      p5.RendererGL.prototype._getPointShader = function () {
82064        if (!this._defaultPointShader) {
82065          this._defaultPointShader = new p5.Shader(this, defaultShaders.pointVert, defaultShaders.pointFrag);
82066        }
82067
82068        return this._defaultPointShader;
82069      };
82070
82071      p5.RendererGL.prototype._getLineShader = function () {
82072        if (!this._defaultLineShader) {
82073          this._defaultLineShader = new p5.Shader(this, defaultShaders.lineVert, defaultShaders.lineFrag);
82074        } //this.drawMode = constants.STROKE;
82075
82076
82077        return this._defaultLineShader;
82078      };
82079
82080      p5.RendererGL.prototype._getFontShader = function () {
82081        if (!this._defaultFontShader) {
82082          this.GL.getExtension('OES_standard_derivatives');
82083          this._defaultFontShader = new p5.Shader(this, defaultShaders.fontVert, defaultShaders.fontFrag);
82084        }
82085
82086        return this._defaultFontShader;
82087      };
82088
82089      p5.RendererGL.prototype._getEmptyTexture = function () {
82090        if (!this._emptyTexture) {
82091          // a plain white texture RGBA, full alpha, single pixel.
82092          var im = new p5.Image(1, 1);
82093          im.set(0, 0, 255);
82094          this._emptyTexture = new p5.Texture(this, im);
82095        }
82096
82097        return this._emptyTexture;
82098      };
82099
82100      p5.RendererGL.prototype.getTexture = function (img) {
82101        var textures = this.textures;
82102
82103        for (var it = 0; it < textures.length; ++it) {
82104          var texture = textures[it];
82105          if (texture.src === img) return texture;
82106        }
82107
82108        var tex = new p5.Texture(this, img);
82109        this.textures.push(tex);
82110        return tex;
82111      }; //Binds a buffer to the drawing context
82112      //when passed more than two arguments it also updates or initializes
82113      //the data associated with the buffer
82114
82115
82116      p5.RendererGL.prototype._bindBuffer = function (buffer, target, values, type, usage) {
82117        this.GL.bindBuffer(target, buffer);
82118
82119        if (values !== undefined) {
82120          var data = new type(values);
82121          this.GL.bufferData(target, data, usage);
82122        }
82123      }; //////////////////////////
82124      //// SMOOTHING
82125      /////////////////////////
82126
82127
82128      p5.RendererGL.prototype.smooth = function () {
82129        if (this.attributes.antialias === false) {
82130          this._pInst.setAttributes('antialias', true);
82131        }
82132      };
82133
82134      p5.RendererGL.prototype.noSmooth = function () {
82135        if (this.attributes.antialias === true) {
82136          this._pInst.setAttributes('antialias', false);
82137        }
82138      }; ///////////////////////////////
82139      //// UTILITY FUNCTIONS
82140      //////////////////////////////
82141
82142      /**
82143       * turn a two dimensional array into one dimensional array
82144       * @private
82145       * @param  {Array} arr 2-dimensional array
82146       * @return {Array}     1-dimensional array
82147       * [[1, 2, 3],[4, 5, 6]] -> [1, 2, 3, 4, 5, 6]
82148       */
82149
82150
82151      p5.RendererGL.prototype._flatten = function (arr) {
82152        //when empty, return empty
82153        if (arr.length === 0) {
82154          return [];
82155        } else if (arr.length > 20000) {
82156          //big models , load slower to avoid stack overflow
82157          //faster non-recursive flatten via axelduch
82158          //stackoverflow.com/questions/27266550/how-to-flatten-nested-array-in-javascript
82159          var toString = Object.prototype.toString;
82160          var arrayTypeStr = '[object Array]';
82161          var result = [];
82162          var nodes = arr.slice();
82163          var node;
82164          node = nodes.pop();
82165
82166          do {
82167            if (toString.call(node) === arrayTypeStr) {
82168              nodes.push.apply(nodes, node);
82169            } else {
82170              result.push(node);
82171            }
82172          } while (nodes.length && (node = nodes.pop()) !== undefined);
82173
82174          result.reverse(); // we reverse result to restore the original order
82175
82176          return result;
82177        } else {
82178          //otherwise if model within limits for browser
82179          //use faster recursive loading
82180          return [].concat.apply([], arr);
82181        }
82182      };
82183      /**
82184       * turn a p5.Vector Array into a one dimensional number array
82185       * @private
82186       * @param  {p5.Vector[]} arr  an array of p5.Vector
82187       * @return {Number[]}     a one dimensional array of numbers
82188       * [p5.Vector(1, 2, 3), p5.Vector(4, 5, 6)] ->
82189       * [1, 2, 3, 4, 5, 6]
82190       */
82191
82192
82193      p5.RendererGL.prototype._vToNArray = function (arr) {
82194        return this._flatten(arr.map(function (item) {
82195          return [item.x, item.y, item.z];
82196        }));
82197      };
82198      /**
82199       * ensures that p5 is using a 3d renderer. throws an error if not.
82200       */
82201
82202
82203      p5.prototype._assert3d = function (name) {
82204        if (!this._renderer.isP3D) throw new Error(name + "() is only supported in WEBGL mode. If you'd like to use 3D graphics" + ' and WebGL, see  https://p5js.org/examples/form-3d-primitives.html' + ' for more information.');
82205      }; // function to initialize GLU Tesselator
82206
82207
82208      p5.RendererGL.prototype._initTessy = function initTesselator() {
82209        // function called for each vertex of tesselator output
82210        function vertexCallback(data, polyVertArray) {
82211          polyVertArray[polyVertArray.length] = data[0];
82212          polyVertArray[polyVertArray.length] = data[1];
82213          polyVertArray[polyVertArray.length] = data[2];
82214        }
82215
82216        function begincallback(type) {
82217          if (type !== libtess.primitiveType.GL_TRIANGLES) {
82218            console.log('expected TRIANGLES but got type: ' + type);
82219          }
82220        }
82221
82222        function errorcallback(errno) {
82223          console.log('error callback');
82224          console.log('error number: ' + errno);
82225        } // callback for when segments intersect and must be split
82226
82227
82228        function combinecallback(coords, data, weight) {
82229          return [coords[0], coords[1], coords[2]];
82230        }
82231
82232        function edgeCallback(flag) {// don't really care about the flag, but need no-strip/no-fan behavior
82233        }
82234
82235        var tessy = new libtess.GluTesselator();
82236        tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_VERTEX_DATA, vertexCallback);
82237        tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_BEGIN, begincallback);
82238        tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_ERROR, errorcallback);
82239        tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_COMBINE, combinecallback);
82240        tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_EDGE_FLAG, edgeCallback);
82241        return tessy;
82242      };
82243
82244      p5.RendererGL.prototype._triangulate = function (contours) {
82245        // libtess will take 3d verts and flatten to a plane for tesselation
82246        // since only doing 2d tesselation here, provide z=1 normal to skip
82247        // iterating over verts only to get the same answer.
82248        // comment out to test normal-generation code
82249        this._tessy.gluTessNormal(0, 0, 1);
82250
82251        var triangleVerts = [];
82252
82253        this._tessy.gluTessBeginPolygon(triangleVerts);
82254
82255        for (var i = 0; i < contours.length; i++) {
82256          this._tessy.gluTessBeginContour();
82257
82258          var contour = contours[i];
82259
82260          for (var j = 0; j < contour.length; j += 3) {
82261            var coords = [contour[j], contour[j + 1], contour[j + 2]];
82262
82263            this._tessy.gluTessVertex(coords, coords);
82264          }
82265
82266          this._tessy.gluTessEndContour();
82267        } // finish polygon
82268
82269
82270        this._tessy.gluTessEndPolygon();
82271
82272        return triangleVerts;
82273      }; // function to calculate BezierVertex Coefficients
82274
82275
82276      p5.RendererGL.prototype._bezierCoefficients = function (t) {
82277        var t2 = t * t;
82278        var t3 = t2 * t;
82279        var mt = 1 - t;
82280        var mt2 = mt * mt;
82281        var mt3 = mt2 * mt;
82282        return [mt3, 3 * mt2 * t, 3 * mt * t2, t3];
82283      }; // function to calculate QuadraticVertex Coefficients
82284
82285
82286      p5.RendererGL.prototype._quadraticCoefficients = function (t) {
82287        var t2 = t * t;
82288        var mt = 1 - t;
82289        var mt2 = mt * mt;
82290        return [mt2, 2 * mt * t, t2];
82291      }; // function to convert Bezier coordinates to Catmull Rom Splines
82292
82293
82294      p5.RendererGL.prototype._bezierToCatmull = function (w) {
82295        var p1 = w[1];
82296        var p2 = w[1] + (w[2] - w[0]) / this._curveTightness;
82297        var p3 = w[2] - (w[3] - w[1]) / this._curveTightness;
82298        var p4 = w[2];
82299        var p = [p1, p2, p3, p4];
82300        return p;
82301      };
82302
82303      module.exports = p5.RendererGL;
82304    }, {
82305      "../core/constants": 18,
82306      "../core/main": 24,
82307      "../core/p5.Renderer": 27,
82308      "./p5.Camera": 69,
82309      "./p5.Matrix": 71,
82310      "./p5.Shader": 75,
82311      "libtess": 9
82312    }],
82313    75: [function (_dereq_, module, exports) {
82314      /**
82315       * This module defines the p5.Shader class
82316       * @module Lights, Camera
82317       * @submodule Shaders
82318       * @for p5
82319       * @requires core
82320       */
82321      'use strict';
82322
82323      var p5 = _dereq_('../core/main');
82324      /**
82325       * Shader class for WEBGL Mode
82326       * @class p5.Shader
82327       * @param {p5.RendererGL} renderer an instance of p5.RendererGL that
82328       * will provide the GL context for this new p5.Shader
82329       * @param {String} vertSrc source code for the vertex shader (as a string)
82330       * @param {String} fragSrc source code for the fragment shader (as a string)
82331       */
82332
82333
82334      p5.Shader = function (renderer, vertSrc, fragSrc) {
82335        // TODO: adapt this to not take ids, but rather,
82336        // to take the source for a vertex and fragment shader
82337        // to enable custom shaders at some later date
82338        this._renderer = renderer;
82339        this._vertSrc = vertSrc;
82340        this._fragSrc = fragSrc;
82341        this._vertShader = -1;
82342        this._fragShader = -1;
82343        this._glProgram = 0;
82344        this._loadedAttributes = false;
82345        this.attributes = {};
82346        this._loadedUniforms = false;
82347        this.uniforms = {};
82348        this._bound = false;
82349        this.samplers = [];
82350      };
82351      /**
82352       * Creates, compiles, and links the shader based on its
82353       * sources for the vertex and fragment shaders (provided
82354       * to the constructor). Populates known attributes and
82355       * uniforms from the shader.
82356       * @method init
82357       * @chainable
82358       * @private
82359       */
82360
82361
82362      p5.Shader.prototype.init = function () {
82363        if (this._glProgram === 0
82364        /* or context is stale? */
82365        ) {
82366            var gl = this._renderer.GL; // @todo: once custom shading is allowed,
82367            // friendly error messages should be used here to share
82368            // compiler and linker errors.
82369            //set up the shader by
82370            // 1. creating and getting a gl id for the shader program,
82371            // 2. compliling its vertex & fragment sources,
82372            // 3. linking the vertex and fragment shaders
82373
82374            this._vertShader = gl.createShader(gl.VERTEX_SHADER); //load in our default vertex shader
82375
82376            gl.shaderSource(this._vertShader, this._vertSrc);
82377            gl.compileShader(this._vertShader); // if our vertex shader failed compilation?
82378
82379            if (!gl.getShaderParameter(this._vertShader, gl.COMPILE_STATUS)) {
82380              console.error('Yikes! An error occurred compiling the vertex shader:' + gl.getShaderInfoLog(this._vertShader));
82381              return null;
82382            }
82383
82384            this._fragShader = gl.createShader(gl.FRAGMENT_SHADER); //load in our material frag shader
82385
82386            gl.shaderSource(this._fragShader, this._fragSrc);
82387            gl.compileShader(this._fragShader); // if our frag shader failed compilation?
82388
82389            if (!gl.getShaderParameter(this._fragShader, gl.COMPILE_STATUS)) {
82390              console.error('Darn! An error occurred compiling the fragment shader:' + gl.getShaderInfoLog(this._fragShader));
82391              return null;
82392            }
82393
82394            this._glProgram = gl.createProgram();
82395            gl.attachShader(this._glProgram, this._vertShader);
82396            gl.attachShader(this._glProgram, this._fragShader);
82397            gl.linkProgram(this._glProgram);
82398
82399            if (!gl.getProgramParameter(this._glProgram, gl.LINK_STATUS)) {
82400              console.error('Snap! Error linking shader program: ' + gl.getProgramInfoLog(this._glProgram));
82401            }
82402
82403            this._loadAttributes();
82404
82405            this._loadUniforms();
82406          }
82407
82408        return this;
82409      };
82410      /**
82411       * Queries the active attributes for this shader and loads
82412       * their names and locations into the attributes array.
82413       * @method _loadAttributes
82414       * @private
82415       */
82416
82417
82418      p5.Shader.prototype._loadAttributes = function () {
82419        if (this._loadedAttributes) {
82420          return;
82421        }
82422
82423        this.attributes = {};
82424        var gl = this._renderer.GL;
82425        var numAttributes = gl.getProgramParameter(this._glProgram, gl.ACTIVE_ATTRIBUTES);
82426
82427        for (var i = 0; i < numAttributes; ++i) {
82428          var attributeInfo = gl.getActiveAttrib(this._glProgram, i);
82429          var name = attributeInfo.name;
82430          var location = gl.getAttribLocation(this._glProgram, name);
82431          var attribute = {};
82432          attribute.name = name;
82433          attribute.location = location;
82434          attribute.type = attributeInfo.type;
82435          attribute.size = attributeInfo.size;
82436          this.attributes[name] = attribute;
82437        }
82438
82439        this._loadedAttributes = true;
82440      };
82441      /**
82442       * Queries the active uniforms for this shader and loads
82443       * their names and locations into the uniforms array.
82444       * @method _loadUniforms
82445       * @private
82446       */
82447
82448
82449      p5.Shader.prototype._loadUniforms = function () {
82450        if (this._loadedUniforms) {
82451          return;
82452        }
82453
82454        var gl = this._renderer.GL; // Inspect shader and cache uniform info
82455
82456        var numUniforms = gl.getProgramParameter(this._glProgram, gl.ACTIVE_UNIFORMS);
82457        var samplerIndex = 0;
82458
82459        for (var i = 0; i < numUniforms; ++i) {
82460          var uniformInfo = gl.getActiveUniform(this._glProgram, i);
82461          var uniform = {};
82462          uniform.location = gl.getUniformLocation(this._glProgram, uniformInfo.name);
82463          uniform.size = uniformInfo.size;
82464          var uniformName = uniformInfo.name; //uniforms thats are arrays have their name returned as
82465          //someUniform[0] which is a bit silly so we trim it
82466          //off here. The size property tells us that its an array
82467          //so we dont lose any information by doing this
82468
82469          if (uniformInfo.size > 1) {
82470            uniformName = uniformName.substring(0, uniformName.indexOf('[0]'));
82471          }
82472
82473          uniform.name = uniformName;
82474          uniform.type = uniformInfo.type;
82475
82476          if (uniform.type === gl.SAMPLER_2D) {
82477            uniform.samplerIndex = samplerIndex;
82478            samplerIndex++;
82479            this.samplers.push(uniform);
82480          }
82481
82482          this.uniforms[uniformName] = uniform;
82483        }
82484
82485        this._loadedUniforms = true;
82486      };
82487
82488      p5.Shader.prototype.compile = function () {// TODO
82489      };
82490      /**
82491       * initializes (if needed) and binds the shader program.
82492       * @method bindShader
82493       * @private
82494       */
82495
82496
82497      p5.Shader.prototype.bindShader = function () {
82498        this.init();
82499
82500        if (!this._bound) {
82501          this.useProgram();
82502          this._bound = true;
82503          this.bindTextures();
82504
82505          this._setMatrixUniforms();
82506
82507          if (this === this._renderer.curStrokeShader) {
82508            this._setViewportUniform();
82509          }
82510        }
82511      };
82512      /**
82513       * @method unbindShader
82514       * @chainable
82515       * @private
82516       */
82517
82518
82519      p5.Shader.prototype.unbindShader = function () {
82520        if (this._bound) {
82521          this.unbindTextures(); //this._renderer.GL.useProgram(0); ??
82522
82523          this._bound = false;
82524        }
82525
82526        return this;
82527      };
82528
82529      p5.Shader.prototype.bindTextures = function () {
82530        var gl = this._renderer.GL;
82531
82532        for (var i = 0; i < this.samplers.length; i++) {
82533          var uniform = this.samplers[i];
82534          var tex = uniform.texture;
82535
82536          if (tex === undefined) {
82537            // user hasn't yet supplied a texture for this slot.
82538            // (or there may not be one--maybe just lighting),
82539            // so we supply a default texture instead.
82540            tex = this._renderer._getEmptyTexture();
82541          }
82542
82543          gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex);
82544          tex.bindTexture();
82545          tex.update();
82546          gl.uniform1i(uniform.location, uniform.samplerIndex);
82547        }
82548      };
82549
82550      p5.Shader.prototype.updateTextures = function () {
82551        for (var i = 0; i < this.samplers.length; i++) {
82552          var uniform = this.samplers[i];
82553          var tex = uniform.texture;
82554
82555          if (tex) {
82556            tex.update();
82557          }
82558        }
82559      };
82560
82561      p5.Shader.prototype.unbindTextures = function () {// TODO: migrate stuff from material.js here
82562        // - OR - have material.js define this function
82563      };
82564
82565      p5.Shader.prototype._setMatrixUniforms = function () {
82566        this.setUniform('uProjectionMatrix', this._renderer.uPMatrix.mat4);
82567        this.setUniform('uModelViewMatrix', this._renderer.uMVMatrix.mat4);
82568        this.setUniform('uViewMatrix', this._renderer._curCamera.cameraMatrix.mat4);
82569
82570        if (this === this._renderer.curFillShader) {
82571          this._renderer.uNMatrix.inverseTranspose(this._renderer.uMVMatrix);
82572
82573          this.setUniform('uNormalMatrix', this._renderer.uNMatrix.mat3);
82574        }
82575      };
82576
82577      p5.Shader.prototype._setViewportUniform = function () {
82578        this.setUniform('uViewport', this._renderer._viewport);
82579      };
82580      /**
82581       * @method useProgram
82582       * @chainable
82583       * @private
82584       */
82585
82586
82587      p5.Shader.prototype.useProgram = function () {
82588        var gl = this._renderer.GL;
82589        gl.useProgram(this._glProgram);
82590        return this;
82591      };
82592      /**
82593       * Wrapper around gl.uniform functions.
82594       * As we store uniform info in the shader we can use that
82595       * to do type checking on the supplied data and call
82596       * the appropriate function.
82597       * @method setUniform
82598       * @chainable
82599       * @param {String} uniformName the name of the uniform in the
82600       * shader program
82601       * @param {Object|Number|Boolean|Number[]} data the data to be associated
82602       * with that uniform; type varies (could be a single numerical value, array,
82603       * matrix, or texture / sampler reference)
82604       */
82605
82606
82607      p5.Shader.prototype.setUniform = function (uniformName, data) {
82608        //@todo update all current gl.uniformXX calls
82609        var uniform = this.uniforms[uniformName];
82610
82611        if (!uniform) {
82612          //@todo warning?
82613          return;
82614        }
82615
82616        var location = uniform.location;
82617        var gl = this._renderer.GL; // todo: is this safe to do here?
82618        // todo: store the values another way?
82619
82620        this.useProgram(); // TODO BIND?
82621
82622        switch (uniform.type) {
82623          case gl.BOOL:
82624            if (data === true) {
82625              gl.uniform1i(location, 1);
82626            } else {
82627              gl.uniform1i(location, 0);
82628            }
82629
82630            break;
82631
82632          case gl.INT:
82633            if (uniform.size > 1) {
82634              data.length && gl.uniform1iv(location, data);
82635            } else {
82636              gl.uniform1i(location, data);
82637            }
82638
82639            break;
82640
82641          case gl.FLOAT:
82642            if (uniform.size > 1) {
82643              data.length && gl.uniform1fv(location, data);
82644            } else {
82645              gl.uniform1f(location, data);
82646            }
82647
82648            break;
82649
82650          case gl.FLOAT_MAT3:
82651            gl.uniformMatrix3fv(location, false, data);
82652            break;
82653
82654          case gl.FLOAT_MAT4:
82655            gl.uniformMatrix4fv(location, false, data);
82656            break;
82657
82658          case gl.FLOAT_VEC2:
82659            if (uniform.size > 1) {
82660              data.length && gl.uniform2fv(location, data);
82661            } else {
82662              gl.uniform2f(location, data[0], data[1]);
82663            }
82664
82665            break;
82666
82667          case gl.FLOAT_VEC3:
82668            if (uniform.size > 1) {
82669              data.length && gl.uniform3fv(location, data);
82670            } else {
82671              gl.uniform3f(location, data[0], data[1], data[2]);
82672            }
82673
82674            break;
82675
82676          case gl.FLOAT_VEC4:
82677            if (uniform.size > 1) {
82678              data.length && gl.uniform4fv(location, data);
82679            } else {
82680              gl.uniform4f(location, data[0], data[1], data[2], data[3]);
82681            }
82682
82683            break;
82684
82685          case gl.INT_VEC2:
82686            if (uniform.size > 1) {
82687              data.length && gl.uniform2iv(location, data);
82688            } else {
82689              gl.uniform2i(location, data[0], data[1]);
82690            }
82691
82692            break;
82693
82694          case gl.INT_VEC3:
82695            if (uniform.size > 1) {
82696              data.length && gl.uniform3iv(location, data);
82697            } else {
82698              gl.uniform3i(location, data[0], data[1], data[2]);
82699            }
82700
82701            break;
82702
82703          case gl.INT_VEC4:
82704            if (uniform.size > 1) {
82705              data.length && gl.uniform4iv(location, data);
82706            } else {
82707              gl.uniform4i(location, data[0], data[1], data[2], data[3]);
82708            }
82709
82710            break;
82711
82712          case gl.SAMPLER_2D:
82713            gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex);
82714            uniform.texture = this._renderer.getTexture(data);
82715            gl.uniform1i(uniform.location, uniform.samplerIndex);
82716            break;
82717          //@todo complete all types
82718        }
82719
82720        return this;
82721      };
82722      /* NONE OF THIS IS FAST OR EFFICIENT BUT BEAR WITH ME
82723       *
82724       * these shader "type" query methods are used by various
82725       * facilities of the renderer to determine if changing
82726       * the shader type for the required action (for example,
82727       * do we need to load the default lighting shader if the
82728       * current shader cannot handle lighting?)
82729       *
82730       **/
82731
82732
82733      p5.Shader.prototype.isLightShader = function () {
82734        return this.uniforms.uUseLighting !== undefined || this.uniforms.uAmbientLightCount !== undefined || this.uniforms.uDirectionalLightCount !== undefined || this.uniforms.uPointLightCount !== undefined || this.uniforms.uAmbientColor !== undefined || this.uniforms.uDirectionalColor !== undefined || this.uniforms.uPointLightLocation !== undefined || this.uniforms.uPointLightColor !== undefined || this.uniforms.uLightingDirection !== undefined || this.uniforms.uSpecular !== undefined;
82735      };
82736
82737      p5.Shader.prototype.isTextureShader = function () {
82738        return this.samplerIndex > 0;
82739      };
82740
82741      p5.Shader.prototype.isColorShader = function () {
82742        return this.attributes.aVertexColor !== undefined || this.uniforms.uMaterialColor !== undefined;
82743      };
82744
82745      p5.Shader.prototype.isTexLightShader = function () {
82746        return this.isLightShader() && this.isTextureShader();
82747      };
82748
82749      p5.Shader.prototype.isStrokeShader = function () {
82750        return this.uniforms.uStrokeWeight !== undefined;
82751      };
82752      /**
82753       * @method enableAttrib
82754       * @chainable
82755       * @private
82756       */
82757
82758
82759      p5.Shader.prototype.enableAttrib = function (loc, size, type, normalized, stride, offset) {
82760        var gl = this._renderer.GL;
82761
82762        if (loc !== -1) {
82763          gl.enableVertexAttribArray(loc);
82764          gl.vertexAttribPointer(loc, size, type, normalized, stride, offset);
82765        }
82766
82767        return this;
82768      };
82769
82770      module.exports = p5.Shader;
82771    }, {
82772      "../core/main": 24
82773    }],
82774    76: [function (_dereq_, module, exports) {
82775      /**
82776       * This module defines the p5.Texture class
82777       * @module Lights, Camera
82778       * @submodule Material
82779       * @for p5
82780       * @requires core
82781       */
82782      'use strict';
82783
82784      var p5 = _dereq_('../core/main');
82785
82786      var constants = _dereq_('../core/constants');
82787      /**
82788       * Texture class for WEBGL Mode
82789       * @private
82790       * @class p5.Texture
82791       * @param {p5.RendererGL} renderer an instance of p5.RendererGL that
82792       * will provide the GL context for this new p5.Texture
82793       * @param {p5.Image|p5.Graphics|p5.Element|p5.MediaElement|ImageData} [obj] the
82794       * object containing the image data to store in the texture.
82795       */
82796
82797
82798      p5.Texture = function (renderer, obj) {
82799        this._renderer = renderer;
82800        var gl = this._renderer.GL;
82801        this.src = obj;
82802        this.glTex = undefined;
82803        this.glTarget = gl.TEXTURE_2D;
82804        this.glFormat = gl.RGBA;
82805        this.mipmaps = false;
82806        this.glMinFilter = gl.LINEAR;
82807        this.glMagFilter = gl.LINEAR;
82808        this.glWrapS = gl.CLAMP_TO_EDGE;
82809        this.glWrapT = gl.CLAMP_TO_EDGE; // used to determine if this texture might need constant updating
82810        // because it is a video or gif.
82811
82812        this.isSrcMediaElement = typeof p5.MediaElement !== 'undefined' && obj instanceof p5.MediaElement;
82813        this._videoPrevUpdateTime = 0;
82814        this.isSrcHTMLElement = typeof p5.Element !== 'undefined' && obj instanceof p5.Element && !(obj instanceof p5.Graphics);
82815        this.isSrcP5Image = obj instanceof p5.Image;
82816        this.isSrcP5Graphics = obj instanceof p5.Graphics;
82817        this.isImageData = typeof ImageData !== 'undefined' && obj instanceof ImageData;
82818
82819        var textureData = this._getTextureDataFromSource();
82820
82821        this.width = textureData.width;
82822        this.height = textureData.height;
82823        this.init(textureData);
82824        return this;
82825      };
82826
82827      p5.Texture.prototype._getTextureDataFromSource = function () {
82828        var textureData;
82829
82830        if (this.isSrcP5Image) {
82831          // param is a p5.Image
82832          textureData = this.src.canvas;
82833        } else if (this.isSrcMediaElement || this.isSrcP5Graphics || this.isSrcHTMLElement) {
82834          // if param is a video HTML element
82835          textureData = this.src.elt;
82836        } else if (this.isImageData) {
82837          textureData = this.src;
82838        }
82839
82840        return textureData;
82841      };
82842      /**
82843       * Initializes common texture parameters, creates a gl texture,
82844       * tries to upload the texture for the first time if data is
82845       * already available.
82846       * @private
82847       * @method init
82848       */
82849
82850
82851      p5.Texture.prototype.init = function (data) {
82852        var gl = this._renderer.GL;
82853        this.glTex = gl.createTexture();
82854        this.bindTexture(); //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
82855
82856        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.glMagFilter);
82857        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.glMinFilter);
82858        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.glWrapS);
82859        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.glWrapT);
82860
82861        if (this.width === 0 || this.height === 0 || this.isSrcMediaElement && !this.src.loadedmetadata) {
82862          // assign a 1x1 empty texture initially, because data is not yet ready,
82863          // so that no errors occur in gl console!
82864          var tmpdata = new Uint8Array([1, 1, 1, 1]);
82865          gl.texImage2D(this.glTarget, 0, gl.RGBA, 1, 1, 0, this.glFormat, gl.UNSIGNED_BYTE, tmpdata);
82866        } else {
82867          // data is ready: just push the texture!
82868          gl.texImage2D(this.glTarget, 0, this.glFormat, this.glFormat, gl.UNSIGNED_BYTE, data);
82869        }
82870      };
82871      /**
82872       * Checks if the source data for this texture has changed (if it's
82873       * easy to do so) and reuploads the texture if necessary. If it's not
82874       * possible or to expensive to do a calculation to determine wheter or
82875       * not the data has occurred, this method simply re-uploads the texture.
82876       * @method update
82877       */
82878
82879
82880      p5.Texture.prototype.update = function () {
82881        var data = this.src;
82882
82883        if (data.width === 0 || data.height === 0) {
82884          return false; // nothing to do!
82885        }
82886
82887        var textureData = this._getTextureDataFromSource();
82888
82889        var updated = false;
82890        var gl = this._renderer.GL; // pull texture from data, make sure width & height are appropriate
82891
82892        if (textureData.width !== this.width || textureData.height !== this.height) {
82893          updated = true; // make sure that if the width and height of this.src have changed
82894          // for some reason, we update our metadata and upload the texture again
82895
82896          this.width = textureData.width;
82897          this.height = textureData.height;
82898
82899          if (this.isSrcP5Image) {
82900            data.setModified(false);
82901          } else if (this.isSrcMediaElement || this.isSrcHTMLElement) {
82902            // on the first frame the metadata comes in, the size will be changed
82903            // from 0 to actual size, but pixels may not be available.
82904            // flag for update in a future frame.
82905            // if we don't do this, a paused video, for example, may not
82906            // send the first frame to texture memory.
82907            data.setModified(true);
82908          }
82909        } else if (this.isSrcP5Image) {
82910          // for an image, we only update if the modified field has been set,
82911          // for example, by a call to p5.Image.set
82912          if (data.isModified()) {
82913            updated = true;
82914            data.setModified(false);
82915          }
82916        } else if (this.isSrcMediaElement) {
82917          // for a media element (video), we'll check if the current time in
82918          // the video frame matches the last time. if it doesn't match, the
82919          // video has advanced or otherwise been taken to a new frame,
82920          // and we need to upload it.
82921          if (data.isModified()) {
82922            // p5.MediaElement may have also had set/updatePixels, etc. called
82923            // on it and should be updated, or may have been set for the first
82924            // time!
82925            updated = true;
82926            data.setModified(false);
82927          } else if (data.loadedmetadata) {
82928            // if the meta data has been loaded, we can ask the video
82929            // what it's current position (in time) is.
82930            if (this._videoPrevUpdateTime !== data.time()) {
82931              // update the texture in gpu mem only if the current
82932              // video timestamp does not match the timestamp of the last
82933              // time we uploaded this texture (and update the time we
82934              // last uploaded, too)
82935              this._videoPrevUpdateTime = data.time();
82936              updated = true;
82937            }
82938          }
82939        } else if (this.isImageData) {
82940          if (data._dirty) {
82941            data._dirty = false;
82942            updated = true;
82943          }
82944        } else {
82945          /* data instanceof p5.Graphics, probably */
82946          // there is not enough information to tell if the texture can be
82947          // conditionally updated; so to be safe, we just go ahead and upload it.
82948          updated = true;
82949        }
82950
82951        if (updated) {
82952          this.bindTexture();
82953          gl.texImage2D(this.glTarget, 0, this.glFormat, this.glFormat, gl.UNSIGNED_BYTE, textureData);
82954        }
82955
82956        return updated;
82957      };
82958      /**
82959       * Binds the texture to the appropriate GL target.
82960       * @method bindTexture
82961       */
82962
82963
82964      p5.Texture.prototype.bindTexture = function () {
82965        // bind texture using gl context + glTarget and
82966        // generated gl texture object
82967        var gl = this._renderer.GL;
82968        gl.bindTexture(this.glTarget, this.glTex);
82969        return this;
82970      };
82971      /**
82972       * Unbinds the texture from the appropriate GL target.
82973       * @method unbindTexture
82974       */
82975
82976
82977      p5.Texture.prototype.unbindTexture = function () {
82978        // unbind per above, disable texturing on glTarget
82979        var gl = this._renderer.GL;
82980        gl.bindTexture(this.glTarget, null);
82981      };
82982      /**
82983       * Sets how a texture is be interpolated when upscaled or downscaled.
82984       * Nearest filtering uses nearest neighbor scaling when interpolating
82985       * Linear filtering uses WebGL's linear scaling when interpolating
82986       * @method setInterpolation
82987       * @param {String} downScale Specifies the texture filtering when
82988       *                           textures are shrunk. Options are LINEAR or NEAREST
82989       * @param {String} upScale Specifies the texture filtering when
82990       *                         textures are magnified. Options are LINEAR or NEAREST
82991       * @todo implement mipmapping filters
82992       */
82993
82994
82995      p5.Texture.prototype.setInterpolation = function (downScale, upScale) {
82996        var gl = this._renderer.GL;
82997
82998        if (downScale === constants.NEAREST) {
82999          this.glMinFilter = gl.NEAREST;
83000        } else {
83001          this.glMinFilter = gl.LINEAR;
83002        }
83003
83004        if (upScale === constants.NEAREST) {
83005          this.glMagFilter = gl.NEAREST;
83006        } else {
83007          this.glMagFilter = gl.LINEAR;
83008        }
83009
83010        this.bindTexture();
83011        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.glMinFilter);
83012        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.glMagFilter);
83013        this.unbindTexture();
83014      };
83015      /**
83016       * Sets the texture wrapping mode. This controls how textures behave
83017       * when their uv's go outside of the 0 - 1 range. There are three options:
83018       * CLAMP, REPEAT, and MIRROR. REPEAT & MIRROR are only available if the texture
83019       * is a power of two size (128, 256, 512, 1024, etc.).
83020       * @method setWrapMode
83021       * @param {String} wrapX Controls the horizontal texture wrapping behavior
83022       * @param {String} wrapY Controls the vertical texture wrapping behavior
83023       */
83024
83025
83026      p5.Texture.prototype.setWrapMode = function (wrapX, wrapY) {
83027        var gl = this._renderer.GL; // for webgl 1 we need to check if the texture is power of two
83028        // if it isn't we will set the wrap mode to CLAMP
83029        // webgl2 will support npot REPEAT and MIRROR but we don't check for it yet
83030
83031        var isPowerOfTwo = function (x) {
83032          return (x & x - 1) === 0;
83033        };
83034
83035        var widthPowerOfTwo = isPowerOfTwo(this.width);
83036        var heightPowerOfTwo = isPowerOfTwo(this.width);
83037
83038        if (wrapX === constants.REPEAT) {
83039          if (widthPowerOfTwo && heightPowerOfTwo) {
83040            this.glWrapS = gl.REPEAT;
83041          } else {
83042            console.warn('You tried to set the wrap mode to REPEAT but the texture size is not a power of two. Setting to CLAMP instead');
83043            this.glWrapS = gl.CLAMP_TO_EDGE;
83044          }
83045        } else if (wrapX === constants.MIRROR) {
83046          if (widthPowerOfTwo && heightPowerOfTwo) {
83047            this.glWrapS = gl.MIRRORED_REPEAT;
83048          } else {
83049            console.warn('You tried to set the wrap mode to MIRROR but the texture size is not a power of two. Setting to CLAMP instead');
83050            this.glWrapS = gl.CLAMP_TO_EDGE;
83051          }
83052        } else {
83053          // falling back to default if didn't get a proper mode
83054          this.glWrapS = gl.CLAMP_TO_EDGE;
83055        }
83056
83057        if (wrapY === constants.REPEAT) {
83058          if (widthPowerOfTwo && heightPowerOfTwo) {
83059            this.glWrapT = gl.REPEAT;
83060          } else {
83061            console.warn('You tried to set the wrap mode to REPEAT but the texture size is not a power of two. Setting to CLAMP instead');
83062            this.glWrapT = gl.CLAMP_TO_EDGE;
83063          }
83064        } else if (wrapY === constants.MIRROR) {
83065          if (widthPowerOfTwo && heightPowerOfTwo) {
83066            this.glWrapT = gl.MIRRORED_REPEAT;
83067          } else {
83068            console.warn('You tried to set the wrap mode to MIRROR but the texture size is not a power of two. Setting to CLAMP instead');
83069            this.glWrapT = gl.CLAMP_TO_EDGE;
83070          }
83071        } else {
83072          // falling back to default if didn't get a proper mode
83073          this.glWrapT = gl.CLAMP_TO_EDGE;
83074        }
83075
83076        this.bindTexture();
83077        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.glWrapS);
83078        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.glWrapT);
83079        this.unbindTexture();
83080      };
83081
83082      module.exports = p5.Texture;
83083    }, {
83084      "../core/constants": 18,
83085      "../core/main": 24
83086    }],
83087    77: [function (_dereq_, module, exports) {
83088      'use strict';
83089
83090      var p5 = _dereq_('../core/main');
83091
83092      var constants = _dereq_('../core/constants');
83093
83094      _dereq_('./p5.Shader');
83095
83096      _dereq_('./p5.RendererGL'); // Text/Typography
83097      // @TODO:
83098
83099
83100      p5.RendererGL.prototype._applyTextProperties = function () {//@TODO finish implementation
83101        //console.error('text commands not yet implemented in webgl');
83102      };
83103
83104      p5.RendererGL.prototype.textWidth = function (s) {
83105        if (this._isOpenType()) {
83106          return this._textFont._textWidth(s, this._textSize);
83107        }
83108
83109        return 0; // TODO: error
83110      }; // rendering constants
83111      // the number of rows/columns dividing each glyph
83112
83113
83114      var charGridWidth = 9;
83115      var charGridHeight = charGridWidth; // size of the image holding the bezier stroke info
83116
83117      var strokeImageWidth = 64;
83118      var strokeImageHeight = 64; // size of the image holding the stroke indices for each row/col
83119
83120      var gridImageWidth = 64;
83121      var gridImageHeight = 64; // size of the image holding the offset/length of each row/col stripe
83122
83123      var cellImageWidth = 64;
83124      var cellImageHeight = 64;
83125      /**
83126       * @private
83127       * @class ImageInfos
83128       * @param {Integer} width
83129       * @param {Integer} height
83130       *
83131       * the ImageInfos class holds a list of ImageDatas of a given size.
83132       */
83133
83134      function ImageInfos(width, height) {
83135        this.width = width;
83136        this.height = height;
83137        this.infos = []; // the list of images
83138
83139        /**
83140         *
83141         * @method findImage
83142         * @param {Integer} space
83143         * @return {Object} contains the ImageData, and pixel index into that
83144         *                  ImageData where the free space was allocated.
83145         *
83146         * finds free space of a given size in the ImageData list
83147         */
83148
83149        this.findImage = function (space) {
83150          var imageSize = this.width * this.height;
83151          if (space > imageSize) throw new Error('font is too complex to render in 3D'); // search through the list of images, looking for one with
83152          // anough unused space.
83153
83154          var imageInfo, imageData;
83155
83156          for (var ii = this.infos.length - 1; ii >= 0; --ii) {
83157            var imageInfoTest = this.infos[ii];
83158
83159            if (imageInfoTest.index + space < imageSize) {
83160              // found one
83161              imageInfo = imageInfoTest;
83162              imageData = imageInfoTest.imageData;
83163              break;
83164            }
83165          }
83166
83167          if (!imageInfo) {
83168            try {
83169              // create a new image
83170              imageData = new ImageData(this.width, this.height);
83171            } catch (err) {
83172              // for browsers that don't support ImageData constructors (ie IE11)
83173              // create an ImageData using the old method
83174              var canvas = document.getElementsByTagName('canvas')[0];
83175              var created = !canvas;
83176
83177              if (!canvas) {
83178                // create a temporary canvas
83179                canvas = document.createElement('canvas');
83180                canvas.style.display = 'none';
83181                document.body.appendChild(canvas);
83182              }
83183
83184              var ctx = canvas.getContext('2d');
83185
83186              if (ctx) {
83187                imageData = ctx.createImageData(this.width, this.height);
83188              }
83189
83190              if (created) {
83191                // distroy the temporary canvas, if necessary
83192                document.body.removeChild(canvas);
83193              }
83194            } // construct & dd the new image info
83195
83196
83197            imageInfo = {
83198              index: 0,
83199              imageData: imageData
83200            };
83201            this.infos.push(imageInfo);
83202          }
83203
83204          var index = imageInfo.index;
83205          imageInfo.index += space; // move to the start of the next image
83206
83207          imageData._dirty = true;
83208          return {
83209            imageData: imageData,
83210            index: index
83211          };
83212        };
83213      }
83214      /**
83215       * @function setPixel
83216       * @param {Object} imageInfo
83217       * @param {Number} r
83218       * @param {Number} g
83219       * @param {Number} b
83220       * @param {Number} a
83221       *
83222       * writes the next pixel into an indexed ImageData
83223       */
83224
83225
83226      function setPixel(imageInfo, r, g, b, a) {
83227        var imageData = imageInfo.imageData;
83228        var pixels = imageData.data;
83229        var index = imageInfo.index++ * 4;
83230        pixels[index++] = r;
83231        pixels[index++] = g;
83232        pixels[index++] = b;
83233        pixels[index++] = a;
83234      }
83235
83236      var SQRT3 = Math.sqrt(3);
83237      /**
83238       * @private
83239       * @class FontInfo
83240       * @param {Object} font an opentype.js font object
83241       *
83242       * contains cached images and glyph information for an opentype font
83243       */
83244
83245      var FontInfo = function (font) {
83246        this.font = font; // the bezier curve coordinates
83247
83248        this.strokeImageInfos = new ImageInfos(strokeImageWidth, strokeImageHeight); // lists of curve indices for each row/column slice
83249
83250        this.colDimImageInfos = new ImageInfos(gridImageWidth, gridImageHeight);
83251        this.rowDimImageInfos = new ImageInfos(gridImageWidth, gridImageHeight); // the offset & length of each row/col slice in the glyph
83252
83253        this.colCellImageInfos = new ImageInfos(cellImageWidth, cellImageHeight);
83254        this.rowCellImageInfos = new ImageInfos(cellImageWidth, cellImageHeight); // the cached information for each glyph
83255
83256        this.glyphInfos = {};
83257        /**
83258         * @method getGlyphInfo
83259         * @param {Glyph} glyph the x positions of points in the curve
83260         * @returns {Object} the glyphInfo for that glyph
83261         *
83262         * calculates rendering info for a glyph, including the curve information,
83263         * row & column stripes compiled into textures.
83264         */
83265
83266        this.getGlyphInfo = function (glyph) {
83267          // check the cache
83268          var gi = this.glyphInfos[glyph.index];
83269          if (gi) return gi; // get the bounding box of the glyph from opentype.js
83270
83271          var bb = glyph.getBoundingBox();
83272          var xMin = bb.x1;
83273          var yMin = bb.y1;
83274          var gWidth = bb.x2 - xMin;
83275          var gHeight = bb.y2 - yMin;
83276          var cmds = glyph.path.commands; // don't bother rendering invisible glyphs
83277
83278          if (gWidth === 0 || gHeight === 0 || !cmds.length) {
83279            return this.glyphInfos[glyph.index] = {};
83280          }
83281
83282          var i;
83283          var strokes = []; // the strokes in this glyph
83284
83285          var rows = []; // the indices of strokes in each row
83286
83287          var cols = []; // the indices of strokes in each column
83288
83289          for (i = charGridWidth - 1; i >= 0; --i) cols.push([]);
83290
83291          for (i = charGridHeight - 1; i >= 0; --i) rows.push([]);
83292          /**
83293           * @function push
83294           * @param {Number[]} xs the x positions of points in the curve
83295           * @param {Number[]} ys the y positions of points in the curve
83296           * @param {Object} v    the curve information
83297           *
83298           * adds a curve to the rows & columns that it intersects with
83299           */
83300
83301
83302          function push(xs, ys, v) {
83303            var index = strokes.length; // the index of this stroke
83304
83305            strokes.push(v);
83305 // add this stroke to the list
83306
83307            /**
83308             * @function minMax
83309             * @param {Number[]} rg the list of values to compare
83310             * @param {Number} min the initial minimum value
83311             * @param {Number} max the initial maximum value
83312             *
83313             * find the minimum & maximum value in a list of values
83314             */
83315
83316            function minMax(rg, min, max) {
83317              for (var i = rg.length; i-- > 0;) {
83318                var v = rg[i];
83319                if (min > v) min = v;
83320                if (max < v) max = v;
83321              }
83322
83323              return {
83324                min: min,
83325                max: max
83326              };
83327            } // loop through the rows & columns that the curve intersects
83328            // adding the curve to those slices
83329
83330
83331            var mmX = minMax(xs, 1, 0);
83332            var ixMin = Math.max(Math.floor(mmX.min * charGridWidth), 0);
83333            var ixMax = Math.min(Math.ceil(mmX.max * charGridWidth), charGridWidth);
83334
83335            for (var iCol = ixMin; iCol < ixMax; ++iCol) cols[iCol].push(index);
83336
83337            var mmY = minMax(ys, 1, 0);
83338            var iyMin = Math.max(Math.floor(mmY.min * charGridHeight), 0);
83339            var iyMax = Math.min(Math.ceil(mmY.max * charGridHeight), charGridHeight);
83340
83341            for (var iRow = iyMin; iRow < iyMax; ++iRow) rows[iRow].push(index);
83342          }
83343          /**
83344           * @function clamp
83345           * @param {Number} v the value to clamp
83346           * @param {Number} min the minimum value
83347           * @param {Number} max the maxmimum value
83348           *
83349           * clamps a value between a minimum & maximum value
83350           */
83351
83352
83353          function clamp(v, min, max) {
83354            if (v < min) return min;
83355            if (v > max) return max;
83356            return v;
83357          }
83358          /**
83359           * @function byte
83360           * @param {Number} v the value to scale
83361           *
83362           * converts a floating-point number in the range 0-1 to a byte 0-255
83363           */
83364
83365
83366          function byte(v) {
83367            return clamp(255 * v, 0, 255);
83368          }
83369          /**
83370           * @private
83371           * @class Cubic
83372           * @param {Number} p0 the start point of the curve
83373           * @param {Number} c0 the first control point
83374           * @param {Number} c1 the second control point
83375           * @param {Number} p1 the end point
83376           *
83377           * a cubic curve
83378           */
83379
83380
83381          function Cubic(p0, c0, c1, p1) {
83382            this.p0 = p0;
83383            this.c0 = c0;
83384            this.c1 = c1;
83385            this.p1 = p1;
83386            /**
83387             * @method toQuadratic
83388             * @return {Object} the quadratic approximation
83389             *
83390             * converts the cubic to a quadtratic approximation by
83391             * picking an appropriate quadratic control point
83392             */
83393
83394            this.toQuadratic = function () {
83395              return {
83396                x: this.p0.x,
83397                y: this.p0.y,
83398                x1: this.p1.x,
83399                y1: this.p1.y,
83400                cx: ((this.c0.x + this.c1.x) * 3 - (this.p0.x + this.p1.x)) / 4,
83401                cy: ((this.c0.y + this.c1.y) * 3 - (this.p0.y + this.p1.y)) / 4
83402              };
83403            };
83404            /**
83405             * @method quadError
83406             * @return {Number} the error
83407             *
83408             * calculates the magnitude of error of this curve's
83409             * quadratic approximation.
83410             */
83411
83412
83413            this.quadError = function () {
83414              return p5.Vector.sub(p5.Vector.sub(this.p1, this.p0), p5.Vector.mult(p5.Vector.sub(this.c1, this.c0), 3)).mag() / 2;
83415            };
83416            /**
83417             * @method split
83418             * @param {Number} t the value (0-1) at which to split
83419             * @return {Cubic} the second part of the curve
83420             *
83421             * splits the cubic into two parts at a point 't' along the curve.
83422             * this cubic keeps its start point and its end point becomes the
83423             * point at 't'. the 'end half is returned.
83424             */
83425
83426
83427            this.split = function (t) {
83428              var m1 = p5.Vector.lerp(this.p0, this.c0, t);
83429              var m2 = p5.Vector.lerp(this.c0, this.c1, t);
83430              var mm1 = p5.Vector.lerp(m1, m2, t);
83431              this.c1 = p5.Vector.lerp(this.c1, this.p1, t);
83432              this.c0 = p5.Vector.lerp(m2, this.c1, t);
83433              var pt = p5.Vector.lerp(mm1, this.c0, t);
83434              var part1 = new Cubic(this.p0, m1, mm1, pt);
83435              this.p0 = pt;
83436              return part1;
83437            };
83438            /**
83439             * @method splitInflections
83440             * @return {Cubic[]} the non-inflecting pieces of this cubic
83441             *
83442             * returns an array containing 0, 1 or 2 cubics split resulting
83443             * from splitting this cubic at its inflection points.
83444             * this cubic is (potentially) altered and returned in the list.
83445             */
83446
83447
83448            this.splitInflections = function () {
83449              var a = p5.Vector.sub(this.c0, this.p0);
83450              var b = p5.Vector.sub(p5.Vector.sub(this.c1, this.c0), a);
83451              var c = p5.Vector.sub(p5.Vector.sub(p5.Vector.sub(this.p1, this.c1), a), p5.Vector.mult(b, 2));
83452              var cubics = []; // find the derivative coefficients
83453
83454              var A = b.x * c.y - b.y * c.x;
83455
83456              if (A !== 0) {
83457                var B = a.x * c.y - a.y * c.x;
83458                var C = a.x * b.y - a.y * b.x;
83459                var disc = B * B - 4 * A * C;
83460
83461                if (disc >= 0) {
83462                  if (A < 0) {
83463                    A = -A;
83464                    B = -B;
83465                    C = -C;
83466                  }
83467
83468                  var Q = Math.sqrt(disc);
83469                  var t0 = (-B - Q) / (2 * A); // the first inflection point
83470
83471                  var t1 = (-B + Q) / (2 * A); // the second inflection point
83472                  // test if the first inflection point lies on the curve
83473
83474                  if (t0 > 0 && t0 < 1) {
83475                    // split at the first inflection point
83476                    cubics.push(this.split(t0)); // scale t2 into the second part
83477
83478                    t1 = 1 - (1 - t1) / (1 - t0);
83479                  } // test if the second inflection point lies on the curve
83480
83481
83482                  if (t1 > 0 && t1 < 1) {
83483                    // split at the second inflection point
83484                    cubics.push(this.split(t1));
83485                  }
83486                }
83487              }
83488
83489              cubics.push(this);
83490              return cubics;
83491            };
83492          }
83493          /**
83494           * @function cubicToQuadratics
83495           * @param {Number} x0
83496           * @param {Number} y0
83497           * @param {Number} cx0
83498           * @param {Number} cy0
83499           * @param {Number} cx1
83500           * @param {Number} cy1
83501           * @param {Number} x1
83502           * @param {Number} y1
83503           * @returns {Cubic[]} an array of cubics whose quadratic approximations
83504           *                    closely match the civen cubic.
83505           *
83506           * converts a cubic curve to a list of quadratics.
83507           */
83508
83509
83510          function cubicToQuadratics(x0, y0, cx0, cy0, cx1, cy1, x1, y1) {
83511            // create the Cubic object and split it at its inflections
83512            var cubics = new Cubic(new p5.Vector(x0, y0), new p5.Vector(cx0, cy0), new p5.Vector(cx1, cy1), new p5.Vector(x1, y1)).splitInflections();
83513            var qs = []; // the final list of quadratics
83514
83515            var precision = 30 / SQRT3; // for each of the non-inflected pieces of the original cubic
83516
83517            for (var i = 0; i < cubics.length; i++) {
83518              var cubic = cubics[i]; // the cubic is iteratively split in 3 pieces:
83519              // the first piece is accumulated in 'qs', the result.
83520              // the last piece is accumulated in 'tail', temporarily.
83521              // the middle piece is repeatedly split again, while necessary.
83522
83523              var tail = [];
83524              var t3;
83525
83526              for (;;) {
83527                // calculate this cubic's precision
83528                t3 = precision / cubic.quadError();
83529
83530                if (t3 >= 0.5 * 0.5 * 0.5) {
83531                  break; // not too bad, we're done
83532                } // find a split point based on the error
83533
83534
83535                var t = Math.pow(t3, 1.0 / 3.0); // split the cubic in 3
83536
83537                var start = cubic.split(t);
83538                var middle = cubic.split(1 - t / (1 - t));
83539                qs.push(start); // the first part
83540
83541                tail.push(cubic); // the last part
83542
83543                cubic = middle; // iterate on the middle piece
83544              }
83545
83546              if (t3 < 1) {
83547                // a little excess error, split the middle in two
83548                qs.push(cubic.split(0.5));
83549              } // add the middle piece to the result
83550
83551
83552              qs.push(cubic); // finally add the tail, reversed, onto the result
83553
83554              Array.prototype.push.apply(qs, tail.reverse());
83555            }
83556
83557            return qs;
83558          }
83559          /**
83560           * @function pushLine
83561           * @param {Number} x0
83562           * @param {Number} y0
83563           * @param {Number} x1
83564           * @param {Number} y1
83565           *
83566           * add a straight line to the row/col grid of a glyph
83567           */
83568
83569
83570          function pushLine(x0, y0, x1, y1) {
83571            var mx = (x0 + x1) / 2;
83572            var my = (y0 + y1) / 2;
83573            push([x0, x1], [y0, y1], {
83574              x: x0,
83575              y: y0,
83576              cx: mx,
83577              cy: my
83578            });
83579          }
83580          /**
83581           * @function samePoint
83582           * @param {Number} x0
83583           * @param {Number} y0
83584           * @param {Number} x1
83585           * @param {Number} y1
83586           * @return {Boolean} true if the two points are sufficiently close
83587           *
83588           * tests if two points are close enough to be considered the same
83589           */
83590
83591
83592          function samePoint(x0, y0, x1, y1) {
83593            return Math.abs(x1 - x0) < 0.00001 && Math.abs(y1 - y0) < 0.00001;
83594          }
83595
83596          var x0, y0, xs, ys;
83597
83598          for (var iCmd = 0; iCmd < cmds.length; ++iCmd) {
83599            var cmd = cmds[iCmd]; // scale the coordinates to the range 0-1
83600
83601            var x1 = (cmd.x - xMin) / gWidth;
83602            var y1 = (cmd.y - yMin) / gHeight; // don't bother if this point is the same as the last
83603
83604            if (samePoint(x0, y0, x1, y1)) continue;
83605
83606            switch (cmd.type) {
83607              case 'M':
83608                // move
83609                xs = x1;
83610                ys = y1;
83611                break;
83612
83613              case 'L':
83614                // line
83615                pushLine(x0, y0, x1, y1);
83616                break;
83617
83618              case 'Q':
83619                // quadratic
83620                var cx = (cmd.x1 - xMin) / gWidth;
83621                var cy = (cmd.y1 - yMin) / gHeight;
83622                push([x0, x1, cx], [y0, y1, cy], {
83623                  x: x0,
83624                  y: y0,
83625                  cx: cx,
83626                  cy: cy
83627                });
83628                break;
83629
83630              case 'Z':
83631                // end
83632                if (!samePoint(x0, y0, xs, ys)) {
83633                  // add an extra line closing the loop, if necessary
83634                  pushLine(x0, y0, xs, ys);
83635                  strokes.push({
83636                    x: xs,
83637                    y: ys
83638                  });
83639                } else {
83640                  strokes.push({
83641                    x: x0,
83642                    y: y0
83643                  });
83644                }
83645
83646                break;
83647
83648              case 'C':
83649                // cubic
83650                var cx1 = (cmd.x1 - xMin) / gWidth;
83651                var cy1 = (cmd.y1 - yMin) / gHeight;
83652                var cx2 = (cmd.x2 - xMin) / gWidth;
83653                var cy2 = (cmd.y2 - yMin) / gHeight;
83654                var qs = cubicToQuadratics(x0, y0, cx1, cy1, cx2, cy2, x1, y1);
83655
83656                for (var iq = 0; iq < qs.length; iq++) {
83657                  var q = qs[iq].toQuadratic();
83658                  push([q.x, q.x1, q.cx], [q.y, q.y1, q.cy], q);
83659                }
83660
83661                break;
83662
83663              default:
83664                throw new Error('unknown command type: ' + cmd.type);
83665            }
83666
83667            x0 = x1;
83668            y0 = y1;
83669          } // allocate space for the strokes
83670
83671
83672          var strokeCount = strokes.length;
83673          var strokeImageInfo = this.strokeImageInfos.findImage(strokeCount);
83674          var strokeOffset = strokeImageInfo.index; // fill the stroke image
83675
83676          for (var il = 0; il < strokeCount; ++il) {
83677            var s = strokes[il];
83678            setPixel(strokeImageInfo, byte(s.x), byte(s.y), byte(s.cx), byte(s.cy));
83679          }
83680          /**
83681           * @function layout
83682           * @param {Number[][]} dim
83683           * @param {ImageInfo[]} dimImageInfos
83684           * @param {ImageInfo[]} cellImageInfos
83685           * @return {Object}
83686           *
83687           * lays out the curves in a dimension (row or col) into two
83688           * images, one for the indices of the curves themselves, and
83689           * one containing the offset and length of those index spans.
83690           */
83691
83692
83693          function layout(dim, dimImageInfos, cellImageInfos) {
83694            var dimLength = dim.length; // the number of slices in this dimension
83695
83696            var dimImageInfo = dimImageInfos.findImage(dimLength);
83697            var dimOffset = dimImageInfo.index; // calculate the total number of stroke indices in this dimension
83698
83699            var totalStrokes = 0;
83700
83701            for (var id = 0; id < dimLength; ++id) {
83702              totalStrokes += dim[id].length;
83703            } // allocate space for the stroke indices
83704
83705
83706            var cellImageInfo = cellImageInfos.findImage(totalStrokes); // for each slice in the glyph
83707
83708            for (var i = 0; i < dimLength; ++i) {
83709              var strokeIndices = dim[i];
83710              var strokeCount = strokeIndices.length;
83711              var cellLineIndex = cellImageInfo.index; // write the offset and count into the glyph slice image
83712
83713              setPixel(dimImageInfo, cellLineIndex >> 7, cellLineIndex & 0x7f, strokeCount >> 7, strokeCount & 0x7f); // for each stroke index in that slice
83714
83715              for (var iil = 0; iil < strokeCount; ++iil) {
83716                // write the stroke index into the slice's image
83717                var strokeIndex = strokeIndices[iil] + strokeOffset;
83718                setPixel(cellImageInfo, strokeIndex >> 7, strokeIndex & 0x7f, 0, 0);
83719              }
83720            }
83721
83722            return {
83723              cellImageInfo: cellImageInfo,
83724              dimOffset: dimOffset,
83725              dimImageInfo: dimImageInfo
83726            };
83727          } // initialize the info for this glyph
83728
83729
83730          gi = this.glyphInfos[glyph.index] = {
83731            glyph: glyph,
83732            uGlyphRect: [bb.x1, -bb.y1, bb.x2, -bb.y2],
83733            strokeImageInfo: strokeImageInfo,
83734            strokes: strokes,
83735            colInfo: layout(cols, this.colDimImageInfos, this.colCellImageInfos),
83736            rowInfo: layout(rows, this.rowDimImageInfos, this.rowCellImageInfos)
83737          };
83738          gi.uGridOffset = [gi.colInfo.dimOffset, gi.rowInfo.dimOffset];
83739          return gi;
83740        };
83741      };
83742
83743      p5.RendererGL.prototype._renderText = function (p, line, x, y, maxY) {
83744        if (y >= maxY || !this._doFill) {
83745          return; // don't render lines beyond our maxY position
83746        }
83747
83748        if (!this._isOpenType()) {
83749          console.log('WEBGL: only opentype fonts are supported');
83750          return p;
83751        }
83752
83753        p.push(); // fix to #803
83754        // remember this state, so it can be restored later
83755
83756        var curFillShader = this.curFillShader;
83757        var doStroke = this._doStroke;
83758        var drawMode = this.drawMode;
83759        this.curFillShader = null;
83760        this._doStroke = false;
83761        this.drawMode = constants.TEXTURE; // get the cached FontInfo object
83762
83763        var font = this._textFont.font;
83764        var fontInfo = this._textFont._fontInfo;
83765
83766        if (!fontInfo) {
83767          fontInfo = this._textFont._fontInfo = new FontInfo(font);
83768        } // calculate the alignment and move/scale the view accordingly
83769
83770
83771        var pos = this._textFont._handleAlignment(this, line, x, y);
83772
83773        var fontSize = this._textSize;
83774        var scale = fontSize / font.unitsPerEm;
83775        this.translate(pos.x, pos.y, 0);
83776        this.scale(scale, scale, 1); // initialize the font shader
83777
83778        var gl = this.GL;
83779        var initializeShader = !this._defaultFontShader;
83780        var sh = this.setFillShader(this._getFontShader());
83781
83782        if (initializeShader) {
83783          // these are constants, really. just initialize them one-time.
83784          sh.setUniform('uGridImageSize', [gridImageWidth, gridImageHeight]);
83785          sh.setUniform('uCellsImageSize', [cellImageWidth, cellImageHeight]);
83786          sh.setUniform('uStrokeImageSize', [strokeImageWidth, strokeImageHeight]);
83787          sh.setUniform('uGridSize', [charGridWidth, charGridHeight]);
83788        }
83789
83790        this._applyColorBlend(this.curFillColor);
83791
83792        var g = this.gHash['glyph'];
83793
83794        if (!g) {
83795          // create the geometry for rendering a quad
83796          var geom = this._textGeom = new p5.Geometry(1, 1, function () {
83797            for (var i = 0; i <= 1; i++) {
83798              for (var j = 0; j <= 1; j++) {
83799                this.vertices.push(new p5.Vector(j, i, 0));
83800                this.uvs.push(j, i);
83801              }
83802            }
83803          });
83804          geom.computeFaces().computeNormals();
83805          g = this.createBuffers('glyph', geom);
83806        } // bind the shader buffers
83807
83808
83809        this._bindBuffer(g.vertexBuffer, gl.ARRAY_BUFFER);
83810
83811        sh.enableAttrib(sh.attributes.aPosition.location, 3, gl.FLOAT, false, 0, 0);
83812
83813        this._bindBuffer(g.indexBuffer, gl.ELEMENT_ARRAY_BUFFER);
83814
83815        this._bindBuffer(g.uvBuffer, gl.ARRAY_BUFFER);
83816
83817        sh.enableAttrib(sh.attributes.aTexCoord.location, 2, gl.FLOAT, false, 0, 0); // this will have to do for now...
83818
83819        sh.setUniform('uMaterialColor', this.curFillColor);
83820
83821        try {
83822          var dx = 0; // the x position in the line
83823
83824          var glyphPrev = null; // the previous glyph, used for kerning
83825
83826          var shaderBound = false; // fetch the glyphs in the line of text
83827
83828          var glyphs = font.stringToGlyphs(line);
83829
83830          for (var ig = 0; ig < glyphs.length; ++ig) {
83831            var glyph = glyphs[ig]; // kern
83832
83833            if (glyphPrev) dx += font.getKerningValue(glyphPrev, glyph);
83834            var gi = fontInfo.getGlyphInfo(glyph);
83835
83836            if (gi.uGlyphRect) {
83837              var rowInfo = gi.rowInfo;
83838              var colInfo = gi.colInfo;
83839              sh.setUniform('uSamplerStrokes', gi.strokeImageInfo.imageData);
83840              sh.setUniform('uSamplerRowStrokes', rowInfo.cellImageInfo.imageData);
83841              sh.setUniform('uSamplerRows', rowInfo.dimImageInfo.imageData);
83842              sh.setUniform('uSamplerColStrokes', colInfo.cellImageInfo.imageData);
83843              sh.setUniform('uSamplerCols', colInfo.dimImageInfo.imageData);
83844              sh.setUniform('uGridOffset', gi.uGridOffset);
83845              sh.setUniform('uGlyphRect', gi.uGlyphRect);
83846              sh.setUniform('uGlyphOffset', dx);
83847
83848              if (!shaderBound) {
83849                shaderBound = true;
83850                sh.bindShader(); // first time around, bind the shader fully
83851              } else {
83852                sh.bindTextures(); // afterwards, only textures need updating
83853              } // draw it
83854
83855
83856              gl.drawElements(gl.TRIANGLES, 6, this.GL.UNSIGNED_SHORT, 0);
83857            }
83858
83859            dx += glyph.advanceWidth;
83860            glyphPrev = glyph;
83861          }
83862        } finally {
83863          // clean up
83864          sh.unbindShader();
83865          this.curFillShader = curFillShader;
83866          this._doStroke = doStroke;
83867          this.drawMode = drawMode;
83868          p.pop();
83869        }
83870
83871        this._pInst._pixelsDirty = true;
83872        return p;
83873      };
83874    }, {
83875      "../core/constants": 18,
83876      "../core/main": 24,
83877      "./p5.RendererGL": 74,
83878      "./p5.Shader": 75
83879    }]
83880  }, {}, [13])(13);
83881});
83882},{"buffer":"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/node_modules/buffer/index.js","process":"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/node_modules/process/browser.js"}],"../node_modules/p5/lib/addons/p5.sound.js":[function(require,module,exports) {
83883var define;
83884/*! p5.sound.js v0.3.10 2019-01-10 */
83885/**
83886 *  p5.sound extends p5 with <a href="http://caniuse.com/audio-api"
83887 *  target="_blank">Web Audio</a> functionality including audio input,
83888 *  playback, analysis and synthesis.
83889 *  <br/><br/>
83890 *  <a href="#/p5.SoundFile"><b>p5.SoundFile</b></a>: Load and play sound files.<br/>
83891 *  <a href="#/p5.Amplitude"><b>p5.Amplitude</b></a>: Get the current volume of a sound.<br/>
83892 *  <a href="#/p5.AudioIn"><b>p5.AudioIn</b></a>: Get sound from an input source, typically
83893 *    a computer microphone.<br/>
83894 *  <a href="#/p5.FFT"><b>p5.FFT</b></a>: Analyze the frequency of sound. Returns
83895 *    results from the frequency spectrum or time domain (waveform).<br/>
83896 *  <a href="#/p5.Oscillator"><b>p5.Oscillator</b></a>: Generate Sine,
83897 *    Triangle, Square and Sawtooth waveforms. Base class of
83898 *    <a href="#/p5.Noise">p5.Noise</a> and <a href="#/p5.Pulse">p5.Pulse</a>.
83899 *    <br/>
83900 *  <a href="#/p5.Envelope"><b>p5.Envelope</b></a>: An Envelope is a series
83901 *    of fades over time. Often used to control an object's
83902 *    output gain level as an "ADSR Envelope" (Attack, Decay,
83903 *    Sustain, Release). Can also modulate other parameters.<br/>
83904 *  <a href="#/p5.Delay"><b>p5.Delay</b></a>: A delay effect with
83905 *    parameters for feedback, delayTime, and lowpass filter.<br/>
83906 *  <a href="#/p5.Filter"><b>p5.Filter</b></a>: Filter the frequency range of a
83907 *    sound.
83908 *  <br/>
83909 *  <a href="#/p5.Reverb"><b>p5.Reverb</b></a>: Add reverb to a sound by specifying
83910 *    duration and decay. <br/>
83911 *  <b><a href="#/p5.Convolver">p5.Convolver</a>:</b> Extends
83912 *  <a href="#/p5.Reverb">p5.Reverb</a> to simulate the sound of real
83913 *    physical spaces through convolution.<br/>
83914 *  <b><a href="#/p5.SoundRecorder">p5.SoundRecorder</a></b>: Record sound for playback
83915 *    / save the .wav file.
83916 *  <b><a href="#/p5.Phrase">p5.Phrase</a></b>, <b><a href="#/p5.Part">p5.Part</a></b> and
83917 *  <b><a href="#/p5.Score">p5.Score</a></b>: Compose musical sequences.
83918 *  <br/><br/>
83919 *  p5.sound is on <a href="https://github.com/therewasaguy/p5.sound/">GitHub</a>.
83920 *  Download the latest version
83921 *  <a href="https://github.com/therewasaguy/p5.sound/blob/master/lib/p5.sound.js">here</a>.
83922 *
83923 *  @module p5.sound
83924 *  @submodule p5.sound
83925 *  @for p5.sound
83926 *  @main
83927 */
83928
83929/**
83930 *  p5.sound 
83931 *  https://p5js.org/reference/#/libraries/p5.sound
83932 *
83933 *  From the Processing Foundation and contributors
83934 *  https://github.com/processing/p5.js-sound/graphs/contributors
83935 *
83936 *  MIT License (MIT)
83937 *  https://github.com/processing/p5.js-sound/blob/master/LICENSE
83938 *
83939 *  Some of the many audio libraries & resources that inspire p5.sound:
83940 *   - TONE.js (c) Yotam Mann. Licensed under The MIT License (MIT). https://github.com/TONEnoTONE/Tone.js
83941 *   - buzz.js (c) Jay Salvat. Licensed under The MIT License (MIT). http://buzz.jaysalvat.com/
83942 *   - Boris Smus Web Audio API book, 2013. Licensed under the Apache License http://www.apache.org/licenses/LICENSE-2.0
83943 *   - wavesurfer.js https://github.com/katspaugh/wavesurfer.js
83944 *   - Web Audio Components by Jordan Santell https://github.com/web-audio-components
83945 *   - Wilm Thoben's Sound library for Processing https://github.com/processing/processing/tree/master/java/libraries/sound
83946 *
83947 *   Web Audio API: http://w3.org/TR/webaudio/
83948 */
83949
83950(function (root, factory) {
83951  if (typeof define === 'function' && define.amd)
83952    define('p5.sound', ['p5'], function (p5) { (factory(p5));});
83953  else if (typeof exports === 'object')
83954    factory(require('../p5'));
83955  else
83956    factory(root['p5']);
83957}(this, function (p5) {
83958  
83959var shims;
83960'use strict';  /**
83961                * This module has shims
83962                */
83963shims = function () {
83964  /* AudioContext Monkeypatch
83965     Copyright 2013 Chris Wilson
83966     Licensed under the Apache License, Version 2.0 (the "License");
83967     you may not use this file except in compliance with the License.
83968     You may obtain a copy of the License at
83969         http://www.apache.org/licenses/LICENSE-2.0
83970     Unless required by applicable law or agreed to in writing, software
83971     distributed under the License is distributed on an "AS IS" BASIS,
83972     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
83973     See the License for the specific language governing permissions and
83974     limitations under the License.
83975  */
83976  (function () {
83977    function fixSetTarget(param) {
83978      if (!param)
83979        // if NYI, just return
83980        return;
83981      if (!param.setTargetAtTime)
83982        param.setTargetAtTime = param.setTargetValueAtTime;
83983    }
83984    if (window.hasOwnProperty('webkitAudioContext') && !window.hasOwnProperty('AudioContext')) {
83985      window.AudioContext = window.webkitAudioContext;
83986      if (typeof AudioContext.prototype.createGain !== 'function')
83987        AudioContext.prototype.createGain = AudioContext.prototype.createGainNode;
83988      if (typeof AudioContext.prototype.createDelay !== 'function')
83989        AudioContext.prototype.createDelay = AudioContext.prototype.createDelayNode;
83990      if (typeof AudioContext.prototype.createScriptProcessor !== 'function')
83991        AudioContext.prototype.createScriptProcessor = AudioContext.prototype.createJavaScriptNode;
83992      if (typeof AudioContext.prototype.createPeriodicWave !== 'function')
83993        AudioContext.prototype.createPeriodicWave = AudioContext.prototype.createWaveTable;
83994      AudioContext.prototype.internal_createGain = AudioContext.prototype.createGain;
83995      AudioContext.prototype.createGain = function () {
83996        var node = this.internal_createGain();
83997        fixSetTarget(node.gain);
83998        return node;
83999      };
84000      AudioContext.prototype.internal_createDelay = AudioContext.prototype.createDelay;
84001      AudioContext.prototype.createDelay = function (maxDelayTime) {
84002        var node = maxDelayTime ? this.internal_createDelay(maxDelayTime) : this.internal_createDelay();
84003        fixSetTarget(node.delayTime);
84004        return node;
84005      };
84006      AudioContext.prototype.internal_createBufferSource = AudioContext.prototype.createBufferSource;
84007      AudioContext.prototype.createBufferSource = function () {
84008        var node = this.internal_createBufferSource();
84009        if (!node.start) {
84010          node.start = function (when, offset, duration) {
84011            if (offset || duration)
84012              this.noteGrainOn(when || 0, offset, duration);
84013            else
84014              this.noteOn(when || 0);
84015          };
84016        } else {
84017          node.internal_start = node.start;
84018          node.start = function (when, offset, duration) {
84019            if (typeof duration !== 'undefined')
84020              node.internal_start(when || 0, offset, duration);
84021            else
84022              node.internal_start(when || 0, offset || 0);
84023          };
84024        }
84025        if (!node.stop) {
84026          node.stop = function (when) {
84027            this.noteOff(when || 0);
84028          };
84029        } else {
84030          node.internal_stop = node.stop;
84031          node.stop = function (when) {
84032            node.internal_stop(when || 0);
84033          };
84034        }
84035        fixSetTarget(node.playbackRate);
84036        return node;
84037      };
84038      AudioContext.prototype.internal_createDynamicsCompressor = AudioContext.prototype.createDynamicsCompressor;
84039      AudioContext.prototype.createDynamicsCompressor = function () {
84040        var node = this.internal_createDynamicsCompressor();
84041        fixSetTarget(node.threshold);
84042        fixSetTarget(node.knee);
84043        fixSetTarget(node.ratio);
84044        fixSetTarget(node.reduction);
84045        fixSetTarget(node.attack);
84046        fixSetTarget(node.release);
84047        return node;
84048      };
84049      AudioContext.prototype.internal_createBiquadFilter = AudioContext.prototype.createBiquadFilter;
84050      AudioContext.prototype.createBiquadFilter = function () {
84051        var node = this.internal_createBiquadFilter();
84052        fixSetTarget(node.frequency);
84053        fixSetTarget(node.detune);
84054        fixSetTarget(node.Q);
84055        fixSetTarget(node.gain);
84056        return node;
84057      };
84058      if (typeof AudioContext.prototype.createOscillator !== 'function') {
84059        AudioContext.prototype.internal_createOscillator = AudioContext.prototype.createOscillator;
84060        AudioContext.prototype.createOscillator = function () {
84061          var node = this.internal_createOscillator();
84062          if (!node.start) {
84063            node.start = function (when) {
84064              this.noteOn(when || 0);
84065            };
84066          } else {
84067            node.internal_start = node.start;
84068            node.start = function (when) {
84069              node.internal_start(when || 0);
84070            };
84071          }
84072          if (!node.stop) {
84073            node.stop = function (when) {
84074              this.noteOff(when || 0);
84075            };
84076          } else {
84077            node.internal_stop = node.stop;
84078            node.stop = function (when) {
84079              node.internal_stop(when || 0);
84080            };
84081          }
84082          if (!node.setPeriodicWave)
84083            node.setPeriodicWave = node.setWaveTable;
84084          fixSetTarget(node.frequency);
84085          fixSetTarget(node.detune);
84086          return node;
84087        };
84088      }
84089    }
84090    if (window.hasOwnProperty('webkitOfflineAudioContext') && !window.hasOwnProperty('OfflineAudioContext')) {
84091      window.OfflineAudioContext = window.webkitOfflineAudioContext;
84092    }
84093  }(window));
84094  // <-- end MonkeyPatch.
84095  // Polyfill for AudioIn, also handled by p5.dom createCapture
84096  navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
84097  /**
84098   * Determine which filetypes are supported (inspired by buzz.js)
84099   * The audio element (el) will only be used to test browser support for various audio formats
84100   */
84101  var el = document.createElement('audio');
84102  p5.prototype.isSupported = function () {
84103    return !!el.canPlayType;
84104  };
84105  var isOGGSupported = function () {
84106    return !!el.canPlayType && el.canPlayType('audio/ogg; codecs="vorbis"');
84107  };
84108  var isMP3Supported = function () {
84109    return !!el.canPlayType && el.canPlayType('audio/mpeg;');
84110  };
84111  var isWAVSupported = function () {
84112    return !!el.canPlayType && el.canPlayType('audio/wav; codecs="1"');
84113  };
84114  var isAACSupported = function () {
84115    return !!el.canPlayType && (el.canPlayType('audio/x-m4a;') || el.canPlayType('audio/aac;'));
84116  };
84117  var isAIFSupported = function () {
84118    return !!el.canPlayType && el.canPlayType('audio/x-aiff;');
84119  };
84120  p5.prototype.isFileSupported = function (extension) {
84121    switch (extension.toLowerCase()) {
84122    case 'mp3':
84123      return isMP3Supported();
84124    case 'wav':
84125      return isWAVSupported();
84126    case 'ogg':
84127      return isOGGSupported();
84128    case 'aac':
84129    case 'm4a':
84130    case 'mp4':
84131      return isAACSupported();
84132    case 'aif':
84133    case 'aiff':
84134      return isAIFSupported();
84135    default:
84136      return false;
84137    }
84138  };
84139}();
84140var StartAudioContext;
84141(function (root, factory) {
84142  if (true) {
84143    StartAudioContext = function () {
84144      return factory();
84145    }();
84146  } else if (typeof module === 'object' && module.exports) {
84147    module.exports = factory();
84148  } else {
84149    root.StartAudioContext = factory();
84150  }
84151}(this, function () {
84152  var TapListener = function (element, context) {
84153    this._dragged = false;
84154    this._element = element;
84155    this._bindedMove = this._moved.bind(this);
84156    this._bindedEnd = this._ended.bind(this, context);
84157  };
84158  TapListener.prototype._moved = function (e) {
84159    this._dragged = true;
84160  };
84161  TapListener.prototype._ended = function (context) {
84162    if (!this._dragged) {
84163      startContext(context);
84164    }
84165    this._dragged = false;
84166  };
84167  TapListener.prototype.dispose = function () {
84168    this._element.removeEventListener('touchstart', this._bindedEnd);
84169    this._element.removeEventListener('touchmove', this._bindedMove);
84170    this._element.removeEventListener('touchend', this._bindedEnd);
84171    this._element.removeEventListener('mouseup', this._bindedEnd);
84172    this._bindedMove = null;
84173    this._bindedEnd = null;
84174    this._element = null;
84175  };
84176  function startContext(context) {
84177    var buffer = context.createBuffer(1, 1, context.sampleRate);
84178    var source = context.createBufferSource();
84179    source.buffer = buffer;
84180    source.connect(context.destination);
84181    source.start(0);
84182    if (context.resume) {
84183      context.resume();
84184    }
84185  }
84186  function isStarted(context) {
84187    return context.state === 'running';
84188  }
84189  function onStarted(context, callback) {
84190    function checkLoop() {
84191      if (isStarted(context)) {
84192        callback();
84193      } else {
84194        requestAnimationFrame(checkLoop);
84195        if (context.resume) {
84196          context.resume();
84197        }
84198      }
84199    }
84200    if (isStarted(context)) {
84201      callback();
84202    } else {
84203      checkLoop();
84204    }
84205  }
84206  function bindTapListener(element, tapListeners, context) {
84207    if (Array.isArray(element) || NodeList && element instanceof NodeList) {
84208      for (var i = 0; i < element.length; i++) {
84209        bindTapListener(element[i], tapListeners, context);
84210      }
84211    } else if (typeof element === 'string') {
84212      bindTapListener(document.querySelectorAll(element), tapListeners, context);
84213    } else if (element.jquery && typeof element.toArray === 'function') {
84214      bindTapListener(element.toArray(), tapListeners, context);
84215    } else if (Element && element instanceof Element) {
84216      var tap = new TapListener(element, context);
84217      tapListeners.push(tap);
84218    }
84219  }
84220  function StartAudioContext(context, elements, callback) {
84221    var promise = new Promise(function (success) {
84222      onStarted(context, success);
84223    });
84224    var tapListeners = [];
84225    if (!elements) {
84226      elements = document.body;
84227    }
84228    bindTapListener(elements, tapListeners, context);
84229    promise.then(function () {
84230      for (var i = 0; i < tapListeners.length; i++) {
84231        tapListeners[i].dispose();
84232      }
84233      tapListeners = null;
84234      if (callback) {
84235        callback();
84236      }
84237    });
84238    return promise;
84239  }
84240  return StartAudioContext;
84241}));
84242var audiocontext;
84243'use strict';
84244audiocontext = function (StartAudioContext) {
84245  // Create the Audio Context
84246  var audiocontext = new window.AudioContext();
84247  /**
84248   * <p>Returns the Audio Context for this sketch. Useful for users
84249   * who would like to dig deeper into the <a target='_blank' href=
84250   * 'http://webaudio.github.io/web-audio-api/'>Web Audio API
84251   * </a>.</p>
84252   *
84253   * <p>Some browsers require users to startAudioContext
84254   * with a user gesture, such as touchStarted in the example below.</p>
84255   *
84256   * @method getAudioContext
84257   * @return {Object}    AudioContext for this sketch
84258   * @example
84259   * <div><code>
84260   *  function draw() {
84261   *    background(255);
84262   *    textAlign(CENTER);
84263   *
84264   *    if (getAudioContext().state !== 'running') {
84265   *      text('click to start audio', width/2, height/2);
84266   *    } else {
84267   *      text('audio is enabled', width/2, height/2);
84268   *    }
84269   *  }
84270   *
84271   *  function touchStarted() {
84272   *    if (getAudioContext().state !== 'running') {
84273   *      getAudioContext().resume();
84274   *    }
84275   *    var synth = new p5.MonoSynth();
84276   *    synth.play('A4', 0.5, 0, 0.2);
84277   *  }
84278   *
84279   * </div></code>
84280   */
84281  p5.prototype.getAudioContext = function () {
84282    return audiocontext;
84283  };
84284  /**
84285   *  <p>It is a good practice to give users control over starting audio playback.
84286   *  This practice is enforced by Google Chrome's autoplay policy as of r70
84287   *  (<a href="https://goo.gl/7K7WLu">info</a>), iOS Safari, and other browsers.
84288   *  </p>
84289   *
84290   *  <p>
84291   *  userStartAudio() starts the <a href="https://developer.mozilla.org/en-US/docs/Web/API/AudioContext"
84292   *  target="_blank" title="Audio Context @ MDN">Audio Context</a> on a user gesture. It utilizes
84293   *  the <a href="https://github.com/tambien/StartAudioContext">StartAudioContext</a> library by
84294   *  Yotam Mann (MIT Licence, 2016). Read more at https://github.com/tambien/StartAudioContext.
84295   *  </p>
84296   *
84297   *  <p>Starting the audio context on a user gesture can be as simple as <code>userStartAudio()</code>.
84298   *  Optional parameters let you decide on a specific element that will start the audio context,
84299   *  and/or call a function once the audio context is started.</p>
84300   *  @param  {Element|Array}   [element(s)] This argument can be an Element,
84301   *                                Selector String, NodeList, p5.Element,
84302   *                                jQuery Element, or an Array of any of those.
84303   *  @param  {Function} [callback] Callback to invoke when the AudioContext has started
84304   *  @return {Promise}            Returns a Promise which is resolved when
84305   *                                       the AudioContext state is 'running'
84306   * @method userStartAudio
84307   *  @example
84308   *  <div><code>
84309   *  function setup() {
84310   *    var myDiv = createDiv('click to start audio');
84311   *    myDiv.position(0, 0);
84312   *
84313   *    var mySynth = new p5.MonoSynth();
84314   * 
84315   *    // This won't play until the context has started
84316   *    mySynth.play('A6');
84317   *
84318   *    // Start the audio context on a click/touch event
84319   *    userStartAudio().then(function() {
84320   *       myDiv.remove();
84321   *     });
84322   *  }
84323   *  </code></div>
84324   */
84325  p5.prototype.userStartAudio = function (elements, callback) {
84326    var elt = elements;
84327    if (elements instanceof p5.Element) {
84328      elt = elements.elt;
84329    } else if (elements instanceof Array && elements[0] instanceof p5.Element) {
84330      elt = elements.map(function (e) {
84331        return e.elt;
84332      });
84333    }
84334    return StartAudioContext(audiocontext, elt, callback);
84335  };
84336  return audiocontext;
84337}(StartAudioContext);
84338var master;
84339'use strict';
84340master = function () {
84341  /**
84342   * Master contains AudioContext and the master sound output.
84343   */
84344  var Master = function () {
84345    var audiocontext = p5.prototype.getAudioContext();
84346    this.input = audiocontext.createGain();
84347    this.output = audiocontext.createGain();
84348    //put a hard limiter on the output
84349    this.limiter = audiocontext.createDynamicsCompressor();
84350    this.limiter.threshold.value = -3;
84351    this.limiter.ratio.value = 20;
84352    this.limiter.knee.value = 1;
84353    this.audiocontext = audiocontext;
84354    this.output.disconnect();
84355    // connect input to limiter
84356    this.input.connect(this.limiter);
84357    // connect limiter to output
84358    this.limiter.connect(this.output);
84359    // meter is just for global Amplitude / FFT analysis
84360    this.meter = audiocontext.createGain();
84361    this.fftMeter = audiocontext.createGain();
84362    this.output.connect(this.meter);
84363    this.output.connect(this.fftMeter);
84364    // connect output to destination
84365    this.output.connect(this.audiocontext.destination);
84366    // an array of all sounds in the sketch
84367    this.soundArray = [];
84368    // an array of all musical parts in the sketch
84369    this.parts = [];
84370    // file extensions to search for
84371    this.extensions = [];
84372  };
84373  // create a single instance of the p5Sound / master output for use within this sketch
84374  var p5sound = new Master();
84375  /**
84376   * Returns a number representing the master amplitude (volume) for sound
84377   * in this sketch.
84378   *
84379   * @method getMasterVolume
84380   * @return {Number} Master amplitude (volume) for sound in this sketch.
84381   *                  Should be between 0.0 (silence) and 1.0.
84382   */
84383  p5.prototype.getMasterVolume = function () {
84384    return p5sound.output.gain.value;
84385  };
84386  /**
84387   *  <p>Scale the output of all sound in this sketch</p>
84388   *  Scaled between 0.0 (silence) and 1.0 (full volume).
84389   *  1.0 is the maximum amplitude of a digital sound, so multiplying
84390   *  by greater than 1.0 may cause digital distortion. To
84391   *  fade, provide a <code>rampTime</code> parameter. For more
84392   *  complex fades, see the Envelope class.
84393   *
84394   *  Alternately, you can pass in a signal source such as an
84395   *  oscillator to modulate the amplitude with an audio signal.
84396   *
84397   *  <p><b>How This Works</b>: When you load the p5.sound module, it
84398   *  creates a single instance of p5sound. All sound objects in this
84399   *  module output to p5sound before reaching your computer's output.
84400   *  So if you change the amplitude of p5sound, it impacts all of the
84401   *  sound in this module.</p>
84402   *
84403   *  <p>If no value is provided, returns a Web Audio API Gain Node</p>
84404   *
84405   *  @method  masterVolume
84406   *  @param {Number|Object} volume  Volume (amplitude) between 0.0
84407   *                                     and 1.0 or modulating signal/oscillator
84408   *  @param {Number} [rampTime]  Fade for t seconds
84409   *  @param {Number} [timeFromNow]  Schedule this event to happen at
84410   *                                 t seconds in the future
84411   */
84412  p5.prototype.masterVolume = function (vol, rampTime, tFromNow) {
84413    if (typeof vol === 'number') {
84414      var rampTime = rampTime || 0;
84415      var tFromNow = tFromNow || 0;
84416      var now = p5sound.audiocontext.currentTime;
84417      var currentVol = p5sound.output.gain.value;
84418      p5sound.output.gain.cancelScheduledValues(now + tFromNow);
84419      p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);
84420      p5sound.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);
84421    } else if (vol) {
84422      vol.connect(p5sound.output.gain);
84423    } else {
84424      // return the Gain Node
84425      return p5sound.output.gain;
84426    }
84427  };
84428  /**
84429   *  `p5.soundOut` is the p5.sound master output. It sends output to
84430   *  the destination of this window's web audio context. It contains
84431   *  Web Audio API nodes including a dyanmicsCompressor (<code>.limiter</code>),
84432   *  and Gain Nodes for <code>.input</code> and <code>.output</code>.
84433   *
84434   *  @property {Object} soundOut
84435   */
84436  p5.prototype.soundOut = p5.soundOut = p5sound;
84437  /**
84438   *  a silent connection to the DesinationNode
84439   *  which will ensure that anything connected to it
84440   *  will not be garbage collected
84441   *
84442   *  @private
84443   */
84444  p5.soundOut._silentNode = p5sound.audiocontext.createGain();
84445  p5.soundOut._silentNode.gain.value = 0;
84446  p5.soundOut._silentNode.connect(p5sound.audiocontext.destination);
84447  return p5sound;
84448}();
84449var helpers;
84450'use strict';
84451helpers = function () {
84452  var p5sound = master;
84453  /**
84454   * @for p5
84455   */
84456  /**
84457   * Returns a number representing the sample rate, in samples per second,
84458   * of all sound objects in this audio context. It is determined by the
84459   * sampling rate of your operating system's sound card, and it is not
84460   * currently possile to change.
84461   * It is often 44100, or twice the range of human hearing.
84462   *
84463   * @method sampleRate
84464   * @return {Number} samplerate samples per second
84465   */
84466  p5.prototype.sampleRate = function () {
84467    return p5sound.audiocontext.sampleRate;
84468  };
84469  /**
84470   *  Returns the closest MIDI note value for
84471   *  a given frequency.
84472   *
84473   *  @method freqToMidi
84474   *  @param  {Number} frequency A freqeuncy, for example, the "A"
84475   *                             above Middle C is 440Hz
84476   *  @return {Number}   MIDI note value
84477   */
84478  p5.prototype.freqToMidi = function (f) {
84479    var mathlog2 = Math.log(f / 440) / Math.log(2);
84480    var m = Math.round(12 * mathlog2) + 69;
84481    return m;
84482  };
84483  /**
84484   *  Returns the frequency value of a MIDI note value.
84485   *  General MIDI treats notes as integers where middle C
84486   *  is 60, C# is 61, D is 62 etc. Useful for generating
84487   *  musical frequencies with oscillators.
84488   *
84489   *  @method  midiToFreq
84490   *  @param  {Number} midiNote The number of a MIDI note
84491   *  @return {Number} Frequency value of the given MIDI note
84492   *  @example
84493   *  <div><code>
84494   *  var notes = [60, 64, 67, 72];
84495   *  var i = 0;
84496   *
84497   *  function setup() {
84498   *    osc = new p5.Oscillator('Triangle');
84499   *    osc.start();
84500   *    frameRate(1);
84501   *  }
84502   *
84503   *  function draw() {
84504   *    var freq = midiToFreq(notes[i]);
84505   *    osc.freq(freq);
84506   *    i++;
84507   *    if (i >= notes.length){
84508   *      i = 0;
84509   *    }
84510   *  }
84511   *  </code></div>
84512   */
84513  var midiToFreq = p5.prototype.midiToFreq = function (m) {
84514    return 440 * Math.pow(2, (m - 69) / 12);
84515  };
84516  // This method converts ANSI notes specified as a string "C4", "Eb3" to a frequency
84517  var noteToFreq = function (note) {
84518    if (typeof note !== 'string') {
84519      return note;
84520    }
84521    var wholeNotes = {
84522      A: 21,
84523      B: 23,
84524      C: 24,
84525      D: 26,
84526      E: 28,
84527      F: 29,
84528      G: 31
84529    };
84530    var value = wholeNotes[note[0].toUpperCase()];
84531    var octave = ~~note.slice(-1);
84532    value += 12 * (octave - 1);
84533    switch (note[1]) {
84534    case '#':
84535      value += 1;
84536      break;
84537    case 'b':
84538      value -= 1;
84539      break;
84540    default:
84541      break;
84542    }
84543    return midiToFreq(value);
84544  };
84545  /**
84546   *  List the SoundFile formats that you will include. LoadSound
84547   *  will search your directory for these extensions, and will pick
84548   *  a format that is compatable with the client's web browser.
84549   *  <a href="http://media.io/">Here</a> is a free online file
84550   *  converter.
84551   *
84552   *  @method soundFormats
84553   *  @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg'
84554   *  @example
84555   *  <div><code>
84556   *  function preload() {
84557   *    // set the global sound formats
84558   *    soundFormats('mp3', 'ogg');
84559   *
84560   *    // load either beatbox.mp3, or .ogg, depending on browser
84561   *    mySound = loadSound('assets/beatbox.mp3');
84562   *  }
84563   *
84564   *  function setup() {
84565   *    mySound.play();
84566   *  }
84567   *  </code></div>
84568   */
84569  p5.prototype.soundFormats = function () {
84570    // reset extensions array
84571    p5sound.extensions = [];
84572    // add extensions
84573    for (var i = 0; i < arguments.length; i++) {
84574      arguments[i] = arguments[i].toLowerCase();
84575      if ([
84576          'mp3',
84577          'wav',
84578          'ogg',
84579          'm4a',
84580          'aac'
84581        ].indexOf(arguments[i]) > -1) {
84582        p5sound.extensions.push(arguments[i]);
84583      } else {
84584        throw arguments[i] + ' is not a valid sound format!';
84585      }
84586    }
84587  };
84588  p5.prototype.disposeSound = function () {
84589    for (var i = 0; i < p5sound.soundArray.length; i++) {
84590      p5sound.soundArray[i].dispose();
84591    }
84592  };
84593  // register removeSound to dispose of p5sound SoundFiles, Convolvers,
84594  // Oscillators etc when sketch ends
84595  p5.prototype.registerMethod('remove', p5.prototype.disposeSound);
84596  p5.prototype._checkFileFormats = function (paths) {
84597    var path;
84598    // if path is a single string, check to see if extension is provided
84599    if (typeof paths === 'string') {
84600      path = paths;
84601      // see if extension is provided
84602      var extTest = path.split('.').pop();
84603      // if an extension is provided...
84604      if ([
84605          'mp3',
84606          'wav',
84607          'ogg',
84608          'm4a',
84609          'aac'
84610        ].indexOf(extTest) > -1) {
84611        if (p5.prototype.isFileSupported(extTest)) {
84612          path = path;
84613        } else {
84614          var pathSplit = path.split('.');
84615          var pathCore = pathSplit[pathSplit.length - 1];
84616          for (var i = 0; i < p5sound.extensions.length; i++) {
84617            var extension = p5sound.extensions[i];
84618            var supported = p5.prototype.isFileSupported(extension);
84619            if (supported) {
84620              pathCore = '';
84621              if (pathSplit.length === 2) {
84622                pathCore += pathSplit[0];
84623              }
84624              for (var i = 1; i <= pathSplit.length - 2; i++) {
84625                var p = pathSplit[i];
84626                pathCore += '.' + p;
84627              }
84628              path = pathCore += '.';
84629              path = path += extension;
84630              break;
84631            }
84632          }
84633        }
84634      } else {
84635        for (var i = 0; i < p5sound.extensions.length; i++) {
84636          var extension = p5sound.extensions[i];
84637          var supported = p5.prototype.isFileSupported(extension);
84638          if (supported) {
84639            path = path + '.' + extension;
84640            break;
84641          }
84642        }
84643      }
84644    } else if (typeof paths === 'object') {
84645      for (var i = 0; i < paths.length; i++) {
84646        var extension = paths[i].split('.').pop();
84647        var supported = p5.prototype.isFileSupported(extension);
84648        if (supported) {
84649          // console.log('.'+extension + ' is ' + supported +
84650          //  ' supported by your browser.');
84651          path = paths[i];
84652          break;
84653        }
84654      }
84655    }
84656    return path;
84657  };
84658  /**
84659   *  Used by Osc and Envelope to chain signal math
84660   */
84661  p5.prototype._mathChain = function (o, math, thisChain, nextChain, type) {
84662    // if this type of math already exists in the chain, replace it
84663    for (var i in o.mathOps) {
84664      if (o.mathOps[i] instanceof type) {
84665        o.mathOps[i].dispose();
84666        thisChain = i;
84667        if (thisChain < o.mathOps.length - 1) {
84668          nextChain = o.mathOps[i + 1];
84669        }
84670      }
84671    }
84672    o.mathOps[thisChain - 1].disconnect();
84673    o.mathOps[thisChain - 1].connect(math);
84674    math.connect(nextChain);
84675    o.mathOps[thisChain] = math;
84676    return o;
84677  };
84678  // helper methods to convert audio file as .wav format,
84679  // will use as saving .wav file and saving blob object
84680  // Thank you to Matt Diamond's RecorderJS (MIT License)
84681  // https://github.com/mattdiamond/Recorderjs
84682  function convertToWav(audioBuffer) {
84683    var leftChannel, rightChannel;
84684    leftChannel = audioBuffer.getChannelData(0);
84685    // handle mono files
84686    if (audioBuffer.numberOfChannels > 1) {
84687      rightChannel = audioBuffer.getChannelData(1);
84688    } else {
84689      rightChannel = leftChannel;
84690    }
84691    var interleaved = interleave(leftChannel, rightChannel);
84692    // create the buffer and view to create the .WAV file
84693    var buffer = new window.ArrayBuffer(44 + interleaved.length * 2);
84694    var view = new window.DataView(buffer);
84695    // write the WAV container,
84696    // check spec at: https://web.archive.org/web/20171215131933/http://tiny.systems/software/soundProgrammer/WavFormatDocs.pdf
84697    // RIFF chunk descriptor
84698    writeUTFBytes(view, 0, 'RIFF');
84699    view.setUint32(4, 36 + interleaved.length * 2, true);
84700    writeUTFBytes(view, 8, 'WAVE');
84701    // FMT sub-chunk
84702    writeUTFBytes(view, 12, 'fmt ');
84703    view.setUint32(16, 16, true);
84704    view.setUint16(20, 1, true);
84705    // stereo (2 channels)
84706    view.setUint16(22, 2, true);
84707    view.setUint32(24, 44100, true);
84708    view.setUint32(28, 44100 * 4, true);
84709    view.setUint16(32, 4, true);
84710    view.setUint16(34, 16, true);
84711    // data sub-chunk
84712    writeUTFBytes(view, 36, 'data');
84713    view.setUint32(40, interleaved.length * 2, true);
84714    // write the PCM samples
84715    var lng = interleaved.length;
84716    var index = 44;
84717    var volume = 1;
84718    for (var i = 0; i < lng; i++) {
84719      view.setInt16(index, interleaved[i] * (32767 * volume), true);
84720      index += 2;
84721    }
84722    return view;
84723  }
84724  // helper methods to save waves
84725  function interleave(leftChannel, rightChannel) {
84726    var length = leftChannel.length + rightChannel.length;
84727    var result = new Float32Array(length);
84728    var inputIndex = 0;
84729    for (var index = 0; index < length;) {
84730      result[index++] = leftChannel[inputIndex];
84731      result[index++] = rightChannel[inputIndex];
84732      inputIndex++;
84733    }
84734    return result;
84735  }
84736  function writeUTFBytes(view, offset, string) {
84737    var lng = string.length;
84738    for (var i = 0; i < lng; i++) {
84739      view.setUint8(offset + i, string.charCodeAt(i));
84740    }
84741  }
84742  return {
84743    convertToWav: convertToWav,
84744    midiToFreq: midiToFreq,
84745    noteToFreq: noteToFreq
84746  };
84747}(master);
84748var errorHandler;
84749'use strict';
84750errorHandler = function () {
84751  /*
84752      Helper function to generate an error
84753      with a custom stack trace that points to the sketch
84754      and removes other parts of the stack trace.
84755  
84756      @private
84757      @class customError
84758      @constructor
84759      @param  {String} name         custom  error name
84760      @param  {String} errorTrace   custom error trace
84761      @param  {String} failedPath     path to the file that failed to load
84762      @property {String} name custom error name
84763      @property {String} message custom error message
84764      @property {String} stack trace the error back to a line in the user's sketch.
84765                               Note: this edits out stack trace within p5.js and p5.sound.
84766      @property {String} originalStack unedited, original stack trace
84767      @property {String} failedPath path to the file that failed to load
84768      @return {Error}     returns a custom Error object
84769     */
84770  var CustomError = function (name, errorTrace, failedPath) {
84771    var err = new Error();
84772    var tempStack, splitStack;
84773    err.name = name;
84774    err.originalStack = err.stack + errorTrace;
84775    tempStack = err.stack + errorTrace;
84776    err.failedPath = failedPath;
84777    // only print the part of the stack trace that refers to the user code:
84778    var splitStack = tempStack.split('\n');
84779    splitStack = splitStack.filter(function (ln) {
84780      return !ln.match(/(p5.|native code|globalInit)/g);
84781    });
84782    err.stack = splitStack.join('\n');
84783    return err;
84784  };
84785  return CustomError;
84786}();
84787var panner;
84788'use strict';
84789panner = function () {
84790  var p5sound = master;
84791  var ac = p5sound.audiocontext;
84792  // Stereo panner
84793  // if there is a stereo panner node use it
84794  if (typeof ac.createStereoPanner !== 'undefined') {
84795    p5.Panner = function (input, output) {
84796      this.stereoPanner = this.input = ac.createStereoPanner();
84797      input.connect(this.stereoPanner);
84798      this.stereoPanner.connect(output);
84799    };
84800    p5.Panner.prototype.pan = function (val, tFromNow) {
84801      var time = tFromNow || 0;
84802      var t = ac.currentTime + time;
84803      this.stereoPanner.pan.linearRampToValueAtTime(val, t);
84804    };
84805    //not implemented because stereopanner
84806    //node does not require this and will automatically
84807    //convert single channel or multichannel to stereo.
84808    //tested with single and stereo, not with (>2) multichannel
84809    p5.Panner.prototype.inputChannels = function () {
84810    };
84811    p5.Panner.prototype.connect = function (obj) {
84812      this.stereoPanner.connect(obj);
84813    };
84814    p5.Panner.prototype.disconnect = function () {
84815      if (this.stereoPanner) {
84816        this.stereoPanner.disconnect();
84817      }
84818    };
84819  } else {
84820    // if there is no createStereoPanner object
84821    // such as in safari 7.1.7 at the time of writing this
84822    // use this method to create the effect
84823    p5.Panner = function (input, output, numInputChannels) {
84824      this.input = ac.createGain();
84825      input.connect(this.input);
84826      this.left = ac.createGain();
84827      this.right = ac.createGain();
84828      this.left.channelInterpretation = 'discrete';
84829      this.right.channelInterpretation = 'discrete';
84830      // if input is stereo
84831      if (numInputChannels > 1) {
84832        this.splitter = ac.createChannelSplitter(2);
84833        this.input.connect(this.splitter);
84834        this.splitter.connect(this.left, 1);
84835        this.splitter.connect(this.right, 0);
84836      } else {
84837        this.input.connect(this.left);
84838        this.input.connect(this.right);
84839      }
84840      this.output = ac.createChannelMerger(2);
84841      this.left.connect(this.output, 0, 1);
84842      this.right.connect(this.output, 0, 0);
84843      this.output.connect(output);
84844    };
84845    // -1 is left, +1 is right
84846    p5.Panner.prototype.pan = function (val, tFromNow) {
84847      var time = tFromNow || 0;
84848      var t = ac.currentTime + time;
84849      var v = (val + 1) / 2;
84850      var rightVal = Math.cos(v * Math.PI / 2);
84851      var leftVal = Math.sin(v * Math.PI / 2);
84852      this.left.gain.linearRampToValueAtTime(leftVal, t);
84853      this.right.gain.linearRampToValueAtTime(rightVal, t);
84854    };
84855    p5.Panner.prototype.inputChannels = function (numChannels) {
84856      if (numChannels === 1) {
84857        this.input.disconnect();
84858        this.input.connect(this.left);
84859        this.input.connect(this.right);
84860      } else if (numChannels === 2) {
84861        if (typeof (this.splitter === 'undefined')) {
84862          this.splitter = ac.createChannelSplitter(2);
84863        }
84864        this.input.disconnect();
84865        this.input.connect(this.splitter);
84866        this.splitter.connect(this.left, 1);
84867        this.splitter.connect(this.right, 0);
84868      }
84869    };
84870    p5.Panner.prototype.connect = function (obj) {
84871      this.output.connect(obj);
84872    };
84873    p5.Panner.prototype.disconnect = function () {
84874      if (this.output) {
84875        this.output.disconnect();
84876      }
84877    };
84878  }
84879}(master);
84880var soundfile;
84881'use strict';
84882soundfile = function () {
84883  var CustomError = errorHandler;
84884  var p5sound = master;
84885  var ac = p5sound.audiocontext;
84886  var midiToFreq = helpers.midiToFreq;
84887  var convertToWav = helpers.convertToWav;
84888  /**
84889   *  <p>SoundFile object with a path to a file.</p>
84890   *
84891   *  <p>The p5.SoundFile may not be available immediately because
84892   *  it loads the file information asynchronously.</p>
84893   *
84894   *  <p>To do something with the sound as soon as it loads
84895   *  pass the name of a function as the second parameter.</p>
84896   *
84897   *  <p>Only one file path is required. However, audio file formats
84898   *  (i.e. mp3, ogg, wav and m4a/aac) are not supported by all
84899   *  web browsers. If you want to ensure compatability, instead of a single
84900   *  file path, you may include an Array of filepaths, and the browser will
84901   *  choose a format that works.</p>
84902   *
84903   *  @class p5.SoundFile
84904   *  @constructor
84905   *  @param {String|Array} path   path to a sound file (String). Optionally,
84906   *                               you may include multiple file formats in
84907   *                               an array. Alternately, accepts an object
84908   *                               from the HTML5 File API, or a p5.File.
84909   *  @param {Function} [successCallback]   Name of a function to call once file loads
84910   *  @param {Function} [errorCallback]   Name of a function to call if file fails to
84911   *                                      load. This function will receive an error or
84912   *                                     XMLHttpRequest object with information
84913   *                                     about what went wrong.
84914   *  @param {Function} [whileLoadingCallback]   Name of a function to call while file
84915   *                                             is loading. That function will
84916   *                                             receive progress of the request to
84917   *                                             load the sound file
84918   *                                             (between 0 and 1) as its first
84919   *                                             parameter. This progress
84920   *                                             does not account for the additional
84921   *                                             time needed to decode the audio data.
84922   *
84923   *  @example
84924   *  <div><code>
84925   *
84926   *  function preload() {
84927   *    soundFormats('mp3', 'ogg');
84928   *    mySound = loadSound('assets/doorbell.mp3');
84929   *  }
84930   *
84931   *  function setup() {
84932   *    mySound.setVolume(0.1);
84933   *    mySound.play();
84934   *  }
84935   *
84936   * </code></div>
84937   */
84938  p5.SoundFile = function (paths, onload, onerror, whileLoading) {
84939    if (typeof paths !== 'undefined') {
84940      if (typeof paths === 'string' || typeof paths[0] === 'string') {
84941        var path = p5.prototype._checkFileFormats(paths);
84942        this.url = path;
84943      } else if (typeof paths === 'object') {
84944        if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
84945          // The File API isn't supported in this browser
84946          throw 'Unable to load file because the File API is not supported';
84947        }
84948      }
84949      // if type is a p5.File...get the actual file
84950      if (paths.file) {
84951        paths = paths.file;
84952      }
84953      this.file = paths;
84954    }
84955    // private _onended callback, set by the method: onended(callback)
84956    this._onended = function () {
84957    };
84958    this._looping = false;
84959    this._playing = false;
84960    this._paused = false;
84961    this._pauseTime = 0;
84962    // cues for scheduling events with addCue() removeCue()
84963    this._cues = [];
84964    this._cueIDCounter = 0;
84965    //  position of the most recently played sample
84966    this._lastPos = 0;
84967    this._counterNode = null;
84968    this._scopeNode = null;
84969    // array of sources so that they can all be stopped!
84970    this.bufferSourceNodes = [];
84971    // current source
84972    this.bufferSourceNode = null;
84973    this.buffer = null;
84974    this.playbackRate = 1;
84975    this.input = p5sound.audiocontext.createGain();
84976    this.output = p5sound.audiocontext.createGain();
84977    this.reversed = false;
84978    // start and end of playback / loop
84979    this.startTime = 0;
84980    this.endTime = null;
84981    this.pauseTime = 0;
84982    // "restart" would stop playback before retriggering
84983    this.mode = 'sustain';
84984    // time that playback was started, in millis
84985    this.startMillis = null;
84986    // stereo panning
84987    this.panPosition = 0;
84988    this.panner = new p5.Panner(this.output, p5sound.input, 2);
84989    // it is possible to instantiate a soundfile with no path
84990    if (this.url || this.file) {
84991      this.load(onload, onerror);
84992    }
84993    // add this p5.SoundFile to the soundArray
84994    p5sound.soundArray.push(this);
84995    if (typeof whileLoading === 'function') {
84996      this._whileLoading = whileLoading;
84997    } else {
84998      this._whileLoading = function () {
84999      };
85000    }
85001  };
85002  // register preload handling of loadSound
85003  p5.prototype.registerPreloadMethod('loadSound', p5.prototype);
85004  /**
85005   *  loadSound() returns a new p5.SoundFile from a specified
85006   *  path. If called during preload(), the p5.SoundFile will be ready
85007   *  to play in time for setup() and draw(). If called outside of
85008   *  preload, the p5.SoundFile will not be ready immediately, so
85009   *  loadSound accepts a callback as the second parameter. Using a
85010   *  <a href="https://github.com/processing/p5.js/wiki/Local-server">
85011   *  local server</a> is recommended when loading external files.
85012   *
85013   *  @method loadSound
85014   *  @param  {String|Array}   path     Path to the sound file, or an array with
85015   *                                    paths to soundfiles in multiple formats
85016   *                                    i.e. ['sound.ogg', 'sound.mp3'].
85017   *                                    Alternately, accepts an object: either
85018   *                                    from the HTML5 File API, or a p5.File.
85019   *  @param {Function} [successCallback]   Name of a function to call once file loads
85020   *  @param {Function} [errorCallback]   Name of a function to call if there is
85021   *                                      an error loading the file.
85022   *  @param {Function} [whileLoading] Name of a function to call while file is loading.
85023   *                                 This function will receive the percentage loaded
85024   *                                 so far, from 0.0 to 1.0.
85025   *  @return {SoundFile}            Returns a p5.SoundFile
85026   *  @example
85027   *  <div><code>
85028   *  function preload() {
85029   *   mySound = loadSound('assets/doorbell.mp3');
85030   *  }
85031   *
85032   *  function setup() {
85033   *    mySound.setVolume(0.1);
85034   *    mySound.play();
85035   *  }
85036   *  </code></div>
85037   */
85038  p5.prototype.loadSound = function (path, callback, onerror, whileLoading) {
85039    // if loading locally without a server
85040    if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {
85041      window.alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');
85042    }
85043    var self = this;
85044    var s = new p5.SoundFile(path, function () {
85045      if (typeof callback === 'function') {
85046        callback.apply(self, arguments);
85047      }
85048      if (typeof self._decrementPreload === 'function') {
85049        self._decrementPreload();
85050      }
85051    }, onerror, whileLoading);
85052    return s;
85053  };
85054  /**
85055   * This is a helper function that the p5.SoundFile calls to load
85056   * itself. Accepts a callback (the name of another function)
85057   * as an optional parameter.
85058   *
85059   * @private
85060   * @param {Function} [successCallback]   Name of a function to call once file loads
85061   * @param {Function} [errorCallback]   Name of a function to call if there is an error
85062   */
85063  p5.SoundFile.prototype.load = function (callback, errorCallback) {
85064    var self = this;
85065    var errorTrace = new Error().stack;
85066    if (this.url !== undefined && this.url !== '') {
85067      var request = new XMLHttpRequest();
85068      request.addEventListener('progress', function (evt) {
85069        self._updateProgress(evt);
85070      }, false);
85071      request.open('GET', this.url, true);
85072      request.responseType = 'arraybuffer';
85073      request.onload = function () {
85074        if (request.status === 200) {
85075          // on sucess loading file:
85076          if (!self.panner)
85077            return;
85078          ac.decodeAudioData(request.response, // success decoding buffer:
85079          function (buff) {
85080            if (!self.panner)
85081              return;
85082            self.buffer = buff;
85083            self.panner.inputChannels(buff.numberOfChannels);
85084            if (callback) {
85085              callback(self);
85086            }
85087          }, // error decoding buffer. "e" is undefined in Chrome 11/22/2015
85088          function () {
85089            if (!self.panner)
85090              return;
85091            var err = new CustomError('decodeAudioData', errorTrace, self.url);
85092            var msg = 'AudioContext error at decodeAudioData for ' + self.url;
85093            if (errorCallback) {
85094              err.msg = msg;
85095              errorCallback(err);
85096            } else {
85097              console.error(msg + '\n The error stack trace includes: \n' + err.stack);
85098            }
85099          });
85100        } else {
85101          if (!self.panner)
85102            return;
85103          var err = new CustomError('loadSound', errorTrace, self.url);
85104          var msg = 'Unable to load ' + self.url + '. The request status was: ' + request.status + ' (' + request.statusText + ')';
85105          if (errorCallback) {
85106            err.message = msg;
85107            errorCallback(err);
85108          } else {
85109            console.error(msg + '\n The error stack trace includes: \n' + err.stack);
85110          }
85111        }
85112      };
85113      // if there is another error, aside from 404...
85114      request.onerror = function () {
85115        var err = new CustomError('loadSound', errorTrace, self.url);
85116        var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.';
85117        if (errorCallback) {
85118          err.message = msg;
85119          errorCallback(err);
85120        } else {
85121          console.error(msg + '\n The error stack trace includes: \n' + err.stack);
85122        }
85123      };
85124      request.send();
85125    } else if (this.file !== undefined) {
85126      var reader = new FileReader();
85127      reader.onload = function () {
85128        if (!self.panner)
85129          return;
85130        ac.decodeAudioData(reader.result, function (buff) {
85131          if (!self.panner)
85132            return;
85133          self.buffer = buff;
85134          self.panner.inputChannels(buff.numberOfChannels);
85135          if (callback) {
85136            callback(self);
85137          }
85138        });
85139      };
85140      reader.onerror = function (e) {
85141        if (!self.panner)
85142          return;
85143        if (onerror) {
85144          onerror(e);
85145        }
85146      };
85147      reader.readAsArrayBuffer(this.file);
85148    }
85149  };
85150  // TO DO: use this method to create a loading bar that shows progress during file upload/decode.
85151  p5.SoundFile.prototype._updateProgress = function (evt) {
85152    if (evt.lengthComputable) {
85153      var percentComplete = evt.loaded / evt.total * 0.99;
85154      this._whileLoading(percentComplete, evt);
85155    } else {
85156      // Unable to compute progress information since the total size is unknown
85157      this._whileLoading('size unknown');
85158    }
85159  };
85160  /**
85161   *  Returns true if the sound file finished loading successfully.
85162   *
85163   *  @method  isLoaded
85164   *  @return {Boolean}
85165   */
85166  p5.SoundFile.prototype.isLoaded = function () {
85167    if (this.buffer) {
85168      return true;
85169    } else {
85170      return false;
85171    }
85172  };
85173  /**
85174   * Play the p5.SoundFile
85175   *
85176   * @method play
85177   * @param {Number} [startTime]            (optional) schedule playback to start (in seconds from now).
85178   * @param {Number} [rate]             (optional) playback rate
85179   * @param {Number} [amp]              (optional) amplitude (volume)
85180   *                                     of playback
85181   * @param {Number} [cueStart]        (optional) cue start time in seconds
85182   * @param {Number} [duration]          (optional) duration of playback in seconds
85183   */
85184  p5.SoundFile.prototype.play = function (startTime, rate, amp, _cueStart, duration) {
85185    if (!this.output) {
85186      console.warn('SoundFile.play() called after dispose');
85187      return;
85188    }
85189    var self = this;
85190    var now = p5sound.audiocontext.currentTime;
85191    var cueStart, cueEnd;
85192    var time = startTime || 0;
85193    if (time < 0) {
85194      time = 0;
85195    }
85196    time = time + now;
85197    if (typeof rate !== 'undefined') {
85198      this.rate(rate);
85199    }
85200    if (typeof amp !== 'undefined') {
85201      this.setVolume(amp);
85202    }
85203    // TO DO: if already playing, create array of buffers for easy stop()
85204    if (this.buffer) {
85205      // reset the pause time (if it was paused)
85206      this._pauseTime = 0;
85207      // handle restart playmode
85208      if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) {
85209        this.bufferSourceNode.stop(time);
85210        this._counterNode.stop(time);
85211      }
85212      //dont create another instance if already playing
85213      if (this.mode === 'untildone' && this.isPlaying()) {
85214        return;
85215      }
85216      // make a new source and counter. They are automatically assigned playbackRate and buffer
85217      this.bufferSourceNode = this._initSourceNode();
85218      // garbage collect counterNode and create a new one
85219      delete this._counterNode;
85220      this._counterNode = this._initCounterNode();
85221      if (_cueStart) {
85222        if (_cueStart >= 0 && _cueStart < this.buffer.duration) {
85223          // this.startTime = cueStart;
85224          cueStart = _cueStart;
85225        } else {
85226          throw 'start time out of range';
85227        }
85228      } else {
85229        cueStart = 0;
85230      }
85231      if (duration) {
85232        // if duration is greater than buffer.duration, just play entire file anyway rather than throw an error
85233        duration = duration <= this.buffer.duration - cueStart ? duration : this.buffer.duration;
85234      }
85235      // if it was paused, play at the pause position
85236      if (this._paused) {
85237        this.bufferSourceNode.start(time, this.pauseTime, duration);
85238        this._counterNode.start(time, this.pauseTime, duration);
85239      } else {
85240        this.bufferSourceNode.start(time, cueStart, duration);
85241        this._counterNode.start(time, cueStart, duration);
85242      }
85243      this._playing = true;
85244      this._paused = false;
85245      // add source to sources array, which is used in stopAll()
85246      this.bufferSourceNodes.push(this.bufferSourceNode);
85247      this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1;
85248      // delete this.bufferSourceNode from the sources array when it is done playing:
85249      var clearOnEnd = function () {
85250        this._playing = false;
85251        this.removeEventListener('ended', clearOnEnd, false);
85252        // call the onended callback
85253        self._onended(self);
85254        self.bufferSourceNodes.forEach(function (n, i) {
85255          if (n._playing === false) {
85256            self.bufferSourceNodes.splice(i);
85257          }
85258        });
85259        if (self.bufferSourceNodes.length === 0) {
85260          self._playing = false;
85261        }
85262      };
85263      this.bufferSourceNode.onended = clearOnEnd;
85264    } else {
85265      throw 'not ready to play file, buffer has yet to load. Try preload()';
85266    }
85267    // if looping, will restart at original time
85268    this.bufferSourceNode.loop = this._looping;
85269    this._counterNode.loop = this._looping;
85270    if (this._looping === true) {
85271      cueEnd = duration ? duration : cueStart - 1e-15;
85272      this.bufferSourceNode.loopStart = cueStart;
85273      this.bufferSourceNode.loopEnd = cueEnd;
85274      this._counterNode.loopStart = cueStart;
85275      this._counterNode.loopEnd = cueEnd;
85276    }
85277  };
85278  /**
85279   *  p5.SoundFile has two play modes: <code>restart</code> and
85280   *  <code>sustain</code>. Play Mode determines what happens to a
85281   *  p5.SoundFile if it is triggered while in the middle of playback.
85282   *  In sustain mode, playback will continue simultaneous to the
85283   *  new playback. In restart mode, play() will stop playback
85284   *  and start over. With untilDone, a sound will play only if it's
85285   *  not already playing. Sustain is the default mode.
85286   *
85287   *  @method  playMode
85288   *  @param  {String} str 'restart' or 'sustain' or 'untilDone'
85289   *  @example
85290   *  <div><code>
85291   *  var mySound;
85292   *  function preload(){
85293   *    mySound = loadSound('assets/Damscray_DancingTiger.mp3');
85294   *  }
85295   *  function mouseClicked() {
85296   *    mySound.playMode('sustain');
85297   *    mySound.play();
85298   *  }
85299   *  function keyPressed() {
85300   *    mySound.playMode('restart');
85301   *    mySound.play();
85302   *  }
85303   *
85304   * </code></div>
85305   */
85306  p5.SoundFile.prototype.playMode = function (str) {
85307    var s = str.toLowerCase();
85308    // if restart, stop all other sounds from playing
85309    if (s === 'restart' && this.buffer && this.bufferSourceNode) {
85310      for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {
85311        var now = p5sound.audiocontext.currentTime;
85312        this.bufferSourceNodes[i].stop(now);
85313      }
85314    }
85315    // set play mode to effect future playback
85316    if (s === 'restart' || s === 'sustain' || s === 'untildone') {
85317      this.mode = s;
85318    } else {
85319      throw 'Invalid play mode. Must be either "restart" or "sustain"';
85320    }
85321  };
85322  /**
85323   *  Pauses a file that is currently playing. If the file is not
85324   *  playing, then nothing will happen.
85325   *
85326   *  After pausing, .play() will resume from the paused
85327   *  position.
85328   *  If p5.SoundFile had been set to loop before it was paused,
85329   *  it will continue to loop after it is unpaused with .play().
85330   *
85331   *  @method pause
85332   *  @param {Number} [startTime] (optional) schedule event to occur
85333   *                               seconds from now
85334   *  @example
85335   *  <div><code>
85336   *  var soundFile;
85337   *
85338   *  function preload() {
85339   *    soundFormats('ogg', 'mp3');
85340   *    soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3');
85341   *  }
85342   *  function setup() {
85343   *    background(0, 255, 0);
85344   *    soundFile.setVolume(0.1);
85345   *    soundFile.loop();
85346   *  }
85347   *  function keyTyped() {
85348   *    if (key == 'p') {
85349   *      soundFile.pause();
85350   *      background(255, 0, 0);
85351   *    }
85352   *  }
85353   *
85354   *  function keyReleased() {
85355   *    if (key == 'p') {
85356   *      soundFile.play();
85357   *      background(0, 255, 0);
85358   *    }
85359   *  }
85360   *  </code>
85361   *  </div>
85362   */
85363  p5.SoundFile.prototype.pause = function (startTime) {
85364    var now = p5sound.audiocontext.currentTime;
85365    var time = startTime || 0;
85366    var pTime = time + now;
85367    if (this.isPlaying() && this.buffer && this.bufferSourceNode) {
85368      this.pauseTime = this.currentTime();
85369      this.bufferSourceNode.stop(pTime);
85370      this._counterNode.stop(pTime);
85371      this._paused = true;
85372      this._playing = false;
85373      this._pauseTime = this.currentTime();
85374    } else {
85375      this._pauseTime = 0;
85376    }
85377  };
85378  /**
85379   * Loop the p5.SoundFile. Accepts optional parameters to set the
85380   * playback rate, playback volume, loopStart, loopEnd.
85381   *
85382   * @method loop
85383   * @param {Number} [startTime] (optional) schedule event to occur
85384   *                             seconds from now
85385   * @param {Number} [rate]        (optional) playback rate
85386   * @param {Number} [amp]         (optional) playback volume
85387   * @param {Number} [cueLoopStart] (optional) startTime in seconds
85388   * @param {Number} [duration]  (optional) loop duration in seconds
85389   */
85390  p5.SoundFile.prototype.loop = function (startTime, rate, amp, loopStart, duration) {
85391    this._looping = true;
85392    this.play(startTime, rate, amp, loopStart, duration);
85393  };
85394  /**
85395   * Set a p5.SoundFile's looping flag to true or false. If the sound
85396   * is currently playing, this change will take effect when it
85397   * reaches the end of the current playback.
85398   *
85399   * @method setLoop
85400   * @param {Boolean} Boolean   set looping to true or false
85401   */
85402  p5.SoundFile.prototype.setLoop = function (bool) {
85403    if (bool === true) {
85404      this._looping = true;
85405    } else if (bool === false) {
85406      this._looping = false;
85407    } else {
85408      throw 'Error: setLoop accepts either true or false';
85409    }
85410    if (this.bufferSourceNode) {
85411      this.bufferSourceNode.loop = this._looping;
85412      this._counterNode.loop = this._looping;
85413    }
85414  };
85415  /**
85416   * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not.
85417   *
85418   * @method isLooping
85419   * @return {Boolean}
85420   */
85421  p5.SoundFile.prototype.isLooping = function () {
85422    if (!this.bufferSourceNode) {
85423      return false;
85424    }
85425    if (this._looping === true && this.isPlaying() === true) {
85426      return true;
85427    }
85428    return false;
85429  };
85430  /**
85431   *  Returns true if a p5.SoundFile is playing, false if not (i.e.
85432   *  paused or stopped).
85433   *
85434   *  @method isPlaying
85435   *  @return {Boolean}
85436   */
85437  p5.SoundFile.prototype.isPlaying = function () {
85438    return this._playing;
85439  };
85440  /**
85441   *  Returns true if a p5.SoundFile is paused, false if not (i.e.
85442   *  playing or stopped).
85443   *
85444   *  @method  isPaused
85445   *  @return {Boolean}
85446   */
85447  p5.SoundFile.prototype.isPaused = function () {
85448    return this._paused;
85449  };
85450  /**
85451   * Stop soundfile playback.
85452   *
85453   * @method stop
85454   * @param {Number} [startTime] (optional) schedule event to occur
85455   *                             in seconds from now
85456   */
85457  p5.SoundFile.prototype.stop = function (timeFromNow) {
85458    var time = timeFromNow || 0;
85459    if (this.mode === 'sustain' || this.mode === 'untildone') {
85460      this.stopAll(time);
85461      this._playing = false;
85462      this.pauseTime = 0;
85463      this._paused = false;
85464    } else if (this.buffer && this.bufferSourceNode) {
85465      var now = p5sound.audiocontext.currentTime;
85466      var t = time || 0;
85467      this.pauseTime = 0;
85468      this.bufferSourceNode.stop(now + t);
85469      this._counterNode.stop(now + t);
85470      this._playing = false;
85471      this._paused = false;
85472    }
85473  };
85474  /**
85475   *  Stop playback on all of this soundfile's sources.
85476   *  @private
85477   */
85478  p5.SoundFile.prototype.stopAll = function (_time) {
85479    var now = p5sound.audiocontext.currentTime;
85480    var time = _time || 0;
85481    if (this.buffer && this.bufferSourceNode) {
85482      for (var i = 0; i < this.bufferSourceNodes.length; i++) {
85483        if (typeof this.bufferSourceNodes[i] !== undefined) {
85484          try {
85485            this.bufferSourceNodes[i].onended = function () {
85486            };
85487            this.bufferSourceNodes[i].stop(now + time);
85488          } catch (e) {
85489          }
85490        }
85491      }
85492      this._counterNode.stop(now + time);
85493      this._onended(this);
85494    }
85495  };
85496  /**
85497   *  Multiply the output volume (amplitude) of a sound file
85498   *  between 0.0 (silence) and 1.0 (full volume).
85499   *  1.0 is the maximum amplitude of a digital sound, so multiplying
85500   *  by greater than 1.0 may cause digital distortion. To
85501   *  fade, provide a <code>rampTime</code> parameter. For more
85502   *  complex fades, see the Envelope class.
85503   *
85504   *  Alternately, you can pass in a signal source such as an
85505   *  oscillator to modulate the amplitude with an audio signal.
85506   *
85507   *  @method  setVolume
85508   *  @param {Number|Object} volume  Volume (amplitude) between 0.0
85509   *                                     and 1.0 or modulating signal/oscillator
85510   *  @param {Number} [rampTime]  Fade for t seconds
85511   *  @param {Number} [timeFromNow]  Schedule this event to happen at
85512   *                                 t seconds in the future
85513   */
85514  p5.SoundFile.prototype.setVolume = function (vol, _rampTime, _tFromNow) {
85515    if (typeof vol === 'number') {
85516      var rampTime = _rampTime || 0;
85517      var tFromNow = _tFromNow || 0;
85518      var now = p5sound.audiocontext.currentTime;
85519      var currentVol = this.output.gain.value;
85520      this.output.gain.cancelScheduledValues(now + tFromNow);
85521      this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);
85522      this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);
85523    } else if (vol) {
85524      vol.connect(this.output.gain);
85525    } else {
85526      // return the Gain Node
85527      return this.output.gain;
85528    }
85529  };
85530  // same as setVolume, to match Processing Sound
85531  p5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume;
85532  // these are the same thing
85533  p5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume;
85534  p5.SoundFile.prototype.getVolume = function () {
85535    return this.output.gain.value;
85536  };
85537  /**
85538   * Set the stereo panning of a p5.sound object to
85539   * a floating point number between -1.0 (left) and 1.0 (right).
85540   * Default is 0.0 (center).
85541   *
85542   * @method pan
85543   * @param {Number} [panValue]     Set the stereo panner
85544   * @param {Number} [timeFromNow]  schedule this event to happen
85545   *                                 seconds from now
85546   * @example
85547   * <div><code>
85548   *
85549   *  var ball = {};
85550   *  var soundFile;
85551   *
85552   *  function preload() {
85553   *    soundFormats('ogg', 'mp3');
85554   *    soundFile = loadSound('assets/beatbox.mp3');
85555   *  }
85556   *
85557   *  function draw() {
85558   *    background(0);
85559   *    ball.x = constrain(mouseX, 0, width);
85560   *    ellipse(ball.x, height/2, 20, 20)
85561   *  }
85562   *
85563   *  function mousePressed(){
85564   *    // map the ball's x location to a panning degree
85565   *    // between -1.0 (left) and 1.0 (right)
85566   *    var panning = map(ball.x, 0., width,-1.0, 1.0);
85567   *    soundFile.pan(panning);
85568   *    soundFile.play();
85569   *  }
85570   *  </div></code>
85571   */
85572  p5.SoundFile.prototype.pan = function (pval, tFromNow) {
85573    this.panPosition = pval;
85574    this.panner.pan(pval, tFromNow);
85575  };
85576  /**
85577   * Returns the current stereo pan position (-1.0 to 1.0)
85578   *
85579   * @method getPan
85580   * @return {Number} Returns the stereo pan setting of the Oscillator
85581   *                          as a number between -1.0 (left) and 1.0 (right).
85582   *                          0.0 is center and default.
85583   */
85584  p5.SoundFile.prototype.getPan = function () {
85585    return this.panPosition;
85586  };
85587  /**
85588   *  Set the playback rate of a sound file. Will change the speed and the pitch.
85589   *  Values less than zero will reverse the audio buffer.
85590   *
85591   *  @method rate
85592   *  @param {Number} [playbackRate]     Set the playback rate. 1.0 is normal,
85593   *                                     .5 is half-speed, 2.0 is twice as fast.
85594   *                                     Values less than zero play backwards.
85595   *  @example
85596   *  <div><code>
85597   *  var song;
85598   *
85599   *  function preload() {
85600   *    song = loadSound('assets/Damscray_DancingTiger.mp3');
85601   *  }
85602   *
85603   *  function setup() {
85604   *    song.loop();
85605   *  }
85606   *
85607   *  function draw() {
85608   *    background(200);
85609   *
85610   *    // Set the rate to a range between 0.1 and 4
85611   *    // Changing the rate also alters the pitch
85612   *    var speed = map(mouseY, 0.1, height, 0, 2);
85613   *    speed = constrain(speed, 0.01, 4);
85614   *    song.rate(speed);
85615   *
85616   *    // Draw a circle to show what is going on
85617   *    stroke(0);
85618   *    fill(51, 100);
85619   *    ellipse(mouseX, 100, 48, 48);
85620   *  }
85621   *
85622   * </code>
85623   * </div>
85624   *
85625   */
85626  p5.SoundFile.prototype.rate = function (playbackRate) {
85627    var reverse = false;
85628    if (typeof playbackRate === 'undefined') {
85629      return this.playbackRate;
85630    }
85631    this.playbackRate = playbackRate;
85632    if (playbackRate === 0) {
85633      playbackRate = 1e-13;
85634    } else if (playbackRate < 0 && !this.reversed) {
85635      playbackRate = Math.abs(playbackRate);
85636      reverse = true;
85637    } else if (playbackRate > 0 && this.reversed) {
85638      reverse = true;
85639    }
85640    if (this.bufferSourceNode) {
85641      var now = p5sound.audiocontext.currentTime;
85642      this.bufferSourceNode.playbackRate.cancelScheduledValues(now);
85643      this.bufferSourceNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now);
85644      this._counterNode.playbackRate.cancelScheduledValues(now);
85645      this._counterNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now);
85646    }
85647    if (reverse) {
85648      this.reverseBuffer();
85649    }
85650    return this.playbackRate;
85651  };
85652  // TO DO: document this
85653  p5.SoundFile.prototype.setPitch = function (num) {
85654    var newPlaybackRate = midiToFreq(num) / midiToFreq(60);
85655    this.rate(newPlaybackRate);
85656  };
85657  p5.SoundFile.prototype.getPlaybackRate = function () {
85658    return this.playbackRate;
85659  };
85660  /**
85661   * Returns the duration of a sound file in seconds.
85662   *
85663   * @method duration
85664   * @return {Number} The duration of the soundFile in seconds.
85665   */
85666  p5.SoundFile.prototype.duration = function () {
85667    // Return Duration
85668    if (this.buffer) {
85669      return this.buffer.duration;
85670    } else {
85671      return 0;
85672    }
85673  };
85674  /**
85675   * Return the current position of the p5.SoundFile playhead, in seconds.
85676   * Time is relative to the normal buffer direction, so if `reverseBuffer`
85677   * has been called, currentTime will count backwards.
85678   *
85679   * @method currentTime
85680   * @return {Number}   currentTime of the soundFile in seconds.
85681   */
85682  p5.SoundFile.prototype.currentTime = function () {
85683    return this.reversed ? Math.abs(this._lastPos - this.buffer.length) / ac.sampleRate : this._lastPos / ac.sampleRate;
85684  };
85685  /**
85686   * Move the playhead of the song to a position, in seconds. Start timing
85687   * and playback duration. If none are given, will reset the file to play
85688   * entire duration from start to finish.
85689   *
85690   * @method jump
85691   * @param {Number} cueTime    cueTime of the soundFile in seconds.
85692   * @param {Number} duration    duration in seconds.
85693   */
85694  p5.SoundFile.prototype.jump = function (cueTime, duration) {
85695    if (cueTime < 0 || cueTime > this.buffer.duration) {
85696      throw 'jump time out of range';
85697    }
85698    if (duration > this.buffer.duration - cueTime) {
85699      throw 'end time out of range';
85700    }
85701    var cTime = cueTime || 0;
85702    var dur = duration || undefined;
85703    if (this.isPlaying()) {
85704      this.stop(0);
85705    }
85706    this.play(0, this.playbackRate, this.output.gain.value, cTime, dur);
85707  };
85708  /**
85709  * Return the number of channels in a sound file.
85710  * For example, Mono = 1, Stereo = 2.
85711  *
85712  * @method channels
85713  * @return {Number} [channels]
85714  */
85715  p5.SoundFile.prototype.channels = function () {
85716    return this.buffer.numberOfChannels;
85717  };
85718  /**
85719  * Return the sample rate of the sound file.
85720  *
85721  * @method sampleRate
85722  * @return {Number} [sampleRate]
85723  */
85724  p5.SoundFile.prototype.sampleRate = function () {
85725    return this.buffer.sampleRate;
85726  };
85727  /**
85728  * Return the number of samples in a sound file.
85729  * Equal to sampleRate * duration.
85730  *
85731  * @method frames
85732  * @return {Number}
85732 [sampleCount]
85733  */
85734  p5.SoundFile.prototype.frames = function () {
85735    return this.buffer.length;
85736  };
85737  /**
85738   * Returns an array of amplitude peaks in a p5.SoundFile that can be
85739   * used to draw a static waveform. Scans through the p5.SoundFile's
85740   * audio buffer to find the greatest amplitudes. Accepts one
85741   * parameter, 'length', which determines size of the array.
85742   * Larger arrays result in more precise waveform visualizations.
85743   *
85744   * Inspired by Wavesurfer.js.
85745   *
85746   * @method  getPeaks
85747   * @params {Number} [length] length is the size of the returned array.
85748   *                          Larger length results in more precision.
85749   *                          Defaults to 5*width of the browser window.
85750   * @returns {Float32Array} Array of peaks.
85751   */
85752  p5.SoundFile.prototype.getPeaks = function (length) {
85753    if (this.buffer) {
85754      // set length to window's width if no length is provided
85755      if (!length) {
85756        length = window.width * 5;
85757      }
85758      if (this.buffer) {
85759        var buffer = this.buffer;
85760        var sampleSize = buffer.length / length;
85761        var sampleStep = ~~(sampleSize / 10) || 1;
85762        var channels = buffer.numberOfChannels;
85763        var peaks = new Float32Array(Math.round(length));
85764        for (var c = 0; c < channels; c++) {
85765          var chan = buffer.getChannelData(c);
85766          for (var i = 0; i < length; i++) {
85767            var start = ~~(i * sampleSize);
85768            var end = ~~(start + sampleSize);
85769            var max = 0;
85770            for (var j = start; j < end; j += sampleStep) {
85771              var value = chan[j];
85772              if (value > max) {
85773                max = value;
85774              } else if (-value > max) {
85775                max = value;
85776              }
85777            }
85778            if (c === 0 || Math.abs(max) > peaks[i]) {
85779              peaks[i] = max;
85780            }
85781          }
85782        }
85783        return peaks;
85784      }
85785    } else {
85786      throw 'Cannot load peaks yet, buffer is not loaded';
85787    }
85788  };
85789  /**
85790   *  Reverses the p5.SoundFile's buffer source.
85791   *  Playback must be handled separately (see example).
85792   *
85793   *  @method  reverseBuffer
85794   *  @example
85795   *  <div><code>
85796   *  var drum;
85797   *
85798   *  function preload() {
85799   *    drum = loadSound('assets/drum.mp3');
85800   *  }
85801   *
85802   *  function setup() {
85803   *    drum.reverseBuffer();
85804   *    drum.play();
85805   *  }
85806   *
85807   * </code>
85808   * </div>
85809   */
85810  p5.SoundFile.prototype.reverseBuffer = function () {
85811    if (this.buffer) {
85812      var currentPos = this._lastPos / ac.sampleRate;
85813      var curVol = this.getVolume();
85814      this.setVolume(0, 0.001);
85815      const numChannels = this.buffer.numberOfChannels;
85816      for (var i = 0; i < numChannels; i++) {
85817        this.buffer.getChannelData(i).reverse();
85818      }
85819      // set reversed flag
85820      this.reversed = !this.reversed;
85821      if (currentPos) {
85822        this.jump(this.duration() - currentPos);
85823      }
85824      this.setVolume(curVol, 0.001);
85825    } else {
85826      throw 'SoundFile is not done loading';
85827    }
85828  };
85829  /**
85830   *  Schedule an event to be called when the soundfile
85831   *  reaches the end of a buffer. If the soundfile is
85832   *  playing through once, this will be called when it
85833   *  ends. If it is looping, it will be called when
85834   *  stop is called.
85835   *
85836   *  @method  onended
85837   *  @param  {Function} callback function to call when the
85838   *                              soundfile has ended.
85839   */
85840  p5.SoundFile.prototype.onended = function (callback) {
85841    this._onended = callback;
85842    return this;
85843  };
85844  p5.SoundFile.prototype.add = function () {
85845  };
85846  p5.SoundFile.prototype.dispose = function () {
85847    var now = p5sound.audiocontext.currentTime;
85848    // remove reference to soundfile
85849    var index = p5sound.soundArray.indexOf(this);
85850    p5sound.soundArray.splice(index, 1);
85851    this.stop(now);
85852    if (this.buffer && this.bufferSourceNode) {
85853      for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) {
85854        if (this.bufferSourceNodes[i] !== null) {
85855          this.bufferSourceNodes[i].disconnect();
85856          try {
85857            this.bufferSourceNodes[i].stop(now);
85858          } catch (e) {
85859            console.warning('no buffer source node to dispose');
85860          }
85861          this.bufferSourceNodes[i] = null;
85862        }
85863      }
85864      if (this.isPlaying()) {
85865        try {
85866          this._counterNode.stop(now);
85867        } catch (e) {
85868          console.log(e);
85869        }
85870        this._counterNode = null;
85871      }
85872    }
85873    if (this.output) {
85874      this.output.disconnect();
85875      this.output = null;
85876    }
85877    if (this.panner) {
85878      this.panner.disconnect();
85879      this.panner = null;
85880    }
85881  };
85882  /**
85883   * Connects the output of a p5sound object to input of another
85884   * p5.sound object. For example, you may connect a p5.SoundFile to an
85885   * FFT or an Effect. If no parameter is given, it will connect to
85886   * the master output. Most p5sound objects connect to the master
85887   * output when they are created.
85888   *
85889   * @method connect
85890   * @param {Object} [object] Audio object that accepts an input
85891   */
85892  p5.SoundFile.prototype.connect = function (unit) {
85893    if (!unit) {
85894      this.panner.connect(p5sound.input);
85895    } else {
85896      if (unit.hasOwnProperty('input')) {
85897        this.panner.connect(unit.input);
85898      } else {
85899        this.panner.connect(unit);
85900      }
85901    }
85902  };
85903  /**
85904   * Disconnects the output of this p5sound object.
85905   *
85906   * @method disconnect
85907   */
85908  p5.SoundFile.prototype.disconnect = function () {
85909    if (this.panner) {
85910      this.panner.disconnect();
85911    }
85912  };
85913  /**
85914   */
85915  p5.SoundFile.prototype.getLevel = function () {
85916    console.warn('p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead');
85917  };
85918  /**
85919   *  Reset the source for this SoundFile to a
85920   *  new path (URL).
85921   *
85922   *  @method  setPath
85923   *  @param {String}   path     path to audio file
85924   *  @param {Function} callback Callback
85925   */
85926  p5.SoundFile.prototype.setPath = function (p, callback) {
85927    var path = p5.prototype._checkFileFormats(p);
85928    this.url = path;
85929    this.load(callback);
85930  };
85931  /**
85932   *  Replace the current Audio Buffer with a new Buffer.
85933   *
85934   *  @method setBuffer
85935   *  @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays
85936   *                     will create a stereo source. 1 will create
85937   *                     a mono source.
85938   */
85939  p5.SoundFile.prototype.setBuffer = function (buf) {
85940    var numChannels = buf.length;
85941    var size = buf[0].length;
85942    var newBuffer = ac.createBuffer(numChannels, size, ac.sampleRate);
85943    if (!(buf[0] instanceof Float32Array)) {
85944      buf[0] = new Float32Array(buf[0]);
85945    }
85946    for (var channelNum = 0; channelNum < numChannels; channelNum++) {
85947      var channel = newBuffer.getChannelData(channelNum);
85948      channel.set(buf[channelNum]);
85949    }
85950    this.buffer = newBuffer;
85951    // set numbers of channels on input to the panner
85952    this.panner.inputChannels(numChannels);
85953  };
85954  //////////////////////////////////////////////////
85955  // script processor node with an empty buffer to help
85956  // keep a sample-accurate position in playback buffer.
85957  // Inspired by Chinmay Pendharkar's technique for Sonoport --> http://bit.ly/1HwdCsV
85958  // Copyright [2015] [Sonoport (Asia) Pte. Ltd.],
85959  // Licensed under the Apache License http://apache.org/licenses/LICENSE-2.0
85960  ////////////////////////////////////////////////////////////////////////////////////
85961  var _createCounterBuffer = function (buffer) {
85962    const len = buffer.length;
85963    const audioBuf = ac.createBuffer(1, buffer.length, ac.sampleRate);
85964    const arrayBuffer = audioBuf.getChannelData(0);
85965    for (var index = 0; index < len; index++) {
85966      arrayBuffer[index] = index;
85967    }
85968    return audioBuf;
85969  };
85970  // initialize counterNode, set its initial buffer and playbackRate
85971  p5.SoundFile.prototype._initCounterNode = function () {
85972    var self = this;
85973    var now = ac.currentTime;
85974    var cNode = ac.createBufferSource();
85975    // dispose of scope node if it already exists
85976    if (self._scopeNode) {
85977      self._scopeNode.disconnect();
85978      delete self._scopeNode.onaudioprocess;
85979      delete self._scopeNode;
85980    }
85981    self._scopeNode = ac.createScriptProcessor(256, 1, 1);
85982    // create counter buffer of the same length as self.buffer
85983    cNode.buffer = _createCounterBuffer(self.buffer);
85984    cNode.playbackRate.setValueAtTime(self.playbackRate, now);
85985    cNode.connect(self._scopeNode);
85986    self._scopeNode.connect(p5.soundOut._silentNode);
85987    self._scopeNode.onaudioprocess = function (processEvent) {
85988      var inputBuffer = processEvent.inputBuffer.getChannelData(0);
85989      self._lastPos = inputBuffer[inputBuffer.length - 1] || 0;
85990      // do any callbacks that have been scheduled
85991      self._onTimeUpdate(self._lastPos);
85992    };
85993    return cNode;
85994  };
85995  // initialize sourceNode, set its initial buffer and playbackRate
85996  p5.SoundFile.prototype._initSourceNode = function () {
85997    var bufferSourceNode = ac.createBufferSource();
85998    bufferSourceNode.buffer = this.buffer;
85999    bufferSourceNode.playbackRate.value = this.playbackRate;
86000    bufferSourceNode.connect(this.output);
86001    return bufferSourceNode;
86002  };
86003  /**
86004   *  processPeaks returns an array of timestamps where it thinks there is a beat.
86005   *
86006   *  This is an asynchronous function that processes the soundfile in an offline audio context,
86007   *  and sends the results to your callback function.
86008   *
86009   *  The process involves running the soundfile through a lowpass filter, and finding all of the
86010   *  peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks,
86011   *  it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached.
86012   *
86013   *  @method  processPeaks
86014   *  @param  {Function} callback       a function to call once this data is returned
86015   *  @param  {Number}   [initThreshold] initial threshold defaults to 0.9
86016   *  @param  {Number}   [minThreshold]   minimum threshold defaults to 0.22
86017   *  @param  {Number}   [minPeaks]       minimum number of peaks defaults to 200
86018   *  @return {Array}                  Array of timestamped peaks
86019   */
86020  p5.SoundFile.prototype.processPeaks = function (callback, _initThreshold, _minThreshold, _minPeaks) {
86021    var bufLen = this.buffer.length;
86022    var sampleRate = this.buffer.sampleRate;
86023    var buffer = this.buffer;
86024    var allPeaks = [];
86025    var initialThreshold = _initThreshold || 0.9, threshold = initialThreshold, minThreshold = _minThreshold || 0.22, minPeaks = _minPeaks || 200;
86026    // Create offline context
86027    var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate);
86028    // create buffer source
86029    var source = offlineContext.createBufferSource();
86030    source.buffer = buffer;
86031    // Create filter. TO DO: allow custom setting of filter
86032    var filter = offlineContext.createBiquadFilter();
86033    filter.type = 'lowpass';
86034    source.connect(filter);
86035    filter.connect(offlineContext.destination);
86036    // start playing at time:0
86037    source.start(0);
86038    offlineContext.startRendering();
86039    // Render the song
86040    // act on the result
86041    offlineContext.oncomplete = function (e) {
86042      if (!self.panner)
86043        return;
86044      var filteredBuffer = e.renderedBuffer;
86045      var bufferData = filteredBuffer.getChannelData(0);
86046      // step 1:
86047      // create Peak instances, add them to array, with strength and sampleIndex
86048      do {
86049        allPeaks = getPeaksAtThreshold(bufferData, threshold);
86050        threshold -= 0.005;
86051      } while (Object.keys(allPeaks).length < minPeaks && threshold >= minThreshold);
86052      // step 2:
86053      // find intervals for each peak in the sampleIndex, add tempos array
86054      var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks);
86055      // step 3: find top tempos
86056      var groups = groupNeighborsByTempo(intervalCounts, filteredBuffer.sampleRate);
86057      // sort top intervals
86058      var topTempos = groups.sort(function (intA, intB) {
86059        return intB.count - intA.count;
86060      }).splice(0, 5);
86061      // set this SoundFile's tempo to the top tempo ??
86062      this.tempo = topTempos[0].tempo;
86063      // step 4:
86064      // new array of peaks at top tempo within a bpmVariance
86065      var bpmVariance = 5;
86066      var tempoPeaks = getPeaksAtTopTempo(allPeaks, topTempos[0].tempo, filteredBuffer.sampleRate, bpmVariance);
86067      callback(tempoPeaks);
86068    };
86069  };
86070  // process peaks
86071  var Peak = function (amp, i) {
86072    this.sampleIndex = i;
86073    this.amplitude = amp;
86074    this.tempos = [];
86075    this.intervals = [];
86076  };
86077  // 1. for processPeaks() Function to identify peaks above a threshold
86078  // returns an array of peak indexes as frames (samples) of the original soundfile
86079  function getPeaksAtThreshold(data, threshold) {
86080    var peaksObj = {};
86081    var length = data.length;
86082    for (var i = 0; i < length; i++) {
86083      if (data[i] > threshold) {
86084        var amp = data[i];
86085        var peak = new Peak(amp, i);
86086        peaksObj[i] = peak;
86087        // Skip forward ~ 1/8s to get past this peak.
86088        i += 6000;
86089      }
86090      i++;
86091    }
86092    return peaksObj;
86093  }
86094  // 2. for processPeaks()
86095  function countIntervalsBetweenNearbyPeaks(peaksObj) {
86096    var intervalCounts = [];
86097    var peaksArray = Object.keys(peaksObj).sort();
86098    for (var index = 0; index < peaksArray.length; index++) {
86099      // find intervals in comparison to nearby peaks
86100      for (var i = 0; i < 10; i++) {
86101        var startPeak = peaksObj[peaksArray[index]];
86102        var endPeak = peaksObj[peaksArray[index + i]];
86103        if (startPeak && endPeak) {
86104          var startPos = startPeak.sampleIndex;
86105          var endPos = endPeak.sampleIndex;
86106          var interval = endPos - startPos;
86107          // add a sample interval to the startPeak in the allPeaks array
86108          if (interval > 0) {
86109            startPeak.intervals.push(interval);
86110          }
86111          // tally the intervals and return interval counts
86112          var foundInterval = intervalCounts.some(function (intervalCount) {
86113            if (intervalCount.interval === interval) {
86114              intervalCount.count++;
86115              return intervalCount;
86116            }
86117          });
86118          // store with JSON like formatting
86119          if (!foundInterval) {
86120            intervalCounts.push({
86121              interval: interval,
86122              count: 1
86123            });
86124          }
86125        }
86126      }
86127    }
86128    return intervalCounts;
86129  }
86130  // 3. for processPeaks --> find tempo
86131  function groupNeighborsByTempo(intervalCounts, sampleRate) {
86132    var tempoCounts = [];
86133    intervalCounts.forEach(function (intervalCount) {
86134      try {
86135        // Convert an interval to tempo
86136        var theoreticalTempo = Math.abs(60 / (intervalCount.interval / sampleRate));
86137        theoreticalTempo = mapTempo(theoreticalTempo);
86138        var foundTempo = tempoCounts.some(function (tempoCount) {
86139          if (tempoCount.tempo === theoreticalTempo)
86140            return tempoCount.count += intervalCount.count;
86141        });
86142        if (!foundTempo) {
86143          if (isNaN(theoreticalTempo)) {
86144            return;
86145          }
86146          tempoCounts.push({
86147            tempo: Math.round(theoreticalTempo),
86148            count: intervalCount.count
86149          });
86150        }
86151      } catch (e) {
86152        throw e;
86153      }
86154    });
86155    return tempoCounts;
86156  }
86157  // 4. for processPeaks - get peaks at top tempo
86158  function getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) {
86159    var peaksAtTopTempo = [];
86160    var peaksArray = Object.keys(peaksObj).sort();
86161    // TO DO: filter out peaks that have the tempo and return
86162    for (var i = 0; i < peaksArray.length; i++) {
86163      var key = peaksArray[i];
86164      var peak = peaksObj[key];
86165      for (var j = 0; j < peak.intervals.length; j++) {
86166        var intervalBPM = Math.round(Math.abs(60 / (peak.intervals[j] / sampleRate)));
86167        intervalBPM = mapTempo(intervalBPM);
86168        if (Math.abs(intervalBPM - tempo) < bpmVariance) {
86169          // convert sampleIndex to seconds
86170          peaksAtTopTempo.push(peak.sampleIndex / sampleRate);
86171        }
86172      }
86173    }
86174    // filter out peaks that are very close to each other
86175    peaksAtTopTempo = peaksAtTopTempo.filter(function (peakTime, index, arr) {
86176      var dif = arr[index + 1] - peakTime;
86177      if (dif > 0.01) {
86178        return true;
86179      }
86180    });
86181    return peaksAtTopTempo;
86182  }
86183  // helper function for processPeaks
86184  function mapTempo(theoreticalTempo) {
86185    // these scenarios create infinite while loop
86186    if (!isFinite(theoreticalTempo) || theoreticalTempo === 0) {
86187      return;
86188    }
86189    // Adjust the tempo to fit within the 90-180 BPM range
86190    while (theoreticalTempo < 90)
86191      theoreticalTempo *= 2;
86192    while (theoreticalTempo > 180 && theoreticalTempo > 90)
86193      theoreticalTempo /= 2;
86194    return theoreticalTempo;
86195  }
86196  /*** SCHEDULE EVENTS ***/
86197  // Cue inspired by JavaScript setTimeout, and the
86198  // Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org
86199  var Cue = function (callback, time, id, val) {
86200    this.callback = callback;
86201    this.time = time;
86202    this.id = id;
86203    this.val = val;
86204  };
86205  /**
86206   *  Schedule events to trigger every time a MediaElement
86207   *  (audio/video) reaches a playback cue point.
86208   *
86209   *  Accepts a callback function, a time (in seconds) at which to trigger
86210   *  the callback, and an optional parameter for the callback.
86211   *
86212   *  Time will be passed as the first parameter to the callback function,
86213   *  and param will be the second parameter.
86214   *
86215   *
86216   *  @method  addCue
86217   *  @param {Number}   time     Time in seconds, relative to this media
86218   *                             element's playback. For example, to trigger
86219   *                             an event every time playback reaches two
86220   *                             seconds, pass in the number 2. This will be
86221   *                             passed as the first parameter to
86222   *                             the callback function.
86223   *  @param {Function} callback Name of a function that will be
86224   *                             called at the given time. The callback will
86225   *                             receive time and (optionally) param as its
86226   *                             two parameters.
86227   *  @param {Object} [value]    An object to be passed as the
86228   *                             second parameter to the
86229   *                             callback function.
86230   *  @return {Number} id ID of this cue,
86231   *                      useful for removeCue(id)
86232   *  @example
86233   *  <div><code>
86234   *  var mySound;
86235   *  function preload() {
86236   *    mySound = loadSound('assets/beat.mp3');
86237   *  }
86238   *
86239   *  function setup() {
86240   *    background(0);
86241   *    noStroke();
86242   *    fill(255);
86243   *    textAlign(CENTER);
86244   *    text('click to play', width/2, height/2);
86245   *
86246   *    // schedule calls to changeText
86247   *    mySound.addCue(0.50, changeText, "hello" );
86248   *    mySound.addCue(1.00, changeText, "p5" );
86249   *    mySound.addCue(1.50, changeText, "what" );
86250   *    mySound.addCue(2.00, changeText, "do" );
86251   *    mySound.addCue(2.50, changeText, "you" );
86252   *    mySound.addCue(3.00, changeText, "want" );
86253   *    mySound.addCue(4.00, changeText, "to" );
86254   *    mySound.addCue(5.00, changeText, "make" );
86255   *    mySound.addCue(6.00, changeText, "?" );
86256   *  }
86257   *
86258   *  function changeText(val) {
86259   *    background(0);
86260   *    text(val, width/2, height/2);
86261   *  }
86262   *
86263   *  function mouseClicked() {
86264   *    if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
86265   *      if (mySound.isPlaying() ) {
86266   *        mySound.stop();
86267   *      } else {
86268   *        mySound.play();
86269   *      }
86270   *    }
86271   *  }
86272   *  </code></div>
86273   */
86274  p5.SoundFile.prototype.addCue = function (time, callback, val) {
86275    var id = this._cueIDCounter++;
86276    var cue = new Cue(callback, time, id, val);
86277    this._cues.push(cue);
86278    // if (!this.elt.ontimeupdate) {
86279    //   this.elt.ontimeupdate = this._onTimeUpdate.bind(this);
86280    // }
86281    return id;
86282  };
86283  /**
86284   *  Remove a callback based on its ID. The ID is returned by the
86285   *  addCue method.
86286   *
86287   *  @method removeCue
86288   *  @param  {Number} id ID of the cue, as returned by addCue
86289   */
86290  p5.SoundFile.prototype.removeCue = function (id) {
86291    var cueLength = this._cues.length;
86292    for (var i = 0; i < cueLength; i++) {
86293      var cue = this._cues[i];
86294      if (cue.id === id) {
86295        this._cues.splice(i, 1);
86296        break;
86297      }
86298    }
86299    if (this._cues.length === 0) {
86300    }
86301  };
86302  /**
86303   *  Remove all of the callbacks that had originally been scheduled
86304   *  via the addCue method.
86305   *
86306   *  @method  clearCues
86307   */
86308  p5.SoundFile.prototype.clearCues = function () {
86309    this._cues = [];
86310  };
86311  // private method that checks for cues to be fired if events
86312  // have been scheduled using addCue(callback, time).
86313  p5.SoundFile.prototype._onTimeUpdate = function (position) {
86314    var playbackTime = position / this.buffer.sampleRate;
86315    var cueLength = this._cues.length;
86316    for (var i = 0; i < cueLength; i++) {
86317      var cue = this._cues[i];
86318      var callbackTime = cue.time;
86319      var val = cue.val;
86320      if (this._prevTime < callbackTime && callbackTime <= playbackTime) {
86321        // pass the scheduled callbackTime as parameter to the callback
86322        cue.callback(val);
86323      }
86324    }
86325    this._prevTime = playbackTime;
86326  };
86327  /**
86328   * Save a p5.SoundFile as a .wav file. The browser will prompt the user
86329   * to download the file to their device. To upload a file to a server, see
86330   * <a href="/docs/reference/#/p5.SoundFile/getBlob">getBlob</a>
86331   * 
86332   * @method save
86333   * @param  {String} [fileName]      name of the resulting .wav file.
86334   * @example
86335   *  <div><code>
86336   *  var inp, button, mySound;
86337   *  var fileName = 'cool';
86338   *  function preload() {
86339   *    mySound = loadSound('assets/doorbell.mp3');
86340   *  }
86341   *  function setup() {
86342   *    btn = createButton('click to save file');
86343   *    btn.position(0, 0);
86344   *    btn.mouseClicked(handleMouseClick);
86345   *  }
86346   *
86347   *  function handleMouseClick() {
86348   *    mySound.save(fileName);
86349   *  }
86350   * </code></div>
86351   */
86352  p5.SoundFile.prototype.save = function (fileName) {
86353    const dataView = convertToWav(this.buffer);
86354    p5.prototype.saveSound([dataView], fileName, 'wav');
86355  };
86356  /**
86357   * This method is useful for sending a SoundFile to a server. It returns the
86358   * .wav-encoded audio data as a "<a target="_blank" title="Blob reference at
86359   * MDN" href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>".
86360   * A Blob is a file-like data object that can be uploaded to a server
86361   * with an <a href="/docs/reference/#/p5/httpDo">http</a> request. We'll
86362   * use the `httpDo` options object to send a POST request with some
86363   * specific options: we encode the request as `multipart/form-data`,
86364   * and attach the blob as one of the form values using `FormData`.
86365   * 
86366   *
86367   * @method getBlob
86368   * @returns {Blob} A file-like data object
86369   * @example
86370   *  <div><code>
86371   *
86372   *  function preload() {
86373   *    mySound = loadSound('assets/doorbell.mp3');
86374   *  }
86375   *
86376   *  function setup() {
86377   *    noCanvas();
86378   *    var soundBlob = mySound.getBlob();
86379   *
86380   *    // Now we can send the blob to a server...
86381   *    var serverUrl = 'https://jsonplaceholder.typicode.com/posts';
86382   *    var httpRequestOptions = {
86383   *      method: 'POST',
86384   *      body: new FormData().append('soundBlob', soundBlob),
86385   *      headers: new Headers({
86386   *        'Content-Type': 'multipart/form-data'
86387   *      })
86388   *    };
86389   *    httpDo(serverUrl, httpRequestOptions);
86390   *
86391   *    // We can also create an `ObjectURL` pointing to the Blob
86392   *    var blobUrl = URL.createObjectURL(soundBlob);
86393   *
86394   *    // The `<Audio>` Element accepts Object URL's
86395   *    var htmlAudioElt = createAudio(blobUrl).showControls();
86396   *
86397   *    createDiv();
86398   *
86399   *    // The ObjectURL exists as long as this tab is open
86400   *    var input = createInput(blobUrl);
86401   *    input.attribute('readonly', true);
86402   *    input.mouseClicked(function() { input.elt.select() });
86403   *  }
86404   *
86405   * </code></div>
86406   */
86407  p5.SoundFile.prototype.getBlob = function () {
86408    const dataView = convertToWav(this.buffer);
86409    return new Blob([dataView], { type: 'audio/wav' });
86410  };
86411}(errorHandler, master, helpers, helpers);
86412var amplitude;
86413'use strict';
86414amplitude = function () {
86415  var p5sound = master;
86416  /**
86417   *  Amplitude measures volume between 0.0 and 1.0.
86418   *  Listens to all p5sound by default, or use setInput()
86419   *  to listen to a specific sound source. Accepts an optional
86420   *  smoothing value, which defaults to 0.
86421   *
86422   *  @class p5.Amplitude
86423   *  @constructor
86424   *  @param {Number} [smoothing] between 0.0 and .999 to smooth
86425   *                             amplitude readings (defaults to 0)
86426   *  @example
86427   *  <div><code>
86428   *  var sound, amplitude, cnv;
86429   *
86430   *  function preload(){
86431   *    sound = loadSound('assets/beat.mp3');
86432   *  }
86433   *  function setup() {
86434   *    cnv = createCanvas(100,100);
86435   *    amplitude = new p5.Amplitude();
86436   *
86437   *    // start / stop the sound when canvas is clicked
86438   *    cnv.mouseClicked(function() {
86439   *      if (sound.isPlaying() ){
86440   *        sound.stop();
86441   *      } else {
86442   *        sound.play();
86443   *      }
86444   *    });
86445   *  }
86446   *  function draw() {
86447   *    background(0);
86448   *    fill(255);
86449   *    var level = amplitude.getLevel();
86450   *    var size = map(level, 0, 1, 0, 200);
86451   *    ellipse(width/2, height/2, size, size);
86452   *  }
86453   *
86454   *  </code></div>
86455   */
86456  p5.Amplitude = function (smoothing) {
86457    // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default
86458    this.bufferSize = 2048;
86459    // set audio context
86460    this.audiocontext = p5sound.audiocontext;
86461    this.processor = this.audiocontext.createScriptProcessor(this.bufferSize, 2, 1);
86462    // for connections
86463    this.input = this.processor;
86464    this.output = this.audiocontext.createGain();
86465    // smoothing defaults to 0
86466    this.smoothing = smoothing || 0;
86467    // the variables to return
86468    this.volume = 0;
86469    this.average = 0;
86470    this.stereoVol = [
86471      0,
86472      0
86473    ];
86474    this.stereoAvg = [
86475      0,
86476      0
86477    ];
86478    this.stereoVolNorm = [
86479      0,
86480      0
86481    ];
86482    this.volMax = 0.001;
86483    this.normalize = false;
86484    this.processor.onaudioprocess = this._audioProcess.bind(this);
86485    this.processor.connect(this.output);
86486    this.output.gain.value = 0;
86487    // this may only be necessary because of a Chrome bug
86488    this.output.connect(this.audiocontext.destination);
86489    // connect to p5sound master output by default, unless set by input()
86490    p5sound.meter.connect(this.processor);
86491    // add this p5.SoundFile to the soundArray
86492    p5sound.soundArray.push(this);
86493  };
86494  /**
86495   *  Connects to the p5sound instance (master output) by default.
86496   *  Optionally, you can pass in a specific source (i.e. a soundfile).
86497   *
86498   *  @method setInput
86499   *  @param {soundObject|undefined} [snd] set the sound source
86500   *                                       (optional, defaults to
86501   *                                       master output)
86502   *  @param {Number|undefined} [smoothing] a range between 0.0 and 1.0
86503   *                                        to smooth amplitude readings
86504   *  @example
86505   *  <div><code>
86506   *  function preload(){
86507   *    sound1 = loadSound('assets/beat.mp3');
86508   *    sound2 = loadSound('assets/drum.mp3');
86509   *  }
86510   *  function setup(){
86511   *    amplitude = new p5.Amplitude();
86512   *    sound1.play();
86513   *    sound2.play();
86514   *    amplitude.setInput(sound2);
86515   *  }
86516   *  function draw() {
86517   *    background(0);
86518   *    fill(255);
86519   *    var level = amplitude.getLevel();
86520   *    var size = map(level, 0, 1, 0, 200);
86521   *    ellipse(width/2, height/2, size, size);
86522   *  }
86523   *  function mouseClicked(){
86524   *    sound1.stop();
86525   *    sound2.stop();
86526   *  }
86527   *  </code></div>
86528   */
86529  p5.Amplitude.prototype.setInput = function (source, smoothing) {
86530    p5sound.meter.disconnect();
86531    if (smoothing) {
86532      this.smoothing = smoothing;
86533    }
86534    // connect to the master out of p5s instance if no snd is provided
86535    if (source == null) {
86536      console.log('Amplitude input source is not ready! Connecting to master output instead');
86537      p5sound.meter.connect(this.processor);
86538    } else if (source instanceof p5.Signal) {
86539      source.output.connect(this.processor);
86540    } else if (source) {
86541      source.connect(this.processor);
86542      this.processor.disconnect();
86543      this.processor.connect(this.output);
86544    } else {
86545      p5sound.meter.connect(this.processor);
86546    }
86547  };
86548  p5.Amplitude.prototype.connect = function (unit) {
86549    if (unit) {
86550      if (unit.hasOwnProperty('input')) {
86551        this.output.connect(unit.input);
86552      } else {
86553        this.output.connect(unit);
86554      }
86555    } else {
86556      this.output.connect(this.panner.connect(p5sound.input));
86557    }
86558  };
86559  p5.Amplitude.prototype.disconnect = function () {
86560    if (this.output) {
86561      this.output.disconnect();
86562    }
86563  };
86564  // TO DO make this stereo / dependent on # of audio channels
86565  p5.Amplitude.prototype._audioProcess = function (event) {
86566    for (var channel = 0; channel < event.inputBuffer.numberOfChannels; channel++) {
86567      var inputBuffer = event.inputBuffer.getChannelData(channel);
86568      var bufLength = inputBuffer.length;
86569      var total = 0;
86570      var sum = 0;
86571      var x;
86572      for (var i = 0; i < bufLength; i++) {
86573        x = inputBuffer[i];
86574        if (this.normalize) {
86575          total += Math.max(Math.min(x / this.volMax, 1), -1);
86576          sum += Math.max(Math.min(x / this.volMax, 1), -1) * Math.max(Math.min(x / this.volMax, 1), -1);
86577        } else {
86578          total += x;
86579          sum += x * x;
86580        }
86581      }
86582      var average = total / bufLength;
86583      // ... then take the square root of the sum.
86584      var rms = Math.sqrt(sum / bufLength);
86585      this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * this.smoothing);
86586      this.stereoAvg[channel] = Math.max(average, this.stereoVol[channel] * this.smoothing);
86587      this.volMax = Math.max(this.stereoVol[channel], this.volMax);
86588    }
86589    // add volume from all channels together
86590    var self = this;
86591    var volSum = this.stereoVol.reduce(function (previousValue, currentValue, index) {
86592      self.stereoVolNorm[index - 1] = Math.max(Math.min(self.stereoVol[index - 1] / self.volMax, 1), 0);
86593      self.stereoVolNorm[index] = Math.max(Math.min(self.stereoVol[index] / self.volMax, 1), 0);
86594      return previousValue + currentValue;
86595    });
86596    // volume is average of channels
86597    this.volume = volSum / this.stereoVol.length;
86598    // normalized value
86599    this.volNorm = Math.max(Math.min(this.volume / this.volMax, 1), 0);
86600  };
86601  /**
86602   *  Returns a single Amplitude reading at the moment it is called.
86603   *  For continuous readings, run in the draw loop.
86604   *
86605   *  @method getLevel
86606   *  @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right)
86607   *  @return {Number}       Amplitude as a number between 0.0 and 1.0
86608   *  @example
86609   *  <div><code>
86610   *  function preload(){
86611   *    sound = loadSound('assets/beat.mp3');
86612   *  }
86613   *  function setup() {
86614   *    amplitude = new p5.Amplitude();
86615   *    sound.play();
86616   *  }
86617   *  function draw() {
86618   *    background(0);
86619   *    fill(255);
86620   *    var level = amplitude.getLevel();
86621   *    var size = map(level, 0, 1, 0, 200);
86622   *    ellipse(width/2, height/2, size, size);
86623   *  }
86624   *  function mouseClicked(){
86625   *    sound.stop();
86626   *  }
86627   *  </code></div>
86628   */
86629  p5.Amplitude.prototype.getLevel = function (channel) {
86630    if (typeof channel !== 'undefined') {
86631      if (this.normalize) {
86632        return this.stereoVolNorm[channel];
86633      } else {
86634        return this.stereoVol[channel];
86635      }
86636    } else if (this.normalize) {
86637      return this.volNorm;
86638    } else {
86639      return this.volume;
86640    }
86641  };
86642  /**
86643   * Determines whether the results of Amplitude.process() will be
86644   * Normalized. To normalize, Amplitude finds the difference the
86645   * loudest reading it has processed and the maximum amplitude of
86646   * 1.0. Amplitude adds this difference to all values to produce
86647   * results that will reliably map between 0.0 and 1.0. However,
86648   * if a louder moment occurs, the amount that Normalize adds to
86649   * all the values will change. Accepts an optional boolean parameter
86650   * (true or false). Normalizing is off by default.
86651   *
86652   * @method toggleNormalize
86653   * @param {boolean} [boolean] set normalize to true (1) or false (0)
86654   */
86655  p5.Amplitude.prototype.toggleNormalize = function (bool) {
86656    if (typeof bool === 'boolean') {
86657      this.normalize = bool;
86658    } else {
86659      this.normalize = !this.normalize;
86660    }
86661  };
86662  /**
86663   *  Smooth Amplitude analysis by averaging with the last analysis
86664   *  frame. Off by default.
86665   *
86666   *  @method smooth
86667   *  @param {Number} set smoothing from 0.0 <= 1
86668   */
86669  p5.Amplitude.prototype.smooth = function (s) {
86670    if (s >= 0 && s < 1) {
86671      this.smoothing = s;
86672    } else {
86673      console.log('Error: smoothing must be between 0 and 1');
86674    }
86675  };
86676  p5.Amplitude.prototype.dispose = function () {
86677    // remove reference from soundArray
86678    var index = p5sound.soundArray.indexOf(this);
86679    p5sound.soundArray.splice(index, 1);
86680    if (this.input) {
86681      this.input.disconnect();
86682      delete this.input;
86683    }
86684    if (this.output) {
86685      this.output.disconnect();
86686      delete this.output;
86687    }
86688    delete this.processor;
86689  };
86690}(master);
86691var fft;
86692'use strict';
86693fft = function () {
86694  var p5sound = master;
86695  /**
86696   *  <p>
86696FFT (Fast Fourier Transform) is an analysis algorithm that
86697   *  isolates individual
86698   *  <a href="https://en.wikipedia.org/wiki/Audio_frequency">
86699   *  audio frequencies</a> within a waveform.</p>
86700   *
86701   *  <p>Once instantiated, a p5.FFT object can return an array based on
86702   *  two types of analyses: <br> • <code>FFT.waveform()</code> computes
86703   *  amplitude values along the time domain. The array indices correspond
86704   *  to samples across a brief moment in time. Each value represents
86705   *  amplitude of the waveform at that sample of time.<br>
86706   *  • <code>FFT.analyze() </code> computes amplitude values along the
86707   *  frequency domain. The array indices correspond to frequencies (i.e.
86708   *  pitches), from the lowest to the highest that humans can hear. Each
86709   *  value represents amplitude at that slice of the frequency spectrum.
86710   *  Use with <code>getEnergy()</code> to measure amplitude at specific
86711   *  frequencies, or within a range of frequencies. </p>
86712   *
86713   *  <p>FFT analyzes a very short snapshot of sound called a sample
86714   *  buffer. It returns an array of amplitude measurements, referred
86715   *  to as <code>bins</code>. The array is 1024 bins long by default.
86716   *  You can change the bin array length, but it must be a power of 2
86717   *  between 16 and 1024 in order for the FFT algorithm to function
86718   *  correctly. The actual size of the FFT buffer is twice the
86719   *  number of bins, so given a standard sample rate, the buffer is
86720   *  2048/44100 seconds long.</p>
86721   *
86722   *
86723   *  @class p5.FFT
86724   *  @constructor
86725   *  @param {Number} [smoothing]   Smooth results of Freq Spectrum.
86726   *                                0.0 < smoothing < 1.0.
86727   *                                Defaults to 0.8.
86728   *  @param {Number} [bins]    Length of resulting array.
86729   *                            Must be a power of two between
86730   *                            16 and 1024. Defaults to 1024.
86731   *  @example
86732   *  <div><code>
86733   *  function preload(){
86734   *    sound = loadSound('assets/Damscray_DancingTiger.mp3');
86735   *  }
86736   *
86737   *  function setup(){
86738   *    var cnv = createCanvas(100,100);
86739   *    cnv.mouseClicked(togglePlay);
86740   *    fft = new p5.FFT();
86741   *    sound.amp(0.2);
86742   *  }
86743   *
86744   *  function draw(){
86745   *    background(0);
86746   *
86747   *    var spectrum = fft.analyze();
86748   *    noStroke();
86749   *    fill(0,255,0); // spectrum is green
86750   *    for (var i = 0; i< spectrum.length; i++){
86751   *      var x = map(i, 0, spectrum.length, 0, width);
86752   *      var h = -height + map(spectrum[i], 0, 255, height, 0);
86753   *      rect(x, height, width / spectrum.length, h )
86754   *    }
86755   *
86756   *    var waveform = fft.waveform();
86757   *    noFill();
86758   *    beginShape();
86759   *    stroke(255,0,0); // waveform is red
86760   *    strokeWeight(1);
86761   *    for (var i = 0; i< waveform.length; i++){
86762   *      var x = map(i, 0, waveform.length, 0, width);
86763   *      var y = map( waveform[i], -1, 1, 0, height);
86764   *      vertex(x,y);
86765   *    }
86766   *    endShape();
86767   *
86768   *    text('click to play/pause', 4, 10);
86769   *  }
86770   *
86771   *  // fade sound if mouse is over canvas
86772   *  function togglePlay() {
86773   *    if (sound.isPlaying()) {
86774   *      sound.pause();
86775   *    } else {
86776   *      sound.loop();
86777   *    }
86778   *  }
86779   *  </code></div>
86780   */
86781  p5.FFT = function (smoothing, bins) {
86782    this.input = this.analyser = p5sound.audiocontext.createAnalyser();
86783    Object.defineProperties(this, {
86784      bins: {
86785        get: function () {
86786          return this.analyser.fftSize / 2;
86787        },
86788        set: function (b) {
86789          this.analyser.fftSize = b * 2;
86790        },
86791        configurable: true,
86792        enumerable: true
86793      },
86794      smoothing: {
86795        get: function () {
86796          return this.analyser.smoothingTimeConstant;
86797        },
86798        set: function (s) {
86799          this.analyser.smoothingTimeConstant = s;
86800        },
86801        configurable: true,
86802        enumerable: true
86803      }
86804    });
86805    // set default smoothing and bins
86806    this.smooth(smoothing);
86807    this.bins = bins || 1024;
86808    // default connections to p5sound fftMeter
86809    p5sound.fftMeter.connect(this.analyser);
86810    this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount);
86811    this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount);
86812    // predefined frequency ranges, these will be tweakable
86813    this.bass = [
86814      20,
86815      140
86816    ];
86817    this.lowMid = [
86818      140,
86819      400
86820    ];
86821    this.mid = [
86822      400,
86823      2600
86824    ];
86825    this.highMid = [
86826      2600,
86827      5200
86828    ];
86829    this.treble = [
86830      5200,
86831      14000
86832    ];
86833    // add this p5.SoundFile to the soundArray
86834    p5sound.soundArray.push(this);
86835  };
86836  /**
86837   *  Set the input source for the FFT analysis. If no source is
86838   *  provided, FFT will analyze all sound in the sketch.
86839   *
86840   *  @method  setInput
86841   *  @param {Object} [source] p5.sound object (or web audio API source node)
86842   */
86843  p5.FFT.prototype.setInput = function (source) {
86844    if (!source) {
86845      p5sound.fftMeter.connect(this.analyser);
86846    } else {
86847      if (source.output) {
86848        source.output.connect(this.analyser);
86849      } else if (source.connect) {
86850        source.connect(this.analyser);
86851      }
86852      p5sound.fftMeter.disconnect();
86853    }
86854  };
86855  /**
86856   *  Returns an array of amplitude values (between -1.0 and +1.0) that represent
86857   *  a snapshot of amplitude readings in a single buffer. Length will be
86858   *  equal to bins (defaults to 1024). Can be used to draw the waveform
86859   *  of a sound.
86860   *
86861   *  @method waveform
86862   *  @param {Number} [bins]    Must be a power of two between
86863   *                            16 and 1024. Defaults to 1024.
86864   *  @param {String} [precision] If any value is provided, will return results
86865   *                              in a Float32 Array which is more precise
86866   *                              than a regular array.
86867   *  @return {Array}  Array    Array of amplitude values (-1 to 1)
86868   *                            over time. Array length = bins.
86869   *
86870   */
86871  p5.FFT.prototype.waveform = function () {
86872    var bins, mode, normalArray;
86873    for (var i = 0; i < arguments.length; i++) {
86874      if (typeof arguments[i] === 'number') {
86875        bins = arguments[i];
86876        this.analyser.fftSize = bins * 2;
86877      }
86878      if (typeof arguments[i] === 'string') {
86879        mode = arguments[i];
86880      }
86881    }
86882    // getFloatFrequencyData doesnt work in Safari as of 5/2015
86883    if (mode && !p5.prototype._isSafari()) {
86884      timeToFloat(this, this.timeDomain);
86885      this.analyser.getFloatTimeDomainData(this.timeDomain);
86886      return this.timeDomain;
86887    } else {
86888      timeToInt(this, this.timeDomain);
86889      this.analyser.getByteTimeDomainData(this.timeDomain);
86890      var normalArray = new Array();
86891      for (var j = 0; j < this.timeDomain.length; j++) {
86892        var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1);
86893        normalArray.push(scaled);
86894      }
86895      return normalArray;
86896    }
86897  };
86898  /**
86899   *  Returns an array of amplitude values (between 0 and 255)
86900   *  across the frequency spectrum. Length is equal to FFT bins
86901   *  (1024 by default). The array indices correspond to frequencies
86902   *  (i.e. pitches), from the lowest to the highest that humans can
86903   *  hear. Each value represents amplitude at that slice of the
86904   *  frequency spectrum. Must be called prior to using
86905   *  <code>getEnergy()</code>.
86906   *
86907   *  @method analyze
86908   *  @param {Number} [bins]    Must be a power of two between
86909   *                             16 and 1024. Defaults to 1024.
86910   *  @param {Number} [scale]    If "dB," returns decibel
86911   *                             float measurements between
86912   *                             -140 and 0 (max).
86913   *                             Otherwise returns integers from 0-255.
86914   *  @return {Array} spectrum    Array of energy (amplitude/volume)
86915   *                              values across the frequency spectrum.
86916   *                              Lowest energy (silence) = 0, highest
86917   *                              possible is 255.
86918   *  @example
86919   *  <div><code>
86920   *  var osc;
86921   *  var fft;
86922   *
86923   *  function setup(){
86924   *    createCanvas(100,100);
86925   *    osc = new p5.Oscillator();
86926   *    osc.amp(0);
86927   *    osc.start();
86928   *    fft = new p5.FFT();
86929   *  }
86930   *
86931   *  function draw(){
86932   *    background(0);
86933   *
86934   *    var freq = map(mouseX, 0, 800, 20, 15000);
86935   *    freq = constrain(freq, 1, 20000);
86936   *    osc.freq(freq);
86937   *
86938   *    var spectrum = fft.analyze();
86939   *    noStroke();
86940   *    fill(0,255,0); // spectrum is green
86941   *    for (var i = 0; i< spectrum.length; i++){
86942   *      var x = map(i, 0, spectrum.length, 0, width);
86943   *      var h = -height + map(spectrum[i], 0, 255, height, 0);
86944   *      rect(x, height, width / spectrum.length, h );
86945   *    }
86946   *
86947   *    stroke(255);
86948   *    text('Freq: ' + round(freq)+'Hz', 10, 10);
86949   *
86950   *    isMouseOverCanvas();
86951   *  }
86952   *
86953   *  // only play sound when mouse is over canvas
86954   *  function isMouseOverCanvas() {
86955   *    var mX = mouseX, mY = mouseY;
86956   *    if (mX > 0 && mX < width && mY < height && mY > 0) {
86957   *      osc.amp(0.5, 0.2);
86958   *    } else {
86959   *      osc.amp(0, 0.2);
86960   *    }
86961   *  }
86962   *  </code></div>
86963   *
86964   *
86965   */
86966  p5.FFT.prototype.analyze = function () {
86967    var mode;
86968    for (var i = 0; i < arguments.length; i++) {
86969      if (typeof arguments[i] === 'number') {
86970        this.bins = arguments[i];
86971        this.analyser.fftSize = this.bins * 2;
86972      }
86973      if (typeof arguments[i] === 'string') {
86974        mode = arguments[i];
86975      }
86976    }
86977    if (mode && mode.toLowerCase() === 'db') {
86978      freqToFloat(this);
86979      this.analyser.getFloatFrequencyData(this.freqDomain);
86980      return this.freqDomain;
86981    } else {
86982      freqToInt(this, this.freqDomain);
86983      this.analyser.getByteFrequencyData(this.freqDomain);
86984      var normalArray = Array.apply([], this.freqDomain);
86985      normalArray.length === this.analyser.fftSize;
86986      normalArray.constructor === Array;
86987      return normalArray;
86988    }
86989  };
86990  /**
86991   *  Returns the amount of energy (volume) at a specific
86992   *  <a href="https://en.wikipedia.org/wiki/Audio_frequency" target="_blank">
86993   *  frequency</a>, or the average amount of energy between two
86994   *  frequencies. Accepts Number(s) corresponding
86995   *  to frequency (in Hz), or a String corresponding to predefined
86996   *  frequency ranges ("bass", "lowMid", "mid", "highMid", "treble").
86997   *  Returns a range between 0 (no energy/volume at that frequency) and
86998   *  255 (maximum energy).
86999   *  <em>NOTE: analyze() must be called prior to getEnergy(). Analyze()
87000   *  tells the FFT to analyze frequency data, and getEnergy() uses
87001   *  the results determine the value at a specific frequency or
87002   *  range of frequencies.</em></p>
87003   *
87004   *  @method  getEnergy
87005   *  @param  {Number|String} frequency1   Will return a value representing
87006   *                                energy at this frequency. Alternately,
87007   *                                the strings "bass", "lowMid" "mid",
87008   *                                "highMid", and "treble" will return
87009   *                                predefined frequency ranges.
87010   *  @param  {Number} [frequency2] If a second frequency is given,
87011   *                                will return average amount of
87012   *                                energy that exists between the
87013   *                                two frequencies.
87014   *  @return {Number}   Energy   Energy (volume/amplitude) from
87015   *                              0 and 255.
87016   *
87017   */
87018  p5.FFT.prototype.getEnergy = function (frequency1, frequency2) {
87019    var nyquist = p5sound.audiocontext.sampleRate / 2;
87020    if (frequency1 === 'bass') {
87021      frequency1 = this.bass[0];
87022      frequency2 = this.bass[1];
87023    } else if (frequency1 === 'lowMid') {
87024      frequency1 = this.lowMid[0];
87025      frequency2 = this.lowMid[1];
87026    } else if (frequency1 === 'mid') {
87027      frequency1 = this.mid[0];
87028      frequency2 = this.mid[1];
87029    } else if (frequency1 === 'highMid') {
87030      frequency1 = this.highMid[0];
87031      frequency2 = this.highMid[1];
87032    } else if (frequency1 === 'treble') {
87033      frequency1 = this.treble[0];
87034      frequency2 = this.treble[1];
87035    }
87036    if (typeof frequency1 !== 'number') {
87037      throw 'invalid input for getEnergy()';
87038    } else if (!frequency2) {
87039      // if only one parameter:
87040      var index = Math.round(frequency1 / nyquist * this.freqDomain.length);
87041      return this.freqDomain[index];
87042    } else if (frequency1 && frequency2) {
87043      // if two parameters:
87044      // if second is higher than first
87045      if (frequency1 > frequency2) {
87046        var swap = frequency2;
87047        frequency2 = frequency1;
87048        frequency1 = swap;
87049      }
87050      var lowIndex = Math.round(frequency1 / nyquist * this.freqDomain.length);
87051      var highIndex = Math.round(frequency2 / nyquist * this.freqDomain.length);
87052      var total = 0;
87053      var numFrequencies = 0;
87054      // add up all of the values for the frequencies
87055      for (var i = lowIndex; i <= highIndex; i++) {
87056        total += this.freqDomain[i];
87057        numFrequencies += 1;
87058      }
87059      // divide by total number of frequencies
87060      var toReturn = total / numFrequencies;
87061      return toReturn;
87062    } else {
87063      throw 'invalid input for getEnergy()';
87064    }
87065  };
87066  // compatability with v.012, changed to getEnergy in v.0121. Will be deprecated...
87067  p5.FFT.prototype.getFreq = function (freq1, freq2) {
87068    console.log('getFreq() is deprecated. Please use getEnergy() instead.');
87069    var x = this.getEnergy(freq1, freq2);
87070    return x;
87071  };
87072  /**
87073     *  Returns the
87074     *  <a href="http://en.wikipedia.org/wiki/Spectral_centroid" target="_blank">
87075     *  spectral centroid</a> of the input signal.
87076     *  <em>NOTE: analyze() must be called prior to getCentroid(). Analyze()
87077     *  tells the FFT to analyze frequency data, and getCentroid() uses
87078     *  the results determine the spectral centroid.</em></p>
87079     *
87080     *  @method  getCentroid
87081     *  @return {Number}   Spectral Centroid Frequency   Frequency of the spectral centroid in Hz.
87082     *
87083     *
87084     * @example
87085     *  <div><code>
87086     *
87087     *
87088     *function setup(){
87089     *  cnv = createCanvas(100,100);
87090     *  sound = new p5.AudioIn();
87091     *  sound.start();
87092     *  fft = new p5.FFT();
87093     *  sound.connect(fft);
87094     *}
87095     *
87096     *
87097     *function draw(){
87098     *
87099     *  var centroidplot = 0.0;
87100     *  var spectralCentroid = 0;
87101     *
87102     *
87103     *  background(0);
87104     *  stroke(0,255,0);
87105     *  var spectrum = fft.analyze();
87106     *  fill(0,255,0); // spectrum is green
87107     *
87108     *  //draw the spectrum
87109     *  for (var i = 0; i< spectrum.length; i++){
87110     *    var x = map(log(i), 0, log(spectrum.length), 0, width);
87111     *    var h = map(spectrum[i], 0, 255, 0, height);
87112     *    var rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length));
87113     *    rect(x, height, rectangle_width, -h )
87114     *  }
87115  
87116     *  var nyquist = 22050;
87117     *
87118     *  // get the centroid
87119     *  spectralCentroid = fft.getCentroid();
87120     *
87121     *  // the mean_freq_index calculation is for the display.
87122     *  var mean_freq_index = spectralCentroid/(nyquist/spectrum.length);
87123     *
87124     *  centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width);
87125     *
87126     *
87127     *  stroke(255,0,0); // the line showing where the centroid is will be red
87128     *
87129     *  rect(centroidplot, 0, width / spectrum.length, height)
87130     *  noStroke();
87131     *  fill(255,255,255);  // text is white
87132     *  text("centroid: ", 10, 20);
87133     *  text(round(spectralCentroid)+" Hz", 10, 40);
87134     *}
87135     * </code></div>
87136     */
87137  p5.FFT.prototype.getCentroid = function () {
87138    var nyquist = p5sound.audiocontext.sampleRate / 2;
87139    var cumulative_sum = 0;
87140    var centroid_normalization = 0;
87141    for (var i = 0; i < this.freqDomain.length; i++) {
87142      cumulative_sum += i * this.freqDomain[i];
87143      centroid_normalization += this.freqDomain[i];
87144    }
87145    var mean_freq_index = 0;
87146    if (centroid_normalization !== 0) {
87147      mean_freq_index = cumulative_sum / centroid_normalization;
87148    }
87149    var spec_centroid_freq = mean_freq_index * (nyquist / this.freqDomain.length);
87150    return spec_centroid_freq;
87151  };
87152  /**
87153   *  Smooth FFT analysis by averaging with the last analysis frame.
87154   *
87155   *  @method smooth
87156   *  @param {Number} smoothing    0.0 < smoothing < 1.0.
87157   *                               Defaults to 0.8.
87158   */
87159  p5.FFT.prototype.smooth = function (s) {
87160    if (typeof s !== 'undefined') {
87161      this.smoothing = s;
87162    }
87163    return this.smoothing;
87164  };
87165  p5.FFT.prototype.dispose = function () {
87166    // remove reference from soundArray
87167    var index = p5sound.soundArray.indexOf(this);
87168    p5sound.soundArray.splice(index, 1);
87169    if (this.analyser) {
87170      this.analyser.disconnect();
87171      delete this.analyser;
87172    }
87173  };
87174  /**
87175   *  Returns an array of average amplitude values for a given number
87176   *  of frequency bands split equally. N defaults to 16.
87177   *  <em>NOTE: analyze() must be called prior to linAverages(). Analyze()
87178   *  tells the FFT to analyze frequency data, and linAverages() uses
87179   *  the results to group them into a smaller set of averages.</em></p>
87180   *
87181   *  @method  linAverages
87182   *  @param  {Number}  N                Number of returned frequency groups
87183   *  @return {Array}   linearAverages   Array of average amplitude values for each group
87184   */
87185  p5.FFT.prototype.linAverages = function (N) {
87186    var N = N || 16;
87187    // This prevents undefined, null or 0 values of N
87188    var spectrum = this.freqDomain;
87189    var spectrumLength = spectrum.length;
87190    var spectrumStep = Math.floor(spectrumLength / N);
87191    var linearAverages = new Array(N);
87192    // Keep a second index for the current average group and place the values accordingly
87193    // with only one loop in the spectrum data
87194    var groupIndex = 0;
87195    for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {
87196      linearAverages[groupIndex] = linearAverages[groupIndex] !== undefined ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2 : spectrum[specIndex];
87197      // Increase the group index when the last element of the group is processed
87198      if (specIndex % spectrumStep === spectrumStep - 1) {
87199        groupIndex++;
87200      }
87201    }
87202    return linearAverages;
87203  };
87204  /**
87205   *  Returns an array of average amplitude values of the spectrum, for a given
87206   *  set of <a href="https://en.wikipedia.org/wiki/Octave_band" target="_blank">
87207   *  Octave Bands</a>
87208   *  <em>NOTE: analyze() must be called prior to logAverages(). Analyze()
87209   *  tells the FFT to analyze frequency data, and logAverages() uses
87210   *  the results to group them into a smaller set of averages.</em></p>
87211   *
87212   *  @method  logAverages
87213   *  @param  {Array}   octaveBands    Array of Octave Bands objects for grouping
87214   *  @return {Array}   logAverages    Array of average amplitude values for each group
87215   */
87216  p5.FFT.prototype.logAverages = function (octaveBands) {
87217    var nyquist = p5sound.audiocontext.sampleRate / 2;
87218    var spectrum = this.freqDomain;
87219    var spectrumLength = spectrum.length;
87220    var logAverages = new Array(octaveBands.length);
87221    // Keep a second index for the current average group and place the values accordingly
87222    // With only one loop in the spectrum data
87223    var octaveIndex = 0;
87224    for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {
87225      var specIndexFrequency = Math.round(specIndex * nyquist / this.freqDomain.length);
87226      // Increase the group index if the current frequency exceeds the limits of the band
87227      if (specIndexFrequency > octaveBands[octaveIndex].hi) {
87228        octaveIndex++;
87229      }
87230      logAverages[octaveIndex] = logAverages[octaveIndex] !== undefined ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2 : spectrum[specIndex];
87231    }
87232    return logAverages;
87233  };
87234  /**
87235   *  Calculates and Returns the 1/N
87236   *  <a href="https://en.wikipedia.org/wiki/Octave_band" target="_blank">Octave Bands</a>
87237   *  N defaults to 3 and minimum central frequency to 15.625Hz.
87238   *  (1/3 Octave Bands ~= 31 Frequency Bands)
87239   *  Setting fCtr0 to a central value of a higher octave will ignore the lower bands
87240   *  and produce less frequency groups.
87241   *
87242   *  @method   getOctaveBands
87243   *  @param  {Number}  N             Specifies the 1/N type of generated octave bands
87244   *  @param  {Number}  fCtr0         Minimum central frequency for the lowest band
87245   *  @return {Array}   octaveBands   Array of octave band objects with their bounds
87246   */
87247  p5.FFT.prototype.getOctaveBands = function (N, fCtr0) {
87248    var N = N || 3;
87249    // Default to 1/3 Octave Bands
87250    var fCtr0 = fCtr0 || 15.625;
87251    // Minimum central frequency, defaults to 15.625Hz
87252    var octaveBands = [];
87253    var lastFrequencyBand = {
87254      lo: fCtr0 / Math.pow(2, 1 / (2 * N)),
87255      ctr: fCtr0,
87256      hi: fCtr0 * Math.pow(2, 1 / (2 * N))
87257    };
87258    octaveBands.push(lastFrequencyBand);
87259    var nyquist = p5sound.audiocontext.sampleRate / 2;
87260    while (lastFrequencyBand.hi < nyquist) {
87261      var newFrequencyBand = {};
87262      newFrequencyBand.lo = lastFrequencyBand.hi;
87263      newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N);
87264      newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N));
87265      octaveBands.push(newFrequencyBand);
87266      lastFrequencyBand = newFrequencyBand;
87267    }
87268    return octaveBands;
87269  };
87270  // helper methods to convert type from float (dB) to int (0-255)
87271  var freqToFloat = function (fft) {
87272    if (fft.freqDomain instanceof Float32Array === false) {
87273      fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount);
87274    }
87275  };
87276  var freqToInt = function (fft) {
87277    if (fft.freqDomain instanceof Uint8Array === false) {
87278      fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount);
87279    }
87280  };
87281  var timeToFloat = function (fft) {
87282    if (fft.timeDomain instanceof Float32Array === false) {
87283      fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount);
87284    }
87285  };
87286  var timeToInt = function (fft) {
87287    if (fft.timeDomain instanceof Uint8Array === false) {
87288      fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount);
87289    }
87290  };
87291}(master);
87292/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
87293var Tone_core_Tone;
87294Tone_core_Tone = function () {
87295  'use strict';
87296  var Tone = function (inputs, outputs) {
87297    if (this.isUndef(inputs) || inputs === 1) {
87298      this.input = this.context.createGain();
87299    } else if (inputs > 1) {
87300      this.input = new Array(inputs);
87301    }
87302    if (this.isUndef(outputs) || outputs === 1) {
87303      this.output = this.context.createGain();
87304    } else if (outputs > 1) {
87305      this.output = new Array(inputs);
87306    }
87307  };
87308  Tone.prototype.set = function (params, value, rampTime) {
87309    if (this.isObject(params)) {
87310      rampTime = value;
87311    } else if (this.isString(params)) {
87312      var tmpObj = {};
87313      tmpObj[params] = value;
87314      params = tmpObj;
87315    }
87316    paramLoop:
87317      for (var attr in params) {
87318        value = params[attr];
87319        var parent = this;
87320        if (attr.indexOf('.') !== -1) {
87321          var attrSplit = attr.split('.');
87322          for (var i = 0; i < attrSplit.length - 1; i++) {
87323            parent = parent[attrSplit[i]];
87324            if (parent instanceof Tone) {
87325              attrSplit.splice(0, i + 1);
87326              var innerParam = attrSplit.join('.');
87327              parent.set(innerParam, value);
87328              continue paramLoop;
87329            }
87330          }
87331          attr = attrSplit[attrSplit.length - 1];
87332        }
87333        var param = parent[attr];
87334        if (this.isUndef(param)) {
87335          continue;
87336        }
87337        if (Tone.Signal && param instanceof Tone.Signal || Tone.Param && param instanceof Tone.Param) {
87338          if (param.value !== value) {
87339            if (this.isUndef(rampTime)) {
87340              param.value = value;
87341            } else {
87342              param.rampTo(value, rampTime);
87343            }
87344          }
87345        } else if (param instanceof AudioParam) {
87346          if (param.value !== value) {
87347            param.value = value;
87348          }
87349        } else if (param instanceof Tone) {
87350          param.set(value);
87351        } else if (param !== value) {
87352          parent[attr] = value;
87353        }
87354      }
87355    return this;
87356  };
87357  Tone.prototype.get = function (params) {
87358    if (this.isUndef(params)) {
87359      params = this._collectDefaults(this.constructor);
87360    } else if (this.isString(params)) {
87361      params = [params];
87362    }
87363    var ret = {};
87364    for (var i = 0; i < params.length; i++) {
87365      var attr = params[i];
87366      var parent = this;
87367      var subRet = ret;
87368      if (attr.indexOf('.') !== -1) {
87369        var attrSplit = attr.split('.');
87370        for (var j = 0; j < attrSplit.length - 1; j++) {
87371          var subAttr = attrSplit[j];
87372          subRet[subAttr] = subRet[subAttr] || {};
87373          subRet = subRet[subAttr];
87374          parent = parent[subAttr];
87375        }
87376        attr = attrSplit[attrSplit.length - 1];
87377      }
87378      var param = parent[attr];
87379      if (this.isObject(params[attr])) {
87380        subRet[attr] = param.get();
87381      } else if (Tone.Signal && param instanceof Tone.Signal) {
87382        subRet[attr] = param.value;
87383      } else if (Tone.Param && param instanceof Tone.Param) {
87384        subRet[attr] = param.value;
87385      } else if (param instanceof AudioParam) {
87386        subRet[attr] = param.value;
87387      } else if (param instanceof Tone) {
87388        subRet[attr] = param.get();
87389      } else if (!this.isFunction(param) && !this.isUndef(param)) {
87390        subRet[attr] = param;
87391      }
87392    }
87393    return ret;
87394  };
87395  Tone.prototype._collectDefaults = function (constr) {
87396    var ret = [];
87397    if (!this.isUndef(constr.defaults)) {
87398      ret = Object.keys(constr.defaults);
87399    }
87400    if (!this.isUndef(constr._super)) {
87401      var superDefs = this._collectDefaults(constr._super);
87402      for (var i = 0; i < superDefs.length; i++) {
87403        if (ret.indexOf(superDefs[i]) === -1) {
87404          ret.push(superDefs[i]);
87405        }
87406      }
87407    }
87408    return ret;
87409  };
87410  Tone.prototype.toString = function () {
87411    for (var className in Tone) {
87412      var isLetter = className[0].match(/^[A-Z]$/);
87413      var sameConstructor = Tone[className] === this.constructor;
87414      if (this.isFunction(Tone[className]) && isLetter && sameConstructor) {
87415        return className;
87416      }
87417    }
87418    return 'Tone';
87419  };
87420  Object.defineProperty(Tone.prototype, 'numberOfInputs', {
87421    get: function () {
87422      if (this.input) {
87423        if (this.isArray(this.input)) {
87424          return this.input.length;
87425        } else {
87426          return 1;
87427        }
87428      } else {
87429        return 0;
87430      }
87431    }
87432  });
87433  Object.defineProperty(Tone.prototype, 'numberOfOutputs', {
87434    get: function () {
87435      if (this.output) {
87436        if (this.isArray(this.output)) {
87437          return this.output.length;
87438        } else {
87439          return 1;
87440        }
87441      } else {
87442        return 0;
87443      }
87444    }
87445  });
87446  Tone.prototype.dispose = function () {
87447    if (!this.isUndef(this.input)) {
87448      if (this.input instanceof AudioNode) {
87449        this.input.disconnect();
87450      }
87451      this.input = null;
87452    }
87453    if (!this.isUndef(this.output)) {
87454      if (this.output instanceof AudioNode) {
87455        this.output.disconnect();
87456      }
87457      this.output = null;
87458    }
87459    return this;
87460  };
87461  Tone.prototype.connect = function (unit, outputNum, inputNum) {
87462    if (Array.isArray(this.output)) {
87463      outputNum = this.defaultArg(outputNum, 0);
87464      this.output[outputNum].connect(unit, 0, inputNum);
87465    } else {
87466      this.output.connect(unit, outputNum, inputNum);
87467    }
87468    return this;
87469  };
87470  Tone.prototype.disconnect = function (destination, outputNum, inputNum) {
87471    if (this.isArray(this.output)) {
87472      if (this.isNumber(destination)) {
87473        this.output[destination].disconnect();
87474      } else {
87475        outputNum = this.defaultArg(outputNum, 0);
87476        this.output[outputNum].disconnect(destination, 0, inputNum);
87477      }
87478    } else {
87479      this.output.disconnect.apply(this.output, arguments);
87480    }
87481  };
87482  Tone.prototype.connectSeries = function () {
87483    if (arguments.length > 1) {
87484      var currentUnit = arguments[0];
87485      for (var i = 1; i < arguments.length; i++) {
87486        var toUnit = arguments[i];
87487        currentUnit.connect(toUnit);
87488        currentUnit = toUnit;
87489      }
87490    }
87491    return this;
87492  };
87493  Tone.prototype.chain = function () {
87494    if (arguments.length > 0) {
87495      var currentUnit = this;
87496      for (var i = 0; i < arguments.length; i++) {
87497        var toUnit = arguments[i];
87498        currentUnit.connect(toUnit);
87499        currentUnit = toUnit;
87500      }
87501    }
87502    return this;
87503  };
87504  Tone.prototype.fan = function () {
87505    if (arguments.length > 0) {
87506      for (var i = 0; i < arguments.length; i++) {
87507        this.connect(arguments[i]);
87508      }
87509    }
87510    return this;
87511  };
87512  AudioNode.prototype.chain = Tone.prototype.chain;
87513  AudioNode.prototype.fan = Tone.prototype.fan;
87514  Tone.prototype.defaultArg = function (given, fallback) {
87515    if (this.isObject(given) && this.isObject(fallback)) {
87516      var ret = {};
87517      for (var givenProp in given) {
87518        ret[givenProp] = this.defaultArg(fallback[givenProp], given[givenProp]);
87519      }
87520      for (var fallbackProp in fallback) {
87521        ret[fallbackProp] = this.defaultArg(given[fallbackProp], fallback[fallbackProp]);
87522      }
87523      return ret;
87524    } else {
87525      return this.isUndef(given) ? fallback : given;
87526    }
87527  };
87528  Tone.prototype.optionsObject = function (values, keys, defaults) {
87529    var options = {};
87530    if (values.length === 1 && this.isObject(values[0])) {
87531      options = values[0];
87532    } else {
87533      for (var i = 0; i < keys.length; i++) {
87534        options[keys[i]] = values[i];
87535      }
87536    }
87537    if (!this.isUndef(defaults)) {
87538      return this.defaultArg(options, defaults);
87539    } else {
87540      return options;
87541    }
87542  };
87543  Tone.prototype.isUndef = function (val) {
87544    return typeof val === 'undefined';
87545  };
87546  Tone.prototype.isFunction = function (val) {
87547    return typeof val === 'function';
87548  };
87549  Tone.prototype.isNumber = function (arg) {
87550    return typeof arg === 'number';
87551  };
87552  Tone.prototype.isObject = function (arg) {
87553    return Object.prototype.toString.call(arg) === '[object Object]' && arg.constructor === Object;
87554  };
87555  Tone.prototype.isBoolean = function (arg) {
87556    return typeof arg === 'boolean';
87557  };
87558  Tone.prototype.isArray = function (arg) {
87559    return Array.isArray(arg);
87560  };
87561  Tone.prototype.isString = function (arg) {
87562    return typeof arg === 'string';
87563  };
87564  Tone.noOp = function () {
87565  };
87566  Tone.prototype._readOnly = function (property) {
87567    if (Array.isArray(property)) {
87568      for (var i = 0; i < property.length; i++) {
87569        this._readOnly(property[i]);
87570      }
87571    } else {
87572      Object.defineProperty(this, property, {
87573        writable: false,
87574        enumerable: true
87575      });
87576    }
87577  };
87578  Tone.prototype._writable = function (property) {
87579    if (Array.isArray(property)) {
87580      for (var i = 0; i < property.length; i++) {
87581        this._writable(property[i]);
87582      }
87583    } else {
87584      Object.defineProperty(this, property, { writable: true });
87585    }
87586  };
87587  Tone.State = {
87588    Started: 'started',
87589    Stopped: 'stopped',
87590    Paused: 'paused'
87591  };
87592  Tone.prototype.equalPowerScale = function (percent) {
87593    var piFactor = 0.5 * Math.PI;
87594    return Math.sin(percent * piFactor);
87595  };
87596  Tone.prototype.dbToGain = function (db) {
87597    return Math.pow(2, db / 6);
87598  };
87599  Tone.prototype.gainToDb = function (gain) {
87600    return 20 * (Math.log(gain) / Math.LN10);
87601  };
87602  Tone.prototype.intervalToFrequencyRatio = function (interval) {
87603    return Math.pow(2, interval / 12);
87604  };
87605  Tone.prototype.now = function () {
87606    return Tone.context.now();
87607  };
87608  Tone.now = function () {
87609    return Tone.context.now();
87610  };
87611  Tone.extend = function (child, parent) {
87612    if (Tone.prototype.isUndef(parent)) {
87613      parent = Tone;
87614    }
87615    function TempConstructor() {
87616    }
87617    TempConstructor.prototype = parent.prototype;
87618    child.prototype = new TempConstructor();
87619    child.prototype.constructor = child;
87620    child._super = parent;
87621  };
87622  var audioContext;
87623  Object.defineProperty(Tone, 'context', {
87624    get: function () {
87625      return audioContext;
87626    },
87627    set: function (context) {
87628      if (Tone.Context && context instanceof Tone.Context) {
87629        audioContext = context;
87630      } else {
87631        audioContext = new Tone.Context(context);
87632      }
87633      if (Tone.Context) {
87634        Tone.Context.emit('init', audioContext);
87635      }
87636    }
87637  });
87638  Object.defineProperty(Tone.prototype, 'context', {
87639    get: function () {
87640      return Tone.context;
87641    }
87642  });
87643  Tone.setContext = function (ctx) {
87644    Tone.context = ctx;
87645  };
87646  Object.defineProperty(Tone.prototype, 'blockTime', {
87647    get: function () {
87648      return 128 / this.context.sampleRate;
87649    }
87650  });
87651  Object.defineProperty(Tone.prototype, 'sampleTime', {
87652    get: function () {
87653      return 1 / this.context.sampleRate;
87654    }
87655  });
87656  Object.defineProperty(Tone, 'supported', {
87657    get: function () {
87658      var hasAudioContext = window.hasOwnProperty('AudioContext') || window.hasOwnProperty('webkitAudioContext');
87659      var hasPromises = window.hasOwnProperty('Promise');
87660      var hasWorkers = window.hasOwnProperty('Worker');
87661      return hasAudioContext && hasPromises && hasWorkers;
87662    }
87663  });
87664  Tone.version = 'r10';
87665  if (!window.TONE_SILENCE_VERSION_LOGGING) {
87666  }
87667  return Tone;
87668}();
87669/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
87670var Tone_signal_SignalBase;
87671Tone_signal_SignalBase = function (Tone) {
87672  'use strict';
87673  Tone.SignalBase = function () {
87674  };
87675  Tone.extend(Tone.SignalBase);
87676  Tone.SignalBase.prototype.connect = function (node, outputNumber, inputNumber) {
87677    if (Tone.Signal && Tone.Signal === node.constructor || Tone.Param && Tone.Param === node.constructor || Tone.TimelineSignal && Tone.TimelineSignal === node.constructor) {
87678      node._param.cancelScheduledValues(0);
87679      node._param.value = 0;
87680      node.overridden = true;
87681    } else if (node instanceof AudioParam) {
87682      node.cancelScheduledValues(0);
87683      node.value = 0;
87684    }
87685    Tone.prototype.connect.call(this, node, outputNumber, inputNumber);
87686    return this;
87687  };
87688  return Tone.SignalBase;
87689}(Tone_core_Tone);
87690/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
87691var Tone_signal_WaveShaper;
87692Tone_signal_WaveShaper = function (Tone) {
87693  'use strict';
87694  Tone.WaveShaper = function (mapping, bufferLen) {
87695    this._shaper = this.input = this.output = this.context.createWaveShaper();
87696    this._curve = null;
87697    if (Array.isArray(mapping)) {
87698      this.curve = mapping;
87699    } else if (isFinite(mapping) || this.isUndef(mapping)) {
87700      this._curve = new Float32Array(this.defaultArg(mapping, 1024));
87701    } else if (this.isFunction(mapping)) {
87702      this._curve = new Float32Array(this.defaultArg(bufferLen, 1024));
87703      this.setMap(mapping);
87704    }
87705  };
87706  Tone.extend(Tone.WaveShaper, Tone.SignalBase);
87707  Tone.WaveShaper.prototype.setMap = function (mapping) {
87708    for (var i = 0, len = this._curve.length; i < len; i++) {
87709      var normalized = i / (len - 1) * 2 - 1;
87710      this._curve[i] = mapping(normalized, i);
87711    }
87712    this._shaper.curve = this._curve;
87713    return this;
87714  };
87715  Object.defineProperty(Tone.WaveShaper.prototype, 'curve', {
87716    get: function () {
87717      return this._shaper.curve;
87718    },
87719    set: function (mapping) {
87720      this._curve = new Float32Array(mapping);
87721      this._shaper.curve = this._curve;
87722    }
87723  });
87724  Object.defineProperty(Tone.WaveShaper.prototype, 'oversample', {
87725    get: function () {
87726      return this._shaper.oversample;
87727    },
87728    set: function (oversampling) {
87729      if ([
87730          'none',
87731          '2x',
87732          '4x'
87733        ].indexOf(oversampling) !== -1) {
87734        this._shaper.oversample = oversampling;
87735      } else {
87736        throw new RangeError('Tone.WaveShaper: oversampling must be either \'none\', \'2x\', or \'4x\'');
87737      }
87738    }
87739  });
87740  Tone.WaveShaper.prototype.dispose = function () {
87741    Tone.prototype.dispose.call(this);
87742    this._shaper.disconnect();
87743    this._shaper = null;
87744    this._curve = null;
87745    return this;
87746  };
87747  return Tone.WaveShaper;
87748}(Tone_core_Tone);
87749/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
87750var Tone_type_TimeBase;
87751Tone_type_TimeBase = function (Tone) {
87752  Tone.TimeBase = function (val, units) {
87753    if (this instanceof Tone.TimeBase) {
87754      this._expr = this._noOp;
87755      if (val instanceof Tone.TimeBase) {
87756        this.copy(val);
87757      } else if (!this.isUndef(units) || this.isNumber(val)) {
87758        units = this.defaultArg(units, this._defaultUnits);
87759        var method = this._primaryExpressions[units].method;
87760        this._expr = method.bind(this, val);
87761      } else if (this.isString(val)) {
87762        this.set(val);
87763      } else if (this.isUndef(val)) {
87764        this._expr = this._defaultExpr();
87765      }
87766    } else {
87767      return new Tone.TimeBase(val, units);
87768    }
87769  };
87770  Tone.extend(Tone.TimeBase);
87771  Tone.TimeBase.prototype.set = function (exprString) {
87772    this._expr = this._parseExprString(exprString);
87773    return this;
87774  };
87775  Tone.TimeBase.prototype.clone = function () {
87776    var instance = new this.constructor();
87777    instance.copy(this);
87778    return instance;
87779  };
87780  Tone.TimeBase.prototype.copy = function (time) {
87781    var val = time._expr();
87782    return this.set(val);
87783  };
87784  Tone.TimeBase.prototype._primaryExpressions = {
87785    'n': {
87786      regexp: /^(\d+)n/i,
87787      method: function (value) {
87788        value = parseInt(value);
87789        if (value === 1) {
87790          return this._beatsToUnits(this._timeSignature());
87791        } else {
87792          return this._beatsToUnits(4 / value);
87793        }
87794      }
87795    },
87796    't': {
87797      regexp: /^(\d+)t/i,
87798      method: function (value) {
87799        value = parseInt(value);
87800        return this._beatsToUnits(8 / (parseInt(value) * 3));
87801      }
87802    },
87803    'm': {
87804      regexp: /^(\d+)m/i,
87805      method: function (value) {
87806        return this._beatsToUnits(parseInt(value) * this._timeSignature());
87807      }
87808    },
87809    'i': {
87810      regexp: /^(\d+)i/i,
87811      method: function (value) {
87812        return this._ticksToUnits(parseInt(value));
87813      }
87814    },
87815    'hz': {
87816      regexp: /^(\d+(?:\.\d+)?)hz/i,
87817      method: function (value) {
87818        return this._frequencyToUnits(parseFloat(value));
87819      }
87820    },
87821    'tr': {
87822      regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/,
87823      method: function (m, q, s) {
87824        var total = 0;
87825        if (m && m !== '0') {
87826          total += this._beatsToUnits(this._timeSignature() * parseFloat(m));
87827        }
87828        if (q && q !== '0') {
87829          total += this._beatsToUnits(parseFloat(q));
87830        }
87831        if (s && s !== '0') {
87832          total += this._beatsToUnits(parseFloat(s) / 4);
87833        }
87834        return total;
87835      }
87836    },
87837    's': {
87838      regexp: /^(\d+(?:\.\d+)?s)/,
87839      method: function (value) {
87840        return this._secondsToUnits(parseFloat(value));
87841      }
87842    },
87843    'samples': {
87844      regexp: /^(\d+)samples/,
87845      method: function (value) {
87846        return parseInt(value) / this.context.sampleRate;
87847      }
87848    },
87849    'default': {
87850      regexp: /^(\d+(?:\.\d+)?)/,
87851      method: function (value) {
87852        return this._primaryExpressions[this._defaultUnits].method.call(this, value);
87853      }
87854    }
87855  };
87856  Tone.TimeBase.prototype._binaryExpressions = {
87857    '+': {
87858      regexp: /^\+/,
87859      precedence: 2,
87860      method: function (lh, rh) {
87861        return lh() + rh();
87862      }
87863    },
87864    '-': {
87865      regexp: /^\-/,
87866      precedence: 2,
87867      method: function (lh, rh) {
87868        return lh() - rh();
87869      }
87870    },
87871    '*': {
87872      regexp: /^\*/,
87873      precedence: 1,
87874      method: function (lh, rh) {
87875        return lh() * rh();
87876      }
87877    },
87878    '/': {
87879      regexp: /^\//,
87880      precedence: 1,
87881      method: function (lh, rh) {
87882        return lh() / rh();
87883      }
87884    }
87885  };
87886  Tone.TimeBase.prototype._unaryExpressions = {
87887    'neg': {
87888      regexp: /^\-/,
87889      method: function (lh) {
87890        return -lh();
87891      }
87892    }
87893  };
87894  Tone.TimeBase.prototype._syntaxGlue = {
87895    '(': { regexp: /^\(/ },
87896    ')': { regexp: /^\)/ }
87897  };
87898  Tone.TimeBase.prototype._tokenize = function (expr) {
87899    var position = -1;
87900    var tokens = [];
87901    while (expr.length > 0) {
87902      expr = expr.trim();
87903      var token = getNextToken(expr, this);
87904      tokens.push(token);
87905      expr = expr.substr(token.value.length);
87906    }
87907    function getNextToken(expr, context) {
87908      var expressions = [
87909        '_binaryExpressions',
87910        '_unaryExpressions',
87911        '_primaryExpressions',
87912        '_syntaxGlue'
87913      ];
87914      for (var i = 0; i < expressions.length; i++) {
87915        var group = context[expressions[i]];
87916        for (var opName in group) {
87917          var op = group[opName];
87918          var reg = op.regexp;
87919          var match = expr.match(reg);
87920          if (match !== null) {
87921            return {
87922              method: op.method,
87923              precedence: op.precedence,
87924              regexp: op.regexp,
87925              value: match[0]
87926            };
87927          }
87928        }
87929      }
87930      throw new SyntaxError('Tone.TimeBase: Unexpected token ' + expr);
87931    }
87932    return {
87933      next: function () {
87934        return tokens[++position];
87935      },
87936      peek: function () {
87937        return tokens[position + 1];
87938      }
87939    };
87940  };
87941  Tone.TimeBase.prototype._matchGroup = function (token, group, prec) {
87942    var ret = false;
87943    if (!this.isUndef(token)) {
87944      for (var opName in group) {
87945        var op = group[opName];
87946        if (op.regexp.test(token.value)) {
87947          if (!this.isUndef(prec)) {
87948            if (op.precedence === prec) {
87949              return op;
87950            }
87951          } else {
87952            return op;
87953          }
87954        }
87955      }
87956    }
87957    return ret;
87958  };
87959  Tone.TimeBase.prototype._parseBinary = function (lexer, precedence) {
87960    if (this.isUndef(precedence)) {
87961      precedence = 2;
87962    }
87963    var expr;
87964    if (precedence < 0) {
87965      expr = this._parseUnary(lexer);
87966    } else {
87967      expr = this._parseBinary(lexer, precedence - 1);
87968    }
87969    var token = lexer.peek();
87970    while (token && this._matchGroup(token, this._binaryExpressions, precedence)) {
87971      token = lexer.next();
87972      expr = token.method.bind(this, expr, this._parseBinary(lexer, precedence - 1));
87973      token = lexer.peek();
87974    }
87975    return expr;
87976  };
87977  Tone.TimeBase.prototype._parseUnary = function (lexer) {
87978    var token, expr;
87979    token = lexer.peek();
87980    var op = this._matchGroup(token, this._unaryExpressions);
87981    if (op) {
87982      token = lexer.next();
87983      expr = this._parseUnary(lexer);
87984      return op.method.bind(this, expr);
87985    }
87986    return this._parsePrimary(lexer);
87987  };
87988  Tone.TimeBase.prototype._parsePrimary = function (lexer) {
87989    var token, expr;
87990    token = lexer.peek();
87991    if (this.isUndef(token)) {
87992      throw new SyntaxError('Tone.TimeBase: Unexpected end of expression');
87993    }
87994    if (this._matchGroup(token, this._primaryExpressions)) {
87995      token = lexer.next();
87996      var matching = token.value.match(token.regexp);
87997      return token.method.bind(this, matching[1], matching[2], matching[3]);
87998    }
87999    if (token && token.value === '(') {
88000      lexer.next();
88001      expr = this._parseBinary(lexer);
88002      token = lexer.next();
88003      if (!(token && token.value === ')')) {
88004        throw new SyntaxError('Expected )');
88005      }
88006      return expr;
88007    }
88008    throw new SyntaxError('Tone.TimeBase: Cannot process token ' + token.value);
88009  };
88010  Tone.TimeBase.prototype._parseExprString = function (exprString) {
88011    if (!this.isString(exprString)) {
88012      exprString = exprString.toString();
88013    }
88014    var lexer = this._tokenize(exprString);
88015    var tree = this._parseBinary(lexer);
88016    return tree;
88017  };
88018  Tone.TimeBase.prototype._noOp = function () {
88019    return 0;
88020  };
88021  Tone.TimeBase.prototype._defaultExpr = function () {
88022    return this._noOp;
88023  };
88024  Tone.TimeBase.prototype._defaultUnits = 's';
88025  Tone.TimeBase.prototype._frequencyToUnits = function (freq) {
88026    return 1 / freq;
88027  };
88028  Tone.TimeBase.prototype._beatsToUnits = function (beats) {
88029    return 60 / Tone.Transport.bpm.value * beats;
88030  };
88031  Tone.TimeBase.prototype._secondsToUnits = function (seconds) {
88032    return seconds;
88033  };
88034  Tone.TimeBase.prototype._ticksToUnits = function (ticks) {
88035    return ticks * (this._beatsToUnits(1) / Tone.Transport.PPQ);
88036  };
88037  Tone.TimeBase.prototype._timeSignature = function () {
88038    return Tone.Transport.timeSignature;
88039  };
88040  Tone.TimeBase.prototype._pushExpr = function (val, name, units) {
88041    if (!(val instanceof Tone.TimeBase)) {
88042      val = new this.constructor(val, units);
88043    }
88044    this._expr = this._binaryExpressions[name].method.bind(this, this._expr, val._expr);
88045    return this;
88046  };
88047  Tone.TimeBase.prototype.add = function (val, units) {
88048    return this._pushExpr(val, '+', units);
88049  };
88050  Tone.TimeBase.prototype.sub = function (val, units) {
88051    return this._pushExpr(val, '-', units);
88052  };
88053  Tone.TimeBase.prototype.mult = function (val, units) {
88054    return this._pushExpr(val, '*', units);
88055  };
88056  Tone.TimeBase.prototype.div = function (val, units) {
88057    return this._pushExpr(val, '/', units);
88058  };
88059  Tone.TimeBase.prototype.valueOf = function () {
88060    return this._expr();
88061  };
88062  Tone.TimeBase.prototype.dispose = function () {
88063    this._expr = null;
88064  };
88065  return Tone.TimeBase;
88066}(Tone_core_Tone);
88067/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
88068var Tone_type_Time;
88069Tone_type_Time = function (Tone) {
88070  Tone.Time = function (val, units) {
88071    if (this instanceof Tone.Time) {
88072      this._plusNow = false;
88073      Tone.TimeBase.call(this, val, units);
88074    } else {
88075      return new Tone.Time(val, units);
88076    }
88077  };
88078  Tone.extend(Tone.Time, Tone.TimeBase);
88079  Tone.Time.prototype._unaryExpressions = Object.create(Tone.TimeBase.prototype._unaryExpressions);
88080  Tone.Time.prototype._unaryExpressions.quantize = {
88081    regexp: /^@/,
88082    method: function (rh) {
88083      return Tone.Transport.nextSubdivision(rh());
88084    }
88085  };
88086  Tone.Time.prototype._unaryExpressions.now = {
88087    regexp: /^\+/,
88088    method: function (lh) {
88089      this._plusNow = true;
88090      return lh();
88091    }
88092  };
88093  Tone.Time.prototype.quantize = function (subdiv, percent) {
88094    percent = this.defaultArg(percent, 1);
88095    this._expr = function (expr, subdivision, percent) {
88096      expr = expr();
88097      subdivision = subdivision.toSeconds();
88098      var multiple = Math.round(expr / subdivision);
88099      var ideal = multiple * subdivision;
88100      var diff = ideal - expr;
88101      return expr + diff * percent;
88102    }.bind(this, this._expr, new this.constructor(subdiv), percent);
88103    return this;
88104  };
88105  Tone.Time.prototype.addNow = function () {
88106    this._plusNow = true;
88107    return this;
88108  };
88109  Tone.Time.prototype._defaultExpr = function () {
88110    this._plusNow = true;
88111    return this._noOp;
88112  };
88113  Tone.Time.prototype.copy = function (time) {
88114    Tone.TimeBase.prototype.copy.call(this, time);
88115    this._plusNow = time._plusNow;
88116    return this;
88117  };
88118  Tone.Time.prototype.toNotation = function () {
88119    var time = this.toSeconds();
88120    var testNotations = [
88121      '1m',
88122      '2n',
88123      '4n',
88124      '8n',
88125      '16n',
88126      '32n',
88127      '64n',
88128      '128n'
88129    ];
88130    var retNotation = this._toNotationHelper(time, testNotations);
88131    var testTripletNotations = [
88132      '1m',
88133      '2n',
88134      '2t',
88135      '4n',
88136      '4t',
88137      '8n',
88138      '8t',
88139      '16n',
88140      '16t',
88141      '32n',
88142      '32t',
88143      '64n',
88144      '64t',
88145      '128n'
88146    ];
88147    var retTripletNotation = this._toNotationHelper(time, testTripletNotations);
88148    if (retTripletNotation.split('+').length < retNotation.split('+').length) {
88149      return retTripletNotation;
88150    } else {
88151      return retNotation;
88152    }
88153  };
88154  Tone.Time.prototype._toNotationHelper = function (units, testNotations) {
88155    var threshold = this._notationToUnits(testNotations[testNotations.length - 1]);
88156    var retNotation = '';
88157    for (var i = 0; i < testNotations.length; i++) {
88158      var notationTime = this._notationToUnits(testNotations[i]);
88159      var multiple = units / notationTime;
88160      var floatingPointError = 0.000001;
88161      if (1 - multiple % 1 < floatingPointError) {
88162        multiple += floatingPointError;
88163      }
88164      multiple = Math.floor(multiple);
88165      if (multiple > 0) {
88166        if (multiple === 1) {
88167          retNotation += testNotations[i];
88168        } else {
88169          retNotation += multiple.toString() + '*' + testNotations[i];
88170        }
88171        units -= multiple * notationTime;
88172        if (units < threshold) {
88173          break;
88174        } else {
88175          retNotation += ' + ';
88176        }
88177      }
88178    }
88179    if (retNotation === '') {
88180      retNotation = '0';
88181    }
88182    return retNotation;
88183  };
88184  Tone.Time.prototype._notationToUnits = function (notation) {
88185    var primaryExprs = this._primaryExpressions;
88186    var notationExprs = [
88187      primaryExprs.n,
88188      primaryExprs.t,
88189      primaryExprs.m
88190    ];
88191    for (var i = 0; i < notationExprs.length; i++) {
88192      var expr = notationExprs[i];
88193      var match = notation.match(expr.regexp);
88194      if (match) {
88195        return expr.method.call(this, match[1]);
88196      }
88197    }
88198  };
88199  Tone.Time.prototype.toBarsBeatsSixteenths = function () {
88200    var quarterTime = this._beatsToUnits(1);
88201    var quarters = this.toSeconds() / quarterTime;
88202    var measures = Math.floor(quarters / this._timeSignature());
88203    var sixteenths = quarters % 1 * 4;
88204    quarters = Math.floor(quarters) % this._timeSignature();
88205    sixteenths = sixteenths.toString();
88206    if (sixteenths.length > 3) {
88207      sixteenths = parseFloat(sixteenths).toFixed(3);
88208    }
88209    var progress = [
88210      measures,
88211      quarters,
88212      sixteenths
88213    ];
88214    return progress.join(':');
88215  };
88216  Tone.Time.prototype.toTicks = function () {
88217    var quarterTime = this._beatsToUnits(1);
88218    var quarters = this.valueOf() / quarterTime;
88219    return Math.floor(quarters * Tone.Transport.PPQ);
88220  };
88221  Tone.Time.prototype.toSamples = function () {
88222    return this.toSeconds() * this.context.sampleRate;
88223  };
88224  Tone.Time.prototype.toFrequency = function () {
88225    return 1 / this.toSeconds();
88226  };
88227  Tone.Time.prototype.toSeconds = function () {
88228    return this.valueOf();
88229  };
88230  Tone.Time.prototype.toMilliseconds = function () {
88231    return this.toSeconds() * 1000;
88232  };
88233  Tone.Time.prototype.valueOf = function () {
88234    var val = this._expr();
88235    return val + (this._plusNow ? this.now() : 0);
88236  };
88237  return Tone.Time;
88238}(Tone_core_Tone);
88239/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
88240var Tone_type_Frequency;
88241Tone_type_Frequency = function (Tone) {
88242  Tone.Frequency = function (val, units) {
88243    if (this instanceof Tone.Frequency) {
88244      Tone.TimeBase.call(this, val, units);
88245    } else {
88246      return new Tone.Frequency(val, units);
88247    }
88248  };
88249  Tone.extend(Tone.Frequency, Tone.TimeBase);
88250  Tone.Frequency.prototype._primaryExpressions = Object.create(Tone.TimeBase.prototype._primaryExpressions);
88251  Tone.Frequency.prototype._primaryExpressions.midi = {
88252    regexp: /^(\d+(?:\.\d+)?midi)/,
88253    method: function (value) {
88254      return this.midiToFrequency(value);
88255    }
88256  };
88257  Tone.Frequency.prototype._primaryExpressions.note = {
88258    regexp: /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i,
88259    method: function (pitch, octave) {
88260      var index = noteToScaleIndex[pitch.toLowerCase()];
88261      var noteNumber = index + (parseInt(octave) + 1) * 12;
88262      return this.midiToFrequency(noteNumber);
88263    }
88264  };
88265  Tone.Frequency.prototype._primaryExpressions.tr = {
88266    regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/,
88267    method: function (m, q, s) {
88268      var total = 1;
88269      if (m && m !== '0') {
88270        total *= this._beatsToUnits(this._timeSignature() * parseFloat(m));
88271      }
88272      if (q && q !== '0') {
88273        total *= this._beatsToUnits(parseFloat(q));
88274      }
88275      if (s && s !== '0') {
88276        total *= this._beatsToUnits(parseFloat(s) / 4);
88277      }
88278      return total;
88279    }
88280  };
88281  Tone.Frequency.prototype.transpose = function (interval) {
88282    this._expr = function (expr, interval) {
88283      var val = expr();
88284      return val * this.intervalToFrequencyRatio(interval);
88285    }.bind(this, this._expr, interval);
88286    return this;
88287  };
88288  Tone.Frequency.prototype.harmonize = function (intervals) {
88289    this._expr = function (expr, intervals) {
88290      var val = expr();
88291      var ret = [];
88292      for (var i = 0; i < intervals.length; i++) {
88293        ret[i] = val * this.intervalToFrequencyRatio(intervals[i]);
88294      }
88295      return ret;
88296    }.bind(this, this._expr, intervals);
88297    return this;
88298  };
88299  Tone.Frequency.prototype.toMidi = function () {
88300    return this.frequencyToMidi(this.valueOf());
88301  };
88302  Tone.Frequency.prototype.toNote = function () {
88303    var freq = this.valueOf();
88304    var log = Math.log(freq / Tone.Frequency.A4) / Math.LN2;
88305    var noteNumber = Math.round(12 * log) + 57;
88306    var octave = Math.floor(noteNumber / 12);
88307    if (octave < 0) {
88308      noteNumber += -12 * octave;
88309    }
88310    var noteName = scaleIndexToNote[noteNumber % 12];
88311    return noteName + octave.toString();
88312  };
88313  Tone.Frequency.prototype.toSeconds = function () {
88314    return 1 / this.valueOf();
88315  };
88316  Tone.Frequency.prototype.toFrequency = function () {
88317    return this.valueOf();
88318  };
88319  Tone.Frequency.prototype.toTicks = function () {
88320    var quarterTime = this._beatsToUnits(1);
88321    var quarters = this.valueOf() / quarterTime;
88322    return Math.floor(quarters * Tone.Transport.PPQ);
88323  };
88324  Tone.Frequency.prototype._frequencyToUnits = function (freq) {
88325    return freq;
88326  };
88327  Tone.Frequency.prototype._ticksToUnits = function (ticks) {
88328    return 1 / (ticks * 60 / (Tone.Transport.bpm.value * Tone.Transport.PPQ));
88329  };
88330  Tone.Frequency.prototype._beatsToUnits = function (beats) {
88331    return 1 / Tone.TimeBase.prototype._beatsToUnits.call(this, beats);
88332  };
88333  Tone.Frequency.prototype._secondsToUnits = function (seconds) {
88334    return 1 / seconds;
88335  };
88336  Tone.Frequency.prototype._defaultUnits = 'hz';
88337  var noteToScaleIndex = {
88338    'cbb': -2,
88339    'cb': -1,
88340    'c': 0,
88341    'c#': 1,
88342    'cx': 2,
88343    'dbb': 0,
88344    'db': 1,
88345    'd': 2,
88346    'd#': 3,
88347    'dx': 4,
88348    'ebb': 2,
88349    'eb': 3,
88350    'e': 4,
88351    'e#': 5,
88352    'ex': 6,
88353    'fbb': 3,
88354    'fb': 4,
88355    'f': 5,
88356    'f#': 6,
88357    'fx': 7,
88358    'gbb': 5,
88359    'gb': 6,
88360    'g': 7,
88361    'g#': 8,
88362    'gx': 9,
88363    'abb': 7,
88364    'ab': 8,
88365    'a': 9,
88366    'a#': 10,
88367    'ax': 11,
88368    'bbb': 9,
88369    'bb': 10,
88370    'b': 11,
88371    'b#': 12,
88372    'bx': 13
88373  };
88374  var scaleIndexToNote = [
88375    'C',
88376    'C#',
88377    'D',
88378    'D#',
88379    'E',
88380    'F',
88381    'F#',
88382    'G',
88383    'G#',
88384    'A',
88385    'A#',
88386    'B'
88387  ];
88388  Tone.Frequency.A4 = 440;
88389  Tone.Frequency.prototype.midiToFrequency = function (midi) {
88390    return Tone.Frequency.A4 * Math.pow(2, (midi - 69) / 12);
88391  };
88392  Tone.Frequency.prototype.frequencyToMidi = function (frequency) {
88393    return 69 + 12 * Math.log(frequency / Tone.Frequency.A4) / Math.LN2;
88394  };
88395  return Tone.Frequency;
88396}(Tone_core_Tone);
88397/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
88398var Tone_type_TransportTime;
88399Tone_type_TransportTime = function (Tone) {
88400  Tone.TransportTime = function (val, units) {
88401    if (this instanceof Tone.TransportTime) {
88402      Tone.Time.call(this, val, units);
88403    } else {
88404      return new Tone.TransportTime(val, units);
88405    }
88406  };
88407  Tone.extend(Tone.TransportTime, Tone.Time);
88408  Tone.TransportTime.prototype._unaryExpressions = Object.create(Tone.Time.prototype._unaryExpressions);
88409  Tone.TransportTime.prototype._unaryExpressions.quantize = {
88410    regexp: /^@/,
88411    method: function (rh) {
88412      var subdivision = this._secondsToTicks(rh());
88413      var multiple = Math.ceil(Tone.Transport.ticks / subdivision);
88414      return this._ticksToUnits(multiple * subdivision);
88415    }
88416  };
88417  Tone.TransportTime.prototype._secondsToTicks = function (seconds) {
88418    var quarterTime = this._beatsToUnits(1);
88419    var quarters = seconds / quarterTime;
88420    return Math.round(quarters * Tone.Transport.PPQ);
88421  };
88422  Tone.TransportTime.prototype.valueOf = function () {
88423    var val = this._secondsToTicks(this._expr());
88424    return val + (this._plusNow ? Tone.Transport.ticks : 0);
88425  };
88426  Tone.TransportTime.prototype.toTicks = function () {
88427    return this.valueOf();
88428  };
88429  Tone.TransportTime.prototype.toSeconds = function () {
88430    var val = this._expr();
88431    return val + (this._plusNow ? Tone.Transport.seconds : 0);
88432  };
88433  Tone.TransportTime.prototype.toFrequency = function () {
88434    return 1 / this.toSeconds();
88435  };
88436  return Tone.TransportTime;
88437}(Tone_core_Tone);
88438/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
88439var Tone_core_Emitter;
88440Tone_core_Emitter = function (Tone) {
88441  'use strict';
88442  Tone.Emitter = function () {
88443    this._events = {};
88444  };
88445  Tone.extend(Tone.Emitter);
88446  Tone.Emitter.prototype.on = function (event, callback) {
88447    var events = event.split(/\W+/);
88448    for (var i = 0; i < events.length; i++) {
88449      var eventName = events[i];
88450      if (!this._events.hasOwnProperty(eventName)) {
88451        this._events[eventName] = [];
88452      }
88453      this._events[eventName].push(callback);
88454    }
88455    return this;
88456  };
88457  Tone.Emitter.prototype.off = function (event, callback) {
88458    var events = event.split(/\W+/);
88459    for (var ev = 0; ev < events.length; ev++) {
88460      event = events[ev];
88461      if (this._events.hasOwnProperty(event)) {
88462        if (Tone.prototype.isUndef(callback)) {
88463          this._events[event] = [];
88464        } else {
88465          var eventList = this._events[event];
88466          for (var i = 0; i < eventList.length; i++) {
88467            if (eventList[i] === callback) {
88468              eventList.splice(i, 1);
88469            }
88470          }
88471        }
88472      }
88473    }
88474    return this;
88475  };
88476  Tone.Emitter.prototype.emit = function (event) {
88477    if (this._events) {
88478      var args = Array.apply(null, arguments).slice(1);
88479      if (this._events.hasOwnProperty(event)) {
88480        var eventList = this._events[event];
88481        for (var i = 0, len = eventList.length; i < len; i++) {
88482          eventList[i].apply(this, args);
88483        }
88484      }
88485    }
88486    return this;
88487  };
88488  Tone.Emitter.mixin = function (object) {
88489    var functions = [
88490      'on',
88491      'off',
88492      'emit'
88493    ];
88494    object._events = {};
88495    for (var i = 0; i < functions.length; i++) {
88496      var func = functions[i];
88497      var emitterFunc = Tone.Emitter.prototype[func];
88498      object[func] = emitterFunc;
88499    }
88500  };
88501  Tone.Emitter.prototype.dispose = function () {
88502    Tone.prototype.dispose.call(this);
88503    this._events = null;
88504    return this;
88505  };
88506  return Tone.Emitter;
88507}(Tone_core_Tone);
88508/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
88509var Tone_core_Context;
88510Tone_core_Context = function (Tone) {
88511  if (!window.hasOwnProperty('AudioContext') && window.hasOwnProperty('webkitAudioContext')) {
88512    window.AudioContext = window.webkitAudioContext;
88513  }
88514  Tone.Context = function (context) {
88515    Tone.Emitter.call(this);
88516    if (!context) {
88517      context = new window.AudioContext();
88518    }
88519    this._context = context;
88520    for (var prop in this._context) {
88521      this._defineProperty(this._context, prop);
88522    }
88523    this._latencyHint = 'interactive';
88524    this._lookAhead = 0.1;
88525    this._updateInterval = this._lookAhead / 3;
88526    this._computedUpdateInterval = 0;
88527    this._worker = this._createWorker();
88528    this._constants = {};
88529  };
88530  Tone.extend(Tone.Context, Tone.Emitter);
88531  Tone.Emitter.mixin(Tone.Context);
88532  Tone.Context.prototype._defineProperty = function (context, prop) {
88533    if (this.isUndef(this[prop])) {
88534      Object.defineProperty(this, prop, {
88535        get: function () {
88536          if (typeof context[prop] === 'function') {
88537            return context[prop].bind(context);
88538          } else {
88539            return context[prop];
88540          }
88541        },
88542        set: function (val) {
88543          context[prop] = val;
88544        }
88545      });
88546    }
88547  };
88548  Tone.Context.prototype.now = function () {
88549    return this._context.currentTime;
88550  };
88551  Tone.Context.prototype._createWorker = function () {
88552    window.URL = window.URL || window.webkitURL;
88553    var blob = new Blob(['var timeoutTime = ' + (this._updateInterval * 1000).toFixed(1) + ';' + 'self.onmessage = function(msg){' + '\ttimeoutTime = parseInt(msg.data);' + '};' + 'function tick(){' + '\tsetTimeout(tick, timeoutTime);' + '\tself.postMessage(\'tick\');' + '}' + 'tick();']);
88554    var blobUrl = URL.createObjectURL(blob);
88555    var worker = new Worker(blobUrl);
88556    worker.addEventListener('message', function () {
88557      this.emit('tick');
88558    }.bind(this));
88559    worker.addEventListener('message', function () {
88560      var now = this.now();
88561      if (this.isNumber(this._lastUpdate)) {
88562        var diff = now - this._lastUpdate;
88563        this._computedUpdateInterval = Math.max(diff, this._computedUpdateInterval * 0.97);
88564      }
88565      this._lastUpdate = now;
88566    }.bind(this));
88567    return worker;
88568  };
88569  Tone.Context.prototype.getConstant = function (val) {
88570    if (this._constants[val]) {
88571      return this._constants[val];
88572    } else {
88573      var buffer = this._context.createBuffer(1, 128, this._context.sampleRate);
88574      var arr = buffer.getChannelData(0);
88575      for (var i = 0; i < arr.length; i++) {
88576        arr[i] = val;
88577      }
88578      var constant = this._context.createBufferSource();
88579      constant.channelCount = 1;
88580      constant.channelCountMode = 'explicit';
88581      constant.buffer = buffer;
88582      constant.loop = true;
88583      constant.start(0);
88584      this._constants[val] = constant;
88585      return constant;
88586    }
88587  };
88588  Object.defineProperty(Tone.Context.prototype, 'lag', {
88589    get: function () {
88590      var diff = this._computedUpdateInterval - this._updateInterval;
88591      diff = Math.max(diff, 0);
88592      return diff;
88593    }
88594  });
88595  Object.defineProperty(Tone.Context.prototype, 'lookAhead', {
88596    get: function () {
88597      return this._lookAhead;
88598    },
88599    set: function (lA) {
88600      this._lookAhead = lA;
88601    }
88602  });
88603  Object.defineProperty(Tone.Context.prototype, 'updateInterval', {
88604    get: function () {
88605      return this._updateInterval;
88606    },
88607    set: function (interval) {
88608      this._updateInterval = Math.max(interval, Tone.prototype.blockTime);
88609      this._worker.postMessage(Math.max(interval * 1000, 1));
88610    }
88611  });
88612  Object.defineProperty(Tone.Context.prototype, 'latencyHint', {
88613    get: function () {
88614      return this._latencyHint;
88615    },
88616    set: function (hint) {
88617      var lookAhead = hint;
88618      this._latencyHint = hint;
88619      if (this.isString(hint)) {
88620        switch (hint) {
88621        case 'interactive':
88622          lookAhead = 0.1;
88623          this._context.latencyHint = hint;
88624          break;
88625        case 'playback':
88626          lookAhead = 0.8;
88627          this._context.latencyHint = hint;
88628          break;
88629        case 'balanced':
88630          lookAhead = 0.25;
88631          this._context.latencyHint = hint;
88632          break;
88633        case 'fastest':
88634          lookAhead = 0.01;
88635          break;
88636        }
88637      }
88638      this.lookAhead = lookAhead;
88639      this.updateInterval = lookAhead / 3;
88640    }
88641  });
88642  function shimConnect() {
88643    var nativeConnect = AudioNode.prototype.connect;
88644    var nativeDisconnect = AudioNode.prototype.disconnect;
88645    function toneConnect(B, outNum, inNum) {
88646      if (B.input) {
88647        if (Array.isArray(B.input)) {
88648          if (Tone.prototype.isUndef(inNum)) {
88649            inNum = 0;
88650          }
88651          this.connect(B.input[inNum]);
88652        } else {
88653          this.connect(B.input, outNum, inNum);
88654        }
88655      } else {
88656        try {
88657          if (B instanceof AudioNode) {
88658            nativeConnect.call(this, B, outNum, inNum);
88659          } else {
88660            nativeConnect.call(this, B, outNum);
88661          }
88662        } catch (e) {
88663          throw new Error('error connecting to node: ' + B + '\n' + e);
88664        }
88665      }
88666    }
88667    function toneDisconnect(B, outNum, inNum) {
88668      if (B && B.input && Array.isArray(B.input)) {
88669        if (Tone.prototype.isUndef(inNum)) {
88670          inNum = 0;
88671        }
88672        this.disconnect(B.input[inNum], outNum, inNum);
88673      } else if (B && B.input) {
88674        this.disconnect(B.input, outNum, inNum);
88675      } else {
88676        try {
88677          nativeDisconnect.apply(this, arguments);
88678        } catch (e) {
88679          throw new Error('error disconnecting node: ' + B + '\n' + e);
88680        }
88681      }
88682    }
88683    if (AudioNode.prototype.connect !== toneConnect) {
88684      AudioNode.prototype.connect = toneConnect;
88685      AudioNode.prototype.disconnect = toneDisconnect;
88686    }
88687  }
88688  if (Tone.supported) {
88689    shimConnect();
88690    Tone.context = new Tone.Context();
88691  } else {
88692    console.warn('This browser does not support Tone.js');
88693  }
88694  return Tone.Context;
88695}(Tone_core_Tone);
88696/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
88697var Tone_type_Type;
88698Tone_type_Type = function (Tone) {
88699  Tone.Type = {
88700    Default: 'number',
88701    Time: 'time',
88702    Frequency: 'frequency',
88703    TransportTime: 'transportTime',
88704    Ticks: 'ticks',
88705    NormalRange: 'normalRange',
88706    AudioRange: 'audioRange',
88707    Decibels: 'db',
88708    Interval: 'interval',
88709    BPM: 'bpm',
88710    Positive: 'positive',
88711    Cents: 'cents',
88712    Degrees: 'degrees',
88713    MIDI: 'midi',
88714    BarsBeatsSixteenths: 'barsBeatsSixteenths',
88715    Samples: 'samples',
88716    Hertz: 'hertz',
88717    Note: 'note',
88718    Milliseconds: 'milliseconds',
88719    Seconds: 'seconds',
88720    Notation: 'notation'
88721  };
88722  Tone.prototype.toSeconds = function (time) {
88723    if (this.isNumber(time)) {
88724      return time;
88725    } else if (this.isUndef(time)) {
88726      return this.now();
88727    } else if (this.isString(time)) {
88728      return new Tone.Time(time).toSeconds();
88729    } else if (time instanceof Tone.TimeBase) {
88730      return time.toSeconds();
88731    }
88732  };
88733  Tone.prototype.toFrequency = function (freq) {
88734    if (this.isNumber(freq)) {
88735      return freq;
88736    } else if (this.isString(freq) || this.isUndef(freq)) {
88737      return new Tone.Frequency(freq).valueOf();
88738    } else if (freq instanceof Tone.TimeBase) {
88739      return freq.toFrequency();
88740    }
88741  };
88742  Tone.prototype.toTicks = function (time) {
88743    if (this.isNumber(time) || this.isString(time)) {
88744      return new Tone.TransportTime(time).toTicks();
88745    } else if (this.isUndef(time)) {
88746      return Tone.Transport.ticks;
88747    } else if (time instanceof Tone.TimeBase) {
88748      return time.toTicks();
88749    }
88750  };
88751  return Tone;
88752}(Tone_core_Tone, Tone_type_Time, Tone_type_Frequency, Tone_type_TransportTime);
88753/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
88754var Tone_core_Param;
88755Tone_core_Param = function (Tone) {
88756  'use strict';
88757  Tone.Param = function () {
88758    var options = this.optionsObject(arguments, [
88759      'param',
88760      'units',
88761      'convert'
88762    ], Tone.Param.defaults);
88763    this._param = this.input = options.param;
88764    this.units = options.units;
88765    this.convert = options.convert;
88766    this.overridden = false;
88767    this._lfo = null;
88768    if (this.isObject(options.lfo)) {
88769      this.value = options.lfo;
88770    } else if (!this.isUndef(options.value)) {
88771      this.value = options.value;
88772    }
88773  };
88774  Tone.extend(Tone.Param);
88775  Tone.Param.defaults = {
88776    'units': Tone.Type.Default,
88777    'convert': true,
88778    'param': undefined
88779  };
88780  Object.defineProperty(Tone.Param.prototype, 'value', {
88781    get: function () {
88782      return this._toUnits(this._param.value);
88783    },
88784    set: function (value) {
88785      if (this.isObject(value)) {
88786        if (this.isUndef(Tone.LFO)) {
88787          throw new Error('Include \'Tone.LFO\' to use an LFO as a Param value.');
88788        }
88789        if (this._lfo) {
88790          this._lfo.dispose();
88791        }
88792        this._lfo = new Tone.LFO(value).start();
88793        this._lfo.connect(this.input);
88794      } else {
88795        var convertedVal = this._fromUnits(value);
88796        this._param.cancelScheduledValues(0);
88797        this._param.value = convertedVal;
88798      }
88799    }
88800  });
88801  Tone.Param.prototype._fromUnits = function (val) {
88802    if (this.convert || this.isUndef(this.convert)) {
88803      switch (this.units) {
88804      case Tone.Type.Time:
88805        return this.toSeconds(val);
88806      case Tone.Type.Frequency:
88807        return this.toFrequency(val);
88808      case Tone.Type.Decibels:
88809        return this.dbToGain(val);
88810      case Tone.Type.NormalRange:
88811        return Math.min(Math.max(val, 0), 1);
88812      case Tone.Type.AudioRange:
88813        return Math.min(Math.max(val, -1), 1);
88814      case Tone.Type.Positive:
88815        return Math.max(val, 0);
88816      default:
88817        return val;
88818      }
88819    } else {
88820      return val;
88821    }
88822  };
88823  Tone.Param.prototype._toUnits = function (val) {
88824    if (this.convert || this.isUndef(this.convert)) {
88825      switch (this.units) {
88826      case Tone.Type.Decibels:
88827        return this.gainToDb(val);
88828      default:
88829        return val;
88830      }
88831    } else {
88832      return val;
88833    }
88834  };
88835  Tone.Param.prototype._minOutput = 0.00001;
88836  Tone.Param.prototype.setValueAtTime = function (value, time) {
88837    value = this._fromUnits(value);
88838    time = this.toSeconds(time);
88839    if (time <= this.now() + this.blockTime) {
88840      this._param.value = value;
88841    } else {
88842      this._param.setValueAtTime(value, time);
88843    }
88844    return this;
88845  };
88846  Tone.Param.prototype.setRampPoint = function (now) {
88847    now = this.defaultArg(now, this.now());
88848    var currentVal = this._param.value;
88849    if (currentVal === 0) {
88850      currentVal = this._minOutput;
88851    }
88852    this._param.setValueAtTime(currentVal, now);
88853    return this;
88854  };
88855  Tone.Param.prototype.linearRampToValueAtTime = function (value, endTime) {
88856    value = this._fromUnits(value);
88857    this._param.linearRampToValueAtTime(value, this.toSeconds(endTime));
88858    return this;
88859  };
88860  Tone.Param.prototype.exponentialRampToValueAtTime = function (value, endTime) {
88861    value = this._fromUnits(value);
88862    value = Math.max(this._minOutput, value);
88863    this._param.exponentialRampToValueAtTime(value, this.toSeconds(endTime));
88864    return this;
88865  };
88866  Tone.Param.prototype.exponentialRampToValue = function (value, rampTime, startTime) {
88867    startTime = this.toSeconds(startTime);
88868    this.setRampPoint(startTime);
88869    this.exponentialRampToValueAtTime(value, startTime + this.toSeconds(rampTime));
88870    return this;
88871  };
88872  Tone.Param.prototype.linearRampToValue = function (value, rampTime, startTime) {
88873    startTime = this.toSeconds(startTime);
88874    this.setRampPoint(startTime);
88875    this.linearRampToValueAtTime(value, startTime + this.toSeconds(rampTime));
88876    return this;
88877  };
88878  Tone.Param.prototype.setTargetAtTime = function (value, startTime, timeConstant) {
88879    value = this._fromUnits(value);
88880    value = Math.max(this._minOutput, value);
88881    timeConstant = Math.max(this._minOutput, timeConstant);
88882    this._param.setTargetAtTime(value, this.toSeconds(startTime), timeConstant);
88883    return this;
88884  };
88885  Tone.Param.prototype.setValueCurveAtTime = function (values, startTime, duration) {
88886    for (var i = 0; i < values.length; i++) {
88887      values[i] = this._fromUnits(values[i]);
88888    }
88889    this._param.setValueCurveAtTime(values, this.toSeconds(startTime), this.toSeconds(duration));
88890    return this;
88891  };
88892  Tone.Param.prototype.cancelScheduledValues = function (startTime) {
88893    this._param.cancelScheduledValues(this.toSeconds(startTime));
88894    return this;
88895  };
88896  Tone.Param.prototype.rampTo = function (value, rampTime, startTime) {
88897    rampTime = this.defaultArg(rampTime, 0);
88898    if (this.units === Tone.Type.Frequency || this.units === Tone.Type.BPM || this.units === Tone.Type.Decibels) {
88899      this.exponentialRampToValue(value, rampTime, startTime);
88900    } else {
88901      this.linearRampToValue(value, rampTime, startTime);
88902    }
88903    return this;
88904  };
88905  Object.defineProperty(Tone.Param.prototype, 'lfo', {
88906    get: function () {
88907      return this._lfo;
88908    }
88909  });
88910  Tone.Param.prototype.dispose = function () {
88911    Tone.prototype.dispose.call(this);
88912    this._param = null;
88913    if (this._lfo) {
88914      this._lfo.dispose();
88915      this._lfo = null;
88916    }
88917    return this;
88918  };
88919  return Tone.Param;
88920}(Tone_core_Tone);
88921/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
88922var Tone_core_Gain;
88923Tone_core_Gain = function (Tone) {
88924  'use strict';
88925  if (window.GainNode && !AudioContext.prototype.createGain) {
88926    AudioContext.prototype.createGain = AudioContext.prototype.createGainNode;
88927  }
88928  Tone.Gain = function () {
88929    var options = this.optionsObject(arguments, [
88930      'gain',
88931      'units'
88932    ], Tone.Gain.defaults);
88933    this.input = this.output = this._gainNode = this.context.createGain();
88934    this.gain = new Tone.Param({
88935      'param': this._gainNode.gain,
88936      'units': options.units,
88937      'value': options.gain,
88938      'convert': options.convert
88939    });
88940    this._readOnly('gain');
88941  };
88942  Tone.extend(Tone.Gain);
88943  Tone.Gain.defaults = {
88944    'gain': 1,
88945    'convert': true
88946  };
88947  Tone.Gain.prototype.dispose = function () {
88948    Tone.Param.prototype.dispose.call(this);
88949    this._gainNode.disconnect();
88950    this._gainNode = null;
88951    this._writable('gain');
88952    this.gain.dispose();
88953    this.gain = null;
88954  };
88955  Tone.prototype.createInsOuts = function (inputs, outputs) {
88956    if (inputs === 1) {
88957      this.input = new Tone.Gain();
88958    } else if (inputs > 1) {
88959      this.input = new Array(inputs);
88960    }
88961    if (outputs === 1) {
88962      this.output = new Tone.Gain();
88963    } else if (outputs > 1) {
88964      this.output = new Array(inputs);
88965    }
88966  };
88967  return Tone.Gain;
88968}(Tone_core_Tone, Tone_core_Param);
88969/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
88970var Tone_signal_Signal;
88971Tone_signal_Signal = function (Tone) {
88972  'use strict';
88973  Tone.Signal = function () {
88974    var options = this.optionsObject(arguments, [
88975      'value',
88976      'units'
88977    ], Tone.Signal.defaults);
88978    this.output = this._gain = this.context.createGain();
88979    options.param = this._gain.gain;
88980    Tone.Param.call(this, options);
88981    this.input = this._param = this._gain.gain;
88982    this.context.getConstant(1).chain(this._gain);
88983  };
88984  Tone.extend(Tone.Signal, Tone.Param);
88985  Tone.Signal.defaults = {
88986    'value': 0,
88987    'units': Tone.Type.Default,
88988    'convert': true
88989  };
88990  Tone.Signal.prototype.connect = Tone.SignalBase.prototype.connect;
88991  Tone.Signal.prototype.dispose = function () {
88992    Tone.Param.prototype.dispose.call(this);
88993    this._param = null;
88994    this._gain.disconnect();
88995    this._gain = null;
88996    return this;
88997  };
88998  return Tone.Signal;
88999}(Tone_core_Tone, Tone_signal_WaveShaper, Tone_type_Type, Tone_core_Param);
89000/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
89001var Tone_signal_Add;
89002Tone_signal_Add = function (Tone) {
89003  'use strict';
89004  Tone.Add = function (value) {
89005    this.createInsOuts(2, 0);
89006    this._sum = this.input[0] = this.input[1] = this.output = new Tone.Gain();
89007    this._param = this.input[1] = new Tone.Signal(value);
89008    this._param.connect(this._sum);
89009  };
89010  Tone.extend(Tone.Add, Tone.Signal);
89011  Tone.Add.prototype.dispose = function () {
89012    Tone.prototype.dispose.call(this);
89013    this._sum.dispose();
89014    this._sum = null;
89015    this._param.dispose();
89016    this._param = null;
89017    return this;
89018  };
89019  return Tone.Add;
89020}(Tone_core_Tone, Tone_signal_Signal);
89021/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
89022var Tone_signal_Multiply;
89023Tone_signal_Multiply = function (Tone) {
89024  'use strict';
89025  Tone.Multiply = function (value) {
89026    this.createInsOuts(2, 0);
89027    this._mult = this.input[0] = this.output = new Tone.Gain();
89028    this._param = this.input[1] = this.output.gain;
89029    this._param.value = this.defaultArg(value, 0);
89030  };
89031  Tone.extend(Tone.Multiply, Tone.Signal);
89032  Tone.Multiply.prototype.dispose = function () {
89033    Tone.prototype.dispose.call(this);
89034    this._mult.dispose();
89035    this._mult = null;
89036    this._param = null;
89037    return this;
89038  };
89039  return Tone.Multiply;
89040}(Tone_core_Tone, Tone_signal_Signal);
89041/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
89042var Tone_signal_Scale;
89043Tone_signal_Scale = function (Tone) {
89044  'use strict';
89045  Tone.Scale = function (outputMin, outputMax) {
89046    this._outputMin = this.defaultArg(outputMin, 0);
89047    this._outputMax = this.defaultArg(outputMax, 1);
89048    this._scale = this.input = new Tone.Multiply(1);
89049    this._add = this.output = new Tone.Add(0);
89050    this._scale.connect(this._add);
89051    this._setRange();
89052  };
89053  Tone.extend(Tone.Scale, Tone.SignalBase);
89054  Object.defineProperty(Tone.Scale.prototype, 'min', {
89055    get: function () {
89056      return this._outputMin;
89057    },
89058    set: function (min) {
89059      this._outputMin = min;
89060      this._setRange();
89061    }
89062  });
89063  Object.defineProperty(Tone.Scale.prototype, 'max', {
89064    get: function () {
89065      return this._outputMax;
89066    },
89067    set: function (max) {
89068      this._outputMax = max;
89069      this._setRange();
89070    }
89071  });
89072  Tone.Scale.prototype._setRange = function () {
89073    this._add.value = this._outputMin;
89074    this._scale.value = this._outputMax - this._outputMin;
89075  };
89076  Tone.Scale.prototype.dispose = function () {
89077    Tone.prototype.dispose.call(this);
89078    this._add.dispose();
89079    this._add = null;
89080    this._scale.dispose();
89081    this._scale = null;
89082    return this;
89083  };
89084  return Tone.Scale;
89085}(Tone_core_Tone, Tone_signal_Add, Tone_signal_Multiply);
89086var signal;
89087'use strict';
89088signal = function () {
89089  // Signal is built with the Tone.js signal by Yotam Mann
89090  // https://github.com/TONEnoTONE/Tone.js/
89091  var Signal = Tone_signal_Signal;
89092  var Add = Tone_signal_Add;
89093  var Mult = Tone_signal_Multiply;
89094  var Scale = Tone_signal_Scale;
89095  var Tone = Tone_core_Tone;
89096  var p5sound = master;
89097  Tone.setContext(p5sound.audiocontext);
89098  /**
89099   *  <p>p5.Signal is a constant audio-rate signal used by p5.Oscillator
89100   *  and p5.Envelope for modulation math.</p>
89101   *
89102   *  <p>This is necessary because Web Audio is processed on a seprate clock.
89103   *  For example, the p5 draw loop runs about 60 times per second. But
89104   *  the audio clock must process samples 44100 times per second. If we
89105   *  want to add a value to each of those samples, we can't do it in the
89106   *  draw loop, but we can do it by adding a constant-rate audio signal.</p.
89107   *
89108   *  <p>This class mostly functions behind the scenes in p5.sound, and returns
89109   *  a Tone.Signal from the Tone.js library by Yotam Mann.
89110   *  If you want to work directly with audio signals for modular
89111   *  synthesis, check out
89112   *  <a href='http://bit.ly/1oIoEng' target=_'blank'>tone.js.</a></p>
89113   *
89114   *  @class  p5.Signal
89115   *  @constructor
89116   *  @return {Tone.Signal} A Signal object from the Tone.js library
89117   *  @example
89118   *  <div><code>
89119   *  function setup() {
89120   *    carrier = new p5.Oscillator('sine');
89121   *    carrier.amp(1); // set amplitude
89122   *    carrier.freq(220); // set frequency
89123   *    carrier.start(); // start oscillating
89124   *
89125   *    modulator = new p5.Oscillator('sawtooth');
89126   *    modulator.disconnect();
89127   *    modulator.amp(1);
89128   *    modulator.freq(4);
89129   *    modulator.start();
89130   *
89131   *    // Modulator's default amplitude range is -1 to 1.
89132   *    // Multiply it by -200, so the range is -200 to 200
89133   *    // then add 220 so the range is 20 to 420
89134   *    carrier.freq( modulator.mult(-200).add(220) );
89135   *  }
89136   *  </code></div>
89137   */
89138  p5.Signal = function (value) {
89139    var s = new Signal(value);
89140    // p5sound.soundArray.push(s);
89141    return s;
89142  };
89143  /**
89144   *  Fade to value, for smooth transitions
89145   *
89146   *  @method  fade
89147   *  @param  {Number} value          Value to set this signal
89148   *  @param  {Number} [secondsFromNow] Length of fade, in seconds from now
89149   */
89150  Signal.prototype.fade = Signal.prototype.linearRampToValueAtTime;
89151  Mult.prototype.fade = Signal.prototype.fade;
89152  Add.prototype.fade = Signal.prototype.fade;
89153  Scale.prototype.fade = Signal.prototype.fade;
89154  /**
89155   *  Connect a p5.sound object or Web Audio node to this
89156   *  p5.Signal so that its amplitude values can be scaled.
89157   *
89158   *  @method setInput
89159   *  @param {Object} input
89160   */
89161  Signal.prototype.setInput = function (_input) {
89162    _input.connect(this);
89163  };
89164  Mult.prototype.setInput = Signal.prototype.setInput;
89165  Add.prototype.setInput = Signal.prototype.setInput;
89166  Scale.prototype.setInput = Signal.prototype.setInput;
89167  // signals can add / mult / scale themselves
89168  /**
89169   *  Add a constant value to this audio signal,
89170   *  and return the resulting audio signal. Does
89171   *  not change the value of the original signal,
89172   *  instead it returns a new p5.SignalAdd.
89173   *
89174   *  @method  add
89175   *  @param {Number} number
89176   *  @return {p5.Signal} object
89177   */
89178  Signal.prototype.add = function (num) {
89179    var add = new Add(num);
89180    // add.setInput(this);
89181    this.connect(add);
89182    return add;
89183  };
89184  Mult.prototype.add = Signal.prototype.add;
89185  Add.prototype.add = Signal.prototype.add;
89186  Scale.prototype.add = Signal.prototype.add;
89187  /**
89188   *  Multiply this signal by a constant value,
89189   *  and return the resulting audio signal. Does
89190   *  not change the value of the original signal,
89191   *  instead it returns a new p5.SignalMult.
89192   *
89193   *  @method  mult
89194   *  @param {Number} number to multiply
89195   *  @return {p5.Signal} object
89196   */
89197  Signal.prototype.mult = function (num) {
89198    var mult = new Mult(num);
89199    // mult.setInput(this);
89200    this.connect(mult);
89201    return mult;
89202  };
89203  Mult.prototype.mult = Signal.prototype.mult;
89204  Add.prototype.mult = Signal.prototype.mult;
89205  Scale.prototype.mult = Signal.prototype.mult;
89206  /**
89207   *  Scale this signal value to a given range,
89208   *  and return the result as an audio signal. Does
89209   *  not change the value of the original signal,
89210   *  instead it returns a new p5.SignalScale.
89211   *
89212   *  @method  scale
89213   *  @param {Number} number to multiply
89214   *  @param  {Number} inMin  input range minumum
89215   *  @param  {Number} inMax  input range maximum
89216   *  @param  {Number} outMin input range minumum
89217   *  @param  {Number} outMax input range maximum
89218   *  @return {p5.Signal} object
89219   */
89220  Signal.prototype.scale = function (inMin, inMax, outMin, outMax) {
89221    var mapOutMin, mapOutMax;
89222    if (arguments.length === 4) {
89223      mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;
89224      mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;
89225    } else {
89226      mapOutMin = arguments[0];
89227      mapOutMax = arguments[1];
89228    }
89229    var scale = new Scale(mapOutMin, mapOutMax);
89230    this.connect(scale);
89231    return scale;
89232  };
89233  Mult.prototype.scale = Signal.prototype.scale;
89234  Add.prototype.scale = Signal.prototype.scale;
89235  Scale.prototype.scale = Signal.prototype.scale;
89236}(Tone_signal_Signal, Tone_signal_Add, Tone_signal_Multiply, Tone_signal_Scale, Tone_core_Tone, master);
89237var oscillator;
89238'use strict';
89239oscillator = function () {
89240  var p5sound = master;
89241  var Add = Tone_signal_Add;
89242  var Mult = Tone_signal_Multiply;
89243  var Scale = Tone_signal_Scale;
89244  /**
89245   *  <p>Creates a signal that oscillates between -1.0 and 1.0.
89246   *  By default, the oscillation takes the form of a sinusoidal
89247   *  shape ('sine'). Additional types include 'triangle',
89248   *  'sawtooth' and 'square'. The frequency defaults to
89249   *  440 oscillations per second (440Hz, equal to the pitch of an
89250   *  'A' note).</p>
89251   *
89252   *  <p>Set the type of oscillation with setType(), or by instantiating a
89253   *  specific oscillator: <a href="/reference/#/p5.SinOsc">p5.SinOsc</a>, <a
89254   *  href="/reference/#/p5.TriOsc">p5.TriOsc</a>, <a
89255   *  href="/reference/#/p5.SqrOsc">p5.SqrOsc</a>, or <a
89256   *  href="/reference/#/p5.SawOsc">p5.SawOsc</a>.
89257   *  </p>
89258   *
89259   *  @class p5.Oscillator
89260   *  @constructor
89261   *  @param {Number} [freq] frequency defaults to 440Hz
89262   *  @param {String} [type] type of oscillator. Options:
89263   *                         'sine' (default), 'triangle',
89264   *                         'sawtooth', 'square'
89265   *  @example
89266   *  <div><code>
89267   *  var osc;
89268   *  var playing = false;
89269   *
89270   *  function setup() {
89271   *    backgroundColor = color(255,0,255);
89272   *    textAlign(CENTER);
89273   *
89274   *    osc = new p5.Oscillator();
89275   *    osc.setType('sine');
89276   *    osc.freq(240);
89277   *    osc.amp(0);
89278   *    osc.start();
89279   *  }
89280   *
89281   *  function draw() {
89282   *    background(backgroundColor)
89283   *    text('click to play', width/2, height/2);
89284   *  }
89285   *
89286   *  function mouseClicked() {
89287   *    if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {
89288   *      if (!playing) {
89289   *        // ramp amplitude to 0.5 over 0.05 seconds
89290   *        osc.amp(0.5, 0.05);
89291   *        playing = true;
89292   *        backgroundColor = color(0,255,255);
89293   *      } else {
89294   *        // ramp amplitude to 0 over 0.5 seconds
89295   *        osc.amp(0, 0.5);
89296   *        playing = false;
89297   *        backgroundColor = color(255,0,255);
89298   *      }
89299   *    }
89300   *  }
89301   *  </code> </div>
89302   */
89303  p5.Oscillator = function (freq, type) {
89304    if (typeof freq === 'string') {
89305      var f = type;
89306      type = freq;
89307      freq = f;
89308    }
89309    if (typeof type === 'number') {
89310      var f = type;
89311      type = freq;
89312      freq = f;
89313    }
89314    this.started = false;
89315    // components
89316    this.phaseAmount = undefined;
89317    this.oscillator = p5sound.audiocontext.createOscillator();
89318    this.f = freq || 440;
89319    // frequency
89320    this.oscillator.type = type || 'sine';
89321    this.oscillator.frequency.setValueAtTime(this.f, p5sound.audiocontext.currentTime);
89322    // connections
89323    this.output = p5sound.audiocontext.createGain();
89324    this._freqMods = [];
89325    // modulators connected to this oscillator's frequency
89326    // set default output gain to 0.5
89327    this.output.gain.value = 0.5;
89328    this.output.gain.setValueAtTime(0.5, p5sound.audiocontext.currentTime);
89329    this.oscillator.connect(this.output);
89330    // stereo panning
89331    this.panPosition = 0;
89332    this.connection = p5sound.input;
89333    // connect to p5sound by default
89334    this.panner = new p5.Panner(this.output, this.connection, 1);
89335    //array of math operation signal chaining
89336    this.mathOps = [this.output];
89337    // add to the soundArray so we can dispose of the osc later
89338    p5sound.soundArray.push(this);
89339  };
89340  /**
89341   *  Start an oscillator. Accepts an optional parameter to
89342   *  determine how long (in seconds from now) until the
89343   *  oscillator starts.
89344   *
89345   *  @method  start
89346   *  @param  {Number} [time] startTime in seconds from now.
89347   *  @param  {Number} [frequency] frequency in Hz.
89348   */
89349  p5.Oscillator.prototype.start = function (time, f) {
89350    if (this.started) {
89351      var now = p5sound.audiocontext.currentTime;
89352      this.stop(now);
89353    }
89354    if (!this.started) {
89355      var freq = f || this.f;
89356      var type = this.oscillator.type;
89357      // set old osc free to be garbage collected (memory)
89358      if (this.oscillator) {
89359        this.oscillator.disconnect();
89360        delete this.oscillator;
89361      }
89362      // var detune = this.oscillator.frequency.value;
89363      this.oscillator = p5sound.audiocontext.createOscillator();
89364      this.oscillator.frequency.value = Math.abs(freq);
89365      this.oscillator.type = type;
89366      // this.oscillator.detune.value = detune;
89367      this.oscillator.connect(this.output);
89368      time = time || 0;
89369      this.oscillator.start(time + p5sound.audiocontext.currentTime);
89370      this.freqNode = this.oscillator.frequency;
89371      // if other oscillators are already connected to this osc's freq
89372      for (var i in this._freqMods) {
89373        if (typeof this._freqMods[i].connect !== 'undefined') {
89374          this._freqMods[i].connect(this.oscillator.frequency);
89375        }
89376      }
89377      this.started = true;
89378    }
89379  };
89380  /**
89381   *  Stop an oscillator. Accepts an optional parameter
89382   *  to determine how long (in seconds from now) until the
89383   *  oscillator stops.
89384   *
89385   *  @method  stop
89386   *  @param  {Number} secondsFromNow Time, in seconds from now.
89387   */
89388  p5.Oscillator.prototype.stop = function (time) {
89389    if (this.started) {
89390      var t = time || 0;
89391      var now = p5sound.audiocontext.currentTime;
89392      this.oscillator.stop(t + now);
89393      this.started = false;
89394    }
89395  };
89396  /**
89397   *  Set the amplitude between 0 and 1.0. Or, pass in an object
89398   *  such as an oscillator to modulate amplitude with an audio signal.
89399   *
89400   *  @method  amp
89401   *  @param  {Number|Object} vol between 0 and 1.0
89402   *                              or a modulating signal/oscillator
89403   *  @param {Number} [rampTime] create a fade that lasts rampTime
89404   *  @param {Number} [timeFromNow] schedule this event to happen
89405   *                                seconds from now
89406   *  @return  {AudioParam} gain  If no value is provided,
89407   *                              returns the Web Audio API
89408   *                              AudioParam that controls
89409   *                              this oscillator's
89410   *                              gain/amplitude/volume)
89411   */
89412  p5.Oscillator.prototype.amp = function (vol, rampTime, tFromNow) {
89413    var self = this;
89414    if (typeof vol === 'number') {
89415      var rampTime = rampTime || 0;
89416      var tFromNow = tFromNow || 0;
89417      var now = p5sound.audiocontext.currentTime;
89418      this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);
89419    } else if (vol) {
89420      vol.connect(self.output.gain);
89421    } else {
89422      // return the Gain Node
89423      return this.output.gain;
89424    }
89425  };
89426  // these are now the same thing
89427  p5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp;
89428  p5.Oscillator.prototype.getAmp = function () {
89429    return this.output.gain.value;
89430  };
89431  /**
89432   *  Set frequency of an oscillator to a value. Or, pass in an object
89433   *  such as an oscillator to modulate the frequency with an audio signal.
89434   *
89435   *  @method  freq
89436   *  @param  {Number|Object} Frequency Frequency in Hz
89437   *                                        or modulating signal/oscillator
89438   *  @param  {Number} [rampTime] Ramp time (in seconds)
89439   *  @param  {Number} [timeFromNow] Schedule this event to happen
89440   *                                   at x seconds from now
89441   *  @return  {AudioParam} Frequency If no value is provided,
89442   *                                  returns the Web Audio API
89443   *                                  AudioParam that controls
89444   *                                  this oscillator's frequency
89445   *  @example
89446   *  <div><code>
89447   *  var osc = new p5.Oscillator(300);
89448   *  osc.start();
89449   *  osc.freq(40, 10);
89450   *  </code></div>
89451   */
89452  p5.Oscillator.prototype.freq = function (val, rampTime, tFromNow) {
89453    if (typeof val === 'number' && !isNaN(val)) {
89454      this.f = val;
89455      var now = p5sound.audiocontext.currentTime;
89456      var rampTime = rampTime || 0;
89457      var tFromNow = tFromNow || 0;
89458      var t = now + tFromNow + rampTime;
89459      // var currentFreq = this.oscillator.frequency.value;
89460      // this.oscillator.frequency.cancelScheduledValues(now);
89461      if (rampTime === 0) {
89462        this.oscillator.frequency.setValueAtTime(val, tFromNow + now);
89463      } else {
89464        if (val > 0) {
89465          this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now);
89466        } else {
89467          this.oscillator.frequency.linearRampToValueAtTime(val, tFromNow + rampTime + now);
89468        }
89469      }
89470      // reset phase if oscillator has a phase
89471      if (this.phaseAmount) {
89472        this.phase(this.phaseAmount);
89473      }
89474    } else if (val) {
89475      if (val.output) {
89476        val = val.output;
89477      }
89478      val.connect(this.oscillator.frequency);
89479      // keep track of what is modulating this param
89480      // so it can be re-connected if
89481      this._freqMods.push(val);
89482    } else {
89483      // return the Frequency Node
89484      return this.oscillator.frequency;
89485    }
89486  };
89487  p5.Oscillator.prototype.getFreq = function () {
89488    return this.oscillator.frequency.value;
89489  };
89490  /**
89491   *  Set type to 'sine', 'triangle', 'sawtooth' or 'square'.
89492   *
89493   *  @method  setType
89494   *  @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'.
89495   */
89496  p5.Oscillator.prototype.setType = function (type) {
89497    this.oscillator.type = type;
89498  };
89499  p5.Oscillator.prototype.getType = function () {
89500    return this.oscillator.type;
89501  };
89502  /**
89503   *  Connect to a p5.sound / Web Audio object.
89504   *
89505   *  @method  connect
89506   *  @param  {Object} unit A p5.sound or Web Audio object
89507   */
89508  p5.Oscillator.prototype.connect = function (unit) {
89509    if (!unit) {
89510      this.panner.connect(p5sound.input);
89511    } else if (unit.hasOwnProperty('input')) {
89512      this.panner.connect(unit.input);
89513      this.connection = unit.input;
89514    } else {
89515      this.panner.connect(unit);
89516      this.connection = unit;
89517    }
89518  };
89519  /**
89520   *  Disconnect all outputs
89521   *
89522   *  @method  disconnect
89523   */
89524  p5.Oscillator.prototype.disconnect = function () {
89525    if (this.output) {
89526      this.output.disconnect();
89527    }
89528    if (this.panner) {
89529      this.panner.disconnect();
89530      if (this.output) {
89531        this.output.connect(this.panner);
89532      }
89533    }
89534    this.oscMods = [];
89535  };
89536  /**
89537   *  Pan between Left (-1) and Right (1)
89538   *
89539   *  @method  pan
89540   *  @param  {Number} panning Number between -1 and 1
89541   *  @param  {Number} timeFromNow schedule this event to happen
89542   *                                seconds from now
89543   */
89544  p5.Oscillator.prototype.pan = function (pval, tFromNow) {
89545    this.panPosition = pval;
89546    this.panner.pan(pval, tFromNow);
89547  };
89548  p5.Oscillator.prototype.getPan = function () {
89549    return this.panPosition;
89550  };
89551  // get rid of the oscillator
89552  p5.Oscillator.prototype.dispose = function () {
89553    // remove reference from soundArray
89554    var index = p5sound.soundArray.indexOf(this);
89555    p5sound.soundArray.splice(index, 1);
89556    if (this.oscillator) {
89557      var now = p5sound.audiocontext.currentTime;
89558      this.stop(now);
89559      this.disconnect();
89560      this.panner = null;
89561      this.oscillator = null;
89562    }
89563    // if it is a Pulse
89564    if (this.osc2) {
89565      this.osc2.dispose();
89566    }
89567  };
89568  /**
89569   *  Set the phase of an oscillator between 0.0 and 1.0.
89570   *  In this implementation, phase is a delay time
89571   *  based on the oscillator's current frequency.
89572   *
89573   *  @method  phase
89574   *  @param  {Number} phase float between 0.0 and 1.0
89575   */
89576  p5.Oscillator.prototype.phase = function (p) {
89577    var delayAmt = p5.prototype.map(p, 0, 1, 0, 1 / this.f);
89578    var now = p5sound.audiocontext.currentTime;
89579    this.phaseAmount = p;
89580    if (!this.dNode) {
89581      // create a delay node
89582      this.dNode = p5sound.audiocontext.createDelay();
89583      // put the delay node in between output and panner
89584      this.oscillator.disconnect();
89585      this.oscillator.connect(this.dNode);
89586      this.dNode.connect(this.output);
89587    }
89588    // set delay time to match phase:
89589    this.dNode.delayTime.setValueAtTime(delayAmt, now);
89590  };
89591  // ========================== //
89592  // SIGNAL MATH FOR MODULATION //
89593  // ========================== //
89594  // return sigChain(this, scale, thisChain, nextChain, Scale);
89595  var sigChain = function (o, mathObj, thisChain, nextChain, type) {
89596    var chainSource = o.oscillator;
89597    // if this type of math already exists in the chain, replace it
89598    for (var i in o.mathOps) {
89599      if (o.mathOps[i] instanceof type) {
89600        chainSource.disconnect();
89601        o.mathOps[i].dispose();
89602        thisChain = i;
89603        // assume nextChain is output gain node unless...
89604        if (thisChain < o.mathOps.length - 2) {
89605          nextChain = o.mathOps[i + 1];
89606        }
89607      }
89608    }
89609    if (thisChain === o.mathOps.length - 1) {
89610      o.mathOps.push(nextChain);
89611    }
89612    // assume source is the oscillator unless i > 0
89613    if (i > 0) {
89614      chainSource = o.mathOps[i - 1];
89615    }
89616    chainSource.disconnect();
89617    chainSource.connect(mathObj);
89618    mathObj.connect(nextChain);
89619    o.mathOps[thisChain] = mathObj;
89620    return o;
89621  };
89622  /**
89623   *  Add a value to the p5.Oscillator's output amplitude,
89624   *  and return the oscillator. Calling this method again
89625   *  will override the initial add() with a new value.
89626   *
89627   *  @method  add
89628   *  @param {Number} number Constant number to add
89629   *  @return {p5.Oscillator} Oscillator Returns this oscillator
89630   *                                     with scaled output
89631   *
89632   */
89633  p5.Oscillator.prototype.add = function (num) {
89634    var add = new Add(num);
89635    var thisChain = this.mathOps.length - 1;
89636    var nextChain = this.output;
89637    return sigChain(this, add, thisChain, nextChain, Add);
89638  };
89639  /**
89640   *  Multiply the p5.Oscillator's output amplitude
89641   *  by a fixed value (i.e. turn it up!). Calling this method
89642   *  again will override the initial mult() with a new value.
89643   *
89644   *  @method  mult
89645   *  @param {Number}
89645 number Constant number to multiply
89646   *  @return {p5.Oscillator} Oscillator Returns this oscillator
89647   *                                     with multiplied output
89648   */
89649  p5.Oscillator.prototype.mult = function (num) {
89650    var mult = new Mult(num);
89651    var thisChain = this.mathOps.length - 1;
89652    var nextChain = this.output;
89653    return sigChain(this, mult, thisChain, nextChain, Mult);
89654  };
89655  /**
89656   *  Scale this oscillator's amplitude values to a given
89657   *  range, and return the oscillator. Calling this method
89658   *  again will override the initial scale() with new values.
89659   *
89660   *  @method  scale
89661   *  @param  {Number} inMin  input range minumum
89662   *  @param  {Number} inMax  input range maximum
89663   *  @param  {Number} outMin input range minumum
89664   *  @param  {Number} outMax input range maximum
89665   *  @return {p5.Oscillator} Oscillator Returns this oscillator
89666   *                                     with scaled output
89667   */
89668  p5.Oscillator.prototype.scale = function (inMin, inMax, outMin, outMax) {
89669    var mapOutMin, mapOutMax;
89670    if (arguments.length === 4) {
89671      mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5;
89672      mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5;
89673    } else {
89674      mapOutMin = arguments[0];
89675      mapOutMax = arguments[1];
89676    }
89677    var scale = new Scale(mapOutMin, mapOutMax);
89678    var thisChain = this.mathOps.length - 1;
89679    var nextChain = this.output;
89680    return sigChain(this, scale, thisChain, nextChain, Scale);
89681  };
89682  // ============================== //
89683  // SinOsc, TriOsc, SqrOsc, SawOsc //
89684  // ============================== //
89685  /**
89686   *  Constructor: <code>new p5.SinOsc()</code>.
89687   *  This creates a Sine Wave Oscillator and is
89688   *  equivalent to <code> new p5.Oscillator('sine')
89689   *  </code> or creating a p5.Oscillator and then calling
89690   *  its method <code>setType('sine')</code>.
89691   *  See p5.Oscillator for methods.
89692   *
89693   *  @class  p5.SinOsc
89694   *  @constructor
89695   *  @extends p5.Oscillator
89696   *  @param {Number} [freq] Set the frequency
89697   */
89698  p5.SinOsc = function (freq) {
89699    p5.Oscillator.call(this, freq, 'sine');
89700  };
89701  p5.SinOsc.prototype = Object.create(p5.Oscillator.prototype);
89702  /**
89703   *  Constructor: <code>new p5.TriOsc()</code>.
89704   *  This creates a Triangle Wave Oscillator and is
89705   *  equivalent to <code>new p5.Oscillator('triangle')
89706   *  </code> or creating a p5.Oscillator and then calling
89707   *  its method <code>setType('triangle')</code>.
89708   *  See p5.Oscillator for methods.
89709   *
89710   *  @class  p5.TriOsc
89711   *  @constructor
89712   *  @extends p5.Oscillator
89713   *  @param {Number} [freq] Set the frequency
89714   */
89715  p5.TriOsc = function (freq) {
89716    p5.Oscillator.call(this, freq, 'triangle');
89717  };
89718  p5.TriOsc.prototype = Object.create(p5.Oscillator.prototype);
89719  /**
89720   *  Constructor: <code>new p5.SawOsc()</code>.
89721   *  This creates a SawTooth Wave Oscillator and is
89722   *  equivalent to <code> new p5.Oscillator('sawtooth')
89723   *  </code> or creating a p5.Oscillator and then calling
89724   *  its method <code>setType('sawtooth')</code>.
89725   *  See p5.Oscillator for methods.
89726   *
89727   *  @class  p5.SawOsc
89728   *  @constructor
89729   *  @extends p5.Oscillator
89730   *  @param {Number} [freq] Set the frequency
89731   */
89732  p5.SawOsc = function (freq) {
89733    p5.Oscillator.call(this, freq, 'sawtooth');
89734  };
89735  p5.SawOsc.prototype = Object.create(p5.Oscillator.prototype);
89736  /**
89737   *  Constructor: <code>new p5.SqrOsc()</code>.
89738   *  This creates a Square Wave Oscillator and is
89739   *  equivalent to <code> new p5.Oscillator('square')
89740   *  </code> or creating a p5.Oscillator and then calling
89741   *  its method <code>setType('square')</code>.
89742   *  See p5.Oscillator for methods.
89743   *
89744   *  @class  p5.SqrOsc
89745   *  @constructor
89746   *  @extends p5.Oscillator
89747   *  @param {Number} [freq] Set the frequency
89748   */
89749  p5.SqrOsc = function (freq) {
89750    p5.Oscillator.call(this, freq, 'square');
89751  };
89752  p5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype);
89753}(master, Tone_signal_Add, Tone_signal_Multiply, Tone_signal_Scale);
89754/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
89755var Tone_core_Timeline;
89756Tone_core_Timeline = function (Tone) {
89757  'use strict';
89758  Tone.Timeline = function () {
89759    var options = this.optionsObject(arguments, ['memory'], Tone.Timeline.defaults);
89760    this._timeline = [];
89761    this._toRemove = [];
89762    this._iterating = false;
89763    this.memory = options.memory;
89764  };
89765  Tone.extend(Tone.Timeline);
89766  Tone.Timeline.defaults = { 'memory': Infinity };
89767  Object.defineProperty(Tone.Timeline.prototype, 'length', {
89768    get: function () {
89769      return this._timeline.length;
89770    }
89771  });
89772  Tone.Timeline.prototype.add = function (event) {
89773    if (this.isUndef(event.time)) {
89774      throw new Error('Tone.Timeline: events must have a time attribute');
89775    }
89776    if (this._timeline.length) {
89777      var index = this._search(event.time);
89778      this._timeline.splice(index + 1, 0, event);
89779    } else {
89780      this._timeline.push(event);
89781    }
89782    if (this.length > this.memory) {
89783      var diff = this.length - this.memory;
89784      this._timeline.splice(0, diff);
89785    }
89786    return this;
89787  };
89788  Tone.Timeline.prototype.remove = function (event) {
89789    if (this._iterating) {
89790      this._toRemove.push(event);
89791    } else {
89792      var index = this._timeline.indexOf(event);
89793      if (index !== -1) {
89794        this._timeline.splice(index, 1);
89795      }
89796    }
89797    return this;
89798  };
89799  Tone.Timeline.prototype.get = function (time) {
89800    var index = this._search(time);
89801    if (index !== -1) {
89802      return this._timeline[index];
89803    } else {
89804      return null;
89805    }
89806  };
89807  Tone.Timeline.prototype.peek = function () {
89808    return this._timeline[0];
89809  };
89810  Tone.Timeline.prototype.shift = function () {
89811    return this._timeline.shift();
89812  };
89813  Tone.Timeline.prototype.getAfter = function (time) {
89814    var index = this._search(time);
89815    if (index + 1 < this._timeline.length) {
89816      return this._timeline[index + 1];
89817    } else {
89818      return null;
89819    }
89820  };
89821  Tone.Timeline.prototype.getBefore = function (time) {
89822    var len = this._timeline.length;
89823    if (len > 0 && this._timeline[len - 1].time < time) {
89824      return this._timeline[len - 1];
89825    }
89826    var index = this._search(time);
89827    if (index - 1 >= 0) {
89828      return this._timeline[index - 1];
89829    } else {
89830      return null;
89831    }
89832  };
89833  Tone.Timeline.prototype.cancel = function (after) {
89834    if (this._timeline.length > 1) {
89835      var index = this._search(after);
89836      if (index >= 0) {
89837        if (this._timeline[index].time === after) {
89838          for (var i = index; i >= 0; i--) {
89839            if (this._timeline[i].time === after) {
89840              index = i;
89841            } else {
89842              break;
89843            }
89844          }
89845          this._timeline = this._timeline.slice(0, index);
89846        } else {
89847          this._timeline = this._timeline.slice(0, index + 1);
89848        }
89849      } else {
89850        this._timeline = [];
89851      }
89852    } else if (this._timeline.length === 1) {
89853      if (this._timeline[0].time >= after) {
89854        this._timeline = [];
89855      }
89856    }
89857    return this;
89858  };
89859  Tone.Timeline.prototype.cancelBefore = function (time) {
89860    if (this._timeline.length) {
89861      var index = this._search(time);
89862      if (index >= 0) {
89863        this._timeline = this._timeline.slice(index + 1);
89864      }
89865    }
89866    return this;
89867  };
89868  Tone.Timeline.prototype._search = function (time) {
89869    var beginning = 0;
89870    var len = this._timeline.length;
89871    var end = len;
89872    if (len > 0 && this._timeline[len - 1].time <= time) {
89873      return len - 1;
89874    }
89875    while (beginning < end) {
89876      var midPoint = Math.floor(beginning + (end - beginning) / 2);
89877      var event = this._timeline[midPoint];
89878      var nextEvent = this._timeline[midPoint + 1];
89879      if (event.time === time) {
89880        for (var i = midPoint; i < this._timeline.length; i++) {
89881          var testEvent = this._timeline[i];
89882          if (testEvent.time === time) {
89883            midPoint = i;
89884          }
89885        }
89886        return midPoint;
89887      } else if (event.time < time && nextEvent.time > time) {
89888        return midPoint;
89889      } else if (event.time > time) {
89890        end = midPoint;
89891      } else if (event.time < time) {
89892        beginning = midPoint + 1;
89893      }
89894    }
89895    return -1;
89896  };
89897  Tone.Timeline.prototype._iterate = function (callback, lowerBound, upperBound) {
89898    this._iterating = true;
89899    lowerBound = this.defaultArg(lowerBound, 0);
89900    upperBound = this.defaultArg(upperBound, this._timeline.length - 1);
89901    for (var i = lowerBound; i <= upperBound; i++) {
89902      callback(this._timeline[i]);
89903    }
89904    this._iterating = false;
89905    if (this._toRemove.length > 0) {
89906      for (var j = 0; j < this._toRemove.length; j++) {
89907        var index = this._timeline.indexOf(this._toRemove[j]);
89908        if (index !== -1) {
89909          this._timeline.splice(index, 1);
89910        }
89911      }
89912      this._toRemove = [];
89913    }
89914  };
89915  Tone.Timeline.prototype.forEach = function (callback) {
89916    this._iterate(callback);
89917    return this;
89918  };
89919  Tone.Timeline.prototype.forEachBefore = function (time, callback) {
89920    var upperBound = this._search(time);
89921    if (upperBound !== -1) {
89922      this._iterate(callback, 0, upperBound);
89923    }
89924    return this;
89925  };
89926  Tone.Timeline.prototype.forEachAfter = function (time, callback) {
89927    var lowerBound = this._search(time);
89928    this._iterate(callback, lowerBound + 1);
89929    return this;
89930  };
89931  Tone.Timeline.prototype.forEachFrom = function (time, callback) {
89932    var lowerBound = this._search(time);
89933    while (lowerBound >= 0 && this._timeline[lowerBound].time >= time) {
89934      lowerBound--;
89935    }
89936    this._iterate(callback, lowerBound + 1);
89937    return this;
89938  };
89939  Tone.Timeline.prototype.forEachAtTime = function (time, callback) {
89940    var upperBound = this._search(time);
89941    if (upperBound !== -1) {
89942      this._iterate(function (event) {
89943        if (event.time === time) {
89944          callback(event);
89945        }
89946      }, 0, upperBound);
89947    }
89948    return this;
89949  };
89950  Tone.Timeline.prototype.dispose = function () {
89951    Tone.prototype.dispose.call(this);
89952    this._timeline = null;
89953    this._toRemove = null;
89954  };
89955  return Tone.Timeline;
89956}(Tone_core_Tone);
89957/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
89958var Tone_signal_TimelineSignal;
89959Tone_signal_TimelineSignal = function (Tone) {
89960  'use strict';
89961  Tone.TimelineSignal = function () {
89962    var options = this.optionsObject(arguments, [
89963      'value',
89964      'units'
89965    ], Tone.Signal.defaults);
89966    this._events = new Tone.Timeline(10);
89967    Tone.Signal.apply(this, options);
89968    options.param = this._param;
89969    Tone.Param.call(this, options);
89970    this._initial = this._fromUnits(this._param.value);
89971  };
89972  Tone.extend(Tone.TimelineSignal, Tone.Param);
89973  Tone.TimelineSignal.Type = {
89974    Linear: 'linear',
89975    Exponential: 'exponential',
89976    Target: 'target',
89977    Curve: 'curve',
89978    Set: 'set'
89979  };
89980  Object.defineProperty(Tone.TimelineSignal.prototype, 'value', {
89981    get: function () {
89982      var now = this.now();
89983      var val = this.getValueAtTime(now);
89984      return this._toUnits(val);
89985    },
89986    set: function (value) {
89987      var convertedVal = this._fromUnits(value);
89988      this._initial = convertedVal;
89989      this.cancelScheduledValues();
89990      this._param.value = convertedVal;
89991    }
89992  });
89993  Tone.TimelineSignal.prototype.setValueAtTime = function (value, startTime) {
89994    value = this._fromUnits(value);
89995    startTime = this.toSeconds(startTime);
89996    this._events.add({
89997      'type': Tone.TimelineSignal.Type.Set,
89998      'value': value,
89999      'time': startTime
90000    });
90001    this._param.setValueAtTime(value, startTime);
90002    return this;
90003  };
90004  Tone.TimelineSignal.prototype.linearRampToValueAtTime = function (value, endTime) {
90005    value = this._fromUnits(value);
90006    endTime = this.toSeconds(endTime);
90007    this._events.add({
90008      'type': Tone.TimelineSignal.Type.Linear,
90009      'value': value,
90010      'time': endTime
90011    });
90012    this._param.linearRampToValueAtTime(value, endTime);
90013    return this;
90014  };
90015  Tone.TimelineSignal.prototype.exponentialRampToValueAtTime = function (value, endTime) {
90016    endTime = this.toSeconds(endTime);
90017    var beforeEvent = this._searchBefore(endTime);
90018    if (beforeEvent && beforeEvent.value === 0) {
90019      this.setValueAtTime(this._minOutput, beforeEvent.time);
90020    }
90021    value = this._fromUnits(value);
90022    var setValue = Math.max(value, this._minOutput);
90023    this._events.add({
90024      'type': Tone.TimelineSignal.Type.Exponential,
90025      'value': setValue,
90026      'time': endTime
90027    });
90028    if (value < this._minOutput) {
90029      this._param.exponentialRampToValueAtTime(this._minOutput, endTime - this.sampleTime);
90030      this.setValueAtTime(0, endTime);
90031    } else {
90032      this._param.exponentialRampToValueAtTime(value, endTime);
90033    }
90034    return this;
90035  };
90036  Tone.TimelineSignal.prototype.setTargetAtTime = function (value, startTime, timeConstant) {
90037    value = this._fromUnits(value);
90038    value = Math.max(this._minOutput, value);
90039    timeConstant = Math.max(this._minOutput, timeConstant);
90040    startTime = this.toSeconds(startTime);
90041    this._events.add({
90042      'type': Tone.TimelineSignal.Type.Target,
90043      'value': value,
90044      'time': startTime,
90045      'constant': timeConstant
90046    });
90047    this._param.setTargetAtTime(value, startTime, timeConstant);
90048    return this;
90049  };
90050  Tone.TimelineSignal.prototype.setValueCurveAtTime = function (values, startTime, duration, scaling) {
90051    scaling = this.defaultArg(scaling, 1);
90052    var floats = new Array(values.length);
90053    for (var i = 0; i < floats.length; i++) {
90054      floats[i] = this._fromUnits(values[i]) * scaling;
90055    }
90056    startTime = this.toSeconds(startTime);
90057    duration = this.toSeconds(duration);
90058    this._events.add({
90059      'type': Tone.TimelineSignal.Type.Curve,
90060      'value': floats,
90061      'time': startTime,
90062      'duration': duration
90063    });
90064    this._param.setValueAtTime(floats[0], startTime);
90065    for (var j = 1; j < floats.length; j++) {
90066      var segmentTime = startTime + j / (floats.length - 1) * duration;
90067      this._param.linearRampToValueAtTime(floats[j], segmentTime);
90068    }
90069    return this;
90070  };
90071  Tone.TimelineSignal.prototype.cancelScheduledValues = function (after) {
90072    after = this.toSeconds(after);
90073    this._events.cancel(after);
90074    this._param.cancelScheduledValues(after);
90075    return this;
90076  };
90077  Tone.TimelineSignal.prototype.setRampPoint = function (time) {
90078    time = this.toSeconds(time);
90079    var val = this._toUnits(this.getValueAtTime(time));
90080    var before = this._searchBefore(time);
90081    if (before && before.time === time) {
90082      this.cancelScheduledValues(time + this.sampleTime);
90083    } else if (before && before.type === Tone.TimelineSignal.Type.Curve && before.time + before.duration > time) {
90084      this.cancelScheduledValues(time);
90085      this.linearRampToValueAtTime(val, time);
90086    } else {
90087      var after = this._searchAfter(time);
90088      if (after) {
90089        this.cancelScheduledValues(time);
90090        if (after.type === Tone.TimelineSignal.Type.Linear) {
90091          this.linearRampToValueAtTime(val, time);
90092        } else if (after.type === Tone.TimelineSignal.Type.Exponential) {
90093          this.exponentialRampToValueAtTime(val, time);
90094        }
90095      }
90096      this.setValueAtTime(val, time);
90097    }
90098    return this;
90099  };
90100  Tone.TimelineSignal.prototype.linearRampToValueBetween = function (value, start, finish) {
90101    this.setRampPoint(start);
90102    this.linearRampToValueAtTime(value, finish);
90103    return this;
90104  };
90105  Tone.TimelineSignal.prototype.exponentialRampToValueBetween = function (value, start, finish) {
90106    this.setRampPoint(start);
90107    this.exponentialRampToValueAtTime(value, finish);
90108    return this;
90109  };
90110  Tone.TimelineSignal.prototype._searchBefore = function (time) {
90111    return this._events.get(time);
90112  };
90113  Tone.TimelineSignal.prototype._searchAfter = function (time) {
90114    return this._events.getAfter(time);
90115  };
90116  Tone.TimelineSignal.prototype.getValueAtTime = function (time) {
90117    time = this.toSeconds(time);
90118    var after = this._searchAfter(time);
90119    var before = this._searchBefore(time);
90120    var value = this._initial;
90121    if (before === null) {
90122      value = this._initial;
90123    } else if (before.type === Tone.TimelineSignal.Type.Target) {
90124      var previous = this._events.getBefore(before.time);
90125      var previouVal;
90126      if (previous === null) {
90127        previouVal = this._initial;
90128      } else {
90129        previouVal = previous.value;
90130      }
90131      value = this._exponentialApproach(before.time, previouVal, before.value, before.constant, time);
90132    } else if (before.type === Tone.TimelineSignal.Type.Curve) {
90133      value = this._curveInterpolate(before.time, before.value, before.duration, time);
90134    } else if (after === null) {
90135      value = before.value;
90136    } else if (after.type === Tone.TimelineSignal.Type.Linear) {
90137      value = this._linearInterpolate(before.time, before.value, after.time, after.value, time);
90138    } else if (after.type === Tone.TimelineSignal.Type.Exponential) {
90139      value = this._exponentialInterpolate(before.time, before.value, after.time, after.value, time);
90140    } else {
90141      value = before.value;
90142    }
90143    return value;
90144  };
90145  Tone.TimelineSignal.prototype.connect = Tone.SignalBase.prototype.connect;
90146  Tone.TimelineSignal.prototype._exponentialApproach = function (t0, v0, v1, timeConstant, t) {
90147    return v1 + (v0 - v1) * Math.exp(-(t - t0) / timeConstant);
90148  };
90149  Tone.TimelineSignal.prototype._linearInterpolate = function (t0, v0, t1, v1, t) {
90150    return v0 + (v1 - v0) * ((t - t0) / (t1 - t0));
90151  };
90152  Tone.TimelineSignal.prototype._exponentialInterpolate = function (t0, v0, t1, v1, t) {
90153    v0 = Math.max(this._minOutput, v0);
90154    return v0 * Math.pow(v1 / v0, (t - t0) / (t1 - t0));
90155  };
90156  Tone.TimelineSignal.prototype._curveInterpolate = function (start, curve, duration, time) {
90157    var len = curve.length;
90158    if (time >= start + duration) {
90159      return curve[len - 1];
90160    } else if (time <= start) {
90161      return curve[0];
90162    } else {
90163      var progress = (time - start) / duration;
90164      var lowerIndex = Math.floor((len - 1) * progress);
90165      var upperIndex = Math.ceil((len - 1) * progress);
90166      var lowerVal = curve[lowerIndex];
90167      var upperVal = curve[upperIndex];
90168      if (upperIndex === lowerIndex) {
90169        return lowerVal;
90170      } else {
90171        return this._linearInterpolate(lowerIndex, lowerVal, upperIndex, upperVal, progress * (len - 1));
90172      }
90173    }
90174  };
90175  Tone.TimelineSignal.prototype.dispose = function () {
90176    Tone.Signal.prototype.dispose.call(this);
90177    Tone.Param.prototype.dispose.call(this);
90178    this._events.dispose();
90179    this._events = null;
90180  };
90181  return Tone.TimelineSignal;
90182}(Tone_core_Tone, Tone_signal_Signal);
90183var envelope;
90184'use strict';
90185envelope = function () {
90186  var p5sound = master;
90187  var Add = Tone_signal_Add;
90188  var Mult = Tone_signal_Multiply;
90189  var Scale = Tone_signal_Scale;
90190  var TimelineSignal = Tone_signal_TimelineSignal;
90191  var Tone = Tone_core_Tone;
90192  Tone.setContext(p5sound.audiocontext);
90193  /**
90194   *  <p>Envelopes are pre-defined amplitude distribution over time.
90195   *  Typically, envelopes are used to control the output volume
90196   *  of an object, a series of fades referred to as Attack, Decay,
90197   *  Sustain and Release (
90198   *  <a href="https://upload.wikimedia.org/wikipedia/commons/e/ea/ADSR_parameter.svg">ADSR</a>
90199   *  ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can
90200   *  control an Oscillator's frequency like this: <code>osc.freq(env)</code>.</p>
90201   *  <p>Use <code><a href="#/p5.Envelope/setRange">setRange</a></code> to change the attack/release level.
90202   *  Use <code><a href="#/p5.Envelope/setADSR">setADSR</a></code> to change attackTime, decayTime, sustainPercent and releaseTime.</p>
90203   *  <p>Use the <code><a href="#/p5.Envelope/play">play</a></code> method to play the entire envelope,
90204   *  the <code><a href="#/p5.Envelope/ramp">ramp</a></code> method for a pingable trigger,
90205   *  or <code><a href="#/p5.Envelope/triggerAttack">triggerAttack</a></code>/
90206   *  <code><a href="#/p5.Envelope/triggerRelease">triggerRelease</a></code> to trigger noteOn/noteOff.</p>
90207   *
90208   *  @class p5.Envelope
90209   *  @constructor
90210   *  @example
90211   *  <div><code>
90212   *  var attackLevel = 1.0;
90213   *  var releaseLevel = 0;
90214   *
90215   *  var attackTime = 0.001;
90216   *  var decayTime = 0.2;
90217   *  var susPercent = 0.2;
90218   *  var releaseTime = 0.5;
90219   *
90220   *  var env, triOsc;
90221   *
90222   *  function setup() {
90223   *    var cnv = createCanvas(100, 100);
90224   *
90225   *    textAlign(CENTER);
90226   *    text('click to play', width/2, height/2);
90227   *
90228   *    env = new p5.Envelope();
90229   *    env.setADSR(attackTime, decayTime, susPercent, releaseTime);
90230   *    env.setRange(attackLevel, releaseLevel);
90231   *
90232   *    triOsc = new p5.Oscillator('triangle');
90233   *    triOsc.amp(env);
90234   *    triOsc.start();
90235   *    triOsc.freq(220);
90236   *
90237   *    cnv.mousePressed(playEnv);
90238   *  }
90239   *
90240   *  function playEnv()  {
90241   *    env.play();
90242   *  }
90243   *  </code></div>
90244   */
90245  p5.Envelope = function (t1, l1, t2, l2, t3, l3) {
90246    /**
90247     * Time until envelope reaches attackLevel
90248     * @property attackTime
90249     */
90250    this.aTime = t1 || 0.1;
90251    /**
90252     * Level once attack is complete.
90253     * @property attackLevel
90254     */
90255    this.aLevel = l1 || 1;
90256    /**
90257     * Time until envelope reaches decayLevel.
90258     * @property decayTime
90259     */
90260    this.dTime = t2 || 0.5;
90261    /**
90262     * Level after decay. The envelope will sustain here until it is released.
90263     * @property decayLevel
90264     */
90265    this.dLevel = l2 || 0;
90266    /**
90267     * Duration of the release portion of the envelope.
90268     * @property releaseTime
90269     */
90270    this.rTime = t3 || 0;
90271    /**
90272     * Level at the end of the release.
90273     * @property releaseLevel
90274     */
90275    this.rLevel = l3 || 0;
90276    this._rampHighPercentage = 0.98;
90277    this._rampLowPercentage = 0.02;
90278    this.output = p5sound.audiocontext.createGain();
90279    this.control = new TimelineSignal();
90280    this._init();
90281    // this makes sure the envelope starts at zero
90282    this.control.connect(this.output);
90283    // connect to the output
90284    this.connection = null;
90285    // store connection
90286    //array of math operation signal chaining
90287    this.mathOps = [this.control];
90288    //whether envelope should be linear or exponential curve
90289    this.isExponential = false;
90290    // oscillator or buffer source to clear on env complete
90291    // to save resources if/when it is retriggered
90292    this.sourceToClear = null;
90293    // set to true if attack is set, then false on release
90294    this.wasTriggered = false;
90295    // add to the soundArray so we can dispose of the env later
90296    p5sound.soundArray.push(this);
90297  };
90298  // this init function just smooths the starting value to zero and gives a start point for the timeline
90299  // - it was necessary to remove glitches at the beginning.
90300  p5.Envelope.prototype._init = function () {
90301    var now = p5sound.audiocontext.currentTime;
90302    var t = now;
90303    this.control.setTargetAtTime(0.00001, t, 0.001);
90304    //also, compute the correct time constants
90305    this._setRampAD(this.aTime, this.dTime);
90306  };
90307  /**
90308   *  Reset the envelope with a series of time/value pairs.
90309   *
90310   *  @method  set
90311   *  @param {Number} attackTime     Time (in seconds) before level
90312   *                                 reaches attackLevel
90313   *  @param {Number} attackLevel    Typically an amplitude between
90314   *                                 0.0 and 1.0
90315   *  @param {Number} decayTime      Time
90316   *  @param {Number} decayLevel   Amplitude (In a standard ADSR envelope,
90317   *                                 decayLevel = sustainLevel)
90318   *  @param {Number} releaseTime   Release Time (in seconds)
90319   *  @param {Number} releaseLevel  Amplitude
90320   *  @example
90321   *  <div><code>
90322   *  var t1 = 0.1;
90322 // attack time in seconds
90323   *  var l1 = 0.7; // attack level 0.0 to 1.0
90324   *  var t2 = 0.3; // decay time in seconds
90325   *  var l2 = 0.1; // decay level  0.0 to 1.0
90326   *  var t3 = 0.2; // sustain time in seconds
90327   *  var l3 = 0.5; // sustain level  0.0 to 1.0
90328   *  // release level defaults to zero
90329   *
90330   *  var env;
90331   *  var triOsc;
90332   *
90333   *  function setup() {
90334   *    background(0);
90335   *    noStroke();
90336   *    fill(255);
90337   *    textAlign(CENTER);
90338   *    text('click to play', width/2, height/2);
90339   *
90340   *    env = new p5.Envelope(t1, l1, t2, l2, t3, l3);
90341   *    triOsc = new p5.Oscillator('triangle');
90342   *    triOsc.amp(env); // give the env control of the triOsc's amp
90343   *    triOsc.start();
90344   *  }
90345   *
90346   *  // mouseClick triggers envelope if over canvas
90347   *  function mouseClicked() {
90348   *    // is mouse over canvas?
90349   *    if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
90350   *      env.play(triOsc);
90351   *    }
90352   *  }
90353   *  </code></div>
90354   *
90355   */
90356  p5.Envelope.prototype.set = function (t1, l1, t2, l2, t3, l3) {
90357    this.aTime = t1;
90358    this.aLevel = l1;
90359    this.dTime = t2 || 0;
90360    this.dLevel = l2 || 0;
90361    this.rTime = t3 || 0;
90362    this.rLevel = l3 || 0;
90363    // set time constants for ramp
90364    this._setRampAD(t1, t2);
90365  };
90366  /**
90367   *  Set values like a traditional
90368   *  <a href="https://en.wikipedia.org/wiki/Synthesizer#/media/File:ADSR_parameter.svg">
90369   *  ADSR envelope
90370   *  </a>.
90371   *
90372   *  @method  setADSR
90373   *  @param {Number} attackTime    Time (in seconds before envelope
90374   *                                reaches Attack Level
90375   *  @param {Number} [decayTime]    Time (in seconds) before envelope
90376   *                                reaches Decay/Sustain Level
90377   *  @param {Number} [susRatio]    Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,
90378   *                                where 1.0 = attackLevel, 0.0 = releaseLevel.
90379   *                                The susRatio determines the decayLevel and the level at which the
90380   *                                sustain portion of the envelope will sustain.
90381   *                                For example, if attackLevel is 0.4, releaseLevel is 0,
90382   *                                and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is
90383   *                                increased to 1.0 (using <code>setRange</code>),
90384   *                                then decayLevel would increase proportionally, to become 0.5.
90385   *  @param {Number} [releaseTime]   Time in seconds from now (defaults to 0)
90386   *  @example
90387   *  <div><code>
90388   *  var attackLevel = 1.0;
90389   *  var releaseLevel = 0;
90390   *
90391   *  var attackTime = 0.001;
90392   *  var decayTime = 0.2;
90393   *  var susPercent = 0.2;
90394   *  var releaseTime = 0.5;
90395   *
90396   *  var env, triOsc;
90397   *
90398   *  function setup() {
90399   *    var cnv = createCanvas(100, 100);
90400   *
90401   *    textAlign(CENTER);
90402   *    text('click to play', width/2, height/2);
90403   *
90404   *    env = new p5.Envelope();
90405   *    env.setADSR(attackTime, decayTime, susPercent, releaseTime);
90406   *    env.setRange(attackLevel, releaseLevel);
90407   *
90408   *    triOsc = new p5.Oscillator('triangle');
90409   *    triOsc.amp(env);
90410   *    triOsc.start();
90411   *    triOsc.freq(220);
90412   *
90413   *    cnv.mousePressed(playEnv);
90414   *  }
90415   *
90416   *  function playEnv()  {
90417   *    env.play();
90418   *  }
90419   *  </code></div>
90420   */
90421  p5.Envelope.prototype.setADSR = function (aTime, dTime, sPercent, rTime) {
90422    this.aTime = aTime;
90423    this.dTime = dTime || 0;
90424    // lerp
90425    this.sPercent = sPercent || 0;
90426    this.dLevel = typeof sPercent !== 'undefined' ? sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0;
90427    this.rTime = rTime || 0;
90428    // also set time constants for ramp
90429    this._setRampAD(aTime, dTime);
90430  };
90431  /**
90432   *  Set max (attackLevel) and min (releaseLevel) of envelope.
90433   *
90434   *  @method  setRange
90435   *  @param {Number} aLevel attack level (defaults to 1)
90436   *  @param {Number} rLevel release level (defaults to 0)
90437   *  @example
90438   *  <div><code>
90439   *  var attackLevel = 1.0;
90440   *  var releaseLevel = 0;
90441   *
90442   *  var attackTime = 0.001;
90443   *  var decayTime = 0.2;
90444   *  var susPercent = 0.2;
90445   *  var releaseTime = 0.5;
90446   *
90447   *  var env, triOsc;
90448   *
90449   *  function setup() {
90450   *    var cnv = createCanvas(100, 100);
90451   *
90452   *    textAlign(CENTER);
90453   *    text('click to play', width/2, height/2);
90454   *
90455   *    env = new p5.Envelope();
90456   *    env.setADSR(attackTime, decayTime, susPercent, releaseTime);
90457   *    env.setRange(attackLevel, releaseLevel);
90458   *
90459   *    triOsc = new p5.Oscillator('triangle');
90460   *    triOsc.amp(env);
90461   *    triOsc.start();
90462   *    triOsc.freq(220);
90463   *
90464   *    cnv.mousePressed(playEnv);
90465   *  }
90466   *
90467   *  function playEnv()  {
90468   *    env.play();
90469   *  }
90470   *  </code></div>
90471   */
90472  p5.Envelope.prototype.setRange = function (aLevel, rLevel) {
90473    this.aLevel = aLevel || 1;
90474    this.rLevel = rLevel || 0;
90475  };
90476  //  private (undocumented) method called when ADSR is set to set time constants for ramp
90477  //
90478  //  Set the <a href="https://en.wikipedia.org/wiki/RC_time_constant">
90479  //  time constants</a> for simple exponential ramps.
90480  //  The larger the time constant value, the slower the
90481  //  transition will be.
90482  //
90483  //  method  _setRampAD
90484  //  param {Number}
90484 attackTimeConstant  attack time constant
90485  //  param {Number} decayTimeConstant   decay time constant
90486  //
90487  p5.Envelope.prototype._setRampAD = function (t1, t2) {
90488    this._rampAttackTime = this.checkExpInput(t1);
90489    this._rampDecayTime = this.checkExpInput(t2);
90490    var TCDenominator = 1;
90491    /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)
90492    TCDenominator = Math.log(1 / this.checkExpInput(1 - this._rampHighPercentage));
90493    this._rampAttackTC = t1 / this.checkExpInput(TCDenominator);
90494    TCDenominator = Math.log(1 / this._rampLowPercentage);
90495    this._rampDecayTC = t2 / this.checkExpInput(TCDenominator);
90496  };
90497  // private method
90498  p5.Envelope.prototype.setRampPercentages = function (p1, p2) {
90499    //set the percentages that the simple exponential ramps go to
90500    this._rampHighPercentage = this.checkExpInput(p1);
90501    this._rampLowPercentage = this.checkExpInput(p2);
90502    var TCDenominator = 1;
90503    //now re-compute the time constants based on those percentages
90504    /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage)
90505    TCDenominator = Math.log(1 / this.checkExpInput(1 - this._rampHighPercentage));
90506    this._rampAttackTC = this._rampAttackTime / this.checkExpInput(TCDenominator);
90507    TCDenominator = Math.log(1 / this._rampLowPercentage);
90508    this._rampDecayTC = this._rampDecayTime / this.checkExpInput(TCDenominator);
90509  };
90510  /**
90511   *  Assign a parameter to be controlled by this envelope.
90512   *  If a p5.Sound object is given, then the p5.Envelope will control its
90513   *  output gain. If multiple inputs are provided, the env will
90514   *  control all of them.
90515   *
90516   *  @method  setInput
90517   *  @param  {Object} [...inputs]         A p5.sound object or
90518   *                                Web Audio Param.
90519   */
90520  p5.Envelope.prototype.setInput = function () {
90521    for (var i = 0; i < arguments.length; i++) {
90522      this.connect(arguments[i]);
90523    }
90524  };
90525  /**
90526   *  Set whether the envelope ramp is linear (default) or exponential.
90527   *  Exponential ramps can be useful because we perceive amplitude
90528   *  and frequency logarithmically.
90529   *
90530   *  @method  setExp
90531   *  @param {Boolean} isExp true is exponential, false is linear
90532   */
90533  p5.Envelope.prototype.setExp = function (isExp) {
90534    this.isExponential = isExp;
90535  };
90536  //helper method to protect against zero values being sent to exponential functions
90537  p5.Envelope.prototype.checkExpInput = function (value) {
90538    if (value <= 0) {
90539      value = 1e-8;
90540    }
90541    return value;
90542  };
90543  /**
90544   *  Play tells the envelope to start acting on a given input.
90545   *  If the input is a p5.sound object (i.e. AudioIn, Oscillator,
90546   *  SoundFile), then Envelope will control its output volume.
90547   *  Envelopes can also be used to control any <a href="
90548   *  http://docs.webplatform.org/wiki/apis/webaudio/AudioParam">
90549   *  Web Audio Audio Param.</a>
90550   *
90551   *  @method  play
90552   *  @param  {Object} unit         A p5.sound object or
90553   *                                Web Audio Param.
90554   *  @param  {Number} [startTime]  time from now (in seconds) at which to play
90555   *  @param  {Number} [sustainTime] time to sustain before releasing the envelope
90556   *  @example
90557   *  <div><code>
90558   *  var attackLevel = 1.0;
90559   *  var releaseLevel = 0;
90560   *
90561   *  var attackTime = 0.001;
90562   *  var decayTime = 0.2;
90563   *  var susPercent = 0.2;
90564   *  var releaseTime = 0.5;
90565   *
90566   *  var env, triOsc;
90567   *
90568   *  function setup() {
90569   *    var cnv = createCanvas(100, 100);
90570   *
90571   *    textAlign(CENTER);
90572   *    text('click to play', width/2, height/2);
90573   *
90574   *    env = new p5.Envelope();
90575   *    env.setADSR(attackTime, decayTime, susPercent, releaseTime);
90576   *    env.setRange(attackLevel, releaseLevel);
90577   *
90578   *    triOsc = new p5.Oscillator('triangle');
90579   *    triOsc.amp(env);
90580   *    triOsc.start();
90581   *    triOsc.freq(220);
90582   *
90583   *    cnv.mousePressed(playEnv);
90584   *  }
90585   *
90586   *  function playEnv()  {
90587   *    // trigger env on triOsc, 0 seconds from now
90588   *    // After decay, sustain for 0.2 seconds before release
90589   *    env.play(triOsc, 0, 0.2);
90590   *  }
90591   *  </code></div>
90592   */
90593  p5.Envelope.prototype.play = function (unit, secondsFromNow, susTime) {
90594    var tFromNow = secondsFromNow || 0;
90595    var susTime = susTime || 0;
90596    if (unit) {
90597      if (this.connection !== unit) {
90598        this.connect(unit);
90599      }
90600    }
90601    this.triggerAttack(unit, tFromNow);
90602    this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + susTime);
90603  };
90604  /**
90605   *  Trigger the Attack, and Decay portion of the Envelope.
90606   *  Similar to holding down a key on a piano, but it will
90607   *  hold the sustain level until you let go. Input can be
90608   *  any p5.sound object, or a <a href="
90609   *  http://docs.webplatform.org/wiki/apis/webaudio/AudioParam">
90610   *  Web Audio Param</a>.
90611   *
90612   *  @method  triggerAttack
90613   *  @param  {Object} unit p5.sound Object or Web Audio Param
90614   *  @param  {Number} secondsFromNow time from now (in seconds)
90615   *  @example
90616   *  <div><code>
90617   *
90618   *  var attackLevel = 1.0;
90619   *  var releaseLevel = 0;
90620   *
90621   *  var attackTime = 0.001;
90622   *  var decayTime = 0.3;
90623   *  var susPercent = 0.4;
90624   *  var releaseTime = 0.5;
90625   *
90626   *  var env, triOsc;
90627   *
90628   *  function setup() {
90629   *    var cnv = createCanvas(100, 100);
90630   *    background(200);
90631   *    textAlign(CENTER);
90632   *    text('click to play', width/2, height/2);
90633   *
90634   *    env = new p5.Envelope();
90635   *    env.setADSR(attackTime, decayTime, susPercent, releaseTime);
90636   *    env.setRange(attackLevel, releaseLevel);
90637   *
90638   *    triOsc = new p5.Oscillator('triangle');
90639   *    triOsc.amp(env);
90640   *    triOsc.start();
90641   *    triOsc.freq(220);
90642   *
90643   *    cnv.mousePressed(envAttack);
90644   *  }
90645   *
90646   *  function envAttack()  {
90647   *    console.log('trigger attack');
90648   *    env.triggerAttack();
90649   *
90650   *    background(0,255,0);
90651   *    text('attack!', width/2, height/2);
90652   *  }
90653   *
90654   *  function mouseReleased() {
90655   *    env.triggerRelease();
90656   *
90657   *    background(200);
90658   *    text('click to play', width/2, height/2);
90659   *  }
90660   *  </code></div>
90661   */
90662  p5.Envelope.prototype.triggerAttack = function (unit, secondsFromNow) {
90663    var now = p5sound.audiocontext.currentTime;
90664    var tFromNow = secondsFromNow || 0;
90665    var t = now + tFromNow;
90666    this.lastAttack = t;
90667    this.wasTriggered = true;
90668    if (unit) {
90669      if (this.connection !== unit) {
90670        this.connect(unit);
90671      }
90672    }
90673    // get and set value (with linear ramp) to anchor automation
90674    var valToSet = this.control.getValueAtTime(t);
90675    if (this.isExponential === true) {
90676      this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);
90677    } else {
90678      this.control.linearRampToValueAtTime(valToSet, t);
90679    }
90680    // after each ramp completes, cancel scheduled values
90681    // (so they can be overridden in case env has been re-triggered)
90682    // then, set current value (with linearRamp to avoid click)
90683    // then, schedule the next automation...
90684    // attack
90685    t += this.aTime;
90686    if (this.isExponential === true) {
90687      this.control.exponentialRampToValueAtTime(this.checkExpInput(this.aLevel), t);
90688      valToSet = this.checkExpInput(this.control.getValueAtTime(t));
90689      this.control.cancelScheduledValues(t);
90690      this.control.exponentialRampToValueAtTime(valToSet, t);
90691    } else {
90692      this.control.linearRampToValueAtTime(this.aLevel, t);
90693      valToSet = this.control.getValueAtTime(t);
90694      this.control.cancelScheduledValues(t);
90695      this.control.linearRampToValueAtTime(valToSet, t);
90696    }
90697    // decay to decay level (if using ADSR, then decay level == sustain level)
90698    t += this.dTime;
90699    if (this.isExponential === true) {
90700      this.control.exponentialRampToValueAtTime(this.checkExpInput(this.dLevel), t);
90701      valToSet = this.checkExpInput(this.control.getValueAtTime(t));
90702      this.control.cancelScheduledValues(t);
90703      this.control.exponentialRampToValueAtTime(valToSet, t);
90704    } else {
90705      this.control.linearRampToValueAtTime(this.dLevel, t);
90706      valToSet = this.control.getValueAtTime(t);
90707      this.control.cancelScheduledValues(t);
90708      this.control.linearRampToValueAtTime(valToSet, t);
90709    }
90710  };
90711  /**
90712   *  Trigger the Release of the Envelope. This is similar to releasing
90713   *  the key on a piano and letting the sound fade according to the
90714   *  release level and release time.
90715   *
90716   *  @method  triggerRelease
90717   *  @param  {Object} unit p5.sound Object or Web Audio Param
90718   *  @param  {Number} secondsFromNow time to trigger the release
90719   *  @example
90720   *  <div><code>
90721   *
90722   *  var attackLevel = 1.0;
90723   *  var releaseLevel = 0;
90724   *
90725   *  var attackTime = 0.001;
90726   *  var decayTime = 0.3;
90727   *  var susPercent = 0.4;
90728   *  var releaseTime = 0.5;
90729   *
90730   *  var env, triOsc;
90731   *
90732   *  function setup() {
90733   *    var cnv = createCanvas(100, 100);
90734   *    background(200);
90735   *    textAlign(CENTER);
90736   *    text('click to play', width/2, height/2);
90737   *
90738   *    env = new p5.Envelope();
90739   *    env.setADSR(attackTime, decayTime, susPercent, releaseTime);
90740   *    env.setRange(attackLevel, releaseLevel);
90741   *
90742   *    triOsc = new p5.Oscillator('triangle');
90743   *    triOsc.amp(env);
90744   *    triOsc.start();
90745   *    triOsc.freq(220);
90746   *
90747   *    cnv.mousePressed(envAttack);
90748   *  }
90749   *
90750   *  function envAttack()  {
90751   *    console.log('trigger attack');
90752   *    env.triggerAttack();
90753   *
90754   *    background(0,255,0);
90755   *    text('attack!', width/2, height/2);
90756   *  }
90757   *
90758   *  function mouseReleased() {
90759   *    env.triggerRelease();
90760   *
90761   *    background(200);
90762   *    text('click to play', width/2, height/2);
90763   *  }
90764   *  </code></div>
90765   */
90766  p5.Envelope.prototype.triggerRelease = function (unit, secondsFromNow) {
90767    // only trigger a release if an attack was triggered
90768    if (!this.wasTriggered) {
90769      // this currently causes a bit of trouble:
90770      // if a later release has been scheduled (via the play function)
90771      // a new earlier release won't interrupt it, because
90772      // this.wasTriggered has already been set to false.
90773      // If we want new earlier releases to override, then we need to
90774      // keep track of the last release time, and if the new release time is
90775      // earlier, then use it.
90776      return;
90777    }
90778    var now = p5sound.audiocontext.currentTime;
90779    var tFromNow = secondsFromNow || 0;
90780    var t = now + tFromNow;
90781    if (unit) {
90782      if (this.connection !== unit) {
90783        this.connect(unit);
90784      }
90785    }
90786    // get and set value (with linear or exponential ramp) to anchor automation
90787    var valToSet = this.control.getValueAtTime(t);
90788    if (this.isExponential === true) {
90789      this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t);
90790    } else {
90791      this.control.linearRampToValueAtTime(valToSet, t);
90792    }
90793    // release
90794    t += this.rTime;
90795    if (this.isExponential === true) {
90796      this.control.exponentialRampToValueAtTime(this.checkExpInput(this.rLevel), t);
90797      valToSet = this.checkExpInput(this.control.getValueAtTime(t));
90798      this.control.cancelScheduledValues(t);
90799      this.control.exponentialRampToValueAtTime(valToSet, t);
90800    } else {
90801      this.control.linearRampToValueAtTime(this.rLevel, t);
90802      valToSet = this.control.getValueAtTime(t);
90803      this.control.cancelScheduledValues(t);
90804      this.control.linearRampToValueAtTime(valToSet, t);
90805    }
90806    this.wasTriggered = false;
90807  };
90808  /**
90809   *  Exponentially ramp to a value using the first two
90810   *  values from <code><a href="#/p5.Envelope/setADSR">setADSR(attackTime, decayTime)</a></code>
90811   *  as <a href="https://en.wikipedia.org/wiki/RC_time_constant">
90812   *  time constants</a> for simple exponential ramps.
90813   *  If the value is higher than current value, it uses attackTime,
90814   *  while a decrease uses decayTime.
90815   *
90816   *  @method  ramp
90817   *  @param  {Object} unit           p5.sound Object or Web Audio Param
90818   *  @param  {Number} secondsFromNow When to trigger the ramp
90819   *  @param  {Number} v              Target value
90820   *  @param  {Number} [v2]           Second target value (optional)
90821   *  @example
90822   *  <div><code>
90823   *  var env, osc, amp, cnv;
90824   *
90825   *  var attackTime = 0.001;
90826   *  var decayTime = 0.2;
90827   *  var attackLevel = 1;
90828   *  var decayLevel = 0;
90829   *
90830   *  function setup() {
90831   *    cnv = createCanvas(100, 100);
90832   *    fill(0,255,0);
90833   *    noStroke();
90834   *
90835   *    env = new p5.Envelope();
90836   *    env.setADSR(attackTime, decayTime);
90837   *
90838   *    osc = new p5.Oscillator();
90839   *    osc.amp(env);
90840   *    osc.start();
90841   *
90842   *    amp = new p5.Amplitude();
90843   *
90844   *    cnv.mousePressed(triggerRamp);
90845   *  }
90846   *
90847   *  function triggerRamp() {
90848   *    env.ramp(osc, 0, attackLevel, decayLevel);
90849   *  }
90850   *
90851   *  function draw() {
90852   *    background(20,20,20);
90853   *    text('click me', 10, 20);
90854   *    var h = map(amp.getLevel(), 0, 0.4, 0, height);;
90855   *
90856   *    rect(0, height, width, -h);
90857   *  }
90858   *  </code></div>
90859   */
90860  p5.Envelope.prototype.ramp = function (unit, secondsFromNow, v1, v2) {
90861    var now = p5sound.audiocontext.currentTime;
90862    var tFromNow = secondsFromNow || 0;
90863    var t = now + tFromNow;
90864    var destination1 = this.checkExpInput(v1);
90865    var destination2 = typeof v2 !== 'undefined' ? this.checkExpInput(v2) : undefined;
90866    // connect env to unit if not already connected
90867    if (unit) {
90868      if (this.connection !== unit) {
90869        this.connect(unit);
90870      }
90871    }
90872    //get current value
90873    var currentVal = this.checkExpInput(this.control.getValueAtTime(t));
90874    // this.control.cancelScheduledValues(t);
90875    //if it's going up
90876    if (destination1 > currentVal) {
90877      this.control.setTargetAtTime(destination1, t, this._rampAttackTC);
90878      t += this._rampAttackTime;
90879    } else if (destination1 < currentVal) {
90880      this.control.setTargetAtTime(destination1, t, this._rampDecayTC);
90881      t += this._rampDecayTime;
90882    }
90883    // Now the second part of envelope begins
90884    if (destination2 === undefined)
90885      return;
90886    //if it's going up
90887    if (destination2 > destination1) {
90888      this.control.setTargetAtTime(destination2, t, this._rampAttackTC);
90889    } else if (destination2 < destination1) {
90890      this.control.setTargetAtTime(destination2, t, this._rampDecayTC);
90891    }
90892  };
90893  p5.Envelope.prototype.connect = function (unit) {
90894    this.connection = unit;
90895    // assume we're talking about output gain
90896    // unless given a different audio param
90897    if (unit instanceof p5.Oscillator || unit instanceof p5.SoundFile || unit instanceof p5.AudioIn || unit instanceof p5.Reverb || unit instanceof p5.Noise || unit instanceof p5.Filter || unit instanceof p5.Delay) {
90898      unit = unit.output.gain;
90899    }
90900    if (unit instanceof AudioParam) {
90901      //set the initial value
90902      unit.setValueAtTime(0, p5sound.audiocontext.currentTime);
90903    }
90904    if (unit instanceof p5.Signal) {
90905      unit.setValue(0);
90906    }
90907    this.output.connect(unit);
90908  };
90909  p5.Envelope.prototype.disconnect = function () {
90910    if (this.output) {
90911      this.output.disconnect();
90912    }
90913  };
90914  // Signal Math
90915  /**
90916   *  Add a value to the p5.Oscillator's output amplitude,
90917   *  and return the oscillator. Calling this method
90918   *  again will override the initial add() with new values.
90919   *
90920   *  @method  add
90921   *  @param {Number} number Constant number to add
90922   *  @return {p5.Envelope} Envelope Returns this envelope
90923   *                                     with scaled output
90924   */
90925  p5.Envelope.prototype.add = function (num) {
90926    var add = new Add(num);
90927    var thisChain = this.mathOps.length;
90928    var nextChain = this.output;
90929    return p5.prototype._mathChain(this, add, thisChain, nextChain, Add);
90930  };
90931  /**
90932   *  Multiply the p5.Envelope's output amplitude
90933   *  by a fixed value. Calling this method
90934   *  again will override the initial mult() with new values.
90935   *
90936   *  @method  mult
90937   *  @param {Number}
90937 number Constant number to multiply
90938   *  @return {p5.Envelope} Envelope Returns this envelope
90939   *                                     with scaled output
90940   */
90941  p5.Envelope.prototype.mult = function (num) {
90942    var mult = new Mult(num);
90943    var thisChain = this.mathOps.length;
90944    var nextChain = this.output;
90945    return p5.prototype._mathChain(this, mult, thisChain, nextChain, Mult);
90946  };
90947  /**
90948   *  Scale this envelope's amplitude values to a given
90949   *  range, and return the envelope. Calling this method
90950   *  again will override the initial scale() with new values.
90951   *
90952   *  @method  scale
90953   *  @param  {Number} inMin  input range minumum
90954   *  @param  {Number} inMax  input range maximum
90955   *  @param  {Number} outMin input range minumum
90956   *  @param  {Number} outMax input range maximum
90957   *  @return {p5.Envelope} Envelope Returns this envelope
90958   *                                     with scaled output
90959   */
90960  p5.Envelope.prototype.scale = function (inMin, inMax, outMin, outMax) {
90961    var scale = new Scale(inMin, inMax, outMin, outMax);
90962    var thisChain = this.mathOps.length;
90963    var nextChain = this.output;
90964    return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale);
90965  };
90966  // get rid of the oscillator
90967  p5.Envelope.prototype.dispose = function () {
90968    // remove reference from soundArray
90969    var index = p5sound.soundArray.indexOf(this);
90970    p5sound.soundArray.splice(index, 1);
90971    this.disconnect();
90972    if (this.control) {
90973      this.control.dispose();
90974      this.control = null;
90975    }
90976    for (var i = 1; i < this.mathOps.length; i++) {
90977      this.mathOps[i].dispose();
90978    }
90979  };
90980  // Different name for backwards compatibility, replicates p5.Envelope class
90981  p5.Env = function (t1, l1, t2, l2, t3, l3) {
90982    console.warn('WARNING: p5.Env is now deprecated and may be removed in future versions. ' + 'Please use the new p5.Envelope instead.');
90983    p5.Envelope.call(this, t1, l1, t2, l2, t3, l3);
90984  };
90985  p5.Env.prototype = Object.create(p5.Envelope.prototype);
90986}(master, Tone_signal_Add, Tone_signal_Multiply, Tone_signal_Scale, Tone_signal_TimelineSignal, Tone_core_Tone);
90987var pulse;
90988'use strict';
90989pulse = function () {
90990  var p5sound = master;
90991  /**
90992   *  Creates a Pulse object, an oscillator that implements
90993   *  Pulse Width Modulation.
90994   *  The pulse is created with two oscillators.
90995   *  Accepts a parameter for frequency, and to set the
90996   *  width between the pulses. See <a href="
90997   *  http://p5js.org/reference/#/p5.Oscillator">
90998   *  <code>p5.Oscillator</code> for a full list of methods.
90999   *
91000   *  @class p5.Pulse
91001   *  @extends p5.Oscillator
91002   *  @constructor
91003   *  @param {Number} [freq] Frequency in oscillations per second (Hz)
91004   *  @param {Number} [w]    Width between the pulses (0 to 1.0,
91005   *                         defaults to 0)
91006   *  @example
91007   *  <div><code>
91008   *  var pulse;
91009   *  function setup() {
91010   *    background(0);
91011   *
91012   *    // Create and start the pulse wave oscillator
91013   *    pulse = new p5.Pulse();
91014   *    pulse.amp(0.5);
91015   *    pulse.freq(220);
91016   *    pulse.start();
91017   *  }
91018   *
91019   *  function draw() {
91020   *    var w = map(mouseX, 0, width, 0, 1);
91021   *    w = constrain(w, 0, 1);
91022   *    pulse.width(w)
91023   *  }
91024   *  </code></div>
91025   */
91026  p5.Pulse = function (freq, w) {
91027    p5.Oscillator.call(this, freq, 'sawtooth');
91028    // width of PWM, should be betw 0 to 1.0
91029    this.w = w || 0;
91030    // create a second oscillator with inverse frequency
91031    this.osc2 = new p5.SawOsc(freq);
91032    // create a delay node
91033    this.dNode = p5sound.audiocontext.createDelay();
91034    // dc offset
91035    this.dcOffset = createDCOffset();
91036    this.dcGain = p5sound.audiocontext.createGain();
91037    this.dcOffset.connect(this.dcGain);
91038    this.dcGain.connect(this.output);
91039    // set delay time based on PWM width
91040    this.f = freq || 440;
91041    var mW = this.w / this.oscillator.frequency.value;
91042    this.dNode.delayTime.value = mW;
91043    this.dcGain.gain.value = 1.7 * (0.5 - this.w);
91044    // disconnect osc2 and connect it to delay, which is connected to output
91045    this.osc2.disconnect();
91046    this.osc2.panner.disconnect();
91047    this.osc2.amp(-1);
91048    // inverted amplitude
91049    this.osc2.output.connect(this.dNode);
91050    this.dNode.connect(this.output);
91051    this.output.gain.value = 1;
91052    this.output.connect(this.panner);
91053  };
91054  p5.Pulse.prototype = Object.create(p5.Oscillator.prototype);
91055  /**
91056   *  Set the width of a Pulse object (an oscillator that implements
91057   *  Pulse Width Modulation).
91058   *
91059   *  @method  width
91060   *  @param {Number} [width]    Width between the pulses (0 to 1.0,
91061   *                         defaults to 0)
91062   */
91063  p5.Pulse.prototype.width = function (w) {
91064    if (typeof w === 'number') {
91065      if (w <= 1 && w >= 0) {
91066        this.w = w;
91067        // set delay time based on PWM width
91068        // var mW = map(this.w, 0, 1.0, 0, 1/this.f);
91069        var mW = this.w / this.oscillator.frequency.value;
91070        this.dNode.delayTime.value = mW;
91071      }
91072      this.dcGain.gain.value = 1.7 * (0.5 - this.w);
91073    } else {
91074      w.connect(this.dNode.delayTime);
91075      var sig = new p5.SignalAdd(-0.5);
91076      sig.setInput(w);
91077      sig = sig.mult(-1);
91078      sig = sig.mult(1.7);
91079      sig.connect(this.dcGain.gain);
91080    }
91081  };
91082  p5.Pulse.prototype.start = function (f, time) {
91083    var now = p5sound.audiocontext.currentTime;
91084    var t = time || 0;
91085    if (!this.started) {
91086      var freq = f || this.f;
91087      var type = this.oscillator.type;
91088      this.oscillator = p5sound.audiocontext.createOscillator();
91089      this.oscillator.frequency.setValueAtTime(freq, now);
91090      this.oscillator.type = type;
91091      this.oscillator.connect(this.output);
91092      this.oscillator.start(t + now);
91093      // set up osc2
91094      this.osc2.oscillator = p5sound.audiocontext.createOscillator();
91095      this.osc2.oscillator.frequency.setValueAtTime(freq, t + now);
91096      this.osc2.oscillator.type = type;
91097      this.osc2.oscillator.connect(this.osc2.output);
91098      this.osc2.start(t + now);
91099      this.freqNode = [
91100        this.oscillator.frequency,
91101        this.osc2.oscillator.frequency
91102      ];
91103      // start dcOffset, too
91104      this.dcOffset = createDCOffset();
91105      this.dcOffset.connect(this.dcGain);
91106      this.dcOffset.start(t + now);
91107      // if LFO connections depend on these oscillators
91108      if (this.mods !== undefined && this.mods.frequency !== undefined) {
91109        this.mods.frequency.connect(this.freqNode[0]);
91110        this.mods.frequency.connect(this.freqNode[1]);
91111      }
91112      this.started = true;
91113      this.osc2.started = true;
91114    }
91115  };
91116  p5.Pulse.prototype.stop = function (time) {
91117    if (this.started) {
91118      var t = time || 0;
91119      var now = p5sound.audiocontext.currentTime;
91120      this.oscillator.stop(t + now);
91121      if (this.osc2.oscillator) {
91122        this.osc2.oscillator.stop(t + now);
91123      }
91124      this.dcOffset.stop(t + now);
91125      this.started = false;
91126      this.osc2.started = false;
91127    }
91128  };
91129  p5.Pulse.prototype.freq = function (val, rampTime, tFromNow) {
91130    if (typeof val === 'number') {
91131      this.f = val;
91132      var now = p5sound.audiocontext.currentTime;
91133      var rampTime = rampTime || 0;
91134      var tFromNow = tFromNow || 0;
91135      var currentFreq = this.oscillator.frequency.value;
91136      this.oscillator.frequency.cancelScheduledValues(now);
91137      this.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow);
91138      this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now);
91139      this.osc2.oscillator.frequency.cancelScheduledValues(now);
91140      this.osc2.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow);
91141      this.osc2.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now);
91142      if (this.freqMod) {
91143        this.freqMod.output.disconnect();
91144        this.freqMod = null;
91145      }
91146    } else if (val.output) {
91147      val.output.disconnect();
91148      val.output.connect(this.oscillator.frequency);
91149      val.output.connect(this.osc2.oscillator.frequency);
91150      this.freqMod = val;
91151    }
91152  };
91153  // inspiration: http://webaudiodemos.appspot.com/oscilloscope/
91154  function createDCOffset() {
91155    var ac = p5sound.audiocontext;
91156    var buffer = ac.createBuffer(1, 2048, ac.sampleRate);
91157    var data = buffer.getChannelData(0);
91158    for (var i = 0; i < 2048; i++)
91159      data[i] = 1;
91160    var bufferSource = ac.createBufferSource();
91161    bufferSource.buffer = buffer;
91162    bufferSource.loop = true;
91163    return bufferSource;
91164  }
91165}(master, oscillator);
91166var noise;
91167'use strict';
91168noise = function () {
91169  var p5sound = master;
91170  /**
91171   *  Noise is a type of oscillator that generates a buffer with random values.
91172   *
91173   *  @class p5.Noise
91174   *  @extends p5.Oscillator
91175   *  @constructor
91176   *  @param {String} type Type of noise can be 'white' (default),
91177   *                       'brown' or 'pink'.
91178   */
91179  p5.Noise = function (type) {
91180    var assignType;
91181    p5.Oscillator.call(this);
91182    delete this.f;
91183    delete this.freq;
91184    delete this.oscillator;
91185    if (type === 'brown') {
91186      assignType = _brownNoise;
91187    } else if (type === 'pink') {
91188      assignType = _pinkNoise;
91189    } else {
91190      assignType = _whiteNoise;
91191    }
91192    this.buffer = assignType;
91193  };
91194  p5.Noise.prototype = Object.create(p5.Oscillator.prototype);
91195  // generate noise buffers
91196  var _whiteNoise = function () {
91197    var bufferSize = 2 * p5sound.audiocontext.sampleRate;
91198    var whiteBuffer = p5sound.audiocontext.createBuffer(1, bufferSize, p5sound.audiocontext.sampleRate);
91199    var noiseData = whiteBuffer.getChannelData(0);
91200    for (var i = 0; i < bufferSize; i++) {
91201      noiseData[i] = Math.random() * 2 - 1;
91202    }
91203    whiteBuffer.type = 'white';
91204    return whiteBuffer;
91205  }();
91206  var _pinkNoise = function () {
91207    var bufferSize = 2 * p5sound.audiocontext.sampleRate;
91208    var pinkBuffer = p5sound.audiocontext.createBuffer(1, bufferSize, p5sound.audiocontext.sampleRate);
91209    var noiseData = pinkBuffer.getChannelData(0);
91210    var b0, b1, b2, b3, b4, b5, b6;
91211    b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0;
91212    for (var i = 0; i < bufferSize; i++) {
91213      var white = Math.random() * 2 - 1;
91214      b0 = 0.99886 * b0 + white * 0.0555179;
91215      b1 = 0.99332 * b1 + white * 0.0750759;
91216      b2 = 0.969 * b2 + white * 0.153852;
91217      b3 = 0.8665 * b3 + white * 0.3104856;
91218      b4 = 0.55 * b4 + white * 0.5329522;
91219      b5 = -0.7616 * b5 - white * 0.016898;
91220      noiseData[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;
91221      noiseData[i] *= 0.11;
91222      // (roughly) compensate for gain
91223      b6 = white * 0.115926;
91224    }
91225    pinkBuffer.type = 'pink';
91226    return pinkBuffer;
91227  }();
91228  var _brownNoise = function () {
91229    var bufferSize = 2 * p5sound.audiocontext.sampleRate;
91230    var brownBuffer = p5sound.audiocontext.createBuffer(1, bufferSize, p5sound.audiocontext.sampleRate);
91231    var noiseData = brownBuffer.getChannelData(0);
91232    var lastOut = 0;
91233    for (var i = 0; i < bufferSize; i++) {
91234      var white = Math.random() * 2 - 1;
91235      noiseData[i] = (lastOut + 0.02 * white) / 1.02;
91236      lastOut = noiseData[i];
91237      noiseData[i] *= 3.5;
91238    }
91239    brownBuffer.type = 'brown';
91240    return brownBuffer;
91241  }();
91242  /**
91243   *  Set type of noise to 'white', 'pink' or 'brown'.
91244   *  White is the default.
91245   *
91246   *  @method setType
91247   *  @param {String} [type] 'white', 'pink' or 'brown'
91248   */
91249  p5.Noise.prototype.setType = function (type) {
91250    switch (type) {
91251    case 'white':
91252      this.buffer = _whiteNoise;
91253      break;
91254    case 'pink':
91255      this.buffer = _pinkNoise;
91256      break;
91257    case 'brown':
91258      this.buffer = _brownNoise;
91259      break;
91260    default:
91261      this.buffer = _whiteNoise;
91262    }
91263    if (this.started) {
91264      var now = p5sound.audiocontext.currentTime;
91265      this.stop(now);
91266      this.start(now + 0.01);
91267    }
91268  };
91269  p5.Noise.prototype.getType = function () {
91270    return this.buffer.type;
91271  };
91272  p5.Noise.prototype.start = function () {
91273    if (this.started) {
91274      this.stop();
91275    }
91276    this.noise = p5sound.audiocontext.createBufferSource();
91277    this.noise.buffer = this.buffer;
91278    this.noise.loop = true;
91279    this.noise.connect(this.output);
91280    var now = p5sound.audiocontext.currentTime;
91281    this.noise.start(now);
91282    this.started = true;
91283  };
91284  p5.Noise.prototype.stop = function () {
91285    var now = p5sound.audiocontext.currentTime;
91286    if (this.noise) {
91287      this.noise.stop(now);
91288      this.started = false;
91289    }
91290  };
91291  p5.Noise.prototype.dispose = function () {
91292    var now = p5sound.audiocontext.currentTime;
91293    // remove reference from soundArray
91294    var index = p5sound.soundArray.indexOf(this);
91295    p5sound.soundArray.splice(index, 1);
91296    if (this.noise) {
91297      this.noise.disconnect();
91298      this.stop(now);
91299    }
91300    if (this.output) {
91301      this.output.disconnect();
91302    }
91303    if (this.panner) {
91304      this.panner.disconnect();
91305    }
91306    this.output = null;
91307    this.panner = null;
91308    this.buffer = null;
91309    this.noise = null;
91310  };
91311}(master);
91312var audioin;
91313'use strict';
91314audioin = function () {
91315  var p5sound = master;
91316  // an array of input sources
91317  p5sound.inputSources = [];
91318  /**
91319   *  <p>Get audio from an input, i.e. your computer's microphone.</p>
91320   *
91321   *  <p>Turn the mic on/off with the start() and stop() methods. When the mic
91322   *  is on, its volume can be measured with getLevel or by connecting an
91323   *  FFT object.</p>
91324   *
91325   *  <p>If you want to hear the AudioIn, use the .connect() method.
91326   *  AudioIn does not connect to p5.sound output by default to prevent
91327   *  feedback.</p>
91328   *
91329   *  <p><em>Note: This uses the <a href="http://caniuse.com/stream">getUserMedia/
91330   *  Stream</a> API, which is not supported by certain browsers. Access in Chrome browser
91331   *  is limited to localhost and https, but access over http may be limited.</em></p>
91332   *
91333   *  @class p5.AudioIn
91334   *  @constructor
91335   *  @param {Function} [errorCallback] A function to call if there is an error
91336   *                                    accessing the AudioIn. For example,
91337   *                                    Safari and iOS devices do not
91338   *                                    currently allow microphone access.
91339   *  @example
91340   *  <div><code>
91341   *  var mic;
91342   *  function setup(){
91343   *    mic = new p5.AudioIn()
91344   *    mic.start();
91345   *  }
91346   *  function draw(){
91347   *    background(0);
91348   *    micLevel = mic.getLevel();
91349   *    ellipse(width/2, constrain(height-micLevel*height*5, 0, height), 10, 10);
91350   *  }
91351   *  </code></div>
91352   */
91353  p5.AudioIn = function (errorCallback) {
91354    // set up audio input
91355    /**
91356     * @property {GainNode} input
91357     */
91358    this.input = p5sound.audiocontext.createGain();
91359    /**
91360     * @property {GainNode} output
91361     */
91362    this.output = p5sound.audiocontext.createGain();
91363    /**
91364     * @property {MediaStream|null} stream
91365     */
91366    this.stream = null;
91367    /**
91368     * @property {MediaStreamAudioSourceNode|null} mediaStream
91369     */
91370    this.mediaStream = null;
91371    /**
91372     * @property {Number|null} currentSource
91373     */
91374    this.currentSource = null;
91375    /**
91376     *  Client must allow browser to access their microphone / audioin source.
91377     *  Default: false. Will become true when the client enables acces.
91378     *
91379     *  @property {Boolean} enabled
91380     */
91381    this.enabled = false;
91382    /**
91383     * Input amplitude, connect to it by default but not to master out
91384     *
91385     *  @property {p5.Amplitude} amplitude
91386     */
91387    this.amplitude = new p5.Amplitude();
91388    this.output.connect(this.amplitude.input);
91389    if (!window.MediaStreamTrack || !window.navigator.mediaDevices || !window.navigator.mediaDevices.getUserMedia) {
91390      errorCallback ? errorCallback() : window.alert('This browser does not support MediaStreamTrack and mediaDevices');
91391    }
91392    // add to soundArray so we can dispose on close
91393    p5sound.soundArray.push(this);
91394  };
91395  /**
91396   *  Start processing audio input. This enables the use of other
91397   *  AudioIn methods like getLevel(). Note that by default, AudioIn
91398   *  is not connected to p5.sound's output. So you won't hear
91399   *  anything unless you use the connect() method.<br/>
91400   *
91401   *  Certain browsers limit access to the user's microphone. For example,
91402   *  Chrome only allows access from localhost and over https. For this reason,
91403   *  you may want to include an errorCallback—a function that is called in case
91404   *  the browser won't provide mic access.
91405   *
91406   *  @method start
91407   *  @param {Function} [successCallback] Name of a function to call on
91408   *                                    success.
91409   *  @param {Function} [errorCallback] Name of a function to call if
91410   *                                    there was an error. For example,
91411   *                                    some browsers do not support
91412   *                                    getUserMedia.
91413   */
91414  p5.AudioIn.prototype.start = function (successCallback, errorCallback) {
91415    var self = this;
91416    if (this.stream) {
91417      this.stop();
91418    }
91419    // set the audio source
91420    var audioSource = p5sound.inputSources[self.currentSource];
91421    var constraints = {
91422      audio: {
91423        sampleRate: p5sound.audiocontext.sampleRate,
91424        echoCancellation: false
91425      }
91426    };
91427    // if developers determine which source to use
91428    if (p5sound.inputSources[this.currentSource]) {
91429      constraints.audio.deviceId = audioSource.deviceId;
91430    }
91431    window.navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
91432      self.stream = stream;
91433      self.enabled = true;
91434      // Wrap a MediaStreamSourceNode around the live input
91435      self.mediaStream = p5sound.audiocontext.createMediaStreamSource(stream);
91436      self.mediaStream.connect(self.output);
91437      // only send to the Amplitude reader, so we can see it but not hear it.
91438      self.amplitude.setInput(self.output);
91439      if (successCallback)
91440        successCallback();
91441    }).catch(function (err) {
91442      if (errorCallback)
91443        errorCallback(err);
91444      else
91445        console.error(err);
91446    });
91447  };
91448  /**
91449   *  Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel().
91450   *  If re-starting, the user may be prompted for permission access.
91451   *
91452   *  @method stop
91453   */
91454  p5.AudioIn.prototype.stop = function () {
91455    if (this.stream) {
91456      this.stream.getTracks().forEach(function (track) {
91457        track.stop();
91458      });
91459      this.mediaStream.disconnect();
91460      delete this.mediaStream;
91461      delete this.stream;
91462    }
91463  };
91464  /**
91465   *  Connect to an audio unit. If no parameter is provided, will
91466   *  connect to the master output (i.e. your speakers).<br/>
91467   *
91468   *  @method  connect
91469   *  @param  {Object} [unit] An object that accepts audio input,
91470   *                          such as an FFT
91471   */
91472  p5.AudioIn.prototype.connect = function (unit) {
91473    if (unit) {
91474      if (unit.hasOwnProperty('input')) {
91475        this.output.connect(unit.input);
91476      } else if (unit.hasOwnProperty('analyser')) {
91477        this.output.connect(unit.analyser);
91478      } else {
91479        this.output.connect(unit);
91480      }
91481    } else {
91482      this.output.connect(p5sound.input);
91483    }
91484  };
91485  /**
91486   *  Disconnect the AudioIn from all audio units. For example, if
91487   *  connect() had been called, disconnect() will stop sending
91488   *  signal to your speakers.<br/>
91489   *
91490   *  @method  disconnect
91491   */
91492  p5.AudioIn.prototype.disconnect = function () {
91493    if (this.output) {
91494      this.output.disconnect();
91495      // stay connected to amplitude even if not outputting to p5
91496      this.output.connect(this.amplitude.input);
91497    }
91498  };
91499  /**
91500   *  Read the Amplitude (volume level) of an AudioIn. The AudioIn
91501   *  class contains its own instance of the Amplitude class to help
91502   *  make it easy to get a microphone's volume level. Accepts an
91503   *  optional smoothing value (0.0 < 1.0). <em>NOTE: AudioIn must
91504   *  .start() before using .getLevel().</em><br/>
91505   *
91506   *  @method  getLevel
91507   *  @param  {Number} [smoothing] Smoothing is 0.0 by default.
91508   *                               Smooths values based on previous values.
91509   *  @return {Number}           Volume level (between 0.0 and 1.0)
91510   */
91511  p5.AudioIn.prototype.getLevel = function (smoothing) {
91512    if (smoothing) {
91513      this.amplitude.smoothing = smoothing;
91514    }
91515    return this.amplitude.getLevel();
91516  };
91517  /**
91518   *  Set amplitude (volume) of a mic input between 0 and 1.0. <br/>
91519   *
91520   *  @method  amp
91521   *  @param  {Number} vol between 0 and 1.0
91522   *  @param {Number} [time] ramp time (optional)
91523   */
91524  p5.AudioIn.prototype.amp = function (vol, t) {
91525    if (t) {
91526      var rampTime = t || 0;
91527      var currentVol = this.output.gain.value;
91528      this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);
91529      this.output.gain.setValueAtTime(currentVol, p5sound.audiocontext.currentTime);
91530      this.output.gain.linearRampToValueAtTime(vol, rampTime + p5sound.audiocontext.currentTime);
91531    } else {
91532      this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime);
91533      this.output.gain.setValueAtTime(vol, p5sound.audiocontext.currentTime);
91534    }
91535  };
91536  /**
91537   * Returns a list of available input sources. This is a wrapper
91538   * for <a title="MediaDevices.enumerateDevices() - Web APIs | MDN" target="_blank" href=
91539   *  "https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices"
91540   *  > and it returns a Promise.
91541   *
91542   * @method  getSources
91543   * @param  {Function} [successCallback] This callback function handles the sources when they
91544   *                                      have been enumerated. The callback function
91545   *                                      receives the deviceList array as its only argument
91546   * @param  {Function} [errorCallback] This optional callback receives the error
91547   *                                    message as its argument.
91548   * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar
91549   *                            to the enumerateDevices() method
91550   * @example
91551   *  <div><code>
91552   *  var audiograb;
91553   *
91554   *  function setup(){
91555   *    //new audioIn
91556   *    audioGrab = new p5.AudioIn();
91557   *
91558   *    audioGrab.getSources(function(deviceList) {
91559   *      //print out the array of available sources
91560   *      console.log(deviceList);
91561   *      //set the source to the first item in the deviceList array
91562   *      audioGrab.setSource(0);
91563   *    });
91564   *  }
91565   *  </code></div>
91566   */
91567  p5.AudioIn.prototype.getSources = function (onSuccess, onError) {
91568    return new Promise(function (resolve, reject) {
91569      window.navigator.mediaDevices.enumerateDevices().then(function (devices) {
91570        p5sound.inputSources = devices.filter(function (device) {
91571          return device.kind === 'audioinput';
91572        });
91573        resolve(p5sound.inputSources);
91574        if (onSuccess) {
91575          onSuccess(p5sound.inputSources);
91576        }
91577      }).catch(function (error) {
91578        reject(error);
91579        if (onError) {
91580          onError(error);
91581        } else {
91582          console.error('This browser does not support MediaStreamTrack.getSources()');
91583        }
91584      });
91585    });
91586  };
91587  /**
91588   *  Set the input source. Accepts a number representing a
91589   *  position in the array returned by getSources().
91590   *  This is only available in browsers that support
91591   *  <a title="MediaDevices.enumerateDevices() - Web APIs | MDN" target="_blank" href=
91592   *  "https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices"
91593   *  >navigator.mediaDevices.enumerateDevices()</a>.<br/>
91594   *
91595   *  @method setSource
91596   *  @param {number} num position of input source in the array
91597   */
91598  p5.AudioIn.prototype.setSource = function (num) {
91599    if (p5sound.inputSources.length > 0 && num < p5sound.inputSources.length) {
91600      // set the current source
91601      this.currentSource = num;
91602      console.log('set source to ', p5sound.inputSources[this.currentSource]);
91603    } else {
91604      console.log('unable to set input source');
91605    }
91606    // restart stream if currently active
91607    if (this.stream && this.stream.active) {
91608      this.start();
91609    }
91610  };
91611  // private method
91612  p5.AudioIn.prototype.dispose = function () {
91613    // remove reference from soundArray
91614    var index = p5sound.soundArray.indexOf(this);
91615    p5sound.soundArray.splice(index, 1);
91616    this.stop();
91617    if (this.output) {
91618      this.output.disconnect();
91619    }
91620    if (this.amplitude) {
91621      this.amplitude.disconnect();
91622    }
91623    delete this.amplitude;
91624    delete this.output;
91625  };
91626}(master);
91627/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
91628var Tone_signal_Negate;
91629Tone_signal_Negate = function (Tone) {
91630  'use strict';
91631  Tone.Negate = function () {
91632    this._multiply = this.input = this.output = new Tone.Multiply(-1);
91633  };
91634  Tone.extend(Tone.Negate, Tone.SignalBase);
91635  Tone.Negate.prototype.dispose = function () {
91636    Tone.prototype.dispose.call(this);
91637    this._multiply.dispose();
91638    this._multiply = null;
91639    return this;
91640  };
91641  return Tone.Negate;
91642}(Tone_core_Tone, Tone_signal_Multiply);
91643/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
91644var Tone_signal_Subtract;
91645Tone_signal_Subtract = function (Tone) {
91646  'use strict';
91647  Tone.Subtract = function (value) {
91648    this.createInsOuts(2, 0);
91649    this._sum = this.input[0] = this.output = new Tone.Gain();
91650    this._neg = new Tone.Negate();
91651    this._param = this.input[1] = new Tone.Signal(value);
91652    this._param.chain(this._neg, this._sum);
91653  };
91654  Tone.extend(Tone.Subtract, Tone.Signal);
91655  Tone.Subtract.prototype.dispose = function () {
91656    Tone.prototype.dispose.call(this);
91657    this._neg.dispose();
91658    this._neg = null;
91659    this._sum.disconnect();
91660    this._sum = null;
91661    this._param.dispose();
91662    this._param = null;
91663    return this;
91664  };
91665  return Tone.Subtract;
91666}(Tone_core_Tone, Tone_signal_Add, Tone_signal_Negate, Tone_signal_Signal);
91667/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
91668var Tone_signal_GreaterThanZero;
91669Tone_signal_GreaterThanZero = function (Tone) {
91670  'use strict';
91671  Tone.GreaterThanZero = function () {
91672    this._thresh = this.output = new Tone.WaveShaper(function (val) {
91673      if (val <= 0) {
91674        return 0;
91675      } else {
91676        return 1;
91677      }
91678    }, 127);
91679    this._scale = this.input = new Tone.Multiply(10000);
91680    this._scale.connect(this._thresh);
91681  };
91682  Tone.extend(Tone.GreaterThanZero, Tone.SignalBase);
91683  Tone.GreaterThanZero.prototype.dispose = function () {
91684    Tone.prototype.dispose.call(this);
91685    this._scale.dispose();
91686    this._scale = null;
91687    this._thresh.dispose();
91688    this._thresh = null;
91689    return this;
91690  };
91691  return Tone.GreaterThanZero;
91692}(Tone_core_Tone, Tone_signal_Signal, Tone_signal_Multiply);
91693/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
91694var Tone_signal_GreaterThan;
91695Tone_signal_GreaterThan = function (Tone) {
91696  'use strict';
91697  Tone.GreaterThan = function (value) {
91698    this.createInsOuts(2, 0);
91699    this._param = this.input[0] = new Tone.Subtract(value);
91700    this.input[1] = this._param.input[1];
91701    this._gtz = this.output = new Tone.GreaterThanZero();
91702    this._param.connect(this._gtz);
91703  };
91704  Tone.extend(Tone.GreaterThan, Tone.Signal);
91705  Tone.GreaterThan.prototype.dispose = function () {
91706    Tone.prototype.dispose.call(this);
91707    this._param.dispose();
91708    this._param = null;
91709    this._gtz.dispose();
91710    this._gtz = null;
91711    return this;
91712  };
91713  return Tone.GreaterThan;
91714}(Tone_core_Tone, Tone_signal_GreaterThanZero, Tone_signal_Subtract);
91715/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
91716var Tone_signal_Abs;
91717Tone_signal_Abs = function (Tone) {
91718  'use strict';
91719  Tone.Abs = function () {
91720    this._abs = this.input = this.output = new Tone.WaveShaper(function (val) {
91721      if (val === 0) {
91722        return 0;
91723      } else {
91724        return Math.abs(val);
91725      }
91726    }, 127);
91727  };
91728  Tone.extend(Tone.Abs, Tone.SignalBase);
91729  Tone.Abs.prototype.dispose = function () {
91730    Tone.prototype.dispose.call(this);
91731    this._abs.dispose();
91732    this._abs = null;
91733    return this;
91734  };
91735  return Tone.Abs;
91736}(Tone_core_Tone, Tone_signal_WaveShaper);
91737/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
91738var Tone_signal_Modulo;
91739Tone_signal_Modulo = function (Tone) {
91740  'use strict';
91741  Tone.Modulo = function (modulus) {
91742    this.createInsOuts(1, 0);
91743    this._shaper = new Tone.WaveShaper(Math.pow(2, 16));
91744    this._multiply = new Tone.Multiply();
91745    this._subtract = this.output = new Tone.Subtract();
91746    this._modSignal = new Tone.Signal(modulus);
91747    this.input.fan(this._shaper, this._subtract);
91748    this._modSignal.connect(this._multiply, 0, 0);
91749    this._shaper.connect(this._multiply, 0, 1);
91750    this._multiply.connect(this._subtract, 0, 1);
91751    this._setWaveShaper(modulus);
91752  };
91753  Tone.extend(Tone.Modulo, Tone.SignalBase);
91754  Tone.Modulo.prototype._setWaveShaper = function (mod) {
91755    this._shaper.setMap(function (val) {
91756      var multiple = Math.floor((val + 0.0001) / mod);
91757      return multiple;
91758    });
91759  };
91760  Object.defineProperty(Tone.Modulo.prototype, 'value', {
91761    get: function () {
91762      return this._modSignal.value;
91763    },
91764    set: function (mod) {
91765      this._modSignal.value = mod;
91766      this._setWaveShaper(mod);
91767    }
91768  });
91769  Tone.Modulo.prototype.dispose = function () {
91770    Tone.prototype.dispose.call(this);
91771    this._shaper.dispose();
91772    this._shaper = null;
91773    this._multiply.dispose();
91774    this._multiply = null;
91775    this._subtract.dispose();
91776    this._subtract = null;
91777    this._modSignal.dispose();
91778    this._modSignal = null;
91779    return this;
91780  };
91781  return Tone.Modulo;
91782}(Tone_core_Tone, Tone_signal_WaveShaper, Tone_signal_Multiply);
91783/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
91784var Tone_signal_Pow;
91785Tone_signal_Pow = function (Tone) {
91786  'use strict';
91787  Tone.Pow = function (exp) {
91788    this._exp = this.defaultArg(exp, 1);
91789    this._expScaler = this.input = this.output = new Tone.WaveShaper(this._expFunc(this._exp), 8192);
91790  };
91791  Tone.extend(Tone.Pow, Tone.SignalBase);
91792  Object.defineProperty(Tone.Pow.prototype, 'value', {
91793    get: function () {
91794      return this._exp;
91795    },
91796    set: function (exp) {
91797      this._exp = exp;
91798      this._expScaler.setMap(this._expFunc(this._exp));
91799    }
91800  });
91801  Tone.Pow.prototype._expFunc = function (exp) {
91802    return function (val) {
91803      return Math.pow(Math.abs(val), exp);
91804    };
91805  };
91806  Tone.Pow.prototype.dispose = function () {
91807    Tone.prototype.dispose.call(this);
91808    this._expScaler.dispose();
91809    this._expScaler = null;
91810    return this;
91811  };
91812  return Tone.Pow;
91813}(Tone_core_Tone);
91814/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
91815var Tone_signal_AudioToGain;
91816Tone_signal_AudioToGain = function (Tone) {
91817  'use strict';
91818  Tone.AudioToGain = function () {
91819    this._norm = this.input = this.output = new Tone.WaveShaper(function (x) {
91820      return (x + 1) / 2;
91821    });
91822  };
91823  Tone.extend(Tone.AudioToGain, Tone.SignalBase);
91824  Tone.AudioToGain.prototype.dispose = function () {
91825    Tone.prototype.dispose.call(this);
91826    this._norm.dispose();
91827    this._norm = null;
91828    return this;
91829  };
91830  return Tone.AudioToGain;
91831}(Tone_core_Tone, Tone_signal_WaveShaper);
91832/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
91833var Tone_signal_Expr;
91834Tone_signal_Expr = function (Tone) {
91835  'use strict';
91836  Tone.Expr = function () {
91837    var expr = this._replacements(Array.prototype.slice.call(arguments));
91838    var inputCount = this._parseInputs(expr);
91839    this._nodes = [];
91840    this.input = new Array(inputCount);
91841    for (var i = 0; i < inputCount; i++) {
91842      this.input[i] = this.context.createGain();
91843    }
91844    var tree = this._parseTree(expr);
91845    var result;
91846    try {
91847      result = this._eval(tree);
91848    } catch (e) {
91849      this._disposeNodes();
91850      throw new Error('Tone.Expr: Could evaluate expression: ' + expr);
91851    }
91852    this.output = result;
91853  };
91854  Tone.extend(Tone.Expr, Tone.SignalBase);
91855  function applyBinary(Constructor, args, self) {
91856    var op = new Constructor();
91857    self._eval(args[0]).connect(op, 0, 0);
91858    self._eval(args[1]).connect(op, 0, 1);
91859    return op;
91860  }
91861  function applyUnary(Constructor, args, self) {
91862    var op = new Constructor();
91863    self._eval(args[0]).connect(op, 0, 0);
91864    return op;
91865  }
91866  function getNumber(arg) {
91867    return arg ? parseFloat(arg) : undefined;
91868  }
91869  function literalNumber(arg) {
91870    return arg && arg.args ? parseFloat(arg.args) : undefined;
91871  }
91872  Tone.Expr._Expressions = {
91873    'value': {
91874      'signal': {
91875        regexp: /^\d+\.\d+|^\d+/,
91876        method: function (arg) {
91877          var sig = new Tone.Signal(getNumber(arg));
91878          return sig;
91879        }
91880      },
91881      'input': {
91882        regexp: /^\$\d/,
91883        method: function (arg, self) {
91884          return self.input[getNumber(arg.substr(1))];
91885        }
91886      }
91887    },
91888    'glue': {
91889      '(': { regexp: /^\(/ },
91890      ')': { regexp: /^\)/ },
91891      ',': { regexp: /^,/ }
91892    },
91893    'func': {
91894      'abs': {
91895        regexp: /^abs/,
91896        method: applyUnary.bind(this, Tone.Abs)
91897      },
91898      'mod': {
91899        regexp: /^mod/,
91900        method: function (args, self) {
91901          var modulus = literalNumber(args[1]);
91902          var op = new Tone.Modulo(modulus);
91903          self._eval(args[0]).connect(op);
91904          return op;
91905        }
91906      },
91907      'pow': {
91908        regexp: /^pow/,
91909        method: function (args, self) {
91910          var exp = literalNumber(args[1]);
91911          var op = new Tone.Pow(exp);
91912          self._eval(args[0]).connect(op);
91913          return op;
91914        }
91915      },
91916      'a2g': {
91917        regexp: /^a2g/,
91918        method: function (args, self) {
91919          var op = new Tone.AudioToGain();
91920          self._eval(args[0]).connect(op);
91921          return op;
91922        }
91923      }
91924    },
91925    'binary': {
91926      '+': {
91927        regexp: /^\+/,
91928        precedence: 1,
91929        method: applyBinary.bind(this, Tone.Add)
91930      },
91931      '-': {
91932        regexp: /^\-/,
91933        precedence: 1,
91934        method: function (args, self) {
91935          if (args.length === 1) {
91936            return applyUnary(Tone.Negate, args, self);
91937          } else {
91938            return applyBinary(Tone.Subtract, args, self);
91939          }
91940        }
91941      },
91942      '*': {
91943        regexp: /^\*/,
91944        precedence: 0,
91945        method: applyBinary.bind(this, Tone.Multiply)
91946      }
91947    },
91948    'unary': {
91949      '-': {
91950        regexp: /^\-/,
91951        method: applyUnary.bind(this, Tone.Negate)
91952      },
91953      '!': {
91954        regexp: /^\!/,
91955        method: applyUnary.bind(this, Tone.NOT)
91956      }
91957    }
91958  };
91959  Tone.Expr.prototype._parseInputs = function (expr) {
91960    var inputArray = expr.match(/\$\d/g);
91961    var inputMax = 0;
91962    if (inputArray !== null) {
91963      for (var i = 0; i < inputArray.length; i++) {
91964        var inputNum = parseInt(inputArray[i].substr(1)) + 1;
91965        inputMax = Math.max(inputMax, inputNum);
91966      }
91967    }
91968    return inputMax;
91969  };
91970  Tone.Expr.prototype._replacements = function (args) {
91971    var expr = args.shift();
91972    for (var i = 0; i < args.length; i++) {
91973      expr = expr.replace(/\%/i, args[i]);
91974    }
91975    return expr;
91976  };
91977  Tone.Expr.prototype._tokenize = function (expr) {
91978    var position = -1;
91979    var tokens = [];
91980    while (expr.length > 0) {
91981      expr = expr.trim();
91982      var token = getNextToken(expr);
91983      tokens.push(token);
91984      expr = expr.substr(token.value.length);
91985    }
91986    function getNextToken(expr) {
91987      for (var type in Tone.Expr._Expressions) {
91988        var group = Tone.Expr._Expressions[type];
91989        for (var opName in group) {
91990          var op = group[opName];
91991          var reg = op.regexp;
91992          var match = expr.match(reg);
91993          if (match !== null) {
91994            return {
91995              type: type,
91996              value: match[0],
91997              method: op.method
91998            };
91999          }
92000        }
92001      }
92002      throw new SyntaxError('Tone.Expr: Unexpected token ' + expr);
92003    }
92004    return {
92005      next: function () {
92006        return tokens[++position];
92007      },
92008      peek: function () {
92009        return tokens[position + 1];
92010      }
92011    };
92012  };
92013  Tone.Expr.prototype._parseTree = function (expr) {
92014    var lexer = this._tokenize(expr);
92015    var isUndef = this.isUndef.bind(this);
92016    function matchSyntax(token, syn) {
92017      return !isUndef(token) && token.type === 'glue' && token.value === syn;
92018    }
92019    function matchGroup(token, groupName, prec) {
92020      var ret = false;
92021      var group = Tone.Expr._Expressions[groupName];
92022      if (!isUndef(token)) {
92023        for (var opName in group) {
92024          var op = group[opName];
92025          if (op.regexp.test(token.value)) {
92026            if (!isUndef(prec)) {
92027              if (op.precedence === prec) {
92028                return true;
92029              }
92030            } else {
92031              return true;
92032            }
92033          }
92034        }
92035      }
92036      return ret;
92037    }
92038    function parseExpression(precedence) {
92039      if (isUndef(precedence)) {
92040        precedence = 5;
92041      }
92042      var expr;
92043      if (precedence < 0) {
92044        expr = parseUnary();
92045      } else {
92046        expr = parseExpression(precedence - 1);
92047      }
92048      var token = lexer.peek();
92049      while (matchGroup(token, 'binary', precedence)) {
92050        token = lexer.next();
92051        expr = {
92052          operator: token.value,
92053          method: token.method,
92054          args: [
92055            expr,
92056            parseExpression(precedence - 1)
92057          ]
92058        };
92059        token = lexer.peek();
92060      }
92061      return expr;
92062    }
92063    function parseUnary() {
92064      var token, expr;
92065      token = lexer.peek();
92066      if (matchGroup(token, 'unary')) {
92067        token = lexer.next();
92068        expr = parseUnary();
92069        return {
92070          operator: token.value,
92071          method: token.method,
92072          args: [expr]
92073        };
92074      }
92075      return parsePrimary();
92076    }
92077    function parsePrimary() {
92078      var token, expr;
92079      token = lexer.peek();
92080      if (isUndef(token)) {
92081        throw new SyntaxError('Tone.Expr: Unexpected termination of expression');
92082      }
92083      if (token.type === 'func') {
92084        token = lexer.next();
92085        return parseFunctionCall(token);
92086      }
92087      if (token.type === 'value') {
92088        token = lexer.next();
92089        return {
92090          method: token.method,
92091          args: token.value
92092        };
92093      }
92094      if (matchSyntax(token, '(')) {
92095        lexer.next();
92096        expr = parseExpression();
92097        token = lexer.next();
92098        if (!matchSyntax(token, ')')) {
92099          throw new SyntaxError('Expected )');
92100        }
92101        return expr;
92102      }
92103      throw new SyntaxError('Tone.Expr: Parse error, cannot process token ' + token.value);
92104    }
92105    function parseFunctionCall(func) {
92106      var token, args = [];
92107      token = lexer.next();
92108      if (!matchSyntax(token, '(')) {
92109        throw new SyntaxError('Tone.Expr: Expected ( in a function call "' + func.value + '"');
92110      }
92111      token = lexer.peek();
92112      if (!matchSyntax(token, ')')) {
92113        args = parseArgumentList();
92114      }
92115      token = lexer.next();
92116      if (!matchSyntax(token, ')')) {
92117        throw new SyntaxError('Tone.Expr: Expected ) in a function call "' + func.value + '"');
92118      }
92119      return {
92120        method: func.method,
92121        args: args,
92122        name: name
92123      };
92124    }
92125    function parseArgumentList() {
92126      var token, expr, args = [];
92127      while (true) {
92128        expr = parseExpression();
92129        if (isUndef(expr)) {
92130          break;
92131        }
92132        args.push(expr);
92133        token = lexer.peek();
92134        if (!matchSyntax(token, ',')) {
92135          break;
92136        }
92137        lexer.next();
92138      }
92139      return args;
92140    }
92141    return parseExpression();
92142  };
92143  Tone.Expr.prototype._eval = function (tree) {
92144    if (!this.isUndef(tree)) {
92145      var node = tree.method(tree.args, this);
92146      this._nodes.push(node);
92147      return node;
92148    }
92149  };
92150  Tone.Expr.prototype._disposeNodes = function () {
92151    for (var i = 0; i < this._nodes.length; i++) {
92152      var node = this._nodes[i];
92153      if (this.isFunction(node.dispose)) {
92154        node.dispose();
92155      } else if (this.isFunction(node.disconnect)) {
92156        node.disconnect();
92157      }
92158      node = null;
92159      this._nodes[i] = null;
92160    }
92161    this._nodes = null;
92162  };
92163  Tone.Expr.prototype.dispose = function () {
92164    Tone.prototype.dispose.call(this);
92165    this._disposeNodes();
92166  };
92167  return Tone.Expr;
92168}(Tone_core_Tone, Tone_signal_Add, Tone_signal_Subtract, Tone_signal_Multiply, Tone_signal_GreaterThan, Tone_signal_GreaterThanZero, Tone_signal_Abs, Tone_signal_Negate, Tone_signal_Modulo, Tone_signal_Pow);
92169/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
92170var Tone_signal_EqualPowerGain;
92171Tone_signal_EqualPowerGain = function (Tone) {
92172  'use strict';
92173  Tone.EqualPowerGain = function () {
92174    this._eqPower = this.input = this.output = new Tone.WaveShaper(function (val) {
92175      if (Math.abs(val) < 0.001) {
92176        return 0;
92177      } else {
92178        return this.equalPowerScale(val);
92179      }
92180    }.bind(this), 4096);
92181  };
92182  Tone.extend(Tone.EqualPowerGain, Tone.SignalBase);
92183  Tone.EqualPowerGain.prototype.dispose = function () {
92184    Tone.prototype.dispose.call(this);
92185    this._eqPower.dispose();
92186    this._eqPower = null;
92187    return this;
92188  };
92189  return Tone.EqualPowerGain;
92190}(Tone_core_Tone);
92191/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
92192var Tone_component_CrossFade;
92193Tone_component_CrossFade = function (Tone) {
92194  'use strict';
92195  Tone.CrossFade = function (initialFade) {
92196    this.createInsOuts(2, 1);
92197    this.a = this.input[0] = new Tone.Gain();
92198    this.b = this.input[1] = new Tone.Gain();
92199    this.fade = new Tone.Signal(this.defaultArg(initialFade, 0.5), Tone.Type.NormalRange);
92200    this._equalPowerA = new Tone.EqualPowerGain();
92201    this._equalPowerB = new Tone.EqualPowerGain();
92202    this._invert = new Tone.Expr('1 - $0');
92203    this.a.connect(this.output);
92204    this.b.connect(this.output);
92205    this.fade.chain(this._equalPowerB, this.b.gain);
92206    this.fade.chain(this._invert, this._equalPowerA, this.a.gain);
92207    this._readOnly('fade');
92208  };
92209  Tone.extend(Tone.CrossFade);
92210  Tone.CrossFade.prototype.dispose = function () {
92211    Tone.prototype.dispose.call(this);
92212    this._writable('fade');
92213    this._equalPowerA.dispose();
92214    this._equalPowerA = null;
92215    this._equalPowerB.dispose();
92216    this._equalPowerB = null;
92217    this.fade.dispose();
92218    this.fade = null;
92219    this._invert.dispose();
92220    this._invert = null;
92221    this.a.dispose();
92222    this.a = null;
92223    this.b.dispose();
92224    this.b = null;
92225    return this;
92226  };
92227  return Tone.CrossFade;
92228}(Tone_core_Tone, Tone_signal_Signal, Tone_signal_Expr, Tone_signal_EqualPowerGain);
92229var effect;
92230'use strict';
92231effect = function () {
92232  var p5sound = master;
92233  var CrossFade = Tone_component_CrossFade;
92234  /**
92235   * Effect is a base class for audio effects in p5. <br>
92236   * This module handles the nodes and methods that are 
92237   * common and useful for current and future effects.
92238   *
92239   *
92240   * This class is extended by <a href="/reference/#/p5.Distortion">p5.Distortion</a>, 
92241   * <a href="/reference/#/p5.Compressor">p5.Compressor</a>,
92242   * <a href="/reference/#/p5.Delay">p5.Delay</a>, 
92243   * <a href="/reference/#/p5.Filter">p5.Filter</a>, 
92244   * <a href="/reference/#/p5.Reverb">p5.Reverb</a>.
92245   *
92246   * @class  p5.Effect
92247   * @constructor
92248   * 
92249   * @param {Object} [ac]   Reference to the audio context of the p5 object
92250   * @param {AudioNode} [input]  Gain Node effect wrapper
92251   * @param {AudioNode} [output] Gain Node effect wrapper
92252   * @param {Object} [_drywet]   Tone.JS CrossFade node (defaults to value: 1)
92253   * @param {AudioNode} [wet]  Effects that extend this class should connect
92254   *                              to the wet signal to this gain node, so that dry and wet 
92255   *                              signals are mixed properly.
92256   */
92257  p5.Effect = function () {
92258    this.ac = p5sound.audiocontext;
92259    this.input = this.ac.createGain();
92260    this.output = this.ac.createGain();
92261    /**
92262    *	The p5.Effect class is built
92263    * 	using Tone.js CrossFade
92264    * 	@private
92265    */
92266    this._drywet = new CrossFade(1);
92267    /**
92268     *	In classes that extend
92269     *	p5.Effect, connect effect nodes
92270     *	to the wet parameter
92271     */
92272    this.wet = this.ac.createGain();
92273    this.input.connect(this._drywet.a);
92274    this.wet.connect(this._drywet.b);
92275    this._drywet.connect(this.output);
92276    this.connect();
92277    //Add to the soundArray
92278    p5sound.soundArray.push(this);
92279  };
92280  /**
92281   *  Set the output volume of the filter.
92282   *  
92283   *  @method  amp
92284   *  @param {Number} [vol] amplitude between 0 and 1.0
92285   *  @param {Number} [rampTime] create a fade that lasts until rampTime 
92286   *  @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds
92287   */
92288  p5.Effect.prototype.amp = function (vol, rampTime, tFromNow) {
92289    var rampTime = rampTime || 0;
92290    var tFromNow = tFromNow || 0;
92291    var now = p5sound.audiocontext.currentTime;
92292    var currentVol = this.output.gain.value;
92293    this.output.gain.cancelScheduledValues(now);
92294    this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow + 0.001);
92295    this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime + 0.001);
92296  };
92297  /**
92298   *	Link effects together in a chain	
92299   *	Example usage: filter.chain(reverb, delay, panner);
92300   *	May be used with an open-ended number of arguments
92301   *
92302   *	@method chain 
92303     *  @param {Object} [arguments]  Chain together multiple sound objects	
92304   */
92305  p5.Effect.prototype.chain = function () {
92306    if (arguments.length > 0) {
92307      this.connect(arguments[0]);
92308      for (var i = 1; i < arguments.length; i += 1) {
92309        arguments[i - 1].connect(arguments[i]);
92310      }
92311    }
92312    return this;
92313  };
92314  /**
92315   *	Adjust the dry/wet value.	
92316   *	
92317   *	@method drywet
92318   *	@param {Number} [fade] The desired drywet value (0 - 1.0)
92319   */
92320  p5.Effect.prototype.drywet = function (fade) {
92321    if (typeof fade !== 'undefined') {
92322      this._drywet.fade.value = fade;
92323    }
92324    return this._drywet.fade.value;
92325  };
92326  /**
92327   *	Send output to a p5.js-sound, Web Audio Node, or use signal to
92328   *	control an AudioParam	
92329   *	
92330   *	@method connect 
92331   *	@param {Object} unit 
92332   */
92333  p5.Effect.prototype.connect = function (unit) {
92334    var u = unit || p5.soundOut.input;
92335    this.output.connect(u.input ? u.input : u);
92336  };
92337  /**
92338   *	Disconnect all output.	
92339   *	
92340   *	@method disconnect 
92341   */
92342  p5.Effect.prototype.disconnect = function () {
92343    if (this.output) {
92344      this.output.disconnect();
92345    }
92346  };
92347  p5.Effect.prototype.dispose = function () {
92348    // remove refernce form soundArray
92349    var index = p5sound.soundArray.indexOf(this);
92350    p5sound.soundArray.splice(index, 1);
92351    if (this.input) {
92352      this.input.disconnect();
92353      delete this.input;
92354    }
92355    if (this.output) {
92356      this.output.disconnect();
92357      delete this.output;
92358    }
92359    if (this._drywet) {
92360      this._drywet.disconnect();
92361      delete this._drywet;
92362    }
92363    if (this.wet) {
92364      this.wet.disconnect();
92365      delete this.wet;
92366    }
92367    this.ac = undefined;
92368  };
92369  return p5.Effect;
92370}(master, Tone_component_CrossFade);
92371var filter;
92372'use strict';
92373filter = function () {
92374  var p5sound = master;
92375  var Effect = effect;
92376  /**
92377   *  <p>A p5.Filter uses a Web Audio Biquad Filter to filter
92378   *  the frequency response of an input source. Subclasses
92379   *  include:</p>
92380   *  * <a href="/reference/#/p5.LowPass"><code>p5.LowPass</code></a>:
92381   *  Allows frequencies below the cutoff frequency to pass through,
92382   *  and attenuates frequencies above the cutoff.<br/>
92383   *  * <a href="/reference/#/p5.HighPass"><code>p5.HighPass</code></a>:
92384   *  The opposite of a lowpass filter. <br/>
92385   *  * <a href="/reference/#/p5.BandPass"><code>p5.BandPass</code></a>:
92386   *  Allows a range of frequencies to pass through and attenuates
92387   *  the frequencies below and above this frequency range.<br/>
92388   *
92389   *  The <code>.res()</code> method controls either width of the
92390   *  bandpass, or resonance of the low/highpass cutoff frequency.
92391   *
92392   *  This class extends <a href = "/reference/#/p5.Effect">p5.Effect</a>.  
92393   *  Methods <a href = "/reference/#/p5.Effect/amp">amp()</a>, <a href = "/reference/#/p5.Effect/chain">chain()</a>, 
92394   *  <a href = "/reference/#/p5.Effect/drywet">drywet()</a>, <a href = "/reference/#/p5.Effect/connect">connect()</a>, and 
92395   *  <a href = "/reference/#/p5.Effect/disconnect">disconnect()</a> are available.
92396   *
92397   *  @class p5.Filter
92398   *  @extends p5.Effect
92399   *  @constructor
92400   *  @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass'
92401   *  @example
92402   *  <div><code>
92403   *  var fft, noise, filter;
92404   *
92405   *  function setup() {
92406   *    fill(255, 40, 255);
92407   *
92408   *    filter = new p5.BandPass();
92409   *
92410   *    noise = new p5.Noise();
92411   *    // disconnect unfiltered noise,
92412   *    // and connect to filter
92413   *    noise.disconnect();
92414   *    noise.connect(filter);
92415   *    noise.start();
92416   *
92417   *    fft = new p5.FFT();
92418   *  }
92419   *
92420   *  function draw() {
92421   *    background(30);
92422   *
92423   *    // set the BandPass frequency based on mouseX
92424   *    var freq = map(mouseX, 0, width, 20, 10000);
92425   *    filter.freq(freq);
92426   *    // give the filter a narrow band (lower res = wider bandpass)
92427   *    filter.res(50);
92428   *
92429   *    // draw filtered spectrum
92430   *    var spectrum = fft.analyze();
92431   *    noStroke();
92432   *    for (var i = 0; i < spectrum.length; i++) {
92433   *      var x = map(i, 0, spectrum.length, 0, width);
92434   *      var h = -height + map(spectrum[i], 0, 255, height, 0);
92435   *      rect(x, height, width/spectrum.length, h);
92436   *    }
92437   *
92438   *    isMouseOverCanvas();
92439   *  }
92440   *
92441   *  function isMouseOverCanvas() {
92442   *    var mX = mouseX, mY = mouseY;
92443   *    if (mX > 0 && mX < width && mY < height && mY > 0) {
92444   *      noise.amp(0.5, 0.2);
92445   *    } else {
92446   *      noise.amp(0, 0.2);
92447   *    }
92448   *  }
92449   *  </code></div>
92450   */
92451  //constructor with inheritance
92452  p5.Filter = function (type) {
92453    Effect.call(this);
92454    //add extend Effect by adding a Biquad Filter
92455    /**
92456        *  The p5.Filter is built with a
92457        *  <a href="http://www.w3.org/TR/webaudio/#BiquadFilterNode">
92458        *  Web Audio BiquadFilter Node</a>.
92459        *
92460        *  @property {DelayNode} biquadFilter
92461     */
92462    this.biquad = this.ac.createBiquadFilter();
92463    this.input.connect(this.biquad);
92464    this.biquad.connect(this.wet);
92465    if (type) {
92466      this.setType(type);
92467    }
92468    //Properties useful for the toggle method.
92469    this._on = true;
92470    this._untoggledType = this.biquad.type;
92471  };
92472  p5.Filter.prototype = Object.create(Effect.prototype);
92473  /**
92474   *  Filter an audio signal according to a set
92475   *  of filter parameters.
92476   *
92477   *  @method  process
92478   *  @param  {Object} Signal  An object that outputs audio
92479   *  @param {Number} [freq] Frequency in Hz, from 10 to 22050
92480   *  @param {Number} [res] Resonance/Width of the filter frequency
92481   *                        from 0.001 to 1000
92482   */
92483  p5.Filter.prototype.process = function (src, freq, res, time) {
92484    src.connect(this.input);
92485    this.set(freq, res, time);
92486  };
92487  /**
92488   *  Set the frequency and the resonance of the filter.
92489   *
92490   *  @method  set
92491   *  @param {Number} [freq] Frequency in Hz, from 10 to 22050
92492   *  @param {Number} [res]  Resonance (Q) from 0.001 to 1000
92493   *  @param {Number} [timeFromNow] schedule this event to happen
92494   *                                seconds from now
92495   */
92496  p5.Filter.prototype.set = function (freq, res, time) {
92497    if (freq) {
92498      this.freq(freq, time);
92499    }
92500    if (res) {
92501      this.res(res, time);
92502    }
92503  };
92504  /**
92505   *  Set the filter frequency, in Hz, from 10 to 22050 (the range of
92506   *  human hearing, although in reality most people hear in a narrower
92507   *  range).
92508   *
92509   *  @method  freq
92510   *  @param  {Number} freq Filter Frequency
92511   *  @param {Number} [timeFromNow] schedule this event to happen
92512   *                                seconds from now
92513   *  @return {Number} value  Returns the current frequency value
92514   */
92515  p5.Filter.prototype.freq = function (freq, time) {
92516    var t = time || 0;
92517    if (freq <= 0) {
92518      freq = 1;
92519    }
92520    if (typeof freq === 'number') {
92521      this.biquad.frequency.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
92522      this.biquad.frequency.exponentialRampToValueAtTime(freq, this.ac.currentTime + 0.02 + t);
92523    } else if (freq) {
92524      freq.connect(this.biquad.frequency);
92525    }
92526    return this.biquad.frequency.value;
92527  };
92528  /**
92529   *  Controls either width of a bandpass frequency,
92530   *  or the resonance of a low/highpass cutoff frequency.
92531   *
92532   *  @method  res
92533   *  @param {Number} res  Resonance/Width of filter freq
92534   *                       from 0.001 to 1000
92535   *  @param {Number} [timeFromNow] schedule this event to happen
92536   *                                seconds from now
92537   *  @return {Number} value Returns the current res value
92538   */
92539  p5.Filter.prototype.res = function (res, time) {
92540    var t = time || 0;
92541    if (typeof res === 'number') {
92542      this.biquad.Q.value = res;
92543      this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
92544      this.biquad.Q.linearRampToValueAtTime(res, this.ac.currentTime + 0.02 + t);
92545    } else if (res) {
92546      res.connect(this.biquad.Q);
92547    }
92548    return this.biquad.Q.value;
92549  };
92550  /**
92551   * Controls the gain attribute of a Biquad Filter.
92552   * This is distinctly different from .amp() which is inherited from p5.Effect
92553   * .amp() controls the volume via the output gain node
92554   * p5.Filter.gain() controls the gain parameter of a Biquad Filter node.
92555   *
92556   * @method gain
92557   * @param  {Number} gain 
92558   * @return {Number} Returns the current or updated gain value
92559   */
92560  p5.Filter.prototype.gain = function (gain, time) {
92561    var t = time || 0;
92562    if (typeof gain === 'number') {
92563      this.biquad.gain.value = gain;
92564      this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
92565      this.biquad.gain.linearRampToValueAtTime(gain, this.ac.currentTime + 0.02 + t);
92566    } else if (gain) {
92567      gain.connect(this.biquad.gain);
92568    }
92569    return this.biquad.gain.value;
92570  };
92571  /**
92572   * Toggle function. Switches between the specified type and allpass
92573   *
92574   * @method toggle
92575   * @return {boolean} [Toggle value]
92576   */
92577  p5.Filter.prototype.toggle = function () {
92578    this._on = !this._on;
92579    if (this._on === true) {
92580      this.biquad.type = this._untoggledType;
92581    } else if (this._on === false) {
92582      this.biquad.type = 'allpass';
92583    }
92584    return this._on;
92585  };
92586  /**
92587   *  Set the type of a p5.Filter. Possible types include:
92588   *  "lowpass" (default), "highpass", "bandpass",
92589   *  "lowshelf", "highshelf", "peaking", "notch",
92590   *  "allpass".
92591   *
92592   *  @method  setType
92593   *  @param {String} t
92594   */
92595  p5.Filter.prototype.setType = function (t) {
92596    this.biquad.type = t;
92597    this._untoggledType = this.biquad.type;
92598  };
92599  p5.Filter.prototype.dispose = function () {
92600    // remove reference from soundArray
92601    Effect.prototype.dispose.apply(this);
92602    if (this.biquad) {
92603      this.biquad.disconnect();
92604      delete this.biquad;
92605    }
92606  };
92607  /**
92608   *  Constructor: <code>new p5.LowPass()</code> Filter.
92609   *  This is the same as creating a p5.Filter and then calling
92610   *  its method <code>setType('lowpass')</code>.
92611   *  See p5.Filter for methods.
92612   *
92613   *  @class p5.LowPass
92614   *  @constructor
92615   *  @extends p5.Filter
92616   */
92617  p5.LowPass = function () {
92618    p5.Filter.call(this, 'lowpass');
92619  };
92620  p5.LowPass.prototype = Object.create(p5.Filter.prototype);
92621  /**
92622   *  Constructor: <code>new p5.HighPass()</code> Filter.
92623   *  This is the same as creating a p5.Filter and then calling
92624   *  its method <code>setType('highpass')</code>.
92625   *  See p5.Filter for methods.
92626   *
92627   *  @class p5.HighPass
92628   *  @constructor
92629   *  @extends p5.Filter
92630   */
92631  p5.HighPass = function () {
92632    p5.Filter.call(this, 'highpass');
92633  };
92634  p5.HighPass.prototype = Object.create(p5.Filter.prototype);
92635  /**
92636   *  Constructor: <code>new p5.BandPass()</code> Filter.
92637   *  This is the same as creating a p5.Filter and then calling
92638   *  its method <code>setType('bandpass')</code>.
92639   *  See p5.Filter for methods.
92640   *
92641   *  @class p5.BandPass
92642   *  @constructor
92643   *  @extends p5.Filter
92644   */
92645  p5.BandPass = function () {
92646    p5.Filter.call(this, 'bandpass');
92647  };
92648  p5.BandPass.prototype = Object.create(p5.Filter.prototype);
92649  return p5.Filter;
92650}(master, effect);
92651var src_eqFilter;
92652'use strict';
92653src_eqFilter = function () {
92654  var Filter = filter;
92655  var p5sound = master;
92656  /**
92657   *  EQFilter extends p5.Filter with constraints
92658   *  necessary for the p5.EQ
92659   *
92660   *  @private
92661   */
92662  var EQFilter = function (freq, res) {
92663    Filter.call(this, 'peaking');
92664    this.disconnect();
92665    this.set(freq, res);
92666    this.biquad.gain.value = 0;
92667    delete this.input;
92668    delete this.output;
92669    delete this._drywet;
92670    delete this.wet;
92671  };
92672  EQFilter.prototype = Object.create(Filter.prototype);
92673  EQFilter.prototype.amp = function () {
92674    console.warn('`amp()` is not available for p5.EQ bands. Use `.gain()`');
92675  };
92676  EQFilter.prototype.drywet = function () {
92677    console.warn('`drywet()` is not available for p5.EQ bands.');
92678  };
92679  EQFilter.prototype.connect = function (unit) {
92680    var u = unit || p5.soundOut.input;
92681    if (this.biquad) {
92682      this.biquad.connect(u.input ? u.input : u);
92683    } else {
92684      this.output.connect(u.input ? u.input : u);
92685    }
92686  };
92687  EQFilter.prototype.disconnect = function () {
92688    if (this.biquad) {
92689      this.biquad.disconnect();
92690    }
92691  };
92692  EQFilter.prototype.dispose = function () {
92693    // remove reference form soundArray
92694    var index = p5sound.soundArray.indexOf(this);
92695    p5sound.soundArray.splice(index, 1);
92696    this.disconnect();
92697    delete this.biquad;
92698  };
92699  return EQFilter;
92700}(filter, master);
92701var eq;
92702'use strict';
92703eq = function () {
92704  var Effect = effect;
92705  var EQFilter = src_eqFilter;
92706  /**
92707   * p5.EQ is an audio effect that performs the function of a multiband
92708   * audio equalizer. Equalization is used to adjust the balance of
92709   * frequency compoenents of an audio signal. This process is commonly used
92710   * in sound production and recording to change the waveform before it reaches
92711   * a sound output device. EQ can also be used as an audio effect to create
92712   * interesting distortions by filtering out parts of the spectrum. p5.EQ is
92713   * built using a chain of Web Audio Biquad Filter Nodes and can be
92714   * instantiated with 3 or 8 bands. Bands can be added or removed from
92715   * the EQ by directly modifying p5.EQ.bands (the array that stores filters).
92716   *
92717   * This class extends <a href = "/reference/#/p5.Effect">p5.Effect</a>.
92718   * Methods <a href = "/reference/#/p5.Effect/amp">amp()</a>, <a href = "/reference/#/p5.Effect/chain">chain()</a>,
92719   * <a href = "/reference/#/p5.Effect/drywet">drywet()</a>, <a href = "/reference/#/p5.Effect/connect">connect()</a>, and
92720   * <a href = "/reference/#/p5.Effect/disconnect">disconnect()</a> are available.
92721   *
92722   * @class p5.EQ
92723   * @constructor
92724   * @extends p5.Effect
92725   * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3
92726   * @return {Object} p5.EQ object
92727   *
92728   * @example
92729   * <div><code>
92730   * var eq;
92731   * var band_names;
92732   * var band_index;
92733   * 
92734   * var soundFile, play;
92735   * 
92736   * function preload() {
92737   *   soundFormats('mp3', 'ogg');
92738   *   soundFile = loadSound('assets/beat');
92739   * }
92740   * 
92741   * function setup() {
92742   *   eq = new p5.EQ(3);
92743   *   soundFile.disconnect();
92744   *   eq.process(soundFile);
92745   * 
92746   *   band_names = ['lows','mids','highs'];
92747   *   band_index = 0;
92748   *   play = false;
92749   *   textAlign(CENTER);
92750   * }
92751   * 
92752   * function draw() {
92753   *   background(30);
92754   *   noStroke();
92755   *   fill(255);
92756   *   text('click to kill',50,25);
92757   * 
92758   *   fill(255, 40, 255);
92759   *   textSize(26);
92760   *   text(band_names[band_index],50,55);
92761   * 
92762   *   fill(255);
92763   *   textSize(9);
92764   *   text('space = play/pause',50,80);
92765   * }
92766   * 
92767   * //If mouse is over canvas, cycle to the next band and kill the frequency
92768   * function mouseClicked() {
92769   *   for (var i = 0; i < eq.bands.length; i++) {
92770   *     eq.bands[i].gain(0);
92771   *   }
92772   *   eq.bands[band_index].gain(-40);
92773   *   if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) {
92774   *     band_index === 2 ? band_index = 0 : band_index++;
92775   *   }
92776   * }
92777   * 
92778   * //use space bar to trigger play / pause
92779   * function keyPressed() {
92780   *   if (key===' ') {
92781   *     play = !play
92782   *     play ? soundFile.loop() : soundFile.pause();
92783   *   }
92784   * }
92785   * </code></div>
92786   */
92787  p5.EQ = function (_eqsize) {
92788    Effect.call(this);
92789    //p5.EQ can be of size (3) or (8), defaults to 3
92790    _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3;
92791    var factor;
92792    _eqsize === 3 ? factor = Math.pow(2, 3) : factor = 2;
92793    /**
92794      *  The p5.EQ is built with abstracted p5.Filter objects.
92795      *  To modify any bands, use methods of the <a 
92796      *  href="/reference/#/p5.Filter" title="p5.Filter reference">
92797      *  p5.Filter</a> API, especially `gain` and `freq`.
92798      *  Bands are stored in an array, with indices 0 - 3, or 0 - 7
92799      *  @property {Array}  bands
92800      *
92801    */
92802    this.bands = [];
92803    var freq, res;
92804    for (var i = 0; i < _eqsize; i++) {
92805      if (i === _eqsize - 1) {
92806        freq = 21000;
92807        res = 0.01;
92808      } else if (i === 0) {
92809        freq = 100;
92810        res = 0.1;
92811      } else if (i === 1) {
92812        freq = _eqsize === 3 ? 360 * factor : 360;
92813        res = 1;
92814      } else {
92815        freq = this.bands[i - 1].freq() * factor;
92816        res = 1;
92817      }
92818      this.bands[i] = this._newBand(freq, res);
92819      if (i > 0) {
92820        this.bands[i - 1].connect(this.bands[i].biquad);
92821      } else {
92822        this.input.connect(this.bands[i].biquad);
92823      }
92824    }
92825    this.bands[_eqsize - 1].connect(this.output);
92826  };
92827  p5.EQ.prototype = Object.create(Effect.prototype);
92828  /**
92829   * Process an input by connecting it to the EQ
92830   * @method  process
92831   * @param  {Object} src Audio source
92832   */
92833  p5.EQ.prototype.process = function (src) {
92834    src.connect(this.input);
92835  };
92836  //  /**
92837  //   * Set the frequency and gain of each band in the EQ. This method should be
92838  //   * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ.
92839  //   * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2);
92840  //   *
92841  //   * @method  set
92842  //   * @param {Number} [freq0] Frequency value for band with index 0
92843  //   * @param {Number} [gain0] Gain value for band with index 0
92844  //   * @param {Number} [freq1] Frequency value for band with index 1
92845  //   * @param {Number} [gain1] Gain value for band with index 1
92846  //   * @param {Number} [freq2] Frequency value for band with index 2
92847  //   * @param {Number} [gain2] Gain value for band with index 2
92848  //   * @param {Number} [freq3] Frequency value for band with index 3
92849  //   * @param {Number} [gain3] Gain value for band with index 3
92850  //   * @param {Number} [freq4] Frequency value for band with index 4
92851  //   * @param {Number} [gain4] Gain value for band with index 4
92852  //   * @param {Number} [freq5] Frequency value for band with index 5
92853  //   * @param {Number} [gain5] Gain value for band with index 5
92854  //   * @param {Number} [freq6] Frequency value for band with index 6
92855  //   * @param {Number} [gain6] Gain value for band with index 6
92856  //   * @param {Number} [freq7] Frequency value for band with index 7
92857  //   * @param {Number} [gain7] Gain value for band with index 7
92858  //   */
92859  p5.EQ.prototype.set = function () {
92860    if (arguments.length === this.bands.length * 2) {
92861      for (var i = 0; i < arguments.length; i += 2) {
92862        this.bands[i / 2].freq(arguments[i]);
92863        this.bands[i / 2].gain(arguments[i + 1]);
92864      }
92865    } else {
92866      console.error('Argument mismatch. .set() should be called with ' + this.bands.length * 2 + ' arguments. (one frequency and gain value pair for each band of the eq)');
92867    }
92868  };
92869  /**
92870   * Add a new band. Creates a p5.Filter and strips away everything but
92871   * the raw biquad filter. This method returns an abstracted p5.Filter,
92872   * which can be added to p5.EQ.bands, in order to create new EQ bands.
92873   * @private
92874   * @method  _newBand
92875   * @param  {Number} freq
92876   * @param  {Number} res
92877   * @return {Object}      Abstracted Filter
92878   */
92879  p5.EQ.prototype._newBand = function (freq, res) {
92880    return new EQFilter(freq, res);
92881  };
92882  p5.EQ.prototype.dispose = function () {
92883    Effect.prototype.dispose.apply(this);
92884    if (this.bands) {
92885      while (this.bands.length > 0) {
92886        delete this.bands.pop().dispose();
92887      }
92888      delete this.bands;
92889    }
92890  };
92891  return p5.EQ;
92892}(effect, src_eqFilter);
92893var panner3d;
92894'use strict';
92895panner3d = function () {
92896  var p5sound = master;
92897  var Effect = effect;
92898  /**
92899   * Panner3D is based on the <a title="Web Audio Panner docs"  href=
92900   * "https://developer.mozilla.org/en-US/docs/Web/API/PannerNode">
92901   * Web Audio Spatial Panner Node</a>.
92902   * This panner is a spatial processing node that allows audio to be positioned
92903   * and oriented in 3D space.
92904   *
92905   * The position is relative to an <a title="Web Audio Listener docs" href=
92906   * "https://developer.mozilla.org/en-US/docs/Web/API/AudioListener">
92907   * Audio Context Listener</a>, which can be accessed
92908   * by <code>p5.soundOut.audiocontext.listener</code>
92909   *
92910   *
92911   * @class p5.Panner3D
92912   * @constructor
92913   */
92914  p5.Panner3D = function () {
92915    Effect.call(this);
92916    /**
92917     *  <a title="Web Audio Panner docs"  href=
92918     *  "https://developer.mozilla.org/en-US/docs/Web/API/PannerNode">
92919     *  Web Audio Spatial Panner Node</a>
92920     *
92921     *  Properties include
92922     *    -  <a title="w3 spec for Panning Model"
92923     *    href="https://www.w3.org/TR/webaudio/#idl-def-PanningModelType"
92924     *    >panningModel</a>: "equal power" or "HRTF"
92925     *    -  <a title="w3 spec for Distance Model"
92926     *    href="https://www.w3.org/TR/webaudio/#idl-def-DistanceModelType"
92927     *    >distanceModel</a>: "linear", "inverse", or "exponential"
92928     *
92929     *  @property {AudioNode} panner
92930     *
92931     */
92932    this.panner = this.ac.createPanner();
92933    this.panner.panningModel = 'HRTF';
92934    this.panner.distanceModel = 'linear';
92935    this.panner.connect(this.output);
92936    this.input.connect(this.panner);
92937  };
92938  p5.Panner3D.prototype = Object.create(Effect.prototype);
92939  /**
92940   * Connect an audio sorce
92941   *
92942   * @method  process
92943   * @param  {Object} src Input source
92944   */
92945  p5.Panner3D.prototype.process = function (src) {
92946    src.connect(this.input);
92947  };
92948  /**
92949   * Set the X,Y,Z position of the Panner
92950   * @method set
92951   * @param  {Number} xVal
92952   * @param  {Number} yVal
92953   * @param  {Number} zVal
92954   * @param  {Number} time
92955   * @return {Array}      Updated x, y, z values as an array
92956   */
92957  p5.Panner3D.prototype.set = function (xVal, yVal, zVal, time) {
92958    this.positionX(xVal, time);
92959    this.positionY(yVal, time);
92960    this.positionZ(zVal, time);
92961    return [
92962      this.panner.positionX.value,
92963      this.panner.positionY.value,
92964      this.panner.positionZ.value
92965    ];
92966  };
92967  /**
92968   * Getter and setter methods for position coordinates
92969   * @method positionX
92970   * @return {Number}      updated coordinate value
92971   */
92972  /**
92973   * Getter and setter methods for position coordinates
92974   * @method positionY
92975   * @return {Number}      updated coordinate value
92976   */
92977  /**
92978   * Getter and setter methods for position coordinates
92979   * @method positionZ
92980   * @return {Number}      updated coordinate value
92981   */
92982  p5.Panner3D.prototype.positionX = function (xVal, time) {
92983    var t = time || 0;
92984    if (typeof xVal === 'number') {
92985      this.panner.positionX.value = xVal;
92986      this.panner.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
92987      this.panner.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);
92988    } else if (xVal) {
92989      xVal.connect(this.panner.positionX);
92990    }
92991    return this.panner.positionX.value;
92992  };
92993  p5.Panner3D.prototype.positionY = function (yVal, time) {
92994    var t = time || 0;
92995    if (typeof yVal === 'number') {
92996      this.panner.positionY.value = yVal;
92997      this.panner.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
92998      this.panner.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);
92999    } else if (yVal) {
93000      yVal.connect(this.panner.positionY);
93001    }
93002    return this.panner.positionY.value;
93003  };
93004  p5.Panner3D.prototype.positionZ = function (zVal, time) {
93005    var t = time || 0;
93006    if (typeof zVal === 'number') {
93007      this.panner.positionZ.value = zVal;
93008      this.panner.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
93009      this.panner.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);
93010    } else if (zVal) {
93011      zVal.connect(this.panner.positionZ);
93012    }
93013    return this.panner.positionZ.value;
93014  };
93015  /**
93016   * Set the X,Y,Z position of the Panner
93017   * @method  orient
93018   * @param  {Number} xVal
93019   * @param  {Number} yVal
93020   * @param  {Number} zVal
93021   * @param  {Number} time
93022   * @return {Array}      Updated x, y, z values as an array
93023   */
93024  p5.Panner3D.prototype.orient = function (xVal, yVal, zVal, time) {
93025    this.orientX(xVal, time);
93026    this.orientY(yVal, time);
93027    this.orientZ(zVal, time);
93028    return [
93029      this.panner.orientationX.value,
93030      this.panner.orientationY.value,
93031      this.panner.orientationZ.value
93032    ];
93033  };
93034  /**
93035   * Getter and setter methods for orient coordinates
93036   * @method orientX
93037   * @return {Number}      updated coordinate value
93038   */
93039  /**
93040   * Getter and setter methods for orient coordinates
93041   * @method orientY
93042   * @return {Number}      updated coordinate value
93043   */
93044  /**
93045   * Getter and setter methods for orient coordinates
93046   * @method orientZ
93047   * @return {Number}      updated coordinate value
93048   */
93049  p5.Panner3D.prototype.orientX = function (xVal, time) {
93050    var t = time || 0;
93051    if (typeof xVal === 'number') {
93052      this.panner.orientationX.value = xVal;
93053      this.panner.orientationX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
93054      this.panner.orientationX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);
93055    } else if (xVal) {
93056      xVal.connect(this.panner.orientationX);
93057    }
93058    return this.panner.orientationX.value;
93059  };
93060  p5.Panner3D.prototype.orientY = function (yVal, time) {
93061    var t = time || 0;
93062    if (typeof yVal === 'number') {
93063      this.panner.orientationY.value = yVal;
93064      this.panner.orientationY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
93065      this.panner.orientationY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);
93066    } else if (yVal) {
93067      yVal.connect(this.panner.orientationY);
93068    }
93069    return this.panner.orientationY.value;
93070  };
93071  p5.Panner3D.prototype.orientZ = function (zVal, time) {
93072    var t = time || 0;
93073    if (typeof zVal === 'number') {
93074      this.panner.orientationZ.value = zVal;
93075      this.panner.orientationZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
93076      this.panner.orientationZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);
93077    } else if (zVal) {
93078      zVal.connect(this.panner.orientationZ);
93079    }
93080    return this.panner.orientationZ.value;
93081  };
93082  /**
93083   * Set the rolloff factor and max distance
93084   * @method  setFalloff
93085   * @param {Number} [maxDistance]
93086   * @param {Number} [rolloffFactor]
93087   */
93088  p5.Panner3D.prototype.setFalloff = function (maxDistance, rolloffFactor) {
93089    this.maxDist(maxDistance);
93090    this.rolloff(rolloffFactor);
93091  };
93092  /**
93093   * Maxium distance between the source and the listener
93094   * @method  maxDist
93095   * @param  {Number} maxDistance
93096   * @return {Number} updated value
93097   */
93098  p5.Panner3D.prototype.maxDist = function (maxDistance) {
93099    if (typeof maxDistance === 'number') {
93100      this.panner.maxDistance = maxDistance;
93101    }
93102    return this.panner.maxDistance;
93103  };
93104  /**
93105   * How quickly the volume is reduced as the source moves away from the listener
93106   * @method  rollof
93107   * @param  {Number} rolloffFactor
93108   * @return {Number} updated value
93109   */
93110  p5.Panner3D.prototype.rolloff = function (rolloffFactor) {
93111    if (typeof rolloffFactor === 'number') {
93112      this.panner.rolloffFactor = rolloffFactor;
93113    }
93114    return this.panner.rolloffFactor;
93115  };
93116  p5.Panner3D.dispose = function () {
93117    Effect.prototype.dispose.apply(this);
93118    if (this.panner) {
93119      this.panner.disconnect();
93120      delete this.panner;
93121    }
93122  };
93123  return p5.Panner3D;
93124}(master, effect);
93125var listener3d;
93126'use strict';
93127listener3d = function () {
93128  var p5sound = master;
93129  var Effect = effect;
93130  //  /**
93131  //   * listener is a class that can construct both a Spatial Panner
93132  //   * and a Spatial Listener. The panner is based on the 
93133  //   * Web Audio Spatial Panner Node
93134  //   * https://www.w3.org/TR/webaudio/#the-listenernode-interface
93135  //   * This panner is a spatial processing node that allows audio to be positioned
93136  //   * and oriented in 3D space. 
93137  //   *
93138  //   * The Listener modifies the properties of the Audio Context Listener. 
93139  //   * Both objects types use the same methods. The default is a spatial panner.
93140  //   *
93141  //   * <code>p5.Panner3D</code> - Constructs a Spatial Panner<br/>
93142  //   * <code>p5.Listener3D</code> - Constructs a Spatial Listener<br/>
93143  //   *
93144  //   * @class listener
93145  //   * @constructor
93146  //   * @return {Object} p5.Listener3D Object
93147  //   *
93148  //   * @param {Web Audio Node} listener Web Audio Spatial Panning Node
93149  //   * @param {AudioParam} listener.panningModel "equal power" or "HRTF"
93150  //   * @param {AudioParam} listener.distanceModel "linear", "inverse", or "exponential"
93151  //   * @param {String} [type] [Specify construction of a spatial panner or listener]
93152  //   */
93153  p5.Listener3D = function (type) {
93154    this.ac = p5sound.audiocontext;
93155    this.listener = this.ac.listener;
93156  };
93157  //  /**
93158  //   * Connect an audio sorce
93159  //   * @param  {Object} src Input source
93160  //   */
93161  p5.Listener3D.prototype.process = function (src) {
93162    src.connect(this.input);
93163  };
93164  //  /**
93165  //   * Set the X,Y,Z position of the Panner
93166  //   * @param  {[Number]} xVal
93167  //   * @param  {[Number]} yVal
93168  //   * @param  {[Number]} zVal
93169  //   * @param  {[Number]} time
93170  //   * @return {[Array]}      [Updated x, y, z values as an array]
93171  //   */
93172  p5.Listener3D.prototype.position = function (xVal, yVal, zVal, time) {
93173    this.positionX(xVal, time);
93174    this.positionY(yVal, time);
93175    this.positionZ(zVal, time);
93176    return [
93177      this.listener.positionX.value,
93178      this.listener.positionY.value,
93179      this.listener.positionZ.value
93180    ];
93181  };
93182  //  /**
93183  //   * Getter and setter methods for position coordinates
93184  //   * @return {Number}      [updated coordinate value]
93185  //   */
93186  p5.Listener3D.prototype.positionX = function (xVal, time) {
93187    var t = time || 0;
93188    if (typeof xVal === 'number') {
93189      this.listener.positionX.value = xVal;
93190      this.listener.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
93191      this.listener.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);
93192    } else if (xVal) {
93193      xVal.connect(this.listener.positionX);
93194    }
93195    return this.listener.positionX.value;
93196  };
93197  p5.Listener3D.prototype.positionY = function (yVal, time) {
93198    var t = time || 0;
93199    if (typeof yVal === 'number') {
93200      this.listener.positionY.value = yVal;
93201      this.listener.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
93202      this.listener.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);
93203    } else if (yVal) {
93204      yVal.connect(this.listener.positionY);
93205    }
93206    return this.listener.positionY.value;
93207  };
93208  p5.Listener3D.prototype.positionZ = function (zVal, time) {
93209    var t = time || 0;
93210    if (typeof zVal === 'number') {
93211      this.listener.positionZ.value = zVal;
93212      this.listener.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
93213      this.listener.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);
93214    } else if (zVal) {
93215      zVal.connect(this.listener.positionZ);
93216    }
93217    return this.listener.positionZ.value;
93218  };
93219  // cannot define method when class definition is commented
93220  //  /**
93221  //   * Overrides the listener orient() method because Listener has slightly
93222  //   * different params. In human terms, Forward vectors are the direction the 
93223  //   * nose is pointing. Up vectors are the direction of the top of the head.
93224  //   *
93225  //   * @method orient
93226  //   * @param  {Number} xValF  Forward vector X direction
93227  //   * @param  {Number} yValF  Forward vector Y direction
93228  //   * @param  {Number} zValF  Forward vector Z direction
93229  //   * @param  {Number} xValU  Up vector X direction
93230  //   * @param  {Number} yValU  Up vector Y direction
93231  //   * @param  {Number} zValU  Up vector Z direction
93232  //   * @param  {Number} time  
93233  //   * @return {Array}       All orienation params
93234  //   */
93235  p5.Listener3D.prototype.orient = function (xValF, yValF, zValF, xValU, yValU, zValU, time) {
93236    if (arguments.length === 3 || arguments.length === 4) {
93237      time = arguments[3];
93238      this.orientForward(xValF, yValF, zValF, time);
93239    } else if (arguments.length === 6 || arguments === 7) {
93240      this.orientForward(xValF, yValF, zValF);
93241      this.orientUp(xValU, yValU, zValU, time);
93242    }
93243    return [
93244      this.listener.forwardX.value,
93245      this.listener.forwardY.value,
93246      this.listener.forwardZ.value,
93247      this.listener.upX.value,
93248      this.listener.upY.value,
93249      this.listener.upZ.value
93250    ];
93251  };
93252  p5.Listener3D.prototype.orientForward = function (xValF, yValF, zValF, time) {
93253    this.forwardX(xValF, time);
93254    this.forwardY(yValF, time);
93255    this.forwardZ(zValF, time);
93256    return [
93257      this.listener.forwardX,
93258      this.listener.forwardY,
93259      this.listener.forwardZ
93260    ];
93261  };
93262  p5.Listener3D.prototype.orientUp = function (xValU, yValU, zValU, time) {
93263    this.upX(xValU, time);
93264    this.upY(yValU, time);
93265    this.upZ(zValU, time);
93266    return [
93267      this.listener.upX,
93268      this.listener.upY,
93269      this.listener.upZ
93270    ];
93271  };
93272  //  /**
93273  //   * Getter and setter methods for orient coordinates
93274  //   * @return {Number}      [updated coordinate value]
93275  //   */
93276  p5.Listener3D.prototype.forwardX = function (xVal, time) {
93277    var t = time || 0;
93278    if (typeof xVal === 'number') {
93279      this.listener.forwardX.value = xVal;
93280      this.listener.forwardX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
93281      this.listener.forwardX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);
93282    } else if (xVal) {
93283      xVal.connect(this.listener.forwardX);
93284    }
93285    return this.listener.forwardX.value;
93286  };
93287  p5.Listener3D.prototype.forwardY = function (yVal, time) {
93288    var t = time || 0;
93289    if (typeof yVal === 'number') {
93290      this.listener.forwardY.value = yVal;
93291      this.listener.forwardY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
93292      this.listener.forwardY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);
93293    } else if (yVal) {
93294      yVal.connect(this.listener.forwardY);
93295    }
93296    return this.listener.forwardY.value;
93297  };
93298  p5.Listener3D.prototype.forwardZ = function (zVal, time) {
93299    var t = time || 0;
93300    if (typeof zVal === 'number') {
93301      this.listener.forwardZ.value = zVal;
93302      this.listener.forwardZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
93303      this.listener.forwardZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);
93304    } else if (zVal) {
93305      zVal.connect(this.listener.forwardZ);
93306    }
93307    return this.listener.forwardZ.value;
93308  };
93309  p5.Listener3D.prototype.upX = function (xVal, time) {
93310    var t = time || 0;
93311    if (typeof xVal === 'number') {
93312      this.listener.upX.value = xVal;
93313      this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
93314      this.listener.upX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t);
93315    } else if (xVal) {
93316      xVal.connect(this.listener.upX);
93317    }
93318    return this.listener.upX.value;
93319  };
93320  p5.Listener3D.prototype.upY = function (yVal, time) {
93321    var t = time || 0;
93322    if (typeof yVal === 'number') {
93323      this.listener.upY.value = yVal;
93324      this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
93325      this.listener.upY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t);
93326    } else if (yVal) {
93327      yVal.connect(this.listener.upY);
93328    }
93329    return this.listener.upY.value;
93330  };
93331  p5.Listener3D.prototype.upZ = function (zVal, time) {
93332    var t = time || 0;
93333    if (typeof zVal === 'number') {
93334      this.listener.upZ.value = zVal;
93335      this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
93336      this.listener.upZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t);
93337    } else if (zVal) {
93338      zVal.connect(this.listener.upZ);
93339    }
93340    return this.listener.upZ.value;
93341  };
93342  return p5.Listener3D;
93343}(master, effect);
93344var delay;
93345'use strict';
93346delay = function () {
93347  var Filter = filter;
93348  var Effect = effect;
93349  /**
93350   *  Delay is an echo effect. It processes an existing sound source,
93351   *  and outputs a delayed version of that sound. The p5.Delay can
93352   *  produce different effects depending on the delayTime, feedback,
93353   *  filter, and type. In the example below, a feedback of 0.5 (the
93354   *  defaul value) will produce a looping delay that decreases in
93355   *  volume by 50% each repeat. A filter will cut out the high
93356   *  frequencies so that the delay does not sound as piercing as the
93357   *  original source.
93358   *
93359   *
93360   *  This class extends <a href = "/reference/#/p5.Effect">p5.Effect</a>.  
93361   *  Methods <a href = "/reference/#/p5.Effect/amp">amp()</a>, <a href = "/reference/#/p5.Effect/chain">chain()</a>, 
93362   *  <a href = "/reference/#/p5.Effect/drywet">drywet()</a>, <a href = "/reference/#/p5.Effect/connect">connect()</a>, and 
93363   *  <a href = "/reference/#/p5.Effect/disconnect">disconnect()</a> are available.
93364   *  @class p5.Delay
93365   *  @extends p5.Effect
93366   *  @constructor
93367   *  @example
93368   *  <div><code>
93369   *  var noise, env, delay;
93370   *
93371   *  function setup() {
93372   *    background(0);
93373   *    noStroke();
93374   *    fill(255);
93375   *    textAlign(CENTER);
93376   *    text('click to play', width/2, height/2);
93377   *
93378   *    noise = new p5.Noise('brown');
93379   *    noise.amp(0);
93380   *    noise.start();
93381   *
93382   *    delay = new p5.Delay();
93383   *
93384   *    // delay.process() accepts 4 parameters:
93385   *    // source, delayTime, feedback, filter frequency
93386   *    // play with these numbers!!
93387   *    delay.process(noise, .12, .7, 2300);
93388   *
93389   *    // play the noise with an envelope,
93390   *    // a series of fades ( time / value pairs )
93391   *    env = new p5.Envelope(.01, 0.2, .2, .1);
93392   *  }
93393   *
93394   *  // mouseClick triggers envelope
93395   *  function mouseClicked() {
93396   *    // is mouse over canvas?
93397   *    if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
93398   *      env.play(noise);
93399   *    }
93400   *  }
93401   *  </code></div>
93402   */
93403  p5.Delay = function () {
93404    Effect.call(this);
93405    this._split = this.ac.createChannelSplitter(2);
93406    this._merge = this.ac.createChannelMerger(2);
93407    this._leftGain = this.ac.createGain();
93408    this._rightGain = this.ac.createGain();
93409    /**
93410     *  The p5.Delay is built with two
93411     *  <a href="http://www.w3.org/TR/webaudio/#DelayNode">
93412     *  Web Audio Delay Nodes</a>, one for each stereo channel.
93413     *
93414     *  @property {DelayNode} leftDelay
93415     */
93416    this.leftDelay = this.ac.createDelay();
93417    /**
93418     *  The p5.Delay is built with two
93419     *  <a href="http://www.w3.org/TR/webaudio/#DelayNode">
93420     *  Web Audio Delay Nodes</a>, one for each stereo channel.
93421     *
93422     *  @property {DelayNode} rightDelay
93423     */
93424    this.rightDelay = this.ac.createDelay();
93425    this._leftFilter = new Filter();
93426    this._rightFilter = new Filter();
93427    this._leftFilter.disconnect();
93428    this._rightFilter.disconnect();
93429    this._leftFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);
93430    this._rightFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime);
93431    this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);
93432    this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime);
93433    // graph routing
93434    this.input.connect(this._split);
93435    this.leftDelay.connect(this._leftGain);
93436    this.rightDelay.connect(this._rightGain);
93437    this._leftGain.connect(this._leftFilter.input);
93438    this._rightGain.connect(this._rightFilter.input);
93439    this._merge.connect(this.wet);
93440    this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);
93441    this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime);
93442    // default routing
93443    this.setType(0);
93444    this._maxDelay = this.leftDelay.delayTime.maxValue;
93445    // set initial feedback to 0.5
93446    this.feedback(0.5);
93447  };
93448  p5.Delay.prototype = Object.create(Effect.prototype);
93449  /**
93450   *  Add delay to an audio signal according to a set
93451   *  of delay parameters.
93452   *
93453   *  @method  process
93454   *  @param  {Object} Signal  An object that outputs audio
93455   *  @param  {Number} [delayTime] Time (in seconds) of the delay/echo.
93456   *                               Some browsers limit delayTime to
93457   *                               1 second.
93458   *  @param  {Number} [feedback]  sends the delay back through itself
93459   *                               in a loop that decreases in volume
93460   *                               each time.
93461   *  @param  {Number} [lowPass]   Cutoff frequency. Only frequencies
93462   *                               below the lowPass will be part of the
93463   *                               delay.
93464   */
93465  p5.Delay.prototype.process = function (src, _delayTime, _feedback, _filter) {
93466    var feedback = _feedback || 0;
93467    var delayTime = _delayTime || 0;
93468    if (feedback >= 1) {
93469      throw new Error('Feedback value will force a positive feedback loop.');
93470    }
93471    if (delayTime >= this._maxDelay) {
93472      throw new Error('Delay Time exceeds maximum delay time of ' + this._maxDelay + ' second.');
93473    }
93474    src.connect(this.input);
93475    this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);
93476    this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime);
93477    this._leftGain.gain.value = feedback;
93478    this._rightGain.gain.value = feedback;
93479    if (_filter) {
93480      this._leftFilter.freq(_filter);
93481      this._rightFilter.freq(_filter);
93482    }
93483  };
93484  /**
93485   *  Set the delay (echo) time, in seconds. Usually this value will be
93486   *  a floating point number between 0.0 and 1.0.
93487   *
93488   *  @method  delayTime
93489   *  @param {Number} delayTime Time (in seconds) of the delay
93490   */
93491  p5.Delay.prototype.delayTime = function (t) {
93492    // if t is an audio node...
93493    if (typeof t !== 'number') {
93494      t.connect(this.leftDelay.delayTime);
93495      t.connect(this.rightDelay.delayTime);
93496    } else {
93497      this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime);
93498      this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime);
93499      this.leftDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);
93500      this.rightDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime);
93501    }
93502  };
93503  /**
93504   *  Feedback occurs when Delay sends its signal back through its input
93505   *  in a loop. The feedback amount determines how much signal to send each
93506   *  time through the loop. A feedback greater than 1.0 is not desirable because
93507   *  it will increase the overall output each time through the loop,
93508   *  creating an infinite feedback loop. The default value is 0.5
93509   *
93510   *  @method  feedback
93511   *  @param {Number|Object} feedback 0.0 to 1.0, or an object such as an
93512   *                                  Oscillator that can be used to
93513   *                                  modulate this param
93514   *  @returns {Number} Feedback value
93515   *
93516   */
93517  p5.Delay.prototype.feedback = function (f) {
93518    // if f is an audio node...
93519    if (f && typeof f !== 'number') {
93520      f.connect(this._leftGain.gain);
93521      f.connect(this._rightGain.gain);
93522    } else if (f >= 1) {
93523      throw new Error('Feedback value will force a positive feedback loop.');
93524    } else if (typeof f === 'number') {
93525      this._leftGain.gain.value = f;
93526      this._rightGain.gain.value = f;
93527    }
93528    // return value of feedback
93529    return this._leftGain.gain.value;
93530  };
93531  /**
93532   *  Set a lowpass filter frequency for the delay. A lowpass filter
93533   *  will cut off any frequencies higher than the filter frequency.
93534   *
93535   *  @method  filter
93536   *  @param {Number|Object} cutoffFreq  A lowpass filter will cut off any
93537   *                              frequencies higher than the filter frequency.
93538   *  @param {Number|Object} res  Resonance of the filter frequency
93539   *                              cutoff, or an object (i.e. a p5.Oscillator)
93540   *                              that can be used to modulate this parameter.
93541   *                              High numbers (i.e. 15) will produce a resonance,
93542   *                              low numbers (i.e. .2) will produce a slope.
93543   */
93544  p5.Delay.prototype.filter = function (freq, q) {
93545    this._leftFilter.set(freq, q);
93546    this._rightFilter.set(freq, q);
93547  };
93548  /**
93549   *  Choose a preset type of delay. 'pingPong' bounces the signal
93550   *  from the left to the right channel to produce a stereo effect.
93551   *  Any other parameter will revert to the default delay setting.
93552   *
93553   *  @method  setType
93554   *  @param {String|Number} type 'pingPong' (1) or 'default' (0)
93555   */
93556  p5.Delay.prototype.setType = function (t) {
93557    if (t === 1) {
93558      t = 'pingPong';
93559    }
93560    this._split.disconnect();
93561    this._leftFilter.disconnect();
93562    this._rightFilter.disconnect();
93563    this._split.connect(this.leftDelay, 0);
93564    this._split.connect(this.rightDelay, 1);
93565    switch (t) {
93566    case 'pingPong':
93567      this._rightFilter.setType(this._leftFilter.biquad.type);
93568      this._leftFilter.output.connect(this._merge, 0, 0);
93569      this._rightFilter.output.connect(this._merge, 0, 1);
93570      this._leftFilter.output.connect(this.rightDelay);
93571      this._rightFilter.output.connect(this.leftDelay);
93572      break;
93573    default:
93574      this._leftFilter.output.connect(this._merge, 0, 0);
93575      this._rightFilter.output.connect(this._merge, 0, 1);
93576      this._leftFilter.output.connect(this.leftDelay);
93577      this._rightFilter.output.connect(this.rightDelay);
93578    }
93579  };
93580  // DocBlocks for methods inherited from p5.Effect
93581  /**
93582   *  Set the output level of the delay effect.
93583   *
93584   *  @method  amp
93585   *  @param  {Number} volume amplitude between 0 and 1.0
93586   *  @param {Number} [rampTime] create a fade that lasts rampTime
93587   *  @param {Number} [timeFromNow] schedule this event to happen
93588   *                                seconds from now
93589   */
93590  /**
93591   *  Send output to a p5.sound or web audio object
93592   *
93593   *  @method  connect
93594   *  @param  {Object} unit
93595   */
93596  /**
93597   *  Disconnect all output.
93598   *
93599   *  @method disconnect
93600   */
93601  p5.Delay.prototype.dispose = function () {
93602    Effect.prototype.dispose.apply(this);
93603    this._split.disconnect();
93604    this._leftFilter.dispose();
93605    this._rightFilter.dispose();
93606    this._merge.disconnect();
93607    this._leftGain.disconnect();
93608    this._rightGain.disconnect();
93609    this.leftDelay.disconnect();
93610    this.rightDelay.disconnect();
93611    this._split = undefined;
93612    this._leftFilter = undefined;
93613    this._rightFilter = undefined;
93614    this._merge = undefined;
93615    this._leftGain = undefined;
93616    this._rightGain = undefined;
93617    this.leftDelay = undefined;
93618    this.rightDelay = undefined;
93619  };
93620}(filter, effect);
93621var reverb;
93622'use strict';
93623reverb = function () {
93624  var CustomError = errorHandler;
93625  var Effect = effect;
93626  /**
93627   *  Reverb adds depth to a sound through a large number of decaying
93628   *  echoes. It creates the perception that sound is occurring in a
93629   *  physical space. The p5.Reverb has paramters for Time (how long does the
93630   *  reverb last) and decayRate (how much the sound decays with each echo)
93631   *  that can be set with the .set() or .process() methods. The p5.Convolver
93632   *  extends p5.Reverb allowing you to recreate the sound of actual physical
93633   *  spaces through convolution.
93634   *
93635   *  This class extends <a href = "/reference/#/p5.Effect">p5.Effect</a>.
93636   *  Methods <a href = "/reference/#/p5.Effect/amp">amp()</a>, <a href = "/reference/#/p5.Effect/chain">chain()</a>,
93637   *  <a href = "/reference/#/p5.Effect/drywet">drywet()</a>, <a href = "/reference/#/p5.Effect/connect">connect()</a>, and
93638   *  <a href = "/reference/#/p5.Effect/disconnect">disconnect()</a> are available.
93639   *
93640   *  @class p5.Reverb
93641   *  @extends p5.Effect
93642   *  @constructor
93643   *  @example
93644   *  <div><code>
93645   *  var soundFile, reverb;
93646   *  function preload() {
93647   *    soundFile = loadSound('assets/Damscray_DancingTiger.mp3');
93648   *  }
93649   *
93650   *  function setup() {
93651   *    reverb = new p5.Reverb();
93652   *    soundFile.disconnect(); // so we'll only hear reverb...
93653   *
93654   *    // connect soundFile to reverb, process w/
93655   *    // 3 second reverbTime, decayRate of 2%
93656   *    reverb.process(soundFile, 3, 2);
93657   *    soundFile.play();
93658   *  }
93659   *  </code></div>
93660   */
93661  p5.Reverb = function () {
93662    Effect.call(this);
93663    this._initConvolverNode();
93664    // otherwise, Safari distorts
93665    this.input.gain.value = 0.5;
93666    // default params
93667    this._seconds = 3;
93668    this._decay = 2;
93669    this._reverse = false;
93670    this._buildImpulse();
93671  };
93672  p5.Reverb.prototype = Object.create(Effect.prototype);
93673  p5.Reverb.prototype._initConvolverNode = function () {
93674    this.convolverNode = this.ac.createConvolver();
93675    this.input.connect(this.convolverNode);
93676    this.convolverNode.connect(this.wet);
93677  };
93678  p5.Reverb.prototype._teardownConvolverNode = function () {
93679    if (this.convolverNode) {
93680      this.convolverNode.disconnect();
93681      delete this.convolverNode;
93682    }
93683  };
93684  p5.Reverb.prototype._setBuffer = function (audioBuffer) {
93685    this._teardownConvolverNode();
93686    this._initConvolverNode();
93687    this.convolverNode.buffer = audioBuffer;
93688  };
93689  /**
93690   *  Connect a source to the reverb, and assign reverb parameters.
93691   *
93692   *  @method  process
93693   *  @param  {Object} src     p5.sound / Web Audio object with a sound
93694   *                           output.
93695   *  @param  {Number} [seconds] Duration of the reverb, in seconds.
93696   *                           Min: 0, Max: 10. Defaults to 3.
93697   *  @param  {Number} [decayRate] Percentage of decay with each echo.
93698   *                            Min: 0, Max: 100. Defaults to 2.
93699   *  @param  {Boolean} [reverse] Play the reverb backwards or forwards.
93700   */
93701  p5.Reverb.prototype.process = function (src, seconds, decayRate, reverse) {
93702    src.connect(this.input);
93703    var rebuild = false;
93704    if (seconds) {
93705      this._seconds = seconds;
93706      rebuild = true;
93707    }
93708    if (decayRate) {
93709      this._decay = decayRate;
93710    }
93711    if (reverse) {
93712      this._reverse = reverse;
93713    }
93714    if (rebuild) {
93715      this._buildImpulse();
93716    }
93717  };
93718  /**
93719   *  Set the reverb settings. Similar to .process(), but without
93720   *  assigning a new input.
93721   *
93722   *  @method  set
93723   *  @param  {Number} [seconds] Duration of the reverb, in seconds.
93724   *                           Min: 0, Max: 10. Defaults to 3.
93725   *  @param  {Number} [decayRate] Percentage of decay with each echo.
93726   *                            Min: 0, Max: 100. Defaults to 2.
93727   *  @param  {Boolean} [reverse] Play the reverb backwards or forwards.
93728   */
93729  p5.Reverb.prototype.set = function (seconds, decayRate, reverse) {
93730    var rebuild = false;
93731    if (seconds) {
93732      this._seconds = seconds;
93733      rebuild = true;
93734    }
93735    if (decayRate) {
93736      this._decay = decayRate;
93737    }
93738    if (reverse) {
93739      this._reverse = reverse;
93740    }
93741    if (rebuild) {
93742      this._buildImpulse();
93743    }
93744  };
93745  // DocBlocks for methods inherited from p5.Effect
93746  /**
93747   *  Set the output level of the reverb effect.
93748   *
93749   *  @method  amp
93750   *  @param  {Number} volume amplitude between 0 and 1.0
93751   *  @param  {Number} [rampTime] create a fade that lasts rampTime
93752   *  @param  {Number} [timeFromNow] schedule this event to happen
93753   *                                seconds from now
93754   */
93755  /**
93756   *  Send output to a p5.sound or web audio object
93757   *
93758   *  @method  connect
93759   *  @param  {Object} unit
93760   */
93761  /**
93762   *  Disconnect all output.
93763   *
93764   *  @method disconnect
93765   */
93766  /**
93767   *  Inspired by Simple Reverb by Jordan Santell
93768   *  https://github.com/web-audio-components/simple-reverb/blob/master/index.js
93769   *
93770   *  Utility function for building an impulse response
93771   *  based on the module parameters.
93772   *
93773   *  @private
93774   */
93775  p5.Reverb.prototype._buildImpulse = function () {
93776    var rate = this.ac.sampleRate;
93777    var length = rate * this._seconds;
93778    var decay = this._decay;
93779    var impulse = this.ac.createBuffer(2, length, rate);
93780    var impulseL = impulse.getChannelData(0);
93781    var impulseR = impulse.getChannelData(1);
93782    var n, i;
93783    for (i = 0; i < length; i++) {
93784      n = this._reverse ? length - i : i;
93785      impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);
93786      impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);
93787    }
93788    this._setBuffer(impulse);
93789  };
93790  p5.Reverb.prototype.dispose = function () {
93791    Effect.prototype.dispose.apply(this);
93792    this._teardownConvolverNode();
93793  };
93794  // =======================================================================
93795  //                          *** p5.Convolver ***
93796  // =======================================================================
93797  /**
93798   *  <p>p5.Convolver extends p5.Reverb. It can emulate the sound of real
93799   *  physical spaces through a process called <a href="
93800   *  https://en.wikipedia.org/wiki/Convolution_reverb#Real_space_simulation">
93801   *  convolution</a>.</p>
93802   *
93803   *  <p>Convolution multiplies any audio input by an "impulse response"
93804   *  to simulate the dispersion of sound over time. The impulse response is
93805   *  generated from an audio file that you provide. One way to
93806   *  generate an impulse response is to pop a balloon in a reverberant space
93807   *  and record the echo. Convolution can also be used to experiment with
93808   *  sound.</p>
93809   *
93810   *  <p>Use the method <code>createConvolution(path)</code> to instantiate a
93811   *  p5.Convolver with a path to your impulse response audio file.</p>
93812   *
93813   *  @class p5.Convolver
93814   *  @extends p5.Effect
93815   *  @constructor
93816   *  @param  {String}   path     path to a sound file
93817   *  @param  {Function} [callback] function to call when loading succeeds
93818   *  @param  {Function} [errorCallback] function to call if loading fails.
93819   *                                     This function will receive an error or
93820   *                                     XMLHttpRequest object with information
93821   *                                     about what went wrong.
93822   *  @example
93823   *  <div><code>
93824   *  var cVerb, sound;
93825   *  function preload() {
93826   *    // We have both MP3 and OGG versions of all sound assets
93827   *    soundFormats('ogg', 'mp3');
93828   *
93829   *    // Try replacing 'bx-spring' with other soundfiles like
93830   *    // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'
93831   *    cVerb = createConvolver('assets/bx-spring.mp3');
93832   *
93833   *    // Try replacing 'Damscray_DancingTiger' with
93834   *    // 'beat', 'doorbell', lucky_dragons_-_power_melody'
93835   *    sound = loadSound('assets/Damscray_DancingTiger.mp3');
93836   *  }
93837   *
93838   *  function setup() {
93839   *    // disconnect from master output...
93840   *    sound.disconnect();
93841   *
93842   *    // ...and process with cVerb
93843   *    // so that we only hear the convolution
93844   *    cVerb.process(sound);
93845   *
93846   *    sound.play();
93847   *  }
93848   *  </code></div>
93849   */
93850  p5.Convolver = function (path, callback, errorCallback) {
93851    p5.Reverb.call(this);
93852    /**
93853     *  Internally, the p5.Convolver uses the a
93854     *  <a href="http://www.w3.org/TR/webaudio/#ConvolverNode">
93855     *  Web Audio Convolver Node</a>.
93856     *
93857     *  @property {ConvolverNode} convolverNode
93858     */
93859    this._initConvolverNode();
93860    // otherwise, Safari distorts
93861    this.input.gain.value = 0.5;
93862    if (path) {
93863      this.impulses = [];
93864      this._loadBuffer(path, callback, errorCallback);
93865    } else {
93866      // parameters
93867      this._seconds = 3;
93868      this._decay = 2;
93869      this._reverse = false;
93870      this._buildImpulse();
93871    }
93872  };
93873  p5.Convolver.prototype = Object.create(p5.Reverb.prototype);
93874  p5.prototype.registerPreloadMethod('createConvolver', p5.prototype);
93875  /**
93876   *  Create a p5.Convolver. Accepts a path to a soundfile
93877   *  that will be used to generate an impulse response.
93878   *
93879   *  @method  createConvolver
93880   *  @param  {String}   path     path to a sound file
93881   *  @param  {Function} [callback] function to call if loading is successful.
93882   *                                The object will be passed in as the argument
93883   *                                to the callback function.
93884   *  @param  {Function} [errorCallback] function to call if loading is not successful.
93885   *                                A custom error will be passed in as the argument
93886   *                                to the callback function.
93887   *  @return {p5.Convolver}
93888   *  @example
93889   *  <div><code>
93890   *  var cVerb, sound;
93891   *  function preload() {
93892   *    // We have both MP3 and OGG versions of all sound assets
93893   *    soundFormats('ogg', 'mp3');
93894   *
93895   *    // Try replacing 'bx-spring' with other soundfiles like
93896   *    // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox'
93897   *    cVerb = createConvolver('assets/bx-spring.mp3');
93898   *
93899   *    // Try replacing 'Damscray_DancingTiger' with
93900   *    // 'beat', 'doorbell', lucky_dragons_-_power_melody'
93901   *    sound = loadSound('assets/Damscray_DancingTiger.mp3');
93902   *  }
93903   *
93904   *  function setup() {
93905   *    // disconnect from master output...
93906   *    sound.disconnect();
93907   *
93908   *    // ...and process with cVerb
93909   *    // so that we only hear the convolution
93910   *    cVerb.process(sound);
93911   *
93912   *    sound.play();
93913   *  }
93914   *  </code></div>
93915   */
93916  p5.prototype.createConvolver = function (path, callback, errorCallback) {
93917    // if loading locally without a server
93918    if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {
93919      alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');
93920    }
93921    var self = this;
93922    var cReverb = new p5.Convolver(path, function (buffer) {
93923      if (typeof callback === 'function') {
93924        callback(buffer);
93925      }
93926      if (typeof self._decrementPreload === 'function') {
93927        self._decrementPreload();
93928      }
93929    }, errorCallback);
93930    cReverb.impulses = [];
93931    return cReverb;
93932  };
93933  /**
93934   *  Private method to load a buffer as an Impulse Response,
93935   *  assign it to the convolverNode, and add to the Array of .impulses.
93936   *
93937   *  @param   {String}   path
93938   *  @param   {Function} callback
93939   *  @param   {Function} errorCallback
93940   *  @private
93941   */
93942  p5.Convolver.prototype._loadBuffer = function (path, callback, errorCallback) {
93943    var path = p5.prototype._checkFileFormats(path);
93944    var self = this;
93945    var errorTrace = new Error().stack;
93946    var ac = p5.prototype.getAudioContext();
93947    var request = new XMLHttpRequest();
93948    request.open('GET', path, true);
93949    request.responseType = 'arraybuffer';
93950    request.onload = function () {
93951      if (request.status === 200) {
93952        // on success loading file:
93953        ac.decodeAudioData(request.response, function (buff) {
93954          var buffer = {};
93955          var chunks = path.split('/');
93956          buffer.name = chunks[chunks.length - 1];
93957          buffer.audioBuffer = buff;
93958          self.impulses.push(buffer);
93959          self._setBuffer(buffer.audioBuffer);
93960          if (callback) {
93961            callback(buffer);
93962          }
93963        }, // error decoding buffer. "e" is undefined in Chrome 11/22/2015
93964        function () {
93965          var err = new CustomError('decodeAudioData', errorTrace, self.url);
93966          var msg = 'AudioContext error at decodeAudioData for ' + self.url;
93967          if (errorCallback) {
93968            err.msg = msg;
93969            errorCallback(err);
93970          } else {
93971            console.error(msg + '\n The error stack trace includes: \n' + err.stack);
93972          }
93973        });
93974      } else {
93975        var err = new CustomError('loadConvolver', errorTrace, self.url);
93976        var msg = 'Unable to load ' + self.url + '. The request status was: ' + request.status + ' (' + request.statusText + ')';
93977        if (errorCallback) {
93978          err.message = msg;
93979          errorCallback(err);
93980        } else {
93981          console.error(msg + '\n The error stack trace includes: \n' + err.stack);
93982        }
93983      }
93984    };
93985    // if there is another error, aside from 404...
93986    request.onerror = function () {
93987      var err = new CustomError('loadConvolver', errorTrace, self.url);
93988      var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.';
93989      if (errorCallback) {
93990        err.message = msg;
93991        errorCallback(err);
93992      } else {
93993        console.error(msg + '\n The error stack trace includes: \n' + err.stack);
93994      }
93995    };
93996    request.send();
93997  };
93998  p5.Convolver.prototype.set = null;
93999  /**
94000   *  Connect a source to the reverb, and assign reverb parameters.
94001   *
94002   *  @method  process
94003   *  @param  {Object} src     p5.sound / Web Audio object with a sound
94004   *                           output.
94005   *  @example
94006   *  <div><code>
94007   *  var cVerb, sound;
94008   *  function preload() {
94009   *    soundFormats('ogg', 'mp3');
94010   *
94011   *    cVerb = createConvolver('assets/concrete-tunnel.mp3');
94012   *
94013   *    sound = loadSound('assets/beat.mp3');
94014   *  }
94015   *
94016   *  function setup() {
94017   *    // disconnect from master output...
94018   *    sound.disconnect();
94019   *
94020   *    // ...and process with (i.e. connect to) cVerb
94021   *    // so that we only hear the convolution
94022   *    cVerb.process(sound);
94023   *
94024   *    sound.play();
94025   *  }
94026   *  </code></div>
94027   */
94028  p5.Convolver.prototype.process = function (src) {
94029    src.connect(this.input);
94030  };
94031  /**
94032   *  If you load multiple impulse files using the .addImpulse method,
94033   *  they will be stored as Objects in this Array. Toggle between them
94034   *  with the <code>toggleImpulse(id)</code> method.
94035   *
94036   *  @property {Array} impulses
94037   */
94038  p5.Convolver.prototype.impulses = [];
94039  /**
94040   *  Load and assign a new Impulse Response to the p5.Convolver.
94041   *  The impulse is added to the <code>.impulses</code> array. Previous
94042   *  impulses can be accessed with the <code>.toggleImpulse(id)</code>
94043   *  method.
94044   *
94045   *  @method  addImpulse
94046   *  @param  {String}   path     path to a sound file
94047   *  @param  {Function} callback function (optional)
94048   *  @param  {Function} errorCallback function (optional)
94049   */
94050  p5.Convolver.prototype.addImpulse = function (path, callback, errorCallback) {
94051    // if loading locally without a server
94052    if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {
94053      alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');
94054    }
94055    this._loadBuffer(path, callback, errorCallback);
94056  };
94057  /**
94058   *  Similar to .addImpulse, except that the <code>.impulses</code>
94059   *  Array is reset to save memory. A new <code>.impulses</code>
94060   *  array is created with this impulse as the only item.
94061   *
94062   *  @method  resetImpulse
94063   *  @param  {String}   path     path to a sound file
94064   *  @param  {Function} callback function (optional)
94065   *  @param  {Function} errorCallback function (optional)
94066   */
94067  p5.Convolver.prototype.resetImpulse = function (path, callback, errorCallback) {
94068    // if loading locally without a server
94069    if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') {
94070      alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS');
94071    }
94072    this.impulses = [];
94073    this._loadBuffer(path, callback, errorCallback);
94074  };
94075  /**
94076   *  If you have used <code>.addImpulse()</code> to add multiple impulses
94077   *  to a p5.Convolver, then you can use this method to toggle between
94078   *  the items in the <code>.impulses</code> Array. Accepts a parameter
94079   *  to identify which impulse you wish to use, identified either by its
94080   *  original filename (String) or by its position in the <code>.impulses
94081   *  </code> Array (Number).<br/>
94082   *  You can access the objects in the .impulses Array directly. Each
94083   *  Object has two attributes: an <code>.audioBuffer</code> (type:
94084   *  Web Audio <a href="
94085   *  http://webaudio.github.io/web-audio-api/#the-audiobuffer-interface">
94086   *  AudioBuffer)</a> and a <code>.name</code>, a String that corresponds
94087   *  with the original filename.
94088   *
94089   *  @method toggleImpulse
94090   *  @param {String|Number} id Identify the impulse by its original filename
94091   *                            (String), or by its position in the
94092   *                            <code>.impulses</code> Array (Number).
94093   */
94094  p5.Convolver.prototype.toggleImpulse = function (id) {
94095    if (typeof id === 'number' && id < this.impulses.length) {
94096      this._setBuffer(this.impulses[id].audioBuffer);
94097    }
94098    if (typeof id === 'string') {
94099      for (var i = 0; i < this.impulses.length; i++) {
94100        if (this.impulses[i].name === id) {
94101          this._setBuffer(this.impulses[i].audioBuffer);
94102          break;
94103        }
94104      }
94105    }
94106  };
94107  p5.Convolver.prototype.dispose = function () {
94108    p5.Reverb.prototype.dispose.apply(this);
94109    // remove all the Impulse Response buffers
94110    for (var i in this.impulses) {
94111      if (this.impulses[i]) {
94112        this.impulses[i] = null;
94113      }
94114    }
94115  };
94116}(errorHandler, effect);
94117/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
94118var Tone_core_TimelineState;
94119Tone_core_TimelineState = function (Tone) {
94120  'use strict';
94121  Tone.TimelineState = function (initial) {
94122    Tone.Timeline.call(this);
94123    this._initial = initial;
94124  };
94125  Tone.extend(Tone.TimelineState, Tone.Timeline);
94126  Tone.TimelineState.prototype.getValueAtTime = function (time) {
94127    var event = this.get(time);
94128    if (event !== null) {
94129      return event.state;
94130    } else {
94131      return this._initial;
94132    }
94133  };
94134  Tone.TimelineState.prototype.setStateAtTime = function (state, time) {
94135    this.add({
94136      'state': state,
94137      'time': time
94138    });
94139  };
94140  return Tone.TimelineState;
94141}(Tone_core_Tone, Tone_core_Timeline);
94142/** Tone.js module by Yotam Mann, MIT License 2016  http://opensource.org/licenses/MIT **/
94143var Tone_core_Clock;
94144Tone_core_Clock = function (Tone) {
94145  'use strict';
94146  Tone.Clock = function () {
94147    Tone.Emitter.call(this);
94148    var options = this.optionsObject(arguments, [
94149      'callback',
94150      'frequency'
94151    ], Tone.Clock.defaults);
94152    this.callback = options.callback;
94153    this._nextTick = 0;
94154    this._lastState = Tone.State.Stopped;
94155    this.frequency = new Tone.TimelineSignal(options.frequency, Tone.Type.Frequency);
94156    this._readOnly('frequency');
94157    this.ticks = 0;
94158    this._state = new Tone.TimelineState(Tone.State.Stopped);
94159    this._boundLoop = this._loop.bind(this);
94160    this.context.on('tick', this._boundLoop);
94161  };
94162  Tone.extend(Tone.Clock, Tone.Emitter);
94163  Tone.Clock.defaults = {
94164    'callback': Tone.noOp,
94165    'frequency': 1,
94166    'lookAhead': 'auto'
94167  };
94168  Object.defineProperty(Tone.Clock.prototype, 'state', {
94169    get: function () {
94170      return this._state.getValueAtTime(this.now());
94171    }
94172  });
94173  Tone.Clock.prototype.start = function (time, offset) {
94174    time = this.toSeconds(time);
94175    if (this._state.getValueAtTime(time) !== Tone.State.Started) {
94176      this._state.add({
94177        'state': Tone.State.Started,
94178        'time': time,
94179        'offset': offset
94180      });
94181    }
94182    return this;
94183  };
94184  Tone.Clock.prototype.stop = function (time) {
94185    time = this.toSeconds(time);
94186    this._state.cancel(time);
94187    this._state.setStateAtTime(Tone.State.Stopped, time);
94188    return this;
94189  };
94190  Tone.Clock.prototype.pause = function (time) {
94191    time = this.toSeconds(time);
94192    if (this._state.getValueAtTime(time) === Tone.State.Started) {
94193      this._state.setStateAtTime(Tone.State.Paused, time);
94194    }
94195    return this;
94196  };
94197  Tone.Clock.prototype._loop = function () {
94198    var now = this.now();
94199    var lookAhead = this.context.lookAhead;
94200    var updateInterval = this.context.updateInterval;
94201    var lagCompensation = this.context.lag * 2;
94202    var loopInterval = now + lookAhead + updateInterval + lagCompensation;
94203    while (loopInterval > this._nextTick && this._state) {
94204      var currentState = this._state.getValueAtTime(this._nextTick);
94205      if (currentState !== this._lastState) {
94206        this._lastState = currentState;
94207        var event = this._state.get(this._nextTick);
94208        if (currentState === Tone.State.Started) {
94209          this._nextTick = event.time;
94210          if (!this.isUndef(event.offset)) {
94211            this.ticks = event.offset;
94212          }
94213          this.emit('start', event.time, this.ticks);
94214        } else if (currentState === Tone.State.Stopped) {
94215          this.ticks = 0;
94216          this.emit('stop', event.time);
94217        } else if (currentState === Tone.State.Paused) {
94218          this.emit('pause', event.time);
94219        }
94220      }
94221      var tickTime = this._nextTick;
94222      if (this.frequency) {
94223        this._nextTick += 1 / this.frequency.getValueAtTime(this._nextTick);
94224        if (currentState === Tone.State.Started) {
94225          this.callback(tickTime);
94226          this.ticks++;
94227        }
94228      }
94229    }
94230  };
94231  Tone.Clock.prototype.getStateAtTime = function (time) {
94232    time = this.toSeconds(time);
94233    return this._state.getValueAtTime(time);
94234  };
94235  Tone.Clock.prototype.dispose = function () {
94236    Tone.Emitter.prototype.dispose.call(this);
94237    this.context.off('tick', this._boundLoop);
94238    this._writable('frequency');
94239    this.frequency.dispose();
94240    this.frequency = null;
94241    this._boundLoop = null;
94242    this._nextTick = Infinity;
94243    this.callback = null;
94244    this._state.dispose();
94245    this._state = null;
94246  };
94247  return Tone.Clock;
94248}(Tone_core_Tone, Tone_signal_TimelineSignal, Tone_core_TimelineState, Tone_core_Emitter);
94249var metro;
94250'use strict';
94251metro = function () {
94252  var p5sound = master;
94253  // requires the Tone.js library's Clock (MIT license, Yotam Mann)
94254  // https://github.com/TONEnoTONE/Tone.js/
94255  var Clock = Tone_core_Clock;
94256  p5.Metro = function () {
94257    this.clock = new Clock({ 'callback': this.ontick.bind(this) });
94258    this.syncedParts = [];
94259    this.bpm = 120;
94260    // gets overridden by p5.Part
94261    this._init();
94262    this.prevTick = 0;
94263    this.tatumTime = 0;
94264    this.tickCallback = function () {
94265    };
94266  };
94267  p5.Metro.prototype.ontick = function (tickTime) {
94268    var elapsedTime = tickTime - this.prevTick;
94269    var secondsFromNow = tickTime - p5sound.audiocontext.currentTime;
94270    if (elapsedTime - this.tatumTime <= -0.02) {
94271      return;
94272    } else {
94273      // console.log('ok', this.syncedParts[0].phrases[0].name);
94274      this.prevTick = tickTime;
94275      // for all of the active things on the metro:
94276      var self = this;
94277      this.syncedParts.forEach(function (thisPart) {
94278        if (!thisPart.isPlaying)
94279          return;
94280        thisPart.incrementStep(secondsFromNow);
94281        // each synced source keeps track of its own beat number
94282        thisPart.phrases.forEach(function (thisPhrase) {
94283          var phraseArray = thisPhrase.sequence;
94284          var bNum = self.metroTicks % phraseArray.length;
94285          if (phraseArray[bNum] !== 0 && (self.metroTicks < phraseArray.length || !thisPhrase.looping)) {
94286            thisPhrase.callback(secondsFromNow, phraseArray[bNum]);
94287          }
94288        });
94289      });
94290      this.metroTicks += 1;
94291      this.tickCallback(secondsFromNow);
94292    }
94293  };
94294  p5.Metro.prototype.setBPM = function (bpm, rampTime) {
94295    var beatTime = 60 / (bpm * this.tatums);
94296    var now = p5sound.audiocontext.currentTime;
94297    this.tatumTime = beatTime;
94298    var rampTime = rampTime || 0;
94299    this.clock.frequency.setValueAtTime(this.clock.frequency.value, now);
94300    this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime);
94301    this.bpm = bpm;
94302  };
94303  p5.Metro.prototype.getBPM = function () {
94304    return this.clock.getRate() / this.tatums * 60;
94305  };
94306  p5.Metro.prototype._init = function () {
94307    this.metroTicks = 0;
94308  };
94309  // clear existing synced parts, add only this one
94310  p5.Metro.prototype.resetSync = function (part) {
94311    this.syncedParts = [part];
94312  };
94313  // push a new synced part to the array
94314  p5.Metro.prototype.pushSync = function (part) {
94315    this.syncedParts.push(part);
94316  };
94317  p5.Metro.prototype.start = function (timeFromNow) {
94318    var t = timeFromNow || 0;
94319    var now = p5sound.audiocontext.currentTime;
94320    this.clock.start(now + t);
94321    this.setBPM(this.bpm);
94322  };
94323  p5.Metro.prototype.stop = function (timeFromNow) {
94324    var t = timeFromNow || 0;
94325    var now = p5sound.audiocontext.currentTime;
94326    this.clock.stop(now + t);
94327  };
94328  p5.Metro.prototype.beatLength = function (tatums) {
94329    this.tatums = 1 / tatums / 4;
94330  };
94331}(master, Tone_core_Clock);
94332var looper;
94333'use strict';
94334looper = function () {
94335  var p5sound = master;
94336  var BPM = 120;
94337  /**
94338   *  Set the global tempo, in beats per minute, for all
94339   *  p5.Parts. This method will impact all active p5.Parts.
94340   *
94341   *  @method setBPM
94342   *  @param {Number} BPM      Beats Per Minute
94343   *  @param {Number} rampTime Seconds from now
94344   */
94345  p5.prototype.setBPM = function (bpm, rampTime) {
94346    BPM = bpm;
94347    for (var i in p5sound.parts) {
94348      if (p5sound.parts[i]) {
94349        p5sound.parts[i].setBPM(bpm, rampTime);
94350      }
94351    }
94352  };
94353  /**
94354   *  <p>A phrase is a pattern of musical events over time, i.e.
94355   *  a series of notes and rests.</p>
94356   *
94357   *  <p>Phrases must be added to a p5.Part for playback, and
94358   *  each part can play multiple phrases at the same time.
94359   *  For example, one Phrase might be a kick drum, another
94360   *  could be a snare, and another could be the bassline.</p>
94361   *
94362   *  <p>The first parameter is a name so that the phrase can be
94363   *  modified or deleted later. The callback is a a function that
94364   *  this phrase will call at every step—for example it might be
94365   *  called <code>playNote(value){}</code>. The array determines
94366   *  which value is passed into the callback at each step of the
94367   *  phrase. It can be numbers, an object with multiple numbers,
94368   *  or a zero (0) indicates a rest so the callback won't be called).</p>
94369   *
94370   *  @class p5.Phrase
94371   *  @constructor
94372   *  @param {String}   name     Name so that you can access the Phrase.
94373   *  @param {Function} callback The name of a function that this phrase
94374   *                             will call. Typically it will play a sound,
94375   *                             and accept two parameters: a time at which
94376   *                             to play the sound (in seconds from now),
94377   *                             and a value from the sequence array. The
94378   *                             time should be passed into the play() or
94379   *                             start() method to ensure precision.
94380   *  @param {Array}   sequence    Array of values to pass into the callback
94381   *                            at each step of the phrase.
94382   *  @example
94383   *  <div><code>
94384   *  var mySound, myPhrase, myPart;
94385   *  var pattern = [1,0,0,2,0,2,0,0];
94386   *  var msg = 'click to play';
94387   *
94388   *  function preload() {
94389   *    mySound = loadSound('assets/beatbox.mp3');
94390   *  }
94391   *
94392   *  function setup() {
94393   *    noStroke();
94394   *    fill(255);
94395   *    textAlign(CENTER);
94396   *    masterVolume(0.1);
94397   *
94398   *    myPhrase = new p5.Phrase('bbox', makeSound, pattern);
94399   *    myPart = new p5.Part();
94400   *    myPart.addPhrase(myPhrase);
94401   *    myPart.setBPM(60);
94402   *  }
94403   *
94404   *  function draw() {
94405   *    background(0);
94406   *    text(msg, width/2, height/2);
94407   *  }
94408   *
94409   *  function makeSound(time, playbackRate) {
94410   *    mySound.rate(playbackRate);
94411   *    mySound.play(time);
94412   *  }
94413   *
94414   *  function mouseClicked() {
94415   *    if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
94416   *      myPart.start();
94417   *      msg = 'playing pattern';
94418   *    }
94419   *  }
94420   *
94421   *  </code></div>
94422   */
94423  p5.Phrase = function (name, callback, sequence) {
94424    this.phraseStep = 0;
94425    this.name = name;
94426    this.callback = callback;
94427    /**
94428     * Array of values to pass into the callback
94429     * at each step of the phrase. Depending on the callback
94430     * function's requirements, these values may be numbers,
94431     * strings, or an object with multiple parameters.
94432     * Zero (0) indicates a rest.
94433     *
94434     * @property {Array} sequence
94435     */
94436    this.sequence = sequence;
94437  };
94438  /**
94439   *  <p>A p5.Part plays back one or more p5.Phrases. Instantiate a part
94440   *  with steps and tatums. By default, each step represents a 1/16th note.</p>
94441   *
94442   *  <p>See p5.Phrase for more about musical timing.</p>
94443   *
94444   *  @class p5.Part
94445   *  @constructor
94446   *  @param {Number} [steps]   Steps in the part
94447   *  @param {Number} [tatums] Divisions of a beat, e.g. use 1/4, or 0.25 for a quater note (default is 1/16, a sixteenth note)
94448   *  @example
94449   *  <div><code>
94450   *  var box, drum, myPart;
94451   *  var boxPat = [1,0,0,2,0,2,0,0];
94452   *  var drumPat = [0,1,1,0,2,0,1,0];
94453   *  var msg = 'click to play';
94454   *
94455   *  function preload() {
94456   *    box = loadSound('assets/beatbox.mp3');
94457   *    drum = loadSound('assets/drum.mp3');
94458   *  }
94459   *
94460   *  function setup() {
94461   *    noStroke();
94462   *    fill(255);
94463   *    textAlign(CENTER);
94464   *    masterVolume(0.1);
94465   *
94466   *    var boxPhrase = new p5.Phrase('box', playBox, boxPat);
94467   *    var drumPhrase = new p5.Phrase('drum', playDrum, drumPat);
94468   *    myPart = new p5.Part();
94469   *    myPart.addPhrase(boxPhrase);
94470   *    myPart.addPhrase(drumPhrase);
94471   *    myPart.setBPM(60);
94472   *    masterVolume(0.1);
94473   *  }
94474   *
94475   *  function draw() {
94476   *    background(0);
94477   *    text(msg, width/2, height/2);
94478   *  }
94479   *
94480   *  function playBox(time, playbackRate) {
94481   *    box.rate(playbackRate);
94482   *    box.play(time);
94483   *  }
94484   *
94485   *  function playDrum(time, playbackRate) {
94486   *    drum.rate(playbackRate);
94487   *    drum.play(time);
94488   *  }
94489   *
94490   *  function mouseClicked() {
94491   *    if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
94492   *      myPart.start();
94493   *      msg = 'playing part';
94494   *    }
94495   *  }
94496   *  </code></div>
94497   */
94498  p5.Part = function (steps, bLength) {
94499    this.length = steps || 0;
94500    // how many beats
94501    this.partStep = 0;
94502    this.phrases = [];
94503    this.isPlaying = false;
94504    this.noLoop();
94505    this.tatums = bLength || 0.0625;
94506    // defaults to quarter note
94507    this.metro = new p5.Metro();
94508    this.metro._init();
94509    this.metro.beatLength(this.tatums);
94510    this.metro.setBPM(BPM);
94511    p5sound.parts.push(this);
94512    this.callback = function () {
94513    };
94514  };
94515  /**
94516   *  Set the tempo of this part, in Beats Per Minute.
94517   *
94518   *  @method  setBPM
94519   *  @param {Number} BPM      Beats Per Minute
94520   *  @param {Number} [rampTime] Seconds from now
94521   */
94522  p5.Part.prototype.setBPM = function (tempo, rampTime) {
94523    this.metro.setBPM(tempo, rampTime);
94524  };
94525  /**
94526   *  Returns the tempo, in Beats Per Minute, of this part.
94527   *
94528   *  @method getBPM
94529   *  @return {Number}
94530   */
94531  p5.Part.prototype.getBPM = function () {
94532    return this.metro.getBPM();
94533  };
94534  /**
94535   *  Start playback of this part. It will play
94536   *  through all of its phrases at a speed
94537   *  determined by setBPM.
94538   *
94539   *  @method  start
94540   *  @param  {Number} [time] seconds from now
94541   */
94542  p5.Part.prototype.start = function (time) {
94543    if (!this.isPlaying) {
94544      this.isPlaying = true;
94545      this.metro.resetSync(this);
94546      var t = time || 0;
94547      this.metro.start(t);
94548    }
94549  };
94550  /**
94551   *  Loop playback of this part. It will begin
94552   *  looping through all of its phrases at a speed
94553   *  determined by setBPM.
94554   *
94555   *  @method  loop
94556   *  @param  {Number} [time] seconds from now
94557   */
94558  p5.Part.prototype.loop = function (time) {
94559    this.looping = true;
94560    // rest onended function
94561    this.onended = function () {
94562      this.partStep = 0;
94563    };
94564    var t = time || 0;
94565    this.start(t);
94566  };
94567  /**
94568   *  Tell the part to stop looping.
94569   *
94570   *  @method  noLoop
94571   */
94572  p5.Part.prototype.noLoop = function () {
94573    this.looping = false;
94574    // rest onended function
94575    this.onended = function () {
94576      this.stop();
94577    };
94578  };
94579  /**
94580   *  Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again.
94581   *
94582   *  @method  stop
94583   *  @param  {Number} [time] seconds from now
94584   */
94585  p5.Part.prototype.stop = function (time) {
94586    this.partStep = 0;
94587    this.pause(time);
94588  };
94589  /**
94590   *  Pause the part. Playback will resume
94591   *  from the current step.
94592   *
94593   *  @method  pause
94594   *  @param  {Number} time seconds from now
94595   */
94596  p5.Part.prototype.pause = function (time) {
94597    this.isPlaying = false;
94598    var t = time || 0;
94599    this.metro.stop(t);
94600  };
94601  /**
94602   *  Add a p5.Phrase to this Part.
94603   *
94604   *  @method  addPhrase
94605   *  @param {p5.Phrase}   phrase   reference to a p5.Phrase
94606   */
94607  p5.Part.prototype.addPhrase = function (name, callback, array) {
94608    var p;
94609    if (arguments.length === 3) {
94610      p = new p5.Phrase(name, callback, array);
94611    } else if (arguments[0] instanceof p5.Phrase) {
94612      p = arguments[0];
94613    } else {
94614      throw 'invalid input. addPhrase accepts name, callback, array or a p5.Phrase';
94615    }
94616    this.phrases.push(p);
94617    // reset the length if phrase is longer than part's existing length
94618    if (p.sequence.length > this.length) {
94619      this.length = p.sequence.length;
94620    }
94621  };
94622  /**
94623   *  Remove a phrase from this part, based on the name it was
94624   *  given when it was created.
94625   *
94626   *  @method  removePhrase
94627   *  @param  {String} phraseName
94628   */
94629  p5.Part.prototype.removePhrase = function (name) {
94630    for (var i in this.phrases) {
94631      if (this.phrases[i].name === name) {
94632        this.phrases.splice(i, 1);
94633      }
94634    }
94635  };
94636  /**
94637   *  Get a phrase from this part, based on the name it was
94638   *  given when it was created. Now you can modify its array.
94639   *
94640   *  @method  getPhrase
94641   *  @param  {String} phraseName
94642   */
94643  p5.Part.prototype.getPhrase = function (name) {
94644    for (var i in this.phrases) {
94645      if (this.phrases[i].name === name) {
94646        return this.phrases[i];
94647      }
94648    }
94649  };
94650  /**
94651   *  Find all sequences with the specified name, and replace their patterns with the specified array.
94652   *
94653   *  @method  replaceSequence
94654   *  @param  {String} phraseName
94655   *  @param  {Array} sequence  Array of values to pass into the callback
94656   *                            at each step of the phrase.
94657   */
94658  p5.Part.prototype.replaceSequence = function (name, array) {
94659    for (var i in this.phrases) {
94660      if (this.phrases[i].name === name) {
94661        this.phrases[i].sequence = array;
94662      }
94663    }
94664  };
94665  p5.Part.prototype.incrementStep = function (time) {
94666    if (this.partStep < this.length - 1) {
94667      this.callback(time);
94668      this.partStep += 1;
94669    } else {
94670      if (!this.looping && this.partStep === this.length - 1) {
94671        console.log('done');
94672        // this.callback(time);
94673        this.onended();
94674      }
94675    }
94676  };
94677  /**
94678   *  Set the function that will be called at every step. This will clear the previous function.
94679   *
94680   *  @method onStep
94681   *  @param  {Function} callback The name of the callback
94682   *                              you want to fire
94683   *                              on every beat/tatum.
94684   */
94685  p5.Part.prototype.onStep = function (callback) {
94686    this.callback = callback;
94687  };
94688  // ===============
94689  // p5.Score
94690  // ===============
94691  /**
94692   *  A Score consists of a series of Parts. The parts will
94693   *  be played back in order. For example, you could have an
94694   *  A part, a B part, and a C part, and play them back in this order
94695   *  <code>new p5.Score(a, a, b, a, c)</code>
94696   *
94697   *  @class p5.Score
94698   *  @constructor
94699   *  @param {p5.Part} [...parts] One or multiple parts, to be played in sequence.
94700   */
94701  p5.Score = function () {
94702    // for all of the arguments
94703    this.parts = [];
94704    this.currentPart = 0;
94705    var thisScore = this;
94706    for (var i in arguments) {
94707      if (arguments[i] && this.parts[i]) {
94708        this.parts[i] = arguments[i];
94709        this.parts[i].nextPart = this.parts[i + 1];
94710        this.parts[i].onended = function () {
94711          thisScore.resetPart(i);
94712          playNextPart(thisScore);
94713        };
94714      }
94715    }
94716    this.looping = false;
94717  };
94718  p5.Score.prototype.onended = function () {
94719    if (this.looping) {
94720      // this.resetParts();
94721      this.parts[0].start();
94722    } else {
94723      this.parts[this.parts.length - 1].onended = function () {
94724        this.stop();
94725        this.resetParts();
94726      };
94727    }
94728    this.currentPart = 0;
94729  };
94730  /**
94731   *  Start playback of the score.
94732   *
94733   *  @method  start
94734   */
94735  p5.Score.prototype.start = function () {
94736    this.parts[this.currentPart].start();
94737    this.scoreStep = 0;
94738  };
94739  /**
94740   *  Stop playback of the score.
94741   *
94742   *  @method  stop
94743   */
94744  p5.Score.prototype.stop = function () {
94745    this.parts[this.currentPart].stop();
94746    this.currentPart = 0;
94747    this.scoreStep = 0;
94748  };
94749  /**
94750   *  Pause playback of the score.
94751   *
94752   *  @method  pause
94753   */
94754  p5.Score.prototype.pause = function () {
94755    this.parts[this.currentPart].stop();
94756  };
94757  /**
94758   *  Loop playback of the score.
94759   *
94760   *  @method  loop
94761   */
94762  p5.Score.prototype.loop = function () {
94763    this.looping = true;
94764    this.start();
94765  };
94766  /**
94767   *  Stop looping playback of the score. If it
94768   *  is currently playing, this will go into effect
94769   *  after the current round of playback completes.
94770   *
94771   *  @method  noLoop
94772   */
94773  p5.Score.prototype.noLoop = function () {
94774    this.looping = false;
94775  };
94776  p5.Score.prototype.resetParts = function () {
94777    var self = this;
94778    this.parts.forEach(function (part) {
94779      self.resetParts[part];
94780    });
94781  };
94782  p5.Score.prototype.resetPart = function (i) {
94783    this.parts[i].stop();
94784    this.parts[i].partStep = 0;
94785    for (var p in this.parts[i].phrases) {
94786      if (this.parts[i]) {
94787        this.parts[i].phrases[p].phraseStep = 0;
94788      }
94789    }
94790  };
94791  /**
94792   *  Set the tempo for all parts in the score
94793   *
94794   *  @method setBPM
94795   *  @param {Number} BPM      Beats Per Minute
94796   *  @param {Number} rampTime Seconds from now
94797   */
94798  p5.Score.prototype.setBPM = function (bpm, rampTime) {
94799    for (var i in this.parts) {
94800      if (this.parts[i]) {
94801        this.parts[i].setBPM(bpm, rampTime);
94802      }
94803    }
94804  };
94805  function playNextPart(aScore) {
94806    aScore.currentPart++;
94807    if (aScore.currentPart >= aScore.parts.length) {
94808      aScore.scoreStep = 0;
94809      aScore.onended();
94810    } else {
94811      aScore.scoreStep = 0;
94812      aScore.parts[aScore.currentPart - 1].stop();
94813      aScore.parts[aScore.currentPart].start();
94814    }
94815  }
94816}(master);
94817var soundloop;
94818'use strict';
94819soundloop = function () {
94820  var p5sound = master;
94821  var Clock = Tone_core_Clock;
94822  /**
94823   * SoundLoop
94824   *
94825   * @class p5.SoundLoop
94826   * @constructor
94827   *
94828   * @param {Function} callback this function will be called on each iteration of theloop
94829   * @param {Number|String} [interval] amount of time or beats for each iteration of the loop
94830   *                                       defaults to 1
94831   *
94832   * @example
94833   * <div><code>
94834   * var click;
94835   * var looper1;
94836   * 
94837   * function preload() {
94838   *   click = loadSound('assets/drum.mp3');
94839   * }
94840   * 
94841   * function setup() {
94842   *   //the looper's callback is passed the timeFromNow
94843   *   //this value should be used as a reference point from 
94844   *   //which to schedule sounds 
94845   *   looper1 = new p5.SoundLoop(function(timeFromNow){
94846   *     click.play(timeFromNow);
94847   *     background(255 * (looper1.iterations % 2));
94848   *     }, 2);
94849   *
94850   *   //stop after 10 iteratios;
94851   *   looper1.maxIterations = 10;
94852   *   //start the loop
94853   *   looper1.start();
94854   * }
94855   * </code></div>
94856   */
94857  p5.SoundLoop = function (callback, interval) {
94858    this.callback = callback;
94859    /**
94860       * musicalTimeMode uses <a href = "https://github.com/Tonejs/Tone.js/wiki/Time">Tone.Time</a> convention
94861    * true if string, false if number
94862       * @property {Boolean} musicalTimeMode
94863       */
94864    this.musicalTimeMode = typeof this._interval === 'number' ? false : true;
94865    this._interval = interval || 1;
94866    /**
94867     * musicalTimeMode variables
94868     * modify these only when the interval is specified in musicalTime format as a string
94869     */
94870    this._timeSignature = 4;
94871    this._bpm = 60;
94872    this.isPlaying = false;
94873    /**
94874     * Set a limit to the number of loops to play. defaults to Infinity
94875     * @property {Number} maxIterations
94876     */
94877    this.maxIterations = Infinity;
94878    var self = this;
94879    this.clock = new Clock({
94880      'callback': function (time) {
94881        var timeFromNow = time - p5sound.audiocontext.currentTime;
94882        /**
94883         * Do not initiate the callback if timeFromNow is < 0
94884         * This ususually occurs for a few milliseconds when the page
94885         * is not fully loaded
94886         *
94887         * The callback should only be called until maxIterations is reached
94888         */
94889        if (timeFromNow > 0 && self.iterations <= self.maxIterations) {
94890          self.callback(timeFromNow);
94891        }
94892      },
94893      'frequency': this._calcFreq()
94894    });
94895  };
94896  /**
94897   * Start the loop
94898   * @method  start
94899   * @param  {Number} [timeFromNow] schedule a starting time
94900   */
94901  p5.SoundLoop.prototype.start = function (timeFromNow) {
94902    var t = timeFromNow || 0;
94903    var now = p5sound.audiocontext.currentTime;
94904    if (!this.isPlaying) {
94905      this.clock.start(now + t);
94906      this.isPlaying = true;
94907    }
94908  };
94909  /**
94910   * Stop the loop
94911   * @method  stop
94912   * @param  {Number} [timeFromNow] schedule a stopping time
94913   */
94914  p5.SoundLoop.prototype.stop = function (timeFromNow) {
94915    var t = timeFromNow || 0;
94916    var now = p5sound.audiocontext.currentTime;
94917    if (this.isPlaying) {
94918      this.clock.stop(now + t);
94919      this.isPlaying = false;
94920    }
94921  };
94922  /**
94923   * Pause the loop
94924   * @method pause
94925   * @param  {Number} [timeFromNow] schedule a pausing time
94926   */
94927  p5.SoundLoop.prototype.pause = function (timeFromNow) {
94928    var t = timeFromNow || 0;
94929    var now = p5sound.audiocontext.currentTime;
94930    if (this.isPlaying) {
94931      this.clock.pause(now + t);
94932      this.isPlaying = false;
94933    }
94934  };
94935  /**
94936   * Synchronize loops. Use this method to start two more more loops in synchronization
94937   * or to start a loop in synchronization with a loop that is already playing
94938   * This method will schedule the implicit loop in sync with the explicit master loop
94939   * i.e. loopToStart.syncedStart(loopToSyncWith)
94940   * 
94941   * @method  syncedStart
94942   * @param  {Object} otherLoop   a p5.SoundLoop to sync with 
94943   * @param  {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds
94944   */
94945  p5.SoundLoop.prototype.syncedStart = function (otherLoop, timeFromNow) {
94946    var t = timeFromNow || 0;
94947    var now = p5sound.audiocontext.currentTime;
94948    if (!otherLoop.isPlaying) {
94949      otherLoop.clock.start(now + t);
94950      otherLoop.isPlaying = true;
94951      this.clock.start(now + t);
94952      this.isPlaying = true;
94953    } else if (otherLoop.isPlaying) {
94954      var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime;
94955      this.clock.start(now + time);
94956      this.isPlaying = true;
94957    }
94958  };
94959  /**
94960   * Updates frequency value, reflected in next callback
94961   * @private
94962   * @method  _update
94963   */
94964  p5.SoundLoop.prototype._update = function () {
94965    this.clock.frequency.value = this._calcFreq();
94966  };
94967  /**
94968   * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature
94969   * @private
94970   * @method  _calcFreq
94971   * @return {Number} new clock frequency value
94972   */
94973  p5.SoundLoop.prototype._calcFreq = function () {
94974    //Seconds mode, bpm / timesignature has no effect
94975    if (typeof this._interval === 'number') {
94976      this.musicalTimeMode = false;
94977      return 1 / this._interval;
94978    } else if (typeof this._interval === 'string') {
94979      this.musicalTimeMode = true;
94980      return this._bpm / 60 / this._convertNotation(this._interval) * (this._timeSignature / 4);
94981    }
94982  };
94983  /**
94984   * Convert notation from musical time format to seconds
94985   * Uses <a href = "https://github.com/Tonejs/Tone.js/wiki/Time">Tone.Time</a> convention
94986   * @private
94987   * @method _convertNotation
94988   * @param  {String} value value to be converted
94989   * @return {Number}       converted value in seconds
94990   */
94991  p5.SoundLoop.prototype._convertNotation = function (value) {
94992    var type = value.slice(-1);
94993    value = Number(value.slice(0, -1));
94994    switch (type) {
94995    case 'm':
94996      return this._measure(value);
94997    case 'n':
94998      return this._note(value);
94999    default:
95000      console.warn('Specified interval is not formatted correctly. See Tone.js ' + 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time');
95001    }
95002  };
95003  /**
95004   * Helper conversion methods of measure and note
95005   * @private
95006   * @method  _measure
95007   * @private
95008   * @method  _note
95009   */
95010  p5.SoundLoop.prototype._measure = function (value) {
95011    return value * this._timeSignature;
95012  };
95013  p5.SoundLoop.prototype._note = function (value) {
95014    return this._timeSignature / value;
95015  };
95016  /**
95017   * Getters and Setters, setting any paramter will result in a change in the clock's
95018   * frequency, that will be reflected after the next callback
95019   * beats per minute (defaults to 60)
95020   * @property {Number} bpm
95021   */
95022  Object.defineProperty(p5.SoundLoop.prototype, 'bpm', {
95023    get: function () {
95024      return this._bpm;
95025    },
95026    set: function (bpm) {
95027      if (!this.musicalTimeMode) {
95028        console.warn('Changing the BPM in "seconds" mode has no effect. ' + 'BPM is only relevant in musicalTimeMode ' + 'when the interval is specified as a string ' + '("2n", "4n", "1m"...etc)');
95029      }
95030      this._bpm = bpm;
95031      this._update();
95032    }
95033  });
95034  /**
95035   * number of quarter notes in a measure (defaults to 4)
95036   * @property {Number} timeSignature
95037   */
95038  Object.defineProperty(p5.SoundLoop.prototype, 'timeSignature', {
95039    get: function () {
95040      return this._timeSignature;
95041    },
95042    set: function (timeSig) {
95043      if (!this.musicalTimeMode) {
95044        console.warn('Changing the timeSignature in "seconds" mode has no effect. ' + 'BPM is only relevant in musicalTimeMode ' + 'when the interval is specified as a string ' + '("2n", "4n", "1m"...etc)');
95045      }
95046      this._timeSignature = timeSig;
95047      this._update();
95048    }
95049  });
95050  /**
95051   * length of the loops interval
95052   * @property {Number|String} interval
95053   */
95054  Object.defineProperty(p5.SoundLoop.prototype, 'interval', {
95055    get: function () {
95056      return this._interval;
95057    },
95058    set: function (interval) {
95059      this.musicalTimeMode = typeof interval === 'Number' ? false : true;
95060      this._interval = interval;
95061      this._update();
95062    }
95063  });
95064  /**
95065   * how many times the callback has been called so far
95066   * @property {Number} iterations
95067   * @readonly
95068   */
95069  Object.defineProperty(p5.SoundLoop.prototype, 'iterations', {
95070    get: function () {
95071      return this.clock.ticks;
95072    }
95073  });
95074  return p5.SoundLoop;
95075}(master, Tone_core_Clock);
95076var compressor;
95077compressor = function () {
95078  'use strict';
95079  var p5sound = master;
95080  var Effect = effect;
95081  var CustomError = errorHandler;
95082  /**
95083   * Compressor is an audio effect class that performs dynamics compression
95084   * on an audio input source. This is a very commonly used technique in music
95085   * and sound production. Compression creates an overall louder, richer, 
95086   * and fuller sound by lowering the volume of louds and raising that of softs.
95087   * Compression can be used to avoid clipping (sound distortion due to 
95088   * peaks in volume) and is especially useful when many sounds are played 
95089   * at once. Compression can be used on indivudal sound sources in addition
95090   * to the master output.  
95091   *
95092   * This class extends <a href = "/reference/#/p5.Effect">p5.Effect</a>.  
95093   * Methods <a href = "/reference/#/p5.Effect/amp">amp()</a>, <a href = "/reference/#/p5.Effect/chain">chain()</a>, 
95094   * <a href = "/reference/#/p5.Effect/drywet">drywet()</a>, <a href = "/reference/#/p5.Effect/connect">connect()</a>, and 
95095   * <a href = "/reference/#/p5.Effect/disconnect">disconnect()</a> are available.
95096   *
95097   * @class p5.Compressor
95098   * @constructor
95099   * @extends p5.Effect
95100   *
95101   * 
95102   */
95103  p5.Compressor = function () {
95104    Effect.call(this);
95105    /**
95106       * The p5.Compressor is built with a <a href="https://www.w3.org/TR/webaudio/#the-dynamicscompressornode-interface" 
95107     *   target="_blank" title="W3 spec for Dynamics Compressor Node">Web Audio Dynamics Compressor Node
95108     *   </a>
95109       * @property {AudioNode} compressor 
95110       */
95111    this.compressor = this.ac.createDynamicsCompressor();
95112    this.input.connect(this.compressor);
95113    this.compressor.connect(this.wet);
95114  };
95115  p5.Compressor.prototype = Object.create(Effect.prototype);
95116  /**
95117  * Performs the same function as .connect, but also accepts
95118  * optional parameters to set compressor's audioParams
95119  * @method process 
95120  *
95121  * @param {Object} src         Sound source to be connected
95122  * 
95123  * @param {Number} [attack]     The amount of time (in seconds) to reduce the gain by 10dB,
95124  *                            default = .003, range 0 - 1
95125  * @param {Number} [knee]       A decibel value representing the range above the 
95126  *                            threshold where the curve smoothly transitions to the "ratio" portion.
95127  *                            default = 30, range 0 - 40
95128  * @param {Number} [ratio]      The amount of dB change in input for a 1 dB change in output
95129  *                            default = 12, range 1 - 20
95130  * @param {Number} [threshold]  The decibel value above which the compression will start taking effect
95131  *                            default = -24, range -100 - 0
95132  * @param {Number} [release]    The amount of time (in seconds) to increase the gain by 10dB
95133  *                            default = .25, range 0 - 1
95134  */
95135  p5.Compressor.prototype.process = function (src, attack, knee, ratio, threshold, release) {
95136    src.connect(this.input);
95137    this.set(attack, knee, ratio, threshold, release);
95138  };
95139  /**
95140   * Set the paramters of a compressor. 
95141   * @method  set
95142   * @param {Number} attack     The amount of time (in seconds) to reduce the gain by 10dB,
95143   *                            default = .003, range 0 - 1
95144   * @param {Number} knee       A decibel value representing the range above the 
95145   *                            threshold where the curve smoothly transitions to the "ratio" portion.
95146   *                            default = 30, range 0 - 40
95147   * @param {Number} ratio      The amount of dB change in input for a 1 dB change in output
95148   *                            default = 12, range 1 - 20
95149   * @param {Number} threshold  The decibel value above which the compression will start taking effect
95150   *                            default = -24, range -100 - 0
95151   * @param {Number} release    The amount of time (in seconds) to increase the gain by 10dB
95152   *                            default = .25, range 0 - 1
95153   */
95154  p5.Compressor.prototype.set = function (attack, knee, ratio, threshold, release) {
95155    if (typeof attack !== 'undefined') {
95156      this.attack(attack);
95157    }
95158    if (typeof knee !== 'undefined') {
95159      this.knee(knee);
95160    }
95161    if (typeof ratio !== 'undefined') {
95162      this.ratio(ratio);
95163    }
95164    if (typeof threshold !== 'undefined') {
95165      this.threshold(threshold);
95166    }
95167    if (typeof release !== 'undefined') {
95168      this.release(release);
95169    }
95170  };
95171  /**
95172   * Get current attack or set value w/ time ramp
95173   * 
95174   * 
95175   * @method attack
95176   * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB,
95177   *                          default = .003, range 0 - 1
95178   * @param {Number} [time]  Assign time value to schedule the change in value
95179   */
95180  p5.Compressor.prototype.attack = function (attack, time) {
95181    var t = time || 0;
95182    if (typeof attack == 'number') {
95183      this.compressor.attack.value = attack;
95184      this.compressor.attack.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
95185      this.compressor.attack.linearRampToValueAtTime(attack, this.ac.currentTime + 0.02 + t);
95186    } else if (typeof attack !== 'undefined') {
95187      attack.connect(this.compressor.attack);
95188    }
95189    return this.compressor.attack.value;
95190  };
95191  /**
95192   * Get current knee or set value w/ time ramp
95193   * 
95194   * @method knee
95195   * @param {Number} [knee] A decibel value representing the range above the 
95196   *                        threshold where the curve smoothly transitions to the "ratio" portion.
95197   *                        default = 30, range 0 - 40
95198   * @param {Number} [time]  Assign time value to schedule the change in value
95199   */
95200  p5.Compressor.prototype.knee = function (knee, time) {
95201    var t = time || 0;
95202    if (typeof knee == 'number') {
95203      this.compressor.knee.value = knee;
95204      this.compressor.knee.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
95205      this.compressor.knee.linearRampToValueAtTime(knee, this.ac.currentTime + 0.02 + t);
95206    } else if (typeof knee !== 'undefined') {
95207      knee.connect(this.compressor.knee);
95208    }
95209    return this.compressor.knee.value;
95210  };
95211  /**
95212   * Get current ratio or set value w/ time ramp
95213   * @method ratio
95214   *
95215   * @param {Number} [ratio]      The amount of dB change in input for a 1 dB change in output
95216   *                            default = 12, range 1 - 20 
95217   * @param {Number} [time]  Assign time value to schedule the change in value
95218   */
95219  p5.Compressor.prototype.ratio = function (ratio, time) {
95220    var t = time || 0;
95221    if (typeof ratio == 'number') {
95222      this.compressor.ratio.value = ratio;
95223      this.compressor.ratio.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
95224      this.compressor.ratio.linearRampToValueAtTime(ratio, this.ac.currentTime + 0.02 + t);
95225    } else if (typeof ratio !== 'undefined') {
95226      ratio.connect(this.compressor.ratio);
95227    }
95228    return this.compressor.ratio.value;
95229  };
95230  /**
95231   * Get current threshold or set value w/ time ramp
95232   * @method threshold
95233   *
95234   * @param {Number} threshold  The decibel value above which the compression will start taking effect
95235   *                            default = -24, range -100 - 0
95236   * @param {Number} [time]  Assign time value to schedule the change in value
95237   */
95238  p5.Compressor.prototype.threshold = function (threshold, time) {
95239    var t = time || 0;
95240    if (typeof threshold == 'number') {
95241      this.compressor.threshold.value = threshold;
95242      this.compressor.threshold.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
95243      this.compressor.threshold.linearRampToValueAtTime(threshold, this.ac.currentTime + 0.02 + t);
95244    } else if (typeof threshold !== 'undefined') {
95245      threshold.connect(this.compressor.threshold);
95246    }
95247    return this.compressor.threshold.value;
95248  };
95249  /**
95250   * Get current release or set value w/ time ramp
95251   * @method release
95252   *
95253   * @param {Number} release    The amount of time (in seconds) to increase the gain by 10dB
95254   *                            default = .25, range 0 - 1
95255   *
95256   * @param {Number} [time]  Assign time value to schedule the change in value
95257   */
95258  p5.Compressor.prototype.release = function (release, time) {
95259    var t = time || 0;
95260    if (typeof release == 'number') {
95261      this.compressor.release.value = release;
95262      this.compressor.release.cancelScheduledValues(this.ac.currentTime + 0.01 + t);
95263      this.compressor.release.linearRampToValueAtTime(release, this.ac.currentTime + 0.02 + t);
95264    } else if (typeof number !== 'undefined') {
95265      release.connect(this.compressor.release);
95266    }
95267    return this.compressor.release.value;
95268  };
95269  /**
95270   * Return the current reduction value
95271   *
95272   * @method reduction
95273   * @return {Number} Value of the amount of gain reduction that is applied to the signal
95274   */
95275  p5.Compressor.prototype.reduction = function () {
95276    return this.compressor.reduction.value;
95277  };
95278  p5.Compressor.prototype.dispose = function () {
95279    Effect.prototype.dispose.apply(this);
95280    if (this.compressor) {
95281      this.compressor.disconnect();
95282      delete this.compressor;
95283    }
95284  };
95285  return p5.Compressor;
95286}(master, effect, errorHandler);
95287var soundRecorder;
95288'use strict';
95289soundRecorder = function () {
95290  // inspiration: recorder.js, Tone.js & typedarray.org
95291  var p5sound = master;
95292  var convertToWav = helpers.convertToWav;
95293  var ac = p5sound.audiocontext;
95294  /**
95295   *  <p>
95295Record sounds for playback and/or to save as a .wav file.
95296   *  The p5.SoundRecorder records all sound output from your sketch,
95297   *  or can be assigned a specific source with setInput().</p>
95298   *  <p>The record() method accepts a p5.SoundFile as a parameter.
95299   *  When playback is stopped (either after the given amount of time,
95300   *  or with the stop() method), the p5.SoundRecorder will send its
95301   *  recording to that p5.SoundFile for playback.</p>
95302   *
95303   *  @class p5.SoundRecorder
95304   *  @constructor
95305   *  @example
95306   *  <div><code>
95307   *  var mic, recorder, soundFile;
95308   *  var state = 0;
95309   *
95310   *  function setup() {
95311   *    background(200);
95312   *    // create an audio in
95313   *    mic = new p5.AudioIn();
95314   *
95315   *    // prompts user to enable their browser mic
95316   *    mic.start();
95317   *
95318   *    // create a sound recorder
95319   *    recorder = new p5.SoundRecorder();
95320   *
95321   *    // connect the mic to the recorder
95322   *    recorder.setInput(mic);
95323   *
95324   *    // this sound file will be used to
95325   *    // playback & save the recording
95326   *    soundFile = new p5.SoundFile();
95327   *
95328   *    text('keyPress to record', 20, 20);
95329   *  }
95330   *
95331   *  function keyPressed() {
95332   *    // make sure user enabled the mic
95333   *    if (state === 0 && mic.enabled) {
95334   *
95335   *      // record to our p5.SoundFile
95336   *      recorder.record(soundFile);
95337   *
95338   *      background(255,0,0);
95339   *      text('Recording!', 20, 20);
95340   *      state++;
95341   *    }
95342   *    else if (state === 1) {
95343   *      background(0,255,0);
95344   *
95345   *      // stop recorder and
95346   *      // send result to soundFile
95347   *      recorder.stop();
95348   *
95349   *      text('Stopped', 20, 20);
95350   *      state++;
95351   *    }
95352   *
95353   *    else if (state === 2) {
95354   *      soundFile.play(); // play the result!
95355   *      save(soundFile, 'mySound.wav');
95356   *      state++;
95357   *    }
95358   *  }
95359   *  </div></code>
95360   */
95361  p5.SoundRecorder = function () {
95362    this.input = ac.createGain();
95363    this.output = ac.createGain();
95364    this.recording = false;
95365    this.bufferSize = 1024;
95366    this._channels = 2;
95367    // stereo (default)
95368    this._clear();
95369    // initialize variables
95370    this._jsNode = ac.createScriptProcessor(this.bufferSize, this._channels, 2);
95371    this._jsNode.onaudioprocess = this._audioprocess.bind(this);
95372    /**
95373     *  callback invoked when the recording is over
95374     *  @private
95375     *  @type Function(Float32Array)
95376     */
95377    this._callback = function () {
95378    };
95379    // connections
95380    this._jsNode.connect(p5.soundOut._silentNode);
95381    this.setInput();
95382    // add this p5.SoundFile to the soundArray
95383    p5sound.soundArray.push(this);
95384  };
95385  /**
95386   *  Connect a specific device to the p5.SoundRecorder.
95387   *  If no parameter is given, p5.SoundRecorer will record
95388   *  all audible p5.sound from your sketch.
95389   *
95390   *  @method  setInput
95391   *  @param {Object} [unit] p5.sound object or a web audio unit
95392   *                         that outputs sound
95393   */
95394  p5.SoundRecorder.prototype.setInput = function (unit) {
95395    this.input.disconnect();
95396    this.input = null;
95397    this.input = ac.createGain();
95398    this.input.connect(this._jsNode);
95399    this.input.connect(this.output);
95400    if (unit) {
95401      unit.connect(this.input);
95402    } else {
95403      p5.soundOut.output.connect(this.input);
95404    }
95405  };
95406  /**
95407   *  Start recording. To access the recording, provide
95408   *  a p5.SoundFile as the first parameter. The p5.SoundRecorder
95409   *  will send its recording to that p5.SoundFile for playback once
95410   *  recording is complete. Optional parameters include duration
95411   *  (in seconds) of the recording, and a callback function that
95412   *  will be called once the complete recording has been
95413   *  transfered to the p5.SoundFile.
95414   *
95415   *  @method  record
95416   *  @param  {p5.SoundFile}   soundFile    p5.SoundFile
95417   *  @param  {Number}   [duration] Time (in seconds)
95418   *  @param  {Function} [callback] The name of a function that will be
95419   *                                called once the recording completes
95420   */
95421  p5.SoundRecorder.prototype.record = function (sFile, duration, callback) {
95422    this.recording = true;
95423    if (duration) {
95424      this.sampleLimit = Math.round(duration * ac.sampleRate);
95425    }
95426    if (sFile && callback) {
95427      this._callback = function () {
95428        this.buffer = this._getBuffer();
95429        sFile.setBuffer(this.buffer);
95430        callback();
95431      };
95432    } else if (sFile) {
95433      this._callback = function () {
95434        this.buffer = this._getBuffer();
95435        sFile.setBuffer(this.buffer);
95436      };
95437    }
95438  };
95439  /**
95440   *  Stop the recording. Once the recording is stopped,
95441   *  the results will be sent to the p5.SoundFile that
95442   *  was given on .record(), and if a callback function
95443   *  was provided on record, that function will be called.
95444   *
95445   *  @method  stop
95446   */
95447  p5.SoundRecorder.prototype.stop = function () {
95448    this.recording = false;
95449    this._callback();
95450    this._clear();
95451  };
95452  p5.SoundRecorder.prototype._clear = function () {
95453    this._leftBuffers = [];
95454    this._rightBuffers = [];
95455    this.recordedSamples = 0;
95456    this.sampleLimit = null;
95457  };
95458  /**
95459   *  internal method called on audio process
95460   *
95461   *  @private
95462   *  @param   {AudioProcessorEvent} event
95463   */
95464  p5.SoundRecorder.prototype._audioprocess = function (event) {
95465    if (this.recording === false) {
95466      return;
95467    } else if (this.recording === true) {
95468      // if we are past the duration, then stop... else:
95469      if (this.sampleLimit && this.recordedSamples >= this.sampleLimit) {
95470        this.stop();
95471      } else {
95472        // get channel data
95473        var left = event.inputBuffer.getChannelData(0);
95474        var right = event.inputBuffer.getChannelData(1);
95475        // clone the samples
95476        this._leftBuffers.push(new Float32Array(left));
95477        this._rightBuffers.push(new Float32Array(right));
95478        this.recordedSamples += this.bufferSize;
95479      }
95480    }
95481  };
95482  p5.SoundRecorder.prototype._getBuffer = function () {
95483    var buffers = [];
95484    buffers.push(this._mergeBuffers(this._leftBuffers));
95485    buffers.push(this._mergeBuffers(this._rightBuffers));
95486    return buffers;
95487  };
95488  p5.SoundRecorder.prototype._mergeBuffers = function (channelBuffer) {
95489    var result = new Float32Array(this.recordedSamples);
95490    var offset = 0;
95491    var lng = channelBuffer.length;
95492    for (var i = 0; i < lng; i++) {
95493      var buffer = channelBuffer[i];
95494      result.set(buffer, offset);
95495      offset += buffer.length;
95496    }
95497    return result;
95498  };
95499  p5.SoundRecorder.prototype.dispose = function () {
95500    this._clear();
95501    // remove reference from soundArray
95502    var index = p5sound.soundArray.indexOf(this);
95503    p5sound.soundArray.splice(index, 1);
95504    this._callback = function () {
95505    };
95506    if (this.input) {
95507      this.input.disconnect();
95508    }
95509    this.input = null;
95510    this._jsNode = null;
95511  };
95512  /**
95513   * Save a p5.SoundFile as a .wav file. The browser will prompt the user
95514   * to download the file to their device.
95515   * For uploading audio to a server, use
95516   * <a href="/docs/reference/#/p5.SoundFile/saveBlob">`p5.SoundFile.saveBlob`</a>.
95517   *
95518   *  @for p5
95519   *  @method saveSound
95520   *  @param  {p5.SoundFile} soundFile p5.SoundFile that you wish to save
95521   *  @param  {String} fileName      name of the resulting .wav file.
95522   */
95523  // add to p5.prototype as this is used by the p5 `save()` method.
95524  p5.prototype.saveSound = function (soundFile, fileName) {
95525    const dataView = convertToWav(soundFile.buffer);
95526    p5.prototype.writeFile([dataView], fileName, 'wav');
95527  };
95528}(master, helpers);
95529var peakdetect;
95530'use strict';
95531peakdetect = function () {
95532  /**
95533   *  <p>PeakDetect works in conjunction with p5.FFT to
95534   *  look for onsets in some or all of the frequency spectrum.
95535   *  </p>
95536   *  <p>
95537   *  To use p5.PeakDetect, call <code>update</code> in the draw loop
95538   *  and pass in a p5.FFT object.
95539   *  </p>
95540   *  <p>
95541   *  You can listen for a specific part of the frequency spectrum by
95542   *  setting the range between <code>freq1</code> and <code>freq2</code>.
95543   *  </p>
95544   *
95545   *  <p><code>threshold</code> is the threshold for detecting a peak,
95546   *  scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud
95547   *  as 1.0.</p>
95548   *
95549   *  <p>
95550   *  The update method is meant to be run in the draw loop, and
95551   *  <b>frames</b> determines how many loops must pass before
95552   *  another peak can be detected.
95553   *  For example, if the frameRate() = 60, you could detect the beat of a
95554   *  120 beat-per-minute song with this equation:
95555   *  <code> framesPerPeak = 60 / (estimatedBPM / 60 );</code>
95556   *  </p>
95557   *
95558   *  <p>
95559   *  Based on example contribtued by @b2renger, and a simple beat detection
95560   *  explanation by <a
95561   *  href="http://www.airtightinteractive.com/2013/10/making-audio-reactive-visuals/"
95562   *  target="_blank">Felix Turner</a>.
95563   *  </p>
95564   *
95565   *  @class  p5.PeakDetect
95566   *  @constructor
95567   *  @param {Number} [freq1]     lowFrequency - defaults to 20Hz
95568   *  @param {Number} [freq2]     highFrequency - defaults to 20000 Hz
95569   *  @param {Number} [threshold] Threshold for detecting a beat between 0 and 1
95570   *                            scaled logarithmically where 0.1 is 1/2 the loudness
95571   *                            of 1.0. Defaults to 0.35.
95572   *  @param {Number} [framesPerPeak]     Defaults to 20.
95573   *  @example
95574   *  <div><code>
95575   *
95576   *  var cnv, soundFile, fft, peakDetect;
95577   *  var ellipseWidth = 10;
95578   *
95579   *  function preload() {
95580   *    soundFile = loadSound('assets/beat.mp3');
95581   *  }
95582   *
95583   *  function setup() {
95584   *    background(0);
95585   *    noStroke();
95586   *    fill(255);
95587   *    textAlign(CENTER);
95588   *
95589   *    // p5.PeakDetect requires a p5.FFT
95590   *    fft = new p5.FFT();
95591   *    peakDetect = new p5.PeakDetect();
95592   *  }
95593   *
95594   *  function draw() {
95595   *    background(0);
95596   *    text('click to play/pause', width/2, height/2);
95597   *
95598   *    // peakDetect accepts an fft post-analysis
95599   *    fft.analyze();
95600   *    peakDetect.update(fft);
95601   *
95602   *    if ( peakDetect.isDetected ) {
95603   *      ellipseWidth = 50;
95604   *    } else {
95605   *      ellipseWidth *= 0.95;
95606   *    }
95607   *
95608   *    ellipse(width/2, height/2, ellipseWidth, ellipseWidth);
95609   *  }
95610   *
95611   *  // toggle play/stop when canvas is clicked
95612   *  function mouseClicked() {
95613   *    if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
95614   *      if (soundFile.isPlaying() ) {
95615   *        soundFile.stop();
95616   *      } else {
95617   *        soundFile.play();
95618   *      }
95619   *    }
95620   *  }
95621   *  </code></div>
95622   */
95623  p5.PeakDetect = function (freq1, freq2, threshold, _framesPerPeak) {
95624    // framesPerPeak determines how often to look for a beat.
95625    // If a beat is provided, try to look for a beat based on bpm
95626    this.framesPerPeak = _framesPerPeak || 20;
95627    this.framesSinceLastPeak = 0;
95628    this.decayRate = 0.95;
95629    this.threshold = threshold || 0.35;
95630    this.cutoff = 0;
95631    // how much to increase the cutoff
95632    // TO DO: document this / figure out how to make it accessible
95633    this.cutoffMult = 1.5;
95634    this.energy = 0;
95635    this.penergy = 0;
95636    // TO DO: document this property / figure out how to make it accessible
95637    this.currentValue = 0;
95638    /**
95639     *  isDetected is set to true when a peak is detected.
95640     *
95641     *  @attribute isDetected {Boolean}
95642     *  @default  false
95643     */
95644    this.isDetected = false;
95645    this.f1 = freq1 || 40;
95646    this.f2 = freq2 || 20000;
95647    // function to call when a peak is detected
95648    this._onPeak = function () {
95649    };
95650  };
95651  /**
95652   *  The update method is run in the draw loop.
95653   *
95654   *  Accepts an FFT object. You must call .analyze()
95655   *  on the FFT object prior to updating the peakDetect
95656   *  because it relies on a completed FFT analysis.
95657   *
95658   *  @method  update
95659   *  @param  {p5.FFT} fftObject A p5.FFT object
95660   */
95661  p5.PeakDetect.prototype.update = function (fftObject) {
95662    var nrg = this.energy = fftObject.getEnergy(this.f1, this.f2) / 255;
95663    if (nrg > this.cutoff && nrg > this.threshold && nrg - this.penergy > 0) {
95664      // trigger callback
95665      this._onPeak();
95666      this.isDetected = true;
95667      // debounce
95668      this.cutoff = nrg * this.cutoffMult;
95669      this.framesSinceLastPeak = 0;
95670    } else {
95671      this.isDetected = false;
95672      if (this.framesSinceLastPeak <= this.framesPerPeak) {
95673        this.framesSinceLastPeak++;
95674      } else {
95675        this.cutoff *= this.decayRate;
95676        this.cutoff = Math.max(this.cutoff, this.threshold);
95677      }
95678    }
95679    this.currentValue = nrg;
95680    this.penergy = nrg;
95681  };
95682  /**
95683   *  onPeak accepts two arguments: a function to call when
95684   *  a peak is detected. The value of the peak,
95685   *  between 0.0 and 1.0, is passed to the callback.
95686   *
95687   *  @method  onPeak
95688   *  @param  {Function} callback Name of a function that will
95689   *                              be called when a peak is
95690   *                              detected.
95691   *  @param  {Object}   [val]    Optional value to pass
95692   *                              into the function when
95693   *                              a peak is detected.
95694   *  @example
95695   *  <div><code>
95696   *  var cnv, soundFile, fft, peakDetect;
95697   *  var ellipseWidth = 0;
95698   *
95699   *  function preload() {
95700   *    soundFile = loadSound('assets/beat.mp3');
95701   *  }
95702   *
95703   *  function setup() {
95704   *    cnv = createCanvas(100,100);
95705   *    textAlign(CENTER);
95706   *
95707   *    fft = new p5.FFT();
95708   *    peakDetect = new p5.PeakDetect();
95709   *
95710   *    setupSound();
95711   *
95712   *    // when a beat is detected, call triggerBeat()
95713   *    peakDetect.onPeak(triggerBeat);
95714   *  }
95715   *
95716   *  function draw() {
95717   *    background(0);
95718   *    fill(255);
95719   *    text('click to play', width/2, height/2);
95720   *
95721   *    fft.analyze();
95722   *    peakDetect.update(fft);
95723   *
95724   *    ellipseWidth *= 0.95;
95725   *    ellipse(width/2, height/2, ellipseWidth, ellipseWidth);
95726   *  }
95727   *
95728   *  // this function is called by peakDetect.onPeak
95729   *  function triggerBeat() {
95730   *    ellipseWidth = 50;
95731   *  }
95732   *
95733   *  // mouseclick starts/stops sound
95734   *  function setupSound() {
95735   *    cnv.mouseClicked( function() {
95736   *      if (soundFile.isPlaying() ) {
95737   *        soundFile.stop();
95738   *      } else {
95739   *        soundFile.play();
95740   *      }
95741   *    });
95742   *  }
95743   *  </code></div>
95744   */
95745  p5.PeakDetect.prototype.onPeak = function (callback, val) {
95746    var self = this;
95747    self._onPeak = function () {
95748      callback(self.energy, val);
95749    };
95750  };
95751}();
95752var gain;
95753'use strict';
95754gain = function () {
95755  var p5sound = master;
95756  /**
95757   *  A gain node is usefull to set the relative volume of sound.
95758   *  It's typically used to build mixers.
95759   *
95760   *  @class p5.Gain
95761   *  @constructor
95762   *  @example
95763   *  <div><code>
95764   *
95765   * // load two soundfile and crossfade beetween them
95766   * var sound1,sound2;
95767   * var gain1, gain2, gain3;
95768   *
95769   * function preload(){
95770   *   soundFormats('ogg', 'mp3');
95771   *   sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01');
95772   *   sound2 = loadSound('assets/beat.mp3');
95773   * }
95774   *
95775   * function setup() {
95776   *   createCanvas(400,200);
95777   *
95778   *   // create a 'master' gain to which we will connect both soundfiles
95779   *   gain3 = new p5.Gain();
95780   *   gain3.connect();
95781   *
95782   *   // setup first sound for playing
95783   *   sound1.rate(1);
95784   *   sound1.loop();
95785   *   sound1.disconnect(); // diconnect from p5 output
95786   *
95787   *   gain1 = new p5.Gain(); // setup a gain node
95788   *   gain1.setInput(sound1); // connect the first sound to its input
95789   *   gain1.connect(gain3); // connect its output to the 'master'
95790   *
95791   *   sound2.rate(1);
95792   *   sound2.disconnect();
95793   *   sound2.loop();
95794   *
95795   *   gain2 = new p5.Gain();
95796   *   gain2.setInput(sound2);
95797   *   gain2.connect(gain3);
95798   *
95799   * }
95800   *
95801   * function draw(){
95802   *   background(180);
95803   *
95804   *   // calculate the horizontal distance beetween the mouse and the right of the screen
95805   *   var d = dist(mouseX,0,width,0);
95806   *
95807   *   // map the horizontal position of the mouse to values useable for volume control of sound1
95808   *   var vol1 = map(mouseX,0,width,0,1);
95809   *   var vol2 = 1-vol1; // when sound1 is loud, sound2 is quiet and vice versa
95810   *
95811   *   gain1.amp(vol1,0.5,0);
95812   *   gain2.amp(vol2,0.5,0);
95813   *
95814   *   // map the vertical position of the mouse to values useable for 'master volume control'
95815   *   var vol3 = map(mouseY,0,height,0,1);
95816   *   gain3.amp(vol3,0.5,0);
95817   * }
95818   *</code></div>
95819   *
95820   */
95821  p5.Gain = function () {
95822    this.ac = p5sound.audiocontext;
95823    this.input = this.ac.createGain();
95824    this.output = this.ac.createGain();
95825    // otherwise, Safari distorts
95826    this.input.gain.value = 0.5;
95827    this.input.connect(this.output);
95828    // add  to the soundArray
95829    p5sound.soundArray.push(this);
95830  };
95831  /**
95832   *  Connect a source to the gain node.
95833   *
95834   *  @method  setInput
95835   *  @param  {Object} src     p5.sound / Web Audio object with a sound
95836   *                           output.
95837   */
95838  p5.Gain.prototype.setInput = function (src) {
95839    src.connect(this.input);
95840  };
95841  /**
95842   *  Send output to a p5.sound or web audio object
95843   *
95844   *  @method  connect
95845   *  @param  {Object} unit
95846   */
95847  p5.Gain.prototype.connect = function (unit) {
95848    var u = unit || p5.soundOut.input;
95849    this.output.connect(u.input ? u.input : u);
95850  };
95851  /**
95852   *  Disconnect all output.
95853   *
95854   *  @method disconnect
95855   */
95856  p5.Gain.prototype.disconnect = function () {
95857    if (this.output) {
95858      this.output.disconnect();
95859    }
95860  };
95861  /**
95862   *  Set the output level of the gain node.
95863   *
95864   *  @method  amp
95865   *  @param  {Number} volume amplitude between 0 and 1.0
95866   *  @param  {Number} [rampTime] create a fade that lasts rampTime
95867   *  @param  {Number} [timeFromNow] schedule this event to happen
95868   *                                seconds from now
95869   */
95870  p5.Gain.prototype.amp = function (vol, rampTime, tFromNow) {
95871    var rampTime = rampTime || 0;
95872    var tFromNow = tFromNow || 0;
95873    var now = p5sound.audiocontext.currentTime;
95874    var currentVol = this.output.gain.value;
95875    this.output.gain.cancelScheduledValues(now);
95876    this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow);
95877    this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime);
95878  };
95879  p5.Gain.prototype.dispose = function () {
95880    // remove reference from soundArray
95881    var index = p5sound.soundArray.indexOf(this);
95882    p5sound.soundArray.splice(index, 1);
95883    if (this.output) {
95884      this.output.disconnect();
95885      delete this.output;
95886    }
95887    if (this.input) {
95888      this.input.disconnect();
95889      delete this.input;
95890    }
95891  };
95892}(master);
95893var audioVoice;
95894'use strict';
95895audioVoice = function () {
95896  var p5sound = master;
95897  /**
95898   * Base class for monophonic synthesizers. Any extensions of this class
95899   * should follow the API and implement the methods below in order to 
95900   * remain compatible with p5.PolySynth();
95901   *
95902   * @class p5.AudioVoice
95903   * @constructor
95904   */
95905  p5.AudioVoice = function () {
95906    this.ac = p5sound.audiocontext;
95907    this.output = this.ac.createGain();
95908    this.connect();
95909    p5sound.soundArray.push(this);
95910  };
95911  p5.AudioVoice.prototype.play = function (note, velocity, secondsFromNow, sustime) {
95912  };
95913  p5.AudioVoice.prototype.triggerAttack = function (note, velocity, secondsFromNow) {
95914  };
95915  p5.AudioVoice.prototype.triggerRelease = function (secondsFromNow) {
95916  };
95917  p5.AudioVoice.prototype.amp = function (vol, rampTime) {
95918  };
95919  /**
95920   * Connect to p5 objects or Web Audio Nodes
95921   * @method  connect
95922   * @param {Object} unit 
95923   */
95924  p5.AudioVoice.prototype.connect = function (unit) {
95925    var u = unit || p5sound.input;
95926    this.output.connect(u.input ? u.input : u);
95927  };
95928  /**
95929   * Disconnect from soundOut
95930   * @method  disconnect
95931   */
95932  p5.AudioVoice.prototype.disconnect = function () {
95933    this.output.disconnect();
95934  };
95935  p5.AudioVoice.prototype.dispose = function () {
95936    if (this.output) {
95937      this.output.disconnect();
95938      delete this.output;
95939    }
95940  };
95941  return p5.AudioVoice;
95942}(master);
95943var monosynth;
95944'use strict';
95945monosynth = function () {
95946  var p5sound = master;
95947  var AudioVoice = audioVoice;
95948  var noteToFreq = helpers.noteToFreq;
95949  var DEFAULT_SUSTAIN = 0.15;
95950  /**
95951  *  A MonoSynth is used as a single voice for sound synthesis.
95952  *  This is a class to be used in conjunction with the PolySynth
95953  *  class. Custom synthetisers should be built inheriting from
95954  *  this class.
95955  *
95956  *  @class p5.MonoSynth
95957  *  @constructor
95958  *  @example
95959  *  <div><code>
95960  *  var monoSynth;
95961  *
95962  *  function setup() {
95963  *    var cnv = createCanvas(100, 100);
95964  *    cnv.mousePressed(playSynth);
95965  *
95966  *    monoSynth = new p5.MonoSynth();
95967  *
95968  *    textAlign(CENTER);
95969  *    text('click to play', width/2, height/2);
95970  *  }
95971  *
95972  *  function playSynth() {
95973  *    // time from now (in seconds)
95974  *    var time = 0;
95975  *    // note duration (in seconds)
95976  *    var dur = 0.25;
95977  *    // velocity (volume, from 0 to 1)
95978  *    var v = 0.2;
95979  *
95980  *    monoSynth.play("G3", v, time, dur);
95981  *    monoSynth.play("C4", v, time += dur, dur);
95982  *
95983  *    background(random(255), random(255), 255);
95984  *    text('click to play', width/2, height/2);
95985  *  }
95986  *  </code></div>
95987  **/
95988  p5.MonoSynth = function () {
95989    AudioVoice.call(this);
95990    this.oscillator = new p5.Oscillator();
95991    this.env = new p5.Envelope();
95992    this.env.setRange(1, 0);
95993    this.env.setExp(true);
95994    //set params
95995    this.setADSR(0.02, 0.25, 0.05, 0.35);
95996    // oscillator --> env --> this.output (gain) --> p5.soundOut
95997    this.oscillator.disconnect();
95998    this.oscillator.connect(this.output);
95999    this.env.disconnect();
96000    this.env.setInput(this.output.gain);
96001    // reset oscillator gain to 1.0
96002    this.oscillator.output.gain.value = 1;
96003    this.oscillator.start();
96004    this.connect();
96005    p5sound.soundArray.push(this);
96006  };
96007  p5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype);
96008  /**
96009  *  Play tells the MonoSynth to start playing a note. This method schedules
96010  *  the calling of .triggerAttack and .triggerRelease.
96011  *
96012  *  @method play
96013  *  @param {String | Number} note the note you want to play, specified as a
96014  *                                 frequency in Hertz (Number) or as a midi
96015  *                                 value in Note/Octave format ("C4", "Eb3"...etc")
96016  *                                 See <a href = "https://github.com/Tonejs/Tone.js/wiki/Instruments">
96017  *                                 Tone</a>. Defaults to 440 hz.
96018  *  @param  {Number} [velocity] velocity of the note to play (ranging from 0 to 1)
96019  *  @param  {Number} [secondsFromNow]  time from now (in seconds) at which to play
96020  *  @param  {Number} [sustainTime] time to sustain before releasing the envelope
96021  *  @example
96022  *  <div><code>
96023  *  var monoSynth;
96024  *
96025  *  function setup() {
96026  *    var cnv = createCanvas(100, 100);
96027  *    cnv.mousePressed(playSynth);
96028  *
96029  *    monoSynth = new p5.MonoSynth();
96030  *
96031  *    textAlign(CENTER);
96032  *    text('click to play', width/2, height/2);
96033  *  }
96034  *
96035  *  function playSynth() {
96036  *    // time from now (in seconds)
96037  *    var time = 0;
96038  *    // note duration (in seconds)
96039  *    var dur = 1/6;
96040  *    // note velocity (volume, from 0 to 1)
96041  *    var v = random();
96042  *
96043  *    monoSynth.play("Fb3", v, 0, dur);
96044  *    monoSynth.play("Gb3", v, time += dur, dur);
96045  *
96046  *    background(random(255), random(255), 255);
96047  *    text('click to play', width/2, height/2);
96048  *  }
96049  *  </code></div>
96050  *
96051  */
96052  p5.MonoSynth.prototype.play = function (note, velocity, secondsFromNow, susTime) {
96053    this.triggerAttack(note, velocity, ~~secondsFromNow);
96054    this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN));
96055  };
96056  /**
96057   *  Trigger the Attack, and Decay portion of the Envelope.
96058   *  Similar to holding down a key on a piano, but it will
96059   *  hold the sustain level until you let go.
96060   *
96061   *  @param {String | Number} note the note you want to play, specified as a
96062   *                                 frequency in Hertz (Number) or as a midi
96063   *                                 value in Note/Octave format ("C4", "Eb3"...etc")
96064   *                                 See <a href = "https://github.com/Tonejs/Tone.js/wiki/Instruments">
96065   *                                 Tone</a>. Defaults to 440 hz
96066   *  @param  {Number} [velocity] velocity of the note to play (ranging from 0 to 1)
96067   *  @param  {Number} [secondsFromNow]  time from now (in seconds) at which to play
96068   *  @method  triggerAttack
96069   *  @example
96070   *  <div><code>
96071   *  var monoSynth = new p5.MonoSynth();
96072   *
96073   *  function mousePressed() {
96074   *    monoSynth.triggerAttack("E3");
96075   *  }
96076   *
96077   *  function mouseReleased() {
96078   *    monoSynth.triggerRelease();
96079   *  }
96080   *  </code></div>
96081   */
96082  p5.MonoSynth.prototype.triggerAttack = function (note, velocity, secondsFromNow) {
96083    var secondsFromNow = ~~secondsFromNow;
96084    var freq = noteToFreq(note);
96085    var vel = velocity || 0.1;
96086    this.oscillator.freq(freq, 0, secondsFromNow);
96087    this.env.ramp(this.output.gain, secondsFromNow, vel);
96088  };
96089  /**
96090   *  Trigger the release of the Envelope. This is similar to releasing
96091   *  the key on a piano and letting the sound fade according to the
96092   *  release level and release time.
96093   *
96094   *  @param  {Number} secondsFromNow time to trigger the release
96095   *  @method  triggerRelease
96096   *  @example
96097   *  <div><code>
96098   *  var monoSynth = new p5.MonoSynth();
96099   *
96100   *  function mousePressed() {
96101   *    monoSynth.triggerAttack("E3");
96102   *  }
96103   *
96104   *  function mouseReleased() {
96105   *    monoSynth.triggerRelease();
96106   *  }
96107   *  </code></div>
96108   */
96109  p5.MonoSynth.prototype.triggerRelease = function (secondsFromNow) {
96110    var secondsFromNow = secondsFromNow || 0;
96111    this.env.ramp(this.output.gain, secondsFromNow, 0);
96112  };
96113  /**
96114   *  Set values like a traditional
96115   *  <a href="https://en.wikipedia.org/wiki/Synthesizer#/media/File:ADSR_parameter.svg">
96116   *  ADSR envelope
96117   *  </a>.
96118   *
96119   *  @method  setADSR
96120   *  @param {Number} attackTime    Time (in seconds before envelope
96121   *                                reaches Attack Level
96122   *  @param {Number} [decayTime]    Time (in seconds) before envelope
96123   *                                reaches Decay/Sustain Level
96124   *  @param {Number} [susRatio]    Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,
96125   *                                where 1.0 = attackLevel, 0.0 = releaseLevel.
96126   *                                The susRatio determines the decayLevel and the level at which the
96127   *                                sustain portion of the envelope will sustain.
96128   *                                For example, if attackLevel is 0.4, releaseLevel is 0,
96129   *                                and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is
96130   *                                increased to 1.0 (using <code>setRange</code>),
96131   *                                then decayLevel would increase proportionally, to become 0.5.
96132   *  @param {Number} [releaseTime]   Time in seconds from now (defaults to 0)
96133   */
96134  p5.MonoSynth.prototype.setADSR = function (attack, decay, sustain, release) {
96135    this.env.setADSR(attack, decay, sustain, release);
96136  };
96137  /**
96138   * Getters and Setters
96139   * @property {Number} attack
96140   */
96141  /**
96142   * @property {Number} decay
96143   */
96144  /**
96145   * @property {Number} sustain
96146   */
96147  /**
96148   * @property {Number} release
96149   */
96150  Object.defineProperties(p5.MonoSynth.prototype, {
96151    'attack': {
96152      get: function () {
96153        return this.env.aTime;
96154      },
96155      set: function (attack) {
96156        this.env.setADSR(attack, this.env.dTime, this.env.sPercent, this.env.rTime);
96157      }
96158    },
96159    'decay': {
96160      get: function () {
96161        return this.env.dTime;
96162      },
96163      set: function (decay) {
96164        this.env.setADSR(this.env.aTime, decay, this.env.sPercent, this.env.rTime);
96165      }
96166    },
96167    'sustain': {
96168      get: function () {
96169        return this.env.sPercent;
96170      },
96171      set: function (sustain) {
96172        this.env.setADSR(this.env.aTime, this.env.dTime, sustain, this.env.rTime);
96173      }
96174    },
96175    'release': {
96176      get: function () {
96177        return this.env.rTime;
96178      },
96179      set: function (release) {
96180        this.env.setADSR(this.env.aTime, this.env.dTime, this.env.sPercent, release);
96181      }
96182    }
96183  });
96184  /**
96185   * MonoSynth amp
96186   * @method  amp
96187   * @param  {Number} vol      desired volume
96188   * @param  {Number} [rampTime] Time to reach new volume
96189   * @return {Number}          new volume value
96190   */
96191  p5.MonoSynth.prototype.amp = function (vol, rampTime) {
96192    var t = rampTime || 0;
96193    if (typeof vol !== 'undefined') {
96194      this.oscillator.amp(vol, t);
96195    }
96196    return this.oscillator.amp().value;
96197  };
96198  /**
96199   *  Connect to a p5.sound / Web Audio object.
96200   *
96201   *  @method  connect
96202   *  @param  {Object} unit A p5.sound or Web Audio object
96203   */
96204  p5.MonoSynth.prototype.connect = function (unit) {
96205    var u = unit || p5sound.input;
96206    this.output.connect(u.input ? u.input : u);
96207  };
96208  /**
96209   *  Disconnect all outputs
96210   *
96211   *  @method  disconnect
96212   */
96213  p5.MonoSynth.prototype.disconnect = function () {
96214    if (this.output) {
96215      this.output.disconnect();
96216    }
96217  };
96218  /**
96219   *  Get rid of the MonoSynth and free up its resources / memory.
96220   *
96221   *  @method  dispose
96222   */
96223  p5.MonoSynth.prototype.dispose = function () {
96224    AudioVoice.prototype.dispose.apply(this);
96225    if (this.env) {
96226      this.env.dispose();
96227    }
96228    if (this.oscillator) {
96229      this.oscillator.dispose();
96230    }
96231  };
96232}(master, audioVoice, helpers);
96233var polysynth;
96234'use strict';
96235polysynth = function () {
96236  var p5sound = master;
96237  var TimelineSignal = Tone_signal_TimelineSignal;
96238  var noteToFreq = helpers.noteToFreq;
96239  /**
96240  *  An AudioVoice is used as a single voice for sound synthesis.
96241  *  The PolySynth class holds an array of AudioVoice, and deals
96242  *  with voices allocations, with setting notes to be played, and
96243  *  parameters to be set.
96244  *
96245  *  @class p5.PolySynth
96246  *  @constructor
96247  *
96248  *  @param {Number} [synthVoice]   A monophonic synth voice inheriting
96249  *                                 the AudioVoice class. Defaults to p5.MonoSynth
96250  *  @param {Number} [maxVoices] Number of voices, defaults to 8;
96251  *  @example
96252  *  <div><code>
96253  *  var polySynth;
96254  *
96255  *  function setup() {
96256  *    var cnv = createCanvas(100, 100);
96257  *    cnv.mousePressed(playSynth);
96258  *
96259  *    polySynth = new p5.PolySynth();
96260  *
96261  *    textAlign(CENTER);
96262  *    text('click to play', width/2, height/2);
96263  *  }
96264  *
96265  *  function playSynth() {
96266  *    // note duration (in seconds)
96267  *    var dur = 1.5;
96268  *
96269  *    // time from now (in seconds)
96270  *    var time = 0;
96271  *
96272  *    // velocity (volume, from 0 to 1)
96273  *    var vel = 0.1;
96274  *
96275  *    // notes can overlap with each other
96276  *    polySynth.play("G2", vel, 0, dur);
96277  *    polySynth.play("C3", vel, time += 1/3, dur);
96278  *    polySynth.play("G3", vel, time += 1/3, dur);
96279  *
96280  *    background(random(255), random(255), 255);
96281  *    text('click to play', width/2, height/2);
96282  *  }
96283  *  </code></div>
96284  **/
96285  p5.PolySynth = function (audioVoice, maxVoices) {
96286    //audiovoices will contain maxVoices many monophonic synths
96287    this.audiovoices = [];
96288    /**
96289     * An object that holds information about which notes have been played and
96290     * which notes are currently being played. New notes are added as keys
96291     * on the fly. While a note has been attacked, but not released, the value of the
96292     * key is the audiovoice which is generating that note. When notes are released,
96293     * the value of the key becomes undefined.
96294     * @property notes
96295     */
96296    this.notes = {};
96297    //indices of the most recently used, and least recently used audiovoice
96298    this._newest = 0;
96299    this._oldest = 0;
96300    /**
96301     * A PolySynth must have at least 1 voice, defaults to 8
96302     * @property polyvalue
96303     */
96304    this.maxVoices = maxVoices || 8;
96305    /**
96306     * Monosynth that generates the sound for each note that is triggered. The
96307     * p5.PolySynth defaults to using the p5.MonoSynth as its voice.
96308     * @property AudioVoice
96309     */
96310    this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice;
96311    /**
96312       * This value must only change as a note is attacked or released. Due to delay
96313       * and sustain times, Tone.TimelineSignal is required to schedule the change in value.
96314    * @private
96315       * @property {Tone.TimelineSignal} _voicesInUse
96316       */
96317    this._voicesInUse = new TimelineSignal(0);
96318    this.output = p5sound.audiocontext.createGain();
96319    this.connect();
96320    //Construct the appropriate number of audiovoices
96321    this._allocateVoices();
96322    p5sound.soundArray.push(this);
96323  };
96324  /**
96325   * Construct the appropriate number of audiovoices
96326   * @private
96327   * @method  _allocateVoices
96328   */
96329  p5.PolySynth.prototype._allocateVoices = function () {
96330    for (var i = 0; i < this.maxVoices; i++) {
96331      this.audiovoices.push(new this.AudioVoice());
96332      this.audiovoices[i].disconnect();
96333      this.audiovoices[i].connect(this.output);
96334    }
96335  };
96336  /**
96337   *  Play a note by triggering noteAttack and noteRelease with sustain time
96338   *
96339   *  @method  play
96340   *  @param  {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C)
96341   *  @param  {Number} [velocity] velocity of the note to play (ranging from 0 to 1)
96342   *  @param  {Number} [secondsFromNow]  time from now (in seconds) at which to play
96343   *  @param  {Number} [sustainTime] time to sustain before releasing the envelope
96344   *  @example
96345   *  <div><code>
96346   *  var polySynth;
96347   *
96348   *  function setup() {
96349   *    var cnv = createCanvas(100, 100);
96350   *    cnv.mousePressed(playSynth);
96351   *
96352   *    polySynth = new p5.PolySynth();
96353   *
96354   *    textAlign(CENTER);
96355   *    text('click to play', width/2, height/2);
96356   *  }
96357   *
96358   *  function playSynth() {
96359   *    // note duration (in seconds)
96360   *    var dur = 0.1;
96361   *
96362   *    // time from now (in seconds)
96363   *    var time = 0;
96364   *
96365   *    // velocity (volume, from 0 to 1)
96366   *    var vel = 0.1;
96367   *
96368   *    polySynth.play("G2", vel, 0, dur);
96369   *    polySynth.play("C3", vel, 0, dur);
96370   *    polySynth.play("G3", vel, 0, dur);
96371   *
96372   *    background(random(255), random(255), 255);
96373   *    text('click to play', width/2, height/2);
96374   *  }
96375   *  </code></div>
96376   */
96377  p5.PolySynth.prototype.play = function (note, velocity, secondsFromNow, susTime) {
96378    var susTime = susTime || 1;
96379    this.noteAttack(note, velocity, secondsFromNow);
96380    this.noteRelease(note, secondsFromNow + susTime);
96381  };
96382  /**
96383   *  noteADSR sets the envelope for a specific note that has just been triggered.
96384   *  Using this method modifies the envelope of whichever audiovoice is being used
96385   *  to play the desired note. The envelope should be reset before noteRelease is called
96386   *  in order to prevent the modified envelope from being used on other notes.
96387   *
96388   *  @method  noteADSR
96389   *  @param {Number} [note]        Midi note on which ADSR should be set.
96390   *  @param {Number} [attackTime]  Time (in seconds before envelope
96391   *                                reaches Attack Level
96392   *  @param {Number} [decayTime]   Time (in seconds) before envelope
96393   *                                reaches Decay/Sustain Level
96394   *  @param {Number} [susRatio]    Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,
96395   *                                where 1.0 = attackLevel, 0.0 = releaseLevel.
96396   *                                The susRatio determines the decayLevel and the level at which the
96397   *                                sustain portion of the envelope will sustain.
96398   *                                For example, if attackLevel is 0.4, releaseLevel is 0,
96399   *                                and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is
96400   *                                increased to 1.0 (using <code>setRange</code>),
96401   *                                then decayLevel would increase proportionally, to become 0.5.
96402   *  @param {Number} [releaseTime]   Time in seconds from now (defaults to 0)
96403   **/
96404  p5.PolySynth.prototype.noteADSR = function (note, a, d, s, r, timeFromNow) {
96405    var now = p5sound.audiocontext.currentTime;
96406    var timeFromNow = timeFromNow || 0;
96407    var t = now + timeFromNow;
96408    this.audiovoices[this.notes[note].getValueAtTime(t)].setADSR(a, d, s, r);
96409  };
96410  /**
96411   * Set the PolySynths global envelope. This method modifies the envelopes of each
96412   * monosynth so that all notes are played with this envelope.
96413   *
96414   *  @method  setADSR
96415   *  @param {Number} [attackTime]  Time (in seconds before envelope
96416   *                                reaches Attack Level
96417   *  @param {Number} [decayTime]   Time (in seconds) before envelope
96418   *                                reaches Decay/Sustain Level
96419   *  @param {Number} [susRatio]    Ratio between attackLevel and releaseLevel, on a scale from 0 to 1,
96420   *                                where 1.0 = attackLevel, 0.0 = releaseLevel.
96421   *                                The susRatio determines the decayLevel and the level at which the
96422   *                                sustain portion of the envelope will sustain.
96423   *                                For example, if attackLevel is 0.4, releaseLevel is 0,
96424   *                                and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is
96425   *                                increased to 1.0 (using <code>setRange</code>),
96426   *                                then decayLevel would increase proportionally, to become 0.5.
96427   *  @param {Number} [releaseTime]   Time in seconds from now (defaults to 0)
96428   **/
96429  p5.PolySynth.prototype.setADSR = function (a, d, s, r) {
96430    this.audiovoices.forEach(function (voice) {
96431      voice.setADSR(a, d, s, r);
96432    });
96433  };
96434  /**
96435   *  Trigger the Attack, and Decay portion of a MonoSynth.
96436   *  Similar to holding down a key on a piano, but it will
96437   *  hold the sustain level until you let go.
96438   *
96439   *  @method  noteAttack
96440   *  @param  {Number} [note]           midi note on which attack should be triggered.
96441   *  @param  {Number} [velocity]       velocity of the note to play (ranging from 0 to 1)/
96442   *  @param  {Number} [secondsFromNow] time from now (in seconds)
96443   *  @example
96444   *  <div><code>
96445   *  var polySynth = new p5.PolySynth();
96446   *  var pitches = ["G", "D", "G", "C"];
96447   *  var octaves = [2, 3, 4];
96448   *
96449   *  function mousePressed() {
96450   *    // play a chord: multiple notes at the same time
96451   *    for (var i = 0; i < 4; i++) {
96452   *      var note = random(pitches) + random(octaves);
96453   *      polySynth.noteAttack(note, 0.1);
96454   *    }
96455   *  }
96456   *
96457   *  function mouseReleased() {
96458   *    // release all voices
96459   *    polySynth.noteRelease();
96460   *  }
96461   *  </code></div>
96462   */
96463  p5.PolySynth.prototype.noteAttack = function (_note, _velocity, secondsFromNow) {
96464    //this value goes to the audiovoices which handle their own scheduling
96465    var secondsFromNow = ~~secondsFromNow;
96466    //this value is used by this._voicesInUse
96467    var acTime = p5sound.audiocontext.currentTime + secondsFromNow;
96468    //Convert note to frequency if necessary. This is because entries into this.notes
96469    //should be based on frequency for the sake of consistency.
96470    var note = noteToFreq(_note);
96471    var velocity = _velocity || 0.1;
96472    var currentVoice;
96473    //Release the note if it is already playing
96474    if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) {
96475      this.noteRelease(note, 0);
96476    }
96477    //Check to see how many voices are in use at the time the note will start
96478    if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) {
96479      currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0);
96480    } else {
96481      currentVoice = this._oldest;
96482      var oldestNote = p5.prototype.freqToMidi(this.audiovoices[this._oldest].oscillator.freq().value);
96483      this.noteRelease(oldestNote);
96484      this._oldest = (this._oldest + 1) % (this.maxVoices - 1);
96485    }
96486    //Overrite the entry in the notes object. A note (frequency value)
96487    //corresponds to the index of the audiovoice that is playing it
96488    this.notes[note] = new TimelineSignal();
96489    this.notes[note].setValueAtTime(currentVoice, acTime);
96490    //Find the scheduled change in this._voicesInUse that will be previous to this new note
96491    //Add 1 and schedule this value at time 't', when this note will start playing
96492    var previousVal = this._voicesInUse._searchBefore(acTime) === null ? 0 : this._voicesInUse._searchBefore(acTime).value;
96493    this._voicesInUse.setValueAtTime(previousVal + 1, acTime);
96494    //Then update all scheduled values that follow to increase by 1
96495    this._updateAfter(acTime, 1);
96496    this._newest = currentVoice;
96497    //The audiovoice handles the actual scheduling of the note
96498    if (typeof velocity === 'number') {
96499      var maxRange = 1 / this._voicesInUse.getValueAtTime(acTime) * 2;
96500      velocity = velocity > maxRange ? maxRange : velocity;
96501    }
96502    this.audiovoices[currentVoice].triggerAttack(note, velocity, secondsFromNow);
96503  };
96504  /**
96505   * Private method to ensure accurate values of this._voicesInUse
96506   * Any time a new value is scheduled, it is necessary to increment all subsequent
96507   * scheduledValues after attack, and decrement all subsequent
96508   * scheduledValues after release
96509   *
96510   * @private
96511   * @param  {[type]} time  [description]
96512   * @param  {[type]} value [description]
96513   * @return {[type]}       [description]
96514   */
96515  p5.PolySynth.prototype._updateAfter = function (time, value) {
96516    if (this._voicesInUse._searchAfter(time) === null) {
96517      return;
96518    } else {
96519      this._voicesInUse._searchAfter(time).value += value;
96520      var nextTime = this._voicesInUse._searchAfter(time).time;
96521      this._updateAfter(nextTime, value);
96522    }
96523  };
96524  /**
96525   *  Trigger the Release of an AudioVoice note. This is similar to releasing
96526   *  the key on a piano and letting the sound fade according to the
96527   *  release level and release time.
96528   *
96529   *  @method  noteRelease
96530   *  @param  {Number} [note]           midi note on which attack should be triggered.
96531   *                                    If no value is provided, all notes will be released.
96532   *  @param  {Number} [secondsFromNow] time to trigger the release
96533   *  @example
96534   *  <div><code>
96535   *  var pitches = ["G", "D", "G", "C"];
96536   *  var octaves = [2, 3, 4];
96537   *  var polySynth = new p5.PolySynth();
96538   *
96539   *  function mousePressed() {
96540   *    // play a chord: multiple notes at the same time
96541   *    for (var i = 0; i < 4; i++) {
96542   *      var note = random(pitches) + random(octaves);
96543   *      polySynth.noteAttack(note, 0.1);
96544   *    }
96545   *  }
96546   *
96547   *  function mouseReleased() {
96548   *    // release all voices
96549   *    polySynth.noteRelease();
96550   *  }
96551   *  </code></div>
96552   *
96553   */
96554  p5.PolySynth.prototype.noteRelease = function (_note, secondsFromNow) {
96555    var now = p5sound.audiocontext.currentTime;
96556    var tFromNow = secondsFromNow || 0;
96557    var t = now + tFromNow;
96558    // if a note value is not provided, release all voices
96559    if (!_note) {
96560      this.audiovoices.forEach(function (voice) {
96561        voice.triggerRelease(tFromNow);
96562      });
96563      this._voicesInUse.setValueAtTime(0, t);
96564      for (var n in this.notes) {
96565        this.notes[n].dispose();
96566        delete this.notes[n];
96567      }
96568      return;
96569    }
96570    //Make sure note is in frequency inorder to query the this.notes object
96571    var note = noteToFreq(_note);
96572    if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) {
96573      console.warn('Cannot release a note that is not already playing');
96574    } else {
96575      //Find the scheduled change in this._voicesInUse that will be previous to this new note
96576      //subtract 1 and schedule this value at time 't', when this note will stop playing
96577      var previousVal = Math.max(~~this._voicesInUse.getValueAtTime(t).value, 1);
96578      this._voicesInUse.setValueAtTime(previousVal - 1, t);
96579      //Then update all scheduled values that follow to decrease by 1 but never go below 0
96580      if (previousVal > 0) {
96581        this._updateAfter(t, -1);
96582      }
96583      this.audiovoices[this.notes[note].getValueAtTime(t)].triggerRelease(tFromNow);
96584      this.notes[note].dispose();
96585      delete this.notes[note];
96586      this._newest = this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1);
96587    }
96588  };
96589  /**
96590  *  Connect to a p5.sound / Web Audio object.
96591  *
96592  *  @method  connect
96593  *  @param  {Object} unit A p5.sound or Web Audio object
96594  */
96595  p5.PolySynth.prototype.connect = function (unit) {
96596    var u = unit || p5sound.input;
96597    this.output.connect(u.input ? u.input : u);
96598  };
96599  /**
96600  *  Disconnect all outputs
96601  *
96602  *  @method  disconnect
96603  */
96604  p5.PolySynth.prototype.disconnect = function () {
96605    if (this.output) {
96606      this.output.disconnect();
96607    }
96608  };
96609  /**
96610  *  Get rid of the MonoSynth and free up its resources / memory.
96611  *
96612  *  @method  dispose
96613  */
96614  p5.PolySynth.prototype.dispose = function () {
96615    this.audiovoices.forEach(function (voice) {
96616      voice.dispose();
96617    });
96618    if (this.output) {
96619      this.output.disconnect();
96620      delete this.output;
96621    }
96622  };
96623}(master, Tone_signal_TimelineSignal, helpers);
96624var distortion;
96625'use strict';
96626distortion = function () {
96627  var Effect = effect;
96628  /*
96629   * Adapted from [Kevin Ennis on StackOverflow](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)
96630   */
96631  function makeDistortionCurve(amount) {
96632    var k = typeof amount === 'number' ? amount : 50;
96633    var numSamples = 44100;
96634    var curve = new Float32Array(numSamples);
96635    var deg = Math.PI / 180;
96636    var i = 0;
96637    var x;
96638    for (; i < numSamples; ++i) {
96639      x = i * 2 / numSamples - 1;
96640      curve[i] = (3 + k) * x * 20 * deg / (Math.PI + k * Math.abs(x));
96641    }
96642    return curve;
96643  }
96644  /**
96645   * A Distortion effect created with a Waveshaper Node,
96646   * with an approach adapted from
96647   * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion)
96648   * 
96649   * This class extends <a href = "/reference/#/p5.Effect">p5.Effect</a>.  
96650   * Methods <a href = "/reference/#/p5.Effect/amp">amp()</a>, <a href = "/reference/#/p5.Effect/chain">chain()</a>, 
96651   * <a href = "/reference/#/p5.Effect/drywet">drywet()</a>, <a href = "/reference/#/p5.Effect/connect">connect()</a>, and 
96652   * <a href = "/reference/#/p5.Effect/disconnect">disconnect()</a> are available.
96653   * 
96654   * @class p5.Distortion
96655   * @extends p5.Effect
96656   * @constructor
96657   * @param {Number} [amount=0.25] Unbounded distortion amount.
96658   *                                Normal values range from 0-1.
96659   * @param {String} [oversample='none'] 'none', '2x', or '4x'.
96660   *
96661   */
96662  p5.Distortion = function (amount, oversample) {
96663    Effect.call(this);
96664    if (typeof amount === 'undefined') {
96665      amount = 0.25;
96666    }
96667    if (typeof amount !== 'number') {
96668      throw new Error('amount must be a number');
96669    }
96670    if (typeof oversample === 'undefined') {
96671      oversample = '2x';
96672    }
96673    if (typeof oversample !== 'string') {
96674      throw new Error('oversample must be a String');
96675    }
96676    var curveAmount = p5.prototype.map(amount, 0, 1, 0, 2000);
96677    /**
96678     *  The p5.Distortion is built with a
96679     *  <a href="http://www.w3.org/TR/webaudio/#WaveShaperNode">
96680     *  Web Audio WaveShaper Node</a>.
96681     *
96682     *  @property {AudioNode} WaveShaperNode
96683     */
96684    this.waveShaperNode = this.ac.createWaveShaper();
96685    this.amount = curveAmount;
96686    this.waveShaperNode.curve = makeDistortionCurve(curveAmount);
96687    this.waveShaperNode.oversample = oversample;
96688    this.input.connect(this.waveShaperNode);
96689    this.waveShaperNode.connect(this.wet);
96690  };
96691  p5.Distortion.prototype = Object.create(Effect.prototype);
96692  /**
96693   * Process a sound source, optionally specify amount and oversample values.
96694   *
96695   * @method process
96696   * @param {Number} [amount=0.25] Unbounded distortion amount.
96697   *                                Normal values range from 0-1.
96698   * @param {String} [oversample='none'] 'none', '2x', or '4x'.
96699   */
96700  p5.Distortion.prototype.process = function (src, amount, oversample) {
96701    src.connect(this.input);
96702    this.set(amount, oversample);
96703  };
96704  /**
96705   * Set the amount and oversample of the waveshaper distortion.
96706   *
96707   * @method set
96708   * @param {Number} [amount=0.25] Unbounded distortion amount.
96709   *                                Normal values range from 0-1.
96710   * @param {String} [oversample='none'] 'none', '2x', or '4x'.
96711   */
96712  p5.Distortion.prototype.set = function (amount, oversample) {
96713    if (amount) {
96714      var curveAmount = p5.prototype.map(amount, 0, 1, 0, 2000);
96715      this.amount = curveAmount;
96716      this.waveShaperNode.curve = makeDistortionCurve(curveAmount);
96717    }
96718    if (oversample) {
96719      this.waveShaperNode.oversample = oversample;
96720    }
96721  };
96722  /**
96723   *  Return the distortion amount, typically between 0-1.
96724   *
96725   *  @method  getAmount
96726   *  @return {Number} Unbounded distortion amount.
96727   *                   Normal values range from 0-1.
96728   */
96729  p5.Distortion.prototype.getAmount = function () {
96730    return this.amount;
96731  };
96732  /**
96733   *  Return the oversampling.
96734   *
96735   *  @method getOversample
96736   *
96737   *  @return {String} Oversample can either be 'none', '2x', or '4x'.
96738   */
96739  p5.Distortion.prototype.getOversample = function () {
96740    return this.waveShaperNode.oversample;
96741  };
96742  p5.Distortion.prototype.dispose = function () {
96743    Effect.prototype.dispose.apply(this);
96744    if (this.waveShaperNode) {
96745      this.waveShaperNode.disconnect();
96746      this.waveShaperNode = null;
96747    }
96748  };
96749}(effect);
96750var src_app;
96751'use strict';
96752src_app = function () {
96753  var p5SOUND = master;
96754  return p5SOUND;
96755}(shims, audiocontext, master, helpers, errorHandler, panner, soundfile, amplitude, fft, signal, oscillator, envelope, pulse, noise, audioin, filter, eq, panner3d, listener3d, delay, reverb, metro, looper, soundloop, compressor, soundRecorder, peakdetect, gain, monosynth, polysynth, distortion, audioVoice, monosynth, polysynth);
96756}));
96757},{"../p5":"../node_modules/p5/lib/p5.js"}],"images/clock.png":[function(require,module,exports) {
96758module.exports = "/clock.903ff57b.png";
96759},{}],"images/mokuhyou_tassei_man.png":[function(require,module,exports) {
96760module.exports = "/mokuhyou_tassei_man.8c5a209c.png";
96761},{}],"images/mokuhyou_tassei_woman.png":[function(require,module,exports) {
96762module.exports = "/mokuhyou_tassei_woman.c2505a38.png";
96763},{}],"images/musician_trumpet_man.png":[function(require,module,exports) {
96764module.exports = "/musician_trumpet_man.a4a6179c.png";
96765},{}],"se/people_people-stadium-cheer1.mp3":[function(require,module,exports) {
96766module.exports = "/people_people-stadium-cheer1.5c7a3fa7.mp3";
96767},{}],"se/trumpet-dub1.mp3":[function(require,module,exports) {
96768module.exports = "/trumpet-dub1.2ea8e318.mp3";
96769},{}],"js/app.js":[function(require,module,exports) {
96770"use strict";
96771
96772require("../scss/style.scss");
96773
96774var _p = _interopRequireDefault(require("p5"));
96775
96776require("p5/lib/addons/p5.sound");
96777
96778var _clock = _interopRequireDefault(require("../images/clock.png"));
96779
96780var _mokuhyou_tassei_man = _interopRequireDefault(require("../images/mokuhyou_tassei_man.png"));
96781
96782var _mokuhyou_tassei_woman = _interopRequireDefault(require("../images/mokuhyou_tassei_woman.png"));
96783
96784var _musician_trumpet_man = _interopRequireDefault(require("../images/musician_trumpet_man.png"));
96785
96786var _people_peopleStadiumCheer = _interopRequireDefault(require("../se/people_people-stadium-cheer1.mp3"));
96787
96788var _trumpetDub = _interopRequireDefault(require("../se/trumpet-dub1.mp3"));
96789
96790function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
96791
96792var sketch = function sketch(p) {
96793  var PEOPLE_TYPE_MAN = "MAN";
96794  var PEOPLE_TYPE_WOMAN = "WOMAN";
96795  var HOURS_LINE_LENGTH = 160;
96796  var MINUTES_LINE_LENGTH = 200;
96797  var SECONDS_LINE_LENGTH = 230; //画面描画用バッファ
96798
96799  var bufferedImage; //画像:時計本体
96800
96801  var imgClock; //画像:報われマン
96802
96803  var imgRewardMan; //画像:報われウーマン
96804
96805  var imgRewardWoman; //画像:トランペットマン
96806
96807  var imgTrumpetMan; //効果音:報われる
96808
96809  var seReward; //効果音:12時
96810
96811  var seTwelve; //マウスを長押しした時間
96812
96813  var mousePressedTime = 0; //加算する時間
96814
96815  var addTime = 0; //前フレームの長針短針重なり判定の結果を保持しておく
96816
96817  var prevCheckResult = null; //報われ処理カウンタ
96818
96819  var rewardCount = 0;
96819 //報われ処理中の人物描画用配列
96820
96821  var rewardPeopleList; //長針と短針の色
96822
96823  var hoursMinutesColor; //秒針の色
96824
96825  var secondsColor; //最後に報われた時
96826
96827  var lastRewardHours; //日付変更処理カウンタ
96828
96829  var newDayCount = 0; //画像の拡大率
96830
96831  var magnification = 1.0; //音声初期化フラグ(iOS対策)
96832
96833  var isInitSE = false; //初期化処理(画像と効果音読み込み)
96834
96835  p.preload = function () {
96836    imgClock = p.loadImage(_clock.default);
96837    imgRewardMan = p.loadImage(_mokuhyou_tassei_man.default);
96838    imgRewardWoman = p.loadImage(_mokuhyou_tassei_woman.default);
96839    imgTrumpetMan = p.loadImage(_musician_trumpet_man.default);
96840    seReward = p.loadSound(_people_peopleStadiumCheer.default);
96841    seTwelve = p.loadSound(_trumpetDub.default);
96842  }; //初期化処理(画面描画設定など)
96843
96844
96845  p.setup = function () {
96846    p.createCanvas(p.windowWidth, p.windowHeight);
96847    bufferedImage = p.createGraphics(p.windowWidth, p.windowHeight);
96848    p.setMagnification();
96849    bufferedImage.noStroke();
96850    bufferedImage.imageMode(p.CENTER);
96851    p.background(255);
96852    p.frameRate(30);
96853    p.angleMode(p.DEGREES);
96854    hoursMinutesColor = p.color(0, 0, 0);
96855    secondsColor = p.color(255, 0, 0);
96856  }; //画面描画処理
96857
96858
96859  p.draw = function () {
96860    //背景描画(前フレームの描画内容を塗りつぶす)
96861    bufferedImage.background(200); //時計描画
96862
96863    p.drawResizedImage(bufferedImage, imgClock, p.windowWidth / 2, p.windowHeight / 2); //画面長押しで時を加速させる
96864
96865    if (p.mouseIsPressed) {
96866      mousePressedTime++;
96867
96868      if (mousePressedTime > 30) {
96869        addTime++;
96870      }
96871    } else {
96872      mousePressedTime = 0;
96873    } //針描画
96874
96875
96876    var now = new Date();
96877    var hours = now.getHours();
96878    var minutes = now.getMinutes() + addTime;
96879    var seconds = now.getSeconds();
96880    var milliSeconds = now.getMilliseconds();
96881
96882    while (minutes >= 60) {
96883      hours++;
96884      minutes -= 60;
96885    }
96886
96887    hours = hours % 24; //長針表示
96888
96889    bufferedImage.strokeWeight(20 * magnification);
96890    bufferedImage.stroke(hoursMinutesColor);
96891    var hoursDeg = p.reviceAngle((hours + minutes / 60) * 30 - 90);
96892    p.drawHand(HOURS_LINE_LENGTH, hoursDeg); //短針表示
96893
96894    var minutesDeg = p.reviceAngle((minutes + seconds / 60) * 6 - 90);
96895    p.drawHand(MINUTES_LINE_LENGTH, minutesDeg); //秒針表示
96896
96897    bufferedImage.strokeWeight(10 * magnification);
96898    bufferedImage.stroke(secondsColor);
96899    var secondsDeg = p.reviceAngle((seconds + milliSeconds / 1000) * 6 - 90);
96900    p.drawHand(SECONDS_LINE_LENGTH, secondsDeg);
96901
96902    if (hours !== 11 && hours !== 23 && hours !== 12 && hours !== 0 && lastRewardHours !== hours) {
96903      var overlapCheckResult = p.checkOverlap(hoursDeg, minutesDeg);
96904
96905      if (overlapCheckResult === 0 || prevCheckResult === -1 && overlapCheckResult === 1) {
96906        lastRewardHours = hours;
96907        p.initReward();
96908      }
96909
96910      prevCheckResult = overlapCheckResult;
96911    }
96912
96913    if (lastRewardHours === 10 && hours === 12 || lastRewardHours === 22 && hours === 0) {
96914      //12時過ぎた
96915      lastRewardHours = 0;
96916      newDayCount = 1;
96917      seTwelve.play();
96918    }
96919
96920    if (newDayCount > 0) {
96921      p.drawResizedImage(bufferedImage, imgTrumpetMan, bufferedImage.width / 2, bufferedImage.height / 2, imgTrumpetMan.width + p.getRandFromRange(0, 40), imgTrumpetMan.height + p.getRandFromRange(0, 40));
96922      newDayCount++;
96923
96924      if (newDayCount >= 150) {
96925        newDayCount = 0;
96926      }
96927    }
96928
96929    if (rewardCount > 0) {
96930      rewardPeopleList.forEach(function (people) {
96931        p.drawResizedImage(bufferedImage, people.type === PEOPLE_TYPE_MAN ? imgRewardMan : imgRewardWoman, people.x + p.getRandFromRange(-2, 3), people.y + p.getRandFromRange(-2, 3));
96932      });
96933      rewardCount++;
96934
96935      if (rewardCount > 60) {
96936        rewardCount = 0;
96937      }
96938    } //バッファに出力した描画内容をcanvasに表示
96939
96940
96941    p.image(bufferedImage, 0, 0);
96942  };
96943  /**
96944   * ウィンドウサイズ変更時イベント
96945   */
96946
96947
96948  p.windowResized = function () {
96949    //変更されたウィンドウサイズに合わせてキャンバスのサイズを更新
96950    p.updateCanvasSize();
96951  };
96952  /**
96953   * 画面タッチ時、1度だけ無音で効果音を再生する
96954   * (iOS対策)
96955   */
96956
96957
96958  p.touchStarted = function () {
96959    if (isInitSE) {
96960      return;
96961    }
96962
96963    seReward.play();
96964    seReward.stop();
96965    isInitSE = true;
96966  };
96967  /**
96968   * キャンバスサイズ更新
96969   */
96970
96971
96972  p.updateCanvasSize = function () {
96973    p.resizeCanvas(p.windowWidth, p.windowHeight);
96974    bufferedImage.resizeCanvas(p.windowWidth, p.windowHeight);
96975    p.setMagnification();
96976  };
96977
96978  p.setMagnification = function () {
96979    //画面サイズに合わせて描画する画像の拡大率を指定
96980    var shorterWindowSize = p.windowWidth < p.windowHeight ? p.windowWidth : p.windowHeight;
96981
96982    if (shorterWindowSize < imgClock.width) {
96983      magnification = shorterWindowSize / imgClock.width;
96984    }
96985  };
96986  /**
96987   * 角度補正
96988   */
96989
96990
96991  p.reviceAngle = function (deg) {
96992    while (deg >= 360) {
96993      deg -= 360;
96994    }
96995
96996    return deg;
96997  };
96998  /**
96999   * 針を描画する
97000   **/
97001
97002
97003  p.drawHand = function (len, deg) {
97004    //長さと角度から針の終端座標を算出
97005    var sx = bufferedImage.width / 2;
97006    var sy = bufferedImage.height / 2;
97007    var ex = sx + len * magnification * p.cos(deg);
97008    var ey = sy + len * magnification * p.sin(deg); //描画
97009
97010    bufferedImage.line(sx, sy, ex, ey);
97011  };
97012  /**
97013   * 針追い越し判定
97014   */
97015
97016
97017  p.checkOverlap = function (hoursDeg, minutesDeg) {
97018    var roundHoursDeg = Math.round(hoursDeg) % 360;
97019    var roundMinutesDeg = Math.round(minutesDeg) % 360;
97020
97021    if (roundHoursDeg < 0) {
97022      roundHoursDeg += 360;
97023    }
97024
97025    if (roundMinutesDeg < 0) {
97026      roundMinutesDeg += 360;
97027    } //長針が短針を追い越す直前
97028
97029
97030    if (roundHoursDeg > roundMinutesDeg && p.abs(roundHoursDeg - roundMinutesDeg) < 10) {
97031      return -1;
97032    } //短針と長針が丁度重なる
97033
97034
97035    if (roundHoursDeg === roundMinutesDeg) {
97036      return 0;
97037    }
97038
97039    return 1;
97040  };
97041  /**
97042   * 乱数取得(min~max(max含まず))
97043   */
97044
97045
97046  p.getRandFromRange = function (min, max) {
97047    return Math.floor(p.random(max - min)) + min;
97048  };
97049  /**
97050   * 画像をサイズ調整して描画
97051   */
97052
97053
97054  p.drawResizedImage = function (baseImage, targetImage, x, y, width, height) {
97055    if (width && height) {
97056      baseImage.image(targetImage, x, y, width * magnification, height * magnification);
97057      return;
97058    }
97059
97060    baseImage.image(targetImage, x, y, targetImage.width * magnification, targetImage.height * magnification);
97061  };
97062  /**
97063   * 報われ処理初期化
97064   */
97065
97066
97067  p.initReward = function () {
97068    rewardCount = 1;
97069    rewardPeopleList = [];
97070    var poopleCount = p.getRandFromRange(15, 30);
97071
97072    while (rewardPeopleList.length < poopleCount) {
97073      var peopleType = p.getRandFromRange(0, 2) === 0 ? PEOPLE_TYPE_MAN : PEOPLE_TYPE_WOMAN;
97074      rewardPeopleList.push({
97075        type: peopleType,
97076        x: p.getRandFromRange(0, p.windowWidth),
97077        y: p.getRandFromRange(0, p.windowHeight)
97078      });
97079    }
97080
97081    seReward.play();
97082  };
97083};
97084
97085new _p.default(sketch);
97086},{"../scss/style.scss":"scss/style.scss","p5":"../node_modules/p5/lib/p5.js","p5/lib/addons/p5.sound":"../node_modules/p5/lib/addons/p5.sound.js","../images/clock.png":"images/clock.png","../images/mokuhyou_tassei_man.png":"images/mokuhyou_tassei_man.png","../images/mokuhyou_tassei_woman.png":"images/mokuhyou_tassei_woman.png","../images/musician_trumpet_man.png":"images/musician_trumpet_man.png","../se/people_people-stadium-cheer1.mp3":"se/people_people-stadium-cheer1.mp3","../se/trumpet-dub1.mp3":"se/trumpet-dub1.mp3"}],"C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/src/builtins/hmr-runtime.js":[function(require,module,exports) {
97087var global = arguments[3];
97088var OVERLAY_ID = '__parcel__error__overlay__';
97089var OldModule = module.bundle.Module;
97090
97091function Module(moduleName) {
97092  OldModule.call(this, moduleName);
97093  this.hot = {
97094    data: module.bundle.hotData,
97095    _acceptCallbacks: [],
97096    _disposeCallbacks: [],
97097    accept: function (fn) {
97098      this._acceptCallbacks.push(fn || function () {});
97099    },
97100    dispose: function (fn) {
97101      this._disposeCallbacks.push(fn);
97102    }
97103  };
97104  module.bundle.hotData = null;
97105}
97106
97107module.bundle.Module = Module;
97108var checkedAssets, assetsToAccept;
97109var parent = module.bundle.parent;
97110
97111if ((!parent || !parent.isParcelRequire) && typeof WebSocket !== 'undefined') {
97112  var hostname = "" || location.hostname;
97113  var protocol = location.protocol === 'https:' ? 'wss' : 'ws';
97114  var ws = new WebSocket(protocol + '://' + hostname + ':' + "9821" + '/');
97115
97116  ws.onmessage = function (event) {
97117    checkedAssets = {};
97118    assetsToAccept = [];
97119    var data = JSON.parse(event.data);
97120
97121    if (data.type === 'update') {
97122      var handled = false;
vendor: 4,230 bytes, lines 97123-97289
97123      data.assets.forEach(function (asset) {
97124        if (!asset.isNew) {
97125          var didAccept = hmrAcceptCheck(global.parcelRequire, asset.id);
97126
97127          if (didAccept) {
97128            handled = true;
97129          }
97130        }
97131      }); // Enable HMR for CSS by default.
97132
97133      handled = handled || data.assets.every(function (asset) {
97134        return asset.type === 'css' && asset.generated.js;
97135      });
97136
97137      if (handled) {
97138        console.clear();
97139        data.assets.forEach(function (asset) {
97140          hmrApply(global.parcelRequire, asset);
97141        });
97142        assetsToAccept.forEach(function (v) {
97143          hmrAcceptRun(v[0], v[1]);
97144        });
97145      } else {
97146        window.location.reload();
97147      }
97148    }
97149
97150    if (data.type === 'reload') {
97151      ws.close();
97152
97153      ws.onclose = function () {
97154        location.reload();
97155      };
97156    }
97157
97158    if (data.type === 'error-resolved') {
97159      console.log('[parcel] ✨ Error resolved');
97160      removeErrorOverlay();
97161    }
97162
97163    if (data.type === 'error') {
97164      console.error('[parcel] 🚨  ' + data.error.message + '\n' + data.error.stack);
97165      removeErrorOverlay();
97166      var overlay = createErrorOverlay(data);
97167      document.body.appendChild(overlay);
97168    }
97169  };
97170}
97171
97172function removeErrorOverlay() {
97173  var overlay = document.getElementById(OVERLAY_ID);
97174
97175  if (overlay) {
97176    overlay.remove();
97177  }
97178}
97179
97180function createErrorOverlay(data) {
97181  var overlay = document.createElement('div');
97182  overlay.id = OVERLAY_ID; // html encode message and stack trace
97183
97184  var message = document.createElement('div');
97185  var stackTrace = document.createElement('pre');
97186  message.innerText = data.error.message;
97187  stackTrace.innerText = data.error.stack;
97188  overlay.innerHTML = '<div style="background: black; font-size: 16px; color: white; position: fixed; height: 100%; width: 100%; top: 0px; left: 0px; padding: 30px; opacity: 0.85; font-family: Menlo, Consolas, monospace; z-index: 9999;">' + '<span style="background: red; padding: 2px 4px; border-radius: 2px;">ERROR</span>' + '<span style="top: 2px; margin-left: 5px; position: relative;">🚨</span>' + '<div style="font-size: 18px; font-weight: bold; margin-top: 20px;">' + message.innerHTML + '</div>' + '<pre>' + stackTrace.innerHTML + '</pre>' + '</div>';
97189  return overlay;
97190}
97191
97192function getParents(bundle, id) {
97193  var modules = bundle.modules;
97194
97195  if (!modules) {
97196    return [];
97197  }
97198
97199  var parents = [];
97200  var k, d, dep;
97201
97202  for (k in modules) {
97203    for (d in modules[k][1]) {
97204      dep = modules[k][1][d];
97205
97206      if (dep === id || Array.isArray(dep) && dep[dep.length - 1] === id) {
97207        parents.push(k);
97208      }
97209    }
97210  }
97211
97212  if (bundle.parent) {
97213    parents = parents.concat(getParents(bundle.parent, id));
97214  }
97215
97216  return parents;
97217}
97218
97219function hmrApply(bundle, asset) {
97220  var modules = bundle.modules;
97221
97222  if (!modules) {
97223    return;
97224  }
97225
97226  if (modules[asset.id] || !bundle.parent) {
97227    var fn = new Function('require', 'module', 'exports', asset.generated.js);
97228    asset.isNew = !modules[asset.id];
97229    modules[asset.id] = [fn, asset.deps];
97230  } else if (bundle.parent) {
97231    hmrApply(bundle.parent, asset);
97232  }
97233}
97234
97235function hmrAcceptCheck(bundle, id) {
97236  var modules = bundle.modules;
97237
97238  if (!modules) {
97239    return;
97240  }
97241
97242  if (!modules[id] && bundle.parent) {
97243    return hmrAcceptCheck(bundle.parent, id);
97244  }
97245
97246  if (checkedAssets[id]) {
97247    return;
97248  }
97249
97250  checkedAssets[id] = true;
97251  var cached = bundle.cache[id];
97252  assetsToAccept.push([bundle, id]);
97253
97254  if (cached && cached.hot && cached.hot._acceptCallbacks.length) {
97255    return true;
97256  }
97257
97258  return getParents(global.parcelRequire, id).some(function (id) {
97259    return hmrAcceptCheck(global.parcelRequire, id);
97260  });
97261}
97262
97263function hmrAcceptRun(bundle, id) {
97264  var cached = bundle.cache[id];
97265  bundle.hotData = {};
97266
97267  if (cached) {
97268    cached.hot.data = bundle.hotData;
97269  }
97270
97271  if (cached && cached.hot && cached.hot._disposeCallbacks.length) {
97272    cached.hot._disposeCallbacks.forEach(function (cb) {
97273      cb(bundle.hotData);
97274    });
97275  }
97276
97277  delete bundle.cache[id];
97278  bundle(id);
97279  cached = bundle.cache[id];
97280
97281  if (cached && cached.hot && cached.hot._acceptCallbacks.length) {
97282    cached.hot._acceptCallbacks.forEach(function (cb) {
97283      cb();
97284    });
97285
97286    return true;
97287  }
97288}
97289},{}]},{}
97289,["C:/Users/tekur/AppData/Roaming/npm/node_modules/parcel-bundler/src/builtins/hmr-runtime.js","js/app.js"], null)
97290//# sourceMappingURL=/app.c3f9f951.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.